Changeset 49457 in vbox for trunk/src/VBox
- Timestamp:
- Nov 13, 2013 10:24:10 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp
r49361 r49457 322 322 uint32_t iKeyCode; 323 323 uint64_t tsKeyDown; 324 uint64_t tsKeyUp;325 324 } VBoxKbdEvent_t; 326 325 … … 1528 1527 if (fKeyDown) 1529 1528 pEvent->tsKeyDown = RTTimeSystemMilliTS(); 1530 else1531 pEvent->tsKeyUp = RTTimeSystemMilliTS();1532 1529 } 1533 1530 … … 1538 1535 pEvent->pKbd = pKbd; 1539 1536 pEvent->iKeyCode = usage; 1540 pEvent->tsKeyUp = 0;1541 1537 1542 1538 /* Append FIFO event queue */ 1543 1539 CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent); 1544 1540 } 1545 else 1541 else if (pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock) 1546 1542 { 1547 uint64_t tsDiff = pEvent->tsKeyUp - pEvent->tsKeyDown;1548 if ( tsDiff < pKbd->cCapsLockTimeout)1543 /* An Apple keyboard */ 1544 if (pKbd->cCapsLockTimeout > 0) 1549 1545 { 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)); 1553 1565 } 1566 /* Non-Apple keyboard */ 1554 1567 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 } 1556 1572 } 1557 1573 } … … 1559 1575 { 1560 1576 if (fKeyDown) 1561 LogRel2(("IOHID: unable to find memory to queueKBD %d event\n", (int)pKbd->idxPosition));1577 LogRel2(("IOHID: unable to find memory for KBD %d event\n", (int)pKbd->idxPosition)); 1562 1578 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)); 1564 1580 } 1565 1581 … … 1571 1587 } 1572 1588 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. */ 1590 static 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. */ 1616 static 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. */ 1649 static CGEventRef darwinCarbonCallback(CGEventTapProxy unused, CGEventType unused1, CGEventRef pEventRef, void *pData) 1575 1650 { 1576 1651 (void)unused; … … 1591 1666 key == kHIDUsage_KeypadNumLock) 1592 1667 { 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); 1618 1670 if (pEvent) 1619 1671 { … … 1622 1674 LogRel2(("CARBON: KBD %d: caps=%s, num=%s. tsKeyDown=%llu, tsKeyUp=%llu [tsDiff=%llu ms]. %d events in queue.\n", 1623 1675 (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, 1625 1677 CFArrayGetCount(pHidState->pFifoEventQueue))); 1626 1678 … … 1641 1693 } 1642 1694 1643 /* Forget event */1644 CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iEvent);1645 1695 free(pEvent); 1646 1696 } 1647 1697 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))); 1649 1700 } 1650 1701 … … 1779 1830 1780 1831 /** Register Carbon key press callback. */ 1781 static int darwinAddCarbon GlobalKeyPressHandler(VBoxHidsState_t *pHidState)1832 static int darwinAddCarbonHandler(VBoxHidsState_t *pHidState) 1782 1833 { 1783 1834 CFMachPortRef pTapRef; … … 1799 1850 } 1800 1851 1801 pTapRef = CGEventTapCreate(kCGSessionEventTap, kCGTailAppendEventTap, 0, fMask, darwinCarbon GlobalKeyPressCallback, (void *)pHidState);1852 pTapRef = CGEventTapCreate(kCGSessionEventTap, kCGTailAppendEventTap, 0, fMask, darwinCarbonCallback, (void *)pHidState); 1802 1853 if (pTapRef) 1803 1854 { … … 1826 1877 1827 1878 /** Remove Carbon key press callback. */ 1828 static void darwinRemoveCarbon GlobalKeyPressHandler(VBoxHidsState_t *pHidState)1879 static void darwinRemoveCarbonHandler(VBoxHidsState_t *pHidState) 1829 1880 { 1830 1881 AssertReturnVoid(pHidState); … … 1872 1923 if (pHidState->pDeviceCollection) 1873 1924 { 1874 if (darwinAddCarbon GlobalKeyPressHandler(pHidState) == 0)1925 if (darwinAddCarbonHandler(pHidState) == 0) 1875 1926 { 1876 1927 /* Populate cache with HID devices */ … … 1941 1992 1942 1993 /* Need to unregister Carbon stuff first */ 1943 darwinRemoveCarbon GlobalKeyPressHandler(pHidState);1994 darwinRemoveCarbonHandler(pHidState); 1944 1995 1945 1996 CFDictionaryRef elementMatchingDict = darwinQueryLedElementMatchingDictionary();
Note:
See TracChangeset
for help on using the changeset viewer.