Search code examples
objective-cmacoscocoamacos-carbon

Cocoa switch focus to application and then switch it back


I want to create OS X application which shows up and getting focused with system-wide hotkey, and then, with same hotkey it should dissapear and switch focus back. Just like Alfred does it.

The problem is that I can't focus back on application previously used. By focusing back I mean that I can't continue typing in previous app.

Here is my hotkey handler:

OSStatus OnHotKeyEvent(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{
    AppDelegate *me = (__bridge AppDelegate*) userData;

    EventHotKeyID hkCom;

    GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hkCom), NULL, &hkCom);

    if([[me window] isVisible]) {
        [[NSApplication sharedApplication] activateIgnoringOtherApps:NO];
        [[me window] orderOut:NULL];
    }
    else {
        [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
        [[me window] makeKeyAndOrderFront:nil];

    }

    return noErr;
}

Solution

  • well activate in both cases... you should deactivate. BEFORE you activate, save old active app

            _oldApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
    

    later activate that

            [_oldApp activateWithOptions:NSApplicationActivateIgnoringOtherApps];
    

    --- full source

    @implementation DDAppDelegate {
        NSStatusItem *_item;
        NSRunningApplication *_oldApp;
    }
    
    - (void)applicationWillFinishLaunching:(NSNotification *)notification {
        NSLog(@"%@", [[NSWorkspace sharedWorkspace] frontmostApplication].bundleIdentifier);
    
        _item = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
        _item.title = @"TEST";
        _item.target = self;
        _item.action = @selector(toggle:);
    }
    
    - (void)applicationWillBecomeActive:(NSNotification *)notification {
        NSLog(@"%@", [[NSWorkspace sharedWorkspace] frontmostApplication].bundleIdentifier);
    }
    
    //---
    
    - (IBAction)toggle:(id)sender {
        if(!_oldApp) {
            NSLog(@"%@", [[NSWorkspace sharedWorkspace] frontmostApplication].bundleIdentifier);
            _oldApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
            [NSApp activateIgnoringOtherApps:YES];
        }
        else {
            [_oldApp activateWithOptions:NSApplicationActivateIgnoringOtherApps];
            _oldApp = nil;
        }
    }
    @end