From a4ed0f51c1560436a4e4f9b9dcd7cb048b4b2397 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 17 May 2022 17:19:30 +1000 Subject: Fix click detection for simulated events Refactoring event click-drag detection broke click detection for simulated events. Resolve this by sharing logic for update previous values in `wmWindow.eventstate` for regular event handling (no functional changes for non-simulated events). Failure to detect clicks for simulated events broke the undo test `test_undo.view3d_multi_mode_select` in `../lib/tests/ui_simulate/run.py`. All undo tests now pass. --- .../blender/windowmanager/intern/wm_event_system.c | 46 +++++++++++++--------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 1c3f7ed3e7a..4b8552a4ec3 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -102,6 +102,11 @@ static int wm_operator_call_internal(bContext *C, static bool wm_operator_check_locked_interface(bContext *C, wmOperatorType *ot); static wmEvent *wm_event_add_mousemove_to_head(wmWindow *win); +static void wm_event_state_update_and_click_set_ex(wmEvent *event, + wmEvent *event_state, + const bool is_keyboard, + const bool check_double_click); + /* -------------------------------------------------------------------- */ /** \name Event Management * \{ */ @@ -147,17 +152,7 @@ wmEvent *WM_event_add_simulate(wmWindow *win, const wmEvent *event_to_add) copy_v2_v2_int(event->prev_xy, win->eventstate->xy); } else if (ISKEYBOARD_OR_BUTTON(event->type)) { - win->eventstate->prev_val = event->prev_val = win->eventstate->val; - win->eventstate->prev_type = event->prev_type = win->eventstate->type; - - win->eventstate->val = event->val; - win->eventstate->type = event->type; - - if (event->val == KM_PRESS) { - if ((event->flag & WM_EVENT_IS_REPEAT) == 0) { - copy_v2_v2_int(win->eventstate->prev_press_xy, event->xy); - } - } + wm_event_state_update_and_click_set_ex(event, win->eventstate, ISKEYBOARD(event->type), false); } return event; } @@ -4950,10 +4945,14 @@ static wmEvent *wm_event_add_trackpad(wmWindow *win, const wmEvent *event, int d /** * Update the event-state for any kind of event that supports #KM_PRESS / #KM_RELEASE. + * + * \param check_double_click: Optionally skip checking for double-click events. + * Needed for event simulation where the time of click events is not so predictable. */ -static void wm_event_state_update_and_click_set(const GHOST_TEventType type, - wmEvent *event, - wmEvent *event_state) +static void wm_event_state_update_and_click_set_ex(wmEvent *event, + wmEvent *event_state, + const bool is_keyboard, + const bool check_double_click) { BLI_assert(ISKEYBOARD_OR_BUTTON(event->type)); BLI_assert(ELEM(event->val, KM_PRESS, KM_RELEASE)); @@ -4969,7 +4968,7 @@ static void wm_event_state_update_and_click_set(const GHOST_TEventType type, /* It's important only to write into the `event_state` modifier for keyboard * events because emulate MMB clears one of the modifiers in `event->modifier`, * making the second press not behave as if the modifier is pressed, see T96279. */ - if (ELEM(type, GHOST_kEventKeyDown, GHOST_kEventKeyUp)) { + if (is_keyboard) { event_state->modifier = event->modifier; } event_state->flag = (event->flag & event_state_flag_mask); @@ -4977,7 +4976,7 @@ static void wm_event_state_update_and_click_set(const GHOST_TEventType type, * since the `event_state` and the `event` are not kept in sync. */ /* Double click test. */ - if (wm_event_is_double_click(event)) { + if (check_double_click && wm_event_is_double_click(event)) { CLOG_INFO(WM_LOG_HANDLERS, 1, "DBL_CLICK: detected"); event->val = KM_DBL_CLICK; } @@ -4988,6 +4987,15 @@ static void wm_event_state_update_and_click_set(const GHOST_TEventType type, } } +static void wm_event_state_update_and_click_set(wmEvent *event, + wmEvent *event_state, + const GHOST_TEventType type) +{ + const bool is_keyboard = ELEM(type, GHOST_kEventKeyDown, GHOST_kEventKeyUp); + const bool check_double_click = true; + wm_event_state_update_and_click_set_ex(event, event_state, is_keyboard, check_double_click); +} + void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void *customdata) { if (UNLIKELY(G.f & G_FLAG_EVENT_SIMULATE)) { @@ -5147,7 +5155,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void wm_tablet_data_from_ghost(&bd->tablet, &event.tablet); wm_eventemulation(&event, false); - wm_event_state_update_and_click_set(type, &event, event_state); + wm_event_state_update_and_click_set(&event, event_state, type); /* Add to other window if event is there (not to both!). */ wmWindow *win_other = wm_event_cursor_other_windows(wm, win, &event); @@ -5271,7 +5279,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void } /* It's important `event.modifier` has been initialized first. */ - wm_event_state_update_and_click_set(type, &event, event_state); + wm_event_state_update_and_click_set(&event, event_state, type); /* If test_break set, it catches this. Do not set with modifier presses. * Exclude modifiers because MS-Windows uses these to bring up the task manager. @@ -5345,7 +5353,7 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, void event.custom = 0; event.customdata = NULL; - wm_event_state_update_and_click_set(type, &event, event_state); + wm_event_state_update_and_click_set(&event, event_state, type); wm_event_add(win, &event); -- cgit v1.2.3