From 3f238e248fc4fc4415b3ce5e420c798d516d24ee Mon Sep 17 00:00:00 2001 From: Hirofumi Katayama Date: Mon, 26 Nov 2018 09:09:52 +0900 Subject: [PATCH] user32: Implement TileWindows Wine lacks the implementations of TileWindows function of window arrangement. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46197 Signed-off-by: Hirofumi Katayama --- dlls/user32/mdi.c | 179 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 175 insertions(+), 4 deletions(-) diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c index 9679be895ed..c752f967b4d 100644 --- a/dlls/user32/mdi.c +++ b/dlls/user32/mdi.c @@ -144,6 +144,10 @@ typedef struct static HBITMAP hBmpClose = 0; +static WCHAR shelltray[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; +static WCHAR progman[] = {'P','r','o','g','m','a','n',0}; + + /* ----------------- declarations ----------------- */ static void MDI_UpdateFrameText( HWND, HWND, BOOL, LPCWSTR); static BOOL MDI_AugmentFrameMenu( HWND, HWND ); @@ -1929,8 +1933,6 @@ WORD WINAPI CascadeWindows (HWND hwndParent, UINT wFlags, const RECT *lpRect, UINT cKids, const HWND *lpKids) { - static WCHAR shelltray[] = {'S','h','e','l','l','_','T','r','a','y','W','n','d',0}; - static WCHAR progman[] = {'P','r','o','g','m','a','n',0}; CASCADE_INFO info; HWND hwnd, top, prev; HMONITOR monitor; @@ -2084,8 +2086,177 @@ WORD WINAPI TileWindows (HWND hwndParent, UINT wFlags, const RECT *lpRect, UINT cKids, const HWND *lpKids) { - FIXME("(%p,0x%08x,...,%u,...): stub\n", hwndParent, wFlags, cKids); - return 0; + HWND hwnd, hwndTop, hwndPrev; + CASCADE_INFO info; + RECT rcWork, rcWnd; + DWORD i, iRow, iColumn, cRows, cColumns, ret = 0; + INT x, y, cx, cy, cxNew, cyNew, cxWork, cyWork, cxCell, cyCell, cxMin2, cyMin3; + HDWP hDWP; + MONITORINFO mi; + HMONITOR hMon; + POINT pt; + + TRACE("(%p,0x%08x,...,%u,...)\n", hwndParent, wFlags, cKids); + + hwndTop = GetTopWindow(hwndParent); + + ZeroMemory(&info, sizeof(info)); + info.desktop = GetDesktopWindow(); + info.tray_wnd = FindWindowW(shelltray, NULL); + info.progman = FindWindowW(progman, NULL); + info.parent = hwndParent; + info.flags = wFlags; + + if (cKids == 0 || lpKids == NULL) + { + info.top = hwndTop; + EnumChildWindows(hwndParent, GetCascadeChildProc, (LPARAM)&info); + + info.top = NULL; + GetCascadeChildProc(hwndTop, (LPARAM)&info); + } + else + { + info.wnd_count = cKids; + info.wnd_array = (HWND *)lpKids; + } + + if (info.wnd_count == 0 || info.wnd_array == NULL) + return ret; + + if (lpRect) + { + rcWork = *lpRect; + } + else if (hwndParent) + { + GetClientRect(hwndParent, &rcWork); + } + else + { + pt.x = pt.y = 0; + hMon = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); + mi.cbSize = sizeof(mi); + GetMonitorInfoW(hMon, &mi); + rcWork = mi.rcWork; + } + + cxWork = rcWork.right - rcWork.left; + cyWork = rcWork.bottom - rcWork.top; + + cxMin2 = GetSystemMetrics(SM_CXMIN) * 2; + cyMin3 = GetSystemMetrics(SM_CYMIN) * 3; + + /* calculate the numbers and widths of columns and rows */ + if (info.flags & MDITILE_HORIZONTAL) + { + cColumns = info.wnd_count; + cRows = 1; + for (;;) + { + cxCell = cxWork / cColumns; + cyCell = cyWork / cRows; + if (cyCell <= cyMin3 || cxCell >= cxMin2) + break; + + ++cRows; + cColumns = (info.wnd_count + cRows - 1) / cRows; + } + } + else + { + cRows = info.wnd_count; + cColumns = 1; + for (;;) + { + cxCell = cxWork / cColumns; + cyCell = cyWork / cRows; + if (cxCell <= cxMin2 || cyCell >= cyMin3) + break; + + ++cColumns; + cRows = (info.wnd_count + cColumns - 1) / cColumns; + } + } + + hDWP = BeginDeferWindowPos(info.wnd_count); + if (hDWP == NULL) + goto cleanup; + + x = rcWork.left; + y = rcWork.top; + hwndPrev = NULL; + iRow = iColumn = 0; + for (i = info.wnd_count; i > 0;) /* in reverse order */ + { + --i; + hwnd = info.wnd_array[i]; + + if (IsZoomed(hwnd)) + NtUserShowWindow(hwnd, SW_RESTORE | SW_SHOWNA); + + GetWindowRect(hwnd, &rcWnd); + cx = rcWnd.right - rcWnd.left; + cy = rcWnd.bottom - rcWnd.top; + + /* if we can change the window size */ + if (GetWindowLongPtrW(hwnd, GWL_STYLE) & WS_THICKFRAME) + { + cxNew = cxCell; + cyNew = cyCell; + /* shrink if we can */ + if (QuerySizeFix(hwnd, &cxNew, &cyNew)) + { + cx = cxNew; + cy = cyNew; + } + } + + hDWP = DeferWindowPos(hDWP, hwnd, HWND_TOP, x, y, cx, cy, SWP_NOACTIVATE); + if (hDWP == NULL) + { + ret = 0; + goto cleanup; + } + + if (info.flags & MDITILE_HORIZONTAL) + { + x += cxCell; + ++iColumn; + if (iColumn >= cColumns) + { + iColumn = 0; + ++iRow; + x = rcWork.left; + y += cyCell; + } + } + else + { + y += cyCell; + ++iRow; + if (iRow >= cRows) + { + iRow = 0; + ++iColumn; + x += cxCell; + y = rcWork.top; + } + } + hwndPrev = hwnd; + ++ret; + } + + EndDeferWindowPos(hDWP); + + if (hwndPrev) + SetForegroundWindow(hwndPrev); + +cleanup: + if (cKids == 0 || lpKids == NULL) + HeapFree(GetProcessHeap(), 0, info.wnd_array); + + return (WORD)ret; } -- 2.24.1