From d0ebbd329bdd78d6197e7c3020575d768ab169c3 Mon Sep 17 00:00:00 2001 From: pelya Date: Sun, 2 Apr 2017 00:50:59 +0300 Subject: [PATCH] no-toolbars: misclicks should be fixed --- src/window.cpp | 200 +++++++------------------------------------------ todo.txt | 4 +- 2 files changed, 28 insertions(+), 176 deletions(-) diff --git a/src/window.cpp b/src/window.cpp index 7899427a9d..8b00b0f30c 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -635,8 +635,15 @@ void Window::HandleButtonClick(byte widget) static void StartWindowDrag(Window *w); static void StartWindowSizing(Window *w, bool to_left); -#if 0 -static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) +/** + * Mouse left button down+up events trigger OnClick event for a window. + * @param w Window to dispatch event in + * @param x X coordinate of the click + * @param y Y coordinate of the click + * @param click_count Number of fast consecutive clicks at same position + * @param mouse_down Event generated on mouse button press + */ +static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count, bool mouse_down) { NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); WidgetType widget_type = (nw != NULL) ? nw->type : WWT_EMPTY; @@ -673,6 +680,18 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) focused_widget_changed |= w->SetFocusedWidget(widget_index); } + if (!_settings_client.gui.windows_titlebars && mouse_down) { + if (widget_type == NWID_VSCROLLBAR || widget_type == NWID_HSCROLLBAR) { + ScrollbarClickHandler(w, nw, x, y); + _dragging_widget = true; + } + if (widget_type == WWT_RESIZEBOX) { + StartWindowSizing(w, (int)nw->pos_x < (w->width / 2)); + nw->SetDirty(w); + } + return; + } + /* Close any child drop down menus. If the button pressed was the drop down * list's own button, then we should not process the click any further. */ if (HideDropDownMenu(w) == widget_index && widget_index >= 0) return; @@ -684,7 +703,7 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) switch (widget_type) { case NWID_VSCROLLBAR: case NWID_HSCROLLBAR: - ScrollbarClickHandler(w, nw, x, y); + if (mouse_down) ScrollbarClickHandler(w, nw, x, y); break; case WWT_EDITBOX: { @@ -761,173 +780,8 @@ static void DispatchLeftClickEvent(Window *w, int x, int y, int click_count) w->OnClick(pt, widget_index, click_count); } -#endif - -/** - * Mouse left button down event changes window focus, but not always triggers OnClick event. - * @param w Window to dispatch event in - * @param x X coordinate of the click - * @param y Y coordinate of the click - */ -static void ChangeFocusedWindow(Window *w, int x, int y) -{ - NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); - WidgetType widget_type = (nw != NULL) ? nw->type : WWT_EMPTY; - - /* If clicked on a window that previously did dot have focus */ - if (_focused_window != w && // We already have focus, right? - (w->window_desc->flags & WDF_NO_FOCUS) == 0 && // Don't lose focus to toolbars - widget_type != WWT_CLOSEBOX) { // Don't change focused window if 'X' (close button) was clicked - SetFocusedWindow(w); - } - - if (nw == NULL) return; // exit if clicked outside of widgets - - /* don't allow any interaction if the button has been disabled */ - if (nw->IsDisabled()) return; - - int widget_index = nw->index; ///< Index of the widget - - /* Clicked on a widget that is not disabled. - * So unless the clicked widget is the caption bar, change focus to this widget. - * Exception: In the OSK we always want the editbox to stay focussed. */ - if (widget_type != WWT_CAPTION && w->window_class != WC_OSK) { - /* focused_widget_changed is 'now' only true if the window this widget - * is in gained focus. In that case it must remain true, also if the - * local widget focus did not change. As such it's the logical-or of - * both changed states. - * - * If this is not preserved, then the OSK window would be opened when - * a user has the edit box focused and then click on another window and - * then back again on the edit box (to type some text). - */ - w->SetFocusedWidget(widget_index); - } - - // Special cases for scrollable widgets and resize button - switch (widget_type) { - case NWID_VSCROLLBAR: - case NWID_HSCROLLBAR: - ScrollbarClickHandler(w, nw, x, y); - _dragging_widget = true; - break; - - case WWT_RESIZEBOX: - /* When the resize widget is on the left size of the window - * we assume that that button is used to resize to the left. */ - StartWindowSizing(w, (int)nw->pos_x < (w->width / 2)); - nw->SetDirty(w); - break; - - default: - break; - } -} - -/** - * Mouse left button down+up events trigger OnClick event for a window. - * @param w Window to dispatch event in - * @param x X coordinate of the click - * @param y Y coordinate of the click - * @param click_count Number of fast consecutive clicks at same position - */ -static void SendLeftClickEventToWindow(Window *w, int x, int y, int click_count) -{ - NWidgetCore *nw = w->nested_root->GetWidgetFromPos(x, y); - if (w->nested_focus != NULL) nw = w->GetWidget(w->nested_focus->index); - WidgetType widget_type = (nw != NULL) ? nw->type : WWT_EMPTY; - - if (nw == NULL) return; // exit if clicked outside of widgets - - /* don't allow any interaction if the button has been disabled */ - if (nw->IsDisabled()) return; - - int widget_index = nw->index; ///< Index of the widget - - /* Close any child drop down menus. If the button pressed was the drop down - * list's own button, then we should not process the click any further. */ - if (HideDropDownMenu(w) == widget_index && widget_index >= 0) return; - - if ((widget_type & ~WWB_PUSHBUTTON) < WWT_LAST && (widget_type & WWB_PUSHBUTTON)) w->HandleButtonClick(widget_index); - - Point pt = { x, y }; - - switch (widget_type) { - case WWT_EDITBOX: { - QueryString *query = w->GetQueryString(widget_index); - if (query != NULL) query->ClickEditBox(w, pt, widget_index, click_count, false); - break; - } - - case WWT_CLOSEBOX: // 'X' - delete w; - return; - - case WWT_CAPTION: // 'Title bar' - StartWindowDrag(w); - return; - - case WWT_RESIZEBOX: - /* When the resize widget is on the left size of the window - * we assume that that button is used to resize to the left. */ - StartWindowSizing(w, (int)nw->pos_x < (w->width / 2)); - nw->SetDirty(w); - return; - - case WWT_DEFSIZEBOX: { - if (_ctrl_pressed) { - w->window_desc->pref_width = w->width; - w->window_desc->pref_height = w->height; - } else { - int16 def_width = max(min(w->window_desc->GetDefaultWidth(), _screen.width), w->nested_root->smallest_x); - int16 def_height = max(min(w->window_desc->GetDefaultHeight(), _screen.height - 50), w->nested_root->smallest_y); - - int dx = (w->resize.step_width == 0) ? 0 : def_width - w->width; - int dy = (w->resize.step_height == 0) ? 0 : def_height - w->height; - /* dx and dy has to go by step.. calculate it. - * The cast to int is necessary else dx/dy are implicitly casted to unsigned int, which won't work. */ - if (w->resize.step_width > 1) dx -= dx % (int)w->resize.step_width; - if (w->resize.step_height > 1) dy -= dy % (int)w->resize.step_height; - ResizeWindow(w, dx, dy, false); - } - - nw->SetLowered(true); - nw->SetDirty(w); - w->SetTimeout(); - break; - } - - case WWT_DEBUGBOX: - w->ShowNewGRFInspectWindow(); - break; - - case WWT_SHADEBOX: - nw->SetDirty(w); - w->SetShaded(!w->IsShaded()); - return; - - case WWT_STICKYBOX: - w->flags ^= WF_STICKY; - nw->SetDirty(w); - if (_ctrl_pressed) w->window_desc->pref_sticky = (w->flags & WF_STICKY) != 0; - return; - - default: - break; - } - - /* Widget has no index, so the window is not interested in it. */ - if (widget_index < 0) return; - - /* Check if the widget is highlighted; if so, disable highlight and dispatch an event to the GameScript */ - if (w->IsWidgetHighlighted(widget_index)) { - w->SetWidgetHighlight(widget_index, TC_INVALID); - Game::NewEvent(new ScriptEventWindowWidgetClick((ScriptWindow::WindowClass)w->window_class, w->window_number, widget_index)); - } - - w->OnClick(pt, widget_index, click_count); -} +static int _left_button_click_count = 0; /** * Dispatch left mouse-button (possibly double) press in window. * @param w Window to dispatch event in @@ -937,10 +791,8 @@ static void SendLeftClickEventToWindow(Window *w, int x, int y, int click_count) */ static void DispatchLeftButtonDownEvent(Window *w, int x, int y, int click_count) { - ChangeFocusedWindow(w, x, y); - if (_settings_client.gui.windows_titlebars || click_count > 1) { - SendLeftClickEventToWindow(w, x, y, click_count); - } + _left_button_click_count = click_count; + DispatchLeftClickEvent(w, x, y, click_count, true); } /** @@ -953,7 +805,7 @@ static void DispatchLeftButtonUpEvent(Window *w, int x, int y) { _dragging_widget = false; if (_settings_client.gui.windows_titlebars || _dragging_window) return; - SendLeftClickEventToWindow(w, x, y, 1); + DispatchLeftClickEvent(w, x, y, _left_button_click_count, false); } /** diff --git a/todo.txt b/todo.txt index e070cd6bfd..9eac80a5cf 100644 --- a/todo.txt +++ b/todo.txt @@ -5,10 +5,10 @@ - Put mouse cursor in the middle between touch points when zooming in and out. +- Add 'Goal' menu item somewhere to compact toolbar. + - Misclicking station from orders dialog should hide the dialog for 3 times. - Fix text input - it should use SDL_ANDROID_GetScreenKeyboardTextInputAsync(), TODO: it's broken in SDL. - Draggable combo boxes. - -- Clicking disabled toolbar buttons is broken, and buttons are clicked randomly when many windows are open.