From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/sysparams.c | 2 +- server/queue.c | 6 +++--- server/user.h | 33 ++++++++++++++++++++++++++++++++- server/window.c | 24 +++++++++++++++++++----- 4 files changed, 55 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c index 60667a39cf8..f069f495620 100644 --- a/dlls/win32u/sysparams.c +++ b/dlls/win32u/sysparams.c @@ -2307,7 +2307,7 @@ static void release_display_dc( HDC hdc ) pthread_mutex_unlock( &display_dc_lock ); }
-/* display_lock must be held */ +/* display_lock must be held, keep in sync with server/window.c */ static struct monitor *get_monitor_from_rect( RECT rect, UINT flags, UINT dpi, MONITOR_DPI_TYPE type ) { struct monitor *monitor, *primary = NULL, *nearest = NULL, *found = NULL; diff --git a/server/queue.c b/server/queue.c index c99c8d8661b..127a4766458 100644 --- a/server/queue.c +++ b/server/queue.c @@ -472,7 +472,7 @@ static int is_cursor_clipped( struct desktop *desktop ) { const desktop_shm_t *desktop_shm = desktop->shared; rectangle_t top_rect, clip_rect = desktop_shm->cursor.clip; - get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 1 ); return !is_rect_equal( &clip_rect, &top_rect ); }
@@ -603,7 +603,7 @@ void set_clip_rectangle( struct desktop *desktop, const rectangle_t *rect, unsig unsigned int old_flags; int x, y;
- get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 1 ); if (rect) { new_rect = *rect; @@ -2522,7 +2522,7 @@ static void queue_pointer_message( struct pointer *pointer, int repeated ) struct message *msg; int x, y;
- get_top_window_rectangle( desktop, &top_rect ); + get_virtual_screen_rect( desktop, &top_rect, 0 ); x = LOWORD(input->hw.lparam) * (top_rect.right - top_rect.left) / 65535; y = HIWORD(input->hw.lparam) * (top_rect.bottom - top_rect.top) / 65535;
diff --git a/server/user.h b/server/user.h index 7a61fa70214..c8514f776b3 100644 --- a/server/user.h +++ b/server/user.h @@ -21,6 +21,7 @@ #ifndef __WINE_SERVER_USER_H #define __WINE_SERVER_USER_H
+#include <limits.h> #include "wine/server_protocol.h" #include "unicode.h"
@@ -173,7 +174,7 @@ extern int rect_in_region( struct region *region, const rectangle_t *rect ); /* window functions */
extern struct process *get_top_window_owner( struct desktop *desktop ); -extern void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ); +extern void get_virtual_screen_rect( struct desktop *desktop, rectangle_t *rect, int is_raw ); extern void post_desktop_message( struct desktop *desktop, unsigned int message, lparam_t wparam, lparam_t lparam ); extern void free_window_handle( struct window *win ); @@ -276,6 +277,36 @@ static inline int intersect_rect( rectangle_t *dst, const rectangle_t *src1, con return !is_rect_empty( dst ); }
+static inline void reset_bounds( rectangle_t *bounds ) +{ + bounds->left = bounds->top = INT_MAX; + bounds->right = bounds->bottom = INT_MIN; +} + +static inline void union_rect( rectangle_t *dest, const rectangle_t *src1, const rectangle_t *src2 ) +{ + if (is_rect_empty( src1 )) + { + if (is_rect_empty( src2 )) + { + reset_bounds( dest ); + return; + } + else *dest = *src2; + } + else + { + if (is_rect_empty( src2 )) *dest = *src1; + else + { + dest->left = min( src1->left, src2->left ); + dest->right = max( src1->right, src2->right ); + dest->top = min( src1->top, src2->top ); + dest->bottom = max( src1->bottom, src2->bottom ); + } + } +} + /* validate a window handle and return the full handle */ static inline user_handle_t get_valid_window_handle( user_handle_t win ) { diff --git a/server/window.c b/server/window.c index 412592fbc71..f40f81f428b 100644 --- a/server/window.c +++ b/server/window.c @@ -240,6 +240,21 @@ static inline void update_pixel_format_flags( struct window *win ) win->paint_flags |= PAINT_PIXEL_FORMAT_CHILD; }
+static rectangle_t monitors_get_union_rect( struct winstation *winstation, int is_raw ) +{ + struct monitor_info *monitor, *end; + rectangle_t rect = {0}; + + for (monitor = winstation->monitors, end = monitor + winstation->monitor_count; monitor < end; monitor++) + { + rectangle_t monitor_rect = is_raw ? monitor->raw : monitor->virt; + if (monitor->flags & (MONITOR_FLAG_CLONE | MONITOR_FLAG_INACTIVE)) continue; + union_rect( &rect, &rect, &monitor_rect ); + } + + return rect; +} + /* get the per-monitor DPI for a window */ static unsigned int get_monitor_dpi( struct window *win ) { @@ -499,10 +514,9 @@ struct process *get_top_window_owner( struct desktop *desktop ) }
/* get the top window size of a given desktop */ -void get_top_window_rectangle( struct desktop *desktop, rectangle_t *rect ) +void get_virtual_screen_rect( struct desktop *desktop, rectangle_t *rect, int is_raw ) { - struct window *win = desktop->top_window; - *rect = win ? win->window_rect : empty_rect; + *rect = monitors_get_union_rect( desktop->winstation, is_raw ); }
/* post a message to the desktop window */ @@ -893,7 +907,7 @@ static int get_window_children_from_point( struct window *parent, int x, int y, return 1; }
-/* get handle of root of top-most window containing point */ +/* 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 ) { struct window *ptr; @@ -910,7 +924,7 @@ user_handle_t shallow_window_from_point( struct desktop *desktop, int x, int y ) return desktop->top_window->handle; }
-/* return thread of top-most window containing point (in absolute coords) */ +/* 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 window *win = get_user_object( scope, USER_WINDOW );