Leave the focus transfer when a window closes to the window not the

application and improve the code there.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@25420 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Fred Kiefer 2007-08-28 22:01:29 +00:00
parent 3406816ab5
commit 1a13f90156
3 changed files with 311 additions and 387 deletions

View file

@ -1,3 +1,10 @@
2007-08-28 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSApplication.m (-_windowWillClose:): Don't call
resignKey on the window. Reorganise the code some more and add comments.
* Source/NSWindow.m (-_lossOfKeyOrMainWindow): Check all windows
whether they could take key or main status.
2007-08-28 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSCell.m (#initialize): Increase version number.

View file

@ -512,46 +512,45 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
{
/* if not hidden raise windows which are possibly obscured. */
if ([NSApp isHidden] == NO)
{
NSArray *windows = RETAIN(GSOrderedWindows());
NSWindow *aWin;
NSEnumerator *iter = [windows reverseObjectEnumerator];
while ((aWin = [iter nextObject]))
{
if ([aWin isVisible] == YES && [aWin isMiniaturized] == NO
&& aWin != [NSApp keyWindow] && aWin != [NSApp mainWindow]
&& aWin != [self window]
&& ([aWin styleMask] & NSMiniWindowMask) == 0)
{
[aWin orderFrontRegardless];
}
}
{
NSArray *windows = RETAIN(GSOrderedWindows());
NSWindow *aWin;
NSEnumerator *iter = [windows reverseObjectEnumerator];
while ((aWin = [iter nextObject]))
{
if ([aWin isVisible] == YES && [aWin isMiniaturized] == NO
&& aWin != [NSApp keyWindow] && aWin != [NSApp mainWindow]
&& aWin != [self window]
&& ([aWin styleMask] & NSMiniWindowMask) == 0)
{
[aWin orderFrontRegardless];
}
}
if ([NSApp isActive] == YES)
{
if ([NSApp keyWindow] != nil)
{
[[NSApp keyWindow] orderFront: self];
}
else if ([NSApp mainWindow] != nil)
{
[[NSApp mainWindow] makeKeyAndOrderFront: self];
}
else
{
/* We need give input focus to some window otherwise we'll
never get keyboard events. FIXME: doesn't work. */
NSWindow *menu_window= [[NSApp mainMenu] window];
NSDebugLLog(@"Focus", @"No key on activation - make menu key");
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
}
}
if ([NSApp isActive] == YES)
{
if ([NSApp keyWindow] != nil)
{
[[NSApp keyWindow] orderFront: self];
}
else if ([NSApp mainWindow] != nil)
{
[[NSApp mainWindow] makeKeyAndOrderFront: self];
}
else
{
/* We need give input focus to some window otherwise we'll
never get keyboard events. FIXME: doesn't work. */
NSWindow *menu_window= [[NSApp mainMenu] window];
NSDebugLLog(@"Focus", @"No key on activation - make menu key");
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
}
}
RELEASE(windows);
}
}
[NSApp unhide: self]; // or activate or do nothing.
}
@ -1151,57 +1150,57 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
* visible when the application is active.
*/
[nc postNotificationName: NSApplicationWillBecomeActiveNotification
object: self];
object: self];
_app_is_active = YES;
/* Make sure to calculate count after the notification, since
inactive status might be changed by a notifiee. */
inactive status might be changed by a notifiee. */
count = [_inactive count];
for (i = 0; i < count; i++)
{
[[_inactive objectAtIndex: i] orderFrontRegardless];
}
{
[[_inactive objectAtIndex: i] orderFrontRegardless];
}
[_inactive removeAllObjects];
if (_unhide_on_activation)
{
[self unhide: nil];
}
{
[self unhide: nil];
}
if ([self keyWindow] == nil && _hidden_key != nil
&& [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound)
{
[_hidden_key makeKeyWindow];
_hidden_key = nil;
}
&& [[self windows] indexOfObjectIdenticalTo: _hidden_key] != NSNotFound)
{
[_hidden_key makeKeyWindow];
_hidden_key = nil;
}
if ([self keyWindow] != nil)
{
[[self keyWindow] orderFront: self];
}
{
[[self keyWindow] orderFront: self];
}
else if ([self mainWindow] != nil)
{
[[self mainWindow] makeKeyAndOrderFront: self];
}
{
[[self mainWindow] makeKeyAndOrderFront: self];
}
else
{
/* We need give input focus to some window otherwise we'll never get
keyboard events. FIXME: doesn't work. */
NSWindow *menu_window= [[self mainMenu] window];
NSDebugLLog(@"Focus", @"No key on activation - make menu key");
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
/* We need give input focus to some window otherwise we'll never get
keyboard events. FIXME: doesn't work. */
NSWindow *menu_window= [[self mainMenu] window];
NSDebugLLog(@"Focus", @"No key on activation - make menu key");
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
}
info = [self _notificationUserInfo];
[nc postNotificationName: NSApplicationDidBecomeActiveNotification
object: self
object: self
userInfo: info];
[[[NSWorkspace sharedWorkspace] notificationCenter]
postNotificationName: NSApplicationDidBecomeActiveNotification
postNotificationName: NSApplicationDidBecomeActiveNotification
object: [NSWorkspace sharedWorkspace]
userInfo: info];
userInfo: info];
}
}
@ -1219,16 +1218,15 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
NSEnumerator *iter;
[nc postNotificationName: NSApplicationWillResignActiveNotification
object: self];
object: self];
_app_is_active = NO;
if ([self keyWindow] != nil)
{
_hidden_key = [self keyWindow];
[_hidden_key resignKeyWindow];
}
{
_hidden_key = [self keyWindow];
[_hidden_key resignKeyWindow];
}
// FIXME: main window is not saved for when the app is activated again.
// This is not a problem if it is also key, and I'm not sure if it
// is a problem at all. May be annoying in the case of workspace switch.
@ -1238,47 +1236,47 @@ static NSSize scaledIconSizeForSize(NSSize imageSize)
iter = [windows_list reverseObjectEnumerator];
while ((win = [iter nextObject]))
{
NSModalSession theSession;
{
NSModalSession theSession;
if ([win isVisible] == NO)
{
continue; /* Already invisible */
}
if ([win canHide] == NO)
{
continue; /* Can't be hidden */
}
if (win == _app_icon_window)
{
continue; /* can't hide the app icon. */
}
/* Don't order out modal windows */
theSession = _session;
while (theSession != 0)
{
if (win == theSession->window)
break;
theSession = theSession->previous;
}
if (theSession)
continue;
if ([win hidesOnDeactivate] == YES)
{
[_inactive addObject: win];
[win orderOut: self];
}
}
if ([win isVisible] == NO)
{
continue; /* Already invisible */
}
if ([win canHide] == NO)
{
continue; /* Can't be hidden */
}
if (win == _app_icon_window)
{
continue; /* can't hide the app icon. */
}
/* Don't order out modal windows */
theSession = _session;
while (theSession != 0)
{
if (win == theSession->window)
break;
theSession = theSession->previous;
}
if (theSession)
continue;
if ([win hidesOnDeactivate] == YES)
{
[_inactive addObject: win];
[win orderOut: self];
}
}
info = [self _notificationUserInfo];
[nc postNotificationName: NSApplicationDidResignActiveNotification
object: self
object: self
userInfo: info];
[[[NSWorkspace sharedWorkspace] notificationCenter]
postNotificationName: NSApplicationDidResignActiveNotification
postNotificationName: NSApplicationDidResignActiveNotification
object: [NSWorkspace sharedWorkspace]
userInfo: info];
userInfo: info];
}
}
@ -2223,35 +2221,35 @@ image.</p><p>See Also: -applicationIconImage</p>
object: self];
if ([self keyWindow] != nil)
{
_hidden_key = [self keyWindow];
[_hidden_key resignKeyWindow];
}
{
_hidden_key = [self keyWindow];
[_hidden_key resignKeyWindow];
}
windows_list = GSOrderedWindows();
iter = [windows_list reverseObjectEnumerator];
while ((win = [iter nextObject]))
{
if ([win isVisible] == NO)
{
continue; /* Already invisible */
}
if ([win canHide] == NO)
{
continue; /* Not hideable */
}
if (win == _app_icon_window)
{
continue; /* can't hide the app icon. */
}
if (_app_is_active == YES && [win hidesOnDeactivate] == YES)
{
continue; /* Will be hidden by deactivation */
}
[_hidden addObject: win];
[win orderOut: self];
}
{
if ([win isVisible] == NO)
{
continue; /* Already invisible */
}
if ([win canHide] == NO)
{
continue; /* Not hideable */
}
if (win == _app_icon_window)
{
continue; /* can't hide the app icon. */
}
if (_app_is_active == YES && [win hidesOnDeactivate] == YES)
{
continue; /* Will be hidden by deactivation */
}
[_hidden addObject: win];
[win orderOut: self];
}
_app_is_hidden = YES;
[[_app_icon_window contentView] setNeedsDisplay: YES];
@ -3610,145 +3608,43 @@ struct _DelegateWrapper
- (void) _windowWillClose: (NSNotification*) notification
{
NSWindow *win = [notification object];
NSArray *windows_list = GSOrderedWindows();
unsigned count = [windows_list count];
unsigned i;
NSMutableArray *list = [NSMutableArray arrayWithCapacity: count];
BOOL wasKey = [win isKeyWindow];
BOOL wasMain = [win isMainWindow];
NSEnumerator *iter = [windows_list objectEnumerator];
NSWindow *tmp;
while ((tmp = [iter nextObject]))
{
if ([tmp canBecomeMainWindow] == YES && [tmp isVisible] == YES)
{
[list addObject: tmp];
}
}
[list removeObjectIdenticalTo: win];
count = [list count];
/* If there's only one window left, and that's the one being closed,
then we ask the delegate if the app is to be terminated. */
if (wasMain && count == 0 && _app_is_running)
{
if ([_delegate respondsToSelector:
@selector(applicationShouldTerminateAfterLastWindowClosed:)])
{
if ([_delegate applicationShouldTerminateAfterLastWindowClosed: self])
{
[self terminate: self];
}
}
}
if (wasMain == YES)
{
[win resignMainWindow];
}
if (wasKey == YES)
{
[win resignKeyWindow];
}
NSWindow *win = [notification object];
BOOL wasMain = [win isMainWindow];
if (_app_is_running)
{
/*
* If we are not quitting, we may need to find a new key/main window.
*/
if (wasKey == YES && [self keyWindow] == nil)
{
win = [self mainWindow];
if (win != nil && [win canBecomeKeyWindow] == YES)
{
/*
* We have a main window that can become key, so do it.
*/
[win makeKeyAndOrderFront: self];
}
else if (win != nil)
{
/*
* We have a main window that can't become key, so we just
* find a new window to make into our key window.
*/
for (i = 0; i < count; i++)
{
win = [list objectAtIndex: i];
NSArray *windows_list = GSOrderedWindows();
unsigned count = [windows_list count];
NSEnumerator *iter = [windows_list objectEnumerator];
NSMutableArray *list = [NSMutableArray arrayWithCapacity: count];
NSWindow *tmp;
if ([win canBecomeKeyWindow] == YES)
{
[win makeKeyAndOrderFront: self];
}
}
}
else
{
/*
* Find a window that can be made key and main - and do it.
*/
for (i = 0; i < count; i++)
{
win = [list objectAtIndex: i];
if ([win canBecomeKeyWindow] && [win canBecomeMainWindow])
{
break;
}
}
if (i < count)
{
[win makeMainWindow];
[win makeKeyAndOrderFront: self];
}
else
{
/*
* No window we can use, so just find any candidate to
* be main window and another to be key window.
*/
for (i = 0; i < count; i++)
{
win = [list objectAtIndex: i];
if ([win canBecomeMainWindow] == YES)
{
[win makeMainWindow];
break;
}
}
for (i = 0; i < count; i++)
{
win = [list objectAtIndex: i];
if ([win canBecomeKeyWindow] == YES)
{
[win makeKeyAndOrderFront: self];
break;
}
}
}
}
}
else if ([self mainWindow] == nil)
{
win = [self keyWindow];
if ([win canBecomeMainWindow] == YES)
{
[win makeMainWindow];
}
else
{
for (i = 0; i < count; i++)
{
win = [list objectAtIndex: i];
if ([win canBecomeMainWindow] == YES)
{
[win makeMainWindow];
break;
}
}
}
}
/* FIXME: Why are non-visible windows not counted? When there are
minimized windows left over, this would still terminate the application.
*/
while ((tmp = [iter nextObject]))
{
if ([tmp canBecomeMainWindow] == YES && [tmp isVisible] == YES)
{
[list addObject: tmp];
}
}
[list removeObjectIdenticalTo: win];
count = [list count];
/* If there's only one window left, and that's the one being closed,
then we ask the delegate if the app is to be terminated. */
if (wasMain && count == 0)
{
if ([_delegate respondsToSelector:
@selector(applicationShouldTerminateAfterLastWindowClosed:)])
{
if ([_delegate applicationShouldTerminateAfterLastWindowClosed: self])
{
[self terminate: self];
}
}
}
}
}

View file

@ -235,70 +235,91 @@ has blocked and waited for events.
- (void) _lossOfKeyOrMainWindow
{
NSArray *windowList = GSOrderedWindows();
unsigned pos = [windowList indexOfObjectIdenticalTo: self];
unsigned c = [windowList count];
unsigned i,ti;
NSWindow *w;
unsigned pos = [windowList indexOfObjectIdenticalTo: self];
unsigned c = [windowList count];
unsigned i;
// Don't bother when application is closing.
if ([NSApp isRunning] == NO)
return;
if (!c)
return;
i = pos + 1;
if (pos >= c || pos + 1 == c)
if (pos == NSNotFound)
{
pos = c - 1;
i = 0;
pos = c;
}
ti = i;
if ([self isKeyWindow])
{
NSWindow *menu_window = [[NSApp mainMenu] window];
NSWindow *w = [NSApp mainWindow];
[self resignKeyWindow];
if (w != nil && w != self
&& [w canBecomeKeyWindow])
{
[w makeKeyWindow];
}
else
{
NSWindow *menu_window = [[NSApp mainMenu] window];
for (; i != pos && i < c; i++)
{
w = [windowList objectAtIndex: i];
if ([w isVisible] && [w canBecomeKeyWindow] && w != menu_window)
{
[w makeKeyWindow];
break;
}
}
/*
* if we didn't find a possible key window - use the main menu window
*/
if (i == c)
{
if (menu_window != nil)
{
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
}
}
// try all windows front to back except self and menu
for (i = 0; i < c; i++)
{
if (i != pos)
{
w = [windowList objectAtIndex: i];
if ([w isVisible] && [w canBecomeKeyWindow]
&& w != menu_window)
{
[w makeKeyWindow];
break;
}
}
}
/*
* if we didn't find a possible key window - use the main menu window
*/
if (i == c)
{
if (menu_window != nil)
{
// FIXME: Why this call and not makeKeyWindow?
[GSServerForWindow(menu_window) setinputfocus:
[menu_window windowNumber]];
}
}
}
}
if ([self isMainWindow])
{
NSWindow *w = [NSApp keyWindow];
NSWindow *w = [NSApp keyWindow];
[self resignMainWindow];
if (w != nil && [w canBecomeMainWindow])
{
[w makeMainWindow];
}
{
[w makeMainWindow];
}
else
{
for (i = ti; i != pos && i < c; i++)
{
w = [windowList objectAtIndex: i];
if ([w isVisible] && [w canBecomeMainWindow])
{
[w makeMainWindow];
break;
}
}
}
{
// try all windows front to back except self
for (i = 0; i < c; i++)
{
if (i != pos)
{
w = [windowList objectAtIndex: i];
if ([w isVisible] && [w canBecomeMainWindow])
{
[w makeMainWindow];
break;
}
}
}
}
}
}
@ -1554,8 +1575,8 @@ many times.
{
if (_windowNum == 0)
{
return; /* This deferred window was never ordered in. */
}
return; /* This deferred window was never ordered in. */
}
_f.visible = NO;
/*
* Don't keep trying to update the window while it is ordered out
@ -1566,23 +1587,23 @@ many times.
else
{
/* Windows need to be constrained when displayed or resized - but only
titled windows are constrained. Also, and this is the tricky part,
titled windows are constrained. Also, and this is the tricky part,
don't constrain if we are merely unhidding the window or if it's
already visible and is just being reordered. */
if ((_styleMask & NSTitledWindowMask)
&& [NSApp isHidden] == NO
&& _f.visible == NO)
{
NSRect nframe = [self constrainFrameRect: _frame
toScreen: [self screen]];
[self setFrame: nframe display: NO];
}
&& [NSApp isHidden] == NO
&& _f.visible == NO)
{
NSRect nframe = [self constrainFrameRect: _frame
toScreen: [self screen]];
[self setFrame: nframe display: NO];
}
// create deferred window
if (_windowNum == 0)
{
[self _initBackendWindow];
display = YES;
}
{
[self _initBackendWindow];
display = YES;
}
}
// Draw content before backend window ordering
@ -1612,32 +1633,32 @@ many times.
[isa _addAutodisplayedWindow: self];
if (_f.has_closed == YES)
{
_f.has_closed = NO; /* A closed window has re-opened */
}
{
_f.has_closed = NO; /* A closed window has re-opened */
}
if (_f.has_opened == NO)
{
_f.has_opened = YES;
if (_f.menu_exclude == NO)
{
BOOL isFileName;
NSString *aString;
aString = [NSString stringWithFormat: @"%@ -- %@",
[_representedFilename lastPathComponent],
[_representedFilename stringByDeletingLastPathComponent]];
isFileName = [_windowTitle isEqual: aString];
{
_f.has_opened = YES;
if (_f.menu_exclude == NO)
{
BOOL isFileName;
NSString *aString;
aString = [NSString stringWithFormat: @"%@ -- %@",
[_representedFilename lastPathComponent],
[_representedFilename stringByDeletingLastPathComponent]];
isFileName = [_windowTitle isEqual: aString];
[NSApp addWindowsItem: self
title: _windowTitle
filename: isFileName];
}
}
[NSApp addWindowsItem: self
title: _windowTitle
filename: isFileName];
}
}
if ([self isKeyWindow] == YES)
{
[_wv setInputState: GSTitleBarKey];
[srv setinputfocus: _windowNum];
}
{
[_wv setInputState: GSTitleBarKey];
[srv setinputfocus: _windowNum];
}
_f.visible = YES;
}
else if ([self isOneShot])
@ -1651,19 +1672,19 @@ many times.
if (_f.is_key == YES)
{
if ((_firstResponder != self)
&& [_firstResponder respondsToSelector: @selector(resignKeyWindow)])
[_firstResponder resignKeyWindow];
&& [_firstResponder respondsToSelector: @selector(resignKeyWindow)])
[_firstResponder resignKeyWindow];
_f.is_key = NO;
if (_f.is_main == YES)
{
[_wv setInputState: GSTitleBarMain];
}
{
[_wv setInputState: GSTitleBarMain];
}
else
{
[_wv setInputState: GSTitleBarNormal];
}
{
[_wv setInputState: GSTitleBarNormal];
}
[self discardCursorRects];
[nc postNotificationName: NSWindowDidResignKeyNotification object: self];
@ -1676,13 +1697,13 @@ many times.
{
_f.is_main = NO;
if (_f.is_key == YES)
{
[_wv setInputState: GSTitleBarKey];
}
{
[_wv setInputState: GSTitleBarKey];
}
else
{
[_wv setInputState: GSTitleBarNormal];
}
{
[_wv setInputState: GSTitleBarNormal];
}
[nc postNotificationName: NSWindowDidResignMainNotification object: self];
}
}
@ -2447,9 +2468,9 @@ resetCursorRectsForView(NSView *theView)
we close).
*/
if (!_f.is_released_when_closed)
{
RETAIN(self);
}
{
RETAIN(self);
}
[nc postNotificationName: NSWindowWillCloseNotification object: self];
_f.has_opened = NO;
@ -3524,31 +3545,31 @@ resetCursorRectsForView(NSView *theView)
case GSAppKitWindowFocusIn:
if (_f.is_miniaturized)
{
/* Window Manager just deminiaturized us */
[self deminiaturize: self];
}
{
/* Window Manager just deminiaturized us */
[self deminiaturize: self];
}
if ([NSApp modalWindow]
&& self != [NSApp modalWindow])
{
/* Ignore this request. We're in a modal loop and the
user pressed on the title bar of another window. */
break;
}
&& self != [NSApp modalWindow])
{
/* Ignore this request. We're in a modal loop and the
user pressed on the title bar of another window. */
break;
}
if ([self canBecomeKeyWindow] == YES)
{
NSDebugLLog(@"Focus", @"Making %d key", _windowNum);
[self makeKeyWindow];
[self makeMainWindow];
[NSApp activateIgnoringOtherApps: YES];
}
{
NSDebugLLog(@"Focus", @"Making %d key", _windowNum);
[self makeKeyWindow];
[self makeMainWindow];
[NSApp activateIgnoringOtherApps: YES];
}
if (self == [[NSApp mainMenu] window])
{
/* We should really find another window that can become
key (if possible)
*/
[self _lossOfKeyOrMainWindow];
}
{
/* We should really find another window that can become
key (if possible)
*/
[self _lossOfKeyOrMainWindow];
}
break;
case GSAppKitWindowFocusOut: