4
votes

I have an NSBorderlessWindow subclass of NSWindow with a transparent and non-opaque background (so it's non-rectangular in appearance). I've added my own buttons to function as the close and minimize buttons when I click them, but for some reason the window will not respond to CMD-W or CMD-M like a normal one does. I have my NSWindow subclass set to return YES to canBecomeKeyWindow and canBecomeMainWindow.

My NIB still has all the standard menu items in it that are there when you create a new project - including the "Minimize" item in the Window menu with the default shortcut CMD-M defined. It's hooked up to send performMiniaturize: to the first responder. However it is not enabled when the app is run, so it seems like it must be asking the window if it can minimize and the window says no or something. (I'm still very new to OSX/Cocoa.)

What am I missing?

Also, and maybe this is related, my borderless window has a shadow enabled - but unlike a normal titled window, when I make my window the active/front window by clicking on it, the shadow doesn't change. Normally an OSX focused window has a slightly larger/darker shadow to make it stand out more but mine never changes the shadow. It's like I'm missing something to make the OS treat this window as a real/normal/main window or something and as a result I lose the shadow change and functioning CMD-W/CMD-M.

4
I think if you change the selector from -performMiniaturize: to -miniaturize: you'll get what you want. -performMiniaturize: doesn't just send the window to the dock, it also momentarily highlights the miniaturize button. That may be what's hanging you up. - NSResponder
You shouldn't use the NS prefix. That's Apple's prefix for their classes in Foundation, AppKit, and Core Data. If Apple ever adds an NSBorderlessWindow class, even a private one, their class and yours will conflict. Make up your own prefix and use that. - Peter Hosey
Peter: The class isn't named NSBorderlessWindow, it's an NSWindow made using the NSBorderlessWindowMask flag. I admit that was worded poorly. :) - Sean

4 Answers

4
votes

What you're missing is that when you make a borderless window, you're eliminating the FrameView that standard windows come with, which actually implement the -keyDown: method that receives those keystrokes and miniaturizes or closes the window.

NSWindow itself is actually a fairly lightweight class, and most of what we think of as standard window behavior is done by the frame view.

1
votes

Could it be that you deleted the File > Close menu item?

By default this has the Cmd-W keyboard shortcut, and is connected to the performClose target in the first responder.

We fixed this by dragging in the standard File menu from the Library panel in Interface Builder.

0
votes

I first tried implementing keyDown: per NSResponder's suggestion, but that didn't do the trick.

I've solved this by simply creating my own IBActions for Close and Minimize. Note that you want to call close and miniaturize: on your NSBorderlessWindow, not performClose: or performMiniaturize:.

0
votes

To add to the accepted answer, here is some code which implements performClose: and performMiniaturize: in a window subclass. Doing it this way means you don't have to modify the main menu at all.

@interface Window : NSWindow
@end
@implementation Window
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item
{
    if ([item action] == @selector(performClose:))
        return YES;
    else if ([item action] == @selector(performMiniaturize:))
        return YES;
    return [super validateUserInterfaceItem:item];
}
- (IBAction)performClose:(id)sender
{
    [self close];
}
- (IBAction)performMiniaturize:(id)sender
{
    [self miniaturize:sender];
}
@end