diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 267b7a66b51..4b39d0aa393 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -260,6 +260,7 @@ static HWND *list_children_from_point( HWND hwnd, POINT pt ) req->parent = wine_server_user_handle( hwnd ); req->x = pt.x; req->y = pt.y; + req->dpi = get_thread_dpi(); wine_server_set_reply( req, list, (size-1) * sizeof(user_handle_t) ); if (!wine_server_call( req )) count = reply->count; } @@ -289,6 +290,7 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) { int i, res; HWND ret, *list; + POINT win_pt; if (!hwndScope) hwndScope = GetDesktopWindow(); @@ -319,7 +321,8 @@ HWND WINPOS_WindowFromPoint( HWND hwndScope, POINT pt, INT *hittest ) *hittest = HTCLIENT; break; } - res = SendMessageW( list[i], WM_NCHITTEST, 0, MAKELONG(pt.x,pt.y) ); + win_pt = point_thread_to_win_dpi( list[i], pt ); + res = SendMessageW( list[i], WM_NCHITTEST, 0, MAKELPARAM( win_pt.x, win_pt.y )); if (res != HTTRANSPARENT) { *hittest = res; /* Found the window */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index a888a63b79c..52c6d1f69ac 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -3634,6 +3634,8 @@ struct get_window_children_from_point_request user_handle_t parent; int x; int y; + int dpi; + char __pad_28[4]; }; struct get_window_children_from_point_reply { @@ -6533,6 +6535,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 558 +#define SERVER_PROTOCOL_VERSION 559 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/protocol.def b/server/protocol.def index f1f4709494d..936eb36af44 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2609,6 +2609,7 @@ enum message_type user_handle_t parent; /* parent window */ int x; /* point in parent coordinates */ int y; + int dpi; /* dpi for the point coordinates */ @REPLY int count; /* total count of children */ VARARG(children,user_handles); /* children handles */ diff --git a/server/request.h b/server/request.h index ddf8a6883f5..6005d1f8f54 100644 --- a/server/request.h +++ b/server/request.h @@ -1745,7 +1745,8 @@ C_ASSERT( sizeof(struct get_window_children_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_window_children_from_point_request, parent) == 12 ); C_ASSERT( FIELD_OFFSET(struct get_window_children_from_point_request, x) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_window_children_from_point_request, y) == 20 ); -C_ASSERT( sizeof(struct get_window_children_from_point_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct get_window_children_from_point_request, dpi) == 24 ); +C_ASSERT( sizeof(struct get_window_children_from_point_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct get_window_children_from_point_reply, count) == 8 ); C_ASSERT( sizeof(struct get_window_children_from_point_reply) == 16 ); C_ASSERT( FIELD_OFFSET(struct get_window_tree_request, handle) == 12 ); diff --git a/server/trace.c b/server/trace.c index 68866885f23..3c0d59257eb 100644 --- a/server/trace.c +++ b/server/trace.c @@ -3181,6 +3181,7 @@ static void dump_get_window_children_from_point_request( const struct get_window fprintf( stderr, " parent=%08x", req->parent ); fprintf( stderr, ", x=%d", req->x ); fprintf( stderr, ", y=%d", req->y ); + fprintf( stderr, ", dpi=%d", req->dpi ); } static void dump_get_window_children_from_point_reply( const struct get_window_children_from_point_reply *req ) diff --git a/server/window.c b/server/window.c index 8d056a21d40..36efb159ac2 100644 --- a/server/window.c +++ b/server/window.c @@ -658,6 +658,29 @@ static void map_dpi_region( struct window *win, struct region *region, unsigned scale_region( region, from, to ); } +/* convert coordinates from client to screen coords */ +static inline void client_to_screen( struct window *win, int *x, int *y ) +{ + for ( ; win && !is_desktop_window(win); win = win->parent) + { + *x += win->client_rect.left; + *y += win->client_rect.top; + } +} + +/* convert coordinates from screen to client coords and dpi */ +static void screen_to_client( struct window *win, int *x, int *y, unsigned int dpi ) +{ + int offset_x = 0, offset_y = 0; + + if (is_desktop_window( win )) return; + + client_to_screen( win, &offset_x, &offset_y ); + map_dpi_point( win, x, y, dpi, win->dpi ); + *x -= offset_x; + *y -= offset_y; +} + /* check if window and all its ancestors are visible */ static int is_visible( const struct window *win ) { @@ -686,18 +709,19 @@ int is_window_transparent( user_handle_t window ) return (win->ex_style & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT); } -/* check if point is inside the window */ -static inline int is_point_in_window( struct window *win, int x, int y ) +/* check if point is inside the window, and map to window dpi */ +static int is_point_in_window( struct window *win, int *x, int *y, unsigned int dpi ) { if (!(win->style & WS_VISIBLE)) return 0; /* not visible */ if ((win->style & (WS_POPUP|WS_CHILD|WS_DISABLED)) == (WS_CHILD|WS_DISABLED)) return 0; /* disabled child */ if ((win->ex_style & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == (WS_EX_LAYERED|WS_EX_TRANSPARENT)) return 0; /* transparent */ - if (!point_in_rect( &win->visible_rect, x, y )) + map_dpi_point( win, x, y, dpi, win->dpi ); + if (!point_in_rect( &win->visible_rect, *x, *y )) return 0; /* not in window */ if (win->win_region && - !point_in_region( win->win_region, x - win->window_rect.left, y - win->window_rect.top )) + !point_in_region( win->win_region, *x - win->window_rect.left, *y - win->window_rect.top )) return 0; /* not in window region */ return 1; } @@ -732,15 +756,18 @@ static struct window *child_window_from_point( struct window *parent, int x, int LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) { - if (!is_point_in_window( ptr, x, y )) continue; /* skip it */ + int x_child = x, y_child = y; + + if (!is_point_in_window( ptr, &x_child, &y_child, parent->dpi )) continue; /* skip it */ /* if window is minimized or disabled, return at once */ if (ptr->style & (WS_MINIMIZE|WS_DISABLED)) return ptr; /* if point is not in client area, return at once */ - if (!point_in_rect( &ptr->client_rect, x, y )) return ptr; + if (!point_in_rect( &ptr->client_rect, x_child, y_child )) return ptr; - return child_window_from_point( ptr, x - ptr->client_rect.left, y - ptr->client_rect.top ); + return child_window_from_point( ptr, x_child - ptr->client_rect.left, + y_child - ptr->client_rect.top ); } return parent; /* not found any child */ } @@ -753,13 +780,15 @@ static int get_window_children_from_point( struct window *parent, int x, int y, LIST_FOR_EACH_ENTRY( ptr, &parent->children, struct window, entry ) { - if (!is_point_in_window( ptr, x, y )) continue; /* skip it */ + int x_child = x, y_child = y; + + if (!is_point_in_window( ptr, &x_child, &y_child, parent->dpi )) continue; /* skip it */ /* if point is in client area, and window is not minimized or disabled, check children */ - if (!(ptr->style & (WS_MINIMIZE|WS_DISABLED)) && point_in_rect( &ptr->client_rect, x, y )) + if (!(ptr->style & (WS_MINIMIZE|WS_DISABLED)) && point_in_rect( &ptr->client_rect, x_child, y_child )) { - if (!get_window_children_from_point( ptr, x - ptr->client_rect.left, - y - ptr->client_rect.top, array )) + if (!get_window_children_from_point( ptr, x_child - ptr->client_rect.left, + y_child - ptr->client_rect.top, array )) return 0; } @@ -778,7 +807,9 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) LIST_FOR_EACH_ENTRY( ptr, &desktop->top_window->children, struct window, entry ) { - if (!is_point_in_window( ptr, x, y )) continue; /* skip it */ + int x_child = x, y_child = y; + + if (!is_point_in_window( ptr, &x_child, &y_child, 0 )) continue; /* skip it */ return ptr->handle; } return desktop->top_window->handle; @@ -788,35 +819,26 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) struct thread *window_thread_from_point( user_handle_t scope, int x, int y ) { struct window *win = get_user_object( scope, USER_WINDOW ); - struct window *ptr; if (!win) return NULL; - for (ptr = win; ptr && !is_desktop_window(ptr); ptr = ptr->parent) - { - x -= ptr->client_rect.left; - y -= ptr->client_rect.top; - } - - ptr = child_window_from_point( win, x, y ); - if (!ptr->thread) return NULL; - return (struct thread *)grab_object( ptr->thread ); + screen_to_client( win, &x, &y, 0 ); + win = child_window_from_point( win, x, y ); + if (!win->thread) return NULL; + return (struct thread *)grab_object( win->thread ); } /* return list of all windows containing point (in absolute coords) */ -static int all_windows_from_point( struct window *top, int x, int y, struct user_handle_array *array ) +static int all_windows_from_point( struct window *top, int x, int y, unsigned int dpi, + struct user_handle_array *array ) { - struct window *ptr; - - /* make point relative to top window */ - for (ptr = top->parent; ptr && !is_desktop_window(ptr); ptr = ptr->parent) + if (!is_desktop_window( top ) && !is_desktop_window( top->parent )) { - x -= ptr->client_rect.left; - y -= ptr->client_rect.top; + screen_to_client( top->parent, &x, &y, dpi ); + dpi = top->parent->dpi; } - if (!is_point_in_window( top, x, y )) return 1; - + if (!is_point_in_window( top, &x, &y, dpi )) return 1; /* if point is in client area, and window is not minimized or disabled, check children */ if (!(top->style & (WS_MINIMIZE|WS_DISABLED)) && point_in_rect( &top->client_rect, x, y )) { @@ -915,16 +937,6 @@ static struct region *intersect_window_region( struct region *region, struct win } -/* convert coordinates from client to screen coords */ -static inline void client_to_screen( struct window *win, int *x, int *y ) -{ - for ( ; win && !is_desktop_window(win); win = win->parent) - { - *x += win->client_rect.left; - *y += win->client_rect.top; - } -} - /* convert coordinates from client to screen coords */ static inline void client_to_screen_rect( struct window *win, rectangle_t *rect ) { @@ -2219,7 +2231,7 @@ DECL_HANDLER(get_window_children_from_point) array.handles = NULL; array.count = 0; array.total = 0; - if (!all_windows_from_point( parent, req->x, req->y, &array )) return; + if (!all_windows_from_point( parent, req->x, req->y, req->dpi, &array )) return; reply->count = array.count; len = min( get_reply_max_size(), array.count * sizeof(user_handle_t) );