Skip to content

Instantly share code, notes, and snippets.

@0xced
Created March 15, 2012 16:00
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0xced/2044955 to your computer and use it in GitHub Desktop.
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
//
// 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
//
// 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