Validate screen before constraining window

If a window is on a screen that gets unplugged it may happen that
[NSWindow screen] returns nil.  Guard against this when constraining
the window frame to the screen frame.

This fixes a bug where a window could "disappear" if it was on a screen
that got unplugged.
This commit is contained in:
Bjorn Winckler
2009-03-29 16:35:47 +02:00
parent 790f685006
commit 73b5d1837c
3 changed files with 60 additions and 35 deletions
+19 -14
View File
@@ -676,21 +676,26 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
[win setFrameTopLeftPoint:topLeft];
NSPoint screenOrigin = [[win screen] frame].origin;
if ([win frame].origin.y < screenOrigin.y) {
// Try to avoid shifting the new window downwards if it means that
// the bottom of the window will be off the screen. E.g. if the
// user has set windows to open maximized in the vertical direction
// then the new window will cascade horizontally only.
topLeft.y = oldTopLeft.y;
[win setFrameTopLeftPoint:topLeft];
}
if ([win screen]) {
NSPoint screenOrigin = [[win screen] frame].origin;
if ([win frame].origin.y < screenOrigin.y) {
// Try to avoid shifting the new window downwards if it means
// that the bottom of the window will be off the screen. E.g.
// if the user has set windows to open maximized in the
// vertical direction then the new window will cascade
// horizontally only.
topLeft.y = oldTopLeft.y;
[win setFrameTopLeftPoint:topLeft];
}
if ([win frame].origin.y < screenOrigin.y) {
// Move the window to the top of the screen if the bottom of the
// window is still obscured.
topLeft.y = NSMaxY([[win screen] frame]);
[win setFrameTopLeftPoint:topLeft];
if ([win frame].origin.y < screenOrigin.y) {
// Move the window to the top of the screen if the bottom of
// the window is still obscured.
topLeft.y = NSMaxY([[win screen] frame]);
[win setFrameTopLeftPoint:topLeft];
}
} else {
NSLog(@"[%s] WINDOW NOT ON SCREEN, don't constrain position", _cmd);
}
}
+11 -1
View File
@@ -142,8 +142,18 @@
- (IBAction)zoom:(id)sender
{
NSScreen *screen = [self screen];
if (!screen) {
NSLog(@"[%s] WINDOW NOT ON SCREEN, zoom to main screen", _cmd);
screen = [NSScreen mainScreen];
if (!screen) {
NSLog(@"[%s] NO MAIN SCREEN, abort zoom", _cmd);
return;
}
}
NSRect frame = [self frame];
NSRect defaultFrame = [[self screen] visibleFrame];
NSRect defaultFrame = [screen visibleFrame];
defaultFrame = [[self delegate] windowWillUseStandardFrame:self
defaultFrame:defaultFrame];
+30 -20
View File
@@ -762,7 +762,10 @@
- (void)windowDidMove:(NSNotification *)notification
{
if (setupDone && windowAutosaveKey) {
if (!setupDone)
return;
if (windowAutosaveKey) {
NSRect frame = [decoratedWindow frame];
NSPoint topLeft = { frame.origin.x, NSMaxY(frame) };
NSString *topLeftString = NSStringFromPoint(topLeft);
@@ -779,6 +782,8 @@
// size in updateResizeConstraints since the screen's visible frame may
// change at any time (dock could move, resolution could change, window
// could be moved to another screen, ...).
if (![win screen])
return proposedFrameSize;
// NOTE: Not called in full-screen mode so use "visibleFrame" instead of
// "frame".
@@ -898,26 +903,28 @@
NSRect newFrame = [decoratedWindow frameRectForContentRect:contentRect];
// Ensure that the window fits inside the visible part of the screen.
// NOTE: Not called in full-screen mode so use "visisbleFrame' instead of
// "frame".
NSRect maxFrame = [[decoratedWindow screen] visibleFrame];
maxFrame = [self constrainFrame:maxFrame];
if ([decoratedWindow screen]) {
// Ensure that the window fits inside the visible part of the screen.
// NOTE: Not called in full-screen mode so use "visibleFrame' instead
// of "frame".
NSRect maxFrame = [[decoratedWindow screen] visibleFrame];
maxFrame = [self constrainFrame:maxFrame];
if (newFrame.size.width > maxFrame.size.width) {
newFrame.size.width = maxFrame.size.width;
newFrame.origin.x = maxFrame.origin.x;
}
if (newFrame.size.height > maxFrame.size.height) {
newFrame.size.height = maxFrame.size.height;
newFrame.origin.y = maxFrame.origin.y;
}
if (onScreen) {
if (newFrame.origin.y < maxFrame.origin.y)
if (newFrame.size.width > maxFrame.size.width) {
newFrame.size.width = maxFrame.size.width;
newFrame.origin.x = maxFrame.origin.x;
}
if (newFrame.size.height > maxFrame.size.height) {
newFrame.size.height = maxFrame.size.height;
newFrame.origin.y = maxFrame.origin.y;
if (NSMaxX(newFrame) > NSMaxX(maxFrame))
newFrame.origin.x = NSMaxX(maxFrame) - newFrame.size.width;
}
if (onScreen) {
if (newFrame.origin.y < maxFrame.origin.y)
newFrame.origin.y = maxFrame.origin.y;
if (NSMaxX(newFrame) > NSMaxX(maxFrame))
newFrame.origin.x = NSMaxX(maxFrame) - newFrame.size.width;
}
}
[decoratedWindow setFrame:newFrame display:YES];
@@ -925,10 +932,13 @@
- (NSSize)constrainContentSizeToScreenSize:(NSSize)contentSize
{
NSWindow *win = [self window];
if (![win screen])
return contentSize;
// NOTE: This may be called in both windowed and full-screen mode. The
// "visibleFrame" method does not overlap menu and dock so should not be
// used in full-screen.
NSWindow *win = [self window];
NSRect screenRect = fullscreenEnabled ? [[win screen] frame]
: [[win screen] visibleFrame];
NSRect rect = [win contentRectForFrameRect:screenRect];