Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Snow Leopard & LSUIElement -> application not activating properly, window not "active" despite being "key"

I'm running into a few problem with a background application that uses LSUIElement=1 to hide its dock item, menu bar and prevent it from appearing in the Command-Tab application switcher.

It seems to be a Snow Leopard only problem.

The application places an NSStatusItem in the menu bar and pops up a menu when clicked on. Selecting "Preferences..." should bring up an NSWindow with the preferences.

The first thing that doesn't seem to work is that the Window does not get ordered in at the front, but appears behind all other application windows.

I tried to fix this by calling

[[NSApplication sharedApplication] activateIgnoringOtherApps: YES]

but that didn't work.

After a while I figured out that the menu is blocking the message to the run loop from being sent, so I wrote another method on the MainController and sent the message with a delay:

[self performSelector:@selector(setFront:) withObject: [preferencesController window] afterDelay:1.0];

-(void)setFront: (id) theWindow {

 [[NSApplication sharedApplication]activateIgnoringOtherApps:YES];
 [theWindow orderFrontRegardless];
 [theWindow makeKeyWindow]; 
        [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}

Note the send-every-possible-message-to-make-it-do-what-it-should-be-doing-approach.

This works, kind-of, the window is brought to the front on top of all other windows from all apps, BUT most of the time it isn't active, meaning it's title bar is greyed out. Clicking on the title bar won't make the window active either. Clicking INSIDE of the window will make it active!?

This all didn't seem to be a problem in Leopard; just calling activateIgnoringOtherApps and making the window key seemed to work just fine.

In Snow Leopard there is a new API designed to replace LSUIElement that is supposed to emulate its behaviour:

http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html

I've played around with that, but it's SL-only and I haven't been able to get LSUIElement being set.

like image 524
Frank R. Avatar asked May 28 '10 11:05

Frank R.


People also ask

What kills snow leopards?

What are the biggest threats to snow leopards? Hunting, habitat loss, retaliatory killings as a result of human-wildlife conflict, poaching and climate change are the biggest threats that snow leopards face.

Are snow leopards friendly?

Snow leopards are not aggressive towards humans. Even if disturbed while feeding, a snow leopard is more likely to run away than try to defend the site.

How rare are snow leopards?

There are fewer than 10,000 mature snow leopards in the world. These beautiful animals are almost impossible to spot in the wild because they live above the treeline and because their fur blends in with the snow.


2 Answers

That's strange - I'm writing a LSUIElement application under Snow Leopard, and I didn't have such problems as you've described... I did have the problem that the newly created window didn't appear at the front, but I fixed it by calling activateIgnoringOtherApps. This was all I had to do to make it work as it should:

[NSApp activateIgnoringOtherApps: YES];
[preferencesWindow makeKeyAndOrderFront: self];

I didn't even touch anything that had 'policy' in the name.

like image 72
Kuba Suder Avatar answered Oct 19 '22 22:10

Kuba Suder


After posting the question in desperation, I did continue looking and did eventually find the solution. Since this stumped me for a few days and there seems to be no other answer out there that google can find, I'll explain the solution for "future generations".

Snow Leopard adds a new NSApplication presentationOptions API:

http://developer.apple.com/mac/library/releasenotes/cocoa/appkit.html

This is supposed to simulate the way that LSUIElement works, but provide more developer control. Unfortunately, the simulation isn't perfect so there is a change of behaviour between 10.5 and 10.6.

In particular, if your application has the LSUIElement = 1 line in its info.plist, Snow Leopard will initialize "the application’s presentationOptions .. to an equivalent combination of NSApplicationPresentationOptions flags instead".

Only it doesn't really. It sets the new NSApplication setActivationPolicy to NSApplicationActivationPolicyAccessory:

"The application does not appear in the Dock and does not have a menu bar, but it may be activated programmatically or by clicking on one of its windows. This corresponds to value of the LSUIElement key in the application’s Info.plist being 1."

Despite the mention of being activated programatically, activateIgnoringOtherApps: is simply ignored completely.

The solution is to set the activation policy to "regular":

[[NSApplication sharedApplication] setActivationPolicy: NSApplicationActivationPolicyRegular];

Of course, you can only do this if you use the 10.6 SDK as Base SDK, something few people want to do at the moment, so below is a 10.5-safe way of doing this:

NSApplication* app = [NSApplication sharedApplication];

if( [app respondsToSelector: @selector(setActivationPolicy:)] ) {

    NSMethodSignature* method = [[app class] instanceMethodSignatureForSelector: @selector(setActivationPolicy:)];
    NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: method];
    [invocation setTarget: app];
    [invocation setSelector: @selector(setActivationPolicy:)];
    NSInteger myNSApplicationActivationPolicyAccessory = 0;
    [invocation setArgument: &myNSApplicationActivationPolicyAccessory atIndex: 2];
    [invocation invoke];

}

I hope somebody will find this useful.

like image 34
Frank R. Avatar answered Oct 19 '22 23:10

Frank R.