mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-04-23 07:00:46 +00:00
Make sure toolbar items are validated w.r.t. the responder chain of
their respective window. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@27627 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
cdc21a5395
commit
f7e864e8ab
2 changed files with 124 additions and 86 deletions
|
@ -1,6 +1,3 @@
|
|||
2009-01-18 Wolfgang Lux <wlux@uni-muenster.de>
|
||||
|
||||
|
||||
2009-01-18 Wolfgang Lux <wolfgang.lux@gmail.com>
|
||||
|
||||
* Source/NSMenu.m (-update, -setAutoenablesItems:, initWithCoder):
|
||||
|
@ -18,6 +15,12 @@
|
|||
item before adding a menu item to an overflow menu. Also rename
|
||||
method to make its purpose clear.
|
||||
|
||||
* Source/NSApplication.m (-targetForAction:to:from:): Make sure
|
||||
toolbar items are validated w.r.t. the responder chain of their
|
||||
respective window.
|
||||
* Source/NSApplication.m (-_targetForAction:keyWindow:mainWindow:):
|
||||
Helper method to consolidate target look up in the responder chain.
|
||||
|
||||
2009-01-17 Wolfgang Lux <wolfgang.lux@gmail.com>
|
||||
|
||||
* Source/NSDocument.m (-windowForSheet): Return nil if the
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
#include "AppKit/NSPageLayout.h"
|
||||
#include "AppKit/NSPanel.h"
|
||||
#include "AppKit/NSPasteboard.h"
|
||||
#include "AppKit/NSToolbarItem.h"
|
||||
#include "AppKit/NSWorkspace.h"
|
||||
#include "AppKit/NSScreen.h"
|
||||
#include "AppKit/PSOperators.h"
|
||||
|
@ -84,6 +85,7 @@
|
|||
#include "GNUstepGUI/GSInfoPanel.h"
|
||||
#include "GNUstepGUI/GSVersion.h"
|
||||
#include "NSDocumentFrameworkPrivate.h"
|
||||
#include "NSToolbarFrameworkPrivate.h"
|
||||
|
||||
/* The -gui thread. See the comment in initialize_gnustep_backend. */
|
||||
NSThread *GSAppKitThread;
|
||||
|
@ -360,6 +362,9 @@ struct _NSModalSession {
|
|||
- _appIconInit;
|
||||
- (NSDictionary*) _notificationUserInfo;
|
||||
- (void) _openDocument: (NSString*)name;
|
||||
- (id) _targetForAction: (SEL)aSelector
|
||||
keyWindow: (NSWindow *)keyWindow
|
||||
mainWindow: (NSWindow *)mainWindow;
|
||||
- (void) _windowDidBecomeKey: (NSNotification*) notification;
|
||||
- (void) _windowDidBecomeMain: (NSNotification*) notification;
|
||||
- (void) _windowDidResignKey: (NSNotification*) notification;
|
||||
|
@ -2053,51 +2058,30 @@ IF_NO_GC(NSAssert([event retainCount] > 0, NSInternalInconsistencyException));
|
|||
{
|
||||
return theTarget;
|
||||
}
|
||||
else if ([sender isKindOfClass: [NSToolbarItem class]])
|
||||
{
|
||||
/* Special case for toolbar items which must look up the target in the
|
||||
responder chain of the window containing their toolbar not in the key
|
||||
or main window.
|
||||
Note: If (and only if) the toolbar's window is key window we must
|
||||
pass it as such to _targetForAction:... so that toolbar items in a
|
||||
modal dialog panel work.
|
||||
*/
|
||||
NSWindow *toolbarWindow =
|
||||
[[[(NSToolbarItem *)sender toolbar] _toolbarView] window];
|
||||
NSWindow *keyWindow = [self keyWindow];
|
||||
if (keyWindow != toolbarWindow)
|
||||
keyWindow = nil;
|
||||
return [self _targetForAction: theAction
|
||||
keyWindow: keyWindow
|
||||
mainWindow: toolbarWindow];
|
||||
}
|
||||
else
|
||||
{
|
||||
return [self targetForAction: theAction];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper method to avoid duplicating code for key and main window
|
||||
*/
|
||||
- (id) targetForAction: (SEL)aSelector forWindow: (NSWindow *)window
|
||||
{
|
||||
id resp, delegate;
|
||||
|
||||
resp = [window firstResponder];
|
||||
while (resp != nil && resp != self)
|
||||
{
|
||||
if ([resp respondsToSelector: aSelector])
|
||||
{
|
||||
return resp;
|
||||
}
|
||||
if (resp == window)
|
||||
{
|
||||
delegate = [window delegate];
|
||||
if ([delegate respondsToSelector: aSelector])
|
||||
{
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
resp = [resp nextResponder];
|
||||
}
|
||||
|
||||
if ([NSDocumentController isDocumentBasedApplication])
|
||||
{
|
||||
resp = [[NSDocumentController sharedDocumentController]
|
||||
documentForWindow: window];
|
||||
|
||||
if (resp != nil && [resp respondsToSelector: aSelector])
|
||||
{
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Returns the target object that will respond to aSelector, if any. The
|
||||
|
@ -2109,52 +2093,12 @@ IF_NO_GC(NSAssert([event retainCount] > 0, NSInternalInconsistencyException));
|
|||
*/
|
||||
- (id) targetForAction: (SEL)aSelector
|
||||
{
|
||||
NSWindow *keyWindow;
|
||||
NSWindow *mainWindow;
|
||||
id resp;
|
||||
|
||||
if (aSelector == NULL)
|
||||
return nil;
|
||||
|
||||
keyWindow = [self keyWindow];
|
||||
if (keyWindow != nil)
|
||||
{
|
||||
resp = [self targetForAction: aSelector forWindow: keyWindow];
|
||||
if (resp != nil)
|
||||
return resp;
|
||||
}
|
||||
|
||||
if (_session != 0)
|
||||
return nil;
|
||||
|
||||
mainWindow = [self mainWindow];
|
||||
if (keyWindow != mainWindow && mainWindow != nil)
|
||||
{
|
||||
resp = [self targetForAction: aSelector forWindow: mainWindow];
|
||||
if (resp != nil)
|
||||
return resp;
|
||||
}
|
||||
|
||||
if ([self respondsToSelector: aSelector])
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
if (_delegate != nil && [_delegate respondsToSelector: aSelector])
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
if ([NSDocumentController isDocumentBasedApplication]
|
||||
&& [[NSDocumentController sharedDocumentController]
|
||||
respondsToSelector: aSelector])
|
||||
{
|
||||
return [NSDocumentController sharedDocumentController];
|
||||
}
|
||||
|
||||
return nil;
|
||||
return [self _targetForAction: aSelector
|
||||
keyWindow: [self keyWindow]
|
||||
mainWindow: [self mainWindow]];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Attempts to perform aSelector using [NSResponder-tryToPerform:with:]
|
||||
* and if that is not possible, attempts to get the application
|
||||
|
@ -3614,6 +3558,97 @@ struct _DelegateWrapper
|
|||
[_listener application: self openFile: filePath];
|
||||
}
|
||||
|
||||
- (id) _targetForAction: (SEL)aSelector
|
||||
keyWindow: (NSWindow *)keyWindow
|
||||
mainWindow: (NSWindow *)mainWindow
|
||||
{
|
||||
id resp, delegate;
|
||||
NSWindow *window;
|
||||
|
||||
if (aSelector == NULL)
|
||||
return nil;
|
||||
|
||||
/* if we have a key window, start looking in its responder chain, ... */
|
||||
if (keyWindow != nil)
|
||||
{
|
||||
window = keyWindow;
|
||||
}
|
||||
/* ... otherwise in the main window's responder chain */
|
||||
else
|
||||
{
|
||||
if (_session != 0)
|
||||
return nil;
|
||||
window = mainWindow;
|
||||
}
|
||||
|
||||
if (window != nil)
|
||||
{
|
||||
/* traverse the responder chain including the window's delegate */
|
||||
resp = [window firstResponder];
|
||||
while (resp != nil && resp != self)
|
||||
{
|
||||
if ([resp respondsToSelector: aSelector])
|
||||
{
|
||||
return resp;
|
||||
}
|
||||
if (resp == window)
|
||||
{
|
||||
delegate = [window delegate];
|
||||
if ([delegate respondsToSelector: aSelector])
|
||||
{
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
resp = [resp nextResponder];
|
||||
}
|
||||
|
||||
/* in a document based app try the window's document */
|
||||
if ([NSDocumentController isDocumentBasedApplication])
|
||||
{
|
||||
resp = [[NSDocumentController sharedDocumentController]
|
||||
documentForWindow: window];
|
||||
|
||||
if (resp != nil && [resp respondsToSelector: aSelector])
|
||||
{
|
||||
return resp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if we've found no target in the key window start over without key window */
|
||||
if (keyWindow != nil)
|
||||
{
|
||||
if (_session != 0)
|
||||
return nil;
|
||||
if (mainWindow != nil && mainWindow != keyWindow)
|
||||
return [self _targetForAction: aSelector
|
||||
keyWindow: nil
|
||||
mainWindow: mainWindow];
|
||||
}
|
||||
|
||||
/* try the shared application imstance and its delegate */
|
||||
if ([self respondsToSelector: aSelector])
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
if (_delegate != nil && [_delegate respondsToSelector: aSelector])
|
||||
{
|
||||
return _delegate;
|
||||
}
|
||||
|
||||
/* as a last resort in a document based app, try the document controller */
|
||||
if ([NSDocumentController isDocumentBasedApplication]
|
||||
&& [[NSDocumentController sharedDocumentController]
|
||||
respondsToSelector: aSelector])
|
||||
{
|
||||
return [NSDocumentController sharedDocumentController];
|
||||
}
|
||||
|
||||
/* give up */
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) _windowDidBecomeKey: (NSNotification*) notification
|
||||
{
|
||||
id obj = [notification object];
|
||||
|
|
Loading…
Reference in a new issue