When Mission Control runs, it prevents applications from receiving keyboard and mouse events. It also leaves the last application running thinking that it still has focus. This is a problem for me because I don't receive keyUp or mouseUp events if I start Mission Control with a mouse button or a key held down and my application will behave as if that mouse button or key is held down.
I would like a way to either read both keyboard and mouse events even when Mission Control is active, or a way of detecting that Mission Control is active. Ideally, I would like to be able to do the latter since I effectively can't use my application when Mission Control is running.
I've tried a couple of things with no luck:
- Use addGlobalMonitorForEventsMatchingMask to register a global monitor for keyboard and mouse events. This captures mouse events (but not keyboard events, although the documentation says keyDown events should be sent to the global monitor) when I switch to another application, but Mission Control doesn't seem to let events propagate to global monitors.
- Check
[[NSRunningApplication currentApplication] {isActive, ownsMenuBar}]
. Apparently, my application is active even though it's not receiving events! - Check
[NSApp keyWindow] != nil
. Apparently, one of my windows should be receiving key events. None of them are. - Check if Mission Control is one of the running applications returned by
[NSWorkspace runningApplications]
. Mission Control does not show up in this list when it's running.
Edit:
I've finally worked around this problem (albeit not in a very satisfactory way). For the mouse, it turns out that you can query the state of the pressed buttons with [NSEvent pressedMouseButtons]
. I simply keep track of what I think the mouse state should be from NSLeftMouseDown and NSLeftMouseUp events and compare that to [NSEvent pressedMouseButtons]
every so often to make sure that they're consistent. If they're not, then I know that something has hijacked my NSLeftMouseUp event and act accordingly.
For the keyboard, I could not find a way to query the keyboard state, so I couldn't do a similar workaround. I ended up disabling application switching using presentation options when keys are pressed.