server: Scale coordinates in get_window_children_from_point based on DPI awareness.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6d4e625cb2
commit
87d1a4a329
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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) );
|
||||
|
|
Loading…
Reference in New Issue