When calling TransformProcessType(), the app menu doesn't show up
Asked Answered
N

3

7

If you call TransformProcessType() like this :

ProcessSerialNumber psn = { 0, kCurrentProcess }; 
(void) TransformProcessType(&psn, kProcessTransformToForegroundApplication);

Then the cocoa app menu doesn't show up unless you call this early enough in your app (eg. in applicationWillFinishLaunching).

Northing answered 29/9, 2011 at 11:27 Comment(4)
I got the answer but because my reputation is too low I can only answer it within 8 hours. I'll try adding a comment already.Northing
I asked Apple for help and they helped me very well. Quote : > The reason why the menu bar isn't show when you call TransformProcessType is that your app is already the active app (that is, [[NSRunningApplication currentApplication] isActive] returns YES) and the menu bar for an app is shown when the app is activatedNorthing
This is their workaround : - (void)transformStep1 { for (NSRunningApplication * app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"]) { [app activateWithOptions:NSApplicationActivateIgnoringOtherApps]; break; } [self performSelector:@selector(transformStep2) withObject:nil afterDelay:0.1]; }Northing
- (void)transformStep2 { ProcessSerialNumber psn = { 0, kCurrentProcess }; (void) TransformProcessType(&psn, kProcessTransformToForegroundApplication); [self performSelector:@selector(transformStep3) withObject:nil afterDelay:0.1]; } - (void)transformStep3 { [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps]; }Northing
N
15

I asked Apple for help and they helped me very well. Quote :

The reason why the menu bar isn't show when you call TransformProcessType is that your app is already the active app (that is, [[NSRunningApplication currentApplication] isActive] returns YES) and the menu bar for an app is shown when the app is activated

This is their workaround :

- (void)transformStep1 {
    for (NSRunningApplication * app in [NSRunningApplication runningApplicationsWithBundleIdentifier:@"com.apple.finder"]) {
        [app activateWithOptions:NSApplicationActivateIgnoringOtherApps];
        break;
    }
    [self performSelector:@selector(transformStep2) withObject:nil afterDelay:0.1];
}

- (void)transformStep2
{
    ProcessSerialNumber psn = { 0, kCurrentProcess }; 
    (void) TransformProcessType(&psn, kProcessTransformToForegroundApplication);

    [self performSelector:@selector(transformStep3) withObject:nil afterDelay:0.1];
}

- (void)transformStep3
{
    [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateIgnoringOtherApps];
}
Northing answered 29/9, 2011 at 19:54 Comment(1)
I have used @"com.apple.dock". That seems better than activating Finder causing it to jump to foreground.Katowice
Z
2

Here is how I made it working.

BOOL MakeAppForeground()
{
    BOOL bSuccess = TranformAppToState(kProcessTransformToForegroundApplication);

    if(bSuccess)
    {
         bSuccess = (SetSystemUIMode(kUIModeNormal, 0) == 0);
        [NSApp activateIgnoringOtherApps:YES];
    }

    return bSuccess;
}

BOOL MakeAppBackground()
{
    return TranformAppToState(kProcessTransformToBackgroundApplication);
}

BOOL TranformAppToState(ProcessApplicationTransformState newState)
{
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    OSStatus transformStatus = TransformProcessType(&psn, newState);

    if((transformStatus != 0))
    {
        NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:transformStatus userInfo:nil];
        NSLog(@"TranformAppToState: Unable to transform App state. Error - %@",error);
    }

    return (transformStatus == 0);
}
Zuniga answered 7/3, 2014 at 6:7 Comment(0)
E
0

Here is my solution, which is triggered on checkbox click in Preferences window. The only side effect is short flashing of the app's windows:

- (void) hideDockIcon:(bool) hide
{
    ProcessSerialNumber psn = { 0, kCurrentProcess };
    ProcessApplicationTransformState state = hide ? kProcessTransformToUIElementApplication : kProcessTransformToForegroundApplication;
    OSStatus err = TransformProcessType(&psn, state);
    
    if (err) {
        NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil];
        NSLog(@"TransformProcessType failed: %@", error);
    }
}

- (void) toggleDockIcon
{
    [NSApp hide:self];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self hideDockIcon:self.preferences.hideDockIcon];
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [NSApp activateIgnoringOtherApps:YES];
        });
    });
}
Eleven answered 25/9, 2022 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.