~ubuntu-branches/ubuntu/utopic/sikuli/utopic

« back to all changes in this revision

Viewing changes to sikuli-script/src/main/native/MacHotkeyManager.cc

  • Committer: Bazaar Package Importer
  • Author(s): Gilles Filippini
  • Date: 2011-10-04 23:32:13 UTC
  • mfrom: (4.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20111004233213-36fm78hx0z53tkuw
Tags: 1.0~x~rc3-dfsg1-2
* New patch fix-cmake-sikuli-ide.patch:
  + Fix random FTBFS due to missing inter target dependency

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2010-2011, Sikuli.org
 
3
 * Released under the MIT License.
 
4
 *
 
5
 */
 
6
#include "org_sikuli_script_internal_hotkey_MacHotkeyManager.h"
 
7
 
 
8
#include <Carbon/Carbon.h>
 
9
#include <CoreFoundation/CoreFoundation.h>
 
10
 
 
11
#include<iostream>
 
12
#include<map>
 
13
 
 
14
#include "sikuli-debug.h"
 
15
 
 
16
using namespace std;
 
17
using namespace sikuli;
 
18
 
 
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"
 
22
 
 
23
struct CallbackData {
 
24
   JavaVM *vm;
 
25
   int hotkey, mods;
 
26
   int jHotkey, jModifiers;
 
27
   jobject listener;
 
28
   EventHotKeyRef ref;
 
29
   EventHotKeyID id;
 
30
 
 
31
   CallbackData(JavaVM *vm_, int hotkey_, int mods_, jobject listener_){
 
32
      vm = vm_;
 
33
      hotkey = hotkey_;
 
34
      mods = mods_;
 
35
      listener = listener_;
 
36
   }
 
37
};
 
38
 
 
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);
 
45
   return ret;
 
46
}
 
47
 
 
48
 
 
49
 
 
50
void callJavaMethod(JavaVM *jvm, jobject listener, CallbackData* data){
 
51
   JNIEnv *env;
 
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); 
 
56
   if( mid == NULL ){
 
57
      cerr << "Callback method not found." << endl;
 
58
      return;
 
59
   }
 
60
   jobject hkEvent = CallbackDataToHotkeyEvent(env, data);
 
61
   env->CallVoidMethod(listener, mid, hkEvent);
 
62
}
 
63
 
 
64
static map<int, CallbackData*> regHotkeys;
 
65
static int gHotkeyId = 0;
 
66
 
 
67
OSStatus shortcutHandler( EventHandlerCallRef inCaller, EventRef inEvent, 
 
68
                          void* args )
 
69
{
 
70
   EventHotKeyID hkId;
 
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);
 
77
   return noErr;
 
78
}
 
79
 
 
80
 
 
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;
 
89
         regHotkeys.erase(it);
 
90
         return true;
 
91
      }
 
92
   }
 
93
   return false;
 
94
}
 
95
 
 
96
 
 
97
bool installShortcutHandler( CallbackData *data ){
 
98
   EventTypeSpec shortcutEvents[] = {
 
99
      { kEventClassKeyboard, kEventHotKeyPressed },
 
100
   };
 
101
   
 
102
   if(gHotkeyId == 0){
 
103
      OSErr err = InstallApplicationEventHandler( &shortcutHandler,
 
104
        GetEventTypeCount(shortcutEvents), shortcutEvents, NULL, NULL);
 
105
      if (err != noErr)
 
106
         cerr << "InstallApplicationEventHandler failed" << endl;
 
107
   }
 
108
 
 
109
   bool registered = unregisterHotkey(data); 
 
110
   if(!registered){
 
111
      data->id.id = gHotkeyId++;
 
112
      data->id.signature='htk1';
 
113
   }
 
114
 
 
115
   OSStatus err = RegisterEventHotKey(data->hotkey, data->mods,
 
116
                      data->id, GetApplicationEventTarget(), 0, 
 
117
                      &(data->ref));
 
118
   if(!err){
 
119
      regHotkeys[data->id.id] = data;
 
120
      return true;
 
121
   }
 
122
   return false;
 
123
}
 
124
 
 
125
/*
 
126
 * Class:     org_sikuli_script_internal_hotkey_MacHotkeyManager
 
127
 * Method:    installGlobalHotkey
 
128
 * Signature: (IIIILorg/sikuli/script/internal/hotkey/HotkeyListener;)Z
 
129
 */
 
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;
 
133
   JavaVM* vm = NULL;
 
134
   env->GetJavaVM(&vm);
 
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);
 
141
}
 
142
 
 
143
 
 
144
/*
 
145
 * Class:     org_sikuli_script_internal_hotkey_MacHotkeyManager
 
146
 * Method:    uninstallGlobalHotkey
 
147
 * Signature: (II)Z
 
148
 */
 
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);
 
154
}
 
155
 
 
156
/*
 
157
 * Class:     org_sikuli_script_internal_hotkey_MacHotkeyManager
 
158
 * Method:    cleanUp
 
159
 * Signature: ()V
 
160
 */
 
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);
 
167
   }
 
168
   regHotkeys.clear();
 
169
   gHotkeyId = 0;
 
170
}