From f12573cb6319b1ee30fdabb2264e8b63bec030e1 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 6 Apr 2019 04:08:09 +0200 Subject: [PATCH] Add a slight hover highlight to GButton and WSButton. :^) --- Servers/WindowServer/WSButton.cpp | 26 ++++++++++++++++-------- Servers/WindowServer/WSButton.h | 1 + Servers/WindowServer/WSWindowFrame.cpp | 2 +- Servers/WindowServer/WSWindowManager.cpp | 9 ++++++++ Servers/WindowServer/WSWindowManager.h | 2 ++ SharedGraphics/StylePainter.cpp | 13 ++++++++---- 6 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Servers/WindowServer/WSButton.cpp b/Servers/WindowServer/WSButton.cpp index 40f393895d..70ef677ca9 100644 --- a/Servers/WindowServer/WSButton.cpp +++ b/Servers/WindowServer/WSButton.cpp @@ -20,7 +20,7 @@ void WSButton::paint(Painter& painter) { PainterStateSaver saver(painter); painter.translate(relative_rect().location()); - StylePainter::paint_button(painter, rect(), ButtonStyle::Normal, m_pressed); + StylePainter::paint_button(painter, rect(), ButtonStyle::Normal, m_pressed, m_hovered); auto x_location = rect().center(); x_location.move_by(-(m_bitmap->width() / 2), -(m_bitmap->height() / 2)); if (m_pressed) @@ -39,13 +39,6 @@ void WSButton::on_mouse_event(const WSMouseEvent& event) return; } - if (event.type() == WSMessage::MouseMove) { - bool old_pressed = m_pressed; - m_pressed = rect().contains(event.position()); - if (old_pressed != m_pressed) - wm.invalidate(screen_rect()); - } - if (event.type() == WSMessage::MouseUp && event.button() == MouseButton::Left) { WSWindowManager::the().set_cursor_tracking_button(nullptr); bool old_pressed = m_pressed; @@ -56,6 +49,23 @@ void WSButton::on_mouse_event(const WSMouseEvent& event) } if (old_pressed != m_pressed) wm.invalidate(screen_rect()); + return; + } + + if (event.type() == WSMessage::MouseMove) { + bool old_hovered = m_hovered; + m_hovered = rect().contains(event.position()); + wm.set_hovered_button(m_hovered ? this : nullptr); + if (old_hovered != m_hovered) + wm.invalidate(screen_rect()); + dbgprintf("move, hov=%d, rect=%s, evpos=%s\n", m_hovered, rect().to_string().characters(), event.position().to_string().characters()); + } + + if (event.type() == WSMessage::MouseMove && event.buttons() & (unsigned)MouseButton::Left) { + bool old_pressed = m_pressed; + m_pressed = m_hovered; + if (old_pressed != m_pressed) + wm.invalidate(screen_rect()); } } diff --git a/Servers/WindowServer/WSButton.h b/Servers/WindowServer/WSButton.h index 569b9f21f5..47937b420a 100644 --- a/Servers/WindowServer/WSButton.h +++ b/Servers/WindowServer/WSButton.h @@ -34,4 +34,5 @@ private: Retained m_bitmap; bool m_pressed { false }; bool m_visible { true }; + bool m_hovered { false }; }; diff --git a/Servers/WindowServer/WSWindowFrame.cpp b/Servers/WindowServer/WSWindowFrame.cpp index 6e9b8726f2..ab6b70d6c1 100644 --- a/Servers/WindowServer/WSWindowFrame.cpp +++ b/Servers/WindowServer/WSWindowFrame.cpp @@ -239,7 +239,7 @@ void WSWindowFrame::on_mouse_event(const WSMouseEvent& event) for (auto& button : m_buttons) { if (button->relative_rect().contains(event.position())) - return button->on_mouse_event(event); + return button->on_mouse_event(event.translated(-button->relative_rect().location())); } if (event.type() == WSMessage::MouseDown && event.button() == MouseButton::Left) wm.start_window_drag(m_window, event.translated(rect().location())); diff --git a/Servers/WindowServer/WSWindowManager.cpp b/Servers/WindowServer/WSWindowManager.cpp index 8e7b9c096e..567d1968bf 100644 --- a/Servers/WindowServer/WSWindowManager.cpp +++ b/Servers/WindowServer/WSWindowManager.cpp @@ -623,6 +623,10 @@ void WSWindowManager::process_mouse_event(const WSMouseEvent& event, WSWindow*& if (m_cursor_tracking_button) return m_cursor_tracking_button->on_mouse_event(event.translated(-m_cursor_tracking_button->screen_rect().location())); + // This is quite hackish, but it's how the WSButton hover effect is implemented. + if (m_hovered_button && event.type() == WSMessage::MouseMove) + m_hovered_button->on_mouse_event(event.translated(-m_hovered_button->screen_rect().location())); + HashTable windows_who_received_mouse_event_due_to_cursor_tracking; for (auto* window = m_windows_in_order.tail(); window; window = window->prev()) { @@ -1099,3 +1103,8 @@ const WSCursor& WSWindowManager::active_cursor() const return *m_arrow_cursor; } + +void WSWindowManager::set_hovered_button(WSButton* button) +{ + m_hovered_button = button; +} diff --git a/Servers/WindowServer/WSWindowManager.h b/Servers/WindowServer/WSWindowManager.h index 185a04af9b..b67466405a 100644 --- a/Servers/WindowServer/WSWindowManager.h +++ b/Servers/WindowServer/WSWindowManager.h @@ -101,6 +101,7 @@ public: void set_active_window(WSWindow*); void set_cursor_tracking_button(WSButton* button) { m_cursor_tracking_button = button; } + void set_hovered_button(WSButton*); private: void process_mouse_event(const WSMouseEvent&, WSWindow*& event_window); @@ -206,6 +207,7 @@ private: String m_username; WSButton* m_cursor_tracking_button { nullptr }; + WSButton* m_hovered_button { nullptr }; }; template diff --git a/SharedGraphics/StylePainter.cpp b/SharedGraphics/StylePainter.cpp index 336f1b5030..d695b07dd8 100644 --- a/SharedGraphics/StylePainter.cpp +++ b/SharedGraphics/StylePainter.cpp @@ -1,15 +1,20 @@ #include #include -static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, bool checked) +static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, bool checked, bool hovered) { Color button_color = Color::from_rgb(0xc0c0c0); Color highlight_color2 = Color::from_rgb(0xdfdfdf); Color shadow_color1 = Color::from_rgb(0x808080); Color shadow_color2 = Color::from_rgb(0x404040); - if (checked) - button_color = Color::from_rgb(0xd6d2ce); + if (checked) { + if (hovered) + button_color = Color::from_rgb(0xe3dfdb); + else + button_color = Color::from_rgb(0xd6d2ce); + } else if (hovered) + button_color = Color::from_rgb(0xd4d4d4); PainterStateSaver saver(painter); painter.translate(rect.location()); @@ -51,7 +56,7 @@ static void paint_button_new(Painter& painter, const Rect& rect, bool pressed, b void StylePainter::paint_button(Painter& painter, const Rect& rect, ButtonStyle button_style, bool pressed, bool hovered, bool checked) { if (button_style == ButtonStyle::Normal) - return paint_button_new(painter, rect, pressed, checked); + return paint_button_new(painter, rect, pressed, checked, hovered); Color button_color = Color::LightGray; Color highlight_color = Color::White;