diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-02-20 10:12:19 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-02-20 10:12:19 +0100 |
commit | bf305025601b28c9c489b97af75a7273e3bd79ed (patch) | |
tree | fd7835164f946d7da7aea38a1de32122b4903fac /WindowServer | |
parent | af7eb5c89c974cdaeadeffa9db2f70b39fb7f373 (diff) | |
download | serenity-bf305025601b28c9c489b97af75a7273e3bd79ed.zip |
LibGUI: Implement enter/leave events (with WindowServer support.)
Windows now learn when the mouse cursor leaves or enters them.
Use this to implement GWidget::{enter,leave}_event() and use that
to implement the CoolBar button effect. :^)
Diffstat (limited to 'WindowServer')
-rw-r--r-- | WindowServer/WSAPITypes.h | 2 | ||||
-rw-r--r-- | WindowServer/WSMessage.h | 2 | ||||
-rw-r--r-- | WindowServer/WSWindow.cpp | 6 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.cpp | 27 | ||||
-rw-r--r-- | WindowServer/WSWindowManager.h | 5 |
5 files changed, 37 insertions, 5 deletions
diff --git a/WindowServer/WSAPITypes.h b/WindowServer/WSAPITypes.h index 3ed1b55077..8be470a257 100644 --- a/WindowServer/WSAPITypes.h +++ b/WindowServer/WSAPITypes.h @@ -62,6 +62,8 @@ struct WSAPI_ServerMessage { MouseMove, MouseDown, MouseUp, + WindowEntered, + WindowLeft, KeyDown, KeyUp, WindowActivated, diff --git a/WindowServer/WSMessage.h b/WindowServer/WSMessage.h index 0656bc4bd5..3e4f236c70 100644 --- a/WindowServer/WSMessage.h +++ b/WindowServer/WSMessage.h @@ -14,6 +14,8 @@ public: MouseMove, MouseDown, MouseUp, + WindowEntered, + WindowLeft, KeyDown, KeyUp, WindowActivated, diff --git a/WindowServer/WSWindow.cpp b/WindowServer/WSWindow.cpp index 61e9073123..5c74b0899a 100644 --- a/WindowServer/WSWindow.cpp +++ b/WindowServer/WSWindow.cpp @@ -94,6 +94,12 @@ void WSWindow::on_message(WSMessage& message) server_message.mouse.button = to_api(static_cast<WSMouseEvent&>(message).button()); server_message.mouse.buttons = static_cast<WSMouseEvent&>(message).buttons(); break; + case WSMessage::WindowEntered: + server_message.type = WSAPI_ServerMessage::Type::WindowEntered; + break; + case WSMessage::WindowLeft: + server_message.type = WSAPI_ServerMessage::Type::WindowLeft; + break; case WSMessage::KeyDown: server_message.type = WSAPI_ServerMessage::Type::KeyDown; server_message.key.character = static_cast<WSKeyEvent&>(message).character(); diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index eafa5f38e7..65db97df6d 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -488,8 +488,10 @@ void WSWindowManager::handle_close_button_mouse_event(WSWindow& window, WSMouseE } } -void WSWindowManager::process_mouse_event(WSMouseEvent& event) +void WSWindowManager::process_mouse_event(WSMouseEvent& event, WSWindow*& event_window) { + event_window = nullptr; + if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Left) { if (m_drag_window) { #ifdef DRAG_DEBUG @@ -561,6 +563,7 @@ void WSWindowManager::process_mouse_event(WSMouseEvent& event) move_to_front(window); set_active_window(&window); } + event_window = &window; // FIXME: Should we just alter the coordinates of the existing MouseEvent and pass it through? Point position { event.x() - window.rect().x(), event.y() - window.rect().y() }; auto local_event = make<WSMouseEvent>(event.type(), position, event.buttons(), event.button()); @@ -753,8 +756,12 @@ void WSWindowManager::draw_cursor() void WSWindowManager::on_message(WSMessage& message) { - if (message.is_mouse_event()) - return process_mouse_event(static_cast<WSMouseEvent&>(message)); + if (message.is_mouse_event()) { + WSWindow* event_window = nullptr; + process_mouse_event(static_cast<WSMouseEvent&>(message), event_window); + set_hovered_window(event_window); + return; + } if (message.is_key_event()) { // FIXME: This is a good place to hook key events globally. :) @@ -795,6 +802,20 @@ void WSWindowManager::set_active_window(WSWindow* window) } } +void WSWindowManager::set_hovered_window(WSWindow* window) +{ + if (m_hovered_window.ptr() == window) + return; + + if (m_hovered_window) + WSMessageLoop::the().post_message(m_hovered_window.ptr(), make<WSMessage>(WSMessage::WindowLeft)); + + m_hovered_window = window ? window->make_weak_ptr() : nullptr; + + if (m_hovered_window) + WSMessageLoop::the().post_message(m_hovered_window.ptr(), make<WSMessage>(WSMessage::WindowEntered)); +} + void WSWindowManager::invalidate() { m_dirty_rects.clear_with_capacity(); diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 40841648a3..aabd31b4e7 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -71,7 +71,7 @@ public: void set_resolution(int width, int height); private: - void process_mouse_event(WSMouseEvent&); + void process_mouse_event(WSMouseEvent&, WSWindow*& event_window); void handle_menu_mouse_event(WSMenu&, WSMouseEvent&); void handle_menubar_mouse_event(WSMouseEvent&); void handle_titlebar_mouse_event(WSWindow&, WSMouseEvent&); @@ -79,6 +79,7 @@ private: void handle_client_request(WSAPIClientRequest&); void set_active_window(WSWindow*); + void set_hovered_window(WSWindow*); template<typename Callback> IterationDecision for_each_visible_window_of_type_from_back_to_front(WSWindowType, Callback); template<typename Callback> IterationDecision for_each_visible_window_of_type_from_front_to_back(WSWindowType, Callback); template<typename Callback> IterationDecision for_each_visible_window_from_front_to_back(Callback); @@ -111,7 +112,7 @@ private: InlineLinkedList<WSWindow> m_windows_in_order; WeakPtr<WSWindow> m_active_window; - + WeakPtr<WSWindow> m_hovered_window; WeakPtr<WSWindow> m_drag_window; Point m_drag_origin; |