Commit f4f50c9e authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

winemac: Implement support for Cocoa-style full-screen mode.

Based in large part on a patch submitted by Kevin Eaves.
parent 00e53de7
......@@ -239,6 +239,11 @@ int macdrv_err_on;
submenu = [[[NSMenu alloc] initWithTitle:@"Window"] autorelease];
[submenu addItemWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@""];
[submenu addItemWithTitle:@"Zoom" action:@selector(performZoom:) keyEquivalent:@""];
if ([NSWindow instancesRespondToSelector:@selector(toggleFullScreen:)])
{
item = [submenu addItemWithTitle:@"Enter Full Screen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"];
[item setKeyEquivalentModifierMask:NSCommandKeyMask | NSAlternateKeyMask | NSControlKeyMask];
}
[submenu addItem:[NSMenuItem separatorItem]];
[submenu addItemWithTitle:@"Bring All to Front" action:@selector(arrangeInFront:) keyEquivalent:@""];
item = [[[NSMenuItem alloc] init] autorelease];
......
......@@ -58,6 +58,11 @@
NSSize savedContentMinSize;
NSSize savedContentMaxSize;
BOOL enteringFullScreen;
BOOL exitingFullScreen;
NSRect nonFullscreenFrame;
NSTimeInterval enteredFullScreenTime;
BOOL ignore_windowDeminiaturize;
BOOL fakingClose;
}
......
......@@ -28,6 +28,20 @@
#import "cocoa_opengl.h"
#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
enum {
NSWindowCollectionBehaviorFullScreenPrimary = 1 << 7,
NSWindowCollectionBehaviorFullScreenAuxiliary = 1 << 8,
NSWindowFullScreenButton = 7,
NSFullScreenWindowMask = 1 << 14,
};
@interface NSWindow (WineFullScreenExtensions)
- (void) toggleFullScreen:(id)sender;
@end
#endif
/* Additional Mac virtual keycode, to complement those in Carbon's <HIToolbox/Events.h>. */
enum {
kVK_RightCommand = 0x36, /* Invented for Wine; was unused */
......@@ -583,6 +597,39 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[[self standardWindowButton:NSWindowMiniaturizeButton] setEnabled:!self.disabled];
if (style & NSResizableWindowMask)
[[self standardWindowButton:NSWindowZoomButton] setEnabled:!self.disabled];
if ([self respondsToSelector:@selector(toggleFullScreen:)])
{
if ([self collectionBehavior] & NSWindowCollectionBehaviorFullScreenPrimary)
[[self standardWindowButton:NSWindowFullScreenButton] setEnabled:!self.disabled];
}
}
- (void) adjustFullScreenBehavior:(NSWindowCollectionBehavior)behavior
{
if ([self respondsToSelector:@selector(toggleFullScreen:)])
{
NSUInteger style = [self styleMask];
if (behavior & NSWindowCollectionBehaviorParticipatesInCycle &&
style & NSResizableWindowMask && !(style & NSUtilityWindowMask))
{
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
}
else
{
behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
if (style & NSFullScreenWindowMask)
[self toggleFullScreen:nil];
}
}
if (behavior != [self collectionBehavior])
{
[self setCollectionBehavior:behavior];
[self adjustFeaturesForState];
}
}
- (void) setWindowFeatures:(const struct macdrv_window_features*)wf
......@@ -606,6 +653,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[self setStyleMask:newStyle ^ NSClosableWindowMask];
}
[self setStyleMask:newStyle];
[self adjustFullScreenBehavior:[self collectionBehavior]];
}
[self adjustFeaturesForState];
......@@ -648,6 +696,19 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
return level;
}
- (void) postDidUnminimizeEvent
{
macdrv_event* event;
/* Coalesce events by discarding any previous ones still in the queue. */
[queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_UNMINIMIZE)
forWindow:self];
event = macdrv_create_event(WINDOW_DID_UNMINIMIZE, self);
[queue postEvent:event];
macdrv_release_event(event);
}
- (void) setMacDrvState:(const struct macdrv_window_state*)state
{
NSWindowCollectionBehavior behavior;
......@@ -703,15 +764,25 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
if ([self isOrderedIn])
[NSApp addWindowsItem:self title:[self title] filename:NO];
}
[self setCollectionBehavior:behavior];
[self adjustFullScreenBehavior:behavior];
if (state->minimized_valid)
{
BOOL discardUnminimize = TRUE;
pendingMinimize = FALSE;
if (state->minimized && ![self isMiniaturized])
{
if ([self isVisible])
[super miniaturize:nil];
{
if ([self styleMask] & NSFullScreenWindowMask)
{
[self postDidUnminimizeEvent];
discardUnminimize = FALSE;
}
else
[super miniaturize:nil];
}
else
pendingMinimize = TRUE;
}
......@@ -721,9 +792,12 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[self deminiaturize:nil];
}
/* Whatever events regarding minimization might have been in the queue are now stale. */
[queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_UNMINIMIZE)
forWindow:self];
if (discardUnminimize)
{
/* Whatever events regarding minimization might have been in the queue are now stale. */
[queue discardEventsMatchingMask:event_mask_for_type(WINDOW_DID_UNMINIMIZE)
forWindow:self];
}
}
}
......@@ -1076,7 +1150,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
- (void) updateFullscreen
{
NSRect contentRect = [self contentRectForFrameRect:[self frame]];
BOOL nowFullscreen = (screen_covered_by_rect(contentRect, [NSScreen screens]) != nil);
BOOL nowFullscreen = !([self styleMask] & NSFullScreenWindowMask) && screen_covered_by_rect(contentRect, [NSScreen screens]);
if (nowFullscreen != fullscreen)
{
......@@ -1130,6 +1204,10 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[self updateColorSpace];
}
if (!enteringFullScreen &&
[[NSProcessInfo processInfo] systemUptime] - enteredFullScreenTime > 1.0)
nonFullscreenFrame = frame;
[self updateFullscreen];
if (on_screen)
......@@ -1345,6 +1423,8 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
if ([menuItem action] == @selector(makeKeyAndOrderFront:))
ret = [self isKeyWindow] || (!self.disabled && !self.noActivate);
if ([menuItem action] == @selector(toggleFullScreen:) && self.disabled)
ret = NO;
return ret;
}
......@@ -1380,6 +1460,12 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
macdrv_release_event(event);
}
- (void) toggleFullScreen:(id)sender
{
if (!self.disabled)
[super toggleFullScreen:sender];
}
// We normally use the generic/calibrated RGB color space for the window,
// rather than the device color space, to avoid expensive color conversion
// which slows down drawing. However, for windows displaying OpenGL, having
......@@ -1483,6 +1569,25 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
/*
* ---------- NSWindowDelegate methods ----------
*/
- (NSSize) window:(NSWindow*)window willUseFullScreenContentSize:(NSSize)proposedSize
{
macdrv_query* query;
NSSize size;
query = macdrv_create_query();
query->type = QUERY_MIN_MAX_INFO;
query->window = (macdrv_window)[self retain];
[self.queue query:query timeout:0.5];
macdrv_release_query(query);
size = [self contentMaxSize];
if (proposedSize.width < size.width)
size.width = proposedSize.width;
if (proposedSize.height < size.height)
size.height = proposedSize.height;
return size;
}
- (void)windowDidBecomeKey:(NSNotification *)notification
{
WineApplicationController* controller = [WineApplicationController sharedController];
......@@ -1500,18 +1605,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
WineApplicationController* controller = [WineApplicationController sharedController];
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_UNMINIMIZE)
forWindow:self];
event = macdrv_create_event(WINDOW_DID_UNMINIMIZE, self);
[queue postEvent:event];
macdrv_release_event(event);
}
[self postDidUnminimizeEvent];
ignore_windowDeminiaturize = FALSE;
[self becameEligibleParentOrChild];
......@@ -1546,6 +1640,31 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
self.liveResizeDisplayTimer = nil;
}
- (void) windowDidEnterFullScreen:(NSNotification*)notification
{
enteringFullScreen = FALSE;
enteredFullScreenTime = [[NSProcessInfo processInfo] systemUptime];
}
- (void) windowDidExitFullScreen:(NSNotification*)notification
{
exitingFullScreen = FALSE;
[self setFrame:nonFullscreenFrame display:YES animate:NO];
[self windowDidResize:nil];
}
- (void) windowDidFailToEnterFullScreen:(NSWindow*)window
{
enteringFullScreen = FALSE;
enteredFullScreenTime = 0;
}
- (void) windowDidFailToExitFullScreen:(NSWindow*)window
{
exitingFullScreen = FALSE;
[self windowDidResize:nil];
}
- (void)windowDidMiniaturize:(NSNotification *)notification
{
if (fullscreen && [self isOnActiveSpace])
......@@ -1573,6 +1692,8 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
macdrv_event* event;
NSRect frame = [self contentRectForFrameRect:[self frame]];
if (exitingFullScreen) return;
if (self.disabled)
{
[self setContentMinSize:frame.size];
......@@ -1587,6 +1708,7 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
event = macdrv_create_event(WINDOW_FRAME_CHANGED, self);
event->window_frame_changed.frame = NSRectToCGRect(frame);
event->window_frame_changed.fullscreen = ([self styleMask] & NSFullScreenWindowMask) != 0;
[queue postEvent:event];
macdrv_release_event(event);
......@@ -1621,6 +1743,17 @@ static inline NSUInteger adjusted_modifiers_for_option_behavior(NSUInteger modif
[latentChildWindows removeAllObjects];
}
- (void) windowWillEnterFullScreen:(NSNotification*)notification
{
enteringFullScreen = TRUE;
nonFullscreenFrame = [self frame];
}
- (void) windowWillExitFullScreen:(NSNotification*)notification
{
exitingFullScreen = TRUE;
}
- (void)windowWillMiniaturize:(NSNotification *)notification
{
[self becameIneligibleParentOrChild];
......
......@@ -246,7 +246,7 @@ void macdrv_handle_event(const macdrv_event *event)
macdrv_window_did_unminimize(hwnd);
break;
case WINDOW_FRAME_CHANGED:
macdrv_window_frame_changed(hwnd, event->window_frame_changed.frame);
macdrv_window_frame_changed(hwnd, event);
break;
case WINDOW_GOT_FOCUS:
macdrv_window_got_focus(hwnd, event);
......
......@@ -155,7 +155,7 @@ extern void surface_clip_to_visible_rect(struct window_surface *window_surface,
extern void macdrv_handle_event(const macdrv_event *event) DECLSPEC_HIDDEN;
extern void macdrv_window_close_requested(HWND hwnd) DECLSPEC_HIDDEN;
extern void macdrv_window_frame_changed(HWND hwnd, CGRect frame) DECLSPEC_HIDDEN;
extern void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event) DECLSPEC_HIDDEN;
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;
......
......@@ -273,7 +273,8 @@ typedef struct macdrv_event {
macdrv_status_item item;
} status_item_mouse_move;
struct {
CGRect frame;
CGRect frame;
int fullscreen;
} window_frame_changed;
struct {
unsigned long serial;
......
......@@ -1654,7 +1654,7 @@ void macdrv_window_close_requested(HWND hwnd)
*
* Handler for WINDOW_FRAME_CHANGED events.
*/
void macdrv_window_frame_changed(HWND hwnd, CGRect frame)
void macdrv_window_frame_changed(HWND hwnd, const macdrv_event *event)
{
struct macdrv_win_data *data;
RECT rect;
......@@ -1674,9 +1674,10 @@ void macdrv_window_frame_changed(HWND hwnd, CGRect frame)
parent = GetAncestor(hwnd, GA_PARENT);
TRACE("win %p/%p new Cocoa frame %s\n", hwnd, data->cocoa_window, wine_dbgstr_cgrect(frame));
TRACE("win %p/%p new Cocoa frame %s\n", hwnd, data->cocoa_window,
wine_dbgstr_cgrect(event->window_frame_changed.frame));
rect = rect_from_cgrect(frame);
rect = rect_from_cgrect(event->window_frame_changed.frame);
macdrv_mac_to_window_rect(data, &rect);
MapWindowPoints(0, parent, (POINT *)&rect, 2);
......@@ -1699,6 +1700,8 @@ void macdrv_window_frame_changed(HWND hwnd, CGRect frame)
release_win_data(data);
if (event->window_frame_changed.fullscreen)
flags |= SWP_NOSENDCHANGING;
if (!(flags & SWP_NOSIZE) || !(flags & SWP_NOMOVE))
SetWindowPos(hwnd, 0, rect.left, rect.top, width, height, flags);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment