summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-06-18 15:35:46 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-18 17:40:05 +0200
commit7b3fdd178ebec04358e4a72b97beced655049655 (patch)
treeb43cef6b47a6d3dfaa8a79253f329b63888156d7
parent2f9e8a982c054b60ced5eda5a0e60531813ecf56 (diff)
downloadserenity-7b3fdd178ebec04358e4a72b97beced655049655.zip
WindowServer: Simplify processing of window-specific mouse events
Move the logic for processing a mouse event that hits a specific window into its own function. If the window is blocked by a modal child, we now get that out of the way first, so we don't have to think about it later.
-rw-r--r--Userland/Services/WindowServer/WindowManager.cpp134
-rw-r--r--Userland/Services/WindowServer/WindowManager.h1
2 files changed, 67 insertions, 68 deletions
diff --git a/Userland/Services/WindowServer/WindowManager.cpp b/Userland/Services/WindowServer/WindowManager.cpp
index bf4707d02b..f23c24a0ba 100644
--- a/Userland/Services/WindowServer/WindowManager.cpp
+++ b/Userland/Services/WindowServer/WindowManager.cpp
@@ -912,9 +912,9 @@ void WindowManager::deliver_mouse_event(Window& window, MouseEvent& event, bool
{
auto translated_event = event.translated(-window.position());
window.dispatch_event(translated_event);
- if (process_double_click && event.type() == Event::MouseUp) {
- process_event_for_doubleclick(window, event);
- if (event.type() == Event::MouseDoubleClick)
+ if (process_double_click && translated_event.type() == Event::MouseUp) {
+ process_event_for_doubleclick(window, translated_event);
+ if (translated_event.type() == Event::MouseDoubleClick)
window.dispatch_event(translated_event);
}
}
@@ -954,6 +954,62 @@ bool WindowManager::process_mouse_event_for_titlebar_buttons(MouseEvent& event)
return false;
}
+void WindowManager::process_mouse_event_for_window(HitTestResult& result, MouseEvent& event, Window*& hovered_window)
+{
+ auto& window = *result.window;
+
+ if (auto* blocking_modal_window = window.blocking_modal_window()) {
+ if (event.type() == Event::Type::MouseDown) {
+ // We're clicking on something that's blocked by a modal window.
+ // Flash the modal window to let the user know about it.
+ blocking_modal_window->frame().start_flash_animation();
+ }
+ // Don't send mouse events to windows blocked by a modal child.
+ return;
+ }
+
+ if (&window != m_resize_candidate.ptr())
+ clear_resize_candidate();
+
+ // First check if we should initiate a move or resize (Super+LMB or Super+RMB).
+ // In those cases, the event is swallowed by the window manager.
+ if (window.is_movable()) {
+ if (!window.is_fullscreen() && m_keyboard_modifiers == Mod_Super && event.type() == Event::MouseDown && event.button() == MouseButton::Left) {
+ hovered_window = &window;
+ start_window_move(window, event);
+ return;
+ }
+ if (window.is_resizable() && m_keyboard_modifiers == Mod_Super && event.type() == Event::MouseDown && event.button() == MouseButton::Right && !window.blocking_modal_window()) {
+ hovered_window = &window;
+ start_window_resize(window, event);
+ return;
+ }
+ }
+
+ if (event.type() == Event::MouseDown) {
+ if (window.type() == WindowType::Normal || window.type() == WindowType::ToolWindow)
+ move_to_front_and_make_active(window);
+ else if (window.type() == WindowType::Desktop)
+ set_active_window(&window);
+ }
+
+ if (result.is_frame_hit) {
+ // We are hitting the frame, pass the event along to WindowFrame.
+ window.frame().handle_mouse_event(event.translated(-window.frame().rect().location()));
+ return;
+ }
+
+ // We are hitting the window content
+ hovered_window = &window;
+
+ if (!window.global_cursor_tracking()) {
+ deliver_mouse_event(window, event, true);
+ }
+
+ if (event.type() == Event::MouseDown)
+ m_active_input_tracking_window = window;
+}
+
void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_window)
{
hovered_window = nullptr;
@@ -1002,58 +1058,6 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
}
}
- Window* event_window_with_frame = nullptr;
- Window* received_mouse_event = nullptr;
-
- auto process_mouse_event_for_window = [&](Window& window) {
- if (&window != m_resize_candidate.ptr())
- clear_resize_candidate();
-
- // First check if we should initiate a move or resize (Super+LMB or Super+RMB).
- // In those cases, the event is swallowed by the window manager.
- if (window.is_movable()) {
- if (!window.is_fullscreen() && m_keyboard_modifiers == Mod_Super && event.type() == Event::MouseDown && event.button() == MouseButton::Left) {
- hovered_window = &window;
- start_window_move(window, event);
- return;
- }
- if (window.is_resizable() && m_keyboard_modifiers == Mod_Super && event.type() == Event::MouseDown && event.button() == MouseButton::Right && !window.blocking_modal_window()) {
- hovered_window = &window;
- start_window_resize(window, event);
- return;
- }
- }
-
- VERIFY(window.hit_test(event.position()).has_value());
- if (event.type() == Event::MouseDown) {
- // We're clicking on something that's blocked by a modal window.
- // Flash the modal window to let the user know about it.
- if (auto* blocking_modal_window = window.blocking_modal_window())
- blocking_modal_window->frame().start_flash_animation();
-
- if (window.type() == WindowType::Normal || window.type() == WindowType::ToolWindow)
- move_to_front_and_make_active(window);
- else if (window.type() == WindowType::Desktop)
- set_active_window(&window);
- }
-
- if (window.frame().hit_test(event.position()).has_value()) {
- // We are hitting the frame, pass the event along to WindowFrame.
- window.frame().handle_mouse_event(event.translated(-window.frame().rect().location()));
- event_window_with_frame = &window;
- } else if (window.hit_test(event.position(), false).has_value()) {
- // We are hitting the window content
- hovered_window = &window;
- if (!window.global_cursor_tracking() && !window.blocking_modal_window()) {
- deliver_mouse_event(window, event, true);
- received_mouse_event = &window;
- if (event.type() == Event::MouseDown) {
- m_active_input_tracking_window = window;
- }
- }
- }
- };
-
// Hit test the window stack to see what's under the cursor.
auto result = m_window_stack.hit_test(event.position());
@@ -1068,20 +1072,14 @@ void WindowManager::process_mouse_event(MouseEvent& event, Window*& hovered_wind
return;
}
- process_mouse_event_for_window(*result->window);
-
- auto reverse_iterator = m_window_stack.windows().rbegin();
- for (; reverse_iterator != m_window_stack.windows().rend(); ++reverse_iterator) {
- auto& window = *reverse_iterator;
- if (received_mouse_event == &window)
- continue;
- if (!window.global_cursor_tracking() || !window.is_visible() || window.is_minimized() || window.blocking_modal_window())
- continue;
- deliver_mouse_event(window, event, false);
- }
+ m_window_stack.for_each_visible_window_from_front_to_back([&](Window& window) {
+ if (window.global_cursor_tracking()) {
+ deliver_mouse_event(window, event, false);
+ }
+ return IterationDecision::Continue;
+ });
- if (event_window_with_frame != m_resize_candidate.ptr())
- clear_resize_candidate();
+ process_mouse_event_for_window(result.value(), event, hovered_window);
}
void WindowManager::reevaluate_hovered_window(Window* updated_window)
diff --git a/Userland/Services/WindowServer/WindowManager.h b/Userland/Services/WindowServer/WindowManager.h
index ecc65180fc..eee7326577 100644
--- a/Userland/Services/WindowServer/WindowManager.h
+++ b/Userland/Services/WindowServer/WindowManager.h
@@ -241,6 +241,7 @@ private:
bool process_ongoing_drag(MouseEvent&, Window*& hovered_window);
bool process_ongoing_active_input_mouse_event(MouseEvent&, Window*& hovered_window);
bool process_mouse_event_for_titlebar_buttons(MouseEvent&);
+ void process_mouse_event_for_window(HitTestResult&, MouseEvent&, Window*& hovered_window);
template<typename Callback>
void for_each_window_manager(Callback);