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

View File

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

View File

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

View File

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

View File

@ -136,6 +136,7 @@
/* main */ /* main */
extern int macdrv_err_on; extern int macdrv_err_on;
extern int topmost_float_inactive DECLSPEC_HIDDEN; 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 int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) 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 #define kCFCoreFoundationVersionNumber10_7 635.00
#endif #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); C_ASSERT(NUM_EVENT_TYPES <= sizeof(macdrv_event_mask) * 8);
DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES; DWORD thread_data_tls_index = TLS_OUT_OF_INDEXES;
int topmost_float_inactive = TOPMOST_FLOAT_INACTIVE_NONFULLSCREEN; 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; 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 (appkey) RegCloseKey(appkey);
if (hkey) RegCloseKey(hkey); if (hkey) RegCloseKey(hkey);
} }