diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h index 62ae75a6083..0aa31399609 100644 --- a/dlls/winemac.drv/cocoa_window.h +++ b/dlls/winemac.drv/cocoa_window.h @@ -47,6 +47,8 @@ @interface WineWindow : NSPanel BOOL usePerPixelAlpha; BOOL causing_becomeKeyWindow; + BOOL ignore_windowMiniaturize; + BOOL ignore_windowDeminiaturize; } @property (retain, readonly, nonatomic) WineEventQueue* queue; diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m index e5e78f99076..5d912212c40 100644 --- a/dlls/winemac.drv/cocoa_window.m +++ b/dlls/winemac.drv/cocoa_window.m @@ -287,6 +287,22 @@ - (void) setMacDrvState:(const struct macdrv_window_state*)state [NSApp addWindowsItem:self title:[self title] filename:NO]; } [self setCollectionBehavior:behavior]; + + if (state->minimized && ![self isMiniaturized]) + { + ignore_windowMiniaturize = TRUE; + [self miniaturize:nil]; + } + else if (!state->minimized && [self isMiniaturized]) + { + ignore_windowDeminiaturize = TRUE; + [self deminiaturize:nil]; + } + + /* Whatever events regarding minimization might have been in the queue are now stale. */ + [queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_MINIMIZE) | + event_mask_for_type(WINDOW_DID_UNMINIMIZE) + forWindow:self]; } /* Returns whether or not the window was ordered in, which depends on if @@ -551,6 +567,25 @@ - (void)windowDidBecomeKey:(NSNotification *)notification [NSApp windowGotFocus:self]; } + - (void)windowDidDeminiaturize:(NSNotification *)notification + { + if (!ignore_windowDeminiaturize) + { + macdrv_event event; + + /* Coalesce events by discarding any previous ones still in the queue. */ + [queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_MINIMIZE) | + event_mask_for_type(WINDOW_DID_UNMINIMIZE) + forWindow:self]; + + event.type = WINDOW_DID_UNMINIMIZE; + event.window = (macdrv_window)[self retain]; + [queue postEvent:&event]; + } + + ignore_windowDeminiaturize = FALSE; + } + - (void)windowDidMove:(NSNotification *)notification { [self windowDidResize:notification]; @@ -593,6 +628,25 @@ - (BOOL)windowShouldClose:(id)sender return NO; } + - (void)windowWillMiniaturize:(NSNotification *)notification + { + if (!ignore_windowMiniaturize) + { + macdrv_event event; + + /* Coalesce events by discarding any previous ones still in the queue. */ + [queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_MINIMIZE) | + event_mask_for_type(WINDOW_DID_UNMINIMIZE) + forWindow:self]; + + event.type = WINDOW_DID_MINIMIZE; + event.window = (macdrv_window)[self retain]; + [queue postEvent:&event]; + } + + ignore_windowMiniaturize = FALSE; + } + @end diff --git a/dlls/winemac.drv/event.c b/dlls/winemac.drv/event.c index 654e691cc7b..616f398ce5b 100644 --- a/dlls/winemac.drv/event.c +++ b/dlls/winemac.drv/event.c @@ -35,6 +35,8 @@ static const char *dbgstr_event(int type) "APP_DEACTIVATED", "MOUSE_BUTTON", "WINDOW_CLOSE_REQUESTED", + "WINDOW_DID_MINIMIZE", + "WINDOW_DID_UNMINIMIZE", "WINDOW_FRAME_CHANGED", "WINDOW_GOT_FOCUS", "WINDOW_LOST_FOCUS", @@ -61,6 +63,8 @@ static macdrv_event_mask get_event_mask(DWORD mask) { event_mask |= event_mask_for_type(APP_DEACTIVATED); event_mask |= event_mask_for_type(WINDOW_CLOSE_REQUESTED); + event_mask |= event_mask_for_type(WINDOW_DID_MINIMIZE); + event_mask |= event_mask_for_type(WINDOW_DID_UNMINIMIZE); event_mask |= event_mask_for_type(WINDOW_FRAME_CHANGED); event_mask |= event_mask_for_type(WINDOW_GOT_FOCUS); event_mask |= event_mask_for_type(WINDOW_LOST_FOCUS); @@ -96,6 +100,12 @@ void macdrv_handle_event(macdrv_event *event) case WINDOW_CLOSE_REQUESTED: macdrv_window_close_requested(hwnd); break; + case WINDOW_DID_MINIMIZE: + macdrv_window_did_minimize(hwnd); + break; + case WINDOW_DID_UNMINIMIZE: + macdrv_window_did_unminimize(hwnd); + break; case WINDOW_FRAME_CHANGED: macdrv_window_frame_changed(hwnd, event->window_frame_changed.frame); break; diff --git a/dlls/winemac.drv/macdrv.h b/dlls/winemac.drv/macdrv.h index d1b73fea4d0..b88fe282a76 100644 --- a/dlls/winemac.drv/macdrv.h +++ b/dlls/winemac.drv/macdrv.h @@ -105,10 +105,11 @@ static inline RECT rect_from_cgrect(CGRect cgrect) RECT whole_rect; /* Mac window rectangle for the whole window relative to parent */ RECT client_rect; /* client area relative to parent */ COLORREF color_key; /* color key for layered window; CLR_INVALID is not color keyed */ - BOOL on_screen : 1; /* is window ordered in? */ + BOOL on_screen : 1; /* is window ordered in? (minimized or not) */ BOOL shaped : 1; /* is window using a custom region shape? */ BOOL layered : 1; /* is window layered and with valid attributes? */ BOOL per_pixel_alpha : 1; /* is window using per-pixel alpha? */ + BOOL minimized : 1; /* is window minimized? */ struct window_surface *surface; }; @@ -122,6 +123,8 @@ static inline RECT rect_from_cgrect(CGRect cgrect) extern void macdrv_window_got_focus(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_window_lost_focus(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN; extern void macdrv_app_deactivated(void) DECLSPEC_HIDDEN; +extern void macdrv_window_did_minimize(HWND hwnd) DECLSPEC_HIDDEN; +extern void macdrv_window_did_unminimize(HWND hwnd) DECLSPEC_HIDDEN; extern void macdrv_mouse_button(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 dcdf91d2b1e..c8d32f127ce 100644 --- a/dlls/winemac.drv/macdrv_cocoa.h +++ b/dlls/winemac.drv/macdrv_cocoa.h @@ -127,6 +127,8 @@ APP_DEACTIVATED, MOUSE_BUTTON, WINDOW_CLOSE_REQUESTED, + WINDOW_DID_MINIMIZE, + WINDOW_DID_UNMINIMIZE, WINDOW_FRAME_CHANGED, WINDOW_GOT_FOCUS, WINDOW_LOST_FOCUS, @@ -186,6 +188,7 @@ extern int macdrv_get_event_from_queue(macdrv_event_queue queue, unsigned int floating:1; unsigned int excluded_by_expose:1; unsigned int excluded_by_cycle:1; + unsigned int minimized:1; }; extern macdrv_window macdrv_create_cocoa_window(const struct macdrv_window_features* wf, diff --git a/dlls/winemac.drv/window.c b/dlls/winemac.drv/window.c index 810d3aeb201..03e98814165 100644 --- a/dlls/winemac.drv/window.c +++ b/dlls/winemac.drv/window.c @@ -113,6 +113,7 @@ static void get_cocoa_window_state(struct macdrv_win_data *data, state->excluded_by_expose = state->excluded_by_cycle = !(ex_style & WS_EX_APPWINDOW) && (GetWindow(data->hwnd, GW_OWNER) || (ex_style & (WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE))); + state->minimized = (style & WS_MINIMIZE) != 0; } @@ -337,6 +338,7 @@ static void set_cocoa_window_properties(struct macdrv_win_data *data) get_cocoa_window_state(data, style, ex_style, &state); macdrv_set_cocoa_window_state(data->cocoa_window, &state); + data->minimized = state.minimized; } @@ -674,7 +676,11 @@ RGNDATA *get_region_data(HRGN hrgn, HDC hdc_lptodp) */ static void sync_window_position(struct macdrv_win_data *data, UINT swp_flags) { - CGRect frame = cgrect_from_rect(data->whole_rect); + CGRect frame; + + if (data->minimized) return; + + frame = cgrect_from_rect(data->whole_rect); constrain_window_frame(&frame); data->on_screen = macdrv_set_cocoa_window_frame(data->cocoa_window, &frame); @@ -1010,7 +1016,9 @@ UINT CDECL macdrv_ShowWindow(HWND hwnd, INT cmd, RECT *rect, UINT swp) if (!thread_data->current_event || thread_data->current_event->window != data->cocoa_window) goto done; - if (thread_data->current_event->type != WINDOW_FRAME_CHANGED) + if (thread_data->current_event->type != WINDOW_FRAME_CHANGED && + thread_data->current_event->type != WINDOW_DID_MINIMIZE && + thread_data->current_event->type != WINDOW_DID_UNMINIMIZE) goto done; TRACE("win %p/%p cmd %d at %s flags %08x\n", @@ -1309,7 +1317,9 @@ void CDECL macdrv_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, /* check if we are currently processing an event relevant to this window */ if (!thread_data || !thread_data->current_event || thread_data->current_event->window != data->cocoa_window || - thread_data->current_event->type != WINDOW_FRAME_CHANGED) + (thread_data->current_event->type != WINDOW_FRAME_CHANGED && + thread_data->current_event->type != WINDOW_DID_MINIMIZE && + thread_data->current_event->type != WINDOW_DID_UNMINIMIZE)) { sync_window_position(data, swp_flags); set_cocoa_window_properties(data); @@ -1484,3 +1494,68 @@ void macdrv_app_deactivated(void) SetForegroundWindow(GetDesktopWindow()); } } + + +/*********************************************************************** + * macdrv_window_did_minimize + * + * Handler for WINDOW_DID_MINIMIZE events. + */ +void macdrv_window_did_minimize(HWND hwnd) +{ + struct macdrv_win_data *data; + DWORD style; + + TRACE("win %p\n", hwnd); + + if (!(data = get_win_data(hwnd))) return; + if (data->minimized) goto done; + + style = GetWindowLongW(hwnd, GWL_STYLE); + + data->minimized = TRUE; + if ((style & WS_MINIMIZEBOX) && !(style & WS_DISABLED)) + { + TRACE("minimizing win %p/%p\n", hwnd, data->cocoa_window); + release_win_data(data); + SendMessageW(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + return; + } + TRACE("not minimizing win %p/%p style %08x\n", hwnd, data->cocoa_window, style); + +done: + release_win_data(data); +} + + +/*********************************************************************** + * macdrv_window_did_unminimize + * + * Handler for WINDOW_DID_UNMINIMIZE events. + */ +void macdrv_window_did_unminimize(HWND hwnd) +{ + struct macdrv_win_data *data; + DWORD style; + + TRACE("win %p\n", hwnd); + + if (!(data = get_win_data(hwnd))) return; + if (!data->minimized) goto done; + + style = GetWindowLongW(hwnd, GWL_STYLE); + + data->minimized = FALSE; + if (style & (WS_MINIMIZE | WS_MAXIMIZE)) + { + TRACE("restoring win %p/%p\n", hwnd, data->cocoa_window); + release_win_data(data); + SendMessageW(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); + return; + } + + TRACE("not restoring win %p/%p style %08x\n", hwnd, data->cocoa_window, style); + +done: + release_win_data(data); +}