Search code examples
cocoascreensaver

Cocoa screen saver config panel floating freely


I'm writing a screen saver using Cocoa's ScreenSaver API. It's compiled for 64-bit arch and I'm running it on Lion.

In order to enable configuration, I have added the following to the main view:

- (BOOL)hasConfigureSheet
{
    return YES;
}

- (NSWindow*)configureSheet
{
    if (configureSheet == nil) {
        if (![NSBundle loadNibNamed: @"WTConfigureSheet" owner: self]) {
            NSLog(@"Failed to load config sheet");
            return nil;
        }
    }

    ScreenSaverDefaults *defaults =
        [ScreenSaverDefaults defaultsForModuleWithName: WTModuleName];

    backgroundColorWell.color = [defaults objectForKey: @"BackgroundColor"];
    lightLetterColorWell.color = [defaults objectForKey: @"LightLetterColor"];
    darkLetterColorWell.color = [defaults objectForKey: @"DarkLetterColor"];

    return configureSheet;
}

After installing the saver freshly, clicking "Options" makes the config sheet appear not as a sheet, but floating freely on the screen, without a border. Otherwise, it works correctly and disappears after being dismissed.

When I click "Options" a second time, the config sheet appears again, this time correctly as a sheet of the preferences window. It then immediately freezes, so that I can't click any of its controls.

Does anyone have an idea what causes this behavior?


Solution

  • I had the same problem as you today and it took me quite some time to figure this one out, so here's my solution:

    I discovered that the NSWindow appears as soon as you call loadNibNamed:owner:. So there had to be some sort of mechanism to automatically open windows from nibs.

    So I re-checked the nib and saw that there is an option called "Visible At Launch" on the attribute inspector pane which is checked by default.

    The solution is very simple: just uncheck that checkbox and it works as expected.

    I find it easy to overlook since you expect the window to open, but it actually opens twice (once automatically and a second time because System Preferences.app shows it as a sheet) which leads to the glitches.

    Another problem that could happen, depending on how you defined the ivar / property on your class is that after the first close and re-open of the window it just freezes. This is because per default the window releases itself when closed.

    So be sure to also uncheck "Release When Closed" in interface builder.