VirtualBox

Changeset 48741 in vbox


Ignore:
Timestamp:
Sep 27, 2013 3:09:56 PM (11 years ago)
Author:
vboxsync
Message:

OS X host: keyboard LEDs ans state sync: sync using IOKit and Carbon callbacks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp

    r48677 r48741  
    300300/* HID LEDs synchronization data: IOKit specific data. */
    301301typedef struct VBoxHidsState_t {
    302     IOHIDManagerRef  hidManagerRef;
    303     IOHIDDeviceRef  *hidDevicesCollection;
    304     VBoxHidLeds_t   *hidLedsCollection;
    305     CFIndex          cDevices;
     302    IOHIDManagerRef     hidManagerRef;
     303    IOHIDDeviceRef     *hidDevicesCollection;
     304    VBoxHidLeds_t      *hidLedsCollection;
     305    CFIndex             cDevices;
     306    CFMachPortRef       pTapRef;
     307    CFRunLoopSourceRef  pLoopSourceRef;
    306308} VBoxHidsState_t;
     309
     310/* A *sync* between IOKit and Carbon callbacks. */
     311static VBoxHidLeds_t *g_LastTouchedState;
    307312#endif // !VBOX_WITH_KBD_LEDS_SYNC
    308313
     
    13581363    return rc2;
    13591364}
     1365
     1366
     1367
     1368static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef valueRef)
     1369{
     1370    (void)unused;
     1371    (void)unused1;
     1372
     1373    IOHIDElementRef pElementRef = IOHIDValueGetElement(valueRef);
     1374
     1375    if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad)        /* Keyboard or keypad event */
     1376        if (IOHIDValueGetIntegerValue(valueRef) == 1)                              /* key has been pressed down */
     1377            if (IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeyboardCapsLock || /* CapsLock key has been pressed */
     1378                IOHIDElementGetUsage(pElementRef) == kHIDUsage_KeypadNumLock)      /* ... or NumLock key has been pressed */
     1379            {
     1380                Log2(("A modifier key has been pressed\n"));
     1381                g_LastTouchedState = (VBoxHidLeds_t *)pData;
     1382            }
     1383}
     1384
     1385#define VBOX_BOOL_TO_STR_STATE(x) (x) ? "ON" : "OFF"
     1386static CGEventRef darwinCarbonGlobalKeyPressCallback(CGEventTapProxy unused, CGEventType type, CGEventRef pEventRef, void *unused1)
     1387{
     1388    (void)unused;
     1389    (void)unused1;
     1390
     1391    /* Skip events we are not interested in. */
     1392    if (type != kCGEventKeyDown && type != kCGEventFlagsChanged)
     1393        return pEventRef;
     1394
     1395    CGEventFlags fMask = CGEventGetFlags(pEventRef);
     1396    bool         fCaps = (bool)(fMask & NX_ALPHASHIFTMASK);
     1397    bool         fNum  = (bool)(fMask & NX_NUMERICPADMASK);
     1398    CGKeyCode    key   = CGEventGetIntegerValueField(pEventRef, kCGKeyboardEventKeycode);
     1399
     1400    if (key == kHIDUsage_KeyboardCapsLock ||
     1401        key == kHIDUsage_KeypadNumLock)
     1402    {
     1403        Log2(("carbon event: caps=%s, num=%s\n", VBOX_BOOL_TO_STR_STATE(fCaps), VBOX_BOOL_TO_STR_STATE(fNum)));
     1404        if (g_LastTouchedState)
     1405        {
     1406            g_LastTouchedState->fCapsLockOn = fCaps;
     1407            g_LastTouchedState->fNumLockOn  = fNum;
     1408        }
     1409    }
     1410
     1411    return pEventRef;
     1412}
     1413#undef VBOX_BOOL_TO_STR_STATE
     1414
     1415static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *pState)
     1416{
     1417    CFMachPortRef pTapRef;
     1418    CGEventMask   fMask = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventFlagsChanged);
     1419
     1420    g_LastTouchedState = NULL;
     1421
     1422    pTapRef = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, fMask, darwinCarbonGlobalKeyPressCallback, NULL);
     1423    if (pTapRef)
     1424    {
     1425        CFRunLoopSourceRef pLoopSourceRef;
     1426        pLoopSourceRef = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, pTapRef, 0);
     1427        if (pLoopSourceRef)
     1428        {
     1429            CFRunLoopAddSource(CFRunLoopGetCurrent(), pLoopSourceRef, kCFRunLoopCommonModes);
     1430            CGEventTapEnable(pTapRef, true);
     1431
     1432            pState->pTapRef = pTapRef;
     1433            pState->pLoopSourceRef = pLoopSourceRef;
     1434
     1435            return 0;
     1436        }
     1437        else
     1438            Log2(("Unable to create a loop source\n"));
     1439
     1440        CFRelease(pTapRef);
     1441    }
     1442    else
     1443        Log2(("Unable to create an event tap\n"));
     1444
     1445    return kIOReturnError;
     1446}
     1447
     1448static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *pState)
     1449{
     1450    AssertReturnVoid(pState);
     1451    AssertReturnVoid(pState->pTapRef);
     1452    AssertReturnVoid(pState->pLoopSourceRef);
     1453
     1454    g_LastTouchedState = NULL;
     1455
     1456    CGEventTapEnable(pState->pTapRef, false);
     1457    CFRunLoopRemoveSource(CFRunLoopGetCurrent(), pState->pLoopSourceRef, kCFRunLoopCommonModes);
     1458    CFRelease(pState->pLoopSourceRef);
     1459}
     1460
    13601461#endif // !VBOX_WITH_KBD_LEDS_SYNC
    13611462
     
    14191520                                            }
    14201521
     1522                                            /* Register per-device input callback */
     1523                                            IOHIDDeviceRegisterInputValueCallback(hidsState->hidDevicesCollection[i], darwinHidInputCallback, (void *)&hidsState->hidLedsCollection[i]);
     1524                                            IOHIDDeviceScheduleWithRunLoop(hidsState->hidDevicesCollection[i], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    14211525                                        }
    14221526                                    }
    14231527
    1424                                     CFRelease(deviceMatchingDictRef);
    14251528                                    CFRelease(elementMatchingDict);
    14261529
    1427                                     return hidsState;
     1530                                    if (darwinAddCarbonGlobalKeyPressHandler(hidsState) == 0)
     1531                                    {
     1532                                        CFRelease(deviceMatchingDictRef);
     1533                                        return hidsState;
     1534                                    }
    14281535                                }
    14291536
     
    14721579    if (hidsState)
    14731580    {
     1581        /* Need to unregister Carbon stuff first */
     1582        darwinRemoveCarbonGlobalKeyPressHandler(hidsState);
     1583
    14741584        CFDictionaryRef elementMatchingDict = darwinGetLedElementMatchingDictionary();
    14751585        if (elementMatchingDict)
     
    14881598                    rc2 = kIOReturnError;
    14891599                }
     1600
     1601                IOHIDDeviceRegisterInputValueCallback(hidsState->hidDevicesCollection[i], NULL, NULL);
     1602                IOHIDDeviceUnscheduleFromRunLoop(hidsState->hidDevicesCollection[i], CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
    14901603            }
    14911604        }
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette