From a0cbb9068b96a825db7e91697ab3d1c3ff94e2fd Mon Sep 17 00:00:00 2001 From: Tom Date: Sat, 20 Feb 2021 16:19:52 -0700 Subject: [PATCH] LibGUI: Let ScrollableWidget handle the wheel events of its ScrollBars Route the ScrollBar's wheel event to the ScrollableWidget so it can handle it itself. This allows it to handle it consistently (e.g. speed) when the cursor is hovering the scroll bars rather than the widget's contents. Fixes #5419 --- Userland/Libraries/LibGUI/ScrollBar.h | 5 ++-- .../Libraries/LibGUI/ScrollableWidget.cpp | 13 ++++++--- Userland/Libraries/LibGUI/ScrollableWidget.h | 28 +++++++++++++++++-- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/Userland/Libraries/LibGUI/ScrollBar.h b/Userland/Libraries/LibGUI/ScrollBar.h index cfe46b4d64..d4fe7e28e9 100644 --- a/Userland/Libraries/LibGUI/ScrollBar.h +++ b/Userland/Libraries/LibGUI/ScrollBar.h @@ -31,7 +31,7 @@ namespace GUI { -class ScrollBar final : public AbstractSlider { +class ScrollBar : public AbstractSlider { C_OBJECT(ScrollBar); public: @@ -49,7 +49,7 @@ public: Scrubber, }; -private: +protected: explicit ScrollBar(Gfx::Orientation = Gfx::Orientation::Vertical); virtual void paint_event(PaintEvent&) override; @@ -60,6 +60,7 @@ private: virtual void leave_event(Core::Event&) override; virtual void change_event(Event&) override; +private: int default_button_size() const { return 16; } int button_size() const { return length(orientation()) <= (default_button_size() * 2) ? length(orientation()) / 2 : default_button_size(); } int button_width() const { return orientation() == Orientation::Vertical ? width() : button_size(); } diff --git a/Userland/Libraries/LibGUI/ScrollableWidget.cpp b/Userland/Libraries/LibGUI/ScrollableWidget.cpp index f2b4cb571f..4a0be62737 100644 --- a/Userland/Libraries/LibGUI/ScrollableWidget.cpp +++ b/Userland/Libraries/LibGUI/ScrollableWidget.cpp @@ -31,14 +31,14 @@ namespace GUI { ScrollableWidget::ScrollableWidget() { - m_vertical_scrollbar = add(Orientation::Vertical); + m_vertical_scrollbar = add(*this, Orientation::Vertical); m_vertical_scrollbar->set_step(4); m_vertical_scrollbar->on_change = [this](int) { did_scroll(); update(); }; - m_horizontal_scrollbar = add(Orientation::Horizontal); + m_horizontal_scrollbar = add(*this, Orientation::Horizontal); m_horizontal_scrollbar->set_step(4); m_horizontal_scrollbar->set_page_step(30); m_horizontal_scrollbar->on_change = [this](int) { @@ -54,20 +54,25 @@ ScrollableWidget::~ScrollableWidget() { } -void ScrollableWidget::mousewheel_event(MouseEvent& event) +void ScrollableWidget::handle_wheel_event(MouseEvent& event, Widget& event_source) { if (!m_scrollbars_enabled) { event.ignore(); return; } // FIXME: The wheel delta multiplier should probably come from... somewhere? - if (event.shift()) { + if (event.shift() || &event_source == m_horizontal_scrollbar.ptr()) { horizontal_scrollbar().set_value(horizontal_scrollbar().value() + event.wheel_delta() * 60); } else { vertical_scrollbar().set_value(vertical_scrollbar().value() + event.wheel_delta() * 20); } } +void ScrollableWidget::mousewheel_event(MouseEvent& event) +{ + handle_wheel_event(event, *this); +} + void ScrollableWidget::custom_layout() { auto inner_rect = frame_inner_rect_for_size(size()); diff --git a/Userland/Libraries/LibGUI/ScrollableWidget.h b/Userland/Libraries/LibGUI/ScrollableWidget.h index 1ffa78ad24..f1e5d9aa65 100644 --- a/Userland/Libraries/LibGUI/ScrollableWidget.h +++ b/Userland/Libraries/LibGUI/ScrollableWidget.h @@ -27,6 +27,7 @@ #pragma once #include +#include namespace GUI { @@ -91,10 +92,31 @@ protected: void set_size_occupied_by_fixed_elements(const Gfx::IntSize&); private: - void update_scrollbar_ranges(); + class ScrollableWidgetScrollBar final : public ScrollBar { + C_OBJECT(ScrollableWidgetScrollBar); - RefPtr m_vertical_scrollbar; - RefPtr m_horizontal_scrollbar; + protected: + explicit ScrollableWidgetScrollBar(ScrollableWidget& owner, Gfx::Orientation orientation) + : ScrollBar(orientation) + , m_owner(owner) + { + } + + virtual void mousewheel_event(MouseEvent& event) override + { + m_owner.handle_wheel_event(event, *this); + } + + private: + ScrollableWidget& m_owner; + }; + friend class ScrollableWidgetScrollBar; + + void update_scrollbar_ranges(); + void handle_wheel_event(MouseEvent&, Widget&); + + RefPtr m_vertical_scrollbar; + RefPtr m_horizontal_scrollbar; RefPtr m_corner_widget; Gfx::IntSize m_content_size; Gfx::IntSize m_size_occupied_by_fixed_elements;