winemac: Implement support for Cocoa-style full-screen mode.
Based in large part on a patch submitted by Kevin Eaves.
This commit is contained in:
parent
00e53de765
commit
f4f50c9e4a
|
@ -239,6 +239,11 @@ - (void) transformProcessToForeground
|
|||
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 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
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 @@ - (void) adjustFeaturesForState
|
|||
[[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 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
|||
[self setStyleMask:newStyle ^ NSClosableWindowMask];
|
||||
}
|
||||
[self setStyleMask:newStyle];
|
||||
[self adjustFullScreenBehavior:[self collectionBehavior]];
|
||||
}
|
||||
|
||||
[self adjustFeaturesForState];
|
||||
|
@ -648,6 +696,19 @@ - (NSInteger) minimumLevelForActive:(BOOL)active
|
|||
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 @@ - (void) setMacDrvState:(const struct macdrv_window_state*)state
|
|||
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])
|
||||
{
|
||||
if ([self styleMask] & NSFullScreenWindowMask)
|
||||
{
|
||||
[self postDidUnminimizeEvent];
|
||||
discardUnminimize = FALSE;
|
||||
}
|
||||
else
|
||||
[super miniaturize:nil];
|
||||
}
|
||||
else
|
||||
pendingMinimize = TRUE;
|
||||
}
|
||||
|
@ -721,11 +792,14 @@ - (void) setMacDrvState:(const struct macdrv_window_state*)state
|
|||
[self deminiaturize:nil];
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL) addChildWineWindow:(WineWindow*)child assumeVisible:(BOOL)assumeVisible
|
||||
{
|
||||
|
@ -1076,7 +1150,7 @@ - (void) doOrderOut
|
|||
- (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 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect
|
|||
[self updateColorSpace];
|
||||
}
|
||||
|
||||
if (!enteringFullScreen &&
|
||||
[[NSProcessInfo processInfo] systemUptime] - enteredFullScreenTime > 1.0)
|
||||
nonFullscreenFrame = frame;
|
||||
|
||||
[self updateFullscreen];
|
||||
|
||||
if (on_screen)
|
||||
|
@ -1345,6 +1423,8 @@ - (BOOL) validateMenuItem:(NSMenuItem *)menuItem
|
|||
|
||||
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 @@ - (void) miniaturize:(id)sender
|
|||
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 @@ - (void) flagsChanged:(NSEvent *)theEvent
|
|||
/*
|
||||
* ---------- 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 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification
|
|||
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 @@ - (void) windowDidEndLiveResize:(NSNotification *)notification
|
|||
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 @@ - (void)windowDidResize:(NSNotification *)notification
|
|||
macdrv_event* event;
|
||||
NSRect frame = [self contentRectForFrameRect:[self frame]];
|
||||
|
||||
if (exitingFullScreen) return;
|
||||
|
||||
if (self.disabled)
|
||||
{
|
||||
[self setContentMinSize:frame.size];
|
||||
|
@ -1587,6 +1708,7 @@ - (void)windowDidResize:(NSNotification *)notification
|
|||
|
||||
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 @@ - (void) windowWillClose:(NSNotification*)notification
|
|||
[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 @@ static inline RECT rect_from_cgrect(CGRect cgrect)
|
|||
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;
|
||||
|
|
|
@ -274,6 +274,7 @@ extern int macdrv_set_display_mode(const struct macdrv_display* display,
|
|||
} status_item_mouse_move;
|
||||
struct {
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue