From a3197b8ad09c92c2af463d1a30ecf15c3ed98ed2 Mon Sep 17 00:00:00 2001 From: Ken Thomases <ken@codeweavers.com> Date: Wed, 18 Sep 2013 13:00:37 -0500 Subject: [PATCH] winemac: At the start of a resize operation, get window min/max size info and pass it to Cocoa. --- dlls/winemac.drv/cocoa_window.h | 3 + dlls/winemac.drv/cocoa_window.m | 52 +++++++++--- dlls/winemac.drv/event.c | 4 + dlls/winemac.drv/macdrv.h | 1 + dlls/winemac.drv/macdrv_cocoa.h | 2 + dlls/winemac.drv/window.c | 136 ++++++++++++++++++++++++++++++++ 6 files changed, 188 insertions(+), 10 deletions(-) diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 5cf47b434d5..86728125233 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -55,6 +55,9 @@ @interface WineWindow : NSPanel <NSWindowDelegate> void* imeData; BOOL commandDone; + NSSize savedContentMinSize; + NSSize savedContentMaxSize; + BOOL causing_becomeKeyWindow; BOOL ignore_windowMiniaturize; BOOL ignore_windowDeminiaturize; diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index 2ad406f608a..e8ac79c1c9b 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -500,6 +500,8 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w [window setDelegate:window]; window.hwnd = hwnd; window.queue = queue; + window->savedContentMinSize = NSZeroSize; + window->savedContentMaxSize = NSMakeSize(FLT_MAX, FLT_MAX); [window registerForDraggedTypes:[NSArray arrayWithObjects:(NSString*)kUTTypeData, (NSString*)kUTTypeContent, @@ -1131,14 +1133,14 @@ - (void) setDisabled:(BOOL)newValue if (disabled) { - NSSize size = [self frame].size; - [self setMinSize:size]; - [self setMaxSize:size]; + NSSize size = [self contentRectForFrameRect:[self frame]].size; + [self setContentMinSize:size]; + [self setContentMaxSize:size]; } else { - [self setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)]; - [self setMinSize:NSZeroSize]; + [self setContentMaxSize:savedContentMaxSize]; + [self setContentMinSize:savedContentMinSize]; } } } @@ -1231,6 +1233,17 @@ - (void) postKeyEvent:(NSEvent *)theEvent event:theEvent]; } + - (void) setWineMinSize:(NSSize)minSize maxSize:(NSSize)maxSize + { + savedContentMinSize = minSize; + savedContentMaxSize = maxSize; + if (!self.disabled) + { + [self setContentMinSize:minSize]; + [self setContentMaxSize:maxSize]; + } + } + /* * ---------- NSWindow method overrides ---------- @@ -1480,16 +1493,14 @@ - (void)windowDidResignKey:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification { macdrv_event* event; - NSRect frame = [self frame]; + NSRect frame = [self contentRectForFrameRect:[self frame]]; if (self.disabled) { - NSSize size = frame.size; - [self setMinSize:size]; - [self setMaxSize:size]; + [self setContentMinSize:frame.size]; + [self setContentMaxSize:frame.size]; } - frame = [self contentRectForFrameRect:frame]; [[WineApplicationController sharedController] flipRect:&frame]; /* Coalesce events by discarding any previous ones still in the queue. */ @@ -1554,6 +1565,13 @@ - (void)windowWillMiniaturize:(NSNotification *)notification - (void) windowWillStartLiveResize:(NSNotification *)notification { + macdrv_query* query = macdrv_create_query(); + query->type = QUERY_RESIZE_START; + query->window = (macdrv_window)[self retain]; + + [self.queue query:query timeout:0.3]; + macdrv_release_query(query); + // There's a strange restriction in window redrawing during Cocoa- // managed window resizing. Only calls to -[NSView setNeedsDisplay...] // that happen synchronously when Cocoa tells us that our window size @@ -2010,6 +2028,20 @@ void macdrv_give_cocoa_window_focus(macdrv_window w, int activate) }); } +/*********************************************************************** + * macdrv_set_window_min_max_sizes + * + * Sets the window's minimum and maximum content sizes. + */ +void macdrv_set_window_min_max_sizes(macdrv_window w, CGSize min_size, CGSize max_size) +{ + WineWindow* window = (WineWindow*)w; + + OnMainThread(^{ + [window setWineMinSize:NSSizeFromCGSize(min_size) maxSize:NSSizeFromCGSize(max_size)]; + }); +} + /*********************************************************************** * macdrv_create_view * diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 8a8acf36b53..97f1e3b38a8 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -146,6 +146,10 @@ static void macdrv_query_event(HWND hwnd, const macdrv_event *event) TRACE("QUERY_PASTEBOARD_DATA\n"); success = query_pasteboard_data(hwnd, query->pasteboard_data.type); break; + case QUERY_RESIZE_START: + TRACE("QUERY_RESIZE_START\n"); + success = query_resize_start(hwnd); + break; default: FIXME("unrecognized query type %d\n", query->type); break; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index 0e7d364be71..d308e690f49 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -161,6 +161,7 @@ static inline RECT rect_from_cgrect(CGRect cgrect) extern void macdrv_app_quit_requested(const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_window_did_minimize(HWND hwnd) DECLSPEC_HIDDEN; extern void macdrv_window_did_unminimize(HWND hwnd) DECLSPEC_HIDDEN; +extern BOOL query_resize_start(HWND hwnd) DECLSPEC_HIDDEN; extern void macdrv_mouse_button(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_mouse_moved(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index 1f68b615244..71d8c9f1513 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -272,6 +272,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display, QUERY_DRAG_OPERATION, QUERY_IME_CHAR_RECT, QUERY_PASTEBOARD_DATA, + QUERY_RESIZE_START, NUM_QUERY_TYPES }; @@ -373,6 +374,7 @@ extern void macdrv_set_window_color_key(macdrv_window w, CGFloat keyRed, CGFloat extern void macdrv_clear_window_color_key(macdrv_window w) DECLSPEC_HIDDEN; extern void macdrv_window_use_per_pixel_alpha(macdrv_window w, int use_per_pixel_alpha) DECLSPEC_HIDDEN; extern void macdrv_give_cocoa_window_focus(macdrv_window w, int activate) DECLSPEC_HIDDEN; +extern void macdrv_set_window_min_max_sizes(macdrv_window w, CGSize min_size, CGSize max_size) DECLSPEC_HIDDEN; extern macdrv_view macdrv_create_view(macdrv_window w, CGRect rect) DECLSPEC_HIDDEN; extern void macdrv_dispose_view(macdrv_view v) DECLSPEC_HIDDEN; extern void macdrv_set_view_window_and_frame(macdrv_view v, macdrv_window w, CGRect rect) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 59912909ddb..411270c4838 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -464,6 +464,129 @@ static void sync_window_opacity(struct macdrv_win_data *data, COLORREF key, BYTE } +/*********************************************************************** + * sync_window_min_max_info + */ +static void sync_window_min_max_info(HWND hwnd) +{ + LONG style = GetWindowLongW(hwnd, GWL_STYLE); + LONG exstyle = GetWindowLongW(hwnd, GWL_EXSTYLE); + RECT win_rect, primary_monitor_rect; + MINMAXINFO minmax; + LONG adjustedStyle; + INT xinc, yinc; + WINDOWPLACEMENT wpl; + HMONITOR monitor; + struct macdrv_win_data *data; + RECT min_rect, max_rect; + CGSize min_size, max_size; + + TRACE("win %p\n", hwnd); + + if (!macdrv_get_cocoa_window(hwnd, FALSE)) return; + + GetWindowRect(hwnd, &win_rect); + minmax.ptReserved.x = win_rect.left; + minmax.ptReserved.y = win_rect.top; + + if ((style & WS_CAPTION) == WS_CAPTION) + adjustedStyle = style & ~WS_BORDER; /* WS_CAPTION = WS_DLGFRAME | WS_BORDER */ + else + adjustedStyle = style; + + primary_monitor_rect.left = primary_monitor_rect.top = 0; + primary_monitor_rect.right = GetSystemMetrics(SM_CXSCREEN); + primary_monitor_rect.bottom = GetSystemMetrics(SM_CYSCREEN); + AdjustWindowRectEx(&primary_monitor_rect, adjustedStyle, ((style & WS_POPUP) && GetMenu(hwnd)), exstyle); + + xinc = -primary_monitor_rect.left; + yinc = -primary_monitor_rect.top; + + minmax.ptMaxSize.x = primary_monitor_rect.right - primary_monitor_rect.left; + minmax.ptMaxSize.y = primary_monitor_rect.bottom - primary_monitor_rect.top; + minmax.ptMaxPosition.x = -xinc; + minmax.ptMaxPosition.y = -yinc; + 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); + + wpl.length = sizeof(wpl); + if (GetWindowPlacement(hwnd, &wpl) && (wpl.ptMaxPosition.x != -1 || wpl.ptMaxPosition.y != -1)) + { + minmax.ptMaxPosition = wpl.ptMaxPosition; + + /* Convert from GetWindowPlacement's workspace coordinates to screen coordinates. */ + minmax.ptMaxPosition.x -= wpl.rcNormalPosition.left - win_rect.left; + minmax.ptMaxPosition.y -= wpl.rcNormalPosition.top - win_rect.top; + } + + TRACE("initial ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize), + wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize)); + + SendMessageW(hwnd, WM_GETMINMAXINFO, 0, (LPARAM)&minmax); + + TRACE("app's ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize), + wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize)); + + /* if the app didn't change the values, adapt them for the window's monitor */ + if ((monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY))) + { + MONITORINFO mon_info; + RECT monitor_rect; + + mon_info.cbSize = sizeof(mon_info); + GetMonitorInfoW(monitor, &mon_info); + + if ((style & WS_MAXIMIZEBOX) && ((style & WS_CAPTION) == WS_CAPTION || !(style & WS_POPUP))) + monitor_rect = mon_info.rcWork; + else + monitor_rect = mon_info.rcMonitor; + + if (minmax.ptMaxSize.x == primary_monitor_rect.right - primary_monitor_rect.left && + minmax.ptMaxSize.y == primary_monitor_rect.bottom - primary_monitor_rect.top) + { + minmax.ptMaxSize.x = (monitor_rect.right - monitor_rect.left) + 2 * xinc; + minmax.ptMaxSize.y = (monitor_rect.bottom - monitor_rect.top) + 2 * yinc; + } + if (minmax.ptMaxPosition.x == -xinc && minmax.ptMaxPosition.y == -yinc) + { + minmax.ptMaxPosition.x = monitor_rect.left - xinc; + minmax.ptMaxPosition.y = monitor_rect.top - yinc; + } + } + + minmax.ptMaxTrackSize.x = max(minmax.ptMaxTrackSize.x, minmax.ptMinTrackSize.x); + minmax.ptMaxTrackSize.y = max(minmax.ptMaxTrackSize.y, minmax.ptMinTrackSize.y); + + TRACE("adjusted ptMaxSize %s ptMaxPosition %s ptMinTrackSize %s ptMaxTrackSize %s\n", wine_dbgstr_point(&minmax.ptMaxSize), + wine_dbgstr_point(&minmax.ptMaxPosition), wine_dbgstr_point(&minmax.ptMinTrackSize), wine_dbgstr_point(&minmax.ptMaxTrackSize)); + + if ((data = get_win_data(hwnd)) && data->cocoa_window) + { + SetRect(&min_rect, 0, 0, minmax.ptMinTrackSize.x, minmax.ptMinTrackSize.y); + SetRect(&max_rect, 0, 0, minmax.ptMaxTrackSize.x, minmax.ptMaxTrackSize.y); + macdrv_window_to_mac_rect(data, style, &min_rect); + macdrv_window_to_mac_rect(data, style, &max_rect); + min_size = CGSizeMake(min_rect.right - min_rect.left, min_rect.bottom - min_rect.top); + max_size = CGSizeMake(max_rect.right - max_rect.left, max_rect.bottom - max_rect.top); + + TRACE("min_size (%g,%g) max_size (%g,%g)\n", min_size.width, min_size.height, max_size.width, max_size.height); + macdrv_set_window_min_max_sizes(data->cocoa_window, min_size, max_size); + } + + release_win_data(data); +} + + /********************************************************************** * create_cocoa_window * @@ -1858,3 +1981,16 @@ fail: } macdrv_quit_reply(FALSE); } + + +/*********************************************************************** + * query_resize_start + * + * Handler for QUERY_RESIZE_START query. + */ +BOOL query_resize_start(HWND hwnd) +{ + TRACE("hwnd %p\n", hwnd); + sync_window_min_max_info(hwnd); + return TRUE; +}