tdevdraw: dynamic discovery of MultiTouch devices - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 5e83be0dbf9667f7d11a167f9eacc31837ed4c7d
 (DIR) parent e055ceb20bd94caff3b07e64a051ab3a899c0463
 (HTM) Author: Marius Eriksen <marius.eriksen@gmail.com>
       Date:   Mon, 20 Jun 2011 14:14:53 -0400
       
       devdraw: dynamic discovery of MultiTouch devices
       
       R=rsc
       CC=plan9port.codebot
       http://codereview.appspot.com/4653041
       
       Diffstat:
         M CONTRIBUTORS                        |       1 +
         M src/cmd/devdraw/osx-screen-carbon.m |     114 ++++++++++++++++++++++++++++---
       
       2 files changed, 107 insertions(+), 8 deletions(-)
       ---
 (DIR) diff --git a/CONTRIBUTORS b/CONTRIBUTORS
       t@@ -17,6 +17,7 @@ Fazlul Shahriar <fshahriar@gmail.com>
        J.R. Mauro <jrm8005@gmail.com>
        Jeff Sickel <jas@corpus-callosum.com>
        Kris Maglione <jg@suckless.org>
       +Marius Eriksen <marius.eriksen@gmail.com>
        Mathieu Lonjaret <lejatorn@gmail.com>
        Mathieu Lonjaret <mathieu.lonjaret@gmail.com>
        Michael Teichgräber <mt4swm@googlemail.com>
 (DIR) diff --git a/src/cmd/devdraw/osx-screen-carbon.m b/src/cmd/devdraw/osx-screen-carbon.m
       t@@ -2,6 +2,10 @@
        #define Rect OSXRect
        #define Cursor OSXCursor
        #include <Carbon/Carbon.h>
       +#ifdef MULTITOUCH
       +#include <IOKit/IOKitLib.h>
       +#include <IOKit/hidsystem/IOHIDShared.h>
       +#endif
        #undef Rect
        #undef Point
        #undef Cursor
       t@@ -26,6 +30,7 @@ AUTOFRAMEWORK(Cocoa)
        
        #ifdef MULTITOUCH
        AUTOFRAMEWORK(MultitouchSupport)
       +AUTOFRAMEWORK(IOKit)
        #endif
        
        #define panic sysfatal
       t@@ -115,11 +120,15 @@ CFMutableArrayRef MTDeviceCreateList(void);
        
        //registers a device's frame callback to your callback function 
        void MTRegisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction); 
       +void MTUnregisterContactFrameCallback(MTDeviceRef, MTContactCallbackFunction); 
        
        //start sending events 
        void MTDeviceStart(MTDeviceRef, int); 
        void MTDeviceStop(MTDeviceRef); 
        
       +MTDeviceRef MTDeviceCreateFromService(io_service_t);
       +io_service_t MTDeviceGetService(MTDeviceRef);
       +
        #define kNTracks 10
        struct TouchTrack {
                int id;
       t@@ -280,25 +289,114 @@ enum
        void screeninit(void);
        void _flushmemscreen(Rectangle r);
        
       +#ifdef MULTITOUCH
       +static void
       +RegisterMultitouch(void *ctx, io_iterator_t iter)
       +{
       +        io_object_t io;
       +        MTDeviceRef dev;
       +
       +        while((io = IOIteratorNext(iter)) != 0){
       +                dev = MTDeviceCreateFromService(io);
       +                if (dev != nil){
       +                        MTRegisterContactFrameCallback(dev, touchCallback);
       +                        [osx.devicelist addObject:dev];
       +                        if(osx.active)
       +                                MTDeviceStart(dev, 0);
       +                }
       +                
       +                IOObjectRelease(io);
       +        }
       +}
       +
        static void
       -InitMultiTouch(void)
       +UnregisterMultitouch(void *ctx, io_iterator_t iter)
       +{
       +        io_object_t io;
       +        MTDeviceRef dev;
       +        int i;
       +        
       +        while((io = IOIteratorNext(iter)) != 0){
       +                for(i = 0; i < [osx.devicelist count]; i++){
       +                        dev = [osx.devicelist objectAtIndex:i];
       +                        if(IOObjectIsEqualTo(MTDeviceGetService(dev), io)){
       +                                if(osx.active)
       +                                        MTDeviceStop(dev);
       +                                MTUnregisterContactFrameCallback(dev, touchCallback);
       +                                [osx.devicelist removeObjectAtIndex:i];
       +                                break;
       +                        }
       +                }
       +
       +                IOObjectRelease(io);
       +        }
       +}
       +
       +#endif /*MULTITOUCH*/
       +
       +static void
       +InitMultiTouch()
        {
        #ifdef MULTITOUCH
       +        IONotificationPortRef port;
       +        CFRunLoopSourceRef source;
       +        io_iterator_t iter;
       +        kern_return_t kr;
       +        io_object_t obj;
                int i;
        
       -        /*
       -         * Setup multitouch queues
       -         */
                if(!multitouch)
                        return;
        
       -        for(i = 0; i<kNTracks; ++i)
       +        osx.devicelist = [[NSMutableArray alloc] init];
       +
       +        for(i = 0; i < kNTracks; ++i)
                        tracks[i].id = -1;
        
       -        osx.devicelist = (NSMutableArray*)MTDeviceCreateList(); //grab our device list 
       -        for(i = 0; i<[osx.devicelist count]; i++) { //iterate available devices 
       -                MTRegisterContactFrameCallback([osx.devicelist objectAtIndex:i], touchCallback); //assign callback for device 
       +        port = IONotificationPortCreate(kIOMasterPortDefault);
       +        if(port == nil){
       +                fprint(2, "failed to get an IO notification port\n");
       +                return;
       +        }
       +
       +        source = IONotificationPortGetRunLoopSource(port);
       +        if(source == nil){
       +                fprint(2, "failed to get loop source for port");
       +                return;
                }
       +
       +        CFRunLoopAddSource(
       +                (CFRunLoopRef)GetCFRunLoopFromEventLoop(GetMainEventLoop()), 
       +                source, 
       +                kCFRunLoopDefaultMode);
       +
       +        kr = IOServiceAddMatchingNotification(
       +                port, kIOTerminatedNotification,
       +                IOServiceMatching("AppleMultitouchDevice"), 
       +                &UnregisterMultitouch,
       +                nil, &iter);
       +
       +        if(kr != KERN_SUCCESS){
       +                fprint(2, "failed to add termination notification\n");
       +                return;
       +        }
       +
       +        /* Arm the notification */
       +        while((obj = IOIteratorNext(iter)) != 0)
       +                IOObjectRelease(obj);
       +
       +        kr = IOServiceAddMatchingNotification(
       +                port, kIOMatchedNotification,
       +                IOServiceMatching("AppleMultitouchDevice"),
       +                &RegisterMultitouch,
       +                nil, &iter);
       +
       +        if(kr != KERN_SUCCESS){
       +                fprint(2, "failed to add matching notification\n");
       +                return;
       +        }
       +
       +        RegisterMultitouch(nil, iter);
        #endif
        }