diff --git a/Applications/Taskbar/TaskbarWindow.cpp b/Applications/Taskbar/TaskbarWindow.cpp index deaae2d789..562d6aad63 100644 --- a/Applications/Taskbar/TaskbarWindow.cpp +++ b/Applications/Taskbar/TaskbarWindow.cpp @@ -76,6 +76,17 @@ void TaskbarWindow::wm_event(GWMEvent& event) update(); break; } + case GEvent::WM_WindowRectChanged: { +#ifdef EVENT_DEBUG + auto& changed_event = static_cast(event); + dbgprintf("WM_WindowRectChanged: client_id=%d, window_id=%d, rect=%s\n", + changed_event.client_id(), + changed_event.window_id(), + changed_event.rect().to_string().characters() + ); +#endif + break; + } case GEvent::WM_WindowIconChanged: { auto& changed_event = static_cast(event); #ifdef EVENT_DEBUG diff --git a/LibGUI/GEvent.h b/LibGUI/GEvent.h index ecbe51ead3..25636afbef 100644 --- a/LibGUI/GEvent.h +++ b/LibGUI/GEvent.h @@ -30,9 +30,13 @@ public: FocusOut, WindowCloseRequest, ContextMenu, + + __Begin_WM_Events, WM_WindowRemoved, WM_WindowStateChanged, + WM_WindowRectChanged, WM_WindowIconChanged, + __End_WM_Events, }; GEvent() { } @@ -95,6 +99,20 @@ private: bool m_minimized; }; +class GWMWindowRectChangedEvent : public GWMEvent { +public: + GWMWindowRectChangedEvent(int client_id, int window_id, const Rect& rect) + : GWMEvent(GEvent::Type::WM_WindowRectChanged, client_id, window_id) + , m_rect(rect) + { + } + + Rect rect() const { return m_rect; } + +private: + Rect m_rect; +}; + class GWMWindowIconChangedEvent : public GWMEvent { public: GWMWindowIconChangedEvent(int client_id, int window_id, const String& icon_path) diff --git a/LibGUI/GEventLoop.cpp b/LibGUI/GEventLoop.cpp index b14c621e91..809943a738 100644 --- a/LibGUI/GEventLoop.cpp +++ b/LibGUI/GEventLoop.cpp @@ -175,6 +175,8 @@ void GEventLoop::handle_wm_event(const WSAPI_ServerMessage& event, GWindow& wind #endif if (event.type == WSAPI_ServerMessage::WM_WindowStateChanged) return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length), event.wm.rect, event.wm.is_active, (GWindowType)event.wm.window_type, event.wm.is_minimized)); + if (event.type == WSAPI_ServerMessage::WM_WindowRectChanged) + return post_event(window, make(event.wm.client_id, event.wm.window_id, event.wm.rect)); if (event.type == WSAPI_ServerMessage::WM_WindowIconChanged) return post_event(window, make(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length))); if (event.type == WSAPI_ServerMessage::WM_WindowRemoved) diff --git a/LibGUI/GWindow.cpp b/LibGUI/GWindow.cpp index de38f0ffcc..505338f7d6 100644 --- a/LibGUI/GWindow.cpp +++ b/LibGUI/GWindow.cpp @@ -277,7 +277,7 @@ void GWindow::event(CEvent& event) return; } - if (event.type() == GEvent::WM_WindowRemoved || event.type() == GEvent::WM_WindowStateChanged || event.type() == GEvent::WM_WindowIconChanged) + if (event.type() > GEvent::__Begin_WM_Events && event.type() < GEvent::__End_WM_Events) return wm_event(static_cast(event)); CObject::event(event); diff --git a/Servers/WindowServer/WSAPITypes.h b/Servers/WindowServer/WSAPITypes.h index c7377d3e00..99f74bbb1d 100644 --- a/Servers/WindowServer/WSAPITypes.h +++ b/Servers/WindowServer/WSAPITypes.h @@ -57,6 +57,13 @@ enum class WSAPI_StandardCursor : unsigned char { ResizeVertical, }; +enum WSAPI_WMEventMask : unsigned { + WindowRectChanges = 1 << 0, + WindowStateChanges = 1 << 1, + WindowIconChanges = 1 << 2, + WindowRemovals = 1 << 3, +}; + struct WSAPI_ServerMessage { enum Type : unsigned { Invalid, @@ -97,6 +104,7 @@ struct WSAPI_ServerMessage { ScreenRectChanged, WM_WindowRemoved, WM_WindowStateChanged, + WM_WindowRectChanged, WM_WindowIconChanged, }; Type type { Invalid }; diff --git a/Servers/WindowServer/WSEvent.h b/Servers/WindowServer/WSEvent.h index 4c9d85f5bf..e667fd5053 100644 --- a/Servers/WindowServer/WSEvent.h +++ b/Servers/WindowServer/WSEvent.h @@ -29,6 +29,7 @@ public: WM_WindowRemoved, WM_WindowStateChanged, + WM_WindowRectChanged, WM_WindowIconChanged, __Begin_API_Client_Requests, @@ -750,3 +751,17 @@ public: private: String m_icon_path; }; + +class WSWMWindowRectChangedEvent : public WSWMEvent { +public: + WSWMWindowRectChangedEvent(int client_id, int window_id, const Rect& rect) + : WSWMEvent(WSEvent::WM_WindowRectChanged, client_id, window_id) + , m_rect(rect) + { + } + + Rect rect() const { return m_rect; } + +private: + Rect m_rect; +}; diff --git a/Servers/WindowServer/WSWindow.cpp b/Servers/WindowServer/WSWindow.cpp index b8f3df4ca8..4bb1e16cd8 100644 --- a/Servers/WindowServer/WSWindow.cpp +++ b/Servers/WindowServer/WSWindow.cpp @@ -38,8 +38,10 @@ WSWindow::WSWindow(WSClientConnection& client, WSWindowType window_type, int win , m_frame(*this) { // FIXME: This should not be hard-coded here. - if (m_type == WSWindowType::Taskbar) + if (m_type == WSWindowType::Taskbar) { + m_wm_event_mask = WSAPI_WMEventMask::WindowStateChanges | WSAPI_WMEventMask::WindowRemovals | WSAPI_WMEventMask::WindowIconChanges; m_listens_to_wm_events = true; + } WSWindowManager::the().add_window(*this); } @@ -210,6 +212,15 @@ void WSWindow::event(CEvent& event) break; } + case WSEvent::WM_WindowRectChanged: { + auto& changed_event = static_cast(event); + server_message.type = WSAPI_ServerMessage::Type::WM_WindowRectChanged; + server_message.wm.client_id = changed_event.client_id(); + server_message.wm.window_id = changed_event.window_id(); + server_message.wm.rect = changed_event.rect(); + break; + } + default: break; } diff --git a/Servers/WindowServer/WSWindow.h b/Servers/WindowServer/WSWindow.h index 4ac39690ed..b256504a04 100644 --- a/Servers/WindowServer/WSWindow.h +++ b/Servers/WindowServer/WSWindow.h @@ -19,6 +19,9 @@ public: WSWindow(CObject&, WSWindowType); virtual ~WSWindow() override; + unsigned wm_event_mask() const { return m_wm_event_mask; } + void set_wm_event_mask(unsigned mask) { m_wm_event_mask = mask; } + Color background_color() const { return m_background_color; } void set_background_color(Color color) { m_background_color = color; } @@ -156,4 +159,5 @@ private: RetainPtr m_override_cursor; WSWindowFrame m_frame; Color m_background_color { Color::LightGray }; + unsigned m_wm_event_mask { 0 }; }; diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index af0c333227..6bbe3d8cb2 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -19,6 +19,7 @@ #include #include #include +#include //#define DEBUG_COUNTERS //#define RESIZE_DEBUG @@ -311,6 +312,8 @@ void WSWindowManager::remove_window(WSWindow& window) m_switcher.refresh(); for_each_window_listening_to_wm_events([&window] (WSWindow& listener) { + if (!(listener.wm_event_mask() & WSAPI_WMEventMask::WindowRemovals)) + return IterationDecision::Continue; if (window.client()) WSEventLoop::the().post_event(listener, make(window.client()->client_id(), window.window_id())); return IterationDecision::Continue; @@ -319,12 +322,24 @@ void WSWindowManager::remove_window(WSWindow& window) void WSWindowManager::tell_wm_listener_about_window(WSWindow& listener, WSWindow& window) { + if (!(listener.wm_event_mask() & WSAPI_WMEventMask::WindowStateChanges)) + return; if (window.client()) WSEventLoop::the().post_event(listener, make(window.client()->client_id(), window.window_id(), window.title(), window.rect(), window.is_active(), window.type(), window.is_minimized())); } +void WSWindowManager::tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow& window) +{ + if (!(listener.wm_event_mask() & WSAPI_WMEventMask::WindowRectChanges)) + return; + if (window.client()) + WSEventLoop::the().post_event(listener, make(window.client()->client_id(), window.window_id(), window.rect())); +} + void WSWindowManager::tell_wm_listener_about_window_icon(WSWindow& listener, WSWindow& window) { + if (!(listener.wm_event_mask() & WSAPI_WMEventMask::WindowIconChanges)) + return; if (window.client()) WSEventLoop::the().post_event(listener, make(window.client()->client_id(), window.window_id(), window.icon_path())); } @@ -345,6 +360,14 @@ void WSWindowManager::tell_wm_listeners_window_icon_changed(WSWindow& window) }); } +void WSWindowManager::tell_wm_listeners_window_rect_changed(WSWindow& window) +{ + for_each_window_listening_to_wm_events([&] (WSWindow& listener) { + tell_wm_listener_about_window_rect(listener, window); + return IterationDecision::Continue; + }); +} + void WSWindowManager::notify_title_changed(WSWindow& window) { dbgprintf("[WM] WSWindow{%p} title set to '%s'\n", &window, window.title().characters()); @@ -364,7 +387,7 @@ void WSWindowManager::notify_rect_changed(WSWindow& window, const Rect& old_rect #endif if (m_switcher.is_visible() && window.type() != WSWindowType::WindowSwitcher) m_switcher.refresh(); - tell_wm_listeners_window_state_changed(window); + tell_wm_listeners_window_rect_changed(window); } void WSWindowManager::notify_minimization_state_changed(WSWindow& window) diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 0c1711e5c9..a2d2bdb664 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -112,6 +112,7 @@ public: void tell_wm_listeners_window_state_changed(WSWindow&); void tell_wm_listeners_window_icon_changed(WSWindow&); + void tell_wm_listeners_window_rect_changed(WSWindow&); private: void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window); @@ -139,6 +140,7 @@ private: void tick_clock(); void tell_wm_listener_about_window(WSWindow& listener, WSWindow&); void tell_wm_listener_about_window_icon(WSWindow& listener, WSWindow&); + void tell_wm_listener_about_window_rect(WSWindow& listener, WSWindow&); void pick_new_active_window(); WSScreen& m_screen;