winemac: Implement support for full-screen windows.
This commit is contained in:
parent
ba86e67792
commit
be6af9a169
|
@ -276,7 +276,7 @@ - (void) wineWindow:(WineWindow*)window
|
|||
index = 0;
|
||||
for (otherWindow in orderedWineWindows)
|
||||
{
|
||||
if ([otherWindow level] <= [window level])
|
||||
if ([otherWindow levelWhenActive] <= [window levelWhenActive])
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
@ -298,7 +298,7 @@ - (void) wineWindow:(WineWindow*)window
|
|||
index = 0;
|
||||
for (otherWindow in orderedWineWindows)
|
||||
{
|
||||
if ([otherWindow level] < [window level])
|
||||
if ([otherWindow levelWhenActive] < [window levelWhenActive])
|
||||
break;
|
||||
index++;
|
||||
}
|
||||
|
@ -328,6 +328,15 @@ - (void) sendEvent:(NSEvent*)anEvent
|
|||
/*
|
||||
* ---------- NSApplicationDelegate methods ----------
|
||||
*/
|
||||
- (void)applicationDidBecomeActive:(NSNotification *)notification
|
||||
{
|
||||
[orderedWineWindows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
|
||||
WineWindow* window = obj;
|
||||
if ([window levelWhenActive] != [window level])
|
||||
[window setLevel:[window levelWhenActive]];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)applicationDidChangeScreenParameters:(NSNotification *)notification
|
||||
{
|
||||
primaryScreenHeightValid = FALSE;
|
||||
|
@ -383,6 +392,16 @@ - (void)applicationWillFinishLaunching:(NSNotification *)notification
|
|||
self.keyboardType = LMGetKbdType();
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(NSNotification *)notification
|
||||
{
|
||||
[orderedWineWindows enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop){
|
||||
WineWindow* window = obj;
|
||||
NSInteger level = window.floating ? NSFloatingWindowLevel : NSNormalWindowLevel;
|
||||
if ([window level] > level)
|
||||
[window setLevel:level];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -51,11 +51,15 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
BOOL forceNextMouseMoveAbsolute;
|
||||
double mouseMoveDeltaX, mouseMoveDeltaY;
|
||||
|
||||
NSInteger levelWhenActive;
|
||||
|
||||
BOOL causing_becomeKeyWindow;
|
||||
BOOL ignore_windowMiniaturize;
|
||||
BOOL ignore_windowDeminiaturize;
|
||||
}
|
||||
|
||||
@property (retain, readonly, nonatomic) WineEventQueue* queue;
|
||||
@property (readonly, nonatomic) BOOL floating;
|
||||
@property (readonly, nonatomic) NSInteger levelWhenActive;
|
||||
|
||||
@end
|
||||
|
|
|
@ -63,6 +63,17 @@ static BOOL frame_intersects_screens(NSRect frame, NSArray* screens)
|
|||
}
|
||||
|
||||
|
||||
static NSScreen* screen_covered_by_rect(NSRect rect, NSArray* screens)
|
||||
{
|
||||
for (NSScreen* screen in screens)
|
||||
{
|
||||
if (NSContainsRect(rect, [screen frame]))
|
||||
return screen;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
/* We rely on the supposedly device-dependent modifier flags to distinguish the
|
||||
keys on the left side of the keyboard from those on the right. Some event
|
||||
sources don't set those device-depdendent flags. If we see a device-independent
|
||||
|
@ -114,7 +125,7 @@ @interface WineWindow ()
|
|||
|
||||
@property (nonatomic) BOOL disabled;
|
||||
@property (nonatomic) BOOL noActivate;
|
||||
@property (nonatomic) BOOL floating;
|
||||
@property (readwrite, nonatomic) BOOL floating;
|
||||
@property (retain, nonatomic) NSWindow* latentParentWindow;
|
||||
|
||||
@property (nonatomic) void* hwnd;
|
||||
|
@ -131,6 +142,8 @@ @interface WineWindow ()
|
|||
@property (nonatomic) CGFloat colorKeyRed, colorKeyGreen, colorKeyBlue;
|
||||
@property (nonatomic) BOOL usePerPixelAlpha;
|
||||
|
||||
@property (readwrite, nonatomic) NSInteger levelWhenActive;
|
||||
|
||||
+ (void) flipRect:(NSRect*)rect;
|
||||
|
||||
@end
|
||||
|
@ -231,6 +244,7 @@ @implementation WineWindow
|
|||
@synthesize shape, shapeChangedSinceLastDraw;
|
||||
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
|
||||
@synthesize usePerPixelAlpha;
|
||||
@synthesize levelWhenActive;
|
||||
|
||||
+ (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)wf
|
||||
windowFrame:(NSRect)window_frame
|
||||
|
@ -321,18 +335,72 @@ - (void) setWindowFeatures:(const struct macdrv_window_features*)wf
|
|||
[self setHasShadow:wf->shadow];
|
||||
}
|
||||
|
||||
- (void) setMacDrvState:(const struct macdrv_window_state*)state
|
||||
- (void) adjustWindowLevel
|
||||
{
|
||||
NSInteger level;
|
||||
BOOL fullscreen;
|
||||
NSScreen* screen;
|
||||
NSUInteger index;
|
||||
WineWindow* other = nil;
|
||||
|
||||
screen = screen_covered_by_rect([self frame], [NSScreen screens]);
|
||||
fullscreen = (screen != nil);
|
||||
|
||||
if (fullscreen)
|
||||
{
|
||||
level = NSMainMenuWindowLevel + 1;
|
||||
if (self.floating)
|
||||
level++;
|
||||
}
|
||||
else if (self.floating)
|
||||
level = NSFloatingWindowLevel;
|
||||
else
|
||||
level = NSNormalWindowLevel;
|
||||
|
||||
index = [[NSApp orderedWineWindows] indexOfObjectIdenticalTo:self];
|
||||
if (index != NSNotFound && index + 1 < [[NSApp orderedWineWindows] count])
|
||||
{
|
||||
other = [[NSApp orderedWineWindows] objectAtIndex:index + 1];
|
||||
if (level < [other level])
|
||||
level = [other level];
|
||||
}
|
||||
|
||||
if (level != [self level])
|
||||
{
|
||||
[self setLevelWhenActive:level];
|
||||
|
||||
/* Setting the window level above has moved this window to the front
|
||||
of all other windows at the same level. We need to move it
|
||||
back into its proper place among other windows of that level.
|
||||
Also, any windows which are supposed to be in front of it had
|
||||
better have the same or higher window level. If not, bump them
|
||||
up. */
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
for (; index > 0; index--)
|
||||
{
|
||||
other = [[NSApp orderedWineWindows] objectAtIndex:index - 1];
|
||||
if ([other level] < level)
|
||||
[other setLevelWhenActive:level];
|
||||
else
|
||||
{
|
||||
[self orderWindow:NSWindowBelow relativeTo:[other windowNumber]];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) setMacDrvState:(const struct macdrv_window_state*)state
|
||||
{
|
||||
NSWindowCollectionBehavior behavior;
|
||||
|
||||
self.disabled = state->disabled;
|
||||
self.noActivate = state->no_activate;
|
||||
|
||||
self.floating = state->floating;
|
||||
level = state->floating ? NSFloatingWindowLevel : NSNormalWindowLevel;
|
||||
if (level != [self level])
|
||||
[self setLevel:level];
|
||||
[self adjustWindowLevel];
|
||||
|
||||
behavior = NSWindowCollectionBehaviorDefault;
|
||||
if (state->excluded_by_expose)
|
||||
|
@ -381,16 +449,39 @@ - (BOOL) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next
|
|||
|
||||
if (prev)
|
||||
{
|
||||
/* Make sure that windows that should be above this one really are.
|
||||
This is necessary since a full-screen window gets a boost to its
|
||||
window level to be in front of the menu bar and Dock and that moves
|
||||
it out of the z-order that Win32 would otherwise establish. */
|
||||
if ([prev level] < [self level])
|
||||
{
|
||||
NSUInteger index = [[NSApp orderedWineWindows] indexOfObjectIdenticalTo:prev];
|
||||
if (index != NSNotFound)
|
||||
{
|
||||
[prev setLevelWhenActive:[self level]];
|
||||
for (; index > 0; index--)
|
||||
{
|
||||
WineWindow* other = [[NSApp orderedWineWindows] objectAtIndex:index - 1];
|
||||
if ([other level] < [self level])
|
||||
[other setLevelWhenActive:[self level]];
|
||||
}
|
||||
}
|
||||
}
|
||||
[self orderWindow:NSWindowBelow relativeTo:[prev windowNumber]];
|
||||
[NSApp wineWindow:self ordered:NSWindowBelow relativeTo:prev];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Similarly, make sure this window is really above what it should be. */
|
||||
if (next && [next level] > [self level])
|
||||
[self setLevelWhenActive:[next level]];
|
||||
[self orderWindow:NSWindowAbove relativeTo:[next windowNumber]];
|
||||
[NSApp wineWindow:self ordered:NSWindowAbove relativeTo:next];
|
||||
}
|
||||
if (latentParentWindow)
|
||||
{
|
||||
if ([latentParentWindow level] > [self level])
|
||||
[self setLevelWhenActive:[latentParentWindow level]];
|
||||
[latentParentWindow addChildWindow:self ordered:NSWindowAbove];
|
||||
[NSApp wineWindow:self ordered:NSWindowAbove relativeTo:latentParentWindow];
|
||||
self.latentParentWindow = nil;
|
||||
|
@ -452,6 +543,8 @@ - (BOOL) setFrameIfOnScreen:(NSRect)contentRect
|
|||
|
||||
if (on_screen)
|
||||
{
|
||||
[self adjustWindowLevel];
|
||||
|
||||
/* 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];
|
||||
|
@ -476,6 +569,8 @@ - (void) setMacDrvParentWindow:(WineWindow*)parent
|
|||
self.latentParentWindow = nil;
|
||||
if ([self isVisible] && parent)
|
||||
{
|
||||
if ([parent level] > [self level])
|
||||
[self setLevelWhenActive:[parent level]];
|
||||
[parent addChildWindow:self ordered:NSWindowAbove];
|
||||
[NSApp wineWindow:self ordered:NSWindowAbove relativeTo:parent];
|
||||
}
|
||||
|
@ -566,6 +661,19 @@ - (void) makeFocused
|
|||
[self setFrame:frame display:YES];
|
||||
}
|
||||
|
||||
if ([[NSApp orderedWineWindows] count])
|
||||
{
|
||||
WineWindow* front;
|
||||
if (self.floating)
|
||||
front = [[NSApp orderedWineWindows] objectAtIndex:0];
|
||||
else
|
||||
{
|
||||
for (front in [NSApp orderedWineWindows])
|
||||
if (!front.floating) break;
|
||||
}
|
||||
if (front && [front levelWhenActive] > [self levelWhenActive])
|
||||
[self setLevelWhenActive:[front levelWhenActive]];
|
||||
}
|
||||
[self orderFront:nil];
|
||||
[NSApp wineWindow:self ordered:NSWindowAbove relativeTo:nil];
|
||||
causing_becomeKeyWindow = TRUE;
|
||||
|
@ -573,6 +681,8 @@ - (void) makeFocused
|
|||
causing_becomeKeyWindow = FALSE;
|
||||
if (latentParentWindow)
|
||||
{
|
||||
if ([latentParentWindow level] > [self level])
|
||||
[self setLevelWhenActive:[latentParentWindow level]];
|
||||
[latentParentWindow addChildWindow:self ordered:NSWindowAbove];
|
||||
[NSApp wineWindow:self ordered:NSWindowAbove relativeTo:latentParentWindow];
|
||||
self.latentParentWindow = nil;
|
||||
|
@ -666,6 +776,14 @@ - (void) postMouseMovedEvent:(NSEvent *)theEvent
|
|||
}
|
||||
}
|
||||
|
||||
- (void) setLevelWhenActive:(NSInteger)level
|
||||
{
|
||||
levelWhenActive = level;
|
||||
if (([NSApp isActive] || level <= NSFloatingWindowLevel) &&
|
||||
level != [self level])
|
||||
[self setLevel:level];
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ---------- NSWindow method overrides ----------
|
||||
|
@ -682,6 +800,17 @@ - (BOOL) canBecomeMainWindow
|
|||
return [self canBecomeKeyWindow];
|
||||
}
|
||||
|
||||
- (NSRect) constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
|
||||
{
|
||||
// If a window is sized to completely cover a screen, then it's in
|
||||
// full-screen mode. In that case, we don't allow NSWindow to constrain
|
||||
// it.
|
||||
NSRect contentRect = [self contentRectForFrameRect:frameRect];
|
||||
if (!screen_covered_by_rect(contentRect, [NSScreen screens]))
|
||||
frameRect = [super constrainFrameRect:frameRect toScreen:screen];
|
||||
return frameRect;
|
||||
}
|
||||
|
||||
- (BOOL) isExcludedFromWindowsMenu
|
||||
{
|
||||
return !([self collectionBehavior] & NSWindowCollectionBehaviorParticipatesInCycle);
|
||||
|
|
Loading…
Reference in New Issue