diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c index e3db8299b48..19e8a2c9dfc 100644 --- a/dlls/user32/driver.c +++ b/dlls/user32/driver.c @@ -134,12 +134,6 @@ static LRESULT CDECL nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam return -1; } -static BOOL CDECL nulldrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, - const RECT *window_rect ) -{ - return TRUE; -} - static BOOL CDECL nulldrv_WindowPosChanging( HWND hwnd, HWND insert_after, UINT swp_flags, const RECT *window_rect, const RECT *client_rect, RECT *visible_rect, struct window_surface **surface ) @@ -183,12 +177,6 @@ static void CDECL loaderdrv_GetDC( HDC hdc, HWND hwnd, HWND top_win, const RECT load_driver()->pGetDC( hdc, hwnd, top_win, win_rect, top_rect, flags ); } -static BOOL CDECL loaderdrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, - const RECT *window_rect ) -{ - return load_driver()->pUpdateLayeredWindow( hwnd, info, window_rect ); -} - static struct user_driver_funcs lazy_load_driver = { { NULL }, @@ -233,7 +221,7 @@ static struct user_driver_funcs lazy_load_driver = nulldrv_SetWindowText, nulldrv_ShowWindow, nulldrv_SysCommand, - loaderdrv_UpdateLayeredWindow, + NULL, NULL, nulldrv_WindowPosChanging, nulldrv_WindowPosChanged, @@ -278,7 +266,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v SET_USER_FUNC(SetWindowText); SET_USER_FUNC(ShowWindow); SET_USER_FUNC(SysCommand); - SET_USER_FUNC(UpdateLayeredWindow); SET_USER_FUNC(WindowPosChanging); SET_USER_FUNC(WindowPosChanged); #undef SET_USER_FUNC diff --git a/dlls/user32/win.c b/dlls/user32/win.c index 554d35635c5..6bbf2068f40 100644 --- a/dlls/user32/win.c +++ b/dlls/user32/win.c @@ -3256,56 +3256,15 @@ BOOL CDECL __wine_set_pixel_format( HWND hwnd, int format ) */ BOOL WINAPI UpdateLayeredWindowIndirect( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info ) { - DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW; - RECT window_rect, client_rect; - SIZE offset; - - if (!info || - info->cbSize != sizeof(*info) || - info->dwFlags & ~(ULW_COLORKEY | ULW_ALPHA | ULW_OPAQUE | ULW_EX_NORESIZE) || - !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) || - NtUserGetLayeredWindowAttributes( hwnd, NULL, NULL, NULL )) + if (!info || info->cbSize != sizeof(*info)) { SetLastError( ERROR_INVALID_PARAMETER ); return FALSE; } - WIN_GetRectangles( hwnd, COORDS_PARENT, &window_rect, &client_rect ); - - if (info->pptDst) - { - offset.cx = info->pptDst->x - window_rect.left; - offset.cy = info->pptDst->y - window_rect.top; - OffsetRect( &client_rect, offset.cx, offset.cy ); - OffsetRect( &window_rect, offset.cx, offset.cy ); - flags &= ~SWP_NOMOVE; - } - if (info->psize) - { - offset.cx = info->psize->cx - (window_rect.right - window_rect.left); - offset.cy = info->psize->cy - (window_rect.bottom - window_rect.top); - if (info->psize->cx <= 0 || info->psize->cy <= 0) - { - SetLastError( ERROR_INVALID_PARAMETER ); - return FALSE; - } - if ((info->dwFlags & ULW_EX_NORESIZE) && (offset.cx || offset.cy)) - { - SetLastError( ERROR_INCORRECT_SIZE ); - return FALSE; - } - client_rect.right += offset.cx; - client_rect.bottom += offset.cy; - window_rect.right += offset.cx; - window_rect.bottom += offset.cy; - flags &= ~SWP_NOSIZE; - } - - TRACE( "window %p win %s client %s\n", hwnd, - wine_dbgstr_rect(&window_rect), wine_dbgstr_rect(&client_rect) ); - - set_window_pos( hwnd, 0, flags, &window_rect, &client_rect, NULL ); - return USER_Driver->pUpdateLayeredWindow( hwnd, info, &window_rect ); + return NtUserUpdateLayeredWindow( hwnd, info->hdcDst, info->pptDst, info->psize, + info->hdcSrc, info->pptSrc, info->crKey, + info->pblend, info->dwFlags, info->prcDirty ); } diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c index 0e0c21c1eab..3f956c315ad 100644 --- a/dlls/win32u/driver.c +++ b/dlls/win32u/driver.c @@ -1147,6 +1147,12 @@ static void CDECL loaderdrv_SetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw ) load_driver()->pSetWindowRgn( hwnd, hrgn, redraw ); } +static BOOL CDECL loaderdrv_UpdateLayeredWindow( HWND hwnd, const UPDATELAYEREDWINDOWINFO *info, + const RECT *window_rect ) +{ + return load_driver()->pUpdateLayeredWindow( hwnd, info, window_rect ); +} + static const struct vulkan_funcs * CDECL loaderdrv_wine_get_vulkan_driver( UINT version ) { return load_driver()->pwine_get_vulkan_driver( version ); @@ -1183,6 +1189,7 @@ static const struct user_driver_funcs lazy_load_driver = .pSetWindowRgn = loaderdrv_SetWindowRgn, .pMsgWaitForMultipleObjectsEx = nulldrv_MsgWaitForMultipleObjectsEx, .pScrollDC = nulldrv_ScrollDC, + .pUpdateLayeredWindow = loaderdrv_UpdateLayeredWindow, .pWindowMessage = nulldrv_WindowMessage, /* system parameters */ .pSystemParametersInfo = nulldrv_SystemParametersInfo, diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c index 72d11667ce9..d63085353e0 100644 --- a/dlls/win32u/gdiobj.c +++ b/dlls/win32u/gdiobj.c @@ -1198,6 +1198,7 @@ static struct unix_funcs unix_funcs = NtUserToUnicodeEx, NtUserUnregisterClass, NtUserUnregisterHotKey, + NtUserUpdateLayeredWindow, NtUserVkKeyScanEx, NtUserWindowFromPoint, diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec index cc1ee83167a..fce73d89692 100644 --- a/dlls/win32u/win32u.spec +++ b/dlls/win32u/win32u.spec @@ -1295,7 +1295,7 @@ @ stub NtUserUpdateDefaultDesktopThumbnail @ stub NtUserUpdateInputContext @ stub NtUserUpdateInstance -@ stub NtUserUpdateLayeredWindow +@ stdcall NtUserUpdateLayeredWindow(long long ptr ptr long ptr long ptr long ptr) @ stub NtUserUpdatePerUserSystemParameters @ stub NtUserUpdateWindowInputSinkHints @ stub NtUserUpdateWindowTrackingInfo diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h index 40ac0d05fef..871c8a2189b 100644 --- a/dlls/win32u/win32u_private.h +++ b/dlls/win32u/win32u_private.h @@ -247,6 +247,10 @@ struct unix_funcs BOOL (WINAPI *pNtUserUnregisterClass)( UNICODE_STRING *name, HINSTANCE instance, struct client_menu_name *client_menu_name ); BOOL (WINAPI *pNtUserUnregisterHotKey)( HWND hwnd, INT id ); + BOOL (WINAPI *pNtUserUpdateLayeredWindow)( HWND hwnd, HDC hdc_dst, const POINT *pts_dst, + const SIZE *size, HDC hdc_src, const POINT *pts_src, + COLORREF key, const BLENDFUNCTION *blend, + DWORD flags, const RECT *dirty ); WORD (WINAPI *pNtUserVkKeyScanEx)( WCHAR chr, HKL layout ); HWND (WINAPI *pNtUserWindowFromPoint)( LONG x, LONG y ); diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c index d21cc0e6887..ce60c46ff4c 100644 --- a/dlls/win32u/window.c +++ b/dlls/win32u/window.c @@ -1337,6 +1337,76 @@ BOOL WINAPI NtUserSetLayeredWindowAttributes( HWND hwnd, COLORREF key, BYTE alph return ret; } +/***************************************************************************** + * UpdateLayeredWindow (win32u.@) + */ +BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_dst, const SIZE *size, + HDC hdc_src, const POINT *pts_src, COLORREF key, + const BLENDFUNCTION *blend, DWORD flags, const RECT *dirty ) +{ + DWORD swp_flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW; + RECT window_rect, client_rect; + UPDATELAYEREDWINDOWINFO info; + SIZE offset; + + if (flags & ~(ULW_COLORKEY | ULW_ALPHA | ULW_OPAQUE | ULW_EX_NORESIZE) || + !(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_LAYERED) || + NtUserGetLayeredWindowAttributes( hwnd, NULL, NULL, NULL )) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + get_window_rects( hwnd, COORDS_PARENT, &window_rect, &client_rect, get_thread_dpi() ); + + if (pts_dst) + { + offset.cx = pts_dst->x - window_rect.left; + offset.cy = pts_dst->y - window_rect.top; + OffsetRect( &client_rect, offset.cx, offset.cy ); + OffsetRect( &window_rect, offset.cx, offset.cy ); + swp_flags &= ~SWP_NOMOVE; + } + if (size) + { + offset.cx = size->cx - (window_rect.right - window_rect.left); + offset.cy = size->cy - (window_rect.bottom - window_rect.top); + if (size->cx <= 0 || size->cy <= 0) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if ((flags & ULW_EX_NORESIZE) && (offset.cx || offset.cy)) + { + SetLastError( ERROR_INCORRECT_SIZE ); + return FALSE; + } + client_rect.right += offset.cx; + client_rect.bottom += offset.cy; + window_rect.right += offset.cx; + window_rect.bottom += offset.cy; + swp_flags &= ~SWP_NOSIZE; + } + + TRACE( "window %p win %s client %s\n", hwnd, + wine_dbgstr_rect(&window_rect), wine_dbgstr_rect(&client_rect) ); + + if (user_callbacks) + user_callbacks->set_window_pos( hwnd, 0, swp_flags, &window_rect, &client_rect, NULL ); + + info.cbSize = sizeof(info); + info.hdcDst = hdc_dst; + info.pptDst = pts_dst; + info.psize = size; + info.hdcSrc = hdc_src; + info.pptSrc = pts_src; + info.crKey = key; + info.pblend = blend; + info.dwFlags = flags; + info.prcDirty = dirty; + return user_driver->pUpdateLayeredWindow( hwnd, &info, &window_rect ); +} + /*********************************************************************** * list_children_from_point * diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c index 40b5ea2d4cf..8e4e250f8c5 100644 --- a/dlls/win32u/wrappers.c +++ b/dlls/win32u/wrappers.c @@ -1002,6 +1002,15 @@ BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id ) return unix_funcs->pNtUserUnregisterHotKey( hwnd, id ); } +BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_dst, const SIZE *size, + HDC hdc_src, const POINT *pts_src, COLORREF key, + const BLENDFUNCTION *blend, DWORD flags, const RECT *dirty ) +{ + if (!unix_funcs) return FALSE; + return unix_funcs->pNtUserUpdateLayeredWindow( hwnd, hdc_dst, pts_dst, size, hdc_src, pts_src, + key, blend, flags, dirty ); +} + WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout ) { if (!unix_funcs) return 0; diff --git a/include/ntuser.h b/include/ntuser.h index 82bf5f89b74..53fe88b5198 100644 --- a/include/ntuser.h +++ b/include/ntuser.h @@ -390,6 +390,9 @@ BOOL WINAPI NtUserUnhookWindowsHookEx( HHOOK handle ); BOOL WINAPI NtUserUnregisterClass( UNICODE_STRING *name, HINSTANCE instance, struct client_menu_name *client_menu_name ); BOOL WINAPI NtUserUnregisterHotKey( HWND hwnd, INT id ); +BOOL WINAPI NtUserUpdateLayeredWindow( HWND hwnd, HDC hdc_dst, const POINT *pts_dst, const SIZE *size, + HDC hdc_src, const POINT *pts_src, COLORREF key, + const BLENDFUNCTION *blend, DWORD flags, const RECT *dirty ); WORD WINAPI NtUserVkKeyScanEx( WCHAR chr, HKL layout ); DWORD WINAPI NtUserWaitForInputIdle( HANDLE process, DWORD timeout, BOOL wow ); HWND WINAPI NtUserWindowFromPoint( LONG x, LONG y );