InterpreterKeyController.m
author Kevin Mitchell <kam@kamit.com>
Thu Feb 07 01:15:46 2008 -0600 (6 months ago)
changeset 18 174a615be869
parent 4bce1a0916c42
permissions -rw-r--r--
Add copyright notices, license, and readme.
        1 //
        2 //  InterpreterKeyController.m
        3 //  EmbeddedInterpreter
        4 //
        5 //  Created by Kevin on 1/20/08.
        6 //  Copyright (c) 2008 Kevin A. Mitchell
        7 //  
        8 //  Permission is hereby granted, free of charge, to any person obtaining a copy
        9 //  of this software and associated documentation files (the "Software"), to deal
       10 //  in the Software without restriction, including without limitation the rights
       11 //  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       12 //  copies of the Software, and to permit persons to whom the Software is
       13 //  furnished to do so, subject to the following conditions:
       14 //  
       15 //  The above copyright notice and this permission notice shall be included in
       16 //  all copies or substantial portions of the Software.
       17 //  
       18 //  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       19 //  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       20 //  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
       21 //  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       22 //  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
       23 //  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
       24 //  THE SOFTWARE.
       25 //
       26 
       27 #import "InterpreterKeyController.h"
       28 #include "Python.h"
       29 
       30 static CGEventRef eventTapFunction(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
       31 {
       32     UniChar unicodeString[10];
       33     UniCharCount actualStringLength;
       34     
       35     if (![InterpreterKeyController enabled])
       36         return event;
       37     
       38     CGEventKeyboardGetUnicodeString(event, sizeof(unicodeString) / sizeof(*unicodeString), &actualStringLength, unicodeString);
       39     
       40     if ((CGEventGetFlags(event) & kCGEventFlagMaskControl == kCGEventFlagMaskControl) && 
       41         actualStringLength == 1 &&
       42         unicodeString[0] == 3)
       43     {
       44         NSLog(@"control-c");
       45 
       46         // Really important to get the GIL lock. Python gives it up
       47         // every 100 bytecodes, so we won't wait too long.
       48         PyGILState_STATE gilstate = PyGILState_Ensure();
       49         // And once the main thread gets control again, it'll get a
       50         // KeyboardInterrupt
       51         PyErr_SetInterrupt();
       52         PyGILState_Release(gilstate);
       53         
       54         // In this case, we used the event, so just make it null
       55         CGEventSetType(event, kCGEventNull);
       56     }
       57     return event;
       58 }
       59 
       60 
       61 @implementation InterpreterKeyController
       62 static BOOL interruptsEnabled = NO;
       63 
       64 + (BOOL) enabled
       65 {
       66     return interruptsEnabled;
       67 }
       68 
       69 + (void) setEnabled: (BOOL) enabled
       70 {
       71     interruptsEnabled = enabled;
       72 }
       73 
       74 - (void) start
       75 {
       76     [NSThread detachNewThreadSelector: @selector(threadproc:) toTarget: self withObject: NULL];
       77 }
       78 
       79 - (void) threadproc: (void*) arg
       80 {
       81     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
       82     
       83     NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
       84     
       85     [runLoop run];
       86     
       87     CFMachPortRef machPortRef = NULL;
       88     ProcessSerialNumber currentProcess;
       89     GetCurrentProcess(&currentProcess);
       90     machPortRef =  CGEventTapCreateForPSN(&currentProcess,
       91                                           kCGHeadInsertEventTap,
       92                                           0,
       93                                           CGEventMaskBit(kCGEventKeyDown),
       94                                           (CGEventTapCallBack)eventTapFunction,
       95                                           NULL);
       96     if (machPortRef == NULL)
       97         NSLog(@"CGEventTapCreate failed!");
       98     
       99     CFRunLoopSourceRef eventSrc = CFMachPortCreateRunLoopSource(NULL, machPortRef, 0);
      100     if ( eventSrc == NULL )
      101         NSLog(@"CFMachPortCreateRunLoopSource failed!");
      102     
      103     CFRunLoopAddSource([runLoop getCFRunLoop],  eventSrc, kCFRunLoopDefaultMode);
      104     
      105     [runLoop run];
      106     
      107     [runLoop release];
      108     
      109     [pool release];
      110 }
      111 @end
      112 /*
      113 Local variables:
      114 mode: ObjC
      115 tab-width: 4
      116 indent-tabs-mode: nil
      117 c-basic-offset: 4
      118 End:
      119 */