瀏覽代碼

WindowServer: Add WindowStack::window_at() and use it a bunch

This performs a hit test on the window stack to find the window under
a given cursor position.
Andreas Kling 4 年之前
父節點
當前提交
f88361fc28

+ 3 - 21
Userland/Services/WindowServer/WindowManager.cpp

@@ -765,14 +765,7 @@ bool WindowManager::process_ongoing_drag(MouseEvent& event, Window*& hovered_win
     if (!(event.type() == Event::MouseUp && event.button() == MouseButton::Left))
         return true;
 
-    hovered_window = nullptr;
-    m_window_stack.for_each_visible_window_from_front_to_back([&](auto& window) {
-        if (window.hit_test(event.position()).has_value()) {
-            hovered_window = &window;
-            return IterationDecision::Break;
-        }
-        return IterationDecision::Continue;
-    });
+    hovered_window = m_window_stack.window_at(event.position());
 
     if (hovered_window) {
         m_dnd_client->async_drag_accepted();
@@ -995,13 +988,7 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
             m_active_input_tracking_window = nullptr;
         }
 
-        m_window_stack.for_each_visible_window_from_front_to_back([&](auto& window) {
-            if (window.hit_test(event.position()).has_value()) {
-                hovered_window = &window;
-                return IterationDecision::Break;
-            }
-            return IterationDecision::Continue;
-        });
+        hovered_window = m_window_stack.window_at(event.position());
     } else {
         auto process_mouse_event_for_window = [&](Window& window) {
             if (&window != m_resize_candidate.ptr())
@@ -1101,12 +1088,7 @@ void WindowManager::reevaluate_hovered_window(Window* updated_window)
         if (fullscreen_window->hit_test(cursor_location).has_value())
             hovered_window = fullscreen_window;
     } else {
-        m_window_stack.for_each_visible_window_from_front_to_back([&](Window& window) {
-            if (!window.hit_test(cursor_location).has_value())
-                return IterationDecision::Continue;
-            hovered_window = &window;
-            return IterationDecision::Break;
-        });
+        hovered_window = m_window_stack.window_at(cursor_location);
     }
 
     if (set_hovered_window(hovered_window)) {

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

@@ -38,6 +38,14 @@ void WindowStack::move_to_front(Window& window)
     m_windows.append(window);
 }
 
+Window* WindowStack::window_at(Gfx::IntPoint const& position) const
+{
+    auto result = hit_test(position);
+    if (!result.has_value())
+        return nullptr;
+    return result->window;
+}
+
 void WindowStack::set_highlight_window(Window* window)
 {
     if (!window)
@@ -54,4 +62,16 @@ void WindowStack::set_active_window(Window* window)
         m_active_window = window->make_weak_ptr<Window>();
 }
 
+Optional<HitTestResult> WindowStack::hit_test(Gfx::IntPoint const& position) const
+{
+    Optional<HitTestResult> result;
+    const_cast<WindowStack*>(this)->for_each_visible_window_from_front_to_back([&](Window& window) {
+        result = window.hit_test(position);
+        if (result.has_value())
+            return IterationDecision::Break;
+        return IterationDecision::Continue;
+    });
+    return result;
+}
+
 }

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

@@ -20,6 +20,8 @@ public:
     void remove(Window&);
     void move_to_front(Window&);
 
+    Window* window_at(Gfx::IntPoint const&) const;
+
     template<typename Callback>
     IterationDecision for_each_visible_window_from_back_to_front(Callback);
     template<typename Callback>
@@ -44,6 +46,8 @@ public:
     Window const* active_window() const { return m_active_window; }
     void set_active_window(Window*);
 
+    Optional<HitTestResult> hit_test(Gfx::IntPoint const&) const;
+
 private:
     WeakPtr<Window> m_highlight_window;
     WeakPtr<Window> m_active_window;