summaryrefslogtreecommitdiff
path: root/WindowServer
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-20 10:12:19 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-20 10:12:19 +0100
commitbf305025601b28c9c489b97af75a7273e3bd79ed (patch)
treefd7835164f946d7da7aea38a1de32122b4903fac /WindowServer
parentaf7eb5c89c974cdaeadeffa9db2f70b39fb7f373 (diff)
downloadserenity-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.h2
-rw-r--r--WindowServer/WSMessage.h2
-rw-r--r--WindowServer/WSWindow.cpp6
-rw-r--r--WindowServer/WSWindowManager.cpp27
-rw-r--r--WindowServer/WSWindowManager.h5
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;