[PATCH 2/4] Cygwin/X: Improve mouse tracking for moving/resizing undecorated windows

Jon TURNEY jon.turney at dronecode.org.uk
Wed Jun 24 13:15:26 PDT 2009


In -multiwindow mode, tell Windows we wish to capture the mouse when a button
is down.  This causes Windows to continue to send movement events for the mouse
even if the mouse pointer moves outside the window frame.

This helps greatly with undecorated windows which have regions you can grab
to move (e.g. gmplayer, xine control panels) or resize (e.g. Songbird) the
window, as it means the window continues to receive the mouse motion even if the
mouse pointer  moves out of the window (which presumably happens if we don't
manage to update the window fast enough to track the mouse pointer)

Consolidate the multiple instances of the code to start the mouse position
polling timer into a new function winStartMousePolling(), and use that to
restart the polling timer when we release the mouse.

Also, start the timer on WM_SHOW, so that xeyes will track the mouse position
when it is first shown, even if the mouse doesn't enter it's window
(You probably need focus-stealing turned off to see this problem)

Signed-off-by: Jon TURNEY <jon.turney at dronecode.org.uk>
---
 hw/xwin/winmultiwindowwndproc.c |   59 ++++++++++++++++++++++++--------------
 1 files changed, 37 insertions(+), 22 deletions(-)

diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index becae29..bd9edcb 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -290,6 +290,20 @@ static void winRaiseWindow(WindowPtr pWin)
   }
 }
 
+static
+void winStartMousePolling(winPrivScreenPtr s_pScreenPriv)
+{
+  /*
+   * Timer to poll mouse position.  This is needed to make
+   * programs like xeyes follow the mouse properly when the
+   * mouse pointer is outside of any X window.
+   */
+  if (g_uipMousePollingTimerID == 0)
+    g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
+					 WIN_POLLING_MOUSE_TIMER_ID,
+					 MOUSE_POLLING_INTERVAL,
+					 NULL);
+}
 
 /*
  * winTopLevelWindowProc - Window procedure for all top-level Windows windows.
@@ -565,15 +579,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
 	  ShowCursor (TRUE);
 	}
 
-      /*
-       * Timer to poll mouse events.  This is needed to make
-       * programs like xeyes follow the mouse properly.
-       */
-      if (g_uipMousePollingTimerID == 0)
-	g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
-					     WIN_POLLING_MOUSE_TIMER_ID,
-					     MOUSE_POLLING_INTERVAL,
-					     NULL);
+      winStartMousePolling(s_pScreenPriv);
+
       break;
 
     case WM_MOUSELEAVE:
@@ -589,15 +596,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
 	  ShowCursor (TRUE);
 	}
 
-      /*
-       * Timer to poll mouse events.  This is needed to make
-       * programs like xeyes follow the mouse properly.
-       */
-      if (g_uipMousePollingTimerID == 0)
-	g_uipMousePollingTimerID = SetTimer (s_pScreenPriv->hwndScreen,
-					     WIN_POLLING_MOUSE_TIMER_ID,
-					     MOUSE_POLLING_INTERVAL,
-					     NULL);
+      winStartMousePolling(s_pScreenPriv);
+
       return 0;
 
     case WM_LBUTTONDBLCLK:
@@ -605,12 +605,15 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[0] = TRUE;
+      SetCapture(hwnd);
       return winMouseButtonsHandle (s_pScreen, ButtonPress, Button1, wParam);
-      
+
     case WM_LBUTTONUP:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[0] = FALSE;
+      ReleaseCapture();
+      winStartMousePolling(s_pScreenPriv);
       return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button1, wParam);
 
     case WM_MBUTTONDBLCLK:
@@ -618,35 +621,45 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[1] = TRUE;
+      SetCapture(hwnd);
       return winMouseButtonsHandle (s_pScreen, ButtonPress, Button2, wParam);
-      
+
     case WM_MBUTTONUP:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[1] = FALSE;
+      ReleaseCapture();
+      winStartMousePolling(s_pScreenPriv);
       return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button2, wParam);
-      
+
     case WM_RBUTTONDBLCLK:
     case WM_RBUTTONDOWN:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[2] = TRUE;
+      SetCapture(hwnd);
       return winMouseButtonsHandle (s_pScreen, ButtonPress, Button3, wParam);
-      
+
     case WM_RBUTTONUP:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
       g_fButton[2] = FALSE;
+      ReleaseCapture();
+      winStartMousePolling(s_pScreenPriv);
       return winMouseButtonsHandle (s_pScreen, ButtonRelease, Button3, wParam);
 
     case WM_XBUTTONDBLCLK:
     case WM_XBUTTONDOWN:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
+	SetCapture(hwnd);
       return winMouseButtonsHandle (s_pScreen, ButtonPress, HIWORD(wParam) + 5, wParam);
+
     case WM_XBUTTONUP:
       if (s_pScreenPriv == NULL || s_pScreenInfo->fIgnoreInput)
 	break;
+      ReleaseCapture();
+      winStartMousePolling(s_pScreenPriv);
       return winMouseButtonsHandle (s_pScreen, ButtonRelease, HIWORD(wParam) + 5, wParam);
 
     case WM_MOUSEWHEEL:
@@ -936,6 +949,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message,
       if (fWMMsgInitialized)
 	winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg);
 
+      winStartMousePolling(s_pScreenPriv);
+
       return 0;
 
     case WM_SIZING:
-- 
1.6.1.2



More information about the xorg-devel mailing list