VirtualBox

Changeset 49457 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 13, 2013 10:24:10 AM (11 years ago)
Author:
vboxsync
Message:

OS X host: HID LEDs sync: take care about CAPS LOCK timeout on Apple keyboards (taking into account current LED state); rename Carbon callback and split it into smaller parts.

File:
1 edited

Legend:

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

    r49361 r49457  
    322322    uint32_t        iKeyCode;
    323323    uint64_t        tsKeyDown;
    324     uint64_t        tsKeyUp;
    325324} VBoxKbdEvent_t;
    326325
     
    15281527                        if (fKeyDown)
    15291528                            pEvent->tsKeyDown = RTTimeSystemMilliTS();
    1530                         else
    1531                             pEvent->tsKeyUp = RTTimeSystemMilliTS();
    15321529                    }
    15331530
     
    15381535                        pEvent->pKbd = pKbd;
    15391536                        pEvent->iKeyCode = usage;
    1540                         pEvent->tsKeyUp = 0;
    15411537
    15421538                        /* Append FIFO event queue */
    15431539                        CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent);
    15441540                    }
    1545                     else
     1541                    else if (pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock)
    15461542                    {
    1547                         uint64_t tsDiff = pEvent->tsKeyUp - pEvent->tsKeyDown;
    1548                         if (tsDiff < pKbd->cCapsLockTimeout)
     1543                        /* An Apple keyboard */
     1544                        if (pKbd->cCapsLockTimeout > 0)
    15491545                        {
    1550                             free(pEvent);
    1551                             CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue);
    1552                             LogRel2(("IOHID: KBD %d: Modifier Key-Up (Key-Down %llu ms ago). Apple keyboard, removed from queue\n", (int)pKbd->idxPosition, tsDiff));
     1546                            if (pHidState->guestState.fCapsLockOn == false)
     1547                            {
     1548                                uint64_t tsDiff = RTTimeSystemMilliTS() - pEvent->tsKeyDown;
     1549                                if (tsDiff < pKbd->cCapsLockTimeout)
     1550                                {
     1551                                    /* Such key-press should not trigger Carbon callback. Just remove an event from queue. */
     1552                                    free(pEvent);
     1553                                    CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue);
     1554                                    LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard. Key-Down event was triggered %llu ms "
     1555                                        "ago. Carbon event should not be triggered, removed from queue\n", (int)pKbd->idxPosition, tsDiff));
     1556                                }
     1557                                else
     1558                                    LogRel2(("IOHID: KBD %d: Modifier Key-Up event: Apple keyboard: possibly LEDs now out of sync. "
     1559                                        "Diff between Key-Down and Key-Up is too big (%llu ms) but Carbon callback did not care about "
     1560                                        "Key-Down event.\n", (int)pKbd->idxPosition, tsDiff));
     1561                            }
     1562                            else
     1563                                LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard occurred before Carbon callback. No worries.\n",
     1564                                    (int)pKbd->idxPosition));
    15531565                        }
     1566                        /* Non-Apple keyboard */
    15541567                        else
    1555                             LogRel2(("IOHID: KBD %d: Modifier Key-Up (Key-Down %llu ms ago)\n", (int)pKbd->idxPosition, tsDiff));
     1568                        {
     1569                            LogRel2(("IOHID: KBD %d: Modifier Key-Up event: Non-Apple keyboard: possibly LEDs now out of sync. "
     1570                                "Carbon callback did not care about Key-Down event.\n", (int)pKbd->idxPosition));
     1571                        }
    15561572                    }
    15571573                }
     
    15591575                {
    15601576                    if (fKeyDown)
    1561                         LogRel2(("IOHID: unable to find memory to queue KBD %d event\n", (int)pKbd->idxPosition));
     1577                        LogRel2(("IOHID: unable to find memory for KBD %d event\n", (int)pKbd->idxPosition));
    15621578                    else
    1563                         LogRel2(("IOHID: unable to find KBD %d event in queue\n", (int)pKbd->idxPosition));
     1579                        LogRel2(("IOHID: KBD %d event was successfully handled by Carbon callback\n", (int)pKbd->idxPosition));
    15641580                }
    15651581
     
    15711587}
    15721588
    1573 /** Carbon key press callback. Triggered after IOKit callback. We update keyboard (catched in darwinHidInputCallback()) internal state here. */
    1574 static CGEventRef darwinCarbonGlobalKeyPressCallback(CGEventTapProxy unused, CGEventType unused1, CGEventRef pEventRef, void *pData)
     1589/** Carbon key press callback helper: CapsLock timeout checker. */
     1590static bool darwinKbdCapsEventMatches(VBoxKbdEvent_t *pEvent, bool fCapsLed)
     1591{
     1592    /* CapsLock timeout is only applicable if conditions
     1593     * below are satisfied:
     1594     *
     1595     * a) Key pressed on Apple keyboard
     1596     * b) CapsLed is OFF at the moment when CapsLock key is pressed
     1597     */
     1598
     1599    bool fAppleKeyboard = (pEvent->pKbd->cCapsLockTimeout > 0);
     1600
     1601    /* Apple keyboard */
     1602    if (fAppleKeyboard && !fCapsLed)
     1603    {
     1604        uint64_t tsDiff = RTTimeSystemMilliTS() - pEvent->tsKeyDown;
     1605        if (tsDiff < pEvent->pKbd->cCapsLockTimeout)
     1606            return false;
     1607    }
     1608
     1609    return true;
     1610}
     1611
     1612/** Carbon key press callback helper: find last occured KBD event in queue
     1613 * (ignoring those events which do not match CAPS LOCK timeout criteria).
     1614 * Once event found, it is removed from queue. This code should be executed
     1615 * within a critical section under pHidState->fifoEventQueueLock. */
     1616static VBoxKbdEvent_t *darwinCarbonCbFindEvent(VBoxHidsState_t *pHidState)
     1617{
     1618    VBoxKbdEvent_t *pEvent = NULL;
     1619
     1620    for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++)
     1621    {
     1622        pEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i);
     1623
     1624        /* Paranoia: skip potentially dangerous data items. */
     1625        if (!pEvent || !pEvent->pKbd) continue;
     1626
     1627        if ( pEvent->iKeyCode == kHIDUsage_KeypadNumLock
     1628         || (pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock && darwinKbdCapsEventMatches(pEvent, pHidState->guestState.fCapsLockOn)))
     1629        {
     1630            /* Found one. Remove it from queue. */
     1631            CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, i);
     1632
     1633            LogRel2(("CARBON: Found event in queue: %d (KBD %d, tsKeyDown=%llu, pressed %llu ms ago)\n", (int)i,
     1634                (int)pEvent->pKbd->idxPosition, pEvent->tsKeyDown, RTTimeSystemMilliTS() - pEvent->tsKeyDown));
     1635
     1636            break;
     1637        }
     1638        else
     1639            LogRel2(("CARBON: Skip keyboard event from KBD %d, key pressed %llu ms ago\n",
     1640                (int)pEvent->pKbd->idxPosition, RTTimeSystemMilliTS() - pEvent->tsKeyDown));
     1641
     1642        pEvent = NULL;
     1643    }
     1644
     1645    return pEvent;
     1646}
     1647
     1648/** Carbon key press callback. Triggered after IOKit callback. */
     1649static CGEventRef darwinCarbonCallback(CGEventTapProxy unused, CGEventType unused1, CGEventRef pEventRef, void *pData)
    15751650{
    15761651    (void)unused;
     
    15911666        key == kHIDUsage_KeypadNumLock)
    15921667    {
    1593         /* Extract last touched state from FIFO event queue */
    1594         VBoxKbdEvent_t *pEvent = NULL;
    1595         CFIndex         iEvent = 0;
    1596 
    1597         /* Find last occured KBD event in queue (ignoring those events which not match CAPS LOCK timeout criteria). */
    1598         for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++)
    1599         {
    1600             pEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i);
    1601             if (!pEvent) continue;
    1602             if (!pEvent->pKbd) continue;
    1603 
    1604             if (pEvent->iKeyCode == kHIDUsage_KeypadNumLock
    1605              || pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock)
    1606             {
    1607                 /* Found one. Keep its index in queue in order to remove it later. */
    1608                 iEvent = i;
    1609                 LogRel2(("CARBON: Found event in queue: %d (KBD %d, tsKeyDown=%llu, pressed %llu ms ago)\n", (int)i, (int)pEvent->pKbd->idxPosition, pEvent->tsKeyDown, RTTimeSystemMilliTS() - pEvent->tsKeyDown));
    1610                 break;
    1611             }
    1612             else
    1613                 LogRel2(("CARBON: skip CAPS LOCK event %d (KBD %d) (tsKeyDown=%llu, pressed %llu ms ago)\n", (int)i, (int)pEvent->pKbd->idxPosition, pEvent->tsKeyDown, RTTimeSystemMilliTS() - pEvent->tsKeyDown));
    1614 
    1615             pEvent = NULL;
    1616         }
    1617 
     1668        /* Attempt to find an event queued by IOKit callback. */
     1669        VBoxKbdEvent_t *pEvent = darwinCarbonCbFindEvent(pHidState);
    16181670        if (pEvent)
    16191671        {
     
    16221674            LogRel2(("CARBON: KBD %d: caps=%s, num=%s. tsKeyDown=%llu, tsKeyUp=%llu [tsDiff=%llu ms]. %d events in queue.\n",
    16231675                (int)pKbd->idxPosition, VBOX_BOOL_TO_STR_STATE(fCaps), VBOX_BOOL_TO_STR_STATE(fNum),
    1624                 pEvent->tsKeyDown, pEvent->tsKeyUp, pEvent->tsKeyUp - pEvent->tsKeyDown,
     1676                pEvent->tsKeyDown, RTTimeSystemMilliTS(), RTTimeSystemMilliTS() - pEvent->tsKeyDown,
    16251677                CFArrayGetCount(pHidState->pFifoEventQueue)));
    16261678
     
    16411693            }
    16421694
    1643             /* Forget event */
    1644             CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iEvent);
    16451695            free(pEvent);
    16461696        }
    16471697        else
    1648             LogRel2(("CARBON: No KBD to take care when modifier key has been pressed: caps=%s, num=%s\n", VBOX_BOOL_TO_STR_STATE(fCaps), VBOX_BOOL_TO_STR_STATE(fNum)));
     1698            LogRel2(("CARBON: No KBD to take care when modifier key has been pressed: caps=%s, num=%s (%d events in queue)\n",
     1699                VBOX_BOOL_TO_STR_STATE(fCaps), VBOX_BOOL_TO_STR_STATE(fNum), CFArrayGetCount(pHidState->pFifoEventQueue)));
    16491700    }
    16501701
     
    17791830
    17801831/** Register Carbon key press callback. */
    1781 static int darwinAddCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState)
     1832static int darwinAddCarbonHandler(VBoxHidsState_t *pHidState)
    17821833{
    17831834    CFMachPortRef pTapRef;
     
    17991850    }
    18001851
    1801     pTapRef = CGEventTapCreate(kCGSessionEventTap, kCGTailAppendEventTap, 0, fMask, darwinCarbonGlobalKeyPressCallback, (void *)pHidState);
     1852    pTapRef = CGEventTapCreate(kCGSessionEventTap, kCGTailAppendEventTap, 0, fMask, darwinCarbonCallback, (void *)pHidState);
    18021853    if (pTapRef)
    18031854    {
     
    18261877
    18271878/** Remove Carbon key press callback. */
    1828 static void darwinRemoveCarbonGlobalKeyPressHandler(VBoxHidsState_t *pHidState)
     1879static void darwinRemoveCarbonHandler(VBoxHidsState_t *pHidState)
    18291880{
    18301881    AssertReturnVoid(pHidState);
     
    18721923                if (pHidState->pDeviceCollection)
    18731924                {
    1874                     if (darwinAddCarbonGlobalKeyPressHandler(pHidState) == 0)
     1925                    if (darwinAddCarbonHandler(pHidState) == 0)
    18751926                    {
    18761927                        /* Populate cache with HID devices */
     
    19411992
    19421993    /* Need to unregister Carbon stuff first */
    1943     darwinRemoveCarbonGlobalKeyPressHandler(pHidState);
     1994    darwinRemoveCarbonHandler(pHidState);
    19441995
    19451996    CFDictionaryRef elementMatchingDict = darwinQueryLedElementMatchingDictionary();
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