Mercurial > osx-quasimode
view QuasimodalEventTap.m @ 18:78807eea31b7
Added EnsoKeyNotifier.m from Enso source, renamed to QuasimodalEventTap.m w/ some notification center stuff removed and formatting fixed to match this codebase.
author | Atul Varma <avarma@mozilla.com> |
---|---|
date | Sun, 11 Apr 2010 23:11:14 -0700 |
parents | |
children | 8053681846ad |
line wrap: on
line source
#include <AppKit/NSWorkspace.h> #include <ApplicationServices/ApplicationServices.h> #import <Foundation/NSAutoreleasePool.h> #import <Foundation/NSDistributedNotificationCenter.h> #import <Foundation/NSArray.h> #import <Foundation/NSDictionary.h> #import <Foundation/NSString.h> #include <stdio.h> #define QUASIMODE_KEY kCGEventFlagMaskAlternate #define MAX_STR_LEN 10 #ifdef DEBUG #define DEBUG_MSG(msg) printf(msg); #else #define DEBUG_MSG(msg) #endif CGKeyCode lastQuasimodalKeyCode; CGEventFlags lastQuasimodalKeyFlags; int numQuasimodalKeyDowns = 0; static BOOL inQuasimode = NO; void sendSomeKeyEvent() { // TODO: Send some-key event } CGEventRef processEvent(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { BOOL passOnEvent = !inQuasimode; if (type == kCGEventFlagsChanged) { CGEventFlags flags = CGEventGetFlags(event); if (inQuasimode) { if (!(flags & QUASIMODE_KEY)) { // TODO: Send quasimodeend event inQuasimode = NO; if (numQuasimodalKeyDowns == 1) { CGEventRef event[2]; DEBUG_MSG("Re-posting single keypress\n"); event[0] = CGEventCreateKeyboardEvent( NULL, (CGKeyCode) lastQuasimodalKeyCode, true ); event[1] = CGEventCreateKeyboardEvent( NULL, (CGKeyCode) lastQuasimodalKeyCode, false ); CGEventSetFlags(event[0], lastQuasimodalKeyFlags); CGEventSetFlags(event[1], lastQuasimodalKeyFlags); CGEventTapPostEvent(proxy, event[0]); CGEventTapPostEvent(proxy, event[1]); CFRelease(event[0]); CFRelease(event[1]); } DEBUG_MSG("Exit quasimode\n"); } } else { if (flags & QUASIMODE_KEY) { // TODO: Send quasimodestart event inQuasimode = YES; passOnEvent = NO; numQuasimodalKeyDowns = 0; DEBUG_MSG("Enter quasimode\n"); } else { sendSomeKeyEvent(); } } } else { /* Key up/down event */ if (inQuasimode) { UniChar strbuf[MAX_STR_LEN]; UniCharCount charsCopied; CGEventKeyboardGetUnicodeString( event, MAX_STR_LEN, &charsCopied, strbuf ); NSString *chars = [NSString stringWithCharacters: strbuf length: charsCopied]; NSString *eventType; int64_t keycode = CGEventGetIntegerValueField( event, kCGKeyboardEventKeycode ); if (type == kCGEventKeyDown) { numQuasimodalKeyDowns += 1; lastQuasimodalKeyCode = keycode; lastQuasimodalKeyFlags = CGEventGetFlags(event); eventType = @"keyDown"; } else eventType = @"keyUp"; NSNumber *keycodeNum = [NSNumber numberWithUnsignedInt: keycode]; // TODO: Send event } else { sendSomeKeyEvent(); } } if (passOnEvent) return event; else return NULL; } CGEventRef myCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; CGEventRef retval; NSString *bundleId = [ [[NSWorkspace sharedWorkspace] activeApplication] objectForKey: @"NSApplicationBundleIdentifier" ]; if (bundleId && [bundleId isEqualToString: @"com.blizzard.worldofwarcraft"]) { retval = event; } else { retval = processEvent(proxy, type, event, refcon); } [pool release]; return retval; } int main(int argc, const char *argv[] ) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; CGEventMask mask = (CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged)); CFMachPortRef portRef = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, 0, mask, myCallback, NULL); CFRunLoopSourceRef rlSrcRef; if (portRef == NULL) { printf( "CGEventTapCreate() failed.\n" ); return -1; } rlSrcRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, portRef, 0); CFRunLoopAddSource(CFRunLoopGetCurrent(), rlSrcRef, kCFRunLoopDefaultMode); // TODO: Run app. CFRunLoopRemoveSource(CFRunLoopGetCurrent(), rlSrcRef, kCFRunLoopDefaultMode); CFRelease( rlSrcRef ); CFRelease( portRef ); [pool release]; return 0; }