[Bf-blender-cvs] [00ac2ddca23] master: Fix T103722: Stuck modifiers for wheel events over unfocused windows
Campbell Barton
noreply at git.blender.org
Sun Jan 22 10:51:01 CET 2023
Commit: 00ac2ddca23ee7391da775563edb5685ccbf6a33
Author: Campbell Barton
Date: Sun Jan 22 20:48:17 2023 +1100
Branches: master
https://developer.blender.org/rB00ac2ddca23ee7391da775563edb5685ccbf6a33
Fix T103722: Stuck modifiers for wheel events over unfocused windows
Regression in [0] caused mouse wheel events over windows without focus
to use the modifier state at the point the window was de-activated.
Now un-focused windows have all events release, when focused again
modifier press events are set again.
[0]: 8bc76bf4b957c51ddc5a13c6305f05c64b218a27
===================================================================
M source/blender/windowmanager/intern/wm_window.c
===================================================================
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 2e5e370ae06..7e245236fe0 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -89,6 +89,20 @@
*/
#define USE_WIN_ACTIVATE
+/**
+ * When the window is de-activated, release all held modifiers.
+ *
+ * Needed so events generated over unfocused (non-active) windows don't have modifiers held.
+ * Since modifier press/release events aren't send to unfocused windows it's best to assume
+ * modifiers are not pressed. This means when modifiers *are* held, events will incorrectly
+ * reported as not being held. Since this is standard behavior for Linux/MS-Window,
+ * opt to use this.
+ *
+ * NOTE(@campbellbarton): Events generated for non-active windows are rare,
+ * this happens when using the mouse-wheel over an unfocused window, see: T103722.
+ */
+#define USE_WIN_DEACTIVATE
+
/* the global to talk to ghost */
static GHOST_SystemHandle g_system = NULL;
#if !(defined(WIN32) || defined(__APPLE__))
@@ -1130,6 +1144,41 @@ static bool ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_pt
switch (type) {
case GHOST_kEventWindowDeactivate:
+#ifdef USE_WIN_DEACTIVATE
+ /* Release all held modifiers before de-activating the window. */
+ if (win->eventstate->modifier != 0) {
+ const uint8_t keymodifier_eventstate = win->eventstate->modifier;
+ const uint8_t keymodifier_l = wm_ghost_modifier_query(MOD_SIDE_LEFT);
+ const uint8_t keymodifier_r = wm_ghost_modifier_query(MOD_SIDE_RIGHT);
+ /* NOTE(@campbellbarton): when non-zero, there are modifiers held in
+ * `win->eventstate` which are not considered held by the GHOST internal state.
+ * While this should not happen, it's important all modifier held in event-state
+ * receive release events. Without this, so any events generated while the window
+ * is *not* active will have modifiers held. */
+ const uint8_t keymodifier_unhandled = keymodifier_eventstate &
+ ~(keymodifier_l | keymodifier_r);
+ const uint8_t keymodifier_sided[2] = {
+ keymodifier_l | keymodifier_unhandled,
+ keymodifier_r,
+ };
+ GHOST_TEventKeyData kdata = {
+ .key = GHOST_kKeyUnknown,
+ .utf8_buf = {'\0'},
+ .is_repeat = false,
+ };
+ for (int i = 0; i < ARRAY_SIZE(g_modifier_table); i++) {
+ if (keymodifier_eventstate & g_modifier_table[i].flag) {
+ for (int side = 0; side < 2; side++) {
+ if ((keymodifier_sided[side] & g_modifier_table[i].flag) == 0) {
+ kdata.key = g_modifier_table[i].ghost_key_pair[side];
+ wm_event_add_ghostevent(wm, win, GHOST_kEventKeyUp, &kdata);
+ }
+ }
+ }
+ }
+ }
+#endif /* USE_WIN_DEACTIVATE */
+
wm_event_add_ghostevent(wm, win, type, data);
win->active = 0; /* XXX */
break;
More information about the Bf-blender-cvs
mailing list