//
//  HotKeyedApplication.m
//  Afficheur
//
//  Created by kichi on 08/04/09.
//  Copyright 2008 Katsuhiko Ichinose. All rights reserved.
//

#import "HotKeyedApplication.h"
#import <Carbon/Carbon.h>


@implementation HotKeyedApplication

enum {
	// NSEvent subtypes for hotkey events (undocumented).
	kEventHotKeyPressedSubtype = 6,
	kEventHotKeyReleasedSubtype = 9,
};

+ (HotKeyedApplication *)sharedApplication
{
	return (HotKeyedApplication *)[super sharedApplication];
}

- (id)init
{
	self = [super init];
	if (self)
	{
		_dic = [[NSMutableDictionary dictionary] retain];
	}
	return self;
}

- (void)dealloc
{
	[_dic release];
	[super dealloc];
}

- (void)sendEvent:(NSEvent *)event
{
	if ([event type] == NSSystemDefined && [event subtype] == kEventHotKeyPressedSubtype)
	{
		EventHotKeyRef	hotKeyRef = (EventHotKeyRef)[event data1];
		NSData *data = (NSData *)[_dic objectForKey:[NSNumber numberWithInt:(int)hotKeyRef]];
		if (data)
		{
			id	target = nil;
			SEL	selector = nil;
			[data getBytes:&target range:NSMakeRange(0, sizeof(int))];
			[data getBytes:&selector range:NSMakeRange(sizeof(int), sizeof(int))];
			if (target && selector && [target respondsToSelector:selector])
			{
				[target performSelector:selector];
			}
		}
	}
	[super sendEvent:event];
}

- (void *)registerHotKey:(unsigned int)keyCode
			withModifier:(unsigned int)modifier
				  target:(id)target
				selector:(SEL)selector
{
	static UInt32	_id = 0;
	UInt32	keyModifiers = 0;
	if (modifier & NSShiftKeyMask)
	{
		keyModifiers |= shiftKey;
	}
	if (modifier & NSControlKeyMask)
	{
		keyModifiers |= controlKey;
	}
	if (modifier & NSCommandKeyMask)
	{
		keyModifiers |= cmdKey;
	}
	if (modifier & NSAlternateKeyMask)
	{
		keyModifiers |= optionKey;
	}
	EventHotKeyID	hotKeyID;
	hotKeyID.signature = 'HotK';
	hotKeyID.id = _id++;
	EventHotKeyRef	hotKeyRef;
	OSStatus result = RegisterEventHotKey(keyCode,
										  keyModifiers,
										  hotKeyID,
										  GetApplicationEventTarget(),
										  0,
										  &hotKeyRef);
	if (result != noErr)
	{
		return NULL;
	}
	int	data[2];
	data[0] = (int)target;
	data[1] = (int)selector;
	[_dic setObject:[NSData dataWithBytes:data length:sizeof(data)]
			 forKey:[NSNumber numberWithInt:(int)hotKeyRef]];
	return (void *)hotKeyRef;
}

- (void)unregisterHotKey:(void *)hotKeyRef
{
	UnregisterEventHotKey(hotKeyRef);
	[_dic removeObjectForKey:[NSNumber numberWithInt:(int)hotKeyRef]];
}

@end
