InterpreterKeyController.m
author Kevin Mitchell <kam@kamit.com>
Thu Feb 07 01:15:46 2008 -0600 (17 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 */