[PATCH 1/6] win32u: Move NtUserSetWindowPlacement implementation from user32.

Jacek Caban wine at gitlab.winehq.org
Thu May 19 08:04:12 CDT 2022


From: Jacek Caban <jacek at codeweavers.com>

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
---
 dlls/user32/user32.spec      |   2 +-
 dlls/user32/winpos.c         |  15 -----
 dlls/win32u/gdiobj.c         |   1 +
 dlls/win32u/sysparams.c      |  20 ++++++
 dlls/win32u/win32u.spec      |   2 +-
 dlls/win32u/win32u_private.h |   3 +
 dlls/win32u/window.c         | 119 +++++++++++++++++++++++++++++++++++
 dlls/win32u/wrappers.c       |   6 ++
 include/ntuser.h             |   1 +
 9 files changed, 152 insertions(+), 17 deletions(-)

diff --git a/dlls/user32/user32.spec b/dlls/user32/user32.spec
index 555023de110..dfa5c2516b9 100644
--- a/dlls/user32/user32.spec
+++ b/dlls/user32/user32.spec
@@ -725,7 +725,7 @@
 @ stdcall -arch=win64 SetWindowLongPtrA(long long long)
 @ stdcall -arch=win64 SetWindowLongPtrW(long long long)
 @ stdcall SetWindowLongW(long long long)
-@ stdcall SetWindowPlacement(long ptr)
+@ stdcall SetWindowPlacement(long ptr) NtUserSetWindowPlacement
 @ stdcall SetWindowPos(long long long long long long long) NtUserSetWindowPos
 @ stdcall SetWindowRgn(long long long) NtUserSetWindowRgn
 @ stdcall SetWindowStationUser(long long)
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index 5987d06c257..d19ebab3e6e 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -428,21 +428,6 @@ static BOOL WINPOS_SetPlacement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT f
 }
 
 
-/***********************************************************************
- *		SetWindowPlacement (USER32.@)
- *
- * Win95:
- * Fails if wndpl->length of Win95 (!) apps is invalid.
- */
-BOOL WINAPI SetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
-{
-    UINT flags = PLACE_MAX | PLACE_RECT;
-    if (!wpl) return FALSE;
-    if (wpl->flags & WPF_SETMINPOSITION) flags |= PLACE_MIN;
-    return WINPOS_SetPlacement( hwnd, wpl, flags );
-}
-
-
 /***********************************************************************
  *		AnimateWindow (USER32.@)
  *		Shows/Hides a window with an animation
diff --git a/dlls/win32u/gdiobj.c b/dlls/win32u/gdiobj.c
index 96d52e4d38e..b9c71674e75 100644
--- a/dlls/win32u/gdiobj.c
+++ b/dlls/win32u/gdiobj.c
@@ -1219,6 +1219,7 @@ static struct unix_funcs unix_funcs =
     NtUserSetSystemMenu,
     NtUserSetWindowLong,
     NtUserSetWindowLongPtr,
+    NtUserSetWindowPlacement,
     NtUserSetWindowPos,
     NtUserSetWindowRgn,
     NtUserSetWindowWord,
diff --git a/dlls/win32u/sysparams.c b/dlls/win32u/sysparams.c
index dd494188121..f9491313384 100644
--- a/dlls/win32u/sysparams.c
+++ b/dlls/win32u/sysparams.c
@@ -1515,6 +1515,26 @@ POINT point_phys_to_win_dpi( HWND hwnd, POINT pt )
     return map_dpi_point( pt, get_win_monitor_dpi( hwnd ), get_dpi_for_window( hwnd ));
 }
 
+/**********************************************************************
+ *              point_thread_to_win_dpi
+ */
+POINT point_thread_to_win_dpi( HWND hwnd, POINT pt )
+{
+    UINT dpi = get_thread_dpi();
+    if (!dpi) dpi = get_win_monitor_dpi( hwnd );
+    return map_dpi_point( pt, dpi, get_dpi_for_window( hwnd ));
+}
+
+/**********************************************************************
+ *              rect_thread_to_win_dpi
+ */
+RECT rect_thread_to_win_dpi( HWND hwnd, RECT rect )
+{
+    UINT dpi = get_thread_dpi();
+    if (!dpi) dpi = get_win_monitor_dpi( hwnd );
+    return map_dpi_rect( rect, dpi, get_dpi_for_window( hwnd ) );
+}
+
 /* map value from system dpi to standard 96 dpi for storing in the registry */
 static int map_from_system_dpi( int val )
 {
diff --git a/dlls/win32u/win32u.spec b/dlls/win32u/win32u.spec
index 1c3cbc59dc2..1652446a503 100644
--- a/dlls/win32u/win32u.spec
+++ b/dlls/win32u/win32u.spec
@@ -1248,7 +1248,7 @@
 @ stub NtUserSetWindowGroup
 @ stdcall NtUserSetWindowLong(long long long long)
 @ stdcall NtUserSetWindowLongPtr(long long long long)
-@ stub NtUserSetWindowPlacement
+@ stdcall NtUserSetWindowPlacement(long ptr)
 @ stdcall NtUserSetWindowPos(long long long long long long long)
 @ stdcall NtUserSetWindowRgn(long long long)
 @ stub NtUserSetWindowRgnEx
diff --git a/dlls/win32u/win32u_private.h b/dlls/win32u/win32u_private.h
index 02784df64f8..c9da765e6a1 100644
--- a/dlls/win32u/win32u_private.h
+++ b/dlls/win32u/win32u_private.h
@@ -289,6 +289,7 @@ struct unix_funcs
     BOOL     (WINAPI *pNtUserSetSystemMenu)( HWND hwnd, HMENU menu );
     LONG     (WINAPI *pNtUserSetWindowLong)( HWND hwnd, INT offset, LONG newval, BOOL ansi );
     LONG_PTR (WINAPI *pNtUserSetWindowLongPtr)( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi );
+    BOOL     (WINAPI *pNtUserSetWindowPlacement)( HWND hwnd, const WINDOWPLACEMENT *wpl );
     BOOL     (WINAPI *pNtUserSetWindowPos)( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags );
     int      (WINAPI *pNtUserSetWindowRgn)( HWND hwnd, HRGN hrgn, BOOL redraw );
     WORD     (WINAPI *pNtUserSetWindowWord)( HWND hwnd, INT offset, WORD newval );
@@ -418,6 +419,8 @@ 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 POINT point_phys_to_win_dpi( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN;
+extern POINT point_thread_to_win_dpi( HWND hwnd, POINT pt ) DECLSPEC_HIDDEN;
+extern RECT rect_thread_to_win_dpi( HWND hwnd, RECT rect ) DECLSPEC_HIDDEN;
 extern HMONITOR monitor_from_point( POINT pt, DWORD flags, UINT dpi ) DECLSPEC_HIDDEN;
 extern HMONITOR monitor_from_rect( const RECT *rect, DWORD flags, UINT dpi ) DECLSPEC_HIDDEN;
 extern HMONITOR monitor_from_window( HWND hwnd, DWORD flags, UINT dpi ) DECLSPEC_HIDDEN;
diff --git a/dlls/win32u/window.c b/dlls/win32u/window.c
index 31512c03e15..e75f47a2fe6 100644
--- a/dlls/win32u/window.c
+++ b/dlls/win32u/window.c
@@ -48,6 +48,10 @@ static void *user_handles[NB_USER_HANDLES];
 #define SWP_AGG_NOCLIENTCHANGE \
         (SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
 
+#define PLACE_MIN		0x0001
+#define PLACE_MAX		0x0002
+#define PLACE_RECT		0x0004
+
 /***********************************************************************
  *           alloc_user_handle
  */
@@ -2484,6 +2488,121 @@ BOOL get_window_placement( HWND hwnd, WINDOWPLACEMENT *placement )
     return TRUE;
 }
 
+/* make sure the specified rect is visible on screen */
+static void make_rect_onscreen( RECT *rect )
+{
+    MONITORINFO info;
+    HMONITOR monitor = monitor_from_rect( rect, MONITOR_DEFAULTTONEAREST, get_thread_dpi() );
+
+    info.cbSize = sizeof(info);
+    if (!monitor || !get_monitor_info( monitor, &info )) return;
+    /* FIXME: map coordinates from rcWork to rcMonitor */
+    if (rect->right <= info.rcWork.left)
+    {
+        rect->right += info.rcWork.left - rect->left;
+        rect->left = info.rcWork.left;
+    }
+    else if (rect->left >= info.rcWork.right)
+    {
+        rect->left += info.rcWork.right - rect->right;
+        rect->right = info.rcWork.right;
+    }
+    if (rect->bottom <= info.rcWork.top)
+    {
+        rect->bottom += info.rcWork.top - rect->top;
+        rect->top = info.rcWork.top;
+    }
+    else if (rect->top >= info.rcWork.bottom)
+    {
+        rect->top += info.rcWork.bottom - rect->bottom;
+        rect->bottom = info.rcWork.bottom;
+    }
+}
+
+/* make sure the specified point is visible on screen */
+static void make_point_onscreen( POINT *pt )
+{
+    RECT rect;
+
+    SetRect( &rect, pt->x, pt->y, pt->x + 1, pt->y + 1 );
+    make_rect_onscreen( &rect );
+    pt->x = rect.left;
+    pt->y = rect.top;
+}
+
+static BOOL set_window_placement( HWND hwnd, const WINDOWPLACEMENT *wndpl, UINT flags )
+{
+    RECT work_rect = get_maximized_work_rect( hwnd );
+    WND *win = get_win_ptr( hwnd );
+    WINDOWPLACEMENT wp = *wndpl;
+    DWORD style;
+
+    if (flags & PLACE_MIN) make_point_onscreen( &wp.ptMinPosition );
+    if (flags & PLACE_MAX) make_point_onscreen( &wp.ptMaxPosition );
+    if (flags & PLACE_RECT) make_rect_onscreen( &wp.rcNormalPosition );
+
+    TRACE( "%p: setting min %d,%d max %d,%d normal %s flags %x adjusted to min %d,%d max %d,%d normal %s\n",
+           hwnd, wndpl->ptMinPosition.x, wndpl->ptMinPosition.y,
+           wndpl->ptMaxPosition.x, wndpl->ptMaxPosition.y,
+           wine_dbgstr_rect(&wndpl->rcNormalPosition), flags,
+           wp.ptMinPosition.x, wp.ptMinPosition.y, wp.ptMaxPosition.x, wp.ptMaxPosition.y,
+           wine_dbgstr_rect(&wp.rcNormalPosition) );
+
+    if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP) return FALSE;
+
+    if (flags & PLACE_MIN) win->min_pos = point_thread_to_win_dpi( hwnd, wp.ptMinPosition );
+    if (flags & PLACE_MAX)
+    {
+        win->max_pos = point_thread_to_win_dpi( hwnd, wp.ptMaxPosition );
+        update_maximized_pos( win, &work_rect );
+    }
+    if (flags & PLACE_RECT) win->normal_rect = rect_thread_to_win_dpi( hwnd, wp.rcNormalPosition );
+
+    style = win->dwStyle;
+
+    release_win_ptr( win );
+
+    if (style & WS_MINIMIZE)
+    {
+        if (flags & PLACE_MIN)
+        {
+            NtUserSetWindowPos( hwnd, 0, wp.ptMinPosition.x, wp.ptMinPosition.y, 0, 0,
+                                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+        }
+    }
+    else if (style & WS_MAXIMIZE)
+    {
+        if (flags & PLACE_MAX)
+            NtUserSetWindowPos( hwnd, 0, wp.ptMaxPosition.x, wp.ptMaxPosition.y, 0, 0,
+                                SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
+    }
+    else if (flags & PLACE_RECT)
+        NtUserSetWindowPos( hwnd, 0, wp.rcNormalPosition.left, wp.rcNormalPosition.top,
+                            wp.rcNormalPosition.right - wp.rcNormalPosition.left,
+                            wp.rcNormalPosition.bottom - wp.rcNormalPosition.top,
+                            SWP_NOZORDER | SWP_NOACTIVATE );
+
+    NtUserShowWindow( hwnd, wndpl->showCmd );
+
+    if (is_iconic( hwnd ))
+    {
+        if (wndpl->flags & WPF_RESTORETOMAXIMIZED)
+            win_set_flags( hwnd, WIN_RESTORE_MAX, 0 );
+    }
+    return TRUE;
+}
+
+/***********************************************************************
+ *           NtUserSetWindowPlacement (win32u.@)
+ */
+BOOL WINAPI NtUserSetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
+{
+    UINT flags = PLACE_MAX | PLACE_RECT;
+    if (!wpl) return FALSE;
+    if (wpl->flags & WPF_SETMINPOSITION) flags |= PLACE_MIN;
+    return set_window_placement( hwnd, wpl, flags );
+}
+
 /*****************************************************************************
  *           NtUserBuildHwndList (win32u.@)
  */
diff --git a/dlls/win32u/wrappers.c b/dlls/win32u/wrappers.c
index 4e750e5aea2..64f823ccd26 100644
--- a/dlls/win32u/wrappers.c
+++ b/dlls/win32u/wrappers.c
@@ -1227,6 +1227,12 @@ LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval,
     return unix_funcs->pNtUserSetWindowLongPtr( hwnd, offset, newval, ansi );
 }
 
+BOOL WINAPI NtUserSetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl )
+{
+    if (!unix_funcs) return 0;
+    return unix_funcs->pNtUserSetWindowPlacement( hwnd, wpl );
+}
+
 BOOL WINAPI NtUserSetWindowPos( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags )
 {
     if (!unix_funcs) return 0;
diff --git a/include/ntuser.h b/include/ntuser.h
index a39fffaedf9..af87d8a5fec 100644
--- a/include/ntuser.h
+++ b/include/ntuser.h
@@ -641,6 +641,7 @@ BOOL    WINAPI NtUserSetThreadDesktop( HDESK handle );
 UINT_PTR WINAPI NtUserSetTimer( HWND hwnd, UINT_PTR id, UINT timeout, TIMERPROC proc, ULONG tolerance );
 LONG    WINAPI NtUserSetWindowLong( HWND hwnd, INT offset, LONG newval, BOOL ansi );
 LONG_PTR WINAPI NtUserSetWindowLongPtr( HWND hwnd, INT offset, LONG_PTR newval, BOOL ansi );
+BOOL    WINAPI NtUserSetWindowPlacement( HWND hwnd, const WINDOWPLACEMENT *wpl );
 BOOL    WINAPI NtUserSetWindowPos( HWND hwnd, HWND after, INT x, INT y, INT cx, INT cy, UINT flags );
 int     WINAPI NtUserSetWindowRgn( HWND hwnd, HRGN hrgn, BOOL redraw );
 WORD    WINAPI NtUserSetWindowWord( HWND hwnd, INT offset, WORD newval );
-- 
GitLab


https://gitlab.winehq.org/wine/wine/-/merge_requests/97



More information about the wine-devel mailing list