2
* Copyright 2010-2011, Sikuli.org
3
* Released under the MIT License.
6
#include "org_sikuli_script_internal_hotkey_MacHotkeyManager.h"
8
#include <Carbon/Carbon.h>
9
#include <CoreFoundation/CoreFoundation.h>
14
#include "sikuli-debug.h"
17
using namespace sikuli;
19
#define HOTKEY_LISTENER_METHOD "invokeHotkeyPressed"
20
#define HOTKEY_LISTENER_SIGNATURE "(Lorg/sikuli/script/HotkeyEvent;)V"
21
#define HOTKEY_EVENT_CLASS "org/sikuli/script/HotkeyEvent"
26
int jHotkey, jModifiers;
31
CallbackData(JavaVM *vm_, int hotkey_, int mods_, jobject listener_){
39
jobject CallbackDataToHotkeyEvent(JNIEnv* env, CallbackData* data){
40
jclass clsHkEvent = env->FindClass(HOTKEY_EVENT_CLASS);
41
jobject ret = env->AllocObject(clsHkEvent);
42
jmethodID initMethod = env->GetMethodID(clsHkEvent, "init", "(II)V");
43
env->CallVoidMethod(ret, initMethod, data->jHotkey, data->jModifiers);
44
env->DeleteLocalRef(clsHkEvent);
50
void callJavaMethod(JavaVM *jvm, jobject listener, CallbackData* data){
52
jvm->GetEnv((void**)&env, JNI_VERSION_1_4);
53
jvm->AttachCurrentThread((void **)&env, NULL);
54
jclass cls = env->GetObjectClass(listener);
55
jmethodID mid = env->GetMethodID(cls, HOTKEY_LISTENER_METHOD, HOTKEY_LISTENER_SIGNATURE);
57
cerr << "Callback method not found." << endl;
60
jobject hkEvent = CallbackDataToHotkeyEvent(env, data);
61
env->CallVoidMethod(listener, mid, hkEvent);
64
static map<int, CallbackData*> regHotkeys;
65
static int gHotkeyId = 0;
67
OSStatus shortcutHandler( EventHandlerCallRef inCaller, EventRef inEvent,
71
GetEventParameter(inEvent, kEventParamDirectObject, typeEventHotKeyID, NULL,
72
sizeof(hkId), NULL, &hkId);
73
CallbackData *data = regHotkeys[hkId.id];
74
int hotkey = data->hotkey;
75
dout("MacHotkeyManager") << "shortcut pressed. " << hotkey << endl;
76
callJavaMethod(data->vm, data->listener, data);
81
bool unregisterHotkey(CallbackData *data){
82
map<int, CallbackData*>::iterator it;
83
for(it = regHotkeys.begin(); it != regHotkeys.end(); ++it){
84
CallbackData *itdata = it->second;
85
if( itdata->hotkey == data->hotkey && itdata->mods == data->mods){
86
UnregisterEventHotKey(itdata->ref);
87
data->id = itdata->id;
88
data->ref = itdata->ref;
97
bool installShortcutHandler( CallbackData *data ){
98
EventTypeSpec shortcutEvents[] = {
99
{ kEventClassKeyboard, kEventHotKeyPressed },
103
OSErr err = InstallApplicationEventHandler( &shortcutHandler,
104
GetEventTypeCount(shortcutEvents), shortcutEvents, NULL, NULL);
106
cerr << "InstallApplicationEventHandler failed" << endl;
109
bool registered = unregisterHotkey(data);
111
data->id.id = gHotkeyId++;
112
data->id.signature='htk1';
115
OSStatus err = RegisterEventHotKey(data->hotkey, data->mods,
116
data->id, GetApplicationEventTarget(), 0,
119
regHotkeys[data->id.id] = data;
126
* Class: org_sikuli_script_internal_hotkey_MacHotkeyManager
127
* Method: installGlobalHotkey
128
* Signature: (IIIILorg/sikuli/script/internal/hotkey/HotkeyListener;)Z
130
JNIEXPORT jboolean JNICALL Java_org_sikuli_script_internal_hotkey_MacHotkeyManager_installGlobalHotkey
131
(JNIEnv *env, jobject jobj, jint jHotkey, jint jModifiers, jint hotkey, jint modifiers, jobject listener){
132
dout("MacHotkeyManager") << "install global hotkey: " << hotkey << " mod: " << modifiers << endl;
135
jobject gListener = env->NewGlobalRef(listener);
136
env->DeleteLocalRef(listener);
137
CallbackData *data = new CallbackData(vm, hotkey, modifiers, gListener);
138
data->jHotkey = jHotkey;
139
data->jModifiers = jModifiers;
140
return installShortcutHandler(data);
145
* Class: org_sikuli_script_internal_hotkey_MacHotkeyManager
146
* Method: uninstallGlobalHotkey
149
JNIEXPORT jboolean JNICALL
150
Java_org_sikuli_script_internal_hotkey_MacHotkeyManager_uninstallGlobalHotkey
151
(JNIEnv *env, jobject jobj, jint hotkey, jint modifiers){
152
CallbackData *data = new CallbackData(NULL, hotkey, modifiers, NULL);
153
return unregisterHotkey(data);
157
* Class: org_sikuli_script_internal_hotkey_MacHotkeyManager
161
JNIEXPORT void JNICALL Java_org_sikuli_script_internal_hotkey_MacHotkeyManager_cleanUp
162
(JNIEnv *env, jobject jobj){
163
map<int, CallbackData*>::iterator it;
164
for(it = regHotkeys.begin(); it != regHotkeys.end(); ++it){
165
CallbackData *itdata = it->second;
166
UnregisterEventHotKey(itdata->ref);