[PATCH] server: Improve handling of cursor position clipping for empty rectangle.
Andrew Eikum
aeikum at codeweavers.com
Mon Feb 18 08:26:11 CST 2019
From: Sebastian Lackner <sebastian at fds-team.de>
Based on a patch by Kevin Buhr.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38791
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=42631
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
>From Sebastian: "We cannot match the Windows behavior because there is
no sane way to emulate the unusual Windows cursor clipping in
winex11/winemac. For now it is better to keep wineserver and backends
synchronized to avoid cursor drift."
Before this patch, a mouse at 0,0 clipped to 0,0,0,0 would end up at
-1,-1 in the server. With the patch, it ends up at 0,0. The new
behavior still doesn't totally match Windows. See the todo_wines in
the tests, which mostly invert if you remove this patch. However, it
fixes a nasty issue in a common game engine.
This patch has been in wine-staging since June 2017.
dlls/user32/tests/input.c | 69 +++++++++++++++++++++++++++++++++++++++
server/queue.c | 8 ++---
2 files changed, 73 insertions(+), 4 deletions(-)
diff --git a/dlls/user32/tests/input.c b/dlls/user32/tests/input.c
index ffdd4b7137..835dfb108d 100644
--- a/dlls/user32/tests/input.c
+++ b/dlls/user32/tests/input.c
@@ -1269,6 +1269,19 @@ static LRESULT CALLBACK hook_proc2( int code, WPARAM wparam, LPARAM lparam )
return CallNextHookEx( 0, code, wparam, lparam );
}
+static LRESULT CALLBACK hook_proc3( int code, WPARAM wparam, LPARAM lparam )
+{
+ POINT pt;
+
+ if (code == HC_ACTION)
+ {
+ /* MSLLHOOKSTRUCT does not seem to be reliable and contains different data on each run. */
+ GetCursorPos(&pt);
+ ok(pt.x == pt_old.x && pt.y == pt_old.y, "GetCursorPos: (%d,%d)\n", pt.x, pt.y);
+ }
+ return CallNextHookEx( 0, code, wparam, lparam );
+}
+
static void test_mouse_ll_hook(void)
{
HWND hwnd;
@@ -1342,6 +1355,62 @@ static void test_mouse_ll_hook(void)
ok(pt.x == pt_new.x && pt.y == pt_new.y, "Position changed: (%d,%d)\n", pt.x, pt.y);
UnhookWindowsHookEx(hook2);
+ hook1 = SetWindowsHookExA(WH_MOUSE_LL, hook_proc3, GetModuleHandleA(0), 0);
+
+ SetRect(&rc, 150, 150, 150, 150);
+ ClipCursor(&rc);
+ clipped = TRUE;
+
+ SetCursorPos(140, 140);
+ GetCursorPos(&pt_old);
+ ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ SetCursorPos(160, 160);
+ GetCursorPos(&pt_old);
+ todo_wine
+ ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ mouse_event(MOUSEEVENTF_MOVE, -STEP, -STEP, 0, 0);
+ GetCursorPos(&pt_old);
+ ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ mouse_event(MOUSEEVENTF_MOVE, +STEP, +STEP, 0, 0);
+ GetCursorPos(&pt_old);
+ todo_wine
+ ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0);
+ GetCursorPos(&pt_old);
+ ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ mouse_event(MOUSEEVENTF_MOVE, 0, 0, 0, 0);
+ GetCursorPos(&pt_old);
+ todo_wine
+ ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+
+ clipped = FALSE;
+ ClipCursor(NULL);
+
+ SetCursorPos(140, 140);
+ SetRect(&rc, 150, 150, 150, 150);
+ ClipCursor(&rc);
+ GetCursorPos(&pt_old);
+ ok(pt_old.x == 150 && pt_old.y == 150, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ ClipCursor(NULL);
+
+ SetCursorPos(160, 160);
+ SetRect(&rc, 150, 150, 150, 150);
+ ClipCursor(&rc);
+ GetCursorPos(&pt_old);
+ todo_wine
+ ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ ClipCursor(NULL);
+
+ SetCursorPos(150, 150);
+ SetRect(&rc, 150, 150, 150, 150);
+ ClipCursor(&rc);
+ GetCursorPos(&pt_old);
+ todo_wine
+ ok(pt_old.x == 149 && pt_old.y == 149, "Wrong new pos: (%d,%d)\n", pt_old.x, pt_old.y);
+ ClipCursor(NULL);
+
+ UnhookWindowsHookEx(hook1);
+
done:
DestroyWindow(hwnd);
SetCursorPos(pt_org.x, pt_org.y);
diff --git a/server/queue.c b/server/queue.c
index 545991b99c..2eec422c57 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -411,8 +411,8 @@ static void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect
post_desktop_message( desktop, desktop->cursor.clip_msg, rect != NULL, 0 );
/* warp the mouse to be inside the clip rect */
- x = min( max( desktop->cursor.x, desktop->cursor.clip.left ), desktop->cursor.clip.right-1 );
- y = min( max( desktop->cursor.y, desktop->cursor.clip.top ), desktop->cursor.clip.bottom-1 );
+ x = max( min( desktop->cursor.x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left );
+ y = max( min( desktop->cursor.y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top );
if (x != desktop->cursor.x || y != desktop->cursor.y) set_cursor_pos( desktop, x, y );
}
@@ -1500,8 +1500,8 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg
{
if (msg->msg == WM_MOUSEMOVE)
{
- int x = min( max( msg->x, desktop->cursor.clip.left ), desktop->cursor.clip.right-1 );
- int y = min( max( msg->y, desktop->cursor.clip.top ), desktop->cursor.clip.bottom-1 );
+ int x = max( min( msg->x, desktop->cursor.clip.right - 1 ), desktop->cursor.clip.left );
+ int y = max( min( msg->y, desktop->cursor.clip.bottom - 1 ), desktop->cursor.clip.top );
if (desktop->cursor.x != x || desktop->cursor.y != y) always_queue = 1;
desktop->cursor.x = x;
desktop->cursor.y = y;
--
2.20.1
More information about the wine-devel
mailing list