Changeset - r23337:5d348848d78f
[Not reviewed]
master
0 3 0
Peter Nelson - 6 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
 
@@ -96,33 +96,33 @@ static void ScrollbarClickPositioning(Wi
 
		/* Pressing the upper button? */
 
		SetBit(sb->disp_flags, NDB_SCROLLBAR_UP);
 
		if (_scroller_click_timeout <= 1) {
 
			_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);
 

	
 
		if (_scroller_click_timeout <= 1) {
 
			_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);
 

	
 
		if (pos < pt.x) {
 
			sb->UpdatePosition(rtl ? 1 : -1, Scrollbar::SS_BIG);
 
		} else if (pos > pt.y) {
 
			sb->UpdatePosition(rtl ? -1 : 1, Scrollbar::SS_BIG);
 
		} 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;
 
		}
 
	}
 

	
 
	w->SetDirty();
 
}
 
@@ -2035,13 +2035,13 @@ void NWidgetScrollbar::Draw(const Window
 

	
 
	const DrawPixelInfo *dpi = _cur_dpi;
 
	if (dpi->left > r.right || dpi->left + dpi->width <= r.left || dpi->top > r.bottom || dpi->top + dpi->height <= r.top) return;
 

	
 
	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);
 
	} else {
 
		DrawVerticalScrollbar(r, this->colour, up_lowered, middle_lowered, down_lowered, this);
 
	}
src/window.cpp
Show inline comments
 
@@ -1843,13 +1843,13 @@ 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)
 
{
 
}
 

	
 
/**
 
 * Do a search for a window at specific coordinates. For this we start
 
 * at the topmost window, obviously and work our way down to the bottom
 
@@ -1931,13 +1931,13 @@ static void DecreaseWindowCounters()
 
			for (uint i = 0; i < w->nested_array_size; i++) {
 
				NWidgetBase *nwid = w->nested_array[i];
 
				if (nwid != NULL && (nwid->type == NWID_HSCROLLBAR || nwid->type == NWID_VSCROLLBAR)) {
 
					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);
 
					}
 
				}
 
			}
 
		}
 

	
 
@@ -2383,53 +2383,72 @@ static void StartWindowSizing(Window *w,
 

	
 
	BringWindowToFront(w);
 
	DeleteWindowById(WC_DROPDOWN_MENU, 0);
 
}
 

	
 
/**
 
 * 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;
 
		}
 
	}
 

	
 
	return ES_NOT_HANDLED;
 
@@ -2842,13 +2861,13 @@ static void MouseLoop(MouseClick click, 
 
	HandlePlacePresize();
 
	UpdateTileSelection();
 

	
 
	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();
 

	
 
	bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
 
	if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
src/window_gui.h
Show inline comments
 
@@ -324,13 +324,13 @@ public:
 
	NWidgetBase *nested_root;        ///< Root of the nested tree.
 
	NWidgetBase **nested_array;      ///< Array of pointers into the tree. Do not access directly, use #Window::GetWidget() instead.
 
	uint nested_array_size;          ///< Size of the nested array.
 
	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.
 
	Window *z_back;                  ///< The window behind us in z-order.
 

	
 
	template <class NWID>
0 comments (0 inline, 0 general)