diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c index 1373a88..badb44a 100644 --- a/dlls/winex11.drv/mouse.c +++ b/dlls/winex11.drv/mouse.c @@ -69,7 +69,18 @@ static const UINT button_up_flags[NB_BUT MOUSEEVENTF_XUP }; -POINT cursor_pos; +POINT cursor_pos = {-10, -10}; + +static CRITICAL_SECTION cursor_CritSection; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &cursor_CritSection, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": cursor_CritSection") } +}; +static CRITICAL_SECTION cursor_CritSection = { &critsect_debug, -1, 0, 0, 0, 0 }; + +BOOL X11DRV_SetCursorPos( INT x, INT y ); /*********************************************************************** * get_coords @@ -109,8 +120,10 @@ static inline void update_button_state( */ static inline void update_key_state( unsigned int state ) { - key_state_table[VK_SHIFT] = (state & ShiftMask ? 0x80 : 0); - key_state_table[VK_CONTROL] = (state & ControlMask ? 0x80 : 0); + DWORD time = GetCurrentTime(); + + KEYBOARD_UpdateOneState( VK_SHIFT, 0x2a, (state & ShiftMask) != 0, time ); + KEYBOARD_UpdateOneState( VK_CONTROL, 0x1d, (state & ControlMask) != 0, time ); } @@ -241,9 +254,6 @@ void X11DRV_send_mouse_input( HWND hwnd, pt.x = x; pt.y = y; } - wine_tsx11_lock(); - cursor_pos = pt; - wine_tsx11_unlock(); } else if (flags & MOUSEEVENTF_MOVE) { @@ -263,23 +273,22 @@ void X11DRV_send_mouse_input( HWND hwnd, if ((abs(y) > accel[1]) && (accel[2] == 2)) yMult = 4; } - wine_tsx11_lock(); + EnterCriticalSection( &cursor_CritSection ); pt.x = cursor_pos.x + (long)x * xMult; pt.y = cursor_pos.y + (long)y * yMult; + LeaveCriticalSection( &cursor_CritSection ); /* Clip to the current screen size */ if (pt.x < 0) pt.x = 0; else if (pt.x >= screen_width) pt.x = screen_width - 1; if (pt.y < 0) pt.y = 0; else if (pt.y >= screen_height) pt.y = screen_height - 1; - cursor_pos = pt; - wine_tsx11_unlock(); } else { - wine_tsx11_lock(); + EnterCriticalSection( &cursor_CritSection ); pt = cursor_pos; - wine_tsx11_unlock(); + LeaveCriticalSection( &cursor_CritSection ); } if (flags & MOUSEEVENTF_MOVE) @@ -289,10 +298,11 @@ void X11DRV_send_mouse_input( HWND hwnd, if ((injected_flags & LLMHF_INJECTED) && ((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */ { - TRACE( "warping to (%ld,%ld)\n", pt.x, pt.y ); - wine_tsx11_lock(); - XWarpPointer( thread_display(), root_window, root_window, 0, 0, 0, 0, pt.x, pt.y ); - wine_tsx11_unlock(); + X11DRV_SetCursorPos(pt.x, pt.y); + } else { + EnterCriticalSection( &cursor_CritSection ); + cursor_pos = pt; + LeaveCriticalSection( &cursor_CritSection ); } } if (flags & MOUSEEVENTF_LEFTDOWN) @@ -689,16 +699,29 @@ void X11DRV_SetCursor( CURSORICONINFO *l */ BOOL X11DRV_SetCursorPos( INT x, INT y ) { - Display *display = thread_display(); + Display *display; + + /* Cursor position hasn't changed at all or not yet. */ + EnterCriticalSection(&cursor_CritSection); + if (cursor_pos.x == x && cursor_pos.y == y) + { + LeaveCriticalSection(&cursor_CritSection); + return TRUE; + } + LeaveCriticalSection(&cursor_CritSection); TRACE( "warping to (%d,%d)\n", x, y ); + display = thread_display(); wine_tsx11_lock(); XWarpPointer( display, root_window, root_window, 0, 0, 0, 0, x, y ); XFlush( display ); /* avoids bad mouse lag in games that do their own mouse warping */ + wine_tsx11_unlock(); + + EnterCriticalSection( &cursor_CritSection ); cursor_pos.x = x; cursor_pos.y = y; - wine_tsx11_unlock(); + LeaveCriticalSection( &cursor_CritSection ); return TRUE; } @@ -707,23 +730,33 @@ BOOL X11DRV_SetCursorPos( INT x, INT y ) */ BOOL X11DRV_GetCursorPos(LPPOINT pos) { - Display *display = thread_display(); - Window root, child; - int rootX, rootY, winX, winY; - unsigned int xstate; - - wine_tsx11_lock(); - if (XQueryPointer( display, root_window, &root, &child, - &rootX, &rootY, &winX, &winY, &xstate )) + if (cursor_pos.x == -10 && cursor_pos.y == -10) { - update_key_state( xstate ); - update_button_state( xstate ); - TRACE("pointer at (%d,%d)\n", winX, winY ); - cursor_pos.x = winX; - cursor_pos.y = winY; + Display *display = thread_display(); + Window root, child; + int rootX, rootY, winX, winY; + unsigned int xstate; + BOOL res; + + wine_tsx11_lock(); + res = XQueryPointer( display, root_window, &root, &child, + &rootX, &rootY, &winX, &winY, &xstate ); + wine_tsx11_unlock(); + if (res) + { + update_key_state( xstate ); + update_button_state( xstate ); + TRACE("pointer at (%d,%d)\n", winX, winY ); + EnterCriticalSection( &cursor_CritSection ); + cursor_pos.x = winX; + cursor_pos.y = winY; + LeaveCriticalSection( &cursor_CritSection ); + } } + EnterCriticalSection( &cursor_CritSection ); *pos = cursor_pos; - wine_tsx11_unlock(); + LeaveCriticalSection( &cursor_CritSection ); + return TRUE; }