Changeset - r23337:5d348848d78f
[Not reviewed]
master
0 3 0
Peter Nelson - 5 years ago 2019-02-14 06:25:17
peter1138@openttd.org
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.
3 files changed with 56 insertions and 37 deletions:
0 comments (0 inline, 0 general)
src/widget.cpp
Show inline comments
 
@@ -99,7 +99,7 @@ static void ScrollbarClickPositioning(Wi
 
			_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(Wi
 
			_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(Wi
 
		} 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
 

	
 
	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);
src/window.cpp
Show inline comments
 
@@ -1846,7 +1846,7 @@ void Window::InitNested(WindowNumber win
 
 * 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<NWidgetScrollbar*>(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,
 
}
 

	
 
/**
 
 * 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<NWidgetScrollbar>(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<NWidgetScrollbar>(w->scrolling_scrollbar);
 
			bool rtl = false;
 

	
 
			if (sb->type == NWID_HSCROLLBAR) {
 
				i = _cursor.pos.x - _cursorpos_drag_start.x;
 
				rtl = _current_text_dir == TD_RTL;
 
			/* If cursor hasn't moved, there is nothing to do. */
 
			if (_cursor.delta.x == 0 && _cursor.delta.y == 0) return ES_HANDLED;
 

	
 
			/* Handle scrollbar internally, or dispatch click event */
 
			WidgetType type = w->GetWidget<NWidgetBase>(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, 
 
	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();
src/window_gui.h
Show inline comments
 
@@ -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.
0 comments (0 inline, 0 general)