From 85614946ba3d5a233eece612afc7f09572a347c2 Mon Sep 17 00:00:00 2001 From: Jon TURNEY Date: Mon, 18 May 2009 18:13:08 +0100 Subject: [PATCH] Cygwin/X: Improve mouse tracking for moving/resizing undecorated windows 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 --- hw/xwin/winmultiwindowwndproc.c | 59 +++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 22 deletions(-) diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index becae2949..bd9edcb4d 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: