6
votes

I added a childWindow of a custom subclass of NSWindow to a parentWindow (also a custom subclass of NSWindow). The childWindow has the NSBorderlessWindowMask and canBecomeKeyWindow: is overridden to return YES and canBecomeMainWindow: to return NO.

The childWindow is set to resize with the parentWindow. So I want to create the illusion that the views of the childWindow are part of the parentWindow. The main idea is to arrange the document windows created by the document-based application within a main window to provide a tabbed interface (just like in a browser) to switch between the documents.

My problem is that whenever I click in one of the views of the childWindow, the parentWindow (the main window) looses focus and the traffic light buttons are getting greyed out. This is obviously contrary to what I want to achieve.

I found this answer: Make NSView in NSPanel first responder without key window status

But even if I override isKeyWindow: (of the main window) to always return YES, the title bar gets greyed out nonetheless when I click into the childWindow.

I also tried to follow this advice: http://www.cocoabuilder.com/archive/cocoa/143945-non-focused-child-window.html

But I'm not sure what "include the child window in its responder chain just ahead of its nextResponder" means. With canBecomeKeyWindow: to return NO (for the childWindow), the views within the child never can become key and are always greyed out.

Any clue what I am doing wrong?

One addition: Is it possible to make the views in the childWindow FirstResponder without giving the childWindow key-status?

1
Is there a reason you're not simply using a tab view (with the tabs turned off, if you'd rather use a custom tab-switcher view) to switch amongst the different views?Peter Hosey
@PeterHosey: Yes, the document-based application creates windows for each document. It would be extremely difficult to hack the document-based application architecture to make it produce views for each open document. The effort would essentially mean to completely rewrite the document architecture. I would like to avoid that, because it will be error-prone and I would have to implement all the features coming with future OS X versions myself. I guess it would not be worth the effort. But at the same time I think that a tabbed-based application is a good approach for my program.tungsten
You could override makeWindowControllers to make a view controller and add its view to the nearest existing window (if there is one) instead.Peter Hosey
@PeterHosey: It is more than that. The whole document architecture expects windows. If I just override makeWindowController, a whole lot of features will break. This can be read in several answers on questions on how to make a single-window-based document application. I really thought the answer by Abhi Beckert for this question would be useful. But I failed so far. I just can't make views key while their corresponding window isn't. Just passing on events is not enough.tungsten
I'm currently playing with this myself. It looks like what will work is to have the document window borderless with canBecomeKeyWindow:YES and canBecomeMainWindow:NO. The add it as a child window to the parent, and observe resize events to keep them in sync. There's more, I think perhaps isKeyWindow for the parent needs to return YES if the child window is key, but so far it seems to be working.Abhi Beckert

1 Answers

1
votes

I got this working by mimicking the behaviour of NSPopover. On investigation I found that a popover (which uses a private NSPanel subclass "_NSPopoverWindow") believed it was the key & main window, even though it is not the window returned from [NSApp keyWindow].

Create your own custom NSPanel subclass, attach it to the parent window, and then override the following methods as so:

- (BOOL)isKeyWindow {
    return YES;
}

- (BOOL)isMainWindow {
    return YES;
}

- (BOOL)canBecomeKeyWindow {
    return YES;
}

- (BOOL)canBecomeMainWindow {
    return YES;
}

- (void)makeKeyWindow {
    [super makeKeyWindow];
    [self.parentWindow makeKeyWindow];
}
- (void)makeMainWindow {
    [super makeMainWindow];
    [self.parentWindow makeMainWindow];
}
- (void)becomeKeyWindow {
    [super becomeKeyWindow];
}

- (void)becomeMainWindow {
    [super becomeMainWindow];
    [self.parentWindow becomeMainWindow];
}

- (void)resignMainWindow {

}
- (void)resignKeyWindow {

}

NSWindow with child window that does not steal its main/key status