Jelajahi Sumber

WindowServer: Allow each WindowStack to have an active window

A window with an inner stack needs to keep track of which inner window
is active.
Andreas Kling 4 tahun lalu
induk
melakukan
e4e94cd43d

+ 3 - 1
Userland/Services/WindowServer/Window.cpp

@@ -592,7 +592,9 @@ void Window::clear_dirty_rects()
 
 bool Window::is_active() const
 {
-    return WindowManager::the().active_window() == this;
+    if (!outer_stack())
+        return false;
+    return outer_stack()->active_window() == this;
 }
 
 Window* Window::blocking_modal_window()

+ 22 - 27
Userland/Services/WindowServer/WindowManager.cpp

@@ -1306,13 +1306,10 @@ void WindowManager::set_highlight_window(Window* new_highlight_window)
 
 bool WindowManager::is_active_window_or_accessory(Window& window) const
 {
-    if (m_active_window == &window)
-        return true;
-
-    if (!window.is_accessory())
-        return false;
+    if (window.is_accessory())
+        return window.parent_window()->is_active();
 
-    return m_active_window == window.parent_window();
+    return window.is_active();
 }
 
 static bool window_type_can_become_active(WindowType type)
@@ -1355,52 +1352,50 @@ Window* WindowManager::set_active_input_window(Window* window)
     return previous_input_window;
 }
 
-void WindowManager::set_active_window(Window* window, bool make_input)
+void WindowManager::set_active_window(Window* new_active_window, bool make_input)
 {
-    if (window) {
-        if (auto* modal_window = window->blocking_modal_window()) {
+    if (new_active_window) {
+        if (auto* modal_window = new_active_window->blocking_modal_window()) {
             VERIFY(modal_window->is_modal());
-            VERIFY(modal_window != window);
-            window = modal_window;
+            VERIFY(modal_window != new_active_window);
+            new_active_window = modal_window;
             make_input = true;
         }
 
-        if (!window_type_can_become_active(window->type()))
+        if (!window_type_can_become_active(new_active_window->type()))
             return;
     }
 
-    auto* new_active_input_window = window;
-    if (window && window->is_accessory()) {
+    auto* new_active_input_window = new_active_window;
+    if (new_active_window && new_active_window->is_accessory()) {
         // The parent of an accessory window is always the active
         // window, but input is routed to the accessory window
-        window = window->parent_window();
+        new_active_window = new_active_window->parent_window();
     }
 
     if (make_input)
         set_active_input_window(new_active_input_window);
 
-    if (window == m_active_window)
+    if (new_active_window == m_window_stack.active_window())
         return;
 
-    auto* previously_active_window = m_active_window.ptr();
-
-    if (previously_active_window) {
+    if (auto* previously_active_window = m_window_stack.active_window()) {
         for (auto& child_window : previously_active_window->child_windows()) {
             if (child_window && child_window->type() == WindowType::Tooltip)
                 child_window->request_close();
         }
         Core::EventLoop::current().post_event(*previously_active_window, make<Event>(Event::WindowDeactivated));
         previously_active_window->invalidate(true, true);
-        m_active_window = nullptr;
+        m_window_stack.set_active_window(nullptr);
         m_active_input_tracking_window = nullptr;
         tell_wms_window_state_changed(*previously_active_window);
     }
 
-    if (window) {
-        m_active_window = *window;
-        Core::EventLoop::current().post_event(*m_active_window, make<Event>(Event::WindowActivated));
-        m_active_window->invalidate(true, true);
-        tell_wms_window_state_changed(*m_active_window);
+    if (new_active_window) {
+        m_window_stack.set_active_window(new_active_window);
+        Core::EventLoop::current().post_event(*new_active_window, make<Event>(Event::WindowActivated));
+        new_active_window->invalidate(true, true);
+        tell_wms_window_state_changed(*new_active_window);
     }
 
     // Window shapes may have changed (e.g. shadows for inactive/active windows)
@@ -1424,8 +1419,8 @@ bool WindowManager::set_hovered_window(Window* window)
 
 ClientConnection const* WindowManager::active_client() const
 {
-    if (m_active_window)
-        return m_active_window->client();
+    if (auto* window = m_window_stack.active_window())
+        return window->client();
     return nullptr;
 }
 

+ 6 - 9
Userland/Services/WindowServer/WindowManager.h

@@ -90,8 +90,8 @@ public:
     void start_dnd_drag(ClientConnection&, String const& text, Gfx::Bitmap const*, Core::MimeData const&);
     void end_dnd_drag();
 
-    Window* active_window() { return m_active_window.ptr(); }
-    Window const* active_window() const { return m_active_window.ptr(); }
+    Window* active_window() { return m_window_stack.active_window(); }
+    Window const* active_window() const { return m_window_stack.active_window(); }
     Window* active_input_window() { return m_active_input_window.ptr(); }
     Window const* active_input_window() const { return m_active_input_window.ptr(); }
     ClientConnection const* active_client() const;
@@ -166,17 +166,15 @@ public:
 
     Window const* active_fullscreen_window() const
     {
-        if (m_active_window && m_active_window->is_fullscreen()) {
-            return m_active_window;
-        }
+        if (active_window() && active_window()->is_fullscreen())
+            return active_window();
         return nullptr;
     };
 
     Window* active_fullscreen_window()
     {
-        if (m_active_window && m_active_window->is_fullscreen()) {
-            return m_active_window;
-        }
+        if (active_window() && active_window()->is_fullscreen())
+            return active_window();
         return nullptr;
     }
 
@@ -308,7 +306,6 @@ private:
     int m_max_distance_for_double_click { 4 };
     bool m_previous_event_was_super_keydown { false };
 
-    WeakPtr<Window> m_active_window;
     WeakPtr<Window> m_hovered_window;
     WeakPtr<Window> m_active_input_window;
     WeakPtr<Window> m_active_input_tracking_window;

+ 8 - 0
Userland/Services/WindowServer/WindowStack.cpp

@@ -46,4 +46,12 @@ void WindowStack::set_highlight_window(Window* window)
         m_highlight_window = window->make_weak_ptr<Window>();
 }
 
+void WindowStack::set_active_window(Window* window)
+{
+    if (!window)
+        m_active_window = nullptr;
+    else
+        m_active_window = window->make_weak_ptr<Window>();
+}
+
 }

+ 5 - 0
Userland/Services/WindowServer/WindowStack.h

@@ -40,8 +40,13 @@ public:
     Window const* highlight_window() const { return m_highlight_window; }
     void set_highlight_window(Window*);
 
+    Window* active_window() { return m_active_window; }
+    Window const* active_window() const { return m_active_window; }
+    void set_active_window(Window*);
+
 private:
     WeakPtr<Window> m_highlight_window;
+    WeakPtr<Window> m_active_window;
 
     Window::List m_windows;
 };