From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 21 ++++++++++++++------- dlls/win32u/win32u_private.h | 2 +- dlls/win32u/window.c | 2 +- dlls/wineandroid.drv/window.c | 12 +++++------- dlls/winemac.drv/macdrv.h | 2 +- dlls/winemac.drv/surface.c | 4 ++-- dlls/winemac.drv/window.c | 4 ++-- dlls/winewayland.drv/window_surface.c | 7 ++----- dlls/winex11.drv/bitblt.c | 4 ++-- dlls/winex11.drv/window.c | 4 ++-- dlls/winex11.drv/x11drv.h | 2 +- include/wine/gdi_driver.h | 3 ++- 12 files changed, 35 insertions(+), 32 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index d8a26b655ef..428b25d3b6e 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -98,7 +98,13 @@ static const struct window_surface_funcs dummy_surface_funcs = dummy_surface_destroy };
-struct window_surface dummy_surface = { &dummy_surface_funcs, { NULL, NULL }, 1, { 0, 0, 1, 1 }, PTHREAD_MUTEX_INITIALIZER }; +struct window_surface dummy_surface = +{ + .funcs = &dummy_surface_funcs, + .ref = 1, + .rect = {.right = 1, .bottom = 1}, + .mutex = PTHREAD_MUTEX_INITIALIZER, +};
/******************************************************************* * Off-screen window surface. @@ -149,13 +155,13 @@ static const struct window_surface_funcs offscreen_window_surface_funcs = offscreen_window_surface_destroy };
-void create_offscreen_window_surface( const RECT *visible_rect, struct window_surface **surface ) +void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struct window_surface **surface ) { struct offscreen_window_surface *impl; SIZE_T size; RECT surface_rect = *visible_rect;
- TRACE( "visible_rect %s, surface %p.\n", wine_dbgstr_rect( visible_rect ), surface ); + TRACE( "hwnd %p, visible_rect %s, surface %p.\n", hwnd, wine_dbgstr_rect( visible_rect ), surface );
OffsetRect( &surface_rect, -surface_rect.left, -surface_rect.top ); surface_rect.right = (surface_rect.right + 0x1f) & ~0x1f; @@ -174,7 +180,7 @@ void create_offscreen_window_surface( const RECT *visible_rect, struct window_su *surface = NULL; size = surface_rect.right * surface_rect.bottom * 4; if (!(impl = calloc(1, offsetof( struct offscreen_window_surface, info.bmiColors[0] ) + size))) return; - window_surface_init( &impl->header, &offscreen_window_surface_funcs, &surface_rect ); + window_surface_init( &impl->header, &offscreen_window_surface_funcs, hwnd, &surface_rect );
impl->bits = (char *)&impl->info.bmiColors[0]; impl->info.bmiHeader.biSize = sizeof( impl->info ); @@ -192,10 +198,11 @@ void create_offscreen_window_surface( const RECT *visible_rect, struct window_su
/* window surface common helpers */
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, const RECT *rect ) +W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ) { surface->funcs = funcs; surface->ref = 1; + surface->hwnd = hwnd; surface->rect = *rect; pthread_mutex_init( &surface->mutex, NULL ); reset_bounds( &surface->bounds ); @@ -236,8 +243,8 @@ W32KAPI void window_surface_flush( struct window_surface *surface )
if (intersect_rect( &dirty, &dirty, &surface->bounds )) { - TRACE( "Flushing surface %p %s, bounds %s, dirty %s\n", surface, wine_dbgstr_rect( &surface->rect ), - wine_dbgstr_rect( &surface->bounds ), wine_dbgstr_rect( &dirty ) ); + TRACE( "Flushing hwnd %p, surface %p %s, bounds %s, dirty %s\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ), wine_dbgstr_rect( &surface->bounds ), wine_dbgstr_rect( &dirty ) ); if (surface->funcs->flush( surface, &surface->rect, &dirty )) reset_bounds( &surface->bounds ); }
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index aecd60bae63..8aed662d2d8 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -45,7 +45,7 @@ extern ULONG_PTR set_icon_param( HICON handle, ULONG_PTR param );
/* dce.c */ extern struct window_surface dummy_surface; -extern void create_offscreen_window_surface( const RECT *visible_rect, +extern void create_offscreen_window_surface( HWND hwnd, const RECT *visible_rect, struct window_surface **surface ); extern void erase_now( HWND hwnd, UINT rdw_flags ); extern void flush_window_surfaces( BOOL idle ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b0fe0218da5..bafceb1a22a 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1814,7 +1814,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, { window_surface_release( new_surface ); if ((new_surface = win->surface)) window_surface_add_ref( new_surface ); - create_offscreen_window_surface( &visible_rect, &new_surface ); + create_offscreen_window_surface( hwnd, &visible_rect, &new_surface ); }
old_visible_rect = win->visible_rect; diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index ddb46c0d4cd..61ebc097f47 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -571,7 +571,6 @@ static int wait_events( int timeout ) struct android_window_surface { struct window_surface header; - HWND hwnd; ANativeWindow *window; BOOL byteswap; RGNDATA *region_data; @@ -656,7 +655,7 @@ static void android_surface_set_region( struct window_surface *window_surface, H { struct android_window_surface *surface = get_android_surface( window_surface );
- TRACE( "updating surface %p hwnd %p with %p\n", surface, surface->hwnd, region ); + TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region );
window_surface_lock( window_surface ); if (!region) @@ -738,7 +737,7 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const surface->window->perform( surface->window, NATIVE_WINDOW_UNLOCK_AND_POST ); } else TRACE( "Unable to lock surface %p window %p buffer %p\n", - surface, surface->hwnd, surface->window ); + surface, window_surface->hwnd, surface->window );
return TRUE; } @@ -806,7 +805,7 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_
if (window_surface->funcs != &android_surface_funcs) return; /* we may get the null surface */
- if (!(win_data = get_win_data( surface->hwnd ))) return; + if (!(win_data = get_win_data( window_surface->hwnd ))) return; offset_x = win_data->window_rect.left - win_data->whole_rect.left; offset_y = win_data->window_rect.top - win_data->whole_rect.top; release_win_data( win_data ); @@ -815,7 +814,7 @@ static void set_surface_region( struct window_surface *window_surface, HRGN win_ { region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left, win_data->window_rect.bottom - win_data->window_rect.top ); - if (NtUserGetWindowRgnEx( surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; + if (NtUserGetWindowRgnEx( window_surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; }
NtGdiOffsetRgn( region, offset_x, offset_y ); @@ -850,7 +849,7 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect,
surface = calloc( 1, FIELD_OFFSET( struct android_window_surface, info.bmiColors[3] )); if (!surface) return NULL; - window_surface_init( &surface->header, &android_surface_funcs, rect ); + window_surface_init( &surface->header, &android_surface_funcs, hwnd, rect );
set_color_info( &surface->info, src_alpha ); surface->info.bmiHeader.biWidth = width; @@ -858,7 +857,6 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->info.bmiHeader.biPlanes = 1; surface->info.bmiHeader.biSizeImage = get_dib_image_size( &surface->info );
- surface->hwnd = hwnd; surface->window = get_ioctl_window( hwnd ); surface->alpha = alpha; set_color_key( surface, color_key ); diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index d1101a4a228..a7905050f16 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -208,7 +208,7 @@ extern BOOL macdrv_SystemParametersInfo(UINT action, UINT int_param, void *ptr_p extern macdrv_window macdrv_get_cocoa_window(HWND hwnd, BOOL require_on_screen); extern RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp); extern void activate_on_following_focus(void); -extern struct window_surface *create_surface(macdrv_window window, const RECT *rect, +extern struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha); extern void set_surface_use_alpha(struct window_surface *window_surface, BOOL use_alpha); extern void surface_clip_to_visible_rect(struct window_surface *window_surface, const RECT *visible_rect); diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 7e296f33a62..a6f61538d16 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -149,7 +149,7 @@ static struct macdrv_window_surface *get_mac_surface(struct window_surface *surf /*********************************************************************** * create_surface */ -struct window_surface *create_surface(macdrv_window window, const RECT *rect, +struct window_surface *create_surface(HWND hwnd, macdrv_window window, const RECT *rect, struct window_surface *old_surface, BOOL use_alpha) { struct macdrv_window_surface *surface; @@ -159,7 +159,7 @@ struct window_surface *create_surface(macdrv_window window, const RECT *rect,
surface = calloc(1, FIELD_OFFSET(struct macdrv_window_surface, info.bmiColors[3])); if (!surface) return NULL; - window_surface_init(&surface->header, &macdrv_surface_funcs, rect); + window_surface_init(&surface->header, &macdrv_surface_funcs, hwnd, rect);
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 04eb6d00860..84668b44c51 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1915,7 +1915,7 @@ BOOL macdrv_UpdateLayeredWindow(HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, surface = data->surface; if (!surface || !EqualRect(&surface->rect, &rect)) { - data->surface = create_surface(data->cocoa_window, &rect, NULL, TRUE); + data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE); macdrv_set_window_surface(data->cocoa_window, data->surface); if (surface) window_surface_release(surface); surface = data->surface; @@ -2094,7 +2094,7 @@ BOOL macdrv_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags, } else if (!(swp_flags & SWP_SHOWWINDOW) && !(style & WS_VISIBLE)) goto done;
- *surface = create_surface(data->cocoa_window, &surface_rect, data->surface, FALSE); + *surface = create_surface(data->hwnd, data->cocoa_window, &surface_rect, data->surface, FALSE);
done: release_win_data(data); diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 2605b3c7b3d..2c19c8ffdc4 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -43,7 +43,6 @@ struct wayland_buffer_queue struct wayland_window_surface { struct window_surface header; - HWND hwnd; struct wayland_surface *wayland_surface; struct wayland_buffer_queue *wayland_buffer_queue; void *bits; @@ -463,7 +462,7 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect
wws = calloc(1, sizeof(*wws)); if (!wws) return NULL; - window_surface_init(&wws->header, &wayland_window_surface_funcs, rect); + window_surface_init(&wws->header, &wayland_window_surface_funcs, hwnd, rect);
wws->info.bmiHeader.biSize = sizeof(wws->info.bmiHeader); wws->info.bmiHeader.biClrUsed = 0; @@ -474,8 +473,6 @@ struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect wws->info.bmiHeader.biPlanes = 1; wws->info.bmiHeader.biSizeImage = width * height * 4;
- wws->hwnd = hwnd; - if (!(wws->bits = malloc(wws->info.bmiHeader.biSizeImage))) goto failed;
@@ -499,7 +496,7 @@ void wayland_window_surface_update_wayland_surface(struct window_surface *window
window_surface_lock(window_surface);
- TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, wws->hwnd, wayland_surface); + TRACE("surface=%p hwnd=%p wayland_surface=%p\n", wws, window_surface->hwnd, wayland_surface);
wws->wayland_surface = wayland_surface;
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index f0d523b6f9c..404beab923d 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1954,7 +1954,7 @@ static const struct window_surface_funcs x11drv_surface_funcs = /*********************************************************************** * create_surface */ -struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect, +struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect, COLORREF color_key, BOOL use_alpha ) { const XPixmapFormatValues *format = pixmap_formats[vis->depth]; @@ -1964,7 +1964,7 @@ struct window_surface *create_surface( Window window, const XVisualInfo *vis, co
surface = calloc( 1, FIELD_OFFSET( struct x11drv_window_surface, info.bmiColors[colors] )); if (!surface) return NULL; - window_surface_init( &surface->header, &x11drv_surface_funcs, rect ); + window_surface_init( &surface->header, &x11drv_surface_funcs, hwnd, rect );
surface->info.bmiHeader.biSize = sizeof(surface->info.bmiHeader); surface->info.bmiHeader.biWidth = width; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 823a17e3998..f975986a9d9 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2645,7 +2645,7 @@ BOOL X11DRV_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, if (!layered || !NtUserGetLayeredWindowAttributes( hwnd, &key, NULL, &flags ) || !(flags & LWA_COLORKEY)) key = CLR_INVALID;
- *surface = create_surface( data->whole_window, &data->vis, &surface_rect, key, FALSE ); + *surface = create_surface( data->hwnd, data->whole_window, &data->vis, &surface_rect, key, FALSE );
done: release_win_data( data ); @@ -2991,7 +2991,7 @@ BOOL X11DRV_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, surface = data->surface; if (!surface || !EqualRect( &surface->rect, &rect )) { - data->surface = create_surface( data->whole_window, &data->vis, &rect, + data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, &rect, color_key, data->use_alpha ); if (surface) window_surface_release( surface ); surface = data->surface; diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d10ade448e2..2a326b07a4c 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -265,7 +265,7 @@ extern Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const B const struct gdi_image_bits *bits, UINT coloruse ); extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis, BITMAPINFO *info, struct gdi_image_bits *bits ); -extern struct window_surface *create_surface( Window window, const XVisualInfo *vis, const RECT *rect, +extern struct window_surface *create_surface( HWND hwnd, Window window, const XVisualInfo *vis, const RECT *rect, COLORREF color_key, BOOL use_alpha ); extern void set_surface_color_key( struct window_surface *window_surface, COLORREF color_key ); extern HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ); diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 2721083c6ad..f6cfc7778de 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -222,6 +222,7 @@ struct window_surface const struct window_surface_funcs *funcs; /* driver-specific implementations */ struct list entry; /* entry in global list managed by user32 */ LONG ref; /* reference count */ + HWND hwnd; /* window the surface was created for */ RECT rect; /* constant, no locking needed */
pthread_mutex_t mutex; @@ -230,7 +231,7 @@ struct window_surface /* driver-specific fields here */ };
-W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, const RECT *rect ); +W32KAPI void window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect ); W32KAPI void window_surface_add_ref( struct window_surface *surface ); W32KAPI void window_surface_release( struct window_surface *surface ); W32KAPI void window_surface_lock( struct window_surface *surface );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index bafceb1a22a..ee0d3001762 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1717,23 +1717,16 @@ static BOOL get_window_info( HWND hwnd, WINDOWINFO *info ) return TRUE; }
-/*********************************************************************** - * update_surface_region - */ -static void update_surface_region( HWND hwnd ) +static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) { NTSTATUS status; - HRGN region = 0; RGNDATA *data; size_t size = 256; - WND *win = get_win_ptr( hwnd ); - - if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; - if (!win->surface) goto done;
+ *region = 0; do { - if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) goto done; + if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) return STATUS_NO_MEMORY;
SERVER_START_REQ( get_surface_region ) { @@ -1748,20 +1741,38 @@ static void update_surface_region( HWND hwnd ) data->rdh.iType = RDH_RECTANGLES; data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nRgnSize = reply_size; - region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiOffsetRgn( region, -reply->visible_rect.left, -reply->visible_rect.top ); + *region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); + NtGdiOffsetRgn( *region, -reply->visible_rect.left, -reply->visible_rect.top ); } } else size = reply->total_size; } SERVER_END_REQ; + free( data ); } while (status == STATUS_BUFFER_OVERFLOW);
- if (status) goto done; + return status; +}
- win->surface->funcs->set_region( win->surface, region ); - if (region) NtGdiDeleteObjectApp( region ); +/*********************************************************************** + * update_surface_region + */ +static void update_surface_region( HWND hwnd ) +{ + WND *win = get_win_ptr( hwnd ); + HRGN region; + + if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; + if (!win->surface) goto done; + + if (get_window_region( hwnd, ®ion )) goto done; + if (!region) win->surface->funcs->set_region( win->surface, 0 ); + else + { + win->surface->funcs->set_region( win->surface, region ); + NtGdiDeleteObjectApp( region ); + }
done: release_win_ptr( win );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 52 +++++++++++++++----------------------------- server/protocol.def | 12 ++-------- server/window.c | 30 ++++++++++++------------- 3 files changed, 33 insertions(+), 61 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index ee0d3001762..4d310edcbb2 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1717,7 +1717,7 @@ static BOOL get_window_info( HWND hwnd, WINDOWINFO *info ) return TRUE; }
-static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) +static NTSTATUS get_window_region( HWND hwnd, BOOL surface, HRGN *region, RECT *visible ) { NTSTATUS status; RGNDATA *data; @@ -1728,9 +1728,10 @@ static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) { if (!(data = malloc( FIELD_OFFSET( RGNDATA, Buffer[size] )))) return STATUS_NO_MEMORY;
- SERVER_START_REQ( get_surface_region ) + SERVER_START_REQ( get_window_region ) { req->window = wine_server_user_handle( hwnd ); + req->surface = surface; wine_server_set_reply( req, data->Buffer, size ); if (!(status = wine_server_call( req ))) { @@ -1742,7 +1743,10 @@ static NTSTATUS get_window_region( HWND hwnd, HRGN *region ) data->rdh.nCount = reply_size / sizeof(RECT); data->rdh.nRgnSize = reply_size; *region = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiOffsetRgn( *region, -reply->visible_rect.left, -reply->visible_rect.top ); + visible->left = reply->visible_rect.left; + visible->top = reply->visible_rect.top; + visible->right = reply->visible_rect.right; + visible->bottom = reply->visible_rect.bottom; } } else size = reply->total_size; @@ -1762,14 +1766,16 @@ static void update_surface_region( HWND hwnd ) { WND *win = get_win_ptr( hwnd ); HRGN region; + RECT visible;
if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; if (!win->surface) goto done;
- if (get_window_region( hwnd, ®ion )) goto done; + if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; if (!region) win->surface->funcs->set_region( win->surface, 0 ); else { + NtGdiOffsetRgn( region, -visible.left, -visible.top ); win->surface->funcs->set_region( win->surface, region ); NtGdiDeleteObjectApp( region ); } @@ -1959,41 +1965,17 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, int WINAPI NtUserGetWindowRgnEx( HWND hwnd, HRGN hrgn, UINT unk ) { NTSTATUS status; - HRGN win_rgn = 0; - RGNDATA *data; - size_t size = 256; int ret = ERROR; + HRGN win_rgn; + RECT visible;
- do + if ((status = get_window_region( hwnd, FALSE, &win_rgn, &visible ))) { - if (!(data = malloc( sizeof(*data) + size - 1 ))) - { - RtlSetLastWin32Error( ERROR_OUTOFMEMORY ); - return ERROR; - } - SERVER_START_REQ( get_window_region ) - { - req->window = wine_server_user_handle( hwnd ); - wine_server_set_reply( req, data->Buffer, size ); - if (!(status = wine_server_call( req ))) - { - size_t reply_size = wine_server_reply_size( reply ); - if (reply_size) - { - data->rdh.dwSize = sizeof(data->rdh); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = reply_size / sizeof(RECT); - data->rdh.nRgnSize = reply_size; - win_rgn = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - } - } - else size = reply->total_size; - } - SERVER_END_REQ; - free( data ); - } while (status == STATUS_BUFFER_OVERFLOW); + set_ntstatus( status ); + return ERROR; + }
- if (set_ntstatus( status ) && win_rgn) + if (win_rgn) { ret = NtGdiCombineRgn( hrgn, win_rgn, 0, RGN_COPY ); NtGdiDeleteObjectApp( win_rgn ); diff --git a/server/protocol.def b/server/protocol.def index 1491994197c..ac103156fe4 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2592,20 +2592,12 @@ enum coords_relative @END
-/* Get the visible surface region of a window */ -@REQ(get_surface_region) - user_handle_t window; /* handle to the window */ -@REPLY - rectangle_t visible_rect; /* window visible rect in screen coords */ - data_size_t total_size; /* total size of the resulting region */ - VARARG(region,rectangles); /* list of rectangles for the region (in screen coords) */ -@END - - /* Get the window region */ @REQ(get_window_region) user_handle_t window; /* handle to the window */ + int surface; /* get the visible surface region */ @REPLY + rectangle_t visible_rect; /* window visible rect in screen coords */ data_size_t total_size; /* total size of the resulting region */ VARARG(region,rectangles); /* list of rectangles for the region (in window coords) */ @END diff --git a/server/window.c b/server/window.c index b98429c8f31..50d6ae5dbcc 100644 --- a/server/window.c +++ b/server/window.c @@ -2631,30 +2631,28 @@ DECL_HANDLER(get_visible_region) }
-/* get the surface visible region of a window */ -DECL_HANDLER(get_surface_region) +/* get the window regions */ +DECL_HANDLER(get_window_region) { + rectangle_t *data; struct region *region; struct window *win = get_window( req->window );
- if (!win || !is_visible( win )) return; + if (!win) return;
- if ((region = get_surface_region( win ))) - { - rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); - if (data) set_reply_data_ptr( data, reply->total_size ); - } reply->visible_rect = win->visible_rect; -} - + if (req->surface) + { + if (!is_visible( win )) return;
-/* get the window region */ -DECL_HANDLER(get_window_region) -{ - rectangle_t *data; - struct window *win = get_window( req->window ); + if ((region = get_surface_region( win ))) + { + rectangle_t *data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size ); + if (data) set_reply_data_ptr( data, reply->total_size ); + } + return; + }
- if (!win) return; if (!win->win_region) return;
if (win->ex_style & WS_EX_LAYOUTRTL)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 4d310edcbb2..7c34c929406 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1765,21 +1765,33 @@ static NTSTATUS get_window_region( HWND hwnd, BOOL surface, HRGN *region, RECT * static void update_surface_region( HWND hwnd ) { WND *win = get_win_ptr( hwnd ); - HRGN region; + HRGN region, shape; RECT visible;
if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; if (!win->surface) goto done;
+ if (get_window_region( hwnd, FALSE, &shape, &visible )) goto done; + if (shape) + { + region = NtGdiCreateRectRgn( 0, 0, visible.right - visible.left, visible.bottom - visible.top ); + NtGdiCombineRgn( shape, shape, region, RGN_AND ); + if (win->dwExStyle & WS_EX_LAYOUTRTL) NtUserMirrorRgn( hwnd, shape ); + NtGdiDeleteObjectApp( region ); + } + if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; - if (!region) win->surface->funcs->set_region( win->surface, 0 ); + if (!region) win->surface->funcs->set_region( win->surface, shape ); else { NtGdiOffsetRgn( region, -visible.left, -visible.top ); + if (shape) NtGdiCombineRgn( region, region, shape, RGN_AND ); win->surface->funcs->set_region( win->surface, region ); NtGdiDeleteObjectApp( region ); }
+ if (shape) NtGdiDeleteObjectApp( shape ); + done: release_win_ptr( win ); }
From: Rémi Bernon rbernon@codeweavers.com
--- server/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/server/window.c b/server/window.c index 50d6ae5dbcc..4ebfec3da12 100644 --- a/server/window.c +++ b/server/window.c @@ -2485,7 +2485,8 @@ DECL_HANDLER(set_window_pos) if (is_visible( top ) && (top->paint_flags & PAINT_HAS_SURFACE)) { reply->surface_win = top->handle; - reply->needs_update = !!(top->paint_flags & (PAINT_HAS_PIXEL_FORMAT | PAINT_PIXEL_FORMAT_CHILD)); + reply->needs_update = !!(top->paint_flags & (PAINT_HAS_PIXEL_FORMAT | PAINT_PIXEL_FORMAT_CHILD)) || + !!top->win_region; } }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/wineandroid.drv/android.h | 1 - dlls/wineandroid.drv/init.c | 1 - dlls/wineandroid.drv/window.c | 81 ++++++---------------------------- 3 files changed, 14 insertions(+), 69 deletions(-)
diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index e793d103788..2512976089b 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -95,7 +95,6 @@ extern LRESULT ANDROID_DesktopWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM extern void ANDROID_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DWORD flags ); extern void ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent ); -extern void ANDROID_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ); extern void ANDROID_SetCapture( HWND hwnd, UINT flags ); extern void ANDROID_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ); extern UINT ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ); diff --git a/dlls/wineandroid.drv/init.c b/dlls/wineandroid.drv/init.c index d48c4153b06..5b4ec59d2fa 100644 --- a/dlls/wineandroid.drv/init.c +++ b/dlls/wineandroid.drv/init.c @@ -346,7 +346,6 @@ static const struct user_driver_funcs android_drv_funcs = .pSetCapture = ANDROID_SetCapture, .pSetLayeredWindowAttributes = ANDROID_SetLayeredWindowAttributes, .pSetParent = ANDROID_SetParent, - .pSetWindowRgn = ANDROID_SetWindowRgn, .pSetWindowStyle = ANDROID_SetWindowStyle, .pShowWindow = ANDROID_ShowWindow, .pUpdateLayeredWindow = ANDROID_UpdateLayeredWindow, diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 61ebc097f47..d04649da69f 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -70,8 +70,6 @@ static inline int context_idx( HWND hwnd ) return LOWORD( hwnd ) >> 1; }
-static void set_surface_region( struct window_surface *window_surface, HRGN win_region ); - /* only for use on sanitized BITMAPINFO structures */ static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse ) { @@ -654,6 +652,8 @@ static void *android_surface_get_bitmap_info( struct window_surface *window_surf static void android_surface_set_region( struct window_surface *window_surface, HRGN region ) { struct android_window_surface *surface = get_android_surface( window_surface ); + RGNDATA *data; + UINT size;
TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region );
@@ -668,8 +668,19 @@ static void android_surface_set_region( struct window_surface *window_surface, H if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); } + + if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; + if (!(data = malloc( size ))) goto done; + if (!NtGdiGetRegionData( region, size, data )) + { + free( data ); + data = NULL; + } + free( surface->region_data ); + surface->region_data = data; + +done: window_surface_unlock( window_surface ); - set_surface_region( &surface->header, (HRGN)1 ); }
/*********************************************************************** @@ -791,53 +802,6 @@ static void set_color_key( struct android_window_surface *surface, COLORREF key surface->color_key = (GetRValue(key) << 16) | (GetGValue(key) << 8) | GetBValue(key); }
-/*********************************************************************** - * set_surface_region - */ -static void set_surface_region( struct window_surface *window_surface, HRGN win_region ) -{ - struct android_window_surface *surface = get_android_surface( window_surface ); - struct android_win_data *win_data; - HRGN region = win_region; - RGNDATA *data = NULL; - DWORD size; - int offset_x, offset_y; - - if (window_surface->funcs != &android_surface_funcs) return; /* we may get the null surface */ - - if (!(win_data = get_win_data( window_surface->hwnd ))) return; - offset_x = win_data->window_rect.left - win_data->whole_rect.left; - offset_y = win_data->window_rect.top - win_data->whole_rect.top; - release_win_data( win_data ); - - if (win_region == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */ - { - region = NtGdiCreateRectRgn( 0, 0, win_data->window_rect.right - win_data->window_rect.left, - win_data->window_rect.bottom - win_data->window_rect.top ); - if (NtUserGetWindowRgnEx( window_surface->hwnd, region, 0 ) == ERROR && !surface->region) goto done; - } - - NtGdiOffsetRgn( region, offset_x, offset_y ); - if (surface->region) NtGdiCombineRgn( region, region, surface->region, RGN_AND ); - - if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; - if (!(data = malloc( size ))) goto done; - - if (!NtGdiGetRegionData( region, size, data )) - { - free( data ); - data = NULL; - } - -done: - window_surface_lock( window_surface ); - free( surface->region_data ); - surface->region_data = data; - window_surface->bounds = surface->header.rect; - window_surface_unlock( window_surface ); - if (region != win_region) NtGdiDeleteObjectApp( region ); -} - /*********************************************************************** * create_surface */ @@ -860,7 +824,6 @@ static struct window_surface *create_surface( HWND hwnd, const RECT *rect, surface->window = get_ioctl_window( hwnd ); surface->alpha = alpha; set_color_key( surface, color_key ); - set_surface_region( &surface->header, (HRGN)1 );
if (!(surface->bits = malloc( surface->info.bmiHeader.biSizeImage ))) goto failed; @@ -1435,22 +1398,6 @@ void ANDROID_SetWindowStyle( HWND hwnd, INT offset, STYLESTRUCT *style ) }
-/*********************************************************************** - * ANDROID_SetWindowRgn - */ -void ANDROID_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) -{ - struct android_win_data *data; - - if ((data = get_win_data( hwnd ))) - { - if (data->surface) set_surface_region( data->surface, hrgn ); - release_win_data( data ); - } - else FIXME( "not supported on other process window %p\n", hwnd ); -} - - /*********************************************************************** * ANDROID_SetLayeredWindowAttributes */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 43 ++++++++++++++++++--- dlls/win32u/window.c | 4 +- dlls/wineandroid.drv/window.c | 52 ++++++------------------- dlls/winemac.drv/surface.c | 26 ++----------- dlls/winewayland.drv/window_surface.c | 8 ++-- dlls/winex11.drv/bitblt.c | 55 ++++++++++++++------------- include/wine/gdi_driver.h | 4 +- 7 files changed, 91 insertions(+), 101 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 428b25d3b6e..a8b81e0ac68 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -74,7 +74,7 @@ static void *dummy_surface_get_bitmap_info( struct window_surface *window_surfac return &dummy_data; }
-static void dummy_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void dummy_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { /* nothing to do */ } @@ -93,7 +93,7 @@ static void dummy_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs dummy_surface_funcs = { dummy_surface_get_bitmap_info, - dummy_surface_set_region, + dummy_surface_set_clip, dummy_surface_flush, dummy_surface_destroy }; @@ -132,7 +132,7 @@ static void *offscreen_window_surface_get_bitmap_info( struct window_surface *ba return impl->bits; }
-static void offscreen_window_surface_set_region( struct window_surface *base, HRGN region ) +static void offscreen_window_surface_set_clip( struct window_surface *base, const RECT *rects, UINT count ) { }
@@ -150,7 +150,7 @@ static void offscreen_window_surface_destroy( struct window_surface *base ) static const struct window_surface_funcs offscreen_window_surface_funcs = { offscreen_window_surface_get_bitmap_info, - offscreen_window_surface_set_region, + offscreen_window_surface_set_clip, offscreen_window_surface_flush, offscreen_window_surface_destroy }; @@ -218,7 +218,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ) ULONG ret = InterlockedDecrement( &surface->ref ); if (!ret) { - if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex ); + if (surface->clip_region) NtGdiDeleteObjectApp( surface->clip_region ); surface->funcs->destroy( surface ); } } @@ -251,6 +251,39 @@ W32KAPI void window_surface_flush( struct window_surface *surface ) window_surface_unlock( surface ); }
+W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_region ) +{ + window_surface_lock( surface ); + + if (!clip_region && surface->clip_region) + { + TRACE( "hwnd %p, surface %p %s, clearing clip region\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ) ); + + NtGdiDeleteObjectApp( surface->clip_region ); + surface->clip_region = 0; + surface->funcs->set_clip( surface, NULL, 0 ); + } + else if (clip_region && !NtGdiEqualRgn( clip_region, surface->clip_region )) + { + WINEREGION *data; + + TRACE( "hwnd %p, surface %p %s, setting clip region %p\n", surface->hwnd, surface, + wine_dbgstr_rect( &surface->rect ), clip_region ); + + if (!surface->clip_region) surface->clip_region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + NtGdiCombineRgn( surface->clip_region, clip_region, 0, RGN_COPY ); + + if ((data = GDI_GetObjPtr( clip_region, NTGDI_OBJ_REGION ))) + { + surface->funcs->set_clip( surface, data->rects, data->numRects ); + GDI_ReleaseObj( clip_region ); + } + } + + window_surface_unlock( surface ); +} + /******************************************************************* * register_window_surface * diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 7c34c929406..d06d6b36941 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1781,12 +1781,12 @@ static void update_surface_region( HWND hwnd ) }
if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; - if (!region) win->surface->funcs->set_region( win->surface, shape ); + if (!region) window_surface_set_clip( win->surface, shape ); else { NtGdiOffsetRgn( region, -visible.left, -visible.top ); if (shape) NtGdiCombineRgn( region, region, shape, RGN_AND ); - win->surface->funcs->set_region( win->surface, region ); + window_surface_set_clip( win->surface, region ); NtGdiDeleteObjectApp( region ); }
diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index d04649da69f..de1de330181 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -571,8 +571,8 @@ struct android_window_surface struct window_surface header; ANativeWindow *window; BOOL byteswap; - RGNDATA *region_data; - HRGN region; + UINT clip_count; + RECT *clip_rects; BYTE alpha; COLORREF color_key; void *bits; @@ -647,40 +647,18 @@ static void *android_surface_get_bitmap_info( struct window_surface *window_surf }
/*********************************************************************** - * android_surface_set_region + * android_surface_set_clip */ -static void android_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void android_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { struct android_window_surface *surface = get_android_surface( window_surface ); - RGNDATA *data; - UINT size;
- TRACE( "updating surface %p hwnd %p with %p\n", surface, window_surface->hwnd, region ); + free( surface->clip_rects ); + surface->clip_rects = NULL;
- window_surface_lock( window_surface ); - if (!region) - { - if (surface->region) NtGdiDeleteObjectApp( surface->region ); - surface->region = 0; - } - else - { - if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); - } - - if (!(size = NtGdiGetRegionData( region, 0, NULL ))) goto done; - if (!(data = malloc( size ))) goto done; - if (!NtGdiGetRegionData( region, size, data )) - { - free( data ); - data = NULL; - } - free( surface->region_data ); - surface->region_data = data; - -done: - window_surface_unlock( window_surface ); + if (!count || !(surface->clip_rects = malloc( count * sizeof(*rects) ))) return; + memcpy( surface->clip_rects, rects, count * sizeof(*rects) ); + surface->clip_count = count; }
/*********************************************************************** @@ -699,7 +677,7 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const
if (!surface->window->perform( surface->window, NATIVE_WINDOW_LOCK, &buffer, &rc )) { - const RECT *rgn_rect = NULL, *end = NULL; + const RECT *rgn_rect = surface->clip_rects, *end = surface->clip_rects + surface->clip_count; DWORD *src, *dst; int x, y, width; RECT locked; @@ -710,11 +688,6 @@ static BOOL android_surface_flush( struct window_surface *window_surface, const locked.bottom = rc.bottom; intersect_rect( &locked, &locked, rect );
- if (surface->region_data) - { - rgn_rect = (RECT *)surface->region_data->Buffer; - end = rgn_rect + surface->region_data->rdh.nCount; - } src = (DWORD *)surface->bits + (locked.top - rect->top) * surface->info.bmiHeader.biWidth + (locked.left - rect->left); dst = (DWORD *)buffer.bits + locked.top * buffer.stride + locked.left; @@ -762,8 +735,7 @@ static void android_surface_destroy( struct window_surface *window_surface )
TRACE( "freeing %p bits %p\n", surface, surface->bits );
- free( surface->region_data ); - if (surface->region) NtGdiDeleteObjectApp( surface->region ); + free( surface->clip_rects ); release_ioctl_window( surface->window ); free( surface->bits ); free( surface ); @@ -772,7 +744,7 @@ static void android_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs android_surface_funcs = { android_surface_get_bitmap_info, - android_surface_set_region, + android_surface_set_clip, android_surface_flush, android_surface_destroy }; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index a6f61538d16..285561e6d02 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -64,7 +64,6 @@ struct macdrv_window_surface { struct window_surface header; macdrv_window window; - HRGN region; BOOL use_alpha; BYTE *bits; BITMAPINFO info; /* variable size, must be last */ @@ -85,28 +84,10 @@ static void *macdrv_surface_get_bitmap_info(struct window_surface *window_surfac }
/*********************************************************************** - * macdrv_surface_set_region + * macdrv_surface_set_clip */ -static void macdrv_surface_set_region(struct window_surface *window_surface, HRGN region) +static void macdrv_surface_set_clip(struct window_surface *window_surface, const RECT *rects, UINT count) { - struct macdrv_window_surface *surface = get_mac_surface(window_surface); - - TRACE("updating surface %p with %p\n", surface, region); - - window_surface_lock(window_surface); - - if (region) - { - if (!surface->region) surface->region = NtGdiCreateRectRgn(0, 0, 0, 0); - NtGdiCombineRgn(surface->region, region, 0, RGN_COPY); - } - else - { - if (surface->region) NtGdiDeleteObjectApp(surface->region); - surface->region = 0; - } - - window_surface_unlock(window_surface); }
/*********************************************************************** @@ -127,7 +108,6 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) struct macdrv_window_surface *surface = get_mac_surface(window_surface);
TRACE("freeing %p bits %p\n", surface, surface->bits); - if (surface->region) NtGdiDeleteObjectApp(surface->region); free(surface->bits); free(surface); } @@ -135,7 +115,7 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) static const struct window_surface_funcs macdrv_surface_funcs = { macdrv_surface_get_bitmap_info, - macdrv_surface_set_region, + macdrv_surface_set_clip, macdrv_surface_flush, macdrv_surface_destroy, }; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 2c19c8ffdc4..752a560ddec 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -224,10 +224,10 @@ static void *wayland_window_surface_get_bitmap_info(struct window_surface *windo }
/*********************************************************************** - * wayland_window_surface_set_region + * wayland_window_surface_set_clip */ -static void wayland_window_surface_set_region(struct window_surface *window_surface, - HRGN region) +static void wayland_window_surface_set_clip(struct window_surface *window_surface, + const RECT *rects, UINT count) { /* TODO */ } @@ -444,7 +444,7 @@ static void wayland_window_surface_destroy(struct window_surface *window_surface static const struct window_surface_funcs wayland_window_surface_funcs = { wayland_window_surface_get_bitmap_info, - wayland_window_surface_set_region, + wayland_window_surface_set_clip, wayland_window_surface_flush, wayland_window_surface_destroy }; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 404beab923d..df8fc8f1257 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1581,7 +1581,6 @@ struct x11drv_window_surface BOOL is_argb; DWORD alpha_bits; COLORREF color_key; - HRGN region; void *bits; #ifdef HAVE_LIBXXSHM XShmSegmentInfo shminfo; @@ -1837,35 +1836,41 @@ static void *x11drv_surface_get_bitmap_info( struct window_surface *window_surfa return surface->bits; }
+static XRectangle *xrectangles_from_rects( const RECT *rects, UINT count ) +{ + XRectangle *xrects; + if (!(xrects = malloc( count * sizeof(*xrects) ))) return NULL; + while (count--) + { + if (rects[count].left > SHRT_MAX) continue; + if (rects[count].top > SHRT_MAX) continue; + if (rects[count].right < SHRT_MIN) continue; + if (rects[count].bottom < SHRT_MIN) continue; + xrects[count].x = max( min( rects[count].left, SHRT_MAX), SHRT_MIN); + xrects[count].y = max( min( rects[count].top, SHRT_MAX), SHRT_MIN); + xrects[count].width = max( min( rects[count].right, SHRT_MAX ) - xrects[count].x, 0); + xrects[count].height = max( min( rects[count].bottom, SHRT_MAX ) - xrects[count].y, 0); + } + return xrects; +} + /*********************************************************************** - * x11drv_surface_set_region + * x11drv_surface_set_clip */ -static void x11drv_surface_set_region( struct window_surface *window_surface, HRGN region ) +static void x11drv_surface_set_clip( struct window_surface *window_surface, const RECT *rects, UINT count ) { - RGNDATA *data; struct x11drv_window_surface *surface = get_x11_surface( window_surface ); + XRectangle *xrects;
- TRACE( "updating surface %p with %p\n", surface, region ); + TRACE( "surface %p, rects %p, count %u\n", surface, rects, count );
- window_surface_lock( window_surface ); - if (!region) - { - if (surface->region) NtGdiDeleteObjectApp( surface->region ); - surface->region = 0; + if (!count) XSetClipMask( gdi_display, surface->gc, None ); - } - else + else if ((xrects = xrectangles_from_rects( rects, count ))) { - if (!surface->region) surface->region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - NtGdiCombineRgn( surface->region, region, 0, RGN_COPY ); - if ((data = X11DRV_GetRegionData( surface->region, 0 ))) - { - XSetClipRectangles( gdi_display, surface->gc, 0, 0, - (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); - free( data ); - } + XSetClipRectangles( gdi_display, surface->gc, 0, 0, xrects, count, YXBanded ); + free( xrects ); } - window_surface_unlock( window_surface ); }
/*********************************************************************** @@ -1938,7 +1943,6 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) surface->image->data = NULL; XDestroyImage( surface->image ); } - if (surface->region) NtGdiDeleteObjectApp( surface->region );
free( surface ); } @@ -1946,7 +1950,7 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs x11drv_surface_funcs = { x11drv_surface_get_bitmap_info, - x11drv_surface_set_region, + x11drv_surface_set_clip, x11drv_surface_flush, x11drv_surface_destroy }; @@ -2038,7 +2042,6 @@ void set_surface_color_key( struct window_surface *window_surface, COLORREF colo */ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) { - struct x11drv_window_surface *surface = get_x11_surface( window_surface ); HRGN region = 0; RECT rc = *rect;
@@ -2047,10 +2050,10 @@ HRGN expose_surface( struct window_surface *window_surface, const RECT *rect ) window_surface_lock( window_surface ); OffsetRect( &rc, -window_surface->rect.left, -window_surface->rect.top ); add_bounds_rect( &window_surface->bounds, &rc ); - if (surface->region) + if (window_surface->clip_region) { region = NtGdiCreateRectRgn( rect->left, rect->top, rect->right, rect->bottom ); - if (NtGdiCombineRgn( region, region, surface->region, RGN_DIFF ) <= NULLREGION) + if (NtGdiCombineRgn( region, region, window_surface->clip_region, RGN_DIFF ) <= NULLREGION) { NtGdiDeleteObjectApp( region ); region = 0; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index f6cfc7778de..588930f9e01 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -212,7 +212,7 @@ struct window_surface; struct window_surface_funcs { void* (*get_info)( struct window_surface *surface, BITMAPINFO *info ); - void (*set_region)( struct window_surface *surface, HRGN region ); + void (*set_clip)( struct window_surface *surface, const RECT *rects, UINT count ); BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty ); void (*destroy)( struct window_surface *surface ); }; @@ -227,6 +227,7 @@ struct window_surface
pthread_mutex_t mutex; RECT bounds; /* dirty area rect, requires locking */ + HRGN clip_region; /* visible region of the surface, fully visible if 0 */ DWORD draw_start_ticks; /* start ticks of fresh draw */ /* driver-specific fields here */ }; @@ -237,6 +238,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ); W32KAPI void window_surface_lock( struct window_surface *surface ); W32KAPI void window_surface_unlock( struct window_surface *surface ); W32KAPI void window_surface_flush( struct window_surface *surface ); +W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_region );
/* display manager interface, used to initialize display device registry data */
Emil Velikov (@xexaxo) commented about dlls/win32u/window.c:
if (win->dwExStyle & WS_EX_LAYOUTRTL) NtUserMirrorRgn( hwnd, shape );
NtGdiDeleteObjectApp( region );
- }
- if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done;
- if (!region) win->surface->funcs->set_region( win->surface, 0 );
if (!region) win->surface->funcs->set_region( win->surface, shape ); else { NtGdiOffsetRgn( region, -visible.left, -visible.top );
if (shape) NtGdiCombineRgn( region, region, shape, RGN_AND ); win->surface->funcs->set_region( win->surface, region ); NtGdiDeleteObjectApp( region );
}
if (shape) NtGdiDeleteObjectApp( shape );
Should probably move the DeleteObj after the done label. Otherwise it'll leak in the err path.
Emil Velikov (@xexaxo) commented about dlls/win32u/dce.c:
ULONG ret = InterlockedDecrement( &surface->ref ); if (!ret) {
if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex );
The mutex_destroy removal seems odd. Is that intentional?