winemac: Add an option to capture the displays for full-screen windows in addition to display mode changes.

Under HKCU\Software\Wine\Mac Driver, set string value
CaptureDisplaysForFullscreen to "y" to enable the new behavior.
This commit is contained in:
Ken Thomases 2013-06-06 17:43:06 -05:00 committed by Alexandre Julliard
parent ba40509f90
commit 220b8b7946
6 changed files with 120 additions and 20 deletions

View File

@ -66,6 +66,7 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
NSUInteger unmatchedMouseDowns;
NSMutableDictionary* originalDisplayModes;
BOOL displaysCapturedForFullscreen;
NSArray* cursorFrames;
int cursorFrame;
@ -109,6 +110,7 @@ - (void) flipRect:(NSRect*)rect;
- (WineWindow*) frontWineWindow;
- (void) adjustWindowLevels;
- (void) updateFullscreenWindows;
- (BOOL) handleEvent:(NSEvent*)anEvent;
- (void) didSendEvent:(NSEvent*)anEvent;

View File

@ -575,6 +575,41 @@ - (void) adjustWindowLevels
[self adjustWindowLevels:[NSApp isActive]];
}
- (void) updateFullscreenWindows
{
if (capture_displays_for_fullscreen && [NSApp isActive])
{
BOOL anyFullscreen = FALSE;
NSNumber* windowNumber;
for (windowNumber in [NSWindow windowNumbersWithOptions:0])
{
WineWindow* window = (WineWindow*)[NSApp windowWithWindowNumber:[windowNumber integerValue]];
if ([window isKindOfClass:[WineWindow class]] && window.fullscreen)
{
anyFullscreen = TRUE;
break;
}
}
if (anyFullscreen)
{
if ([self areDisplaysCaptured] || CGCaptureAllDisplays() == CGDisplayNoErr)
displaysCapturedForFullscreen = TRUE;
}
else if (displaysCapturedForFullscreen)
{
if ([originalDisplayModes count] || CGReleaseAllDisplays() == CGDisplayNoErr)
displaysCapturedForFullscreen = FALSE;
}
}
}
- (void) activeSpaceDidChange
{
[self updateFullscreenWindows];
[self adjustWindowLevels];
}
- (void) sendDisplaysChanged:(BOOL)activating
{
macdrv_event* event;
@ -680,6 +715,7 @@ - (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
if ([originalDisplayModes count] == 1) // If this is the last changed display, do a blanket reset
{
CGRestorePermanentDisplayConfiguration();
if (!displaysCapturedForFullscreen)
CGReleaseAllDisplays();
[originalDisplayModes removeAllObjects];
ret = TRUE;
@ -695,7 +731,8 @@ - (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
}
else
{
if ([originalDisplayModes count] || CGCaptureAllDisplays() == CGDisplayNoErr)
if ([originalDisplayModes count] || displaysCapturedForFullscreen ||
CGCaptureAllDisplays() == CGDisplayNoErr)
{
if (CGDisplaySetDisplayMode(displayID, mode, NULL) == CGDisplayNoErr)
{
@ -705,6 +742,7 @@ - (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
else if (![originalDisplayModes count])
{
CGRestorePermanentDisplayConfiguration();
if (!displaysCapturedForFullscreen)
CGReleaseAllDisplays();
}
}
@ -720,7 +758,7 @@ - (BOOL) setMode:(CGDisplayModeRef)mode forDisplay:(CGDirectDisplayID)displayID
- (BOOL) areDisplaysCaptured
{
return ([originalDisplayModes count] > 0);
return ([originalDisplayModes count] > 0 || displaysCapturedForFullscreen);
}
- (void) hideCursor
@ -851,11 +889,12 @@ - (void) handleCommandTab
NSRunningApplication* app;
NSRunningApplication* otherValidApp = nil;
if ([originalDisplayModes count])
if ([originalDisplayModes count] || displaysCapturedForFullscreen)
{
CGRestorePermanentDisplayConfiguration();
CGReleaseAllDisplays();
[originalDisplayModes removeAllObjects];
displaysCapturedForFullscreen = FALSE;
}
for (app in [[NSWorkspace sharedWorkspace] runningApplications])
@ -1661,6 +1700,12 @@ - (void) setupObservations
lastTargetWindow = nil;
if (window == self.mouseCaptureWindow)
self.mouseCaptureWindow = nil;
if ([window isKindOfClass:[WineWindow class]] && [(WineWindow*)window isFullscreen])
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0), dispatch_get_main_queue(), ^{
[self updateFullscreenWindows];
});
}
}];
[nc addObserver:self
@ -1673,7 +1718,7 @@ - (void) setupObservations
[NSTextInputContext self];
[wsnc addObserver:self
selector:@selector(adjustWindowLevels)
selector:@selector(activeSpaceDidChange)
name:NSWorkspaceActiveSpaceDidChangeNotification
object:nil];
}
@ -1705,6 +1750,7 @@ - (void)applicationDidBecomeActive:(NSNotification *)notification
{
[self activateCursorClipping];
[self updateFullscreenWindows];
[self adjustWindowLevels:YES];
if (beenActive && ![self frontWineWindow])

View File

@ -29,6 +29,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
BOOL disabled;
BOOL noActivate;
BOOL floating;
BOOL fullscreen;
BOOL pendingMinimize;
WineWindow* latentParentWindow;
@ -60,7 +61,9 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
@property (retain, readonly, nonatomic) WineEventQueue* queue;
@property (readonly, nonatomic) BOOL floating;
@property (readonly, getter=isFullscreen, nonatomic) BOOL fullscreen;
- (NSInteger) minimumLevelForActive:(BOOL)active;
- (void) updateFullscreen;
@end

View File

@ -450,7 +450,7 @@ - (NSInteger) windowLevel
@implementation WineWindow
@synthesize disabled, noActivate, floating, latentParentWindow, hwnd, queue;
@synthesize disabled, noActivate, floating, fullscreen, latentParentWindow, hwnd, queue;
@synthesize surface, surface_mutex;
@synthesize shape, shapeChangedSinceLastDraw;
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
@ -513,11 +513,18 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
[window setContentView:contentView];
[window setInitialFirstResponder:contentView];
[[NSNotificationCenter defaultCenter] addObserver:window
selector:@selector(updateFullscreen)
name:NSApplicationDidChangeScreenParametersNotification
object:NSApp];
[window updateFullscreen];
return window;
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[liveResizeDisplayTimer invalidate];
[liveResizeDisplayTimer release];
[queue release];
@ -570,13 +577,8 @@ - (BOOL) isOrderedIn
- (NSInteger) minimumLevelForActive:(BOOL)active
{
NSScreen* screen;
BOOL fullscreen;
NSInteger level;
screen = screen_covered_by_rect([self frame], [NSScreen screens]);
fullscreen = (screen != nil);
if (self.floating && (active || topmost_float_inactive == TOPMOST_FLOAT_INACTIVE_ALL ||
(topmost_float_inactive == TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN && !fullscreen)))
level = NSFloatingWindowLevel;
@ -587,7 +589,7 @@ - (NSInteger) minimumLevelForActive:(BOOL)active
{
BOOL captured;
captured = (screen || [self screen]) && [[WineApplicationController sharedController] areDisplaysCaptured];
captured = (fullscreen || [self screen]) && [[WineApplicationController sharedController] areDisplaysCaptured];
if (captured || fullscreen)
{
@ -717,6 +719,7 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
if (on_screen && ![self isMiniaturized])
{
BOOL needAdjustWindowLevels = FALSE;
BOOL wasVisible = [self isVisible];
[controller transformProcessToForeground];
@ -758,7 +761,11 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
needAdjustWindowLevels = TRUE;
}
if (needAdjustWindowLevels)
{
if (!wasVisible && fullscreen && [self isOnActiveSpace])
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
}
if (pendingMinimize)
{
@ -783,15 +790,38 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
- (void) doOrderOut
{
WineApplicationController* controller = [WineApplicationController sharedController];
BOOL wasVisible = [self isVisible];
BOOL wasOnActiveSpace = [self isOnActiveSpace];
if ([self isMiniaturized])
pendingMinimize = TRUE;
self.latentParentWindow = [self parentWindow];
[latentParentWindow removeChildWindow:self];
[self orderOut:nil];
[[WineApplicationController sharedController] adjustWindowLevels];
if (wasVisible && wasOnActiveSpace && fullscreen)
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
[NSApp removeWindowsItem:self];
}
- (void) updateFullscreen
{
NSRect contentRect = [self contentRectForFrameRect:[self frame]];
BOOL nowFullscreen = (screen_covered_by_rect(contentRect, [NSScreen screens]) != nil);
if (nowFullscreen != fullscreen)
{
WineApplicationController* controller = [WineApplicationController sharedController];
fullscreen = nowFullscreen;
if ([self isVisible] && [self isOnActiveSpace])
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
}
}
- (BOOL) setFrameIfOnScreen:(NSRect)contentRect
{
NSArray* screens = [NSScreen screens];
@ -829,14 +859,10 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect
else
[self setFrame:frame display:YES];
[self updateFullscreen];
if (on_screen)
{
BOOL fullscreen = (screen_covered_by_rect(frame, screens) != nil);
BOOL oldFullscreen = (screen_covered_by_rect(oldFrame, screens) != nil);
if (fullscreen != oldFullscreen)
[[WineApplicationController sharedController] adjustWindowLevels];
/* 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. */
[self windowDidResize:nil];
@ -929,6 +955,7 @@ - (void) makeFocused:(BOOL)activate
WineApplicationController* controller = [WineApplicationController sharedController];
NSArray* screens;
WineWindow* front;
BOOL wasVisible = [self isVisible];
[controller transformProcessToForeground];
@ -961,6 +988,8 @@ - (void) makeFocused:(BOOL)activate
if (front && [self level] < [front level])
[self setLevel:[front level]];
[self orderFront:nil];
if (!wasVisible && fullscreen && [self isOnActiveSpace])
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
if (pendingMinimize)
@ -1071,6 +1100,7 @@ - (void) makeKeyAndOrderFront:(id)sender
{
WineApplicationController* controller = [WineApplicationController sharedController];
WineWindow* front = [controller frontWineWindow];
BOOL wasVisible = [self isVisible];
if (![self isKeyWindow] && !self.disabled && !self.noActivate)
[controller windowGotFocus:self];
@ -1078,6 +1108,8 @@ - (void) makeKeyAndOrderFront:(id)sender
if (front && [self level] < [front level])
[self setLevel:[front level]];
[self orderFront:nil];
if (!wasVisible && fullscreen && [self isOnActiveSpace])
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
if (pendingMinimize)
@ -1220,6 +1252,8 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification
ignore_windowDeminiaturize = FALSE;
if (fullscreen && [self isOnActiveSpace])
[controller updateFullscreenWindows];
[controller adjustWindowLevels];
if (!self.disabled && !self.noActivate)
@ -1240,6 +1274,12 @@ - (void) windowDidEndLiveResize:(NSNotification *)notification
liveResizeDisplayTimer = nil;
}
- (void)windowDidMiniaturize:(NSNotification *)notification
{
if (fullscreen && [self isOnActiveSpace])
[[WineApplicationController sharedController] updateFullscreenWindows];
}
- (void)windowDidMove:(NSNotification *)notification
{
[self windowDidResize:notification];
@ -1281,6 +1321,7 @@ - (void)windowDidResize:(NSNotification *)notification
macdrv_release_event(event);
[[[self contentView] inputContext] invalidateCharacterCoordinates];
[self updateFullscreen];
}
- (BOOL)windowShouldClose:(id)sender

View File

@ -136,6 +136,7 @@
/* main */
extern int macdrv_err_on;
extern int topmost_float_inactive DECLSPEC_HIDDEN;
extern int capture_displays_for_fullscreen DECLSPEC_HIDDEN;
extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;

View File

@ -38,11 +38,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(macdrv);
#define kCFCoreFoundationVersionNumber10_7 635.00
#endif
#define IS_OPTION_TRUE(ch) \
((ch) == 'y' || (ch) == 'Y' || (ch) == 't' || (ch) == 'T' || (ch) == '1')
C_ASSERT(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
int topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN;
int capture_displays_for_fullscreen = 0;
/**************************************************************************
@ -149,6 +153,9 @@ static void setup_options(void)
topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN;
}
if (!get_config_key(hkey, appkey, "CaptureDisplaysForFullscreen", buffer, sizeof(buffer)))
capture_displays_for_fullscreen = IS_OPTION_TRUE(buffer[0]);
if (appkey) RegCloseKey(appkey);
if (hkey) RegCloseKey(hkey);
}