Mercurial > enso_osx
view src/EnsoKeyNotifier.m @ 16:e07f0c7abdc0
Changed the notification messages sent by the key notifier to be more descriptive.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Sun, 24 Feb 2008 20:15:57 -0600 |
parents | af72a81169aa |
children | 5477703cfb73 |
line wrap: on
line source
#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 NSDistributedNotificationCenter *center; CGKeyCode lastQuasimodalKeyCode; CGEventFlags lastQuasimodalKeyFlags; int numQuasimodalKeyDowns = 0; static BOOL inQuasimode = NO; static void sendSomeKeyEvent( void ) { NSArray *keys = [NSArray arrayWithObjects: @"event", nil]; NSArray *values = [NSArray arrayWithObjects: @"someKey", nil]; NSDictionary *dict = [NSDictionary dictionaryWithObjects: values forKeys: keys]; [center postNotificationName: @"EnsoKeyNotifier_msg" object: @"EnsoKeyNotifier" userInfo: dict]; } CGEventRef myCallback( CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon ) { //int64_t keycode = CGEventGetIntegerValueField( // event, // kCGKeyboardEventKeycode // ); BOOL passOnEvent = !inQuasimode; if ( type == kCGEventFlagsChanged ) { CGEventFlags flags = CGEventGetFlags( event ); if ( inQuasimode ) { if ( !(flags & QUASIMODE_KEY) ) { NSArray *keys = [NSArray arrayWithObjects: @"event", nil]; NSArray *values = [NSArray arrayWithObjects: @"quasimodeEnd", nil]; NSDictionary *dict = [NSDictionary dictionaryWithObjects: values forKeys: keys]; [center postNotificationName: @"EnsoKeyNotifier_msg" object: @"EnsoKeyNotifier" userInfo: dict]; inQuasimode = NO; if ( numQuasimodalKeyDowns == 1 ) { CGEventRef event[2]; printf( "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] ); } printf( "Exit quasimode\n" ); } } else { if ( flags & QUASIMODE_KEY ) { NSArray *keys = [NSArray arrayWithObjects: @"event", nil]; NSArray *values = [NSArray arrayWithObjects: @"quasimodeStart", nil]; NSDictionary *dict = [NSDictionary dictionaryWithObjects: values forKeys: keys]; [center postNotificationName: @"EnsoKeyNotifier_msg" object: @"EnsoKeyNotifier" userInfo: dict]; inQuasimode = YES; passOnEvent = NO; numQuasimodalKeyDowns = 0; printf( "Enter quasimode\n" ); } else { sendSomeKeyEvent(); } } } else { /* Key up/down event */ if ( inQuasimode ) { #define MAX_STR_LEN 10 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]; NSArray *keys = [NSArray arrayWithObjects: @"event", @"chars", @"keycode", nil]; NSArray *values = [NSArray arrayWithObjects: eventType, chars, keycodeNum, nil]; NSDictionary *dict = [NSDictionary dictionaryWithObjects: values forKeys: keys]; [center postNotificationName: @"EnsoKeyNotifier_msg" object: @"EnsoKeyNotifier" userInfo: dict]; } else { sendSomeKeyEvent(); } } if ( passOnEvent ) return event; else return NULL; } int main( int argc, const char *argv[] ) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; center = [NSDistributedNotificationCenter defaultCenter]; CGEventMask mask = ( CGEventMaskBit( kCGEventKeyDown ) | CGEventMaskBit( kCGEventKeyUp ) | CGEventMaskBit( kCGEventFlagsChanged ) ); CFMachPortRef portRef = CGEventTapCreate( //kCGSessionEventTap, 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 ); printf( "Please make sure either of the following is true:\n\n" " (1) This program is running with super-user privileges.\n" " (2) Access for assistive devices is enabled in the \n" " Universal Access System Preferences.\n\n" "If one or more of these conditions is not satisfied, then " "quasimodal keypresses will not be recognized.\n" ); printf( "Running event loop...\n" ); //CFRunLoopRunInMode( kCFRunLoopDefaultMode, 10.0, false ); CFRunLoopRun(); printf( "Done running event loop.\n" ); CFRunLoopRemoveSource( CFRunLoopGetCurrent(), rlSrcRef, kCFRunLoopDefaultMode ); CFRelease( rlSrcRef ); CFRelease( portRef ); [pool release]; return 0; }