From de9f54ccc185d35727858a36fcebc82178c519c6 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 14 Feb 2019 06:25:17 +0000 Subject: Codechange: Change scrolling_scrollbar to mouse_capture_widget, and dispatch OnClick() event if widget is not a scrollbar. This allows any widget to support mouse capture. --- src/widget.cpp | 8 +++--- src/window.cpp | 81 ++++++++++++++++++++++++++++++++++---------------------- src/window_gui.h | 2 +- 3 files changed, 55 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/widget.cpp b/src/widget.cpp index 73190f5e6..5ec539a49 100644 --- a/src/widget.cpp +++ b/src/widget.cpp @@ -99,7 +99,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in _scroller_click_timeout = 3; sb->UpdatePosition(rtl ? 1 : -1); } - w->scrolling_scrollbar = sb->index; + w->mouse_capture_widget = sb->index; } else if (pos >= ma - button_size) { /* Pressing the lower button? */ SetBit(sb->disp_flags, NDB_SCROLLBAR_DOWN); @@ -108,7 +108,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in _scroller_click_timeout = 3; sb->UpdatePosition(rtl ? -1 : 1); } - w->scrolling_scrollbar = sb->index; + w->mouse_capture_widget = sb->index; } else { Point pt = HandleScrollbarHittest(sb, mi, ma, sb->type == NWID_HSCROLLBAR); @@ -119,7 +119,7 @@ static void ScrollbarClickPositioning(Window *w, NWidgetScrollbar *sb, int x, in } else { _scrollbar_start_pos = pt.x - mi - button_size; _scrollbar_size = ma - mi - button_size * 2; - w->scrolling_scrollbar = sb->index; + w->mouse_capture_widget = sb->index; _cursorpos_drag_start = _cursor.pos; } } @@ -2038,7 +2038,7 @@ void NWidgetScrollbar::Draw(const Window *w) bool up_lowered = HasBit(this->disp_flags, NDB_SCROLLBAR_UP); bool down_lowered = HasBit(this->disp_flags, NDB_SCROLLBAR_DOWN); - bool middle_lowered = !(this->disp_flags & ND_SCROLLBAR_BTN) && w->scrolling_scrollbar == this->index; + bool middle_lowered = !(this->disp_flags & ND_SCROLLBAR_BTN) && w->mouse_capture_widget == this->index; if (this->type == NWID_HSCROLLBAR) { DrawHorizontalScrollbar(r, this->colour, up_lowered, middle_lowered, down_lowered, this); diff --git a/src/window.cpp b/src/window.cpp index e8c4fe74d..1729687f2 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -1846,7 +1846,7 @@ void Window::InitNested(WindowNumber window_number) * Empty constructor, initialization has been moved to #InitNested() called from the constructor of the derived class. * @param desc The description of the window. */ -Window::Window(WindowDesc *desc) : window_desc(desc), scrolling_scrollbar(-1) +Window::Window(WindowDesc *desc) : window_desc(desc), mouse_capture_widget(-1) { } @@ -1934,7 +1934,7 @@ static void DecreaseWindowCounters() NWidgetScrollbar *sb = static_cast(nwid); if (sb->disp_flags & (ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN)) { sb->disp_flags &= ~(ND_SCROLLBAR_UP | ND_SCROLLBAR_DOWN); - w->scrolling_scrollbar = -1; + w->mouse_capture_widget = -1; sb->SetDirty(w); } } @@ -2386,47 +2386,66 @@ static void StartWindowSizing(Window *w, bool to_left) } /** - * handle scrollbar scrolling with the mouse. + * Handle scrollbar scrolling with the mouse. + * @param w window with active scrollbar. + */ +static void HandleScrollbarScrolling(Window *w) +{ + int i; + NWidgetScrollbar *sb = w->GetWidget(w->mouse_capture_widget); + bool rtl = false; + + if (sb->type == NWID_HSCROLLBAR) { + i = _cursor.pos.x - _cursorpos_drag_start.x; + rtl = _current_text_dir == TD_RTL; + } else { + i = _cursor.pos.y - _cursorpos_drag_start.y; + } + + if (sb->disp_flags & ND_SCROLLBAR_BTN) { + if (_scroller_click_timeout == 1) { + _scroller_click_timeout = 3; + sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1); + w->SetDirty(); + } + return; + } + + /* Find the item we want to move to and make sure it's inside bounds. */ + int pos = min(max(0, i + _scrollbar_start_pos) * sb->GetCount() / _scrollbar_size, max(0, sb->GetCount() - sb->GetCapacity())); + if (rtl) pos = max(0, sb->GetCount() - sb->GetCapacity() - pos); + if (pos != sb->GetPosition()) { + sb->SetPosition(pos); + w->SetDirty(); + } +} + +/** + * Handle active widget (mouse draggin on widget) with the mouse. * @return State of handling the event. */ -static EventState HandleScrollbarScrolling() +static EventState HandleActiveWidget() { Window *w; FOR_ALL_WINDOWS_FROM_BACK(w) { - if (w->scrolling_scrollbar >= 0) { + if (w->mouse_capture_widget >= 0) { /* Abort if no button is clicked any more. */ if (!_left_button_down) { - w->scrolling_scrollbar = -1; + w->mouse_capture_widget = -1; w->SetDirty(); return ES_HANDLED; } - int i; - NWidgetScrollbar *sb = w->GetWidget(w->scrolling_scrollbar); - bool rtl = false; + /* If cursor hasn't moved, there is nothing to do. */ + if (_cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED; - if (sb->type == NWID_HSCROLLBAR) { - i = _cursor.pos.x - _cursorpos_drag_start.x; - rtl = _current_text_dir == TD_RTL; + /* Handle scrollbar internally, or dispatch click event */ + WidgetType type = w->GetWidget(w->mouse_capture_widget)->type; + if (type == NWID_VSCROLLBAR || type == NWID_HSCROLLBAR) { + HandleScrollbarScrolling(w); } else { - i = _cursor.pos.y - _cursorpos_drag_start.y; - } - - if (sb->disp_flags & ND_SCROLLBAR_BTN) { - if (_scroller_click_timeout == 1) { - _scroller_click_timeout = 3; - sb->UpdatePosition(rtl == HasBit(sb->disp_flags, NDB_SCROLLBAR_UP) ? 1 : -1); - w->SetDirty(); - } - return ES_HANDLED; - } - - /* Find the item we want to move to and make sure it's inside bounds. */ - int pos = min(max(0, i + _scrollbar_start_pos) * sb->GetCount() / _scrollbar_size, max(0, sb->GetCount() - sb->GetCapacity())); - if (rtl) pos = max(0, sb->GetCount() - sb->GetCapacity() - pos); - if (pos != sb->GetPosition()) { - sb->SetPosition(pos); - w->SetDirty(); + Point pt = { _cursor.pos.x - w->left, _cursor.pos.y - w->top }; + w->OnClick(pt, w->mouse_capture_widget, 0); } return ES_HANDLED; } @@ -2845,7 +2864,7 @@ static void MouseLoop(MouseClick click, int mousewheel) if (VpHandlePlaceSizingDrag() == ES_HANDLED) return; if (HandleMouseDragDrop() == ES_HANDLED) return; if (HandleWindowDragging() == ES_HANDLED) return; - if (HandleScrollbarScrolling() == ES_HANDLED) return; + if (HandleActiveWidget() == ES_HANDLED) return; if (HandleViewportScroll() == ES_HANDLED) return; HandleMouseOver(); diff --git a/src/window_gui.h b/src/window_gui.h index f5f9734c3..0abf79cca 100644 --- a/src/window_gui.h +++ b/src/window_gui.h @@ -327,7 +327,7 @@ public: NWidgetStacked *shade_select; ///< Selection widget (#NWID_SELECTION) to use for shading the window. If \c NULL, window cannot shade. Dimension unshaded_size; ///< Last known unshaded size (only valid while shaded). - int scrolling_scrollbar; ///< Widgetindex of just being dragged scrollbar. -1 if none is active. + int mouse_capture_widget; ///< Widgetindex of current mouse capture widget (e.g. dragged scrollbar). -1 if no widget has mouse capture. Window *parent; ///< Parent window. Window *z_front; ///< The window in front of us in z-order. -- cgit v1.2.3-54-g00ecf