summaryrefslogtreecommitdiff
path: root/Servers/WindowServer/WSWindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Servers/WindowServer/WSWindow.cpp')
-rw-r--r--Servers/WindowServer/WSWindow.cpp180
1 files changed, 180 insertions, 0 deletions
diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp
new file mode 100644
index 0000000000..c2e1435efb
--- /dev/null
+++ b/Servers/WindowServer/WSWindow.cpp
@@ -0,0 +1,180 @@
+#include "WSWindow.h"
+#include "WSWindowManager.h"
+#include "WSMessage.h"
+#include "WSMessageLoop.h"
+#include <WindowServer/WSAPITypes.h>
+#include <WindowServer/WSClientConnection.h>
+
+static GraphicsBitmap& default_window_icon()
+{
+ static GraphicsBitmap* s_icon;
+ if (!s_icon)
+ s_icon = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, "/res/icons/window16.rgb", { 16, 16 }).leak_ref();
+ return *s_icon;
+}
+
+WSWindow::WSWindow(WSMessageReceiver& internal_owner, WSWindowType type)
+ : m_internal_owner(&internal_owner)
+ , m_type(type)
+ , m_icon(default_window_icon())
+{
+ WSWindowManager::the().add_window(*this);
+}
+
+WSWindow::WSWindow(WSClientConnection& client, int window_id, bool modal)
+ : m_client(&client)
+ , m_type(WSWindowType::Normal)
+ , m_modal(modal)
+ , m_window_id(window_id)
+ , m_icon(default_window_icon())
+{
+ WSWindowManager::the().add_window(*this);
+}
+
+WSWindow::~WSWindow()
+{
+ WSWindowManager::the().remove_window(*this);
+}
+
+void WSWindow::set_title(String&& title)
+{
+ if (m_title == title)
+ return;
+ m_title = move(title);
+ WSWindowManager::the().notify_title_changed(*this);
+}
+
+void WSWindow::set_rect(const Rect& rect)
+{
+ Rect old_rect;
+ if (m_rect == rect)
+ return;
+ old_rect = m_rect;
+ m_rect = rect;
+ if (!m_client && (!m_backing_store || old_rect.size() != rect.size())) {
+ m_backing_store = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, m_rect.size());
+ }
+ WSWindowManager::the().notify_rect_changed(*this, old_rect, rect);
+}
+
+// FIXME: Just use the same types.
+static WSAPI_MouseButton to_api(MouseButton button)
+{
+ switch (button) {
+ case MouseButton::None: return WSAPI_MouseButton::NoButton;
+ case MouseButton::Left: return WSAPI_MouseButton::Left;
+ case MouseButton::Right: return WSAPI_MouseButton::Right;
+ case MouseButton::Middle: return WSAPI_MouseButton::Middle;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void WSWindow::on_message(WSMessage& message)
+{
+ if (m_internal_owner)
+ return m_internal_owner->on_message(message);
+
+ if (is_blocked_by_modal_window())
+ return;
+
+ WSAPI_ServerMessage server_message;
+ server_message.window_id = window_id();
+
+ switch (message.type()) {
+ case WSMessage::MouseMove:
+ server_message.type = WSAPI_ServerMessage::Type::MouseMove;
+ server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
+ server_message.mouse.button = WSAPI_MouseButton::NoButton;
+ server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
+ server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
+ break;
+ case WSMessage::MouseDown:
+ server_message.type = WSAPI_ServerMessage::Type::MouseDown;
+ server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
+ server_message.mouse.button = to_api(static_cast<WSMouseEvent&>(message).button());
+ server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
+ server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
+ break;
+ case WSMessage::MouseUp:
+ server_message.type = WSAPI_ServerMessage::Type::MouseUp;
+ server_message.mouse.position = static_cast<WSMouseEvent&>(message).position();
+ server_message.mouse.button = to_api(static_cast<WSMouseEvent&>(message).button());
+ server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons();
+ server_message.mouse.modifiers = static_cast<WSMouseEvent&>(message).modifiers();
+ break;
+ case WSMessage::WindowEntered:
+ server_message.type = WSAPI_ServerMessage::Type::WindowEntered;
+ break;
+ case WSMessage::WindowLeft:
+ server_message.type = WSAPI_ServerMessage::Type::WindowLeft;
+ break;
+ case WSMessage::KeyDown:
+ server_message.type = WSAPI_ServerMessage::Type::KeyDown;
+ server_message.key.character = static_cast<WSKeyEvent&>(message).character();
+ server_message.key.key = static_cast<WSKeyEvent&>(message).key();
+ server_message.key.modifiers = static_cast<WSKeyEvent&>(message).modifiers();
+ break;
+ case WSMessage::KeyUp:
+ server_message.type = WSAPI_ServerMessage::Type::KeyUp;
+ server_message.key.character = static_cast<WSKeyEvent&>(message).character();
+ server_message.key.key = static_cast<WSKeyEvent&>(message).key();
+ server_message.key.modifiers = static_cast<WSKeyEvent&>(message).modifiers();
+ break;
+ case WSMessage::WindowActivated:
+ server_message.type = WSAPI_ServerMessage::Type::WindowActivated;
+ break;
+ case WSMessage::WindowDeactivated:
+ server_message.type = WSAPI_ServerMessage::Type::WindowDeactivated;
+ break;
+ case WSMessage::WindowCloseRequest:
+ server_message.type = WSAPI_ServerMessage::Type::WindowCloseRequest;
+ break;
+ case WSMessage::WindowResized:
+ server_message.type = WSAPI_ServerMessage::Type::WindowResized;
+ server_message.window.old_rect = static_cast<WSResizeEvent&>(message).old_rect();
+ server_message.window.rect = static_cast<WSResizeEvent&>(message).rect();
+ break;
+ default:
+ break;
+ }
+
+ if (server_message.type == WSAPI_ServerMessage::Type::Invalid)
+ return;
+
+ m_client->post_message(server_message);
+}
+
+void WSWindow::set_global_cursor_tracking_enabled(bool enabled)
+{
+ m_global_cursor_tracking_enabled = enabled;
+}
+
+void WSWindow::set_visible(bool b)
+{
+ if (m_visible == b)
+ return;
+ m_visible = b;
+ invalidate();
+}
+
+void WSWindow::set_resizable(bool resizable)
+{
+ if (m_resizable == resizable)
+ return;
+ m_resizable = resizable;
+}
+
+void WSWindow::invalidate()
+{
+ WSWindowManager::the().invalidate(*this);
+}
+
+bool WSWindow::is_active() const
+{
+ return WSWindowManager::the().active_window() == this;
+}
+
+bool WSWindow::is_blocked_by_modal_window() const
+{
+ return !is_modal() && client() && client()->is_showing_modal_window();
+}