Module: wine Branch: master Commit: cc7bf355c50b17b2e04f754c80464289df2a9ee7 URL: http://source.winehq.org/git/wine.git/?a=commit;h=cc7bf355c50b17b2e04f754c80...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Oct 9 15:21:21 2012 +0200
user32: Add support for setting the window surface visible region.
---
dlls/user32/win.c | 6 +++++ dlls/user32/winpos.c | 55 ++++++++++++++++++++++++++++++++++++++++++++- dlls/winex11.drv/bitblt.c | 23 ++++++++++++++++++ include/wine/gdi_driver.h | 1 + 4 files changed, 84 insertions(+), 1 deletions(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 7da4972..66eaf09 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -539,6 +539,11 @@ static RECT *dummy_surface_get_bounds( struct window_surface *window_surface ) return &dummy_bounds; }
+static void dummy_surface_set_region( struct window_surface *window_surface, HRGN region ) +{ + /* nothing to do */ +} + static void dummy_surface_flush( struct window_surface *window_surface ) { /* nothing to do */ @@ -555,6 +560,7 @@ static const struct window_surface_funcs dummy_surface_funcs = dummy_surface_unlock, dummy_surface_get_bitmap_info, dummy_surface_get_bounds, + dummy_surface_set_region, dummy_surface_flush, dummy_surface_destroy }; diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c index 7a0d8f9..a04bf2c 100644 --- a/dlls/user32/winpos.c +++ b/dlls/user32/winpos.c @@ -1941,6 +1941,57 @@ static BOOL fixup_flags( WINDOWPOS *winpos )
/*********************************************************************** + * update_surface_region + */ +static void update_surface_region( HWND hwnd ) +{ + NTSTATUS status; + HRGN region = 0; + RGNDATA *data; + size_t size = 256; + WND *win = WIN_GetPtr( hwnd ); + + if (!win || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return; + if (!win->surface) goto done; + + do + { + if (!(data = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( RGNDATA, Buffer[size] )))) goto done; + + SERVER_START_REQ( get_surface_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; + region = ExtCreateRegion( NULL, size, data ); + OffsetRgn( region, -reply->visible_rect.left, -reply->visible_rect.top ); + } + } + else size = reply->total_size; + } + SERVER_END_REQ; + HeapFree( GetProcessHeap(), 0, data ); + } while (status == STATUS_BUFFER_OVERFLOW); + + if (status) goto done; + + win->surface->funcs->set_region( win->surface, region ); + if (region) DeleteObject( region ); + +done: + WIN_ReleasePtr( win ); +} + + +/*********************************************************************** * set_window_pos * * Backend implementation of SetWindowPos. @@ -1949,7 +2000,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects ) { WND *win; - HWND parent = GetAncestor( hwnd, GA_PARENT ); + HWND surface_win = 0, parent = GetAncestor( hwnd, GA_PARENT ); BOOL ret; int old_width; RECT visible_rect, old_visible_rect, old_window_rect; @@ -2005,6 +2056,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, win->visible_rect = visible_rect; old_surface = win->surface; win->surface = new_surface; + surface_win = wine_server_ptr_handle( reply->surface_win ); if (GetWindowLongW( win->parent, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) { RECT client; @@ -2022,6 +2074,7 @@ BOOL set_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags,
if (ret) { + if (surface_win) update_surface_region( surface_win ); if (old_surface != new_surface || ((swp_flags & SWP_AGG_NOPOSCHANGE) != SWP_AGG_NOPOSCHANGE) || (swp_flags & (SWP_HIDEWINDOW | SWP_SHOWWINDOW | SWP_STATECHANGED | SWP_FRAMECHANGED))) diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index e1812cd..c3cf056 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1848,6 +1848,28 @@ static RECT *x11drv_surface_get_bounds( struct window_surface *window_surface ) }
/*********************************************************************** + * x11drv_surface_set_region + */ +static void x11drv_surface_set_region( struct window_surface *window_surface, HRGN region ) +{ + RGNDATA *data; + struct x11drv_window_surface *surface = get_x11_surface( window_surface ); + + TRACE( "updating surface %p with %p\n", surface, region ); + + if (!region) + { + XSetClipMask( gdi_display, surface->gc, None ); + } + else if ((data = X11DRV_GetRegionData( region, 0 ))) + { + XSetClipRectangles( gdi_display, surface->gc, 0, 0, + (XRectangle *)data->Buffer, data->rdh.nCount, YXBanded ); + HeapFree( GetProcessHeap(), 0, data ); + } +} + +/*********************************************************************** * x11drv_surface_flush */ static void x11drv_surface_flush( struct window_surface *window_surface ) @@ -1945,6 +1967,7 @@ static const struct window_surface_funcs x11drv_surface_funcs = x11drv_surface_unlock, x11drv_surface_get_bitmap_info, x11drv_surface_get_bounds, + x11drv_surface_set_region, x11drv_surface_flush, x11drv_surface_destroy }; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index c58803d..e942ed9 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -233,6 +233,7 @@ struct window_surface_funcs void (*unlock)( struct window_surface *surface ); void* (*get_info)( struct window_surface *surface, BITMAPINFO *info ); RECT* (*get_bounds)( struct window_surface *surface ); + void (*set_region)( struct window_surface *surface, HRGN region ); void (*flush)( struct window_surface *surface ); void (*destroy)( struct window_surface *surface ); };