Wine-Devel
Threads by month
- ----- 2026 -----
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 4 participants
- 84517 discussions
[PATCH v2 5/5] win32u: Move GetWindowContextHelpId implementation from user32.
by Huw Davies March 17, 2022
by Huw Davies March 17, 2022
March 17, 2022
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/win.c | 12 +-----------
dlls/win32u/window.c | 18 ++++++++++++++++++
include/ntuser.h | 1 +
3 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index 4d4199c67fc..22227c23280 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -2249,17 +2249,7 @@ BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
*/
DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
{
- DWORD retval;
- WND *wnd = WIN_GetPtr( hwnd );
- if (!wnd || wnd == WND_DESKTOP) return 0;
- if (wnd == WND_OTHER_PROCESS)
- {
- if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
- return 0;
- }
- retval = wnd->helpContext;
- WIN_ReleasePtr( wnd );
- return retval;
+ return NtUserCallHwnd( hwnd, NtUserGetWindowContextHelpId );
}
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index ab69096184c..e513a13b152 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3913,6 +3913,22 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info )
}
}
+/* see GetWindowContextHelpId */
+static DWORD get_window_context_help_id( HWND hwnd )
+{
+ DWORD retval;
+ WND *win = get_win_ptr( hwnd );
+ if (!win || win == WND_DESKTOP) return 0;
+ if (win == WND_OTHER_PROCESS)
+ {
+ if (is_window( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
+ return 0;
+ }
+ retval = win->helpContext;
+ release_win_ptr( win );
+ return retval;
+}
+
/***********************************************************************
* send_destroy_message
*/
@@ -4190,6 +4206,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
return get_dpi_for_window( hwnd );
case NtUserGetParent:
return HandleToUlong( get_parent( hwnd ));
+ case NtUserGetWindowContextHelpId:
+ return get_window_context_help_id( hwnd );
case NtUserGetWindowDpiAwarenessContext:
return (ULONG_PTR)get_window_dpi_awareness_context( hwnd );
case NtUserGetWindowTextLength:
diff --git a/include/ntuser.h b/include/ntuser.h
index 6526d190e28..7bcb91fcc25 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -147,6 +147,7 @@ enum
{
NtUserGetDpiForWindow,
NtUserGetParent,
+ NtUserGetWindowContextHelpId,
NtUserGetWindowDpiAwarenessContext,
NtUserGetWindowTextLength,
NtUserIsWindow,
--
2.23.0
1
0
[PATCH v2 4/5] win32u: Move NtUserShowWindow implementation from user32.
by Huw Davies March 17, 2022
by Huw Davies March 17, 2022
March 17, 2022
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/combo.c | 4 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 6 +-
dlls/user32/driver.c | 8 +-
dlls/user32/mdi.c | 12 +-
dlls/user32/message.c | 21 +-
dlls/user32/nonclient.c | 6 +-
dlls/user32/scroll.c | 2 +-
dlls/user32/user32.spec | 4 +-
dlls/user32/user_main.c | 1 -
dlls/user32/win.c | 10 +-
dlls/user32/win.h | 6 -
dlls/user32/winpos.c | 228 +---------------
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 2 +
dlls/win32u/input.c | 2 +-
dlls/win32u/message.c | 3 +
dlls/win32u/ntuser_private.h | 7 +-
dlls/win32u/win32u.spec | 4 +-
dlls/win32u/win32u_private.h | 4 +
dlls/win32u/window.c | 487 ++++++++++++++++++++++++++++++++++-
dlls/win32u/wrappers.c | 12 +
include/ntuser.h | 1 +
23 files changed, 542 insertions(+), 291 deletions(-)
diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index b375de5080c..d9123057295 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -1030,7 +1030,7 @@ static void CBRollUp( LPHEADCOMBO lphc, BOOL ok, BOOL bButton )
RECT rect;
lphc->wState &= ~CBF_DROPPED;
- ShowWindow( lphc->hWndLBox, SW_HIDE );
+ NtUserShowWindow( lphc->hWndLBox, SW_HIDE );
if(GetCapture() == lphc->hWndLBox)
{
@@ -1419,7 +1419,7 @@ static void CBResetPos(HEADCOMBO *combo, BOOL redraw)
if (combo->wState & CBF_DROPPED)
{
combo->wState &= ~CBF_DROPPED;
- ShowWindow(combo->hWndLBox, SW_HIDE);
+ NtUserShowWindow( combo->hWndLBox, SW_HIDE );
}
if (redraw && !(combo->wState & CBF_NOREDRAW))
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index 271644bb953..bd1928412e0 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -562,7 +562,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
}
else pWnd->flags |= WIN_NEEDS_SHOW_OWNEDPOPUP;
WIN_ReleasePtr( pWnd );
- ShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
+ NtUserShowWindow( hwnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE );
break;
}
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c
index f9d388d0104..a3efd5b6742 100644
--- a/dlls/user32/dialog.c
+++ b/dlls/user32/dialog.c
@@ -702,7 +702,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
if (template.style & WS_VISIBLE && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
{
- ShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL ); /* SW_SHOW doesn't always work */
}
return hwnd;
}
@@ -793,7 +793,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
if (bFirstEmpty)
{
/* ShowWindow the first time the queue goes empty */
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
bFirstEmpty = FALSE;
}
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
@@ -821,7 +821,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
if (bFirstEmpty && msg.message == WM_TIMER)
{
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
bFirstEmpty = FALSE;
}
}
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index ada0b8ca2f7..25ed33ff073 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -95,11 +95,6 @@ static void CDECL nulldrv_SetWindowText( HWND hwnd, LPCWSTR text )
{
}
-static UINT CDECL nulldrv_ShowWindow( HWND hwnd, INT cmd, RECT *rect, UINT swp )
-{
- return ~0; /* use default implementation */
-}
-
static LRESULT CDECL nulldrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
return -1;
@@ -184,7 +179,7 @@ static struct user_driver_funcs lazy_load_driver =
nulldrv_SetWindowIcon,
NULL,
nulldrv_SetWindowText,
- nulldrv_ShowWindow,
+ NULL,
nulldrv_SysCommand,
NULL,
NULL,
@@ -222,7 +217,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
SET_USER_FUNC(SetWindowIcon);
SET_USER_FUNC(SetWindowText);
- SET_USER_FUNC(ShowWindow);
SET_USER_FUNC(SysCommand);
SET_USER_FUNC(WindowPosChanging);
SET_USER_FUNC(WindowPosChanged);
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index 3d85487f808..19db8382bd0 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -514,13 +514,13 @@ static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo, BOOL activate
{
/* restore old MDI child */
SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 );
- ShowWindow( hwndPrev, SW_RESTORE );
+ NtUserShowWindow( hwndPrev, SW_RESTORE );
SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 );
/* activate new MDI child */
NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
/* maximize new MDI child */
- ShowWindow( hwndTo, SW_MAXIMIZE );
+ NtUserShowWindow( hwndTo, SW_MAXIMIZE );
}
/* activate new MDI child */
NtUserSetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
@@ -547,7 +547,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci,
MDI_SwitchActiveChild(ci, next, TRUE);
else
{
- ShowWindow(child, SW_HIDE);
+ NtUserShowWindow( child, SW_HIDE );
if (child == ci->hwndChildMaximized)
{
HWND frame = GetParent(client);
@@ -1133,7 +1133,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM
return 0;
case WM_MDIMAXIMIZE:
- ShowWindow( (HWND)wParam, SW_MAXIMIZE );
+ NtUserShowWindow( (HWND)wParam, SW_MAXIMIZE );
return 0;
case WM_MDINEXT: /* lParam != 0 means previous window */
@@ -1147,7 +1147,7 @@ LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM
}
case WM_MDIRESTORE:
- ShowWindow( (HWND)wParam, SW_SHOWNORMAL );
+ NtUserShowWindow( (HWND)wParam, SW_SHOWNORMAL );
return 0;
case WM_MDISETMENU:
@@ -1518,7 +1518,7 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
SendMessageW( hMaxChild, WM_SETREDRAW, FALSE, 0 );
MDI_RestoreFrameMenu( GetParent(client), hMaxChild );
- ShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
+ NtUserShowWindow( hMaxChild, SW_SHOWNOACTIVATE );
SendMessageW( hMaxChild, WM_SETREDRAW, TRUE, 0 );
}
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 0ba540d2e5d..2badec331c1 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -1857,21 +1857,12 @@ static void reply_message( struct received_message_info *info, LRESULT result, B
*/
LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
{
- switch(msg)
- {
- case WM_WINE_SHOWWINDOW:
- if (is_desktop_window( hwnd )) return 0;
- return ShowWindow( hwnd, wparam );
- default:
- {
- MSG m;
- m.hwnd = hwnd;
- m.message = msg;
- m.wParam = wparam;
- m.lParam = lparam;
- return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage );
- }
- }
+ MSG m;
+ m.hwnd = hwnd;
+ m.message = msg;
+ m.wParam = wparam;
+ m.lParam = lparam;
+ return NtUserCallOneParam( (UINT_PTR)&m, NtUserHandleInternalMessage );
}
/* since the WM_DDE_ACK response to a WM_DDE_EXECUTE message should contain the handle
diff --git a/dlls/user32/nonclient.c b/dlls/user32/nonclient.c
index 096674db5f7..a2a49fda27b 100644
--- a/dlls/user32/nonclient.c
+++ b/dlls/user32/nonclient.c
@@ -1557,19 +1557,19 @@ LRESULT NC_HandleSysCommand( HWND hwnd, WPARAM wParam, LPARAM lParam )
case SC_MINIMIZE:
ShowOwnedPopups(hwnd,FALSE);
- ShowWindow( hwnd, SW_MINIMIZE );
+ NtUserShowWindow( hwnd, SW_MINIMIZE );
break;
case SC_MAXIMIZE:
if (IsIconic(hwnd))
ShowOwnedPopups(hwnd,TRUE);
- ShowWindow( hwnd, SW_MAXIMIZE );
+ NtUserShowWindow( hwnd, SW_MAXIMIZE );
break;
case SC_RESTORE:
if (IsIconic(hwnd))
ShowOwnedPopups(hwnd,TRUE);
- ShowWindow( hwnd, SW_RESTORE );
+ NtUserShowWindow( hwnd, SW_RESTORE );
break;
case SC_CLOSE:
diff --git a/dlls/user32/scroll.c b/dlls/user32/scroll.c
index d666707299f..c042b72a344 100644
--- a/dlls/user32/scroll.c
+++ b/dlls/user32/scroll.c
@@ -1973,7 +1973,7 @@ static BOOL SCROLL_ShowScrollBar( HWND hwnd, INT nBar, BOOL fShowH, BOOL fShowV
switch(nBar)
{
case SB_CTL:
- ShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
+ NtUserShowWindow( hwnd, fShowH ? SW_SHOW : SW_HIDE );
return TRUE;
case SB_BOTH:
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index cb18d9415c9..36ec63c21d4 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -740,8 +740,8 @@
@ stdcall ShowOwnedPopups(long long)
@ stdcall ShowScrollBar(long long long)
@ stub ShowStartGlass
-@ stdcall ShowWindow(long long)
-@ stdcall ShowWindowAsync(long long)
+@ stdcall ShowWindow(long long) NtUserShowWindow
+@ stdcall ShowWindowAsync(long long) NtUserShowWindowAsync
@ stdcall ShutdownBlockReasonCreate(long wstr)
@ stdcall ShutdownBlockReasonDestroy(long)
# @ stub SoftModalMessageBox
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 15293d76c41..5a3db40c93c 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -166,7 +166,6 @@ static const struct user_callbacks user_funcs =
SendMessageW,
SendNotifyMessageW,
ShowCaret,
- ShowWindow,
WaitForInputIdle,
free_win_ptr,
MENU_IsMenuActive,
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index b0e6b33eb56..4d4199c67fc 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -1023,10 +1023,10 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
{
/* if the new window is maximized don't bother repainting */
SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
- ShowWindow( top_child, SW_SHOWNORMAL );
+ NtUserShowWindow( top_child, SW_SHOWNORMAL );
SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
}
- else ShowWindow( top_child, SW_SHOWNORMAL );
+ else NtUserShowWindow( top_child, SW_SHOWNORMAL );
}
}
}
@@ -1303,7 +1303,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
else if (cs->style & WS_MINIMIZE)
sw = SW_SHOWMINIMIZED;
- ShowWindow( hwnd, sw );
+ NtUserShowWindow( hwnd, sw );
if (cs->dwExStyle & WS_EX_MDICHILD)
{
SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
@@ -1399,7 +1399,7 @@ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR className,
BOOL WINAPI CloseWindow( HWND hwnd )
{
if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
- ShowWindow( hwnd, SW_MINIMIZE );
+ NtUserShowWindow( hwnd, SW_MINIMIZE );
return TRUE;
}
@@ -1410,7 +1410,7 @@ BOOL WINAPI CloseWindow( HWND hwnd )
BOOL WINAPI OpenIcon( HWND hwnd )
{
if (!IsIconic( hwnd )) return FALSE;
- ShowWindow( hwnd, SW_SHOWNORMAL );
+ NtUserShowWindow( hwnd, SW_SHOWNORMAL );
return TRUE;
}
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 89e91a255f9..79a57de6bb9 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -42,7 +42,6 @@ extern WND *WIN_GetPtr( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_GetFullHandle( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_IsCurrentProcess( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN;
-extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN;
extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN;
extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
@@ -94,9 +93,4 @@ static inline void mirror_rect( const RECT *window_rect, RECT *rect )
rect->right = width - tmp;
}
-static inline UINT win_get_flags( HWND hwnd )
-{
- return win_set_flags( hwnd, 0, 0 );
-}
-
#endif /* __WINE_WIN_H */
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 1951f887351..4ba0c47626d 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -67,7 +67,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
*/
void WINAPI SwitchToThisWindow( HWND hwnd, BOOL alt_tab )
{
- if (IsIconic( hwnd )) ShowWindow( hwnd, SW_RESTORE );
+ if (IsIconic( hwnd )) NtUserShowWindow( hwnd, SW_RESTORE );
else BringWindowToTop( hwnd );
}
@@ -799,228 +799,6 @@ UINT WINPOS_MinMaximize( HWND hwnd, UINT cmd, LPRECT rect )
}
-/***********************************************************************
- * show_window
- *
- * Implementation of ShowWindow and ShowWindowAsync.
- */
-static BOOL show_window( HWND hwnd, INT cmd )
-{
- WND *wndPtr;
- HWND parent;
- DPI_AWARENESS_CONTEXT context;
- LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- BOOL wasVisible = (style & WS_VISIBLE) != 0;
- BOOL showFlag = TRUE;
- RECT newPos = {0, 0, 0, 0};
- UINT new_swp, swp = 0;
-
- TRACE("hwnd=%p, cmd=%d, wasVisible %d\n", hwnd, cmd, wasVisible);
-
- context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
-
- switch(cmd)
- {
- case SW_HIDE:
- if (!wasVisible) goto done;
- showFlag = FALSE;
- swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
-
- case SW_SHOWMINNOACTIVE:
- case SW_MINIMIZE:
- case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
- swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- /* fall through */
- case SW_SHOWMINIMIZED:
- swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
- if ((style & WS_MINIMIZE) && wasVisible) goto done;
- break;
-
- case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
- if (!wasVisible) swp |= SWP_SHOWWINDOW;
- swp |= SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, SW_MAXIMIZE, &newPos );
- if ((style & WS_MAXIMIZE) && wasVisible) goto done;
- break;
-
- case SW_SHOWNA:
- swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOZORDER;
- break;
- case SW_SHOW:
- if (wasVisible) goto done;
- swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
- if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
-
- case SW_SHOWNOACTIVATE:
- swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- /* fall through */
- case SW_RESTORE:
- /* fall through */
- case SW_SHOWNORMAL: /* same as SW_NORMAL: */
- case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
- if (!wasVisible) swp |= SWP_SHOWWINDOW;
- if (style & (WS_MINIMIZE | WS_MAXIMIZE))
- {
- swp |= SWP_FRAMECHANGED;
- swp |= WINPOS_MinMaximize( hwnd, cmd, &newPos );
- }
- else
- {
- if (wasVisible) goto done;
- swp |= SWP_NOSIZE | SWP_NOMOVE;
- }
- if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
- break;
- default:
- goto done;
- }
-
- if ((showFlag != wasVisible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED))
- {
- SendMessageW( hwnd, WM_SHOWWINDOW, showFlag, 0 );
- if (!IsWindow( hwnd )) goto done;
- }
-
- if (IsRectEmpty( &newPos )) new_swp = swp;
- else if ((new_swp = USER_Driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0)
- {
- if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp;
- else if (IsIconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000))
- {
- OffsetRect( &newPos, -32000 - newPos.left, -32000 - newPos.top );
- new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
- }
- else new_swp = swp;
- }
- swp = new_swp;
-
- parent = NtUserGetAncestor( hwnd, GA_PARENT );
- if (parent && !IsWindowVisible( parent ) && !(swp & SWP_STATECHANGED))
- {
- /* if parent is not visible simply toggle WS_VISIBLE and return */
- if (showFlag) WIN_SetStyle( hwnd, WS_VISIBLE, 0 );
- else WIN_SetStyle( hwnd, 0, WS_VISIBLE );
- }
- else
- NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
- newPos.right - newPos.left, newPos.bottom - newPos.top, swp );
-
- if (cmd == SW_HIDE)
- {
- HWND hFocus;
-
- /* FIXME: This will cause the window to be activated irrespective
- * of whether it is owned by the same thread. Has to be done
- * asynchronously.
- */
-
- if (hwnd == GetActiveWindow())
- WINPOS_ActivateOtherWindow(hwnd);
-
- /* Revert focus to parent */
- hFocus = GetFocus();
- if (hwnd == hFocus)
- {
- HWND parent = NtUserGetAncestor(hwnd, GA_PARENT);
- if (parent == GetDesktopWindow()) parent = 0;
- NtUserSetFocus( parent );
- }
- goto done;
- }
-
- if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) goto done;
-
- if (wndPtr->flags & WIN_NEED_SIZE)
- {
- /* should happen only in CreateWindowEx() */
- int wParam = SIZE_RESTORED;
- RECT client;
- LPARAM lparam;
-
- WIN_GetRectangles( hwnd, COORDS_PARENT, NULL, &client );
- lparam = MAKELONG( client.right - client.left, client.bottom - client.top );
- wndPtr->flags &= ~WIN_NEED_SIZE;
- if (wndPtr->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
- else if (wndPtr->dwStyle & WS_MINIMIZE)
- {
- wParam = SIZE_MINIMIZED;
- lparam = 0;
- }
- WIN_ReleasePtr( wndPtr );
-
- SendMessageW( hwnd, WM_SIZE, wParam, lparam );
- SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top ));
- }
- else WIN_ReleasePtr( wndPtr );
-
- /* if previous state was minimized Windows sets focus to the window */
- if (style & WS_MINIMIZE)
- {
- NtUserSetFocus( hwnd );
- /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */
- if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE))
- SendMessageW( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 );
- }
-
-done:
- SetThreadDpiAwarenessContext( context );
- return wasVisible;
-}
-
-
-/***********************************************************************
- * ShowWindowAsync (USER32.@)
- *
- * doesn't wait; returns immediately.
- * used by threads to toggle windows in other (possibly hanging) threads
- */
-BOOL WINAPI ShowWindowAsync( HWND hwnd, INT cmd )
-{
- HWND full_handle;
-
- if (is_broadcast(hwnd))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
-
- if ((full_handle = WIN_IsCurrentThread( hwnd )))
- return show_window( full_handle, cmd );
-
- return SendNotifyMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
-}
-
-
-/***********************************************************************
- * ShowWindow (USER32.@)
- */
-BOOL WINAPI ShowWindow( HWND hwnd, INT cmd )
-{
- HWND full_handle;
-
- if (is_broadcast(hwnd))
- {
- SetLastError( ERROR_INVALID_PARAMETER );
- return FALSE;
- }
- if ((full_handle = WIN_IsCurrentThread( hwnd )))
- return show_window( full_handle, cmd );
-
- if ((cmd == SW_HIDE) && !(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
- return FALSE;
-
- if ((cmd == SW_SHOW) && (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE))
- return TRUE;
-
- return SendMessageW( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
-}
-
-
/***********************************************************************
* GetInternalWindowPos (USER32.@)
*/
@@ -1190,7 +968,7 @@ static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT f
wp.rcNormalPosition.bottom - wp.rcNormalPosition.top,
SWP_NOZORDER | SWP_NOACTIVATE );
- ShowWindow( hwnd, wndpl->showCmd );
+ NtUserShowWindow( hwnd, wndpl->showCmd );
if (IsIconic( hwnd ))
{
@@ -1237,7 +1015,7 @@ BOOL WINAPI AnimateWindow(HWND hwnd, DWORD dwTime, DWORD dwFlags)
return FALSE;
}
- ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
+ NtUserShowWindow( hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA) );
return TRUE;
}
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index 166c2009dbc..ec8162b0284 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -1202,6 +1202,7 @@ static const struct user_driver_funcs lazy_load_driver =
.pReleaseDC = nulldrv_ReleaseDC,
.pScrollDC = nulldrv_ScrollDC,
.pSetFocus = nulldrv_SetFocus,
+ .pShowWindow = nulldrv_ShowWindow,
.pUpdateLayeredWindow = loaderdrv_UpdateLayeredWindow,
.pWindowMessage = nulldrv_WindowMessage,
/* system parameters */
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 69607f0e3de..e47271e6108 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1210,6 +1210,8 @@ static struct unix_funcs unix_funcs =
NtUserSetWindowRgn,
NtUserSetWindowWord,
NtUserShowCursor,
+ NtUserShowWindow,
+ NtUserShowWindowAsync,
NtUserSystemParametersInfo,
NtUserSystemParametersInfoForDpi,
NtUserToUnicodeEx,
diff --git a/dlls/win32u/input.c b/dlls/win32u/input.c
index bc82d5e17a3..5cd2cdd0970 100644
--- a/dlls/win32u/input.c
+++ b/dlls/win32u/input.c
@@ -1162,7 +1162,7 @@ HWND get_active_window(void)
}
/* see GetFocus */
-static HWND get_focus(void)
+HWND get_focus(void)
{
GUITHREADINFO info;
info.cbSize = sizeof(info);
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index 690de6cdf8a..853182b6e94 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -46,6 +46,9 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
case WM_WINE_SETWINDOWPOS:
if (is_desktop_window( hwnd )) return 0;
return set_window_pos( (WINDOWPOS *)lparam, 0, 0 );
+ case WM_WINE_SHOWWINDOW:
+ if (is_desktop_window( hwnd )) return 0;
+ return NtUserShowWindow( hwnd, wparam );
case WM_WINE_SETPARENT:
if (is_desktop_window( hwnd )) return 0;
return HandleToUlong( NtUserSetParent( hwnd, UlongToHandle(wparam) ));
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index 51f17f63de5..49fd22ca140 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -42,7 +42,6 @@ struct user_callbacks
LRESULT (WINAPI *pSendMessageW)( HWND, UINT, WPARAM, LPARAM );
BOOL (WINAPI *pSendNotifyMessageW)( HWND, UINT, WPARAM, LPARAM );
BOOL (WINAPI *pShowCaret)( HWND hwnd );
- BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
void (CDECL *free_win_ptr)( struct tagWND *win );
HWND (CDECL *is_menu_active)(void);
@@ -278,6 +277,12 @@ HANDLE alloc_user_handle( struct user_object *ptr, unsigned int type ) DECLSPEC_
void *free_user_handle( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void *get_user_handle_ptr( HANDLE handle, unsigned int type ) DECLSPEC_HIDDEN;
void release_user_handle_ptr( void *ptr ) DECLSPEC_HIDDEN;
+UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN;
+
+static inline UINT win_get_flags( HWND hwnd )
+{
+ return win_set_flags( hwnd, 0, 0 );
+}
WND *get_win_ptr( HWND hwnd ) DECLSPEC_HIDDEN;
BOOL is_child( HWND parent, HWND child );
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index aacfebd1b15..68348db4033 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1261,8 +1261,8 @@
@ stdcall NtUserShowCursor(long)
@ stub NtUserShowScrollBar
@ stub NtUserShowSystemCursor
-@ stub NtUserShowWindow
-@ stub NtUserShowWindowAsync
+@ stdcall NtUserShowWindow(long long)
+@ stdcall NtUserShowWindowAsync(long long)
@ stub NtUserShutdownBlockReasonCreate
@ stub NtUserShutdownBlockReasonQuery
@ stub NtUserShutdownReasonDestroy
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 2e8a8e3da8e..361bec31ec8 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -258,6 +258,8 @@ struct unix_funcs
int (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw );
WORD (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval );
INT (WINAPI *pNtUserShowCursor)( BOOL show );
+ BOOL (WINAPI *pNtUserShowWindow)( HWND hwnd, INT cmd );
+ BOOL (WINAPI *pNtUserShowWindowAsync)( HWND hwnd, INT cmd );
BOOL (WINAPI *pNtUserSystemParametersInfo)( UINT action, UINT val, PVOID ptr, UINT winini );
BOOL (WINAPI *pNtUserSystemParametersInfoForDpi)( UINT action, UINT val, PVOID ptr,
UINT winini, UINT dpi );
@@ -311,6 +313,7 @@ extern BOOL unhook_windows_hook( INT id, HOOKPROC proc ) DECLSPEC_HIDDEN;
extern LONG global_key_state_counter DECLSPEC_HIDDEN;
extern HWND get_active_window(void) DECLSPEC_HIDDEN;
extern BOOL get_cursor_pos( POINT *pt ) DECLSPEC_HIDDEN;
+extern HWND get_focus(void) DECLSPEC_HIDDEN;
extern DWORD get_input_state(void) DECLSPEC_HIDDEN;
extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
@@ -353,6 +356,7 @@ struct tagWND;
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern LRESULT destroy_window( HWND hwnd ) DECLSPEC_HIDDEN;
+extern BOOL get_client_rect( HWND hwnd, RECT *rect ) DECLSPEC_HIDDEN;
extern HWND get_desktop_window(void) DECLSPEC_HIDDEN;
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index 1069ace0794..ab69096184c 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -916,6 +916,11 @@ BOOL is_iconic( HWND hwnd )
return (get_window_long( hwnd, GWL_STYLE ) & WS_MINIMIZE) != 0;
}
+static BOOL is_zoomed( HWND hwnd )
+{
+ return (get_window_long( hwnd, GWL_STYLE ) & WS_MAXIMIZE) != 0;
+}
+
static LONG_PTR get_window_long_size( HWND hwnd, INT offset, UINT size, BOOL ansi )
{
LONG_PTR retval = 0;
@@ -1655,7 +1660,7 @@ BOOL get_window_rect( HWND hwnd, RECT *rect, UINT dpi )
}
/* see GetClientRect */
-static BOOL get_client_rect( HWND hwnd, RECT *rect )
+BOOL get_client_rect( HWND hwnd, RECT *rect )
{
return get_window_rects( hwnd, COORDS_CLIENT, NULL, rect, get_thread_dpi() );
}
@@ -2174,14 +2179,6 @@ BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement )
return TRUE;
}
-/*****************************************************************************
- * NtUserShowWindow (win32u.@)
- */
-BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
-{
- return user_callbacks && user_callbacks->pShowWindow( hwnd, cmd );
-}
-
/*****************************************************************************
* NtUserBuildHwndList (win32u.@)
*/
@@ -3179,7 +3176,7 @@ BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async )
*
* Set the flags of a window and return the previous value.
*/
-static UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask )
+UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask )
{
WND *win = get_win_ptr( hwnd );
UINT ret;
@@ -3361,6 +3358,255 @@ static MINMAXINFO get_min_max_info( HWND hwnd )
return minmax;
}
+static POINT get_first_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
+ int width, int height )
+{
+ POINT ret;
+
+ if (mm->iArrange & ARW_STARTRIGHT)
+ ret.x = parent->right - mm->iHorzGap - width;
+ else
+ ret.x = parent->left + mm->iHorzGap;
+ if (mm->iArrange & ARW_STARTTOP)
+ ret.y = parent->top + mm->iVertGap;
+ else
+ ret.y = parent->bottom - mm->iVertGap - height;
+
+ return ret;
+}
+
+static void get_next_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
+ int width, int height, POINT *pos )
+{
+ BOOL next;
+
+ if (mm->iArrange & ARW_UP) /* == ARW_DOWN */
+ {
+ if (mm->iArrange & ARW_STARTTOP)
+ {
+ pos->y += height + mm->iVertGap;
+ if ((next = pos->y + height > parent->bottom))
+ pos->y = parent->top + mm->iVertGap;
+ }
+ else
+ {
+ pos->y -= height + mm->iVertGap;
+ if ((next = pos->y < parent->top))
+ pos->y = parent->bottom - mm->iVertGap - height;
+ }
+
+ if (next)
+ {
+ if (mm->iArrange & ARW_STARTRIGHT)
+ pos->x -= width + mm->iHorzGap;
+ else
+ pos->x += width + mm->iHorzGap;
+ }
+ }
+ else
+ {
+ if (mm->iArrange & ARW_STARTRIGHT)
+ {
+ pos->x -= width + mm->iHorzGap;
+ if ((next = pos->x < parent->left))
+ pos->x = parent->right - mm->iHorzGap - width;
+ }
+ else
+ {
+ pos->x += width + mm->iHorzGap;
+ if ((next = pos->x + width > parent->right))
+ pos->x = parent->left + mm->iHorzGap;
+ }
+
+ if (next)
+ {
+ if (mm->iArrange & ARW_STARTTOP)
+ pos->y += height + mm->iVertGap;
+ else
+ pos->y -= height + mm->iVertGap;
+ }
+ }
+}
+
+static POINT get_minimized_pos( HWND hwnd, POINT pt )
+{
+ RECT rect, parent_rect;
+ HWND parent, child;
+ HRGN hrgn, tmp;
+ MINIMIZEDMETRICS metrics;
+ int width, height;
+
+ parent = NtUserGetAncestor( hwnd, GA_PARENT );
+ if (parent == get_desktop_window())
+ {
+ MONITORINFO mon_info;
+ HMONITOR monitor = monitor_from_window( hwnd, MONITOR_DEFAULTTOPRIMARY, get_thread_dpi() );
+
+ mon_info.cbSize = sizeof( mon_info );
+ get_monitor_info( monitor, &mon_info );
+ parent_rect = mon_info.rcWork;
+ }
+ else get_client_rect( parent, &parent_rect );
+
+ if (pt.x >= parent_rect.left && (pt.x + get_system_metrics( SM_CXMINIMIZED ) < parent_rect.right) &&
+ pt.y >= parent_rect.top && (pt.y + get_system_metrics( SM_CYMINIMIZED ) < parent_rect.bottom))
+ return pt; /* The icon already has a suitable position */
+
+ width = get_system_metrics( SM_CXMINIMIZED );
+ height = get_system_metrics( SM_CYMINIMIZED );
+
+ metrics.cbSize = sizeof(metrics);
+ NtUserSystemParametersInfo( SPI_GETMINIMIZEDMETRICS, sizeof(metrics), &metrics, 0 );
+
+ /* Check if another icon already occupies this spot */
+ /* FIXME: this is completely inefficient */
+
+ hrgn = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ tmp = NtGdiCreateRectRgn( 0, 0, 0, 0 );
+ for (child = get_window_relative( parent, GW_CHILD );
+ child;
+ child = get_window_relative( child, GW_HWNDNEXT ))
+ {
+ if (child == hwnd) continue;
+ if ((get_window_long( child, GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != (WS_VISIBLE|WS_MINIMIZE))
+ continue;
+ if (get_window_rects( child, COORDS_PARENT, &rect, NULL, get_thread_dpi() ))
+ {
+ NtGdiSetRectRgn( tmp, rect.left, rect.top, rect.right, rect.bottom );
+ NtGdiCombineRgn( hrgn, hrgn, tmp, RGN_OR );
+ }
+ }
+ NtGdiDeleteObjectApp( tmp );
+
+ pt = get_first_minimized_child_pos( &parent_rect, &metrics, width, height );
+ for (;;)
+ {
+ set_rect( &rect, pt.x, pt.y, pt.x + width, pt.y + height );
+ if (!NtGdiRectInRegion( hrgn, &rect ))
+ break;
+
+ get_next_minimized_child_pos( &parent_rect, &metrics, width, height, &pt );
+ }
+
+ NtGdiDeleteObjectApp( hrgn );
+ return pt;
+}
+
+/***********************************************************************
+ * window_min_maximize
+ */
+static UINT window_min_maximize( HWND hwnd, UINT cmd, RECT *rect )
+{
+ UINT swp_flags = 0;
+ LONG old_style;
+ MINMAXINFO minmax;
+ WINDOWPLACEMENT wpl;
+
+ TRACE( "%p %u\n", hwnd, cmd );
+
+ wpl.length = sizeof(wpl);
+ get_window_placement( hwnd, &wpl );
+
+ if (call_hooks( WH_CBT, HCBT_MINMAX, (WPARAM)hwnd, cmd, TRUE ))
+ return SWP_NOSIZE | SWP_NOMOVE;
+
+ if (is_iconic( hwnd ))
+ {
+ switch (cmd)
+ {
+ case SW_SHOWMINNOACTIVE:
+ case SW_SHOWMINIMIZED:
+ case SW_FORCEMINIMIZE:
+ case SW_MINIMIZE:
+ wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
+
+ set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
+ wpl.ptMinPosition.x + get_system_metrics( SM_CXMINIMIZED ),
+ wpl.ptMinPosition.y + get_system_metrics( SM_CYMINIMIZED ));
+ return SWP_NOSIZE | SWP_NOMOVE;
+ }
+ if (!send_message( hwnd, WM_QUERYOPEN, 0, 0 )) return SWP_NOSIZE | SWP_NOMOVE;
+ swp_flags |= SWP_NOCOPYBITS;
+ }
+
+ switch( cmd )
+ {
+ case SW_SHOWMINNOACTIVE:
+ case SW_SHOWMINIMIZED:
+ case SW_FORCEMINIMIZE:
+ case SW_MINIMIZE:
+ if (is_zoomed( hwnd )) win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
+ else win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
+
+ if (get_focus() == hwnd)
+ {
+ if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD)
+ NtUserSetFocus( NtUserGetAncestor( hwnd, GA_PARENT ));
+ else
+ NtUserSetFocus( 0 );
+ }
+
+ old_style = set_window_style( hwnd, WS_MINIMIZE, WS_MAXIMIZE );
+
+ wpl.ptMinPosition = get_minimized_pos( hwnd, wpl.ptMinPosition );
+
+ if (!(old_style & WS_MINIMIZE)) swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, wpl.ptMinPosition.x, wpl.ptMinPosition.y,
+ wpl.ptMinPosition.x + get_system_metrics(SM_CXMINIMIZED),
+ wpl.ptMinPosition.y + get_system_metrics(SM_CYMINIMIZED) );
+ swp_flags |= SWP_NOCOPYBITS;
+ break;
+
+ case SW_MAXIMIZE:
+ old_style = get_window_long( hwnd, GWL_STYLE );
+ if ((old_style & WS_MAXIMIZE) && (old_style & WS_VISIBLE)) return SWP_NOSIZE | SWP_NOMOVE;
+
+ minmax = get_min_max_info( hwnd );
+
+ old_style = set_window_style( hwnd, WS_MAXIMIZE, WS_MINIMIZE );
+ if (old_style & WS_MINIMIZE)
+ win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
+
+ if (!(old_style & WS_MAXIMIZE)) swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxPosition.x + minmax.ptMaxSize.x,
+ minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
+ break;
+
+ case SW_SHOWNOACTIVATE:
+ win_set_flags( hwnd, 0, WIN_RESTORE_MAX );
+ /* fall through */
+ case SW_SHOWNORMAL:
+ case SW_RESTORE:
+ case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
+ old_style = set_window_style( hwnd, 0, WS_MINIMIZE | WS_MAXIMIZE );
+ if (old_style & WS_MINIMIZE)
+ {
+ if (win_get_flags( hwnd ) & WIN_RESTORE_MAX)
+ {
+ /* Restore to maximized position */
+ minmax = get_min_max_info( hwnd );
+ set_window_style( hwnd, WS_MAXIMIZE, 0 );
+ swp_flags |= SWP_STATECHANGED;
+ set_rect( rect, minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxPosition.x + minmax.ptMaxSize.x,
+ minmax.ptMaxPosition.y + minmax.ptMaxSize.y );
+ break;
+ }
+ }
+ else if (!(old_style & WS_MAXIMIZE)) break;
+
+ swp_flags |= SWP_STATECHANGED;
+
+ /* Restore to normal position */
+
+ *rect = wpl.rcNormalPosition;
+ break;
+ }
+
+ return swp_flags;
+}
+
/*******************************************************************
* update_window_state
*
@@ -3387,6 +3633,227 @@ void update_window_state( HWND hwnd )
set_thread_dpi_awareness_context( context );
}
+/***********************************************************************
+ * show_window
+ *
+ * Implementation of ShowWindow and ShowWindowAsync.
+ */
+static BOOL show_window( HWND hwnd, INT cmd )
+{
+ WND *win;
+ HWND parent;
+ DPI_AWARENESS_CONTEXT context;
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ BOOL was_visible = (style & WS_VISIBLE) != 0;
+ BOOL show_flag = TRUE;
+ RECT newPos = {0, 0, 0, 0};
+ UINT new_swp, swp = 0;
+
+ TRACE( "hwnd=%p, cmd=%d, was_visible %d\n", hwnd, cmd, was_visible );
+
+ context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
+
+ switch(cmd)
+ {
+ case SW_HIDE:
+ if (!was_visible) goto done;
+ show_flag = FALSE;
+ swp |= SWP_HIDEWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ case SW_SHOWMINNOACTIVE:
+ case SW_MINIMIZE:
+ case SW_FORCEMINIMIZE: /* FIXME: Does not work if thread is hung. */
+ swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ /* fall through */
+ case SW_SHOWMINIMIZED:
+ swp |= SWP_SHOWWINDOW | SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, cmd, &newPos );
+ if ((style & WS_MINIMIZE) && was_visible) goto done;
+ break;
+
+ case SW_SHOWMAXIMIZED: /* same as SW_MAXIMIZE */
+ if (!was_visible) swp |= SWP_SHOWWINDOW;
+ swp |= SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, SW_MAXIMIZE, &newPos );
+ if ((style & WS_MAXIMIZE) && was_visible) goto done;
+ break;
+
+ case SW_SHOWNA:
+ swp |= SWP_NOACTIVATE | SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOZORDER;
+ break;
+
+ case SW_SHOW:
+ if (was_visible) goto done;
+ swp |= SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE;
+ if (style & WS_CHILD) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ case SW_SHOWNOACTIVATE:
+ swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ /* fall through */
+ case SW_RESTORE:
+ /* fall through */
+ case SW_SHOWNORMAL: /* same as SW_NORMAL: */
+ case SW_SHOWDEFAULT: /* FIXME: should have its own handler */
+ if (!was_visible) swp |= SWP_SHOWWINDOW;
+ if (style & (WS_MINIMIZE | WS_MAXIMIZE))
+ {
+ swp |= SWP_FRAMECHANGED;
+ swp |= window_min_maximize( hwnd, cmd, &newPos );
+ }
+ else
+ {
+ if (was_visible) goto done;
+ swp |= SWP_NOSIZE | SWP_NOMOVE;
+ }
+ if (style & WS_CHILD && !(swp & SWP_STATECHANGED)) swp |= SWP_NOACTIVATE | SWP_NOZORDER;
+ break;
+
+ default:
+ goto done;
+ }
+
+ if ((show_flag != was_visible || cmd == SW_SHOWNA) && cmd != SW_SHOWMAXIMIZED && !(swp & SWP_STATECHANGED))
+ {
+ send_message( hwnd, WM_SHOWWINDOW, show_flag, 0 );
+ if (!is_window( hwnd )) goto done;
+ }
+
+ if (IsRectEmpty( &newPos )) new_swp = swp;
+ else if ((new_swp = user_driver->pShowWindow( hwnd, cmd, &newPos, swp )) == ~0)
+ {
+ if (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) new_swp = swp;
+ else if (is_iconic( hwnd ) && (newPos.left != -32000 || newPos.top != -32000))
+ {
+ offset_rect( &newPos, -32000 - newPos.left, -32000 - newPos.top );
+ new_swp = swp & ~(SWP_NOMOVE | SWP_NOCLIENTMOVE);
+ }
+ else new_swp = swp;
+ }
+ swp = new_swp;
+
+ parent = NtUserGetAncestor( hwnd, GA_PARENT );
+ if (parent && !is_window_visible( parent ) && !(swp & SWP_STATECHANGED))
+ {
+ /* if parent is not visible simply toggle WS_VISIBLE and return */
+ if (show_flag) set_window_style( hwnd, WS_VISIBLE, 0 );
+ else set_window_style( hwnd, 0, WS_VISIBLE );
+ }
+ else
+ NtUserSetWindowPos( hwnd, HWND_TOP, newPos.left, newPos.top,
+ newPos.right - newPos.left, newPos.bottom - newPos.top, swp );
+
+ if (cmd == SW_HIDE)
+ {
+ HWND hFocus;
+
+ /* FIXME: This will cause the window to be activated irrespective
+ * of whether it is owned by the same thread. Has to be done
+ * asynchronously.
+ */
+
+ if (hwnd == get_active_window()) activate_other_window( hwnd );
+
+ /* Revert focus to parent */
+ hFocus = get_focus();
+ if (hwnd == hFocus)
+ {
+ HWND parent = NtUserGetAncestor(hwnd, GA_PARENT);
+ if (parent == get_desktop_window()) parent = 0;
+ NtUserSetFocus(parent);
+ }
+ goto done;
+ }
+
+ if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) goto done;
+
+ if (win->flags & WIN_NEED_SIZE)
+ {
+ /* should happen only in CreateWindowEx() */
+ int wParam = SIZE_RESTORED;
+ RECT client;
+ LPARAM lparam;
+
+ get_window_rects( hwnd, COORDS_PARENT, NULL, &client, get_thread_dpi() );
+ lparam = MAKELONG( client.right - client.left, client.bottom - client.top );
+ win->flags &= ~WIN_NEED_SIZE;
+ if (win->dwStyle & WS_MAXIMIZE) wParam = SIZE_MAXIMIZED;
+ else if (win->dwStyle & WS_MINIMIZE)
+ {
+ wParam = SIZE_MINIMIZED;
+ lparam = 0;
+ }
+ release_win_ptr( win );
+
+ send_message( hwnd, WM_SIZE, wParam, lparam );
+ send_message( hwnd, WM_MOVE, 0, MAKELONG( client.left, client.top ));
+ }
+ else release_win_ptr( win );
+
+ /* if previous state was minimized Windows sets focus to the window */
+ if (style & WS_MINIMIZE)
+ {
+ NtUserSetFocus( hwnd );
+ /* Send a WM_ACTIVATE message for a top level window, even if the window is already active */
+ if (NtUserGetAncestor( hwnd, GA_ROOT ) == hwnd && !(swp & SWP_NOACTIVATE))
+ send_message( hwnd, WM_ACTIVATE, WA_ACTIVE, 0 );
+ }
+
+done:
+ set_thread_dpi_awareness_context( context );
+ return was_visible;
+}
+
+/***********************************************************************
+ * NtUserShowWindowAsync (win32u.@)
+ *
+ * doesn't wait; returns immediately.
+ * used by threads to toggle windows in other (possibly hanging) threads
+ */
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd )
+{
+ HWND full_handle;
+
+ if (is_broadcast(hwnd))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+
+ if ((full_handle = is_current_thread_window( hwnd )))
+ return show_window( full_handle, cmd );
+
+ return NtUserMessageCall( hwnd, WM_WINE_SHOWWINDOW, cmd, 0, 0,
+ FNID_SENDNOTIFYMESSAGE, FALSE );
+}
+
+/***********************************************************************
+ * NtUserShowWindow (win32u.@)
+ */
+BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
+{
+ HWND full_handle;
+
+ if (is_broadcast(hwnd))
+ {
+ SetLastError( ERROR_INVALID_PARAMETER );
+ return FALSE;
+ }
+ if ((full_handle = is_current_thread_window( hwnd )))
+ return show_window( full_handle, cmd );
+
+ if ((cmd == SW_HIDE) && !(get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE))
+ return FALSE;
+
+ if ((cmd == SW_SHOW) && (get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE))
+ return TRUE;
+
+ return send_message( hwnd, WM_WINE_SHOWWINDOW, cmd, 0 );
+}
+
/*******************************************************************
* NtUserFlashWindowEx (win32u.@)
*/
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index da1957c8c88..6cb3a6896b5 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1075,6 +1075,18 @@ INT WINAPI NtUserShowCursor( BOOL show )
return unix_funcs->pNtUserShowCursor( show );
}
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserShowWindowAsync( hwnd, cmd );
+}
+
+BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserShowWindow( hwnd, cmd );
+}
+
BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, PVOID ptr, UINT winini )
{
if (!unix_funcs) return FALSE;
diff --git a/include/ntuser.h b/include/ntuser.h
index 274c0cf31c9..6526d190e28 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -422,6 +422,7 @@ HWINEVENTHOOK WINAPI NtUserSetWinEventHook( DWORD event_min, DWORD event_max, HM
DWORD pid, DWORD tid, DWORD flags );
INT WINAPI NtUserShowCursor( BOOL show );
BOOL WINAPI NtUserShowWindow( HWND hwnd, INT cmd );
+BOOL WINAPI NtUserShowWindowAsync( HWND hwnd, INT cmd );
BOOL WINAPI NtUserSystemParametersInfo( UINT action, UINT val, void *ptr, UINT winini );
BOOL WINAPI NtUserSystemParametersInfoForDpi( UINT action, UINT val, PVOID ptr, UINT winini, UINT dpi );
INT WINAPI NtUserToUnicodeEx( UINT virt, UINT scan, const BYTE *state,
--
2.23.0
1
0
[PATCH v2 3/5] win32u: Move get_min_max_info implementation from user32.
by Huw Davies March 17, 2022
by Huw Davies March 17, 2022
March 17, 2022
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/user_main.c | 1 +
dlls/user32/winpos.c | 92 ++--------------------------------
dlls/win32u/menu.c | 6 +++
dlls/win32u/ntuser_private.h | 1 +
dlls/win32u/win32u_private.h | 3 ++
dlls/win32u/window.c | 97 ++++++++++++++++++++++++++++++++++++
include/ntuser.h | 1 +
7 files changed, 113 insertions(+), 88 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index bc0dec6b579..15293d76c41 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -154,6 +154,7 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs =
{
+ AdjustWindowRectEx,
CopyImage,
DestroyCaret,
DestroyMenu,
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index b3e8aff3cfa..1951f887351 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -48,8 +48,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(win);
(((style) & WS_THICKFRAME) && \
!(((style) & (WS_DLGFRAME|WS_BORDER)) == WS_DLGFRAME))
-#define EMPTYPOINT(pt) ((pt).x == -1 && (pt).y == -1)
-
#define ON_LEFT_BORDER(hit) \
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
#define ON_RIGHT_BORDER(hit) \
@@ -548,94 +546,12 @@ static BOOL get_work_rect( HWND hwnd, RECT *rect )
*/
MINMAXINFO WINPOS_GetMinMaxInfo( HWND hwnd )
{
- DPI_AWARENESS_CONTEXT context;
- RECT rc_work, rc_primary;
- MINMAXINFO MinMax;
- INT xinc, yinc;
- LONG style = GetWindowLongW( hwnd, GWL_STYLE );
- LONG adjustedStyle;
- LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
- RECT rc;
- WND *win;
-
- context = SetThreadDpiAwarenessContext( GetWindowDpiAwarenessContext( hwnd ));
-
- /* Compute default values */
-
- GetWindowRect(hwnd, &rc);
- MinMax.ptReserved.x = rc.left;
- MinMax.ptReserved.y = rc.top;
-
- if ((style & WS_CAPTION) == WS_CAPTION)
- adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
- else
- adjustedStyle = style;
-
- GetClientRect(NtUserGetAncestor(hwnd,GA_PARENT), &rc);
- AdjustWindowRectEx(&rc, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle);
-
- xinc = -rc.left;
- yinc = -rc.top;
-
- MinMax.ptMaxSize.x = rc.right - rc.left;
- MinMax.ptMaxSize.y = rc.bottom - rc.top;
- if (style & (WS_DLGFRAME | WS_BORDER))
- {
- MinMax.ptMinTrackSize.x = GetSystemMetrics(SM_CXMINTRACK);
- MinMax.ptMinTrackSize.y = GetSystemMetrics(SM_CYMINTRACK);
- }
- else
- {
- MinMax.ptMinTrackSize.x = 2 * xinc;
- MinMax.ptMinTrackSize.y = 2 * yinc;
- }
- MinMax.ptMaxTrackSize.x = GetSystemMetrics(SM_CXMAXTRACK);
- MinMax.ptMaxTrackSize.y = GetSystemMetrics(SM_CYMAXTRACK);
- MinMax.ptMaxPosition.x = -xinc;
- MinMax.ptMaxPosition.y = -yinc;
-
- if ((win = WIN_GetPtr( hwnd )) && win != WND_DESKTOP && win != WND_OTHER_PROCESS)
- {
- if (!EMPTYPOINT(win->max_pos)) MinMax.ptMaxPosition = win->max_pos;
- WIN_ReleasePtr( win );
- }
-
- SendMessageW( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&MinMax );
-
- /* if the app didn't change the values, adapt them for the current monitor */
-
- if (get_work_rect( hwnd, &rc_work ))
- {
- rc_primary = get_primary_monitor_rect();
- if (MinMax.ptMaxSize.x == (rc_primary.right - rc_primary.left) + 2 * xinc &&
- MinMax.ptMaxSize.y == (rc_primary.bottom - rc_primary.top) + 2 * yinc)
- {
- MinMax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
- MinMax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
- }
- if (MinMax.ptMaxPosition.x == -xinc && MinMax.ptMaxPosition.y == -yinc)
- {
- MinMax.ptMaxPosition.x = rc_work.left - xinc;
- MinMax.ptMaxPosition.y = rc_work.top - yinc;
- }
- }
-
- /* Some sanity checks */
-
- TRACE("%d %d / %d %d / %d %d / %d %d\n",
- MinMax.ptMaxSize.x, MinMax.ptMaxSize.y,
- MinMax.ptMaxPosition.x, MinMax.ptMaxPosition.y,
- MinMax.ptMaxTrackSize.x, MinMax.ptMaxTrackSize.y,
- MinMax.ptMinTrackSize.x, MinMax.ptMinTrackSize.y);
- MinMax.ptMaxTrackSize.x = max( MinMax.ptMaxTrackSize.x,
- MinMax.ptMinTrackSize.x );
- MinMax.ptMaxTrackSize.y = max( MinMax.ptMaxTrackSize.y,
- MinMax.ptMinTrackSize.y );
-
- SetThreadDpiAwarenessContext( context );
- return MinMax;
+ MINMAXINFO info;
+ NtUserCallHwndParam( hwnd, (UINT_PTR)&info, NtUserGetMinMaxInfo );
+ return info;
}
+
static POINT get_first_minimized_child_pos( const RECT *parent, const MINIMIZEDMETRICS *mm,
int width, int height )
{
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index 1e8410d347e..921c5752536 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -106,6 +106,12 @@ BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle )
return TRUE;
}
+/* see GetMenu */
+HMENU get_menu( HWND hwnd )
+{
+ return UlongToHandle( get_window_long( hwnd, GWLP_ID ));
+}
+
/**********************************************************************
* NtUserDestroyMenu (win32u.@)
*/
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index b3cafe791df..51f17f63de5 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -30,6 +30,7 @@ struct tagWND;
struct user_callbacks
{
+ BOOL (WINAPI *pAdjustWindowRectEx)( RECT *, DWORD, BOOL, DWORD );
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
BOOL (WINAPI *pDestroyCaret)(void);
BOOL (WINAPI *pDestroyMenu)( HMENU );
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 83b0e093a20..2e8a8e3da8e 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -316,6 +316,9 @@ extern BOOL WINAPI release_capture(void) DECLSPEC_HIDDEN;
extern BOOL set_capture_window( HWND hwnd, UINT gui_flags, HWND *prev_ret ) DECLSPEC_HIDDEN;
extern BOOL set_foreground_window( HWND hwnd, BOOL mouse ) DECLSPEC_HIDDEN;
+/* menu.c */
+extern HMENU get_menu( HWND hwnd ) DECLSPEC_HIDDEN;
+
/* message.c */
extern BOOL kill_system_timer( HWND hwnd, UINT_PTR id ) DECLSPEC_HIDDEN;
extern LRESULT post_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index f8d147b785c..1069ace0794 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3267,6 +3267,100 @@ static void send_parent_notify( HWND hwnd, UINT msg )
}
}
+/*******************************************************************
+ * get_min_max_info
+ *
+ * Get the minimized and maximized information for a window.
+ */
+static MINMAXINFO get_min_max_info( HWND hwnd )
+{
+ LONG style = get_window_long( hwnd, GWL_STYLE );
+ LONG exstyle = get_window_long( hwnd, GWL_EXSTYLE );
+ DPI_AWARENESS_CONTEXT context;
+ RECT rc_work, rc_primary;
+ LONG adjusted_style;
+ MINMAXINFO minmax;
+ INT xinc, yinc;
+ RECT rc;
+ WND *win;
+
+ context = set_thread_dpi_awareness_context( get_window_dpi_awareness_context( hwnd ));
+
+ /* Compute default values */
+
+ get_window_rect( hwnd, &rc, get_thread_dpi() );
+ minmax.ptReserved.x = rc.left;
+ minmax.ptReserved.y = rc.top;
+
+ if ((style & WS_CAPTION) == WS_CAPTION)
+ adjusted_style = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */
+ else
+ adjusted_style = style;
+
+ get_client_rect( NtUserGetAncestor( hwnd, GA_PARENT ), &rc );
+ if (user_callbacks)
+ user_callbacks->pAdjustWindowRectEx( &rc, adjusted_style,
+ (style & WS_POPUP) && get_menu( hwnd ), exstyle);
+
+ xinc = -rc.left;
+ yinc = -rc.top;
+
+ minmax.ptMaxSize.x = rc.right - rc.left;
+ minmax.ptMaxSize.y = rc.bottom - rc.top;
+ if (style & (WS_DLGFRAME | WS_BORDER))
+ {
+ minmax.ptMinTrackSize.x = get_system_metrics( SM_CXMINTRACK );
+ minmax.ptMinTrackSize.y = get_system_metrics( SM_CYMINTRACK );
+ }
+ else
+ {
+ minmax.ptMinTrackSize.x = 2 * xinc;
+ minmax.ptMinTrackSize.y = 2 * yinc;
+ }
+ minmax.ptMaxTrackSize.x = get_system_metrics( SM_CXMAXTRACK );
+ minmax.ptMaxTrackSize.y = get_system_metrics( SM_CYMAXTRACK );
+ minmax.ptMaxPosition.x = -xinc;
+ minmax.ptMaxPosition.y = -yinc;
+
+ if ((win = get_win_ptr( hwnd )) && win != WND_DESKTOP && win != WND_OTHER_PROCESS)
+ {
+ if (!empty_point( win->max_pos )) minmax.ptMaxPosition = win->max_pos;
+ release_win_ptr( win );
+ }
+
+ send_message( hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax );
+
+ /* if the app didn't change the values, adapt them for the current monitor */
+
+ if (get_work_rect( hwnd, &rc_work ))
+ {
+ rc_primary = get_primary_monitor_rect( get_thread_dpi() );
+ if (minmax.ptMaxSize.x == (rc_primary.right - rc_primary.left) + 2 * xinc &&
+ minmax.ptMaxSize.y == (rc_primary.bottom - rc_primary.top) + 2 * yinc)
+ {
+ minmax.ptMaxSize.x = (rc_work.right - rc_work.left) + 2 * xinc;
+ minmax.ptMaxSize.y = (rc_work.bottom - rc_work.top) + 2 * yinc;
+ }
+ if (minmax.ptMaxPosition.x == -xinc && minmax.ptMaxPosition.y == -yinc)
+ {
+ minmax.ptMaxPosition.x = rc_work.left - xinc;
+ minmax.ptMaxPosition.y = rc_work.top - yinc;
+ }
+ }
+
+ TRACE( "%d %d / %d %d / %d %d / %d %d\n",
+ minmax.ptMaxSize.x, minmax.ptMaxSize.y,
+ minmax.ptMaxPosition.x, minmax.ptMaxPosition.y,
+ minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y,
+ minmax.ptMinTrackSize.x, minmax.ptMinTrackSize.y );
+
+ minmax.ptMaxTrackSize.x = max( minmax.ptMaxTrackSize.x, minmax.ptMinTrackSize.x );
+ minmax.ptMaxTrackSize.y = max( minmax.ptMaxTrackSize.y, minmax.ptMinTrackSize.y );
+
+ set_thread_dpi_awareness_context( context );
+ return minmax;
+}
+
/*******************************************************************
* update_window_state
*
@@ -3671,6 +3765,9 @@ ULONG_PTR WINAPI NtUserCallHwndParam( HWND hwnd, DWORD_PTR param, DWORD code )
return get_class_word( hwnd, param );
case NtUserGetClientRect:
return get_client_rect( hwnd, (RECT *)param );
+ case NtUserGetMinMaxInfo:
+ *(MINMAXINFO *)param = get_min_max_info( hwnd );
+ return 0;
case NtUserGetWindowInfo:
return get_window_info( hwnd, (WINDOWINFO *)param );
case NtUserGetWindowLongA:
diff --git a/include/ntuser.h b/include/ntuser.h
index de958caa735..274c0cf31c9 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -167,6 +167,7 @@ enum
NtUserGetClassLongPtrW,
NtUserGetClassWord,
NtUserGetClientRect,
+ NtUserGetMinMaxInfo,
NtUserGetWindowInfo,
NtUserGetWindowLongA,
NtUserGetWindowLongW,
--
2.23.0
1
0
[PATCH v2 2/5] win32u: Move NtUserDestroyWindow implementation from user32.
by Huw Davies March 17, 2022
by Huw Davies March 17, 2022
March 17, 2022
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/clipboard.c | 23 ---
dlls/user32/combo.c | 2 +-
dlls/user32/dde_misc.c | 6 +-
dlls/user32/dde_server.c | 2 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 4 +-
dlls/user32/driver.c | 7 +-
dlls/user32/mdi.c | 2 +-
dlls/user32/menu.c | 8 +-
dlls/user32/message.c | 2 -
dlls/user32/msgbox.c | 70 ++++----
dlls/user32/painting.c | 12 --
dlls/user32/user32.spec | 2 +-
dlls/user32/user_main.c | 10 ++
dlls/user32/win.c | 248 +--------------------------
dlls/user32/win.h | 1 -
dlls/win32u/clipboard.c | 25 +++
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 1 +
dlls/win32u/message.c | 2 +
dlls/win32u/ntuser_private.h | 4 +
dlls/win32u/sysparams.c | 18 +-
dlls/win32u/win32u.spec | 2 +-
dlls/win32u/win32u_private.h | 6 +
dlls/win32u/window.c | 315 +++++++++++++++++++++++++++++++++++
dlls/win32u/wrappers.c | 6 +
include/ntuser.h | 4 +-
27 files changed, 440 insertions(+), 345 deletions(-)
diff --git a/dlls/user32/clipboard.c b/dlls/user32/clipboard.c
index 1a69421ea17..b45ddf9c7c0 100644
--- a/dlls/user32/clipboard.c
+++ b/dlls/user32/clipboard.c
@@ -616,29 +616,6 @@ static HANDLE render_synthesized_format( UINT format, UINT from )
return data;
}
-/**************************************************************************
- * CLIPBOARD_ReleaseOwner
- */
-void CLIPBOARD_ReleaseOwner( HWND hwnd )
-{
- HWND viewer = 0, owner = 0;
-
- SendMessageW( hwnd, WM_RENDERALLFORMATS, 0, 0 );
-
- SERVER_START_REQ( release_clipboard )
- {
- req->owner = wine_server_user_handle( hwnd );
- if (!wine_server_call( req ))
- {
- viewer = wine_server_ptr_handle( reply->viewer );
- owner = wine_server_ptr_handle( reply->owner );
- }
- }
- SERVER_END_REQ;
-
- if (viewer) SendNotifyMessageW( viewer, WM_DRAWCLIPBOARD, (WPARAM)owner, 0 );
-}
-
/**************************************************************************
* RegisterClipboardFormatW (USER32.@)
diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index 77cb24be064..b375de5080c 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -173,7 +173,7 @@ static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
TRACE("[%p]: freeing storage\n", lphc->self);
if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
- DestroyWindow( lphc->hWndLBox );
+ NtUserDestroyWindow( lphc->hWndLBox );
SetWindowLongPtrW( lphc->self, 0, 0 );
HeapFree( GetProcessHeap(), 0, lphc );
diff --git a/dlls/user32/dde_misc.c b/dlls/user32/dde_misc.c
index 41181d099cc..7bc1656432e 100644
--- a/dlls/user32/dde_misc.c
+++ b/dlls/user32/dde_misc.c
@@ -1158,7 +1158,7 @@ BOOL WINAPI DdeUninitialize(DWORD idInst)
*/
WDML_FreeAllHSZ(pInstance);
- DestroyWindow(pInstance->hwndEvent);
+ NtUserDestroyWindow( pInstance->hwndEvent );
/* OK now delete the instance handle itself */
@@ -1711,7 +1711,7 @@ void WDML_RemoveServer(WDML_INSTANCE* pInstance, HSZ hszService, HSZ hszTopic)
pPrev->next = pServer->next;
}
- DestroyWindow(pServer->hwndServer);
+ NtUserDestroyWindow(pServer->hwndServer);
WDML_DecHSZ(pInstance, pServer->hszServiceSpec);
WDML_DecHSZ(pInstance, pServer->hszService);
@@ -2105,7 +2105,7 @@ void WDML_RemoveConv(WDML_CONV* pRef, WDML_SIDE side)
hWnd = (side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer;
SetWindowLongPtrW(hWnd, GWL_WDML_CONVERSATION, 0);
- DestroyWindow((side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer);
+ NtUserDestroyWindow((side == WDML_CLIENT_SIDE) ? pRef->hwndClient : pRef->hwndServer);
WDML_DecHSZ(pRef->instance, pRef->hszService);
WDML_DecHSZ(pRef->instance, pRef->hszTopic);
diff --git a/dlls/user32/dde_server.c b/dlls/user32/dde_server.c
index 3867e0f014b..26494b835e5 100644
--- a/dlls/user32/dde_server.c
+++ b/dlls/user32/dde_server.c
@@ -360,7 +360,7 @@ static WDML_CONV* WDML_CreateServerConv(WDML_INSTANCE* pInstance, HWND hwndClien
}
else
{
- DestroyWindow(hwndServerConv);
+ NtUserDestroyWindow(hwndServerConv);
}
return pConv;
}
diff --git a/dlls/user32/defwnd.c b/dlls/user32/defwnd.c
index f78236cb194..271644bb953 100644
--- a/dlls/user32/defwnd.c
+++ b/dlls/user32/defwnd.c
@@ -400,7 +400,7 @@ static LRESULT DEFWND_DefWinProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPa
return 0;
case WM_CLOSE:
- DestroyWindow( hwnd );
+ NtUserDestroyWindow( hwnd );
return 0;
case WM_MOUSEACTIVATE:
diff --git a/dlls/user32/dialog.c b/dlls/user32/dialog.c
index e6e5b91587c..f9d388d0104 100644
--- a/dlls/user32/dialog.c
+++ b/dlls/user32/dialog.c
@@ -707,7 +707,7 @@ static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
return hwnd;
}
if (disabled_owner) EnableWindow( disabled_owner, TRUE );
- if( IsWindow(hwnd) ) DestroyWindow( hwnd );
+ if (IsWindow(hwnd)) NtUserDestroyWindow( hwnd );
return 0;
}
@@ -827,7 +827,7 @@ INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
}
}
retval = dlgInfo->idResult;
- DestroyWindow( hwnd );
+ NtUserDestroyWindow( hwnd );
return retval;
}
diff --git a/dlls/user32/driver.c b/dlls/user32/driver.c
index 72ea5ad17bd..ada0b8ca2f7 100644
--- a/dlls/user32/driver.c
+++ b/dlls/user32/driver.c
@@ -79,10 +79,6 @@ static BOOL CDECL nulldrv_CreateWindow( HWND hwnd )
return TRUE;
}
-static void CDECL nulldrv_DestroyWindow( HWND hwnd )
-{
-}
-
static DWORD CDECL nulldrv_MsgWaitForMultipleObjectsEx( DWORD count, const HANDLE *handles, DWORD timeout,
DWORD mask, DWORD flags )
{
@@ -174,7 +170,7 @@ static struct user_driver_funcs lazy_load_driver =
/* windowing functions */
NULL,
loaderdrv_CreateWindow,
- nulldrv_DestroyWindow,
+ NULL,
NULL,
NULL,
nulldrv_MsgWaitForMultipleObjectsEx,
@@ -223,7 +219,6 @@ void CDECL __wine_set_user_driver( const struct user_driver_funcs *funcs, UINT v
SET_USER_FUNC(SetCursorPos);
SET_USER_FUNC(UpdateClipboard);
SET_USER_FUNC(CreateWindow);
- SET_USER_FUNC(DestroyWindow);
SET_USER_FUNC(MsgWaitForMultipleObjectsEx);
SET_USER_FUNC(SetWindowIcon);
SET_USER_FUNC(SetWindowText);
diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c
index 6bab3e96adf..3d85487f808 100644
--- a/dlls/user32/mdi.c
+++ b/dlls/user32/mdi.c
@@ -580,7 +580,7 @@ static LRESULT MDIDestroyChild( HWND client, MDICLIENTINFO *ci,
{
SendMessageW(client, WM_MDIREFRESHMENU, 0, 0);
MDI_PostUpdate(GetParent(child), ci, SB_BOTH+1);
- DestroyWindow(child);
+ NtUserDestroyWindow(child);
}
TRACE("child destroyed - %p\n", child);
diff --git a/dlls/user32/menu.c b/dlls/user32/menu.c
index 1d680009747..113e6103cd9 100644
--- a/dlls/user32/menu.c
+++ b/dlls/user32/menu.c
@@ -2333,7 +2333,7 @@ static void MENU_HideSubPopups( HWND hwndOwner, HMENU hmenu,
if (!(submenu = MENU_GetMenu( hsubmenu ))) return;
MENU_HideSubPopups( hwndOwner, hsubmenu, FALSE, wFlags );
MENU_SelectItem( hwndOwner, hsubmenu, NO_SELECTED_ITEM, sendMenuSelect, 0 );
- DestroyWindow( submenu->hWnd );
+ NtUserDestroyWindow( submenu->hWnd );
submenu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY))
@@ -3319,7 +3319,7 @@ static BOOL MENU_TrackMenu( HMENU hmenu, UINT wFlags, INT x, INT y,
if (menu && (menu->wFlags & MF_POPUP))
{
- DestroyWindow( menu->hWnd );
+ NtUserDestroyWindow( menu->hWnd );
menu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY))
@@ -3531,7 +3531,7 @@ BOOL WINAPI TrackPopupMenuEx( HMENU hMenu, UINT wFlags, INT x, INT y,
if (menu->hWnd)
{
- DestroyWindow( menu->hWnd );
+ NtUserDestroyWindow( menu->hWnd );
menu->hWnd = 0;
if (!(wFlags & TPM_NONOTIFY))
@@ -4269,7 +4269,7 @@ BOOL WINAPI DestroyMenu( HMENU hMenu )
/* DestroyMenu should not destroy system menu popup owner */
if ((lppop->wFlags & (MF_POPUP | MF_SYSMENU)) == MF_POPUP && lppop->hWnd)
{
- DestroyWindow( lppop->hWnd );
+ NtUserDestroyWindow( lppop->hWnd );
lppop->hWnd = 0;
}
diff --git a/dlls/user32/message.c b/dlls/user32/message.c
index 365f703c56e..0ba540d2e5d 100644
--- a/dlls/user32/message.c
+++ b/dlls/user32/message.c
@@ -1859,8 +1859,6 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
{
switch(msg)
{
- case WM_WINE_DESTROYWINDOW:
- return WIN_DestroyWindow( hwnd );
case WM_WINE_SHOWWINDOW:
if (is_desktop_window( hwnd )) return 0;
return ShowWindow( hwnd, wparam );
diff --git a/dlls/user32/msgbox.c b/dlls/user32/msgbox.c
index 195bab2384b..c74d33092f0 100644
--- a/dlls/user32/msgbox.c
+++ b/dlls/user32/msgbox.c
@@ -116,57 +116,57 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb)
hItem = 0;
switch(lpmb->dwStyle & MB_TYPEMASK) {
case MB_OK:
- DestroyWindow(GetDlgItem(hwnd, IDCANCEL));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
/* fall through */
case MB_OKCANCEL:
hItem = GetDlgItem(hwnd, IDOK);
- DestroyWindow(GetDlgItem(hwnd, IDABORT));
- DestroyWindow(GetDlgItem(hwnd, IDRETRY));
- DestroyWindow(GetDlgItem(hwnd, IDIGNORE));
- DestroyWindow(GetDlgItem(hwnd, IDYES));
- DestroyWindow(GetDlgItem(hwnd, IDNO));
- DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
- DestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
break;
case MB_ABORTRETRYIGNORE:
hItem = GetDlgItem(hwnd, IDABORT);
- DestroyWindow(GetDlgItem(hwnd, IDOK));
- DestroyWindow(GetDlgItem(hwnd, IDCANCEL));
- DestroyWindow(GetDlgItem(hwnd, IDYES));
- DestroyWindow(GetDlgItem(hwnd, IDNO));
- DestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
- DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break;
case MB_YESNO:
- DestroyWindow(GetDlgItem(hwnd, IDCANCEL));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCANCEL));
/* fall through */
case MB_YESNOCANCEL:
hItem = GetDlgItem(hwnd, IDYES);
- DestroyWindow(GetDlgItem(hwnd, IDOK));
- DestroyWindow(GetDlgItem(hwnd, IDABORT));
- DestroyWindow(GetDlgItem(hwnd, IDRETRY));
- DestroyWindow(GetDlgItem(hwnd, IDIGNORE));
- DestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
- DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break;
case MB_RETRYCANCEL:
hItem = GetDlgItem(hwnd, IDRETRY);
- DestroyWindow(GetDlgItem(hwnd, IDOK));
- DestroyWindow(GetDlgItem(hwnd, IDABORT));
- DestroyWindow(GetDlgItem(hwnd, IDIGNORE));
- DestroyWindow(GetDlgItem(hwnd, IDYES));
- DestroyWindow(GetDlgItem(hwnd, IDNO));
- DestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
- DestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDCONTINUE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDTRYAGAIN));
break;
case MB_CANCELTRYCONTINUE:
hItem = GetDlgItem(hwnd, IDCANCEL);
- DestroyWindow(GetDlgItem(hwnd, IDOK));
- DestroyWindow(GetDlgItem(hwnd, IDABORT));
- DestroyWindow(GetDlgItem(hwnd, IDIGNORE));
- DestroyWindow(GetDlgItem(hwnd, IDYES));
- DestroyWindow(GetDlgItem(hwnd, IDNO));
- DestroyWindow(GetDlgItem(hwnd, IDRETRY));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDOK));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDABORT));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDIGNORE));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDYES));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDNO));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDRETRY));
}
if (hItem) SetWindowLongW(hItem, GWL_STYLE, GetWindowLongW(hItem, GWL_STYLE) | WS_GROUP);
@@ -202,7 +202,7 @@ static void MSGBOX_OnInit(HWND hwnd, LPMSGBOXPARAMSW lpmb)
/* Remove Help button unless MB_HELP supplied */
if (!(lpmb->dwStyle & MB_HELP)) {
- DestroyWindow(GetDlgItem(hwnd, IDHELP));
+ NtUserDestroyWindow(GetDlgItem(hwnd, IDHELP));
}
/* Position everything */
diff --git a/dlls/user32/painting.c b/dlls/user32/painting.c
index 8722cb68f12..ee9d23b1f71 100644
--- a/dlls/user32/painting.c
+++ b/dlls/user32/painting.c
@@ -35,18 +35,6 @@
WINE_DEFAULT_DEBUG_CHANNEL(win);
-/***********************************************************************
- * free_dce
- *
- * Free a class or window DCE.
- */
-void free_dce( struct dce *dce, HWND hwnd )
-{
- /* FIXME: move callers to win32u */
- NtUserCallTwoParam( (UINT_PTR)dce, HandleToUlong(hwnd), NtUserFreeDCE );
-}
-
-
/***********************************************************************
* invalidate_dce
*
diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 7c27d9400db..cb18d9415c9 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -161,7 +161,7 @@
@ stdcall DestroyIcon(long)
@ stdcall DestroyMenu(long)
# @ stub DestroyReasons
-@ stdcall DestroyWindow(long)
+@ stdcall DestroyWindow(long) NtUserDestroyWindow
# @ stub DeviceEventWorker
@ stdcall DialogBoxIndirectParamA(long ptr long ptr long)
@ stdcall DialogBoxIndirectParamAorW(long ptr long ptr long long)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index ff9b469dae6..bc0dec6b579 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -140,6 +140,11 @@ static void CDECL notify_ime( HWND hwnd, UINT param )
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
}
+void WINAPI unregister_imm( HWND hwnd )
+{
+ imm_unregister_window( hwnd );
+}
+
static void CDECL free_win_ptr( WND *win )
{
HeapFree( GetProcessHeap(), 0, win->text );
@@ -150,7 +155,9 @@ static void CDECL free_win_ptr( WND *win )
static const struct user_callbacks user_funcs =
{
CopyImage,
+ DestroyCaret,
DestroyMenu,
+ EndMenu,
HideCaret,
PostMessageW,
SendInput,
@@ -161,12 +168,14 @@ static const struct user_callbacks user_funcs =
ShowWindow,
WaitForInputIdle,
free_win_ptr,
+ MENU_IsMenuActive,
notify_ime,
register_builtin_classes,
MSG_SendInternalMessageTimeout,
SCROLL_SetStandardScrollPainted,
(void *)__wine_set_user_driver,
set_window_pos,
+ unregister_imm,
};
static void WINAPI User32CallFreeIcon( ULONG *param, ULONG size )
@@ -227,6 +236,7 @@ static void thread_detach(void)
struct user_thread_info *thread_info = get_user_thread_info();
exiting_thread_id = GetCurrentThreadId();
+ NtUserCallNoParam( NtUserExitingThread );
WDML_NotifyThreadDetach();
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index b57d6bd7566..b0e6b33eb56 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -558,38 +558,6 @@ HWND WIN_GetFullHandle( HWND hwnd )
}
-/***********************************************************************
- * WIN_SetOwner
- *
- * Change the owner of a window.
- */
-static HWND WIN_SetOwner( HWND hwnd, HWND owner )
-{
- WND *win = WIN_GetPtr( hwnd );
- HWND ret = 0;
-
- if (!win || win == WND_DESKTOP) return 0;
- if (win == WND_OTHER_PROCESS)
- {
- if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
- return 0;
- }
- SERVER_START_REQ( set_window_owner )
- {
- req->handle = wine_server_user_handle( hwnd );
- req->owner = wine_server_user_handle( owner );
- if (!wine_server_call( req ))
- {
- win->owner = wine_server_ptr_handle( reply->full_owner );
- ret = wine_server_ptr_handle( reply->prev_owner );
- }
- }
- SERVER_END_REQ;
- WIN_ReleasePtr( win );
- return ret;
-}
-
-
/***********************************************************************
* WIN_SetStyle
*
@@ -739,87 +707,6 @@ other_process:
}
-/***********************************************************************
- * WIN_DestroyWindow
- *
- * Destroy storage associated to a window. "Internals" p.358
- */
-LRESULT WIN_DestroyWindow( HWND hwnd )
-{
- WND *wndPtr;
- HWND *list;
- HMENU menu = 0, sys_menu;
- struct window_surface *surface;
-
- TRACE("%p\n", hwnd );
-
- /* destroy default IME window */
- if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)
- {
- TRACE("unregister IME window for %p\n", hwnd);
- imm_unregister_window( hwnd );
- }
-
- /* free child windows */
- if ((list = WIN_ListChildren( hwnd )))
- {
- int i;
- for (i = 0; list[i]; i++)
- {
- if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
- else SendNotifyMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
- }
- HeapFree( GetProcessHeap(), 0, list );
- }
-
- /* Unlink now so we won't bother with the children later on */
- SERVER_START_REQ( set_parent )
- {
- req->handle = wine_server_user_handle( hwnd );
- req->parent = 0;
- wine_server_call( req );
- }
- SERVER_END_REQ;
-
- /*
- * Send the WM_NCDESTROY to the window being destroyed.
- */
- SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
-
- /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
-
- /* free resources associated with the window */
-
- if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
- if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
- menu = (HMENU)wndPtr->wIDmenu;
- sys_menu = wndPtr->hSysMenu;
- free_dce( wndPtr->dce, hwnd );
- wndPtr->dce = NULL;
- HeapFree( GetProcessHeap(), 0, wndPtr->text );
- wndPtr->text = NULL;
- HeapFree( GetProcessHeap(), 0, wndPtr->pScroll );
- wndPtr->pScroll = NULL;
- DestroyIcon( wndPtr->hIconSmall2 );
- surface = wndPtr->surface;
- wndPtr->surface = NULL;
- WIN_ReleasePtr( wndPtr );
-
- if (menu) DestroyMenu( menu );
- if (sys_menu) DestroyMenu( sys_menu );
- if (surface)
- {
- register_window_surface( surface, NULL );
- window_surface_release( surface );
- }
-
- USER_Driver->pDestroyWindow( hwnd );
-
- free_window_handle( hwnd );
- return 0;
-}
-
-
/***********************************************************************
* WIN_FixCoordinates
*
@@ -1435,7 +1322,7 @@ HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module,
return hwnd;
failed:
- WIN_DestroyWindow( hwnd );
+ NtUserCallHwnd( hwnd, NtUserDestroyWindowHandle );
SetThreadDpiAwarenessContext( context );
return 0;
}
@@ -1506,139 +1393,6 @@ HWND WINAPI DECLSPEC_HOTPATCH CreateWindowExW( DWORD exStyle, LPCWSTR className,
}
-/***********************************************************************
- * WIN_SendDestroyMsg
- */
-static void WIN_SendDestroyMsg( HWND hwnd )
-{
- GUITHREADINFO info;
-
- info.cbSize = sizeof(info);
- if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ))
- {
- if (hwnd == info.hwndCaret) DestroyCaret();
- if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
- }
-
- if (hwnd == NtUserGetClipboardOwner()) CLIPBOARD_ReleaseOwner( hwnd );
-
- /*
- * Send the WM_DESTROY to the window.
- */
- SendMessageW( hwnd, WM_DESTROY, 0, 0);
-
- /*
- * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
- * make sure that the window still exists when we come back.
- */
- if (IsWindow(hwnd))
- {
- HWND* pWndArray;
- int i;
-
- if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
-
- for (i = 0; pWndArray[i]; i++)
- {
- if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
- }
- HeapFree( GetProcessHeap(), 0, pWndArray );
- }
- else
- WARN("\tdestroyed itself while in WM_DESTROY!\n");
-}
-
-
-/***********************************************************************
- * DestroyWindow (USER32.@)
- */
-BOOL WINAPI DestroyWindow( HWND hwnd )
-{
- BOOL is_child;
-
- if (!(hwnd = WIN_IsCurrentThread( hwnd )) || is_desktop_window( hwnd ))
- {
- SetLastError( ERROR_ACCESS_DENIED );
- return FALSE;
- }
-
- TRACE("(%p)\n", hwnd);
-
- /* Call hooks */
-
- if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
-
- if (MENU_IsMenuActive() == hwnd)
- EndMenu();
-
- is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
-
- if (is_child)
- {
- if (!USER_IsExitingThread( GetCurrentThreadId() ))
- send_parent_notify( hwnd, WM_DESTROY );
- }
- else if (!GetWindow( hwnd, GW_OWNER ))
- {
- HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
- /* FIXME: clean up palette - see "Internals" p.352 */
- }
-
- if (!IsWindow(hwnd)) return TRUE;
-
- /* Hide the window */
- if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
- {
- /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
- if (is_child)
- ShowWindow( hwnd, SW_HIDE );
- else
- NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
- SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
- }
-
- if (!IsWindow(hwnd)) return TRUE;
-
- /* Recursively destroy owned windows */
-
- if (!is_child)
- {
- for (;;)
- {
- int i;
- BOOL got_one = FALSE;
- HWND *list = WIN_ListChildren( GetDesktopWindow() );
- if (list)
- {
- for (i = 0; list[i]; i++)
- {
- if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
- if (WIN_IsCurrentThread( list[i] ))
- {
- DestroyWindow( list[i] );
- got_one = TRUE;
- continue;
- }
- WIN_SetOwner( list[i], 0 );
- }
- HeapFree( GetProcessHeap(), 0, list );
- }
- if (!got_one) break;
- }
- }
-
- /* Send destroy messages */
-
- WIN_SendDestroyMsg( hwnd );
- if (!IsWindow( hwnd )) return TRUE;
-
- /* Destroy the window storage */
-
- WIN_DestroyWindow( hwnd );
- return TRUE;
-}
-
-
/***********************************************************************
* CloseWindow (USER32.@)
*/
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 3e6885ab090..89e91a255f9 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -45,7 +45,6 @@ extern HWND WIN_IsCurrentThread( HWND hwnd ) DECLSPEC_HIDDEN;
extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_HIDDEN;
extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN;
extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN;
-extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/clipboard.c b/dlls/win32u/clipboard.c
index e132f981344..585a2aae631 100644
--- a/dlls/win32u/clipboard.c
+++ b/dlls/win32u/clipboard.c
@@ -288,3 +288,28 @@ BOOL WINAPI NtUserRemoveClipboardFormatListener( HWND hwnd )
SERVER_END_REQ;
return ret;
}
+
+/**************************************************************************
+ * release_clipboard_owner
+ */
+void release_clipboard_owner( HWND hwnd )
+{
+ HWND viewer = 0, owner = 0;
+
+ send_message( hwnd, WM_RENDERALLFORMATS, 0, 0 );
+
+ SERVER_START_REQ( release_clipboard )
+ {
+ req->owner = wine_server_user_handle( hwnd );
+ if (!wine_server_call( req ))
+ {
+ viewer = wine_server_ptr_handle( reply->viewer );
+ owner = wine_server_ptr_handle( reply->owner );
+ }
+ }
+ SERVER_END_REQ;
+
+ if (viewer)
+ NtUserMessageCall( viewer, WM_DRAWCLIPBOARD, (WPARAM)owner, 0,
+ 0, FNID_SENDNOTIFYMESSAGE, FALSE );
+}
diff --git a/dlls/win32u/driver.c b/dlls/win32u/driver.c
index afe44e1c4a3..166c2009dbc 100644
--- a/dlls/win32u/driver.c
+++ b/dlls/win32u/driver.c
@@ -1190,6 +1190,7 @@ static const struct user_driver_funcs lazy_load_driver =
.pUpdateDisplayDevices = loaderdrv_UpdateDisplayDevices,
/* windowing functions */
.pCreateDesktopWindow = loaderdrv_CreateDesktopWindow,
+ .pDestroyWindow = nulldrv_DestroyWindow,
.pFlashWindowEx = loaderdrv_FlashWindowEx,
.pGetDC = loaderdrv_GetDC,
.pSetCapture = nulldrv_SetCapture,
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index adb162ab7ff..69607f0e3de 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1162,6 +1162,7 @@ static struct unix_funcs unix_funcs =
NtUserCountClipboardFormats,
NtUserDeferWindowPosAndBand,
NtUserDestroyCursor,
+ NtUserDestroyWindow,
NtUserDrawIconEx,
NtUserEndDeferWindowPosEx,
NtUserEndPaint,
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c
index d00178e6aa4..690de6cdf8a 100644
--- a/dlls/win32u/message.c
+++ b/dlls/win32u/message.c
@@ -41,6 +41,8 @@ LRESULT handle_internal_message( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lpar
{
switch(msg)
{
+ case WM_WINE_DESTROYWINDOW:
+ return destroy_window( hwnd );
case WM_WINE_SETWINDOWPOS:
if (is_desktop_window( hwnd )) return 0;
return set_window_pos( (WINDOWPOS *)lparam, 0, 0 );
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index aa9b45b1542..b3cafe791df 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -31,7 +31,9 @@ struct tagWND;
struct user_callbacks
{
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
+ BOOL (WINAPI *pDestroyCaret)(void);
BOOL (WINAPI *pDestroyMenu)( HMENU );
+ BOOL (WINAPI *pEndMenu)(void);
BOOL (WINAPI *pHideCaret)( HWND hwnd );
BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM );
UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size );
@@ -42,6 +44,7 @@ struct user_callbacks
BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
void (CDECL *free_win_ptr)( struct tagWND *win );
+ HWND (CDECL *is_menu_active)(void);
void (CDECL *notify_ime)( HWND hwnd, UINT param );
void (CDECL *register_builtin_classes)(void);
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
@@ -50,6 +53,7 @@ struct user_callbacks
BOOL (CDECL *set_window_pos)( HWND hwnd, HWND insert_after, UINT swp_flags,
const RECT *window_rect, const RECT *client_rect,
const RECT *valid_rects );
+ void (WINAPI *unregister_imm)( HWND hwnd );
};
#define WM_SYSTIMER 0x0118
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index d9ddfe3400e..0166b64c76a 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -4591,6 +4591,16 @@ static BOOL message_beep( UINT i )
return TRUE;
}
+static DWORD exiting_thread_id;
+
+/**********************************************************************
+ * is_exiting_thread
+ */
+BOOL is_exiting_thread( DWORD tid )
+{
+ return tid == exiting_thread_id;
+}
+
static void thread_detach(void)
{
struct user_thread_info *thread_info = get_user_thread_info();
@@ -4602,6 +4612,8 @@ static void thread_detach(void)
destroy_thread_windows();
NtClose( thread_info->server_queue );
+
+ exiting_thread_id = 0;
}
/***********************************************************************
@@ -4618,6 +4630,9 @@ ULONG_PTR WINAPI NtUserCallNoParam( ULONG code )
case NtUserReleaseCapture:
return release_capture();
/* temporary exports */
+ case NtUserExitingThread:
+ exiting_thread_id = GetCurrentThreadId();
+ return 0;
case NtUserThreadDetach:
thread_detach();
return 0;
@@ -4724,9 +4739,6 @@ ULONG_PTR WINAPI NtUserCallTwoParam( ULONG_PTR arg1, ULONG_PTR arg2, ULONG code
return HandleToUlong( alloc_user_handle( (struct user_object *)arg1, arg2 ));
case NtUserAllocWinProc:
return (UINT_PTR)alloc_winproc( (WNDPROC)arg1, arg2 );
- case NtUserFreeDCE:
- free_dce( (struct dce *)arg1, UlongToHandle(arg2) );
- return 0;
case NtUserFreeHandle:
return (UINT_PTR)free_user_handle( UlongToHandle(arg1), arg2 );
case NtUserGetHandlePtr:
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 96d8d4833b0..aacfebd1b15 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -834,7 +834,7 @@
@ stub NtUserDestroyInputContext
@ stub NtUserDestroyMenu
@ stub NtUserDestroyPalmRejectionDelayZone
-@ stub NtUserDestroyWindow
+@ stdcall NtUserDestroyWindow(long)
@ stub NtUserDisableImmersiveOwner
@ stub NtUserDisableProcessWindowFiltering
@ stub NtUserDisableThreadIme
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 516f4540315..83b0e093a20 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -199,6 +199,7 @@ struct unix_funcs
INT x, INT y, INT cx, INT cy,
UINT flags, UINT unk1, UINT unk2 );
BOOL (WINAPI *pNtUserDestroyCursor)( HCURSOR cursor, ULONG arg );
+ BOOL (WINAPI *pNtUserDestroyWindow)( HWND hwnd );
BOOL (WINAPI *pNtUserDrawIconEx)( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
BOOL (WINAPI *pNtUserEndDeferWindowPosEx)( HDWP hdwp, BOOL async );
@@ -286,6 +287,9 @@ struct unix_funcs
struct window_surface *surface );
};
+/* clipboard.c */
+extern void release_clipboard_owner( HWND hwnd ) DECLSPEC_HIDDEN;
+
/* cursoricon.c */
extern HICON alloc_cursoricon_handle( BOOL is_icon ) DECLSPEC_HIDDEN;
extern BOOL get_clip_cursor( RECT *rect ) DECLSPEC_HIDDEN;
@@ -327,6 +331,7 @@ extern UINT get_system_dpi(void) DECLSPEC_HIDDEN;
extern int get_system_metrics( int index ) DECLSPEC_HIDDEN;
extern UINT get_thread_dpi(void) DECLSPEC_HIDDEN;
extern RECT get_virtual_screen_rect( UINT dpi ) DECLSPEC_HIDDEN;
+extern BOOL is_exiting_thread( DWORD tid ) DECLSPEC_HIDDEN;
extern POINT map_dpi_point( POINT pt, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN;
extern RECT map_dpi_rect( RECT rect, UINT dpi_from, UINT dpi_to ) DECLSPEC_HIDDEN;
extern HMONITOR monitor_from_point( POINT pt, DWORD flags, UINT dpi ) DECLSPEC_HIDDEN;
@@ -344,6 +349,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
struct tagWND;
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
+extern LRESULT destroy_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND get_desktop_window(void) DECLSPEC_HIDDEN;
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index a28b6ae9ebf..f8d147b785c 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -3174,6 +3174,99 @@ BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async )
return TRUE;
}
+/***********************************************************************
+ * win_set_flags
+ *
+ * Set the flags of a window and return the previous value.
+ */
+static UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask )
+{
+ WND *win = get_win_ptr( hwnd );
+ UINT ret;
+
+ if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return 0;
+ ret = win->flags;
+ win->flags = (ret & ~clear_mask) | set_mask;
+ release_win_ptr( win );
+ return ret;
+}
+
+/*******************************************************************
+ * can_activate_window
+ *
+ * Check if we can activate the specified window.
+ */
+static BOOL can_activate_window( HWND hwnd )
+{
+ LONG style;
+
+ if (!hwnd) return FALSE;
+ style = get_window_long( hwnd, GWL_STYLE );
+ if (!(style & WS_VISIBLE)) return FALSE;
+ if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
+ return !(style & WS_DISABLED);
+}
+
+/*******************************************************************
+ * activate_other_window
+ *
+ * Activates window other than hwnd.
+ */
+static void activate_other_window( HWND hwnd )
+{
+ HWND hwnd_to, fg;
+
+ if ((get_window_long( hwnd, GWL_STYLE ) & WS_POPUP) &&
+ (hwnd_to = get_window_relative( hwnd, GW_OWNER )))
+ {
+ hwnd_to = NtUserGetAncestor( hwnd_to, GA_ROOT );
+ if (can_activate_window( hwnd_to )) goto done;
+ }
+
+ hwnd_to = hwnd;
+ for (;;)
+ {
+ if (!(hwnd_to = get_window_relative( hwnd_to, GW_HWNDNEXT ))) break;
+ if (can_activate_window( hwnd_to )) goto done;
+ }
+
+ hwnd_to = get_window_relative( get_desktop_window(), GW_CHILD );
+ for (;;)
+ {
+ if (hwnd_to == hwnd)
+ {
+ hwnd_to = 0;
+ break;
+ }
+ if (can_activate_window( hwnd_to )) goto done;
+ if (!(hwnd_to = get_window_relative( hwnd_to, GW_HWNDNEXT ))) break;
+ }
+
+ done:
+ fg = NtUserGetForegroundWindow();
+ TRACE( "win = %p fg = %p\n", hwnd_to, fg );
+ if (!fg || hwnd == fg)
+ {
+ if (set_foreground_window( hwnd_to, FALSE )) return;
+ }
+ if (NtUserSetActiveWindow( hwnd_to )) NtUserSetActiveWindow( 0 );
+}
+
+/*******************************************************************
+ * send_parent_notify
+ */
+static void send_parent_notify( HWND hwnd, UINT msg )
+{
+ if ((get_window_long( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
+ !(get_window_long( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
+ {
+ HWND parent = get_parent( hwnd );
+ if (parent && parent != get_desktop_window())
+ send_message( parent, WM_PARENTNOTIFY,
+ MAKEWPARAM( msg, get_window_long( hwnd, GWLP_ID )), (LPARAM)hwnd );
+ }
+}
+
/*******************************************************************
* update_window_state
*
@@ -3260,6 +3353,226 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info )
}
/***********************************************************************
+ * send_destroy_message
+ */
+static void send_destroy_message( HWND hwnd )
+{
+ GUITHREADINFO info;
+
+ info.cbSize = sizeof(info);
+ if (NtUserGetGUIThreadInfo( GetCurrentThreadId(), &info ))
+ {
+ if (hwnd == info.hwndCaret && user_callbacks) user_callbacks->pDestroyCaret();
+ if (hwnd == info.hwndActive) activate_other_window( hwnd );
+ }
+
+ if (hwnd == NtUserGetClipboardOwner()) release_clipboard_owner( hwnd );
+
+ send_message( hwnd, WM_DESTROY, 0, 0);
+
+ /*
+ * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
+ * make sure that the window still exists when we come back.
+ */
+ if (is_window(hwnd))
+ {
+ HWND *children;
+ int i;
+
+ if (!(children = list_window_children( 0, hwnd, NULL, 0 ))) return;
+
+ for (i = 0; children[i]; i++)
+ {
+ if (is_window( children[i] )) send_destroy_message( children[i] );
+ }
+ free( children );
+ }
+ else
+ WARN( "\tdestroyed itself while in WM_DESTROY!\n" );
+}
+
+/***********************************************************************
+ * free_window_handle
+ *
+ * Free a window handle.
+ */
+static void free_window_handle( HWND hwnd )
+{
+ WND *win;
+
+ TRACE( "\n" );
+
+ if ((win = get_user_handle_ptr( hwnd, NTUSER_OBJ_WINDOW )) && win != OBJ_OTHER_PROCESS)
+ {
+ SERVER_START_REQ( destroy_window )
+ {
+ req->handle = wine_server_user_handle( hwnd );
+ wine_server_call( req );
+ set_user_handle_ptr( hwnd, NULL );
+ }
+ SERVER_END_REQ;
+ user_unlock();
+ if (user_callbacks) user_callbacks->free_win_ptr( win );
+ }
+}
+
+/***********************************************************************
+ * destroy_window
+ */
+LRESULT destroy_window( HWND hwnd )
+{
+ struct window_surface *surface;
+ HMENU menu = 0, sys_menu;
+ WND *win;
+ HWND *children;
+
+ TRACE( "%p\n", hwnd );
+
+ /* destroy default IME window */
+ if (win_set_flags( hwnd, 0, WIN_HAS_IME_WIN ) & WIN_HAS_IME_WIN)
+ {
+ TRACE("unregister IME window for %p\n", hwnd);
+ if (user_callbacks) user_callbacks->unregister_imm( hwnd );
+ }
+
+ /* free child windows */
+ if ((children = list_window_children( 0, hwnd, NULL, 0 )))
+ {
+ int i;
+ for (i = 0; children[i]; i++)
+ {
+ if (is_current_thread_window( children[i] ))
+ destroy_window( children[i] );
+ else
+ NtUserMessageCall( children[i], WM_WINE_DESTROYWINDOW, 0, 0,
+ 0, FNID_SENDNOTIFYMESSAGE, FALSE );
+ }
+ free( children );
+ }
+
+ /* Unlink now so we won't bother with the children later on */
+ SERVER_START_REQ( set_parent )
+ {
+ req->handle = wine_server_user_handle( hwnd );
+ req->parent = 0;
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+
+ send_message( hwnd, WM_NCDESTROY, 0, 0 );
+
+ /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
+
+ /* free resources associated with the window */
+
+ if (!(win = get_win_ptr( hwnd )) || win == WND_OTHER_PROCESS) return 0;
+ if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
+ menu = (HMENU)win->wIDmenu;
+ sys_menu = win->hSysMenu;
+ free_dce( win->dce, hwnd );
+ win->dce = NULL;
+ NtUserDestroyCursor( win->hIconSmall2, 0 );
+ surface = win->surface;
+ win->surface = NULL;
+ release_win_ptr( win );
+
+ NtUserDestroyMenu( menu );
+ NtUserDestroyMenu( sys_menu );
+ if (surface)
+ {
+ register_window_surface( surface, NULL );
+ window_surface_release( surface );
+ }
+
+ user_driver->pDestroyWindow( hwnd );
+
+ free_window_handle( hwnd );
+ return 0;
+}
+
+/***********************************************************************
+ * NtUserDestroyWindow (win32u.@)
+ */
+BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
+{
+ BOOL is_child;
+
+ if (!(hwnd = is_current_thread_window( hwnd )) || is_desktop_window( hwnd ))
+ {
+ SetLastError( ERROR_ACCESS_DENIED );
+ return FALSE;
+ }
+
+ TRACE( "(%p)\n", hwnd );
+
+ if (call_hooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
+
+ if (user_callbacks && user_callbacks->is_menu_active() == hwnd)
+ user_callbacks->pEndMenu();
+
+ is_child = (get_window_long( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
+
+ if (is_child)
+ {
+ if (!is_exiting_thread( GetCurrentThreadId() ))
+ send_parent_notify( hwnd, WM_DESTROY );
+ }
+ else if (!get_window_relative( hwnd, GW_OWNER ))
+ {
+ call_hooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
+ /* FIXME: clean up palette - see "Internals" p.352 */
+ }
+
+ if (!is_window( hwnd )) return TRUE;
+
+ /* Hide the window */
+ if (get_window_long( hwnd, GWL_STYLE ) & WS_VISIBLE)
+ {
+ /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
+ if (is_child)
+ NtUserShowWindow( hwnd, SW_HIDE );
+ else
+ NtUserSetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
+ SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
+ }
+
+ if (!is_window( hwnd )) return TRUE;
+
+ /* Recursively destroy child windows */
+ if (!is_child)
+ {
+ for (;;)
+ {
+ BOOL got_one = FALSE;
+ HWND *children;
+ unsigned int i;
+
+ if (!(children = list_window_children( 0, get_desktop_window(), NULL, 0 ))) break;
+
+ for (i = 0; children[i]; i++)
+ {
+ if (get_window_relative( children[i], GW_OWNER ) != hwnd) continue;
+ if (is_current_thread_window( children[i] ))
+ {
+ NtUserDestroyWindow( children[i] );
+ got_one = TRUE;
+ continue;
+ }
+ set_window_owner( children[i], 0 );
+ }
+ free( children );
+ if (!got_one) break;
+ }
+ }
+
+ send_destroy_message( hwnd );
+ if (!is_window( hwnd )) return TRUE;
+
+ destroy_window( hwnd );
+ return TRUE;
+}
+
+/*****************************************************************************
* destroy_thread_windows
*
* Destroy all window owned by the current thread.
@@ -3329,6 +3642,8 @@ ULONG_PTR WINAPI NtUserCallHwnd( HWND hwnd, DWORD code )
/* temporary exports */
case NtUserCreateDesktopWindow:
return user_driver->pCreateDesktopWindow( hwnd );
+ case NtUserDestroyWindowHandle:
+ return destroy_window( hwnd );
case NtUserGetDummySurface:
return (UINT_PTR)&dummy_surface;
default:
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 258483ad8de..da1957c8c88 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -783,6 +783,12 @@ BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg )
return unix_funcs->pNtUserDestroyCursor( cursor, arg );
}
+BOOL WINAPI NtUserDestroyWindow( HWND hwnd )
+{
+ if (!unix_funcs) return FALSE;
+ return unix_funcs->pNtUserDestroyWindow( hwnd );
+}
+
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags )
{
diff --git a/include/ntuser.h b/include/ntuser.h
index aeb3e9ae2cc..de958caa735 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -91,6 +91,7 @@ enum
NtUserGetInputState,
NtUserReleaseCapture,
/* temporary exports */
+ NtUserExitingThread,
NtUserThreadDetach,
};
@@ -134,7 +135,6 @@ enum
/* temporary exports */
NtUserAllocHandle,
NtUserAllocWinProc,
- NtUserFreeDCE,
NtUserFreeHandle,
NtUserGetHandlePtr,
NtUserInvalidateDCE,
@@ -154,6 +154,7 @@ enum
NtUserIsWindowVisible,
/* temporary exports */
NtUserCreateDesktopWindow,
+ NtUserDestroyWindowHandle,
NtUserGetDummySurface,
};
@@ -302,6 +303,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN
BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
BOOL WINAPI NtUserDestroyMenu( HMENU menu );
+BOOL WINAPI NtUserDestroyWindow( HWND hwnd );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );
--
2.23.0
1
0
[PATCH v2 1/5] win32u: Move destroy_thread_windows implementation from user32.
by Huw Davies March 17, 2022
by Huw Davies March 17, 2022
March 17, 2022
From: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
Signed-off-by: Huw Davies <huw(a)codeweavers.com>
---
dlls/user32/user_main.c | 11 +++++--
dlls/user32/win.c | 56 ------------------------------------
dlls/user32/win.h | 1 -
dlls/win32u/menu.c | 8 ++++++
dlls/win32u/ntuser_private.h | 5 ++--
dlls/win32u/sysparams.c | 5 ++--
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/window.c | 48 ++++++++++++++++++++++++++++++-
include/ntuser.h | 2 +-
9 files changed, 72 insertions(+), 65 deletions(-)
diff --git a/dlls/user32/user_main.c b/dlls/user32/user_main.c
index 8e8c357bdcf..ff9b469dae6 100644
--- a/dlls/user32/user_main.c
+++ b/dlls/user32/user_main.c
@@ -140,9 +140,17 @@ static void CDECL notify_ime( HWND hwnd, UINT param )
if (ime_default) SendMessageW( ime_default, WM_IME_INTERNAL, param, HandleToUlong(hwnd) );
}
+static void CDECL free_win_ptr( WND *win )
+{
+ HeapFree( GetProcessHeap(), 0, win->text );
+ HeapFree( GetProcessHeap(), 0, win->pScroll );
+ HeapFree( GetProcessHeap(), 0, win );
+}
+
static const struct user_callbacks user_funcs =
{
CopyImage,
+ DestroyMenu,
HideCaret,
PostMessageW,
SendInput,
@@ -152,6 +160,7 @@ static const struct user_callbacks user_funcs =
ShowCaret,
ShowWindow,
WaitForInputIdle,
+ free_win_ptr,
notify_ime,
register_builtin_classes,
MSG_SendInternalMessageTimeout,
@@ -222,8 +231,6 @@ static void thread_detach(void)
WDML_NotifyThreadDetach();
NtUserCallNoParam( NtUserThreadDetach );
- destroy_thread_windows();
- CloseHandle( thread_info->server_queue );
HeapFree( GetProcessHeap(), 0, thread_info->wmchar_data );
HeapFree( GetProcessHeap(), 0, thread_info->rawinput );
diff --git a/dlls/user32/win.c b/dlls/user32/win.c
index a21bdc62ed5..b57d6bd7566 100644
--- a/dlls/user32/win.c
+++ b/dlls/user32/win.c
@@ -820,62 +820,6 @@ LRESULT WIN_DestroyWindow( HWND hwnd )
}
-/***********************************************************************
- * next_thread_window
- */
-static WND *next_thread_window( HWND *hwnd )
-{
- return (WND *)NtUserCallOneParam( (UINT_PTR)hwnd, NtUserNextThreadWindow );
-}
-
-
-/***********************************************************************
- * destroy_thread_windows
- *
- * Destroy all window owned by the current thread.
- */
-void destroy_thread_windows(void)
-{
- WND *win, *free_list = NULL, **free_list_ptr = &free_list;
- HWND hwnd = 0;
-
- USER_Lock();
- while ((win = next_thread_window( &hwnd )))
- {
- free_dce( win->dce, win->obj.handle );
- NtUserCallTwoParam( HandleToUlong(hwnd), 0, NtUserSetHandlePtr );
- win->obj.handle = *free_list_ptr;
- free_list_ptr = (WND **)&win->obj.handle;
- }
- if (free_list)
- {
- SERVER_START_REQ( destroy_window )
- {
- req->handle = 0; /* destroy all thread windows */
- wine_server_call( req );
- }
- SERVER_END_REQ;
- }
- USER_Unlock();
-
- while ((win = free_list))
- {
- free_list = win->obj.handle;
- TRACE( "destroying %p\n", win );
-
- if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && win->wIDmenu)
- DestroyMenu( UlongToHandle(win->wIDmenu) );
- if (win->hSysMenu) DestroyMenu( win->hSysMenu );
- if (win->surface)
- {
- register_window_surface( win->surface, NULL );
- window_surface_release( win->surface );
- }
- HeapFree( GetProcessHeap(), 0, win );
- }
-}
-
-
/***********************************************************************
* WIN_FixCoordinates
*
diff --git a/dlls/user32/win.h b/dlls/user32/win.h
index 08bb16a0d4a..3e6885ab090 100644
--- a/dlls/user32/win.h
+++ b/dlls/user32/win.h
@@ -46,7 +46,6 @@ extern UINT win_set_flags( HWND hwnd, UINT set_mask, UINT clear_mask ) DECLSPEC_
extern ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits ) DECLSPEC_HIDDEN;
extern BOOL WIN_GetRectangles( HWND hwnd, enum coords_relative relative, RECT *rectWindow, RECT *rectClient ) DECLSPEC_HIDDEN;
extern LRESULT WIN_DestroyWindow( HWND hwnd ) DECLSPEC_HIDDEN;
-extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern HWND WIN_CreateWindowEx( CREATESTRUCTW *cs, LPCWSTR className, HINSTANCE module, BOOL unicode ) DECLSPEC_HIDDEN;
extern BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL ) DECLSPEC_HIDDEN;
extern HWND *WIN_ListChildren( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/menu.c b/dlls/win32u/menu.c
index abaca12047f..1e8410d347e 100644
--- a/dlls/win32u/menu.c
+++ b/dlls/win32u/menu.c
@@ -105,3 +105,11 @@ BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle )
free( accel );
return TRUE;
}
+
+/**********************************************************************
+ * NtUserDestroyMenu (win32u.@)
+ */
+BOOL WINAPI NtUserDestroyMenu( HMENU menu )
+{
+ return user_callbacks && user_callbacks->pDestroyMenu( menu );
+}
diff --git a/dlls/win32u/ntuser_private.h b/dlls/win32u/ntuser_private.h
index d6c3e681c2f..aa9b45b1542 100644
--- a/dlls/win32u/ntuser_private.h
+++ b/dlls/win32u/ntuser_private.h
@@ -26,10 +26,12 @@
#include "wine/list.h"
struct dce;
+struct tagWND;
struct user_callbacks
{
HANDLE (WINAPI *pCopyImage)( HANDLE, UINT, INT, INT, UINT );
+ BOOL (WINAPI *pDestroyMenu)( HMENU );
BOOL (WINAPI *pHideCaret)( HWND hwnd );
BOOL (WINAPI *pPostMessageW)( HWND, UINT, WPARAM, LPARAM );
UINT (WINAPI *pSendInput)( UINT count, INPUT *inputs, int size );
@@ -39,6 +41,7 @@ struct user_callbacks
BOOL (WINAPI *pShowCaret)( HWND hwnd );
BOOL (WINAPI *pShowWindow)( HWND, INT );
DWORD (WINAPI *pWaitForInputIdle)( HANDLE, DWORD );
+ void (CDECL *free_win_ptr)( struct tagWND *win );
void (CDECL *notify_ime)( HWND hwnd, UINT param );
void (CDECL *register_builtin_classes)(void);
LRESULT (WINAPI *send_ll_message)( DWORD, DWORD, UINT, WPARAM, LPARAM, UINT, UINT, PDWORD_PTR );
@@ -122,8 +125,6 @@ static inline BOOL is_broadcast( HWND hwnd )
return hwnd == HWND_BROADCAST || hwnd == HWND_TOPMOST;
}
-WND *next_thread_window_ptr( HWND *hwnd );
-
#define WM_IME_INTERNAL 0x287
#define IME_INTERNAL_ACTIVATE 0x17
#define IME_INTERNAL_DEACTIVATE 0x18
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index f0ecb3b92bb..d9ddfe3400e 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -4599,6 +4599,9 @@ static void thread_detach(void)
free( thread_info->key_state );
thread_info->key_state = 0;
+
+ destroy_thread_windows();
+ NtClose( thread_info->server_queue );
}
/***********************************************************************
@@ -4689,8 +4692,6 @@ ULONG_PTR WINAPI NtUserCallOneParam( ULONG_PTR arg, ULONG code )
case 1: user_unlock(); return 0;
default: user_check_not_lock(); return 0;
}
- case NtUserNextThreadWindow:
- return (UINT_PTR)next_thread_window_ptr( (HWND *)arg );
case NtUserSetCallbacks:
return (UINT_PTR)InterlockedExchangePointer( (void **)&user_callbacks, (void *)arg );
default:
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 0c4e3b82f0f..516f4540315 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -343,6 +343,7 @@ extern void erase_now( HWND hwnd, UINT rdw_flags ) DECLSPEC_HIDDEN;
/* window.c */
struct tagWND;
extern HDWP begin_defer_window_pos( INT count ) DECLSPEC_HIDDEN;
+extern void destroy_thread_windows(void) DECLSPEC_HIDDEN;
extern HWND get_desktop_window(void) DECLSPEC_HIDDEN;
extern UINT get_dpi_for_window( HWND hwnd ) DECLSPEC_HIDDEN;
extern HWND get_full_window_handle( HWND hwnd ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index 079b4b0695f..a28b6ae9ebf 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -141,7 +141,7 @@ void *free_user_handle( HANDLE handle, unsigned int type )
/***********************************************************************
* next_thread_window
*/
-WND *next_thread_window_ptr( HWND *hwnd )
+static WND *next_thread_window_ptr( HWND *hwnd )
{
struct user_object *ptr;
WND *win;
@@ -3259,6 +3259,52 @@ BOOL WINAPI NtUserFlashWindowEx( FLASHWINFO *info )
}
}
+/***********************************************************************
+ * destroy_thread_windows
+ *
+ * Destroy all window owned by the current thread.
+ */
+void destroy_thread_windows(void)
+{
+ WND *win, *free_list = NULL;
+ HWND hwnd = 0;
+
+ user_lock();
+ while ((win = next_thread_window_ptr( &hwnd )))
+ {
+ free_dce( win->dce, win->obj.handle );
+ set_user_handle_ptr( hwnd, NULL );
+ win->obj.handle = free_list;
+ free_list = win;
+ }
+ if (free_list)
+ {
+ SERVER_START_REQ( destroy_window )
+ {
+ req->handle = 0; /* destroy all thread windows */
+ wine_server_call( req );
+ }
+ SERVER_END_REQ;
+ }
+ user_unlock();
+
+ while ((win = free_list))
+ {
+ free_list = win->obj.handle;
+ TRACE( "destroying %p\n", win );
+
+ if ((win->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD && win->wIDmenu)
+ NtUserDestroyMenu( UlongToHandle(win->wIDmenu) );
+ if (win->hSysMenu) NtUserDestroyMenu( win->hSysMenu );
+ if (win->surface)
+ {
+ register_window_surface( win->surface, NULL );
+ window_surface_release( win->surface );
+ }
+ if (user_callbacks) user_callbacks->free_win_ptr( win );
+ }
+}
+
/*****************************************************************************
* NtUserCallHwnd (win32u.@)
*/
diff --git a/include/ntuser.h b/include/ntuser.h
index 5e79083aa01..aeb3e9ae2cc 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -119,7 +119,6 @@ enum
NtUserHandleInternalMessage,
NtUserIncrementKeyStateCounter,
NtUserLock,
- NtUserNextThreadWindow,
NtUserSetCallbacks,
};
@@ -302,6 +301,7 @@ HDWP WINAPI NtUserDeferWindowPosAndBand( HDWP hdwp, HWND hwnd, HWND after, IN
INT cx, INT cy, UINT flags, UINT unk1, UINT unk2 );
BOOL WINAPI NtUserDestroyAcceleratorTable( HACCEL handle );
BOOL WINAPI NtUserDestroyCursor( HCURSOR cursor, ULONG arg );
+BOOL WINAPI NtUserDestroyMenu( HMENU menu );
BOOL WINAPI NtUserDrawIconEx( HDC hdc, INT x0, INT y0, HICON icon, INT width,
INT height, UINT istep, HBRUSH hbr, UINT flags );
BOOL WINAPI NtUserEndDeferWindowPosEx( HDWP hdwp, BOOL async );
--
2.23.0
1
0
[PATCH 5/5] win32u: Move GetWindowContextHelpId implementation from user32.
by Jacek Caban March 17, 2022
by Jacek Caban March 17, 2022
March 17, 2022
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/win.c | 12 +-----------
dlls/win32u/window.c | 18 ++++++++++++++++++
include/ntuser.h | 1 +
3 files changed, 20 insertions(+), 11 deletions(-)
1
0
March 17, 2022
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/combo.c | 4 +-
dlls/user32/defwnd.c | 2 +-
dlls/user32/dialog.c | 6 +-
dlls/user32/driver.c | 8 +-
dlls/user32/mdi.c | 12 +-
dlls/user32/message.c | 21 +-
dlls/user32/nonclient.c | 6 +-
dlls/user32/scroll.c | 2 +-
dlls/user32/user32.spec | 4 +-
dlls/user32/user_main.c | 1 -
dlls/user32/win.c | 10 +-
dlls/user32/win.h | 6 -
dlls/user32/winpos.c | 228 +---------------
dlls/win32u/driver.c | 1 +
dlls/win32u/gdiobj.c | 2 +
dlls/win32u/input.c | 2 +-
dlls/win32u/message.c | 3 +
dlls/win32u/ntuser_private.h | 7 +-
dlls/win32u/win32u.spec | 4 +-
dlls/win32u/win32u_private.h | 4 +
dlls/win32u/window.c | 485 ++++++++++++++++++++++++++++++++++-
dlls/win32u/wrappers.c | 12 +
include/ntuser.h | 1 +
23 files changed, 540 insertions(+), 291 deletions(-)
1
0
March 17, 2022
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/user_main.c | 1 +
dlls/user32/winpos.c | 92 ++--------------------------------
dlls/win32u/menu.c | 6 +++
dlls/win32u/ntuser_private.h | 1 +
dlls/win32u/win32u_private.h | 3 ++
dlls/win32u/window.c | 97 ++++++++++++++++++++++++++++++++++++
include/ntuser.h | 1 +
7 files changed, 113 insertions(+), 88 deletions(-)
1
0
[PATCH 1/5] win32u: Move destroy_thread_windows implementation from user32.
by Jacek Caban March 17, 2022
by Jacek Caban March 17, 2022
March 17, 2022
Signed-off-by: Jacek Caban <jacek(a)codeweavers.com>
---
dlls/user32/user_main.c | 11 +++++--
dlls/user32/win.c | 56 ------------------------------------
dlls/user32/win.h | 1 -
dlls/win32u/menu.c | 8 ++++++
dlls/win32u/ntuser_private.h | 5 ++--
dlls/win32u/sysparams.c | 5 ++--
dlls/win32u/win32u_private.h | 1 +
dlls/win32u/window.c | 48 ++++++++++++++++++++++++++++++-
include/ntuser.h | 2 +-
9 files changed, 72 insertions(+), 65 deletions(-)
1
0
[PATCH vkd3d v2 1/3] tests: Work around a rounding difference between NVIDIA and AMD.
by Giovanni Mascellani March 17, 2022
by Giovanni Mascellani March 17, 2022
March 17, 2022
NVIDIA and AMD round differently the assignment of 0.5f to a UAV
of type R16G16_UNORM. NVIDIA rounds to 0x7fff and AMD to 0x8000.
According to both Vulkan and D3D12 specifications, both values
are acceptable, but the discrepancy currently appears as a
failure on NVIDIA cards.
Work around the issue by using 0.25f instead of 0.5f, which is
rounded as 0x4000 on both implementations.
Signed-off-by: Giovanni Mascellani <gmascellani(a)codeweavers.com>
---
tests/d3d12.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c
index 5067dd97..46de3316 100644
--- a/tests/d3d12.c
+++ b/tests/d3d12.c
@@ -4930,7 +4930,7 @@ static void test_clear_unordered_access_view_buffer(void)
{DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE},
{0x1234, 0xabcd, 0, 0}, 0xabcd1234},
{DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE},
- {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff8000, true},
+ {0x3e800000 /* 0.25f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff4000, true},
{DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE},
{0x40000000 /* 2.0f */, 0 /* 0.0f */, 0, 0}, 0x0000ffff, true},
{DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE},
@@ -5124,7 +5124,7 @@ static void test_clear_unordered_access_view_image(void)
{DXGI_FORMAT_R11G11B10_FLOAT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00c01001},
/* Test float clears with formats. */
{DXGI_FORMAT_R16G16_UNORM, 1, 1, 0, 0, 1, 0, {},
- {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff8000, true},
+ {0x3e800000 /* 0.25f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff4000, true},
{DXGI_FORMAT_R16G16_FLOAT, 1, 1, 0, 0, 1, 0, {},
{0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0x3c003800, true},
{DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 0, 0, 1, 0, {},
--
2.35.1
2
5