diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index bc996d9e..4574cf15 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -318,6 +318,7 @@ patch_enable_all () enable_user32_FlashWindowEx="$1" enable_user32_GetPointerType="$1" enable_user32_GetSystemMetrics="$1" + enable_user32_Implement_CascadeWindows="$1" enable_user32_LR_LOADFROMFILE="$1" enable_user32_ListBox_Size="$1" enable_user32_MessageBox_WS_EX_TOPMOST="$1" @@ -1118,6 +1119,9 @@ patch_enable () user32-GetSystemMetrics) enable_user32_GetSystemMetrics="$2" ;; + user32-Implement-CascadeWindows) + enable_user32_Implement_CascadeWindows="$2" + ;; user32-LR_LOADFROMFILE) enable_user32_LR_LOADFROMFILE="$2" ;; @@ -6678,6 +6682,21 @@ if test "$enable_user32_GetSystemMetrics" -eq 1; then ) >> "$patchlist" fi +# Patchset user32-Implement-CascadeWindows +# | +# | This patchset fixes the following Wine bugs: +# | * [#45968] user32: Implement CascadeWindows +# | +# | Modified files: +# | * dlls/user32/mdi.c +# | +if test "$enable_user32_Implement_CascadeWindows" -eq 1; then + patch_apply user32-Implement-CascadeWindows/0001-user32-Implement-CascadeWindows.patch + ( + printf '%s\n' '+ { "katahiromz", "user32: Implement CascadeWindows.", 1 },'; + ) >> "$patchlist" +fi + # Patchset user32-LR_LOADFROMFILE # | # | This patchset fixes the following Wine bugs: diff --git a/patches/user32-Implement-CascadeWindows/0001-user32-Implement-CascadeWindows.patch b/patches/user32-Implement-CascadeWindows/0001-user32-Implement-CascadeWindows.patch new file mode 100644 index 00000000..f9269ef2 --- /dev/null +++ b/patches/user32-Implement-CascadeWindows/0001-user32-Implement-CascadeWindows.patch @@ -0,0 +1,257 @@ +From d5389dd8bb868076b75675719d529d0507a90815 Mon Sep 17 00:00:00 2001 +From: katahiromz +Date: Thu, 11 Oct 2018 13:47:02 +0900 +Subject: [PATCH] user32: Implement CascadeWindows. + +Changes +Minor formatting +Added WCHAR for FindWindowW parameters +Use stanard heap_ functions. + +Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45968 +Signed-off-by: Hirofumi Katayama +--- + dlls/user32/mdi.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 214 insertions(+), 2 deletions(-) + +diff --git a/dlls/user32/mdi.c b/dlls/user32/mdi.c +index 10a3882..2e93056 100644 +--- a/dlls/user32/mdi.c ++++ b/dlls/user32/mdi.c +@@ -2,6 +2,7 @@ + * + * Copyright 1994, Bob Amstadt + * 1995,1996 Alex Korobka ++ * Copyright 2018 Katayama Hirofumi MZ + * + * This file contains routines to support MDI (Multiple Document + * Interface) features . +@@ -1846,12 +1847,223 @@ done: + * Success: Number of cascaded windows. + * Failure: 0 + */ ++ ++typedef struct CASCADE_INFO ++{ ++ HWND top; ++ UINT flags; ++ HWND parent; ++ HWND desktop; ++ HWND tray_wnd; ++ HWND progman; ++ HWND *wnd_array; ++ DWORD wnd_count; ++} CASCADE_INFO; ++ ++static BOOL CALLBACK GetCascadeChildProc(HWND hwnd, LPARAM lParam) ++{ ++ DWORD count, size; ++ HWND *wnd_array; ++ CASCADE_INFO *info = (CASCADE_INFO *)lParam; ++ ++ if (hwnd == info->desktop || hwnd == info->tray_wnd || ++ hwnd == info->progman || hwnd == info->top) ++ { ++ return TRUE; ++ } ++ ++ if (info->parent && GetParent(hwnd) != info->parent) ++ return TRUE; ++ ++ if ((info->flags & MDITILE_SKIPDISABLED) && !IsWindowEnabled(hwnd)) ++ return TRUE; ++ ++ if (!IsWindowVisible(hwnd) || IsIconic(hwnd)) ++ return TRUE; ++ ++ count = info->wnd_count; ++ size = (count + 1) * sizeof(HWND); ++ ++ if (count == 0 || !info->wnd_array) ++ { ++ count = 0; ++ info->wnd_array = (HWND *)heap_alloc(size); ++ } ++ else ++ { ++ wnd_array = (HWND *)heap_realloc(info->wnd_array, size); ++ if (!wnd_array) ++ { ++ heap_free(info->wnd_array); ++ } ++ info->wnd_array = wnd_array; ++ } ++ ++ if (!info->wnd_array) ++ { ++ info->wnd_count = 0; ++ return FALSE; ++ } ++ ++ info->wnd_array[count] = hwnd; ++ info->wnd_count = count + 1; ++ return TRUE; ++} ++ ++static BOOL ++QuerySizeFix(HWND hwnd, INT *pcx, INT *pcy) ++{ ++ MINMAXINFO mmi; ++ DWORD_PTR result; ++ ++ mmi.ptMinTrackSize.x = mmi.ptMinTrackSize.y = 0; ++ mmi.ptMaxTrackSize.x = mmi.ptMaxTrackSize.y = MAXLONG; ++ if (SendMessageTimeoutW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&mmi, ++ SMTO_ABORTIFHUNG | SMTO_NORMAL, 120, &result)) ++ { ++ *pcx = min(max(*pcx, mmi.ptMinTrackSize.x), mmi.ptMaxTrackSize.x); ++ *pcy = min(max(*pcy, mmi.ptMinTrackSize.y), mmi.ptMaxTrackSize.y); ++ return TRUE; ++ } ++ return FALSE; ++} ++ + WORD WINAPI + CascadeWindows (HWND hwndParent, UINT wFlags, const RECT *lpRect, + UINT cKids, const HWND *lpKids) + { +- FIXME("(%p,0x%08x,...,%u,...): stub\n", hwndParent, wFlags, cKids); +- return 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}; ++ CASCADE_INFO info; ++ HWND hwnd, top, prev; ++ HMONITOR monitor; ++ MONITORINFO mi; ++ RECT work_rect, wnd_rect; ++ DWORD i, ret = 0; ++ INT x, y, width, height, new_width, new_height, work_width, work_height, dx, dy; ++ HDWP hDWP; ++ POINT pt; ++ ++ TRACE("(%p,0x%08x,%p,%u,%p)\n", hwndParent, wFlags, lpRect, cKids, lpKids); ++ ++ top = 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 = top; ++ EnumChildWindows(hwndParent, GetCascadeChildProc, (LPARAM)&info); ++ ++ info.top = NULL; ++ GetCascadeChildProc(top, (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) ++ { ++ work_rect = *lpRect; ++ } ++ else if (hwndParent) ++ { ++ GetClientRect(hwndParent, &work_rect); ++ } ++ else ++ { ++ pt.x = pt.y = 0; ++ monitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); ++ mi.cbSize = sizeof(mi); ++ GetMonitorInfoW(monitor, &mi); ++ work_rect = mi.rcWork; ++ } ++ ++ hDWP = BeginDeferWindowPos(info.wnd_count); ++ if (hDWP == NULL) ++ goto cleanup; ++ ++ x = work_rect.left; ++ y = work_rect.top; ++ dx = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXSIZE); ++ dy = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CYSIZE); ++ work_width = work_rect.right - work_rect.left; ++ work_height = work_rect.bottom - work_rect.top; ++ prev = NULL; ++ for (i = info.wnd_count; i > 0;) /* in reverse order */ ++ { ++ --i; ++ hwnd = info.wnd_array[i]; ++ ++ if (!IsWindowVisible(hwnd) || IsIconic(hwnd)) ++ continue; ++ ++ if ((info.flags & MDITILE_SKIPDISABLED) && !IsWindowEnabled(hwnd)) ++ continue; ++ ++ if (IsZoomed(hwnd)) ++ ShowWindow(hwnd, SW_RESTORE | SW_SHOWNA); ++ ++ GetWindowRect(hwnd, &wnd_rect); ++ new_width = width = wnd_rect.right - wnd_rect.left; ++ new_height = height = wnd_rect.bottom - wnd_rect.top; ++ ++ /* if we can change the window size and it is not only one */ ++ if (info.wnd_count != 1 && (GetWindowLongPtrW(hwnd, GWL_STYLE) & WS_THICKFRAME)) ++ { ++ /* check the size */ ++#define THRESHOLD(xy) (((xy) * 5) / 7) /* in the rate 5/7 */ ++ new_width = min(new_width, THRESHOLD(work_width)); ++ new_height = min(new_height, THRESHOLD(work_height)); ++#undef THRESHOLD ++ if (width != new_width || height != new_height) ++ { ++ /* too large. shrink if we can */ ++ if (QuerySizeFix(hwnd, &new_width, &new_height)) ++ { ++ width = new_width; ++ height = new_height; ++ } ++ } ++ } ++ ++ if (x + width > work_rect.right) ++ x = work_rect.left; ++ if (y + height > work_rect.bottom) ++ y = work_rect.top; ++ ++ hDWP = DeferWindowPos(hDWP, hwnd, HWND_TOP, x, y, width, height, SWP_NOACTIVATE); ++ if (hDWP == NULL) ++ { ++ ret = 0; ++ goto cleanup; ++ } ++ ++ x += dx; ++ y += dy; ++ prev = hwnd; ++ ++ret; ++ } ++ ++ EndDeferWindowPos(hDWP); ++ ++ if (prev) ++ SetForegroundWindow(prev); ++ ++cleanup: ++ heap_free(info.wnd_array); ++ ++ return (WORD)ret; + } + + +-- +1.9.1 + diff --git a/patches/user32-Implement-CascadeWindows/definition b/patches/user32-Implement-CascadeWindows/definition new file mode 100644 index 00000000..0e9a58e3 --- /dev/null +++ b/patches/user32-Implement-CascadeWindows/definition @@ -0,0 +1 @@ +Fixes: [45968] user32: Implement CascadeWindows