[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