views:

267

answers:

2

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.

A: 

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.

NSResponder
And NSFrameView is undocumented, isn't it? ARG! Even if I intercepted events or key presses in my window to do that, what controls the menu item in the Window menubar item from enable/disabling? There must be a lot of magic there somewhere.
Sean
No magic, just the responder chain. Check Apple's docs for the description of how menu items are validated. In a nutshell, for each menu item, its target is queried to see if it responds to the menu's action selector. If the target is firstResponder, then it will walk the responder chain looking for anything that implements the method in question.
NSResponder
In that case, though, shouldn't the menu item be enabled? NSWindow itself responds to performMiniaturize: which is what the menu item (at least) is connected to. Is it not the first responder or not in the chain or something? Why wouldn't it be? I added acceptsFirstResponder to my NSWindow subclass and return YES just to be sure, but it still doesn't work.
Sean
Correction, the uppermost view in a typical window is an NSThemeFrame, not an NSFrameView. I just did a little experiment with the Round Transparent Window sample project from Apple, and it turns out that even a borderless window will miniaturize if you send it a -miniaturize: message. The theme frame is typically the responder that happens to catch the keystrokes for command-m and send that message to the window. You should be able to do the same thing with a window delegate that implements -keyDown: and sends -miniaturize: to the window in question.
NSResponder
A: 

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.

Philipp