comparison QuasimodalEventTap.m @ 19:8053681846ad

Refactored event tap C code into an Objective-C class.
author Atul Varma <avarma@mozilla.com>
date Sun, 11 Apr 2010 23:53:49 -0700
parents 78807eea31b7
children 58522f82a39e
comparison
equal deleted inserted replaced
18:78807eea31b7 19:8053681846ad
1 #include <AppKit/NSWorkspace.h> 1 #include <AppKit/NSWorkspace.h>
2 #include <ApplicationServices/ApplicationServices.h>
3 #import <Foundation/NSAutoreleasePool.h> 2 #import <Foundation/NSAutoreleasePool.h>
4 #import <Foundation/NSDistributedNotificationCenter.h> 3 #import <Foundation/NSString.h>
5 #import <Foundation/NSArray.h>
6 #import <Foundation/NSDictionary.h> 4 #import <Foundation/NSDictionary.h>
7 #import <Foundation/NSString.h> 5
8 #include <stdio.h> 6 #import "QuasimodalEventTap.h"
9 7
10 #define QUASIMODE_KEY kCGEventFlagMaskAlternate 8 #define QUASIMODE_KEY kCGEventFlagMaskAlternate
11 #define MAX_STR_LEN 10 9 #define MAX_STR_LEN 10
12 10
13 #ifdef DEBUG 11 #ifdef DEBUG
14 #define DEBUG_MSG(msg) printf(msg); 12 #define DEBUG_MSG(msg) printf(msg);
15 #else 13 #else
16 #define DEBUG_MSG(msg) 14 #define DEBUG_MSG(msg)
17 #endif 15 #endif
18 16
19 CGKeyCode lastQuasimodalKeyCode; 17 static CGEventRef eventTapCallback(CGEventTapProxy proxy,
20 CGEventFlags lastQuasimodalKeyFlags; 18 CGEventType type,
21 int numQuasimodalKeyDowns = 0; 19 CGEventRef event,
20 void *refcon);
22 21
23 static BOOL inQuasimode = NO; 22 @implementation QuasimodalEventTap
24 23 - (void)sendSomeKeyEvent {
25 void sendSomeKeyEvent() {
26 // TODO: Send some-key event 24 // TODO: Send some-key event
27 } 25 }
28 26
29 CGEventRef processEvent(CGEventTapProxy proxy, 27 - (CGEventRef)processEventWithProxy: (CGEventTapProxy)proxy
30 CGEventType type, 28 type: (CGEventType)type
31 CGEventRef event, 29 event: (CGEventRef)event {
32 void *refcon)
33 {
34 BOOL passOnEvent = !inQuasimode; 30 BOOL passOnEvent = !inQuasimode;
35 31
36 if (type == kCGEventFlagsChanged) { 32 if (type == kCGEventFlagsChanged) {
37 CGEventFlags flags = CGEventGetFlags(event); 33 CGEventFlags flags = CGEventGetFlags(event);
38 34
74 inQuasimode = YES; 70 inQuasimode = YES;
75 passOnEvent = NO; 71 passOnEvent = NO;
76 numQuasimodalKeyDowns = 0; 72 numQuasimodalKeyDowns = 0;
77 DEBUG_MSG("Enter quasimode\n"); 73 DEBUG_MSG("Enter quasimode\n");
78 } else { 74 } else {
79 sendSomeKeyEvent(); 75 [self sendSomeKeyEvent];
80 } 76 }
81 } 77 }
82 } else { 78 } else {
83 /* Key up/down event */ 79 /* Key up/down event */
84 80
112 108
113 NSNumber *keycodeNum = [NSNumber numberWithUnsignedInt: keycode]; 109 NSNumber *keycodeNum = [NSNumber numberWithUnsignedInt: keycode];
114 110
115 // TODO: Send event 111 // TODO: Send event
116 } else { 112 } else {
117 sendSomeKeyEvent(); 113 [self sendSomeKeyEvent];
118 } 114 }
119 } 115 }
120 116
121 if (passOnEvent) 117 if (passOnEvent)
122 return event; 118 return event;
123 else 119 else
124 return NULL; 120 return NULL;
125 } 121 }
126 122
127 CGEventRef myCallback(CGEventTapProxy proxy, 123 - (id)init {
128 CGEventType type, 124 if (self = [super init]) {
129 CGEventRef event, 125 numQuasimodalKeyDowns = 0;
130 void *refcon) 126 inQuasimode = NO;
127
128 CGEventMask mask = (CGEventMaskBit(kCGEventKeyDown) |
129 CGEventMaskBit(kCGEventKeyUp) |
130 CGEventMaskBit(kCGEventFlagsChanged));
131
132 portRef = CGEventTapCreate(kCGHIDEventTap,
133 kCGHeadInsertEventTap,
134 0,
135 mask,
136 eventTapCallback,
137 self);
138
139 if (portRef == NULL)
140 printf( "CGEventTapCreate() failed.\n" );
141
142 rlSrcRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault,
143 portRef,
144 0);
145
146 CFRunLoopAddSource(CFRunLoopGetCurrent(),
147 rlSrcRef,
148 kCFRunLoopDefaultMode);
149 }
150 return self;
151 }
152
153 - (void)finalize {
154 CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
155 rlSrcRef,
156 kCFRunLoopDefaultMode);
157
158 CFRelease(rlSrcRef);
159 CFRelease(portRef);
160 }
161 @end
162
163 static CGEventRef eventTapCallback(CGEventTapProxy proxy,
164 CGEventType type,
165 CGEventRef event,
166 void *refcon)
167
131 { 168 {
132 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 169 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
133 CGEventRef retval; 170 CGEventRef retval;
134 NSString *bundleId = [ 171 NSString *bundleId = [
135 [[NSWorkspace sharedWorkspace] activeApplication] 172 [[NSWorkspace sharedWorkspace] activeApplication]
138 175
139 if (bundleId && 176 if (bundleId &&
140 [bundleId isEqualToString: @"com.blizzard.worldofwarcraft"]) { 177 [bundleId isEqualToString: @"com.blizzard.worldofwarcraft"]) {
141 retval = event; 178 retval = event;
142 } else { 179 } else {
143 retval = processEvent(proxy, type, event, refcon); 180 QuasimodalEventTap *tap = (QuasimodalEventTap *) refcon;
181 retval = [tap processEventWithProxy: proxy
182 type: type
183 event: event];
144 } 184 }
145 185
146 [pool release]; 186 [pool release];
147 187
148 return retval; 188 return retval;
149 } 189 }
150
151 int main(int argc, const char *argv[] )
152 {
153 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
154
155 CGEventMask mask = (CGEventMaskBit(kCGEventKeyDown) |
156 CGEventMaskBit(kCGEventKeyUp) |
157 CGEventMaskBit(kCGEventFlagsChanged));
158
159 CFMachPortRef portRef = CGEventTapCreate(kCGHIDEventTap,
160 kCGHeadInsertEventTap,
161 0,
162 mask,
163 myCallback,
164 NULL);
165
166 CFRunLoopSourceRef rlSrcRef;
167
168 if (portRef == NULL) {
169 printf( "CGEventTapCreate() failed.\n" );
170 return -1;
171 }
172
173 rlSrcRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault,
174 portRef,
175 0);
176
177 CFRunLoopAddSource(CFRunLoopGetCurrent(),
178 rlSrcRef,
179 kCFRunLoopDefaultMode);
180
181 // TODO: Run app.
182
183 CFRunLoopRemoveSource(CFRunLoopGetCurrent(),
184 rlSrcRef,
185 kCFRunLoopDefaultMode);
186
187 CFRelease( rlSrcRef );
188 CFRelease( portRef );
189
190 [pool release];
191
192 return 0;
193 }