[Bf-blender-cvs] [9bd586a01e6] blender-v3.1-release: Fix T95608: Mac issues with drag drop on multi-monitor

Germano Cavalcante noreply at git.blender.org
Tue Mar 1 22:25:31 CET 2022


Commit: 9bd586a01e6813a615eab05871803730603e2152
Author: Germano Cavalcante
Date:   Tue Mar 1 18:09:28 2022 -0300
Branches: blender-v3.1-release
https://developer.blender.org/rB9bd586a01e6813a615eab05871803730603e2152

Fix T95608: Mac issues with drag drop on multi-monitor

Mousemove events are sent to windows.

In Windows OS, almost all mousemove events are sent to the window whose
mouse cursor is over.

On MacOS, the window with mousemove events is always the active window.
It doesn't matter if the mouse cursor is inside or outside the window.

So, in order for non-active windows to also have events,
`WM_window_find_under_cursor` is called to find those windows and send
the same events.

The problem is that to find the window, `WM_window_find_under_cursor`
only has the mouse coordinates available, it doesn't differentiate
which monitor these coordinates came from.

So the mouse on one monitor may incorrectly send events to a window on
another monitor.

The solution used is to use a native API on Mac to detect the window
under the cursor.

For Windows and Linux nothing has changed.

Reviewed By: brecht

Differential Revision: https://developer.blender.org/D14197

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_ISystem.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_System.cpp
M	intern/ghost/intern/GHOST_System.h
M	intern/ghost/intern/GHOST_SystemCocoa.h
M	intern/ghost/intern/GHOST_SystemCocoa.mm
M	intern/ghost/intern/GHOST_SystemNULL.h
M	source/blender/editors/interface/interface_eyedropper.c
M	source/blender/windowmanager/WM_api.h
M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_window.c

===================================================================

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 98094cc0669..a2eef91c704 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -265,6 +265,16 @@ extern GHOST_TSuccess GHOST_EndFullScreen(GHOST_SystemHandle systemhandle);
  */
 extern int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle);
 
+/**
+ * Get the Window under the cursor.
+ * \param x: The x-coordinate of the cursor.
+ * \param y: The y-coordinate of the cursor.
+ * @return The window under the cursor or nullptr in none.
+ */
+extern GHOST_WindowHandle GHOST_GetWindowUnderCursor(GHOST_SystemHandle systemhandle,
+                                                     int32_t x,
+                                                     int32_t y);
+
 /***************************************************************************************
  * Event management functionality
  ***************************************************************************************/
diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h
index 05c6c9d907f..4c568a0cc02 100644
--- a/intern/ghost/GHOST_ISystem.h
+++ b/intern/ghost/GHOST_ISystem.h
@@ -325,6 +325,14 @@ class GHOST_ISystem {
    */
   virtual void useWindowFocus(const bool use_focus) = 0;
 
+  /**
+   * Get the Window under the cursor.
+   * \param x: The x-coordinate of the cursor.
+   * \param y: The y-coordinate of the cursor.
+   * @return The window under the cursor or nullptr if none.
+   */
+  virtual GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y) = 0;
+
   /***************************************************************************************
    * Event management functionality
    ***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index a21c3a90c06..3d8411a8268 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -249,6 +249,16 @@ int GHOST_GetFullScreen(GHOST_SystemHandle systemhandle)
   return (int)system->getFullScreen();
 }
 
+GHOST_WindowHandle GHOST_GetWindowUnderCursor(GHOST_SystemHandle systemhandle,
+                                              int32_t x,
+                                              int32_t y)
+{
+  GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
+  GHOST_IWindow *window = system->getWindowUnderCursor(x, y);
+
+  return (GHOST_WindowHandle)window;
+}
+
 bool GHOST_ProcessEvents(GHOST_SystemHandle systemhandle, bool waitForEvent)
 {
   GHOST_ISystem *system = (GHOST_ISystem *)systemhandle;
diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp
index d09c167cb95..17f74003805 100644
--- a/intern/ghost/intern/GHOST_System.cpp
+++ b/intern/ghost/intern/GHOST_System.cpp
@@ -205,6 +205,25 @@ bool GHOST_System::getFullScreen(void)
   return fullScreen;
 }
 
+GHOST_IWindow *GHOST_System::getWindowUnderCursor(int32_t x, int32_t y)
+{
+  /* TODO: This solution should follow the order of the activated windows (Z-order).
+   * It is imperfect but usable in most cases. */
+  for (GHOST_IWindow *iwindow : m_windowManager->getWindows()) {
+    if (iwindow->getState() == GHOST_kWindowStateMinimized) {
+      continue;
+    }
+
+    GHOST_Rect bounds;
+    iwindow->getClientBounds(bounds);
+    if (bounds.isInside(x, y)) {
+      return iwindow;
+    }
+  }
+
+  return NULL;
+}
+
 void GHOST_System::dispatchEvents()
 {
 #ifdef WITH_INPUT_NDOF
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 16c34ff1a6d..692e483be2a 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -173,6 +173,14 @@ class GHOST_System : public GHOST_ISystem {
   void useWindowFocus(const bool use_focus);
   bool m_windowFocus;
 
+  /**
+   * Get the Window under the cursor.
+   * \param x: The x-coordinate of the cursor.
+   * \param y: The y-coordinate of the cursor.
+   * @return The window under the cursor or nullptr if none.
+   */
+  GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y);
+
   /***************************************************************************************
    * Event management functionality
    ***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index 5950da6813d..37cba8b8559 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -125,6 +125,14 @@ class GHOST_SystemCocoa : public GHOST_System {
    */
   GHOST_TSuccess disposeContext(GHOST_IContext *context);
 
+  /**
+   * Get the Window under the cursor.
+   * \param x: The x-coordinate of the cursor.
+   * \param y: The y-coordinate of the cursor.
+   * @return The window under the cursor or nullptr if none.
+   */
+  GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y);
+
   /***************************************************************************************
    * Event management functionality
    ***************************************************************************************/
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index a53c3d8f2ab..b54bfab5547 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -788,6 +788,20 @@ GHOST_TSuccess GHOST_SystemCocoa::disposeContext(GHOST_IContext *context)
   return GHOST_kSuccess;
 }
 
+GHOST_IWindow *GHOST_SystemCocoa::getWindowUnderCursor(int32_t x, int32_t y)
+{
+  NSPoint scr_co = NSMakePoint(x, y);
+
+  int windowNumberAtPoint = [NSWindow windowNumberAtPoint:scr_co belowWindowWithWindowNumber:0];
+  NSWindow *nswindow = [NSApp windowWithWindowNumber:windowNumberAtPoint];
+
+  if (nswindow == nil) {
+    return nil;
+  }
+
+  return m_windowManager->getWindowAssociatedWithOSWindow((void *)nswindow);
+}
+
 /**
  * \note : returns coordinates in Cocoa screen coordinates
  */
diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h
index 5dbc42b53a2..43bbc788113 100644
--- a/intern/ghost/intern/GHOST_SystemNULL.h
+++ b/intern/ghost/intern/GHOST_SystemNULL.h
@@ -128,4 +128,9 @@ class GHOST_SystemNULL : public GHOST_System {
                                 type,
                                 ((glSettings.flags & GHOST_glStereoVisual) != 0));
   }
+
+  GHOST_IWindow *getWindowUnderCursor(int32_t x, int32_t y)
+  {
+    return NULL;
+  }
 };
diff --git a/source/blender/editors/interface/interface_eyedropper.c b/source/blender/editors/interface/interface_eyedropper.c
index fd03cc5e12c..c475e143df0 100644
--- a/source/blender/editors/interface/interface_eyedropper.c
+++ b/source/blender/editors/interface/interface_eyedropper.c
@@ -165,8 +165,7 @@ void datadropper_win_area_find(
   *r_win = CTX_wm_window(C);
   *r_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mval);
   if (*r_area == NULL) {
-    wmWindowManager *wm = CTX_wm_manager(C);
-    *r_win = WM_window_find_under_cursor(wm, NULL, *r_win, mval, r_mval);
+    *r_win = WM_window_find_under_cursor(*r_win, mval, r_mval);
     if (*r_win) {
       screen = WM_window_get_active_screen(*r_win);
       *r_area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, r_mval);
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ff3e1b7474c..5f8a831706b 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -143,11 +143,7 @@ void WM_reinit_gizmomap_all(struct Main *bmain);
  */
 void WM_script_tag_reload(void);
 
-wmWindow *WM_window_find_under_cursor(const wmWindowManager *wm,
-                                      const wmWindow *win_ignore,
-                                      const wmWindow *win,
-                                      const int mval[2],
-                                      int r_mval[2]);
+wmWindow *WM_window_find_under_cursor(wmWindow *win, const int mval[2], int r_mval[2]);
 void WM_window_pixel_sample_read(const wmWindowManager *wm,
                                  const wmWindow *win,
                                  const int pos[2],
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index 0cc2db661ec..d9ef7dc63ff 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -4663,8 +4663,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
       }
     }
 
-    wmWindow *win_other = WM_window_find_under_cursor(wm, win, win, mval, mval);
-    if (win_other) {
+    wmWindow *win_other = WM_window_find_under_cursor(win, mval, mval);
+    if (win_other && win_other != win) {
       copy_v2_v2_int(event->xy, mval);
       return win_other;
     }
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index a1854a8ed86..0a229b2ea56 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1855,56 +1855,23 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
 /** \name Find Window Utility
  * \{ */
 
-static void wm_window_desktop_pos_get(const wmWindow *win,
-                                      const int screen_pos[2],
-                                      int r_desk_pos[2])
+wmWindow *WM_window_find_under_cursor(wmWindow *win, const int mval[2], int r_mval[2])
 {
-  /* To desktop space. */
-  r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx);
-  r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy);
-}
-
-static void wm_window_screen_pos_get(const wmWindow *win,
-                                     const int desktop_pos[2],
-                                     int r_scr_pos[2])
-{
-  /* To window space. */
-  r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx);
-  r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy);
-}
-
-wmWindow *WM_window_find_under_cursor(const wmWindowManager *wm,
-                                      const wmWindo

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list