Used for winex11 and later will be used in winemac and winewayland.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 841ab220074..8f36f913415 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1841,7 +1841,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, { WND *win; HWND surface_win = 0; - BOOL ret, needs_surface, needs_update = FALSE; + BOOL ret, needs_surface, needs_update = FALSE, layered, ulw_layered = FALSE; RECT surface_rect, visible_rect = *window_rect, old_visible_rect, old_window_rect, old_client_rect, extra_rects[3]; struct window_surface *old_surface, *new_surface;
@@ -1856,6 +1856,16 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, if (!needs_surface || IsRectEmpty( &visible_rect )) needs_surface = FALSE; /* use default surface */ else needs_surface = !user_driver->pCreateWindowSurface( hwnd, &surface_rect, &new_surface );
+ if ((layered = !!(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED))) + ulw_layered = !NtUserGetLayeredWindowAttributes( hwnd, NULL, NULL, NULL ); + + /* create or update window surface for top-level windows if the driver doesn't implement CreateWindowSurface */ + if (needs_surface && new_surface == &dummy_surface && (!layered || !ulw_layered)) + { + window_surface_release( new_surface ); + create_offscreen_window_surface( hwnd, &surface_rect, &new_surface ); + } + get_window_rects( hwnd, COORDS_SCREEN, &old_window_rect, NULL, get_thread_dpi() ); if (IsRectEmpty( &valid_rects[0] )) valid_rects = NULL;
@@ -1865,15 +1875,6 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, return FALSE; }
- /* create or update window surface for top-level windows if the driver doesn't implement WindowPosChanging */ - if (needs_surface && new_surface && (!(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) || - NtUserGetLayeredWindowAttributes( hwnd, NULL, NULL, NULL ))) - { - window_surface_release( new_surface ); - if ((new_surface = win->surface)) window_surface_add_ref( new_surface ); - create_offscreen_window_surface( hwnd, &surface_rect, &new_surface ); - } - old_visible_rect = win->visible_rect; old_client_rect = win->client_rect; old_surface = win->surface;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/window.c | 128 ++++++++++++++++++++++++++----------------- 1 file changed, 79 insertions(+), 49 deletions(-)
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 8f36f913415..2b65bb635c9 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1831,30 +1831,23 @@ static BOOL get_default_window_surface( HWND hwnd, const RECT *surface_rect, str return TRUE; }
-/*********************************************************************** - * apply_window_pos - * - * Backend implementation of SetWindowPos. - */ -static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, - const RECT *window_rect, const RECT *client_rect, const RECT *valid_rects ) +static struct window_surface *create_window_surface( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, + RECT *visible_rect, RECT *surface_rect ) { - WND *win; - HWND surface_win = 0; - BOOL ret, needs_surface, needs_update = FALSE, layered, ulw_layered = FALSE; - RECT surface_rect, visible_rect = *window_rect, old_visible_rect, old_window_rect, old_client_rect, extra_rects[3]; - struct window_surface *old_surface, *new_surface; + BOOL needs_surface, layered, ulw_layered = FALSE; + struct window_surface *new_surface;
- if (!user_driver->pWindowPosChanging( hwnd, swp_flags, window_rect, client_rect, &visible_rect )) needs_surface = FALSE; + *visible_rect = *window_rect; + if (!user_driver->pWindowPosChanging( hwnd, swp_flags, window_rect, client_rect, visible_rect )) needs_surface = FALSE; else if (swp_flags & SWP_HIDEWINDOW) needs_surface = FALSE; else if (swp_flags & SWP_SHOWWINDOW) needs_surface = TRUE; else needs_surface = !!(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE);
- if (!get_surface_rect( &visible_rect, &surface_rect )) needs_surface = FALSE; - if (!get_default_window_surface( hwnd, &surface_rect, &new_surface )) return FALSE; + if (!get_surface_rect( visible_rect, surface_rect )) needs_surface = FALSE; + if (!get_default_window_surface( hwnd, surface_rect, &new_surface )) return NULL;
- if (!needs_surface || IsRectEmpty( &visible_rect )) needs_surface = FALSE; /* use default surface */ - else needs_surface = !user_driver->pCreateWindowSurface( hwnd, &surface_rect, &new_surface ); + if (!needs_surface || IsRectEmpty( visible_rect )) needs_surface = FALSE; /* use default surface */ + else needs_surface = !user_driver->pCreateWindowSurface( hwnd, surface_rect, &new_surface );
if ((layered = !!(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED))) ulw_layered = !NtUserGetLayeredWindowAttributes( hwnd, NULL, NULL, NULL ); @@ -1863,17 +1856,30 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, if (needs_surface && new_surface == &dummy_surface && (!layered || !ulw_layered)) { window_surface_release( new_surface ); - create_offscreen_window_surface( hwnd, &surface_rect, &new_surface ); + create_offscreen_window_surface( hwnd, surface_rect, &new_surface ); }
+ return new_surface; +} + +/*********************************************************************** + * apply_window_pos + * + * Backend implementation of SetWindowPos. + */ +static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, struct window_surface *new_surface, + const RECT *window_rect, const RECT *client_rect, const RECT *visible_rect, const RECT *valid_rects ) +{ + WND *win; + HWND surface_win = 0; + BOOL ret, needs_update = FALSE; + RECT old_visible_rect, old_window_rect, old_client_rect, extra_rects[3]; + struct window_surface *old_surface; + get_window_rects( hwnd, COORDS_SCREEN, &old_window_rect, NULL, get_thread_dpi() ); if (IsRectEmpty( &valid_rects[0] )) valid_rects = NULL;
- if (!(win = get_win_ptr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) - { - if (new_surface) window_surface_release( new_surface ); - return FALSE; - } + if (!(win = get_win_ptr( hwnd )) || win == WND_DESKTOP || win == WND_OTHER_PROCESS) return FALSE;
old_visible_rect = win->visible_rect; old_client_rect = win->client_rect; @@ -1893,13 +1899,13 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, req->swp_flags = swp_flags; req->window = wine_server_rectangle( *window_rect ); req->client = wine_server_rectangle( *client_rect ); - if (!EqualRect( window_rect, &visible_rect ) || new_surface || valid_rects) + if (!EqualRect( window_rect, visible_rect ) || new_surface || valid_rects) { - extra_rects[0] = extra_rects[1] = visible_rect; + extra_rects[0] = extra_rects[1] = *visible_rect; if (new_surface) { extra_rects[1] = new_surface->rect; - OffsetRect( &extra_rects[1], visible_rect.left, visible_rect.top ); + OffsetRect( &extra_rects[1], visible_rect->left, visible_rect->top ); } if (valid_rects) extra_rects[2] = valid_rects[0]; else SetRectEmpty( &extra_rects[2] ); @@ -1915,8 +1921,8 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, win->dwExStyle = reply->new_ex_style; win->window_rect = *window_rect; win->client_rect = *client_rect; - win->visible_rect = visible_rect; - win->surface = new_surface; + win->visible_rect = *visible_rect; + if ((win->surface = new_surface)) window_surface_add_ref( win->surface ); surface_win = wine_server_ptr_handle( reply->surface_win ); needs_update = reply->needs_update; if (get_window_long( win->parent, GWL_EXSTYLE ) & WS_EX_LAYOUTRTL) @@ -1956,7 +1962,7 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, if (old_surface != new_surface) move_window_bits_surface( hwnd, window_rect, old_surface, &old_visible_rect, valid_rects ); else - move_window_bits( hwnd, &visible_rect, &old_visible_rect, window_rect, valid_rects ); + move_window_bits( hwnd, visible_rect, &old_visible_rect, window_rect, valid_rects ); valid_rects = NULL; /* prevent the driver from trying to also move the bits */ } window_surface_release( old_surface ); @@ -1966,32 +1972,31 @@ static BOOL apply_window_pos( HWND hwnd, HWND insert_after, UINT swp_flags, if (valid_rects) { RECT rects[2]; - int x_offset = old_visible_rect.left - visible_rect.left; - int y_offset = old_visible_rect.top - visible_rect.top; + int x_offset = old_visible_rect.left - visible_rect->left; + int y_offset = old_visible_rect.top - visible_rect->top;
/* if all that happened is that the whole window moved, copy everything */ if (!(swp_flags & SWP_FRAMECHANGED) && - old_visible_rect.right - visible_rect.right == x_offset && - old_visible_rect.bottom - visible_rect.bottom == y_offset && + old_visible_rect.right - visible_rect->right == x_offset && + old_visible_rect.bottom - visible_rect->bottom == y_offset && old_client_rect.left - client_rect->left == x_offset && old_client_rect.right - client_rect->right == x_offset && old_client_rect.top - client_rect->top == y_offset && old_client_rect.bottom - client_rect->bottom == y_offset && EqualRect( &valid_rects[0], client_rect )) { - rects[0] = visible_rect; + rects[0] = *visible_rect; rects[1] = old_visible_rect; valid_rects = rects; } - move_window_bits( hwnd, &visible_rect, &visible_rect, window_rect, valid_rects ); + move_window_bits( hwnd, visible_rect, visible_rect, window_rect, valid_rects ); valid_rects = NULL; /* prevent the driver from trying to also move the bits */ } }
user_driver->pWindowPosChanged( hwnd, insert_after, swp_flags, window_rect, - client_rect, &visible_rect, valid_rects, new_surface ); + client_rect, visible_rect, valid_rects, new_surface ); } - else if (new_surface) window_surface_release( new_surface );
return ret; } @@ -2146,7 +2151,7 @@ BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_ { DWORD swp_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW; struct window_surface *surface; - RECT window_rect, client_rect; + RECT window_rect, client_rect, visible_rect, surface_rect; SIZE offset; BOOL ret = FALSE;
@@ -2192,7 +2197,9 @@ BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_ TRACE( "window %p win %s client %s\n", hwnd, wine_dbgstr_rect(&window_rect), wine_dbgstr_rect(&client_rect) );
- apply_window_pos( hwnd, 0, swp_flags, &window_rect, &client_rect, NULL ); + surface = create_window_surface( hwnd, swp_flags, &window_rect, &client_rect, &visible_rect, &surface_rect ); + apply_window_pos( hwnd, 0, swp_flags, surface, &window_rect, &client_rect, &visible_rect, NULL ); + if (surface) window_surface_release( surface );
if (!(flags & ULW_COLORKEY)) key = CLR_INVALID; if (!(user_driver->pCreateLayeredWindow( hwnd, &window_rect, key, &surface )) || !surface) return FALSE; @@ -3444,7 +3451,8 @@ done: /* NtUserSetWindowPos implementation */ BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) { - RECT old_window_rect, old_client_rect, new_window_rect, new_client_rect, valid_rects[2]; + RECT old_window_rect, old_client_rect, new_window_rect, new_client_rect, valid_rects[2], visible_rect, surface_rect; + struct window_surface *surface; UINT orig_flags, context; BOOL ret = FALSE;
@@ -3506,9 +3514,15 @@ BOOL set_window_pos( WINDOWPOS *winpos, int parent_x, int parent_y ) calc_ncsize( winpos, &old_window_rect, &old_client_rect, &new_window_rect, &new_client_rect, valid_rects, parent_x, parent_y );
- if (!apply_window_pos( winpos->hwnd, winpos->hwndInsertAfter, winpos->flags, - &new_window_rect, &new_client_rect, valid_rects )) + surface = create_window_surface( winpos->hwnd, winpos->flags, &new_window_rect, &new_client_rect, + &visible_rect, &surface_rect ); + if (!apply_window_pos( winpos->hwnd, winpos->hwndInsertAfter, winpos->flags, surface, + &new_window_rect, &new_client_rect, &visible_rect, valid_rects )) + { + if (surface) window_surface_release( surface ); goto done; + } + if (surface) window_surface_release( surface );
if (winpos->flags & SWP_HIDEWINDOW) { @@ -4283,8 +4297,11 @@ static UINT arrange_iconic_windows( HWND parent ) */ void update_window_state( HWND hwnd ) { + static const UINT swp_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | + SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW; UINT context; - RECT window_rect, client_rect, valid_rects[2]; + RECT window_rect, client_rect, valid_rects[2], visible_rect, surface_rect; + struct window_surface *surface;
if (!is_current_thread_window( hwnd )) { @@ -4295,9 +4312,11 @@ void update_window_state( HWND hwnd ) context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd )); get_window_rects( hwnd, COORDS_PARENT, &window_rect, &client_rect, get_thread_dpi() ); valid_rects[0] = valid_rects[1] = client_rect; - apply_window_pos( hwnd, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE | - SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW, - &window_rect, &client_rect, valid_rects ); + + surface = create_window_surface( hwnd, swp_flags, &window_rect, &client_rect, &visible_rect, &surface_rect ); + apply_window_pos( hwnd, 0, swp_flags, surface, &window_rect, &client_rect, &visible_rect, valid_rects ); + if (surface) window_surface_release( surface ); + set_thread_dpi_awareness_context( context ); }
@@ -5159,11 +5178,12 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, DWORD flags, HINSTANCE client_instance, DWORD unk, BOOL ansi ) { UINT win_dpi, thread_dpi = get_thread_dpi(), context; + struct window_surface *surface; CBT_CREATEWNDW cbtc; HWND hwnd, owner = 0; CREATESTRUCTW cs; INT sw = SW_SHOW; - RECT rect; + RECT rect, visible_rect, surface_rect; WND *win;
static const WCHAR messageW[] = {'M','e','s','s','a','g','e'}; @@ -5336,7 +5356,14 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, /* check for wraparound */ if (cs.x > 0x7fffffff - cx) rect.right = 0x7fffffff; if (cs.y > 0x7fffffff - cy) rect.bottom = 0x7fffffff; - if (!apply_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed; + + surface = create_window_surface( hwnd, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, &visible_rect, &surface_rect ); + if (!apply_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, surface, &rect, &rect, &visible_rect, NULL )) + { + if (surface) window_surface_release( surface ); + goto failed; + } + if (surface) window_surface_release( surface );
/* send WM_NCCREATE */
@@ -5368,7 +5395,10 @@ HWND WINAPI NtUserCreateWindowEx( DWORD ex_style, UNICODE_STRING *class_name, map_window_points( parent, 0, (POINT *)&client_rect, 2, win_dpi ); send_message( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect ); map_window_points( 0, parent, (POINT *)&client_rect, 2, win_dpi ); - apply_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &rect, &client_rect, NULL ); + + surface = create_window_surface( hwnd, SWP_NOACTIVATE, &rect, &client_rect, &visible_rect, &surface_rect ); + apply_window_pos( hwnd, insert_after, SWP_NOACTIVATE, surface, &rect, &client_rect, &visible_rect, NULL ); + if (surface) window_surface_release( surface ); } else goto failed;
From: Rémi Bernon rbernon@codeweavers.com
Cropping and rounding it similarly to non-layered window surfaces. --- dlls/win32u/driver.c | 6 +++--- dlls/win32u/window.c | 3 ++- dlls/wineandroid.drv/android.h | 2 +- dlls/wineandroid.drv/window.c | 10 +++------- dlls/winemac.drv/surface.c | 10 +++------- dlls/winex11.drv/bitblt.c | 10 +++------- dlls/winex11.drv/x11drv.h | 2 +- 7 files changed, 16 insertions(+), 27 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 7918945b625..4bc49619970 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -867,7 +867,7 @@ static LRESULT nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ) return -1; }
-static BOOL nulldrv_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +static BOOL nulldrv_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **surface ) { *surface = NULL; @@ -1217,10 +1217,10 @@ static void loaderdrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) load_driver()->pSetWindowRgn( hwnd, hrgn, redraw ); }
-static BOOL loaderdrv_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +static BOOL loaderdrv_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **surface ) { - return load_driver()->pCreateLayeredWindow( hwnd, window_rect, color_key, surface ); + return load_driver()->pCreateLayeredWindow( hwnd, surface_rect, color_key, surface ); }
static void loaderdrv_UpdateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index 2b65bb635c9..b63392b1f2d 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -2202,7 +2202,7 @@ BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_ if (surface) window_surface_release( surface );
if (!(flags & ULW_COLORKEY)) key = CLR_INVALID; - if (!(user_driver->pCreateLayeredWindow( hwnd, &window_rect, key, &surface )) || !surface) return FALSE; + if (!(user_driver->pCreateLayeredWindow( hwnd, &surface_rect, key, &surface )) || !surface) return FALSE;
if (!hdc_src) ret = TRUE; else @@ -2213,6 +2213,7 @@ BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_ HDC hdc = NULL;
OffsetRect( &rect, -rect.left, -rect.top ); + intersect_rect( &rect, &rect, &surface_rect );
if (!(hdc = NtGdiCreateCompatibleDC( 0 ))) goto done; window_surface_lock( surface ); diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index c92240c40bc..3f0329bac10 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -98,7 +98,7 @@ extern void ANDROID_SetParent( HWND hwnd, HWND parent, HWND old_parent ); 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 ); -extern BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +extern BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **surface ); extern LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ); extern BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ); diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 1ee542455a3..73f2c0b9897 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -1305,18 +1305,14 @@ void ANDROID_SetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alpha, DW /***************************************************************************** * ANDROID_CreateLayeredWindow */ -BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **window_surface ) { struct window_surface *surface; struct android_win_data *data; - RECT rect;
if (!(data = get_win_data( hwnd ))) return FALSE;
- rect = *window_rect; - OffsetRect( &rect, -window_rect->left, -window_rect->top ); - surface = data->surface; if (!is_argb_surface( surface )) { @@ -1324,9 +1320,9 @@ BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF c surface = NULL; }
- if (!surface || !EqualRect( &surface->rect, &rect )) + if (!surface || !EqualRect( &surface->rect, surface_rect )) { - data->surface = create_surface( data->hwnd, &rect, 255, color_key, TRUE ); + data->surface = create_surface( data->hwnd, surface_rect, 255, color_key, TRUE ); if (surface) window_surface_release( surface ); surface = data->surface; } diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index e4f140a898e..d8a49674a5b 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -226,25 +226,21 @@ done: /*********************************************************************** * CreateLayeredWindow (MACDRV.@) */ -BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *window_rect, COLORREF color_key, +BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **window_surface) { struct window_surface *surface; struct macdrv_win_data *data; - RECT rect;
if (!(data = get_win_data(hwnd))) return FALSE;
data->layered = TRUE; data->ulw_layered = TRUE;
- rect = *window_rect; - OffsetRect(&rect, -window_rect->left, -window_rect->top); - surface = data->surface; - if (!surface || !EqualRect(&surface->rect, &rect)) + if (!surface || !EqualRect(&surface->rect, surface_rect)) { - data->surface = create_surface(data->hwnd, data->cocoa_window, &rect, NULL, TRUE); + data->surface = create_surface(data->hwnd, data->cocoa_window, surface_rect, NULL, TRUE); if (surface) window_surface_release(surface); surface = data->surface; if (data->unminimized_surface) diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index c28a4d2d9a3..28723425029 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -2172,25 +2172,21 @@ done: /***************************************************************************** * CreateLayeredWindow (X11DRV.@) */ -BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **window_surface ) { struct window_surface *surface; struct x11drv_win_data *data; - RECT rect;
if (!(data = get_win_data( hwnd ))) return FALSE;
data->layered = TRUE; if (!data->embedded && argb_visual.visualid) set_window_visual( data, &argb_visual, TRUE );
- rect = *window_rect; - OffsetRect( &rect, -window_rect->left, -window_rect->top ); - surface = data->surface; - if (!surface || !EqualRect( &surface->rect, &rect )) + if (!surface || !EqualRect( &surface->rect, surface_rect )) { - data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, &rect, + data->surface = create_surface( data->hwnd, data->whole_window, &data->vis, surface_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 49e4f039b18..1078270eefe 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -240,7 +240,7 @@ extern UINT X11DRV_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ); extern LRESULT X11DRV_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam ); extern LRESULT X11DRV_ClipboardWindowProc( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ); extern void X11DRV_UpdateClipboard(void); -extern BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, +extern BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **surface ); extern void X11DRV_UpdateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, BYTE alpha, UINT flags );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/driver.c | 2 +- dlls/win32u/window.c | 9 +++++++-- dlls/wineandroid.drv/android.h | 3 ++- dlls/wineandroid.drv/window.c | 9 +++++---- dlls/winemac.drv/macdrv.h | 3 ++- dlls/winemac.drv/window.c | 8 +++++--- dlls/winewayland.drv/waylanddrv.h | 3 ++- dlls/winewayland.drv/window.c | 9 +++++---- dlls/winex11.drv/window.c | 8 +++++++- dlls/winex11.drv/x11drv.h | 3 ++- include/wine/gdi_driver.h | 4 ++-- 11 files changed, 40 insertions(+), 21 deletions(-)
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 4bc49619970..76e717648d6 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -884,7 +884,7 @@ static LRESULT nulldrv_WindowMessage( HWND hwnd, UINT msg, WPARAM wparam, LPARAM return 0; }
-static BOOL nulldrv_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ) +static BOOL nulldrv_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ) { return TRUE; } diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index b63392b1f2d..f065fd7309e 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1834,11 +1834,16 @@ static BOOL get_default_window_surface( HWND hwnd, const RECT *surface_rect, str static struct window_surface *create_window_surface( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect, RECT *surface_rect ) { - BOOL needs_surface, layered, ulw_layered = FALSE; + BOOL shaped, needs_surface, layered, ulw_layered = FALSE; struct window_surface *new_surface; + RECT dummy; + HRGN shape; + + if (get_window_region( hwnd, FALSE, &shape, &dummy )) shaped = FALSE; + else if ((shaped = !!shape)) NtGdiDeleteObjectApp( shape );
*visible_rect = *window_rect; - if (!user_driver->pWindowPosChanging( hwnd, swp_flags, window_rect, client_rect, visible_rect )) needs_surface = FALSE; + if (!user_driver->pWindowPosChanging( hwnd, swp_flags, shaped, window_rect, client_rect, visible_rect )) needs_surface = FALSE; else if (swp_flags & SWP_HIDEWINDOW) needs_surface = FALSE; else if (swp_flags & SWP_SHOWWINDOW) needs_surface = TRUE; else needs_surface = !!(NtUserGetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE); diff --git a/dlls/wineandroid.drv/android.h b/dlls/wineandroid.drv/android.h index 3f0329bac10..54062b04db0 100644 --- a/dlls/wineandroid.drv/android.h +++ b/dlls/wineandroid.drv/android.h @@ -101,7 +101,8 @@ extern UINT ANDROID_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp ); extern BOOL ANDROID_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COLORREF color_key, struct window_surface **surface ); extern LRESULT ANDROID_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ); -extern BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ); +extern BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect ); extern BOOL ANDROID_CreateWindowSurface( HWND hwnd, const RECT *surface_rect, struct window_surface **surface ); extern void ANDROID_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 73f2c0b9897..5da40b4a2f1 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -1059,14 +1059,15 @@ static struct android_win_data *create_win_data( HWND hwnd, const RECT *window_r /*********************************************************************** * ANDROID_WindowPosChanging */ -BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ) +BOOL ANDROID_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect ) { struct android_win_data *data = get_win_data( hwnd ); BOOL ret = FALSE;
- TRACE( "win %p window %s client %s style %08x flags %08x\n", - hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), - (int)NtUserGetWindowLongW( hwnd, GWL_STYLE ), swp_flags ); + TRACE( "hwnd %p, swp_flags %04x, shaped %u, window_rect %s, client_rect %s, visible_rect %s\n", + hwnd, swp_flags, shaped, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), + wine_dbgstr_rect(visible_rect) );
if (!data && !(data = create_win_data( hwnd, window_rect, client_rect ))) return FALSE; /* use default surface */
diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 8824f3385fa..8b9e908bc1a 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -150,7 +150,8 @@ extern BOOL macdrv_CreateLayeredWindow(HWND hwnd, const RECT *window_rect, COLOR extern void macdrv_UpdateLayeredWindow(HWND hwnd, const RECT *window_rect, COLORREF color_key, BYTE alpha, UINT flags); extern LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp); -extern BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect); +extern BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect); extern BOOL macdrv_CreateWindowSurface(HWND hwnd, const RECT *surface_rect, struct window_surface **surface); extern void macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 0bbb7e4fc34..0784b0e4e39 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -1947,17 +1947,19 @@ LRESULT macdrv_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) /*********************************************************************** * WindowPosChanging (MACDRV.@) */ -BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect) +BOOL macdrv_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect) { struct macdrv_win_data *data = get_win_data(hwnd); DWORD style = NtUserGetWindowLongW(hwnd, GWL_STYLE); BOOL ret = FALSE;
- TRACE("%p swp %04x window %s client %s visible %s\n", hwnd, - swp_flags, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), + TRACE("hwnd %p, swp_flags %04x, shaped %u, window_rect %s, client_rect %s, visible_rect %s\n", + hwnd, swp_flags, shaped, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), wine_dbgstr_rect(visible_rect));
if (!data && !(data = macdrv_create_win_data(hwnd, window_rect, client_rect))) return FALSE; /* use default surface */ + data->shaped = shaped;
macdrv_window_to_mac_rect(data, style, visible_rect, window_rect, client_rect); TRACE("visible_rect %s -> %s\n", wine_dbgstr_rect(window_rect), diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index d4ef01a8a1e..efb13821696 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -360,7 +360,8 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, const RECT *visible_rect, const RECT *valid_rects, struct window_surface *surface); -BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect); +BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect); BOOL WAYLAND_CreateWindowSurface(HWND hwnd, const RECT *surface_rect, struct window_surface **surface); UINT WAYLAND_VulkanInit(UINT version, void *vulkan_handle, const struct vulkan_driver_funcs **driver_funcs); struct opengl_funcs *WAYLAND_wine_get_wgl_driver(UINT version); diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index c1fb5c6e0b5..dc6a6b7e03a 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -427,15 +427,16 @@ void WAYLAND_DestroyWindow(HWND hwnd) /*********************************************************************** * WAYLAND_WindowPosChanging */ -BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect) +BOOL WAYLAND_WindowPosChanging(HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect) { struct wayland_win_data *data = wayland_win_data_get(hwnd); HWND parent; BOOL ret = FALSE;
- TRACE("hwnd %p window %s client %s visible %s flags %08x\n", - hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), - wine_dbgstr_rect(visible_rect), swp_flags); + TRACE("hwnd %p, swp_flags %04x, shaped %u, window_rect %s, client_rect %s, visible_rect %s\n", + hwnd, swp_flags, shaped, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), + wine_dbgstr_rect(visible_rect));
if (!data && !(data = wayland_win_data_create(hwnd, window_rect, client_rect))) return FALSE; /* use default surface */
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 7416164bbb1..5c949525598 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2579,12 +2579,18 @@ done: /*********************************************************************** * WindowPosChanging (X11DRV.@) */ -BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ) +BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect ) { struct x11drv_win_data *data = get_win_data( hwnd ); BOOL ret = FALSE;
+ TRACE( "hwnd %p, swp_flags %04x, shaped %u, window_rect %s, client_rect %s, visible_rect %s\n", + hwnd, swp_flags, shaped, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), + wine_dbgstr_rect(visible_rect) ); + if (!data && !(data = X11DRV_create_win_data( hwnd, window_rect, client_rect ))) return FALSE; /* use default surface */ + data->shaped = shaped;
/* check if we need to switch the window to managed */ if (!data->managed && data->whole_window && is_window_managed( hwnd, swp_flags, window_rect )) diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index 1078270eefe..fc57c72cb79 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -245,7 +245,8 @@ extern BOOL X11DRV_CreateLayeredWindow( HWND hwnd, const RECT *surface_rect, COL extern void X11DRV_UpdateLayeredWindow( HWND hwnd, const RECT *window_rect, COLORREF color_key, BYTE alpha, UINT flags ); extern LRESULT X11DRV_WindowMessage( HWND hwnd, UINT msg, WPARAM wp, LPARAM lp ); -extern BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect ); +extern BOOL X11DRV_WindowPosChanging( HWND hwnd, UINT swp_flags, BOOL shaped, const RECT *window_rect, + const RECT *client_rect, RECT *visible_rect ); extern BOOL X11DRV_CreateWindowSurface( HWND hwnd, const RECT *surface_rect, struct window_surface **surface ); extern void X11DRV_WindowPosChanged( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *rectWindow, const RECT *rectClient, diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index b1b07f8dc72..ef2d284cfe1 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -179,7 +179,7 @@ struct gdi_dc_funcs };
/* increment this when you change the DC function table */ -#define WINE_GDI_DRIVER_VERSION 86 +#define WINE_GDI_DRIVER_VERSION 87
#define GDI_PRIORITY_NULL_DRV 0 /* null driver */ #define GDI_PRIORITY_FONT_DRV 100 /* any font driver */ @@ -340,7 +340,7 @@ struct user_driver_funcs BOOL (*pCreateLayeredWindow)(HWND,const RECT *,COLORREF,struct window_surface **); void (*pUpdateLayeredWindow)(HWND,const RECT *,COLORREF,BYTE,UINT); LRESULT (*pWindowMessage)(HWND,UINT,WPARAM,LPARAM); - BOOL (*pWindowPosChanging)(HWND,UINT,const RECT *,const RECT *,RECT *); + BOOL (*pWindowPosChanging)(HWND,UINT,BOOL,const RECT *,const RECT *,RECT *); BOOL (*pCreateWindowSurface)(HWND,const RECT *,struct window_surface**); void (*pWindowPosChanged)(HWND,HWND,UINT,const RECT *,const RECT *,const RECT *, const RECT *,struct window_surface*);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 38 +++++++++++++++++++++++++++ dlls/win32u/window.c | 1 + dlls/wineandroid.drv/window.c | 8 ++++++ dlls/winemac.drv/surface.c | 9 +++++++ dlls/winewayland.drv/window_surface.c | 9 +++++++ dlls/winex11.drv/bitblt.c | 24 +++++++++++++++++ dlls/winex11.drv/window.c | 5 +++- include/wine/gdi_driver.h | 5 ++++ 8 files changed, 98 insertions(+), 1 deletion(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 91bcb02a6a8..c7199e6b64a 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -61,6 +61,11 @@ static void dummy_surface_set_clip( struct window_surface *window_surface, const /* nothing to do */ }
+static void dummy_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +{ + /* nothing to do */ +} + static BOOL dummy_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, const void *color_bits ) { @@ -76,6 +81,7 @@ static void dummy_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs dummy_surface_funcs = { dummy_surface_set_clip, + dummy_surface_set_shape, dummy_surface_flush, dummy_surface_destroy }; @@ -96,6 +102,10 @@ static void offscreen_window_surface_set_clip( struct window_surface *surface, c { }
+static void offscreen_window_surface_set_shape( struct window_surface *surface, const RECT *rects, UINT count ) +{ +} + static BOOL offscreen_window_surface_flush( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, const void *color_bits ) { @@ -110,6 +120,7 @@ static void offscreen_window_surface_destroy( struct window_surface *surface ) static const struct window_surface_funcs offscreen_window_surface_funcs = { offscreen_window_surface_set_clip, + offscreen_window_surface_set_shape, offscreen_window_surface_flush, offscreen_window_surface_destroy }; @@ -328,6 +339,33 @@ W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_ window_surface_unlock( surface ); }
+W32KAPI void window_surface_set_shape( struct window_surface *surface, HRGN shape_region ) +{ + window_surface_lock( surface ); + + if (!shape_region && surface->shape_region) + { + NtGdiDeleteObjectApp( surface->shape_region ); + surface->shape_region = 0; + surface->funcs->set_shape( surface, NULL, 0 ); + } + else if (shape_region && !NtGdiEqualRgn( shape_region, surface->shape_region )) + { + WINEREGION *data; + + if (!surface->shape_region) surface->shape_region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); + NtGdiCombineRgn( surface->shape_region, shape_region, 0, RGN_COPY ); + + if ((data = GDI_GetObjPtr( shape_region, NTGDI_OBJ_REGION ))) + { + surface->funcs->set_shape( surface, data->rects, data->numRects ); + GDI_ReleaseObj( shape_region ); + } + } + + window_surface_unlock( surface ); +} + /******************************************************************* * register_window_surface * diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index f065fd7309e..ad4d49ca034 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1764,6 +1764,7 @@ static void update_surface_region( HWND hwnd ) if (win->dwExStyle & WS_EX_LAYOUTRTL) NtUserMirrorRgn( hwnd, shape ); NtGdiDeleteObjectApp( region ); } + window_surface_set_shape( win->surface, shape );
if (get_window_region( hwnd, TRUE, ®ion, &visible )) goto done; if (!region) window_surface_set_clip( win->surface, shape ); diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 5da40b4a2f1..550d98e5c85 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -618,6 +618,13 @@ static void android_surface_set_clip( struct window_surface *window_surface, con surface->clip_count = count; }
+/*********************************************************************** + * android_surface_set_shape + */ +static void android_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +{ +} + /*********************************************************************** * android_surface_flush */ @@ -704,6 +711,7 @@ static void android_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs android_surface_funcs = { android_surface_set_clip, + android_surface_set_shape, android_surface_flush, android_surface_destroy }; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index d8a49674a5b..6961baf0d2e 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -74,6 +74,14 @@ static void macdrv_surface_set_clip(struct window_surface *window_surface, const { }
+/*********************************************************************** + * macdrv_surface_set_shape + */ +static void macdrv_surface_set_shape(struct window_surface *window_surface, const RECT *rects, UINT count) +{ + /* TODO */ +} + /*********************************************************************** * macdrv_surface_flush */ @@ -112,6 +120,7 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) static const struct window_surface_funcs macdrv_surface_funcs = { macdrv_surface_set_clip, + macdrv_surface_set_shape, macdrv_surface_flush, macdrv_surface_destroy, }; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index 084f987df6c..ed11323ea51 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -217,6 +217,14 @@ static void wayland_window_surface_set_clip(struct window_surface *window_surfac /* TODO */ }
+/*********************************************************************** + * wayland_window_surface_set_shape + */ +static void wayland_window_surface_set_shape(struct window_surface *window_surface, const RECT *rects, UINT count) +{ + /* TODO */ +} + /********************************************************************** * get_region_data */ @@ -430,6 +438,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_set_clip, + wayland_window_surface_set_shape, wayland_window_surface_flush, wayland_window_surface_destroy }; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 28723425029..68d7f528601 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1941,6 +1941,29 @@ static void x11drv_surface_set_clip( struct window_surface *window_surface, cons } }
+/*********************************************************************** + * x11drv_surface_set_shape + */ +static void x11drv_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +{ +#ifdef HAVE_LIBXSHAPE + struct x11drv_window_surface *surface = get_x11_surface( window_surface ); + XRectangle *xrects; + + TRACE( "surface %p, rects %p, count %u\n", surface, rects, count ); + + if (!count) + XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); + else if ((xrects = xrectangles_from_rects( rects, count ))) + { + XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0, + xrects, count, ShapeSet, YXBanded ); + free( xrects ); + } + XFlush( gdi_display ); +#endif /* HAVE_LIBXSHAPE */ +} + /*********************************************************************** * x11drv_surface_flush */ @@ -2013,6 +2036,7 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs x11drv_surface_funcs = { x11drv_surface_set_clip, + x11drv_surface_set_shape, x11drv_surface_flush, x11drv_surface_destroy }; diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 5c949525598..9e51d76e5ab 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -386,16 +386,19 @@ static void sync_window_region( struct x11drv_win_data *data, HRGN win_region ) HRGN hrgn = win_region;
if (!data->whole_window) return; - data->shaped = FALSE;
if (IsRectEmpty( &data->window_rect )) /* set an empty shape */ { static XRectangle empty_rect; + data->shaped = FALSE; XShapeCombineRectangles( data->display, data->whole_window, ShapeBounding, 0, 0, &empty_rect, 1, ShapeSet, YXBanded ); return; }
+ if (data->surface) return; /* use surface shape instead */ + data->shaped = FALSE; + if (hrgn == (HRGN)1) /* hack: win_region == 1 means retrieve region from server */ { if (!(hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ))) return; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index ef2d284cfe1..0ce908e5cad 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -212,6 +212,7 @@ struct window_surface; struct window_surface_funcs { void (*set_clip)( struct window_surface *surface, const RECT *rects, UINT count ); + void (*set_shape)( struct window_surface *surface, const RECT *rects, UINT count ); BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, const void *color_bits ); void (*destroy)( struct window_surface *surface ); @@ -232,6 +233,8 @@ struct window_surface COLORREF color_key; /* layered window surface color key, invalid if CLR_INVALID */ UINT alpha_bits; /* layered window global alpha bits, invalid if -1 */ UINT alpha_mask; /* layered window per-pixel alpha mask, invalid if 0 */ + HRGN shape_region; /* shape of the window surface, unshaped if 0 */ + HBITMAP shape_bitmap; /* bitmap for the surface shape (1bpp) */ HBITMAP color_bitmap; /* bitmap for the surface colors */ /* driver-specific fields here */ }; @@ -245,6 +248,8 @@ W32KAPI void window_surface_unlock( struct window_surface *surface ); W32KAPI void window_surface_set_layered( struct window_surface *surface, COLORREF color_key, UINT alpha_bits, UINT alpha_mask ); W32KAPI void window_surface_flush( struct window_surface *surface ); W32KAPI void window_surface_set_clip( struct window_surface *surface, HRGN clip_region ); +W32KAPI void window_surface_set_shape( struct window_surface *surface, HRGN shape_region ); +W32KAPI void window_surface_set_layered( struct window_surface *surface, COLORREF color_key, UINT alpha_bits, UINT alpha_mask );
/* display manager interface, used to initialize display device registry data */
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 124 +++++++++++++++++++++++--- dlls/wineandroid.drv/window.c | 3 +- dlls/winemac.drv/surface.c | 3 +- dlls/winewayland.drv/window_surface.c | 3 +- dlls/winex11.drv/bitblt.c | 21 +++-- include/wine/gdi_driver.h | 3 +- 6 files changed, 131 insertions(+), 26 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index c7199e6b64a..43b81e4e738 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -61,7 +61,8 @@ static void dummy_surface_set_clip( struct window_surface *window_surface, const /* nothing to do */ }
-static void dummy_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +static void dummy_surface_set_shape( struct window_surface *window_surface, + const BITMAPINFO *shape_info, const void *shape_bits ) { /* nothing to do */ } @@ -102,7 +103,8 @@ static void offscreen_window_surface_set_clip( struct window_surface *surface, c { }
-static void offscreen_window_surface_set_shape( struct window_surface *surface, const RECT *rects, UINT count ) +static void offscreen_window_surface_set_shape( struct window_surface *surface, + const BITMAPINFO *shape_info, const void *shape_bits ) { }
@@ -184,6 +186,96 @@ static COLORREF get_color_key( const BITMAPINFO *info, COLORREF color_key ) return (GetRValue( color_key ) << 16) | (GetGValue( color_key ) << 8) | GetBValue( color_key ); }
+static void set_surface_shape_rect( BYTE *bits, UINT stride, const RECT *rect ) +{ + BYTE *begin = bits + rect->top * stride, *end = bits + rect->bottom * stride; + UINT l = rect->left / 8, l_mask, r = rect->right / 8, r_mask; + + /* 1bpp bitmaps use MSB for lowest X */ + l_mask = (1 << (8 - (rect->left & 7))) - 1; + r_mask = (1 << (8 - (rect->right & 7))) - 1; + if (r_mask == 0xff) { r--; r_mask = 0; } /* avoid writing to the next byte */ + + if (rect->right - rect->left == 8 * stride) memset( begin, 0xff, end - begin ); + else if (l == r) for (bits = begin; bits < end; bits += stride) bits[l] |= l_mask & r_mask; + else if (l < r) + { + for (bits = begin; bits < end; bits += stride) + { + bits[l] |= l_mask; + memset( bits + l + 1, 0xff, r - l - 1 ); + bits[r] |= ~r_mask; + } + } +} + +static void *window_surface_get_shape( struct window_surface *surface, BITMAPINFO *info ) +{ + struct bitblt_coords coords = {0}; + struct gdi_image_bits gdi_bits; + BITMAPOBJ *bmp; + + if (!(bmp = GDI_GetObjPtr( surface->shape_bitmap, NTGDI_OBJ_BITMAP ))) return NULL; + get_image_from_bitmap( bmp, info, &gdi_bits, &coords ); + GDI_ReleaseObj( surface->shape_bitmap ); + + return gdi_bits.ptr; +} + +static void set_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, + const BITMAPINFO *color_info, void *color_bits ) +{ + UINT width, height, shape_stride; + char shape_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *shape_info = (BITMAPINFO *)shape_buf; + RECT *shape_rect, tmp_rect; + WINEREGION *data; + void *shape_bits; + + width = color_info->bmiHeader.biWidth; + height = abs( color_info->bmiHeader.biHeight ); + assert( !(width & 7) ); /* expect 1bpp bitmap to be aligned on bytes */ + + if (!surface->shape_bitmap) surface->shape_bitmap = NtGdiCreateBitmap( width, height, 1, 1, NULL ); + if (!(shape_bits = window_surface_get_shape( surface, shape_info ))) return; + + shape_stride = shape_info->bmiHeader.biSizeImage / abs( shape_info->bmiHeader.biHeight ); + if (!surface->shape_region) set_surface_shape_rect( shape_bits, shape_stride, dirty ); + else if ((data = GDI_GetObjPtr( surface->shape_region, NTGDI_OBJ_REGION ))) + { + if (EqualRect( rect, dirty )) memset( shape_bits, 0, shape_info->bmiHeader.biSizeImage ); + for (shape_rect = data->rects; shape_rect < data->rects + data->numRects; shape_rect++) + { + if (!intersect_rect( &tmp_rect, shape_rect, dirty )) continue; + set_surface_shape_rect( shape_bits, shape_stride, &tmp_rect ); + } + GDI_ReleaseObj( surface->shape_region ); + } + + surface->funcs->set_shape( surface, shape_info, shape_bits ); +} + +static void clear_surface_shape( struct window_surface *surface ) +{ + if (surface->shape_bitmap) + { + NtGdiDeleteObjectApp( surface->shape_bitmap ); + surface->shape_bitmap = 0; + surface->funcs->set_shape( surface, NULL, NULL ); + } +} + +static void update_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, + const BITMAPINFO *color_info, void *color_bits ) +{ + if (surface == &dummy_surface) return; + + if (surface->shape_region) + set_surface_shape( surface, rect, dirty, color_info, color_bits ); + else + clear_surface_shape( surface ); +} + W32KAPI BOOL window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, HWND hwnd, const RECT *rect, BITMAPINFO *info, HBITMAP bitmap ) { @@ -216,6 +308,7 @@ W32KAPI void window_surface_release( struct window_surface *surface ) if (surface != &dummy_surface) pthread_mutex_destroy( &surface->mutex ); if (surface->clip_region) NtGdiDeleteObjectApp( surface->clip_region ); if (surface->color_bitmap) NtGdiDeleteObjectApp( surface->color_bitmap ); + if (surface->shape_bitmap) NtGdiDeleteObjectApp( surface->shape_bitmap ); surface->funcs->destroy( surface ); } } @@ -259,16 +352,26 @@ W32KAPI void window_surface_flush( struct window_surface *surface ) { char color_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *color_info = (BITMAPINFO *)color_buf; - RECT dirty = surface->rect; + RECT dirty = surface->rect, bounds; void *color_bits;
window_surface_lock( surface );
+ /* align bounds / dirty rect to help with 1bpp shape bitmap updates */ + bounds.left = surface->bounds.left & ~7; + bounds.top = surface->bounds.top; + bounds.right = (surface->bounds.right + 7) & ~7; + bounds.bottom = surface->bounds.bottom; + OffsetRect( &dirty, -dirty.left, -dirty.top ); - if (intersect_rect( &dirty, &dirty, &surface->bounds ) && (color_bits = window_surface_get_color( surface, color_info ))) + + if (intersect_rect( &dirty, &dirty, &bounds ) && (color_bits = window_surface_get_color( surface, color_info ))) { + update_surface_shape( surface, &surface->rect, &dirty, color_info, color_bits ); + 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, color_info, color_bits )) reset_bounds( &surface->bounds ); }
@@ -347,23 +450,18 @@ W32KAPI void window_surface_set_shape( struct window_surface *surface, HRGN shap { NtGdiDeleteObjectApp( surface->shape_region ); surface->shape_region = 0; - surface->funcs->set_shape( surface, NULL, 0 ); + surface->bounds = surface->rect; } else if (shape_region && !NtGdiEqualRgn( shape_region, surface->shape_region )) { - WINEREGION *data; - if (!surface->shape_region) surface->shape_region = NtGdiCreateRectRgn( 0, 0, 0, 0 ); NtGdiCombineRgn( surface->shape_region, shape_region, 0, RGN_COPY ); - - if ((data = GDI_GetObjPtr( shape_region, NTGDI_OBJ_REGION ))) - { - surface->funcs->set_shape( surface, data->rects, data->numRects ); - GDI_ReleaseObj( shape_region ); - } + surface->bounds = surface->rect; }
window_surface_unlock( surface ); + + window_surface_flush( surface ); }
/******************************************************************* diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 550d98e5c85..498cb744a64 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -621,7 +621,8 @@ static void android_surface_set_clip( struct window_surface *window_surface, con /*********************************************************************** * android_surface_set_shape */ -static void android_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +static void android_surface_set_shape( struct window_surface *window_surface, + const BITMAPINFO *shape_info, const void *shape_bits ) { }
diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index 6961baf0d2e..a4103b1818b 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -77,7 +77,8 @@ static void macdrv_surface_set_clip(struct window_surface *window_surface, const /*********************************************************************** * macdrv_surface_set_shape */ -static void macdrv_surface_set_shape(struct window_surface *window_surface, const RECT *rects, UINT count) +static void macdrv_surface_set_shape(struct window_surface *window_surface, + const BITMAPINFO *shape_info, const void *shape_bits) { /* TODO */ } diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index ed11323ea51..b29f7faf781 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -220,7 +220,8 @@ static void wayland_window_surface_set_clip(struct window_surface *window_surfac /*********************************************************************** * wayland_window_surface_set_shape */ -static void wayland_window_surface_set_shape(struct window_surface *window_surface, const RECT *rects, UINT count) +static void wayland_window_surface_set_shape(struct window_surface *window_surface, + const BITMAPINFO *shape_info, const void *shape_bits) { /* TODO */ } diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 68d7f528601..a7d41e37d79 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1944,21 +1944,24 @@ static void x11drv_surface_set_clip( struct window_surface *window_surface, cons /*********************************************************************** * x11drv_surface_set_shape */ -static void x11drv_surface_set_shape( struct window_surface *window_surface, const RECT *rects, UINT count ) +static void x11drv_surface_set_shape( struct window_surface *window_surface, + const BITMAPINFO *shape_info, const void *shape_bits ) { #ifdef HAVE_LIBXSHAPE struct x11drv_window_surface *surface = get_x11_surface( window_surface ); - XRectangle *xrects; - - TRACE( "surface %p, rects %p, count %u\n", surface, rects, count );
- if (!count) + if (!shape_info) XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); - else if ((xrects = xrectangles_from_rects( rects, count ))) + else { - XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0, - xrects, count, ShapeSet, YXBanded ); - free( xrects ); + struct gdi_image_bits bits = {.ptr = (void *)shape_bits}; + XVisualInfo vis = default_visual; + Pixmap shape; + + vis.depth = 1; + shape = create_pixmap_from_image( 0, &vis, shape_info, &bits, DIB_RGB_COLORS ); + XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, shape, ShapeSet ); + XFreePixmap( gdi_display, shape ); } XFlush( gdi_display ); #endif /* HAVE_LIBXSHAPE */ diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index 0ce908e5cad..a8f4eb97cfa 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -212,7 +212,8 @@ struct window_surface; struct window_surface_funcs { void (*set_clip)( struct window_surface *surface, const RECT *rects, UINT count ); - void (*set_shape)( struct window_surface *surface, const RECT *rects, UINT count ); + void (*set_shape)( struct window_surface *surface, const BITMAPINFO *shape_info, + const void *shape_bits ); BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, const void *color_bits ); void (*destroy)( struct window_surface *surface );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 82 +++++++++++++++++++- dlls/winex11.drv/bitblt.c | 159 -------------------------------------- 2 files changed, 79 insertions(+), 162 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 43b81e4e738..1f8d1e4c3e2 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -174,7 +174,6 @@ static COLORREF get_color_key( const BITMAPINFO *info, COLORREF color_key ) if (color_key & (1 << 24)) /* PALETTEINDEX */ return 0; if (color_key >> 16 == 0x10ff) /* DIBINDEX */ return 0;
- if (info->bmiHeader.biBitCount == 24) return color_key; if (info->bmiHeader.biCompression == BI_BITFIELDS) { UINT *masks = (UINT *)info->bmiColors; @@ -222,12 +221,34 @@ static void *window_surface_get_shape( struct window_surface *surface, BITMAPINF return gdi_bits.ptr; }
+static BYTE shape_from_alpha_mask( UINT32 *bits, UINT32 alpha_mask, UINT32 alpha ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & alpha_mask) == alpha) << bit; + return ~mask; +} + +static BYTE shape_from_color_key_16( UINT16 *bits, UINT16 color_mask, UINT16 color_key ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & color_mask) == color_key) << bit; + return ~mask; +} + +static BYTE shape_from_color_key_32( UINT32 *bits, UINT32 color_mask, UINT32 color_key ) +{ + BYTE i, bit, mask = 0; + for (i = 0, bit = 7; i < 8; i++, bit--) mask |= ((bits[i] & color_mask) == color_key) << bit; + return ~mask; +} + static void set_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, void *color_bits ) { - UINT width, height, shape_stride; + UINT width, height, x, y, shape_stride, color_stride, alpha_mask = surface->alpha_mask; char shape_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *shape_info = (BITMAPINFO *)shape_buf; + COLORREF color_key = surface->color_key; RECT *shape_rect, tmp_rect; WINEREGION *data; void *shape_bits; @@ -239,7 +260,9 @@ static void set_surface_shape( struct window_surface *surface, const RECT *rect, if (!surface->shape_bitmap) surface->shape_bitmap = NtGdiCreateBitmap( width, height, 1, 1, NULL ); if (!(shape_bits = window_surface_get_shape( surface, shape_info ))) return;
+ color_stride = color_info->bmiHeader.biSizeImage / height; shape_stride = shape_info->bmiHeader.biSizeImage / abs( shape_info->bmiHeader.biHeight ); + if (!surface->shape_region) set_surface_shape_rect( shape_bits, shape_stride, dirty ); else if ((data = GDI_GetObjPtr( surface->shape_region, NTGDI_OBJ_REGION ))) { @@ -252,6 +275,59 @@ static void set_surface_shape( struct window_surface *surface, const RECT *rect, GDI_ReleaseObj( surface->shape_region ); }
+ switch (color_info->bmiHeader.biBitCount) + { + case 16: + { + UINT *masks = (UINT *)color_info->bmiColors, color_mask; + BYTE *shape = shape_bits, *color = color_bits; + + if (color_key == CLR_INVALID) color_mask = 0; + else color_mask = masks[0] | masks[1] | masks[2]; + if (!color_mask) break; + + color += dirty->top * color_stride; + shape += dirty->top * shape_stride; + + for (y = dirty->top; y < dirty->bottom; y++, color += color_stride, shape += shape_stride) + { + for (x = dirty->left; x < dirty->right; x += 8) + { + shape[x / 8] &= shape_from_color_key_16( (UINT16 *)color + x, color_mask, color_key ); + } + } + break; + } + case 24: case 32: + { + BYTE *shape = shape_bits, *color = color_bits; + UINT color_mask, alpha = 0; + + if (color_key == CLR_INVALID) color_mask = 0; + else if (color_info->bmiHeader.biCompression == BI_RGB) color_mask = 0xffffff; + else + { + UINT *masks = (UINT *)color_info->bmiColors; + color_mask = masks[0] | masks[1] | masks[2]; + } + if (!alpha_mask && !color_mask) break; + if (!alpha_mask) alpha = -1; + + color += dirty->top * color_stride; + shape += dirty->top * shape_stride; + + for (y = dirty->top; y < dirty->bottom; y++, color += color_stride, shape += shape_stride) + { + for (x = dirty->left; x < dirty->right; x += 8) + { + shape[x / 8] &= shape_from_alpha_mask( (UINT32 *)color + x, alpha_mask, alpha ); + shape[x / 8] &= shape_from_color_key_32( (UINT32 *)color + x, color_mask, color_key ); + } + } + break; + } + } + surface->funcs->set_shape( surface, shape_info, shape_bits ); }
@@ -270,7 +346,7 @@ static void update_surface_shape( struct window_surface *surface, const RECT *re { if (surface == &dummy_surface) return;
- if (surface->shape_region) + if (surface->shape_region || surface->alpha_mask || surface->color_key != CLR_INVALID) set_surface_shape( surface, rect, dirty, color_info, color_bits ); else clear_surface_shape( surface ); diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index a7d41e37d79..0d27f6b847f 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1596,162 +1596,6 @@ static struct x11drv_window_surface *get_x11_surface( struct window_surface *sur return (struct x11drv_window_surface *)surface; }
-#ifdef HAVE_LIBXSHAPE -static inline void flush_rgn_data( HRGN rgn, RGNDATA *data ) -{ - HRGN tmp = NtGdiExtCreateRegion( NULL, data->rdh.dwSize + data->rdh.nRgnSize, data ); - NtGdiCombineRgn( rgn, rgn, tmp, RGN_OR ); - NtGdiDeleteObjectApp( tmp ); - data->rdh.nCount = 0; -} - -static inline void add_row( HRGN rgn, RGNDATA *data, int x, int y, int len ) -{ - RECT *rect = (RECT *)data->Buffer + data->rdh.nCount; - - if (len <= 0) return; - rect->left = x; - rect->top = y; - rect->right = x + len; - rect->bottom = y + 1; - data->rdh.nCount++; - if (data->rdh.nCount * sizeof(RECT) > data->rdh.nRgnSize - sizeof(RECT)) - flush_rgn_data( rgn, data ); -} -#endif - -/*********************************************************************** - * update_surface_region - */ -static void update_surface_region( struct x11drv_window_surface *surface, const BITMAPINFO *info, const void *color_bits, - COLORREF color_key, UINT alpha_mask ) -{ -#ifdef HAVE_LIBXSHAPE - char buffer[4096]; - RGNDATA *data = (RGNDATA *)buffer; - UINT *masks = (UINT *)info->bmiColors; - int x, y, start, width; - HRGN rgn; - - if (!shape_layered_windows) return; - - if (!alpha_mask && color_key == CLR_INVALID) - { - XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); - return; - } - - data->rdh.dwSize = sizeof(data->rdh); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = 0; - data->rdh.nRgnSize = sizeof(buffer) - sizeof(data->rdh); - - rgn = NtGdiCreateRectRgn( 0, 0, 0, 0 ); - width = surface->header.rect.right - surface->header.rect.left; - - switch (info->bmiHeader.biBitCount) - { - case 16: - { - const WORD *bits = color_bits; - int stride = (width + 1) & ~1; - UINT mask = masks[0] | masks[1] | masks[2]; - - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride) - { - x = 0; - while (x < width) - { - while (x < width && (bits[x] & mask) == color_key) x++; - start = x; - while (x < width && (bits[x] & mask) != color_key) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - break; - } - case 24: - { - const BYTE *bits = color_bits; - int stride = (width * 3 + 3) & ~3; - - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += stride) - { - x = 0; - while (x < width) - { - while (x < width && - (bits[x * 3] == GetBValue(color_key)) && - (bits[x * 3 + 1] == GetGValue(color_key)) && - (bits[x * 3 + 2] == GetRValue(color_key))) - x++; - start = x; - while (x < width && - ((bits[x * 3] != GetBValue(color_key)) || - (bits[x * 3 + 1] != GetGValue(color_key)) || - (bits[x * 3 + 2] != GetRValue(color_key)))) - x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - break; - } - case 32: - { - const DWORD *bits = color_bits; - - if (info->bmiHeader.biCompression == BI_RGB) - { - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width) - { - x = 0; - while (x < width) - { - while (x < width && - ((bits[x] & 0xffffff) == color_key || - (alpha_mask && !(bits[x] & alpha_mask)))) x++; - start = x; - while (x < width && - !((bits[x] & 0xffffff) == color_key || - (alpha_mask && !(bits[x] & alpha_mask)))) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - } - else - { - UINT mask = masks[0] | masks[1] | masks[2]; - for (y = surface->header.rect.top; y < surface->header.rect.bottom; y++, bits += width) - { - x = 0; - while (x < width) - { - while (x < width && (bits[x] & mask) == color_key) x++; - start = x; - while (x < width && (bits[x] & mask) != color_key) x++; - add_row( rgn, data, surface->header.rect.left + start, y, x - start ); - } - } - } - break; - } - default: - assert(0); - } - - if (data->rdh.nCount) flush_rgn_data( rgn, data ); - - if ((data = X11DRV_GetRegionData( rgn, 0 ))) - { - XShapeCombineRectangles( gdi_display, surface->window, ShapeBounding, 0, 0, - (XRectangle *)data->Buffer, data->rdh.nCount, ShapeSet, YXBanded ); - free( data ); - } - - NtGdiDeleteObjectApp( rgn ); -#endif -} - #ifdef HAVE_LIBXXSHM static int xshm_error_handler( Display *display, XErrorEvent *event, void *arg ) { @@ -1975,13 +1819,10 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R { UINT alpha_mask = window_surface->alpha_mask, alpha_bits = window_surface->alpha_bits; struct x11drv_window_surface *surface = get_x11_surface( window_surface ); - COLORREF color_key = window_surface->color_key; XImage *ximage = surface->image->ximage; const unsigned char *src = color_bits; unsigned char *dst = (unsigned char *)ximage->data;
- if (alpha_mask || color_key != CLR_INVALID) update_surface_region( surface, color_info, color_bits, color_key, alpha_mask ); - if (alpha_bits == -1) { if (alpha_mask || color_info->bmiHeader.biBitCount != 32) alpha_bits = 0;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/dce.c | 62 +++++++++++++-------------- dlls/wineandroid.drv/window.c | 12 +----- dlls/winemac.drv/surface.c | 13 +----- dlls/winewayland.drv/window_surface.c | 13 +----- dlls/winex11.drv/bitblt.c | 49 +++++++++------------ include/wine/gdi_driver.h | 5 +-- 6 files changed, 59 insertions(+), 95 deletions(-)
diff --git a/dlls/win32u/dce.c b/dlls/win32u/dce.c index 1f8d1e4c3e2..aa6836e3440 100644 --- a/dlls/win32u/dce.c +++ b/dlls/win32u/dce.c @@ -61,14 +61,9 @@ static void dummy_surface_set_clip( struct window_surface *window_surface, const /* nothing to do */ }
-static void dummy_surface_set_shape( struct window_surface *window_surface, - const BITMAPINFO *shape_info, const void *shape_bits ) -{ - /* nothing to do */ -} - static BOOL dummy_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits ) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits ) { /* nothing to do */ return TRUE; @@ -82,7 +77,6 @@ static void dummy_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs dummy_surface_funcs = { dummy_surface_set_clip, - dummy_surface_set_shape, dummy_surface_flush, dummy_surface_destroy }; @@ -103,13 +97,9 @@ static void offscreen_window_surface_set_clip( struct window_surface *surface, c { }
-static void offscreen_window_surface_set_shape( struct window_surface *surface, - const BITMAPINFO *shape_info, const void *shape_bits ) -{ -} - static BOOL offscreen_window_surface_flush( struct window_surface *surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits ) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits ) { return TRUE; } @@ -122,7 +112,6 @@ static void offscreen_window_surface_destroy( struct window_surface *surface ) static const struct window_surface_funcs offscreen_window_surface_funcs = { offscreen_window_surface_set_clip, - offscreen_window_surface_set_shape, offscreen_window_surface_flush, offscreen_window_surface_destroy }; @@ -242,23 +231,27 @@ static BYTE shape_from_color_key_32( UINT32 *bits, UINT32 color_mask, UINT32 col return ~mask; }
-static void set_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, +static BOOL set_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, void *color_bits ) { UINT width, height, x, y, shape_stride, color_stride, alpha_mask = surface->alpha_mask; char shape_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *shape_info = (BITMAPINFO *)shape_buf; COLORREF color_key = surface->color_key; + void *shape_bits, *old_shape; RECT *shape_rect, tmp_rect; WINEREGION *data; - void *shape_bits; + BOOL ret;
width = color_info->bmiHeader.biWidth; height = abs( color_info->bmiHeader.biHeight ); assert( !(width & 7) ); /* expect 1bpp bitmap to be aligned on bytes */
if (!surface->shape_bitmap) surface->shape_bitmap = NtGdiCreateBitmap( width, height, 1, 1, NULL ); - if (!(shape_bits = window_surface_get_shape( surface, shape_info ))) return; + if (!(shape_bits = window_surface_get_shape( surface, shape_info ))) return FALSE; + + old_shape = malloc( shape_info->bmiHeader.biSizeImage ); + memcpy( old_shape, shape_bits, shape_info->bmiHeader.biSizeImage );
color_stride = color_info->bmiHeader.biSizeImage / height; shape_stride = shape_info->bmiHeader.biSizeImage / abs( shape_info->bmiHeader.biHeight ); @@ -328,28 +321,28 @@ static void set_surface_shape( struct window_surface *surface, const RECT *rect, } }
- surface->funcs->set_shape( surface, shape_info, shape_bits ); + ret = memcmp( old_shape, shape_bits, shape_info->bmiHeader.biSizeImage ); + free( old_shape ); + return ret; }
-static void clear_surface_shape( struct window_surface *surface ) +static BOOL clear_surface_shape( struct window_surface *surface ) { - if (surface->shape_bitmap) - { - NtGdiDeleteObjectApp( surface->shape_bitmap ); - surface->shape_bitmap = 0; - surface->funcs->set_shape( surface, NULL, NULL ); - } + if (!surface->shape_bitmap) return FALSE; + NtGdiDeleteObjectApp( surface->shape_bitmap ); + surface->shape_bitmap = 0; + return TRUE; }
-static void update_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, +static BOOL update_surface_shape( struct window_surface *surface, const RECT *rect, const RECT *dirty, const BITMAPINFO *color_info, void *color_bits ) { - if (surface == &dummy_surface) return; + if (surface == &dummy_surface) return FALSE;
if (surface->shape_region || surface->alpha_mask || surface->color_key != CLR_INVALID) - set_surface_shape( surface, rect, dirty, color_info, color_bits ); + return set_surface_shape( surface, rect, dirty, color_info, color_bits ); else - clear_surface_shape( surface ); + return clear_surface_shape( surface ); }
W32KAPI BOOL window_surface_init( struct window_surface *surface, const struct window_surface_funcs *funcs, @@ -427,7 +420,9 @@ void *window_surface_get_color( struct window_surface *surface, BITMAPINFO *info W32KAPI void window_surface_flush( struct window_surface *surface ) { char color_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + char shape_buf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; BITMAPINFO *color_info = (BITMAPINFO *)color_buf; + BITMAPINFO *shape_info = (BITMAPINFO *)shape_buf; RECT dirty = surface->rect, bounds; void *color_bits;
@@ -443,12 +438,15 @@ W32KAPI void window_surface_flush( struct window_surface *surface )
if (intersect_rect( &dirty, &dirty, &bounds ) && (color_bits = window_surface_get_color( surface, color_info ))) { - update_surface_shape( surface, &surface->rect, &dirty, color_info, color_bits ); + BOOL shape_changed = update_surface_shape( surface, &surface->rect, &dirty, color_info, color_bits ); + void *shape_bits = window_surface_get_shape( surface, shape_info );
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, color_info, color_bits )) reset_bounds( &surface->bounds ); + if (surface->funcs->flush( surface, &surface->rect, &dirty, color_info, color_bits, + shape_changed, shape_info, shape_bits )) + reset_bounds( &surface->bounds ); }
window_surface_unlock( surface ); diff --git a/dlls/wineandroid.drv/window.c b/dlls/wineandroid.drv/window.c index 498cb744a64..0f8cedfbd0b 100644 --- a/dlls/wineandroid.drv/window.c +++ b/dlls/wineandroid.drv/window.c @@ -618,19 +618,12 @@ static void android_surface_set_clip( struct window_surface *window_surface, con surface->clip_count = count; }
-/*********************************************************************** - * android_surface_set_shape - */ -static void android_surface_set_shape( struct window_surface *window_surface, - const BITMAPINFO *shape_info, const void *shape_bits ) -{ -} - /*********************************************************************** * android_surface_flush */ static BOOL android_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits ) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits ) { struct android_window_surface *surface = get_android_surface( window_surface ); ANativeWindow_Buffer buffer; @@ -712,7 +705,6 @@ static void android_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs android_surface_funcs = { android_surface_set_clip, - android_surface_set_shape, android_surface_flush, android_surface_destroy }; diff --git a/dlls/winemac.drv/surface.c b/dlls/winemac.drv/surface.c index a4103b1818b..fa34a5122ab 100644 --- a/dlls/winemac.drv/surface.c +++ b/dlls/winemac.drv/surface.c @@ -74,20 +74,12 @@ static void macdrv_surface_set_clip(struct window_surface *window_surface, const { }
-/*********************************************************************** - * macdrv_surface_set_shape - */ -static void macdrv_surface_set_shape(struct window_surface *window_surface, - const BITMAPINFO *shape_info, const void *shape_bits) -{ - /* TODO */ -} - /*********************************************************************** * macdrv_surface_flush */ static BOOL macdrv_surface_flush(struct window_surface *window_surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits) { struct macdrv_window_surface *surface = get_mac_surface(window_surface); CGImageAlphaInfo alpha_info = (window_surface->alpha_mask ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaNoneSkipFirst); @@ -121,7 +113,6 @@ static void macdrv_surface_destroy(struct window_surface *window_surface) static const struct window_surface_funcs macdrv_surface_funcs = { macdrv_surface_set_clip, - macdrv_surface_set_shape, macdrv_surface_flush, macdrv_surface_destroy, }; diff --git a/dlls/winewayland.drv/window_surface.c b/dlls/winewayland.drv/window_surface.c index b29f7faf781..e9eb74b17ca 100644 --- a/dlls/winewayland.drv/window_surface.c +++ b/dlls/winewayland.drv/window_surface.c @@ -217,15 +217,6 @@ static void wayland_window_surface_set_clip(struct window_surface *window_surfac /* TODO */ }
-/*********************************************************************** - * wayland_window_surface_set_shape - */ -static void wayland_window_surface_set_shape(struct window_surface *window_surface, - const BITMAPINFO *shape_info, const void *shape_bits) -{ - /* TODO */ -} - /********************************************************************** * get_region_data */ @@ -328,7 +319,8 @@ static void wayland_shm_buffer_copy(struct wayland_shm_buffer *src, * wayland_window_surface_flush */ static BOOL wayland_window_surface_flush(struct window_surface *window_surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits) { RECT surface_rect = {.right = color_info->bmiHeader.biWidth, .bottom = abs(color_info->bmiHeader.biHeight)}; struct wayland_window_surface *wws = wayland_window_surface_cast(window_surface); @@ -439,7 +431,6 @@ static void wayland_window_surface_destroy(struct window_surface *window_surface static const struct window_surface_funcs wayland_window_surface_funcs = { wayland_window_surface_set_clip, - wayland_window_surface_set_shape, wayland_window_surface_flush, wayland_window_surface_destroy }; diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 0d27f6b847f..02c960c0074 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -1785,37 +1785,12 @@ static void x11drv_surface_set_clip( struct window_surface *window_surface, cons } }
-/*********************************************************************** - * x11drv_surface_set_shape - */ -static void x11drv_surface_set_shape( struct window_surface *window_surface, - const BITMAPINFO *shape_info, const void *shape_bits ) -{ -#ifdef HAVE_LIBXSHAPE - struct x11drv_window_surface *surface = get_x11_surface( window_surface ); - - if (!shape_info) - XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); - else - { - struct gdi_image_bits bits = {.ptr = (void *)shape_bits}; - XVisualInfo vis = default_visual; - Pixmap shape; - - vis.depth = 1; - shape = create_pixmap_from_image( 0, &vis, shape_info, &bits, DIB_RGB_COLORS ); - XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, shape, ShapeSet ); - XFreePixmap( gdi_display, shape ); - } - XFlush( gdi_display ); -#endif /* HAVE_LIBXSHAPE */ -} - /*********************************************************************** * x11drv_surface_flush */ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits ) + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits ) { UINT alpha_mask = window_surface->alpha_mask, alpha_bits = window_surface->alpha_bits; struct x11drv_window_surface *surface = get_x11_surface( window_surface ); @@ -1859,6 +1834,25 @@ static BOOL x11drv_surface_flush( struct window_surface *window_surface, const R dirty->top, rect->left + dirty->left, rect->top + dirty->top, dirty->right - dirty->left, dirty->bottom - dirty->top );
+ if (shape_changed) + { +#ifdef HAVE_LIBXSHAPE + if (!shape_info) + XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, None, ShapeSet ); + else + { + struct gdi_image_bits bits = {.ptr = (void *)shape_bits}; + XVisualInfo vis = default_visual; + Pixmap shape; + + vis.depth = 1; + shape = create_pixmap_from_image( 0, &vis, shape_info, &bits, DIB_RGB_COLORS ); + XShapeCombineMask( gdi_display, surface->window, ShapeBounding, 0, 0, shape, ShapeSet ); + XFreePixmap( gdi_display, shape ); + } +#endif /* HAVE_LIBXSHAPE */ + } + XFlush( gdi_display );
return TRUE; @@ -1880,7 +1874,6 @@ static void x11drv_surface_destroy( struct window_surface *window_surface ) static const struct window_surface_funcs x11drv_surface_funcs = { x11drv_surface_set_clip, - x11drv_surface_set_shape, x11drv_surface_flush, x11drv_surface_destroy }; diff --git a/include/wine/gdi_driver.h b/include/wine/gdi_driver.h index a8f4eb97cfa..774211fea15 100644 --- a/include/wine/gdi_driver.h +++ b/include/wine/gdi_driver.h @@ -212,10 +212,9 @@ struct window_surface; struct window_surface_funcs { void (*set_clip)( struct window_surface *surface, const RECT *rects, UINT count ); - void (*set_shape)( struct window_surface *surface, const BITMAPINFO *shape_info, - const void *shape_bits ); BOOL (*flush)( struct window_surface *surface, const RECT *rect, const RECT *dirty, - const BITMAPINFO *color_info, const void *color_bits ); + const BITMAPINFO *color_info, const void *color_bits, BOOL shape_changed, + const BITMAPINFO *shape_info, const void *shape_bits ); void (*destroy)( struct window_surface *surface ); };
Looks like there's some suspicious X error, thanks Huw.