user32: Add a test for fullscreen window sizing, make it pass under Wine.

Dmitry Timoshkov dmitry at codeweavers.com
Thu Oct 16 05:58:56 CDT 2008


It appears that Windows doesn't always restrict the window size by
the monitor work area. The tests pass under XP SP3 and Win98.

This patch should fix the regression reported in the bug 15598.
---
 dlls/user32/tests/win.c |  191 +++++++++++++++++++++++++++++++++++++++++++++++
 dlls/user32/winpos.c    |   21 ++++--
 2 files changed, 206 insertions(+), 6 deletions(-)

diff --git a/dlls/user32/tests/win.c b/dlls/user32/tests/win.c
index db1de11..1b9d729 100644
--- a/dlls/user32/tests/win.c
+++ b/dlls/user32/tests/win.c
@@ -49,6 +49,8 @@ static BOOL (WINAPI *pGetWindowInfo)(HWND,WINDOWINFO*);
 static UINT (WINAPI *pGetWindowModuleFileNameA)(HWND,LPSTR,UINT);
 static BOOL (WINAPI *pGetLayeredWindowAttributes)(HWND,COLORREF*,BYTE*,DWORD*);
 static BOOL (WINAPI *pSetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD);
+static BOOL (WINAPI *pGetMonitorInfoA)(HMONITOR,LPMONITORINFO);
+static HMONITOR (WINAPI *pMonitorFromPoint)(POINT,DWORD);
 
 static BOOL test_lbuttondown_flag;
 static HWND hwndMessage;
@@ -4906,6 +4908,192 @@ static void test_layered_window(void)
     DestroyWindow( hwnd );
 }
 
+static MONITORINFO mi;
+
+static LRESULT CALLBACK fullscreen_wnd_proc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
+{
+    switch (msg)
+    {
+        case WM_NCCREATE:
+        {
+            CREATESTRUCTA *cs = (CREATESTRUCTA *)lp;
+            trace("WM_NCCREATE: rect %d,%d-%d,%d\n", cs->x, cs->y, cs->cx, cs->cy);
+            ok(cs->x == mi.rcMonitor.left && cs->y == mi.rcMonitor.top &&
+               cs->cx == mi.rcMonitor.right && cs->cy == mi.rcMonitor.bottom,
+               "expected %d,%d-%d,%d, got %d,%d-%d,%d\n",
+               mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+               cs->x, cs->y, cs->cx, cs->cy);
+            break;
+        }
+        case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO *minmax = (MINMAXINFO *)lp;
+            dump_minmax_info(minmax);
+            ok(minmax->ptMaxPosition.x <= mi.rcMonitor.left, "%d <= %d\n", minmax->ptMaxPosition.x, mi.rcMonitor.left);
+            ok(minmax->ptMaxPosition.y <= mi.rcMonitor.top, "%d <= %d\n", minmax->ptMaxPosition.y, mi.rcMonitor.top);
+            ok(minmax->ptMaxSize.x >= mi.rcMonitor.right, "%d >= %d\n", minmax->ptMaxSize.x, mi.rcMonitor.right);
+            ok(minmax->ptMaxSize.y >= mi.rcMonitor.bottom, "%d >= %d\n", minmax->ptMaxSize.y, mi.rcMonitor.bottom);
+            break;
+        }
+    }
+    return DefWindowProc(hwnd, msg, wp, lp);
+}
+
+static void test_fullscreen(void)
+{
+    static const DWORD t_style[] = {
+        WS_OVERLAPPED, WS_POPUP, WS_CHILD, WS_THICKFRAME, WS_DLGFRAME
+    };
+    static const DWORD t_ex_style[] = {
+        0, WS_EX_APPWINDOW, WS_EX_TOOLWINDOW
+    };
+    WNDCLASS cls;
+    HWND hwnd;
+    int i, j;
+    POINT pt;
+    RECT rc;
+    HMONITOR hmon;
+    LRESULT ret;
+
+    if (!pGetMonitorInfoA || !pMonitorFromPoint)
+    {
+        win_skip("GetMonitorInfoA or MonitorFromPoint are not available on this platform\n");
+        return;
+    }
+
+    pt.x = pt.y = 0;
+    SetLastError(0xdeadbeef);
+    hmon = pMonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
+    ok(hmon != 0, "MonitorFromPoint error %u\n", GetLastError());
+
+    mi.cbSize = sizeof(mi);
+    SetLastError(0xdeadbeef);
+    ret = pGetMonitorInfoA(hmon, &mi);
+    ok(ret, "GetMonitorInfo error %u\n", GetLastError());
+    trace("monitor (%d,%d-%d,%d), work (%d,%d-%d,%d)\n",
+        mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+        mi.rcWork.left, mi.rcWork.top, mi.rcWork.right, mi.rcWork.bottom);
+
+    cls.style = 0;
+    cls.lpfnWndProc = fullscreen_wnd_proc;
+    cls.cbClsExtra = 0;
+    cls.cbWndExtra = 0;
+    cls.hInstance = GetModuleHandle(0);
+    cls.hIcon = 0;
+    cls.hCursor = LoadCursorA(0, (LPSTR)IDC_ARROW);
+    cls.hbrBackground = GetStockObject(WHITE_BRUSH);
+    cls.lpszMenuName = NULL;
+    cls.lpszClassName = "fullscreen_class";
+    RegisterClass(&cls);
+
+    for (i = 0; i < sizeof(t_style)/sizeof(t_style[0]); i++)
+    {
+        DWORD style, ex_style;
+
+        /* avoid a WM interaction */
+        assert(!(t_style[i] & WS_VISIBLE));
+
+        for (j = 0; j < sizeof(t_ex_style)/sizeof(t_ex_style[0]); j++)
+        {
+            int fixup;
+
+            style = t_style[i];
+            ex_style = t_ex_style[j];
+
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
+               rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+
+            style = t_style[i] | WS_MAXIMIZE;
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
+               rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+
+            style = t_style[i] | WS_MAXIMIZE | WS_CAPTION;
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
+               rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+
+            style = t_style[i] | WS_CAPTION | WS_MAXIMIZEBOX;
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
+               rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+
+            style = t_style[i] | WS_MAXIMIZE | WS_CAPTION | WS_MAXIMIZEBOX;
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            /* Windows makes a maximized window slightly larger (to hide the borders?) */
+            fixup = min(abs(rc.left), abs(rc.top));
+            InflateRect(&rc, -fixup, -fixup);
+            /* FIXME: this doesn't work correctly in Wine for child windows yet */
+            if (style & WS_CHILD)
+            todo_wine
+            ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
+               rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            else
+            ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
+               rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
+               "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+
+            style = t_style[i] | WS_MAXIMIZE | WS_MAXIMIZEBOX;
+            hwnd = CreateWindowExA(ex_style, "fullscreen_class", NULL, style,
+                                   mi.rcMonitor.left, mi.rcMonitor.top, mi.rcMonitor.right, mi.rcMonitor.bottom,
+                                   GetDesktopWindow(), 0, GetModuleHandle(0), NULL);
+            ok(hwnd != 0, "%d: CreateWindowExA(%#x/%#x) failed\n", i, ex_style, style);
+            GetWindowRect(hwnd, &rc);
+            trace("%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            /* Windows makes a maximized window slightly larger (to hide the borders?) */
+            fixup = min(abs(rc.left), abs(rc.top));
+            InflateRect(&rc, -fixup, -fixup);
+            if (style & (WS_CHILD | WS_POPUP))
+                ok(rc.left <= mi.rcMonitor.left && rc.top <= mi.rcMonitor.top &&
+                   rc.right >= mi.rcMonitor.right && rc.bottom >= mi.rcMonitor.bottom,
+                   "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            else
+                ok(rc.left >= mi.rcWork.left && rc.top <= mi.rcWork.top &&
+                   rc.right <= mi.rcWork.right && rc.bottom <= mi.rcWork.bottom,
+                   "%#x/%#x: window rect %d,%d-%d,%d\n", ex_style, style, rc.left, rc.top, rc.right, rc.bottom);
+            DestroyWindow(hwnd);
+        }
+    }
+
+    UnregisterClass("MinMax_WndClass", GetModuleHandle(0));
+}
+
 START_TEST(win)
 {
     HMODULE user32 = GetModuleHandleA( "user32.dll" );
@@ -4914,6 +5102,8 @@ START_TEST(win)
     pGetWindowModuleFileNameA = (void *)GetProcAddress( user32, "GetWindowModuleFileNameA" );
     pGetLayeredWindowAttributes = (void *)GetProcAddress( user32, "GetLayeredWindowAttributes" );
     pSetLayeredWindowAttributes = (void *)GetProcAddress( user32, "SetLayeredWindowAttributes" );
+    pGetMonitorInfoA = (void *)GetProcAddress( user32,  "GetMonitorInfoA" );
+    pMonitorFromPoint = (void *)GetProcAddress( user32,  "MonitorFromPoint" );
 
     if (!RegisterWindowClasses()) assert(0);
 
@@ -4936,6 +5126,7 @@ START_TEST(win)
     our_pid = GetWindowThreadProcessId(hwndMain, NULL);
 
     /* Add the tests below this line */
+    test_fullscreen();
     test_hwnd_message();
     test_nonclient_area(hwndMain);
     test_params();
diff --git a/dlls/user32/winpos.c b/dlls/user32/winpos.c
index cbe844a..734b504 100644
--- a/dlls/user32/winpos.c
+++ b/dlls/user32/winpos.c
@@ -654,8 +654,8 @@ void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
     MINMAXINFO MinMax;
     HMONITOR monitor;
     INT xinc, yinc;
-    LONG style = GetWindowLongA( hwnd, GWL_STYLE );
-    LONG exstyle = GetWindowLongA( hwnd, GWL_EXSTYLE );
+    LONG style = GetWindowLongW( hwnd, GWL_STYLE );
+    LONG exstyle = GetWindowLongW( hwnd, GWL_EXSTYLE );
     RECT rc;
     WND *win;
 
@@ -725,21 +725,30 @@ void WINPOS_GetMinMaxInfo( HWND hwnd, POINT *maxSize, POINT *maxPos,
 
     if ((monitor = MonitorFromWindow( hwnd, MONITOR_DEFAULTTOPRIMARY )))
     {
+        RECT rc_work;
         MONITORINFO mon_info;
 
         mon_info.cbSize = sizeof(mon_info);
         GetMonitorInfoW( monitor, &mon_info );
 
+        rc_work = mon_info.rcMonitor;
+
+        if (style & WS_MAXIMIZEBOX)
+        {
+            if ((style & WS_CAPTION) == WS_CAPTION || !(style & (WS_CHILD | WS_POPUP)))
+                rc_work = mon_info.rcWork;
+        }
+    
         if (MinMax.ptMaxSize.x == GetSystemMetrics(SM_CXSCREEN) + 2 * xinc &&
             MinMax.ptMaxSize.y == GetSystemMetrics(SM_CYSCREEN) + 2 * yinc)
         {
-            MinMax.ptMaxSize.x = (mon_info.rcWork.right - mon_info.rcWork.left) + 2 * xinc;
-            MinMax.ptMaxSize.y = (mon_info.rcWork.bottom - mon_info.rcWork.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 = mon_info.rcWork.left - xinc;
-            MinMax.ptMaxPosition.y = mon_info.rcWork.top - yinc;
+            MinMax.ptMaxPosition.x = rc_work.left - xinc;
+            MinMax.ptMaxPosition.y = rc_work.top - yinc;
         }
     }
 
-- 
1.6.0.2




More information about the wine-patches mailing list