Kaynağa Gözat

WindowServer: Introduce a WM event mask so Taskbar can ignore window rects.

Taskbar was waking up to do nothing every time a window rect changed.
Andreas Kling 6 yıl önce
ebeveyn
işleme
49e7ffc06a

+ 11 - 0
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<GWMWindowRectChangedEvent&>(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<GWMWindowIconChangedEvent&>(event);
 #ifdef EVENT_DEBUG

+ 18 - 0
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)

+ 2 - 0
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<GWMWindowStateChangedEvent>(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<GWMWindowRectChangedEvent>(event.wm.client_id, event.wm.window_id, event.wm.rect));
     if (event.type == WSAPI_ServerMessage::WM_WindowIconChanged)
         return post_event(window, make<GWMWindowIconChangedEvent>(event.wm.client_id, event.wm.window_id, String(event.text, event.text_length)));
     if (event.type == WSAPI_ServerMessage::WM_WindowRemoved)

+ 1 - 1
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<GWMEvent&>(event));
 
     CObject::event(event);

+ 8 - 0
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 };

+ 15 - 0
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;
+};

+ 12 - 1
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<const WSWMWindowRectChangedEvent&>(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;
     }

+ 4 - 0
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<WSCursor> m_override_cursor;
     WSWindowFrame m_frame;
     Color m_background_color { Color::LightGray };
+    unsigned m_wm_event_mask { 0 };
 };

+ 24 - 1
Servers/WindowServer/WSWindowManager.cpp

@@ -19,6 +19,7 @@
 #include <WindowServer/WSCursor.h>
 #include <WindowServer/WSButton.h>
 #include <LibCore/CTimer.h>
+#include <WindowServer/WSAPITypes.h>
 
 //#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<WSWMWindowRemovedEvent>(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<WSWMWindowStateChangedEvent>(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<WSWMWindowRectChangedEvent>(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<WSWMWindowIconChangedEvent>(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)

+ 2 - 0
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;