From 784a91390eb64bf0e6cf3a27be9becff7ad5787f Mon Sep 17 00:00:00 2001 From: Ken Thomases Date: Thu, 14 Nov 2013 20:52:04 -0600 Subject: [PATCH] winemac: Allow ordering a window into Cocoa's window list even if it's positioned outside of the desktop. Some programs minimize windows which are outside of the desktop. The Mac driver had been leaving such windows ordered out, which prevented them from minimizing and appearing on the Dock. That, in turn, made it difficult for the user to restore them. --- dlls/winemac.drv/cocoa_window.m | 64 ++++++++++----------------------- dlls/winemac.drv/macdrv_cocoa.h | 4 +-- dlls/winemac.drv/window.c | 20 +++++------ 3 files changed, 31 insertions(+), 57 deletions(-) diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index dbac40a4202..f7c2cd09f9e 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -1045,11 +1045,10 @@ - (void) order:(NSWindowOrderingMode)mode childWindow:(WineWindow*)child relativ /* Returns whether or not the window was ordered in, which depends on if its frame intersects any screen. */ - - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)activate + - (void) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)activate { WineApplicationController* controller = [WineApplicationController sharedController]; - BOOL on_screen = frame_intersects_screens([self frame], [NSScreen screens]); - if (on_screen && ![self isMiniaturized]) + if (![self isMiniaturized]) { BOOL needAdjustWindowLevels = FALSE; BOOL wasVisible = [self isVisible]; @@ -1128,8 +1127,6 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)a if (![self isExcludedFromWindowsMenu]) [NSApp addWindowsItem:self title:[self title] filename:NO]; } - - return on_screen; } - (void) doOrderOut @@ -1173,24 +1170,12 @@ - (void) updateFullscreen } } - - (BOOL) setFrameIfOnScreen:(NSRect)contentRect + - (void) setFrameFromWine:(NSRect)contentRect { - NSArray* screens = [NSScreen screens]; - BOOL on_screen = [self isOrderedIn]; - - if (![screens count]) return on_screen; - /* Origin is (left, top) in a top-down space. Need to convert it to (left, bottom) in a bottom-up space. */ [[WineApplicationController sharedController] flipRect:&contentRect]; - if (on_screen) - { - on_screen = frame_intersects_screens(contentRect, screens); - if (!on_screen) - [self doOrderOut]; - } - /* The back end is establishing a new window size and position. It's not interested in any stale events regarding those that may be sitting in the queue. */ @@ -1219,7 +1204,7 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect [self updateFullscreen]; - if (on_screen) + if ([self isOrderedIn]) { /* In case Cocoa adjusted the frame we tried to set, generate a frame-changed event. The back end will ignore it if nothing actually changed. */ @@ -1227,8 +1212,6 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect } } } - - return on_screen; } - (void) setMacDrvParentWindow:(WineWindow*)parent @@ -1415,8 +1398,10 @@ - (NSRect) constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen // If a window is sized to completely cover a screen, then it's in // full-screen mode. In that case, we don't allow NSWindow to constrain // it. + NSArray* screens = [NSScreen screens]; NSRect contentRect = [self contentRectForFrameRect:frameRect]; - if (!screen_covered_by_rect(contentRect, [NSScreen screens])) + if (!screen_covered_by_rect(contentRect, screens) && + frame_intersects_screens(frameRect, screens)) frameRect = [super constrainFrameRect:frameRect toScreen:screen]; return frameRect; } @@ -2042,23 +2027,19 @@ void macdrv_set_cocoa_window_title(macdrv_window w, const unsigned short* title, * non-NULL, it is ordered below that window. Else, if next is non-NULL, * it is ordered above that window. Otherwise, it is ordered to the * front. - * - * Returns true if the window has actually been ordered onto the screen - * (i.e. if its frame intersects with a screen). Otherwise, false. */ -int macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, - macdrv_window next, int activate) +void macdrv_order_cocoa_window(macdrv_window w, macdrv_window p, + macdrv_window n, int activate) { WineWindow* window = (WineWindow*)w; - __block BOOL on_screen; + WineWindow* prev = (WineWindow*)p; + WineWindow* next = (WineWindow*)n; - OnMainThread(^{ - on_screen = [window orderBelow:(WineWindow*)prev - orAbove:(WineWindow*)next - activate:activate]; + OnMainThreadAsync(^{ + [window orderBelow:prev + orAbove:next + activate:activate]; }); - - return on_screen; } /*********************************************************************** @@ -2078,22 +2059,15 @@ void macdrv_hide_cocoa_window(macdrv_window w) /*********************************************************************** * macdrv_set_cocoa_window_frame * - * Move a Cocoa window. If the window has been moved out of the bounds - * of the desktop, it is ordered out. (This routine won't ever order a - * window in, though.) - * - * Returns true if the window is on screen; false otherwise. + * Move a Cocoa window. */ -int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) +void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) { WineWindow* window = (WineWindow*)w; - __block BOOL on_screen; - OnMainThread(^{ - on_screen = [window setFrameIfOnScreen:NSRectFromCGRect(*new_frame)]; + OnMainThreadAsync(^{ + [window setFrameFromWine:NSRectFromCGRect(*new_frame)]; }); - - return on_screen; } /*********************************************************************** diff --git a/dlls/winemac.drv/macdrv_cocoa.h b/dlls/winemac.drv/macdrv_cocoa.h index e0c4f290b41..b452461f413 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -381,10 +381,10 @@ extern void macdrv_set_cocoa_window_state(macdrv_window w, const struct macdrv_window_state* state) DECLSPEC_HIDDEN; extern void macdrv_set_cocoa_window_title(macdrv_window w, const UniChar* title, size_t length) DECLSPEC_HIDDEN; -extern int macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, +extern void macdrv_order_cocoa_window(macdrv_window w, macdrv_window prev, macdrv_window next, int activate) DECLSPEC_HIDDEN; extern void macdrv_hide_cocoa_window(macdrv_window w) DECLSPEC_HIDDEN; -extern int macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) DECLSPEC_HIDDEN; +extern void macdrv_set_cocoa_window_frame(macdrv_window w, const CGRect* new_frame) DECLSPEC_HIDDEN; extern void macdrv_get_cocoa_window_frame(macdrv_window w, CGRect* out_frame) DECLSPEC_HIDDEN; extern void macdrv_set_cocoa_parent_window(macdrv_window w, macdrv_window parent) DECLSPEC_HIDDEN; extern void macdrv_set_window_surface(macdrv_window w, void *surface, pthread_mutex_t *mutex) DECLSPEC_HIDDEN; diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 3d92481e4c7..eac333a7e1b 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -729,6 +729,7 @@ static void show_window(struct macdrv_win_data *data) macdrv_window prev_window = NULL; macdrv_window next_window = NULL; BOOL activate = FALSE; + HWND hwndFocus; /* find window that this one must be after */ prev = GetWindow(data->hwnd, GW_HWNDPREV); @@ -749,15 +750,14 @@ static void show_window(struct macdrv_win_data *data) if (!prev_window) activate = activate_on_focus_time && (GetTickCount() - activate_on_focus_time < 2000); - data->on_screen = macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window, activate); - if (data->on_screen) - { - HWND hwndFocus = GetFocus(); - if (hwndFocus && (data->hwnd == hwndFocus || IsChild(data->hwnd, hwndFocus))) - macdrv_SetFocus(hwndFocus); - if (activate) - activate_on_focus_time = 0; - } + macdrv_order_cocoa_window(data->cocoa_window, prev_window, next_window, activate); + data->on_screen = TRUE; + + hwndFocus = GetFocus(); + if (hwndFocus && (data->hwnd == hwndFocus || IsChild(data->hwnd, hwndFocus))) + macdrv_SetFocus(hwndFocus); + if (activate) + activate_on_focus_time = 0; } @@ -857,7 +857,7 @@ static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags, c if (frame.size.width < 1 || frame.size.height < 1) frame.size.width = frame.size.height = 1; - data->on_screen = macdrv_set_cocoa_window_frame(data->cocoa_window, &frame); + macdrv_set_cocoa_window_frame(data->cocoa_window, &frame); if (old_window_rect && old_whole_rect && (IsRectEmpty(old_window_rect) != IsRectEmpty(&data->window_rect) || old_window_rect->left - old_whole_rect->left != data->window_rect.left - data->whole_rect.left ||