7

I'm porting a game from pc to osx and I'm getting stuck with input events. The main game window is a cocoa app that interfaces with a C++ backend. The pc code uses DirectInput and windows messages to generate keyboard and mouse events that the game understands.

When I first started the port I replaced the windows messages with Carbon event handling, but since discovered that Cocoa apps don't fire off carbon events. I did a bit more reading and discovered the HIDManager which seemed to do what I want and was accessible from c++. Using the information in the post here Using IOHIDManager to Get Modifier Key Events I managed to get keyboard input working, but have so far been unable to extend the example code to generate mouse events as well. The code is have is as follows:

 void myHIDCallback(void* context, IOReturn result, void* sender, IOHIDValueRef value)
{
    IOHIDElementRef elem = IOHIDValueGetElement(value);
    if (IOHIDElementGetUsagePage(elem) == 0x07)
    {


        // Keyboard events
        card32 scancode = IOHIDElementGetUsage(elem);
        if (scancode >= 4 && scancode <= 231)
        {
            long pressed = IOHIDValueGetIntegerValue(value);

            KEY_EVENT_DETAILS details = { KEY_EVENT_NONE, NUM_KEYS };

            for (card32 n=0; n<NUM_KEYS; ++n)
            {
                if (n_direct_input_mappings[n].direct_input_key == scancode)
                {
                    details.key_type = n_direct_input_mappings[n].key;
                    break;
                }
            }


            switch (pressed)
            {
                case 0:
                    details.event_type = KEY_EVENT_KEY_DOWN;
                    break;
                case 1:
                    details.event_type = KEY_EVENT_KEY_UP;
                    break;    
            } 

            sApplication->handle_key_event(details);
        }
    }
    else                                                                                                                                            
    if (IOHIDElementGetUsagePage(elem) == 0x02)
    {
        // Mouse events
        card32 usage = IOHIDElementGetUsage(elem);
        long pressed = IOHIDValueGetIntegerValue(value);

    }
    else
    {
    }
}

CFMutableDictionaryRef myCreateDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage)
{
    CFMutableDictionaryRef ret = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (ret)
    {
        CFNumberRef pageNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
        if (pageNumberRef)
        {
            CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsagePageKey), pageNumberRef);
            CFRelease(pageNumberRef);

            CFNumberRef usageNumberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
            if (usageNumberRef)
            {
                CFDictionarySetValue(ret, CFSTR(kIOHIDDeviceUsageKey), usageNumberRef);
                CFRelease(usageNumberRef);

                return ret;

            }                
        }
        CFRelease(ret);
    }
    return NULL;
}

bool acquire_hardware_controllers(CA::Application& app, CAWindow& window_handle)
{        
    sApplication = &app;

    // Setup the keyboard event handler
    sHIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
    IOHIDManagerOpen(sHIDManager, kIOHIDOptionsTypeNone);

    CFMutableDictionaryRef mouse    = myCreateDeviceMatchingDictionary(0x01, 2);
    CFMutableDictionaryRef keyboard = myCreateDeviceMatchingDictionary(0x01, 6);
    CFMutableDictionaryRef keypad   = myCreateDeviceMatchingDictionary(0x01, 7);

    CFMutableDictionaryRef matchesList[] = {
        keyboard,
        keypad,
        mouse
    };

    CFArrayRef matches = CFArrayCreate(kCFAllocatorDefault, (const void**)matchesList, 3, NULL);
    IOHIDManagerSetDeviceMatchingMultiple(sHIDManager, matches);
    IOHIDManagerRegisterInputValueCallback(sHIDManager, myHIDCallback, NULL);
    IOHIDManagerScheduleWithRunLoop(sHIDManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);

}

If anyone can help me out then that would be great. If I can't get this working then I guess I can move over to Cocoa event handling, but the pc code also has some keyboard and mouse polling that I was hoping to implement as well, and I'm not sure that Cocoa supports polling keyboard state - although I will be happy to be corrected.

TIA.

Community
  • 1
  • 1
Teknogrebo
  • 1,247
  • 1
  • 12
  • 22
  • Have you had any luck with this in the time since you asked the question? If so, I'd love to hear what you found out. :) – jalf Feb 13 '13 at 21:29
  • Alternatively you can post events to Window server using [Quartz APIs](http://www.cocoabuilder.com/archive/cocoa/217649-posting-keyboard-events.html). Events can be tapped using [CGEventTapCreate](https://developer.apple.com/library/mac/#documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html) – Raviprakash May 06 '13 at 12:18
  • So, did you find anything? – SkrewEverything Jan 14 '17 at 07:25

0 Answers0