(I sent a message about this before, but I think it got blocked by the spam filter.)
I noticed that the responder chain does not include the current document. Here is my idea for how to fix that. It also makes target-action handling more consistent, routing all actions with targetForAction:to:from:
-_sameWindowTargetForAction:(SEL)action to:target {
// Search just one window's responder chain.
if ([target respondsToSelector:action])
return target;
if ([target respondsToSelector:@selector(nextResponder)])
{
target = [target nextResponder];
while (target != nil)
{
if ([target respondsToSelector:action])
return target;
if ([target isKindOfClass:[NSWindow class]])
{
if ([[target delegate] respondsToSelector:action])
return [target delegate];
if ([[target windowController] respondsToSelector:action])
return [target windowController];
}
target = [target nextResponder];
}
}
return nil;
}
-targetForAction:(SEL)action {
return [self targetForAction:action to:nil from:nil];
}
-targetForAction:(SEL)action to:target from:sender {
if (target == nil)
{
target = [self _sameWindowTargetForAction:action to:[[self keyWindow] firstResponder]];
if (target)
return target;
if ([self mainWindow] != [self keyWindow])
{
target = [self _sameWindowTargetForAction:action to:[[self mainWindow] firstResponder]];
if (target)
return target;
}
}
else
{
target = [self _sameWindowTargetForAction:action to:target];
if (target)
return target;
}
NSDocumentController *documentController = [NSDocumentController sharedDocumentController];
if ([[documentController currentDocument] respondsToSelector:action])
return [documentController currentDocument];
if([self respondsToSelector:action])
return self;
if([[self delegate] respondsToSelector:action])
return [self delegate];
if([documentController respondsToSelector:action])
return documentController;
return nil;
}
-(BOOL)sendAction:(SEL)action to:target from:sender {
if([target respondsToSelector:action])
{
[target performSelector:action withObject:sender];
return YES;
}
target=[self targetForAction:action to:target from:sender];
if (target != nil)
{
[target performSelector:action withObject:sender];
return YES;
}
return NO;
}