Created
March 15, 2012 16:00
-
-
Save 0xced/2044955 to your computer and use it in GitHub Desktop.
NSRunningApplication category to dynamically show and hide any running application icon in the Dock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Cédric Luthi on 2011-05-03 | |
// Copyright 2011-2012 Cédric Luthi. All rights reserved. | |
// | |
#import <AppKit/AppKit.h> | |
@interface NSRunningApplication (DockIcon) | |
- (BOOL) setDockIconHidden_xcd:(BOOL)dockIconHidden; | |
@end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by Cédric Luthi on 2011-05-03 | |
// Copyright 2011-2012 Cédric Luthi. All rights reserved. | |
// | |
#import "NSRunningApplication+DockIcon.h" | |
#import <dlfcn.h> | |
@interface NSRunningApplication (Private) | |
- (CFTypeRef) applicationSerialNumber; | |
@end | |
@implementation NSRunningApplication (DockIcon) | |
static NSString *const HideDockIconKey = @"HideDockIcon"; | |
static OSStatus (*_LSSetApplicationInformationItem)(int, CFTypeRef asn, CFStringRef key, CFStringRef value, CFDictionaryRef *info) = NULL; | |
static CFStringRef _kLSApplicationTypeKey = NULL; | |
static CFStringRef _kLSApplicationForegroundTypeKey = NULL; | |
static CFStringRef _kLSApplicationUIElementTypeKey = NULL; | |
static CFStringRef _kLSApplicationBackgroundOnlyTypeKey = NULL; | |
static BOOL isSafe = NO; | |
+ (void) load | |
{ | |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
[self performSelector:@selector(initializeDockIcon) withObject:nil afterDelay:0.0]; | |
[pool drain]; | |
} | |
static CFStringRef launchServicesKey(const char *symbol) | |
{ | |
CFStringRef *keyPtr = dlsym(RTLD_DEFAULT, symbol); | |
return keyPtr ? *keyPtr : NULL; | |
} | |
+ (void) initializeDockIcon | |
{ | |
if (![[NSUserDefaults standardUserDefaults] boolForKey:HideDockIconKey]) | |
[[NSRunningApplication currentApplication] setDockIconHidden_xcd:NO]; | |
_LSSetApplicationInformationItem = dlsym(RTLD_DEFAULT, "_LSSetApplicationInformationItem"); | |
_kLSApplicationTypeKey = launchServicesKey("_kLSApplicationTypeKey"); | |
_kLSApplicationForegroundTypeKey = launchServicesKey("_kLSApplicationForegroundTypeKey"); | |
_kLSApplicationUIElementTypeKey = launchServicesKey("_kLSApplicationUIElementTypeKey"); | |
_kLSApplicationBackgroundOnlyTypeKey = launchServicesKey("_kLSApplicationBackgroundOnlyTypeKey"); | |
BOOL allSymbolsFound = _LSSetApplicationInformationItem && _kLSApplicationTypeKey && | |
_kLSApplicationForegroundTypeKey && _kLSApplicationUIElementTypeKey && _kLSApplicationBackgroundOnlyTypeKey; | |
if (!allSymbolsFound) | |
return; | |
NSMethodSignature *asnMethodSignature = [NSRunningApplication instanceMethodSignatureForSelector:@selector(applicationSerialNumber)]; | |
NSString *asnMethodReturnType = asnMethodSignature ? [NSString stringWithUTF8String:[asnMethodSignature methodReturnType]] : @""; | |
isSafe = [asnMethodReturnType isEqualToString:@"^{__LSASN=}"]; | |
} | |
- (BOOL) setDockIconHidden_xcd:(BOOL)dockIconHidden | |
{ | |
BOOL isCurrentApplication = [self isEqual:[NSRunningApplication currentApplication]]; | |
if (isCurrentApplication) | |
[[NSUserDefaults standardUserDefaults] setBool:dockIconHidden forKey:HideDockIconKey]; | |
OSStatus status = noErr; | |
if (dockIconHidden) | |
{ | |
if (!isSafe) | |
return NO; | |
BOOL isBackgroundOnlyType = self.bundleURL ? [[[NSBundle bundleWithURL:self.bundleURL] objectForInfoDictionaryKey:@"LSBackgroundOnly"] boolValue] : YES; | |
CFStringRef applicationType = isBackgroundOnlyType ? _kLSApplicationBackgroundOnlyTypeKey : _kLSApplicationUIElementTypeKey; | |
status = _LSSetApplicationInformationItem(-2, [self applicationSerialNumber], _kLSApplicationTypeKey, applicationType, NULL); | |
} | |
else | |
{ | |
if (isCurrentApplication) | |
{ | |
ProcessSerialNumber psn; | |
status = GetProcessForPID(self.processIdentifier, &psn); | |
if (status != noErr) | |
return NO; | |
status = TransformProcessType(&psn, kProcessTransformToForegroundApplication); | |
} | |
else | |
{ | |
if (!isSafe) | |
return NO; | |
status = _LSSetApplicationInformationItem(-2, [self applicationSerialNumber], _kLSApplicationTypeKey, _kLSApplicationForegroundTypeKey, NULL); | |
} | |
} | |
return status == noErr; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment