Search code examples
cocoaappkit

NSDocument with multiple windows -- Appkit dialog sheets jump to the wrong window


It is rarely used, but Apple's NSDocument documentation describes how to set up an NSDocument with multiple windows for a single document. I'm working on a database application that does this. Here is an example of a checkbook database document with two windows open. Each window shows a different view of the document, in this case a spreadsheet like view in the back, and a chart summarizing this data set in the front window. This example shows two windows for one document, but the user can create as many windows per document as they want, each displaying the same underlying document in a different way.

enter image description here

Everything works fine, except that if a system dialog sheet is opened (Save As, Print, Page Setup), most of the time (but not every time) the dialog sheet jumps to another window and attaches to that window instead of the current window, as shown in this movie.

enter image description here

Notice that although the dialog sheet attaches to the window containing the chart, it is correctly printing the content in the spreadsheet window. If I press Print, the correct content will be printed.

For printing, all our code does is call the NSDocument printDocument: method.

[NSApplication sendActionToFirstResponder:@selector(printDocument:)];

Page Setup code is also just calling NSDocument.

[NSApplication sendActionToFirstResponder:@selector(runPageLayout:)];

Our code is not customizing any of these dialog sheets, they are completely stock.

For the Save As command there is no code in our application at all, this appears automatically in the menu when the option key is pressed.

This problem appears in all versions of macOS supported by our application, from 10.9 thru 10.13. Perhaps this is an AppKit bug that is rarely seen because multiple windows with a single document is so rarely used?

This problem doesn't cause a crash, or prevent a user from doing what they want, but it is very visibly incorrect and reduces user confidence in the quality of the program.

For my reference this is #221 in the Panorama X issue tracker.


Solution

  • Implement/override NSDocument property windowForSheet.

    The value of this property may be nil, in which case the sender should present an app-modal panel. The NSDocument implementation of this property sets the value to the window of the first window controller, or [NSApp mainWindow] if there are no window controllers or if the first window controller has no window.