diff options
-rw-r--r-- | source/blender/windowmanager/WM_types.h | 9 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 31 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_gesture.c | 2 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_gesture_ops.c | 15 |
4 files changed, 49 insertions, 8 deletions
diff --git a/source/blender/windowmanager/WM_types.h b/source/blender/windowmanager/WM_types.h index 2f431bcd208..e9f12287d29 100644 --- a/source/blender/windowmanager/WM_types.h +++ b/source/blender/windowmanager/WM_types.h @@ -510,6 +510,10 @@ typedef struct wmGesture { struct wmGesture *next, *prev; /** #wmEvent.type */ int event_type; + /** #wmEvent.modifier */ + uint8_t event_modifier; + /** #wmEvent.keymodifier */ + short event_keymodifier; /** Gesture type define. */ int type; /** bounds of region to draw gesture within. */ @@ -628,6 +632,11 @@ typedef struct wmEvent { double prev_click_time; /** The location when the key is pressed (used to enforce drag thresholds). */ int prev_click_xy[2]; + /** The `modifier` at the point of the click action. */ + uint8_t prev_click_modifier; + /** The `keymodifier` at the point of the click action. */ + short prev_click_keymodifier; + /** * The previous value of #wmEvent.xy, * Unlike other previous state variables, this is set on any mouse motion. diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 326b8c167b8..6753978eece 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -3161,21 +3161,27 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) if (WM_event_drag_test(event, event->prev_click_xy)) { win->event_queue_check_drag_handled = true; - int xy[2] = {UNPACK2(event->xy)}; - short val = event->val; - short type = event->type; + const int prev_xy[2] = {UNPACK2(event->xy)}; + const short prev_val = event->val; + const short prev_type = event->type; + const uint8_t prev_modifier = event->modifier; + const short prev_keymodifier = event->keymodifier; copy_v2_v2_int(event->xy, event->prev_click_xy); event->val = KM_CLICK_DRAG; event->type = event->prev_type; + event->modifier = event->prev_click_modifier; + event->keymodifier = event->prev_click_keymodifier; CLOG_INFO(WM_LOG_HANDLERS, 1, "handling PRESS_DRAG"); action |= wm_handlers_do_intern(C, win, event, handlers); - event->val = val; - event->type = type; - copy_v2_v2_int(event->xy, xy); + event->keymodifier = prev_keymodifier; + event->modifier = prev_modifier; + event->val = prev_val; + event->type = prev_type; + copy_v2_v2_int(event->xy, prev_xy); win->event_queue_check_click = false; if (!wm_action_not_handled(action)) { @@ -3205,7 +3211,16 @@ static int wm_handlers_do(bContext *C, wmEvent *event, ListBase *handlers) } } else if (event->val == KM_RELEASE) { - win->event_queue_check_drag = false; + if (win->event_queue_check_drag) { + if ((event->prev_type != event->type) && + (ISKEYMODIFIER(event->type) || (event->type == event->prev_click_keymodifier))) { + /* Support releasing modifier keys without canceling the drag event, see T89989. + * NOTE: this logic is replicated for tweak gestures. */ + } + else { + win->event_queue_check_drag = false; + } + } } if (event->prev_type == event->type) { @@ -4692,6 +4707,8 @@ static void wm_event_prev_click_set(wmEvent *event, wmEvent *event_state) event->prev_click_time = event_state->prev_click_time = PIL_check_seconds_timer(); event->prev_click_xy[0] = event_state->prev_click_xy[0] = event_state->xy[0]; event->prev_click_xy[1] = event_state->prev_click_xy[1] = event_state->xy[1]; + event->prev_click_modifier = event_state->prev_click_modifier = event_state->modifier; + event->prev_click_keymodifier = event_state->prev_click_keymodifier = event_state->keymodifier; } static wmEvent *wm_event_add_mousemove(wmWindow *win, const wmEvent *event) diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c index 581c5f8a198..86ada4aaf2a 100644 --- a/source/blender/windowmanager/intern/wm_gesture.c +++ b/source/blender/windowmanager/intern/wm_gesture.c @@ -42,6 +42,8 @@ wmGesture *WM_gesture_new(wmWindow *window, const ARegion *region, const wmEvent gesture->type = type; gesture->event_type = event->type; + gesture->event_modifier = event->modifier; + gesture->event_keymodifier = event->keymodifier; gesture->winrct = region->winrct; gesture->user_data.use_free = true; /* Free if userdata is set. */ gesture->modal_state = GESTURE_MODAL_NOP; diff --git a/source/blender/windowmanager/intern/wm_gesture_ops.c b/source/blender/windowmanager/intern/wm_gesture_ops.c index 2a27a8df411..d7e62d549d0 100644 --- a/source/blender/windowmanager/intern/wm_gesture_ops.c +++ b/source/blender/windowmanager/intern/wm_gesture_ops.c @@ -507,6 +507,8 @@ static void gesture_tweak_modal(bContext *C, const wmEvent *event) tevent.type = EVT_TWEAK_M; } tevent.val = val; + tevent.modifier = gesture->event_modifier; + tevent.keymodifier = gesture->event_keymodifier; tevent.is_repeat = false; /* mouse coords! */ @@ -533,7 +535,18 @@ static void gesture_tweak_modal(bContext *C, const wmEvent *event) } break; default: - if (!ISTIMER(event->type) && event->type != EVENT_NONE) { + if (ISTIMER(event->type)) { + /* Ignore timers. */ + } + else if (event->type == EVENT_NONE) { + /* Ignore none events. */ + } + else if ((event->val == KM_RELEASE) && + (ISKEYMODIFIER(event->type) || (event->type == event->prev_click_keymodifier))) { + /* Support releasing modifier keys without canceling the drag event, see T89989. + * NOTE: this logic is replicated for drag events. */ + } + else { gesture_end = true; } break; |