NSPanel in "Non-Activating"-Mode does not always show correct cursors - objective-c

I've created a simple Cocoa-Application in XCode 4.6 with an NSPanel instead of the default NSWindow. When I enable the Non-Activating
option and start the application everything works fine:
The panel is displayed in front of everything else and when
the mouse cursor hovers over the panel's edges it changes from a normal
arrow-cursor to the appropriate resize-cursor, so the user knows that he can resize
the panel.
This works fine as longs as I don't click on any other application
as for example Safari or Finder.
From the moment I once give focus to another application,
I can click on and hover over my panel as much as I want, the
cursor style will not change anymore - it always stays an arrow and it's not possible to return to the normal behavior.
The panel stays selectable and in the front, you still can move and resize it,
but the mouse cursor stays an arrow all the time. You then cannot even change it
manually using something like: [[NSCursor crosshairCursor] set].
So I need to find a way to create a NSPanel that keeps the normal
automatic-change-cursorstyle-when-hovering-over-panel-edges-behaviour
even when you give focus to another application.
I have already tried to use an customized NSPanel-class,
where I have overwritten the canBecomeKeyWindow and
canBecomeMainWindow methods, so that they return YES
but even when I make my Panel KeyWindow and MainWindow...
[myPanel makeKeyAndOrderFront:self];
[myPanel makeMainWindow];
...it doesn't solve the cursor issue.
Would be great if someone could help me here :)
PS.: the Base SDK and the Deployment Target are set to 10.8 in my project
So I found out that the described issue has nothing to to with the panel's window-state. It really doesn't matter if it is set to key or to main, instead the cursor-problem (stays arrow all the time)is related to the application's activation state.
Everything works fine as long as the application that owns the panel is active but if you click on another application my application is deactivated and does not get activated again - even if you click on the panel - because the "non-activating"-option is enabled.
The problem is that i need the "non activating"-option because I am creating a status-bar-screen-capturing app that should be displayed and operate in front of everything else but without deactivating any running application. I could solve the cursor problem by
[NSApp activateIgnoringOtherApps];
but then taking a screenshot of a fullscreen video running in Safari would deactivate Safari and minimize the video, which I don't want.

I don’t think it’s possible through normal APIs to change the cursor when your app isn’t active. I’m pretty sure the window system doesn’t allow it: it’d be a violation of the boundaries between apps—if you try to set a cursor from the background, and the foreground app also tries to set a cursor, who would win?
Of course the system can do it (like when you take a screenshot with ⌘⇧4), because that’s in the window system itself.

Related

Possible to make an OS X with a window that blocks a portion screen like the system menu bar?

Is it possible to create a NSWindow that will not only is above all other windows (including other applications) but also able to block windows from going "into" that window. Basically I would like to extend the system's menu bar by having another bar below it, but it stops the user from resizing other windows to occupy that space.
For instance, if the user was to maximize a window, it would only be able to have a height of the screen size minus the system status bar minus my application's window.
I was thinking it may be possible by listening to some sort of window resizing notification and if the user tries to set the frame of that other window to a size that would go inside of my application's window then I would resize the other window, but method seems like such a pain.
I also acknowledge that this may not be possible, but was curious if it is!
Thanks in advance!
It is totally possible to make a window which is above all other windows, just set It's level to NSMainMenuWindowLevel.
But preventing other windows from resizing beyond It, I don't think so.
Even if there is a system API to limit window resizing (I don't think there is), some apps use custom code to control window resizing and would completely ignore the presence of your "special" window. I've seen apps which simply hardcode 22 (the height of the menu bar) when calculating window resizing stuff.

Disable application activation on window click

In my Cocoa/Objective-C application I have a utility panel floating "always on top" to be accessible even when my application is not active. I am trying to disable the "switching to my application when a user clicks on that panel".
The behaviour I would like to achieve is similar to OSX's Keyboard Viewer, (which is also a never activating panel), so that some other application remained active after clicking on my app's panel. i.e. Safari stays active when typing an address using Keyboard Viewer. Even third-party onscreen keyboards have this functionality (for example the one from CORALLO Software), which means this behavior is not reserved system-only.
I was messing around with NSApplicationActivationPolicy, but without positive results. In which direction should I go?
You should take a look at the canBecomeKeyWindow and canBecomeMainWindow methods on NSWindow. It sounds like you want your window to maintain key status while not being able to be the main window. Here are some resources to help you:
Window Programming Guide - Explains the difference between main and key windows
NSWindow class reference - Jump to the sections on canBecomeKeyWindow and canBecomeMainWindow

How can I check whether Exposé is being activated or not?

I'm creating an application that emulates MacBook's multi-touch Trackpad. As you may know, on MacBook's trackpad
if you swipe 4 fingers up, it triggers the Show Desktop.
if you swipe 4 fingers down, it shows the Exposé.
However, if the Show Desktop is being activated and you swipe 4 fingers down, it will come back to the normal mode. The same goes with the Exposé: if the Exposé is being activated and you swipe 4 fingers up, it will also come back to the normal mode.
Here is the problem: I use the keyboard shortcut F3 to show the Exposé and F11 to show the Show Desktop. The problem is, when the Show Desktop is being activated, if I press F3, it will go straight to the Exposé. And when the Exposé is being activated, if I press F11 it will go straight to the Show Desktop. But I want it to behave like Trackpad, which I guess its code may look like this
- FourFingersDidSwipeUp {
if (isExposeBeingActivated() || isShowDesktopBeingActivated()) {
pressKey("Esc");
} else {
pressKey("F11");
}
}
But I don't know how to implement the "isExposeBeingActivated()" and "isShowDesktopBeingActivated()" methods. I've tried creating a window and check whether its size has changed (on assumption that if the Expose is being activated, its size should be smaller), but the system always returns the same size. I tried monitoring the background processes during the Expose, but nothing happened. Does anyknow have any suggestions on this?
(I'm sorry if my English sounds weird.)
As far as I know, there's no public interface to any Exposé related functionality beyond the ability to specify the "collection behavior" of your own application's windows.
came here after reading your email. I understand the problem. After a bit of googling I found out what you already know, that there's really no official API or documentation for Exposé. A very ugly solution I've thought of could be having Exposé trigger a timer equal to the total time it takes to show all windows fully (guessing this is constant). If a swipe up would be done within that timer, it would mean that Exposé would still be active (isExposeBeingActivated()), so you would trigger a cancel instead of a Show Desktop. This wouldn't cover the use of the "slow motion" Exposé (via SHIFT key). Maybe you can detect if it's a normal or "slow motion" Exposé call?
Really sorry if this doesn't make sense at all within your application's scope, guess I'm just really saying the first solution I thought of.
Cheers.
Pedro.

Keeping window of another application active while still receiving mouse events from another app's window?

Is there a way to have my app's window receive keyboard and/or mouse events (i.e. user clicking on window's buttons) while still retaining focus to another, unrelated app?
I've tried configuring my window at different levels, including [myWindow setLevel:NSPopUpMenuWindowLevel] to no avail.
You should be able to handle mouse clicks without ordering your window front by making your views (at least the ones that handle mouse clicks) respond to acceptsFirstMouse: messages by sending NSApp a preventWindowOrdering message and then returning YES.
You should not make your app handle typing without ordering itself front. The user might not realize where their typing is going if the field where it's appearing is obscured by another window.
Found it. Simple, yet elusive.
Use NSPanel and make sure panel style is Non Activating (NSNonactivatingPanelMask) or tick the same option in IB's inspector.

NSBorderlessWindowMask Window wont show NSPanels if not front most window

I have a window that is set with NSBorderlessWindowMask, and also kCGDesktopWindowLevel. When a NSPanel is supposed to appear from say the selection of a Dock Icon menu or a Status Bar Item menu, the NSPanel will not display if the application is not the front most window.
So this program at this time only has a Status Menu Item (think how QuickSilver is implemented) and when I choose Preferences from my menu it is set to show the Preferences Panel by using Makekeyandorderfront, however unless you have just launched the application and done nothing else, when you select Preferences nothing happens.
I have found that when I choose my menu item for Sparkle's Check for Updates, that the check for update panel will appear and then my preference panel which I told to open will appear.
So it seems like makekeyandorderfront is not really bringing it to the front, perhaps.
Does anyone know how to fix this?
Should I call something besides makekeyandorderfront, or maybe something in conjunction with it?
Thanks in advance
Panels are designed by default to work this way. They're designed as auxiliary windows for your application and always disappear when the application deactivates. You will probably also run into issues with the panel becoming key... but to cure your disappearing panel issue, send this message to your panel:
[panelObject setHidesOnDeactivate:NO];
You should probably be using actual NSWindow objects here instead of NSPanel objects, but since I don't know much about how your application works, you'll have to look into that yourself. For more information on the difference between panels and windows, please review the documentation here: Window Programming Guide