From: Conor McCarthy cmccarthy@codeweavers.com
When scaling applies, after a call to SetCursorPos(), a subsequent call to GetCursorPos() may not return the exact coordinates set, which an app may interpret as mouse movement. --- dlls/user32/tests/monitor.c | 2 - dlls/win32u/input.c | 35 +++++++----- dlls/win32u/message.c | 24 +++++---- dlls/win32u/sysparams.c | 97 ++++++++++++++++++++++++++++++++++ dlls/win32u/win32u_private.h | 7 +++ include/wine/server_protocol.h | 14 ++--- server/protocol.def | 12 ++--- server/queue.c | 21 ++++---- server/request_handlers.h | 1 + server/request_trace.h | 8 +-- server/user.h | 11 +++- server/window.c | 63 +++++++++++++++------- tools/make_requests | 1 + 13 files changed, 226 insertions(+), 70 deletions(-)
diff --git a/dlls/user32/tests/monitor.c b/dlls/user32/tests/monitor.c index 7ad3970a646..f76971c1b53 100644 --- a/dlls/user32/tests/monitor.c +++ b/dlls/user32/tests/monitor.c @@ -3731,9 +3731,7 @@ static void test_monitor_dpi(void) y = x - infos[i].rect.left + infos[i].rect.top; SetCursorPos(x, y); GetCursorPos(&pt); - todo_wine_if(pt.x != x) ok(pt.x == x, "got x %ld, expected %d.\n", pt.x, x); - todo_wine_if(pt.y != y) ok(pt.y == y, "got y %ld, expected %d.\n", pt.y, y); }
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c index 252ae78e6a0..6e7f382ad02 100644 --- a/dlls/win32u/input.c +++ b/dlls/win32u/input.c @@ -706,16 +706,18 @@ UINT WINAPI NtUserSendInput( UINT count, INPUT *inputs, int size ) */ BOOL WINAPI NtUserSetCursorPos( INT x, INT y ) { - RECT rect = {x, y, x, y}; + float float_x, float_y; BOOL ret; INT prev_x, prev_y, new_x, new_y;
- rect = map_rect_virt_to_raw( rect, get_thread_dpi() ); + float_x = x; + float_y = y; + map_float_point_virt_to_raw( &float_x, &float_y, get_thread_dpi() ); SERVER_START_REQ( set_cursor ) { req->flags = SET_CURSOR_POS; - req->x = rect.left; - req->y = rect.top; + req->x = float_x; + req->y = float_y; if ((ret = !wine_server_call( req ))) { prev_x = reply->prev_x; @@ -736,28 +738,37 @@ BOOL WINAPI NtUserGetCursorPos( POINT *pt ) { struct object_lock lock = OBJECT_LOCK_INIT; const desktop_shm_t *desktop_shm; + float x = 0.0f, y = 0.0f; BOOL ret = TRUE; DWORD last_change = 0; NTSTATUS status; - RECT rect;
if (!pt) return FALSE;
while ((status = get_shared_desktop( &lock, &desktop_shm )) == STATUS_PENDING) { - pt->x = desktop_shm->cursor.x; - pt->y = desktop_shm->cursor.y; + x = desktop_shm->cursor.x; + y = desktop_shm->cursor.y; last_change = desktop_shm->cursor.last_change; } if (status) return FALSE;
/* query new position from graphics driver if we haven't updated recently */ - if (NtGetTickCount() - last_change > 100) ret = user_driver->pGetCursorPos( pt ); - if (!ret) return FALSE; + if (NtGetTickCount() - last_change > 100) + { + ret = user_driver->pGetCursorPos( pt ); + if (!ret) return FALSE; + /* keep the more accurate float position if the driver's position matches */ + if (pt->x != float_round_to_int( x ) || pt->y != float_round_to_int( y )) + { + x = pt->x; + y = pt->y; + } + }
- SetRect( &rect, pt->x, pt->y, pt->x, pt->y ); - rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); - *pt = *(POINT *)&rect.left; + map_float_point_raw_to_virt( &x, &y, get_thread_dpi() ); + pt->x = float_round_to_int( x ); + pt->y = float_round_to_int( y ); return ret; }
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 9e8f9d54af8..203fea7b041 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2771,7 +2771,7 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar HWND hwnd_filter, UINT first, UINT last, BOOL remove ) { struct ntuser_thread_info *thread_info = NtUserGetThreadInfo(); - RECT rect = {msg->pt.x, msg->pt.y, msg->pt.x, msg->pt.y}; + float x, y; UINT context; BOOL ret = FALSE;
@@ -2780,9 +2780,11 @@ static BOOL process_hardware_message( MSG *msg, UINT hw_id, const struct hardwar
/* hardware messages are always in raw physical coords */ context = set_thread_dpi_awareness_context( NTUSER_DPI_PER_MONITOR_AWARE ); - rect = map_rect_raw_to_virt( rect, get_thread_dpi() ); - msg->pt.x = rect.left; - msg->pt.y = rect.top; + x = msg->pt.x; + y = msg->pt.y; + map_float_point_raw_to_virt( &x, &y, get_thread_dpi() ); + msg->pt.x = float_round_to_int( x ); + msg->pt.y = float_round_to_int( y );
if (msg->message == WM_INPUT || msg->message == WM_INPUT_DEVICE_CHANGE) ret = process_rawinput_message( msg, hw_id, msg_data ); @@ -2855,6 +2857,7 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter ) unsigned char buffer_init[1024]; size_t buffer_size = sizeof(buffer_init); void *buffer = buffer_init; + float reply_x, reply_y;
if (!first && !last) last = ~0; if (hwnd == HWND_BROADCAST) hwnd = HWND_TOPMOST; @@ -2906,8 +2909,10 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter ) info.msg.wParam = reply->wparam; info.msg.lParam = reply->lparam; info.msg.time = reply->time; - info.msg.pt.x = reply->x; - info.msg.pt.y = reply->y; + reply_x = reply->x; + reply_y = reply->y; + info.msg.pt.x = float_round_to_int( reply_x ); + info.msg.pt.y = float_round_to_int( reply_y ); hw_id = 0; } else buffer_size = reply->total; @@ -3007,12 +3012,11 @@ static int peek_message( MSG *msg, const struct peek_message_filter *filter ) } else if (info.msg.message == WH_MOUSE_LL && size >= sizeof(msg_data->hardware)) { - RECT rect = {info.msg.pt.x, info.msg.pt.y, info.msg.pt.x, info.msg.pt.y}; MSLLHOOKSTRUCT hook;
- rect = map_rect_raw_to_virt( rect, 0 ); - info.msg.pt.x = rect.left; - info.msg.pt.y = rect.top; + map_float_point_raw_to_virt( &reply_x, &reply_y, 0 ); + info.msg.pt.x = float_round_to_int( reply_x ); + info.msg.pt.y = float_round_to_int( reply_y );
hook.pt = info.msg.pt; hook.mouseData = info.msg.lParam; diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 13b49a9f12c..aa8fd8179a6 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -1913,6 +1913,75 @@ static UINT monitor_get_dpi( struct monitor *monitor, MONITOR_DPI_TYPE type, UIN return min( *dpi_x, *dpi_y ); }
+/* display_lock must be held */ +static void map_monitor_float_point( struct monitor *monitor, float *x, float *y, UINT dpi_from, + MONITOR_DPI_TYPE type_from, UINT dpi_to, MONITOR_DPI_TYPE type_to ) +{ + UINT dpi_x, dpi_y; + float r; + + assert( type_from != type_to ); + + if (monitor->source) + { + DEVMODEW current_mode = {.dmSize = sizeof(DEVMODEW)}, *mode_from, *mode_to; + UINT num, den, dpi; + + source_get_current_settings( monitor->source, ¤t_mode ); + + dpi = monitor_get_dpi( monitor, MDT_DEFAULT, &dpi_x, &dpi_y ); + if (!dpi_from) dpi_from = dpi; + if (!dpi_to) dpi_to = dpi; + + if (type_from == MDT_RAW_DPI) + { + monitor_virt_to_raw_ratio( monitor, &den, &num ); + mode_from = &monitor->source->physical; + mode_to = ¤t_mode; + } + else + { + monitor_virt_to_raw_ratio( monitor, &num, &den ); + mode_from = ¤t_mode; + mode_to = &monitor->source->physical; + } + + if (dpi != dpi_from) + { + r = (float)dpi / dpi_from; + *x *= r; + *y *= r; + } + *x -= mode_from->dmPosition.x + mode_from->dmPelsWidth / 2.0f; + *y -= mode_from->dmPosition.y + mode_from->dmPelsHeight / 2.0f; + if (num != den) + { + r = (float)num / den; + *x *= r; + *y *= r; + } + *x += mode_to->dmPosition.x + mode_to->dmPelsWidth / 2.0f; + *y += mode_to->dmPosition.y + mode_to->dmPelsHeight / 2.0f; + if (dpi_to != dpi) + { + r = (float)dpi_to / dpi; + *x *= r; + *y *= r; + } + + return; + } + + if (!dpi_from) dpi_from = monitor_get_dpi( monitor, type_from, &dpi_x, &dpi_y ); + if (!dpi_to) dpi_to = monitor_get_dpi( monitor, type_to, &dpi_x, &dpi_y ); + if (dpi_from != dpi_to) + { + r = (float)dpi_to / dpi_from; + *x *= r; + *y *= r; + } +} + /* display_lock must be held */ static RECT map_monitor_rect( struct monitor *monitor, RECT rect, UINT dpi_from, MONITOR_DPI_TYPE type_from, UINT dpi_to, MONITOR_DPI_TYPE type_to ) @@ -2604,6 +2673,20 @@ static RECT monitors_get_union_rect( UINT dpi, MONITOR_DPI_TYPE type ) return rect; }
+/* map a monitor point from MDT_RAW_DPI to MDT_DEFAULT coordinates */ +void map_float_point_raw_to_virt( float *x, float *y, UINT dpi_to ) +{ + struct monitor *monitor; + RECT pos; + + if (!lock_display_devices( FALSE )) return; + pos.left = pos.right = float_round_to_int( *x ); + pos.top = pos.bottom = float_round_to_int( *y ); + if ((monitor = get_monitor_from_rect( pos, MONITOR_DEFAULTTONEAREST, 0, MDT_RAW_DPI ))) + map_monitor_float_point( monitor, x, y, 0, MDT_RAW_DPI, dpi_to, MDT_DEFAULT ); + unlock_display_devices(); +} + /* map a monitor rect from MDT_RAW_DPI to MDT_DEFAULT coordinates */ RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ) { @@ -2618,6 +2701,20 @@ RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ) return rect; }
+/* map a monitor point from MDT_DEFAULT to MDT_RAW_DPI coordinates */ +void map_float_point_virt_to_raw( float *x, float *y, UINT dpi_from ) +{ + struct monitor *monitor; + RECT pos; + + if (!lock_display_devices( FALSE )) return; + pos.left = pos.right = float_round_to_int( *x ); + pos.top = pos.bottom = float_round_to_int( *y ); + if ((monitor = get_monitor_from_rect( pos, MONITOR_DEFAULTTONEAREST, dpi_from, MDT_DEFAULT ))) + map_monitor_float_point( monitor, x, y, dpi_from, MDT_DEFAULT, 0, MDT_RAW_DPI ); + unlock_display_devices(); +} + /* map a monitor rect from MDT_DEFAULT to MDT_RAW_DPI coordinates */ RECT map_rect_virt_to_raw( RECT rect, UINT dpi_from ) { diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 6eaa7270b01..a0d01c83ef1 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -174,7 +174,9 @@ extern POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to ); extern RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ); extern HRGN map_dpi_region( HRGN region, UINT dpi_from, UINT dpi_to ); extern struct window_rects map_dpi_window_rects( struct window_rects rects, UINT dpi_from, UINT dpi_to ); +extern void map_float_point_raw_to_virt( float *x, float *y, UINT dpi_to ); extern RECT map_rect_raw_to_virt( RECT rect, UINT dpi_to ); +extern void map_float_point_virt_to_raw( float *x, float *y, UINT dpi_from ); extern RECT map_rect_virt_to_raw( RECT rect, UINT dpi_from ); extern struct window_rects map_window_rects_virt_to_raw( struct window_rects rects, UINT dpi_from ); extern POINT point_phys_to_win_dpi( HWND hwnd, POINT pt ); @@ -418,4 +420,9 @@ static inline BOOL intersect_rect( RECT *dst, const RECT *src1, const RECT *src2 return !IsRectEmpty( dst ); }
+static inline int float_round_to_int( float val ) +{ + return val + 0.5f; +} + #endif /* __WINE_WIN32U_PRIVATE */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index d9f1099f154..f5076ca9b0a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -979,8 +979,8 @@ struct obj_locator
struct shared_cursor { - int x; - int y; + float x; + float y; unsigned int last_change; struct rectangle clip; }; @@ -3146,8 +3146,8 @@ struct get_message_reply lparam_t wparam; lparam_t lparam; int type; - int x; - int y; + float x; + float y; unsigned int time; data_size_t total; /* VARARG(data,message_data); */ @@ -5713,8 +5713,8 @@ struct set_cursor_request unsigned int flags; user_handle_t handle; int show_count; - int x; - int y; + float x; + float y; struct rectangle clip; }; struct set_cursor_reply @@ -7040,6 +7040,6 @@ union generic_reply struct d3dkmt_object_open_name_reply d3dkmt_object_open_name_reply; };
-#define SERVER_PROTOCOL_VERSION 921 +#define SERVER_PROTOCOL_VERSION 922
#endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index 87b8730f92a..9ace253d701 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -995,8 +995,8 @@ struct obj_locator
struct shared_cursor { - int x; /* cursor position */ - int y; + float x; /* cursor position */ + float y; unsigned int last_change; /* time of last position change */ struct rectangle clip; /* cursor clip rectangle */ }; @@ -2400,8 +2400,8 @@ enum message_type lparam_t wparam; /* parameters */ lparam_t lparam; /* parameters */ int type; /* message type */ - int x; /* message x position */ - int y; /* message y position */ + float x; /* message x position */ + float y; /* message y position */ unsigned int time; /* message time */ data_size_t total; /* total size of extra data */ VARARG(data,message_data); /* message data for sent messages */ @@ -3997,8 +3997,8 @@ struct handle_info unsigned int flags; /* flags for fields to set (see below) */ user_handle_t handle; /* handle to the cursor */ int show_count; /* show count increment/decrement */ - int x; /* cursor position */ - int y; + float x; /* cursor position */ + float y; struct rectangle clip; /* cursor clip rectangle */ @REPLY user_handle_t prev_handle; /* previous handle */ diff --git a/server/queue.c b/server/queue.c index 6b48a5dfdc8..71fd90e0680 100644 --- a/server/queue.c +++ b/server/queue.c @@ -85,8 +85,8 @@ struct message unsigned int msg; /* message code */ lparam_t wparam; /* parameters */ lparam_t lparam; /* parameters */ - int x; /* message position */ - int y; + float x; /* message position */ + float y; unsigned int time; /* message time */ void *data; /* message data for sent messages */ unsigned int data_size; /* size of message data */ @@ -540,7 +540,7 @@ static int update_desktop_cursor_window( struct desktop *desktop, user_handle_t return updated; }
-static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win, int x, int y ) +static int update_desktop_cursor_pos( struct desktop *desktop, user_handle_t win, float x, float y ) { desktop_shm_t *desktop_shm = desktop->shared; int updated; @@ -577,7 +577,7 @@ static void update_desktop_cursor_handle( struct desktop *desktop, struct thread }
/* set the cursor position and queue the corresponding mouse message */ -static void set_cursor_pos( struct desktop *desktop, int x, int y ) +static void set_cursor_pos( struct desktop *desktop, float x, float y ) { static const struct hw_msg_source source = { IMDT_UNAVAILABLE, IMO_SYSTEM }; const struct rawinput_device *device; @@ -607,7 +607,7 @@ void update_cursor_pos( struct desktop *desktop ) }
/* retrieve default position and time for synthesized messages */ -static void get_message_defaults( struct msg_queue *queue, int *x, int *y, unsigned int *time ) +static void get_message_defaults( struct msg_queue *queue, float *x, float *y, unsigned int *time ) { struct desktop *desktop = queue->input->desktop; desktop_shm_t *desktop_shm = desktop->shared; @@ -623,7 +623,7 @@ void set_clip_rectangle( struct desktop *desktop, const struct rectangle *rect, desktop_shm_t *desktop_shm = desktop->shared; struct rectangle top_rect, new_rect; unsigned int old_flags; - int x, y; + float x, y;
get_virtual_screen_rect( desktop, &top_rect, 1 ); if (rect) @@ -1913,7 +1913,7 @@ static void queue_hardware_message( struct desktop *desktop, struct message *msg msg->lparam &= ~(KF_EXTENDED << 16); break; case QS_MOUSEMOVE: - prepend_cursor_history( msg->x, msg->y, msg->time, msg_data->info ); + prepend_cursor_history( float_round_to_int( msg->x ), float_round_to_int( msg->y ), msg->time, msg_data->info ); /* fallthrough */ case QS_MOUSEBUTTON: if (update_desktop_cursor_pos( desktop, msg->win, msg->x, msg->y )) always_queue = 1; @@ -2217,7 +2217,8 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons unsigned int i, time = get_tick_count(), flags; struct hw_msg_source source = { IMDT_MOUSE, origin }; lparam_t wparam = input->mouse.data << 16; - int wait = 0, x, y; + int wait = 0; + float x, y;
static const unsigned int messages[] = { @@ -2275,7 +2276,9 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.time = time; raw_msg.message = WM_INPUT; raw_msg.flags = flags; - rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop_shm->cursor.x, y - desktop_shm->cursor.y, + rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, + float_round_to_int( x - desktop_shm->cursor.x ), + float_round_to_int( y - desktop_shm->cursor.y ), raw_msg.flags, input->mouse.data, input->mouse.info );
dispatch_rawinput_message( desktop, &raw_msg ); diff --git a/server/request_handlers.h b/server/request_handlers.h index 6bef45d4ff9..0206aded583 100644 --- a/server/request_handlers.h +++ b/server/request_handlers.h @@ -630,6 +630,7 @@ C_ASSERT( sizeof(client_ptr_t) == 8 ); C_ASSERT( sizeof(d3dkmt_handle_t) == 4 ); C_ASSERT( sizeof(data_size_t) == 4 ); C_ASSERT( sizeof(file_pos_t) == 8 ); +C_ASSERT( sizeof(float) == 4 ); C_ASSERT( sizeof(int) == 4 ); C_ASSERT( sizeof(ioctl_code_t) == 4 ); C_ASSERT( sizeof(lparam_t) == 8 ); diff --git a/server/request_trace.h b/server/request_trace.h index 8090f80eb76..1c969e60462 100644 --- a/server/request_trace.h +++ b/server/request_trace.h @@ -1468,8 +1468,8 @@ static void dump_get_message_reply( const struct get_message_reply *req ) dump_uint64( ", wparam=", &req->wparam ); dump_uint64( ", lparam=", &req->lparam ); fprintf( stderr, ", type=%d", req->type ); - fprintf( stderr, ", x=%d", req->x ); - fprintf( stderr, ", y=%d", req->y ); + fprintf( stderr, ", x=%05.2f", req->x ); + fprintf( stderr, ", y=%05.2f", req->y ); fprintf( stderr, ", time=%08x", req->time ); fprintf( stderr, ", total=%u", req->total ); dump_varargs_message_data( ", data=", cur_size ); @@ -3212,8 +3212,8 @@ static void dump_set_cursor_request( const struct set_cursor_request *req ) fprintf( stderr, " flags=%08x", req->flags ); fprintf( stderr, ", handle=%08x", req->handle ); fprintf( stderr, ", show_count=%d", req->show_count ); - fprintf( stderr, ", x=%d", req->x ); - fprintf( stderr, ", y=%d", req->y ); + fprintf( stderr, ", x=%05.2f", req->x ); + fprintf( stderr, ", y=%05.2f", req->y ); dump_rectangle( ", clip=", &req->clip ); }
diff --git a/server/user.h b/server/user.h index 73b10aaf5ac..46a38ae8150 100644 --- a/server/user.h +++ b/server/user.h @@ -168,6 +168,8 @@ extern int rect_in_region( struct region *region, const struct rectangle *rect )
/* window functions */
+extern void map_float_point_raw_to_virt( struct desktop *desktop, float *x, float *y ); +extern void map_float_point_virt_to_raw( struct desktop *desktop, float *x, float *y ); extern struct process *get_top_window_owner( struct desktop *desktop ); extern void get_virtual_screen_rect( struct desktop *desktop, struct rectangle *rect, int is_raw ); extern void post_desktop_message( struct desktop *desktop, unsigned int message, @@ -180,8 +182,8 @@ extern int is_window_visible( user_handle_t window ); extern int is_window_transparent( user_handle_t window ); extern int make_window_active( user_handle_t window ); extern struct thread *get_window_thread( user_handle_t handle ); -extern user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ); -extern struct thread *window_thread_from_point( user_handle_t scope, int x, int y ); +extern user_handle_t shallow_window_from_point( struct desktop *desktop, float x, float y ); +extern struct thread *window_thread_from_point( user_handle_t scope, float x, float y ); extern user_handle_t find_window_to_repaint( user_handle_t parent, struct thread *thread ); extern struct window_class *get_window_class( user_handle_t window );
@@ -230,6 +232,11 @@ static inline int point_in_rect( const struct rectangle *rect, int x, int y ) return (x >= rect->left && x < rect->right && y >= rect->top && y < rect->bottom); }
+static inline int float_round_to_int( float val ) +{ + return val + 0.5f; +} + static inline int scale_dpi( int val, unsigned int dpi_from, unsigned int dpi_to ) { if (val >= 0) return (val * dpi_to + (dpi_from / 2)) / dpi_from; diff --git a/server/window.c b/server/window.c index d9a2689ae5a..55ee1dfe3af 100644 --- a/server/window.c +++ b/server/window.c @@ -307,25 +307,49 @@ static struct monitor_info *get_monitor_from_rect( struct winstation *winstation return found ? found : nearest; }
-static void map_point_raw_to_virt( struct desktop *desktop, int *x, int *y ) +static void rect_map_float_point( const struct rectangle *rect_to, const struct rectangle *rect_from, + float *x, float *y ) { int width_from, height_from, width_to, height_to; - struct rectangle rect = {*x, *y, *x + 1, *y + 1}; + + width_to = rect_to->right - rect_to->left; + height_to = rect_to->bottom - rect_to->top; + width_from = rect_from->right - rect_from->left; + height_from = rect_from->bottom - rect_from->top; + + *x -= rect_from->left + width_from / 2.0f; + *x *= (float)width_to / width_from; + *x += rect_to->left + width_to / 2.0f; + + *y -= rect_from->top + height_from / 2.0f; + *y *= (float)height_to / height_from; + *y += rect_to->top + height_to / 2.0f; +} + +void map_float_point_raw_to_virt( struct desktop *desktop, float *x, float *y ) +{ struct monitor_info *monitor; + struct rectangle rect;
- if (!(monitor = get_monitor_from_rect( desktop->winstation, &rect, 1 ))) return; - width_to = monitor->virt.right - monitor->virt.left; - height_to = monitor->virt.bottom - monitor->virt.top; - width_from = monitor->raw.right - monitor->raw.left; - height_from = monitor->raw.bottom - monitor->raw.top; + rect.left = float_round_to_int( *x ); + rect.top = float_round_to_int( *y ); + rect.right = rect.left + 1; + rect.bottom = rect.top + 1; + if ((monitor = get_monitor_from_rect( desktop->winstation, &rect, 1 ))) + rect_map_float_point( &monitor->virt, &monitor->raw, x, y); +}
- *x = *x * 2 - (monitor->raw.left * 2 + width_from); - *x = (*x * width_to * 2 + width_from) / (width_from * 2); - *x = (*x + monitor->virt.left * 2 + width_to) / 2; +void map_float_point_virt_to_raw( struct desktop *desktop, float *x, float *y ) +{ + struct monitor_info *monitor; + struct rectangle rect;
- *y = *y * 2 - (monitor->raw.top * 2 + height_from); - *y = (*y * height_to * 2 + height_from) / (height_from * 2); - *y = (*y + monitor->virt.top * 2 + height_to) / 2; + rect.left = float_round_to_int( *x ); + rect.top = float_round_to_int( *y ); + rect.right = rect.left + 1; + rect.bottom = rect.top + 1; + if ((monitor = get_monitor_from_rect( desktop->winstation, &rect, 0 ))) + rect_map_float_point( &monitor->raw, &monitor->virt, x, y); }
/* get the per-monitor DPI for a window */ @@ -1028,17 +1052,17 @@ static int get_window_children_from_point( struct window *parent, int x, int y, }
/* get handle of root of top-most window containing point (in absolute raw coords) */ -user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) +user_handle_t shallow_window_from_point( struct desktop *desktop, float x, float y ) { struct window *ptr;
if (!desktop->top_window) return 0;
- map_point_raw_to_virt( desktop, &x, &y ); + map_float_point_raw_to_virt( desktop, &x, &y );
LIST_FOR_EACH_ENTRY( ptr, &desktop->top_window->children, struct window, entry ) { - int x_child = x, y_child = y; + int x_child = float_round_to_int( x ), y_child = float_round_to_int( y );
if (!is_point_in_window( ptr, &x_child, &y_child, 0 )) continue; /* skip it */ return ptr->handle; @@ -1047,14 +1071,17 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) }
/* return thread of top-most window containing point (in absolute raw coords) */ -struct thread *window_thread_from_point( user_handle_t scope, int x, int y ) +struct thread *window_thread_from_point( user_handle_t scope, float float_x, float float_y ) { struct window *win = get_user_object( scope, NTUSER_OBJ_WINDOW ); + int x, y;
if (!win) return NULL;
- map_point_raw_to_virt( win->desktop, &x, &y ); + map_float_point_raw_to_virt( win->desktop, &float_x, &float_y );
+ x = float_round_to_int( float_x ); + y = float_round_to_int( float_y ); screen_to_client( win, &x, &y, 0 ); win = child_window_from_point( win, x, y ); if (!win->thread) return NULL; diff --git a/tools/make_requests b/tools/make_requests index 17e425537b5..c9d4965d4fb 100755 --- a/tools/make_requests +++ b/tools/make_requests @@ -29,6 +29,7 @@ my %formats = "unsigned char" => [ 1, 1, "%02x" ], "unsigned short"=> [ 2, 2, "%04x" ], "unsigned int" => [ 4, 4, "%08x" ], + "float" => [ 4, 4, "%05.2f" ], "data_size_t" => [ 4, 4, "%u" ], "obj_handle_t" => [ 4, 4, "%04x" ], "atom_t" => [ 4, 4, "%04x" ],