Changeset 49463 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Nov 13, 2013 12:35:28 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/platform/darwin/DarwinKeyboard.cpp
r49457 r49463 1472 1472 } 1473 1473 1474 /** IOKit key press callback. Triggered before Carbon callback. We remember which keyboard produced a keypress here. */ 1475 static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef) 1476 { 1477 (void)unused; 1478 (void)unused1; 1479 1480 AssertReturnVoid(pValueRef); 1481 1482 IOHIDElementRef pElementRef = IOHIDValueGetElement(pValueRef); 1483 AssertReturnVoid(pElementRef); 1484 1485 uint32_t usage = IOHIDElementGetUsage(pElementRef); 1486 1487 if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad) /* Keyboard or keypad event */ 1488 if (usage == kHIDUsage_KeyboardCapsLock || /* CapsLock key has been pressed */ 1489 usage == kHIDUsage_KeypadNumLock) /* ... or NumLock key has been pressed */ 1490 { 1491 VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData; 1492 1493 if (pKbd && pKbd->pParentContainer) 1494 { 1495 bool fKeyDown = (IOHIDValueGetIntegerValue(pValueRef) == 1); 1496 1497 VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pKbd->pParentContainer; 1498 VBoxKbdEvent_t *pEvent = NULL;; 1499 CFIndex iQueue = 0; 1500 1501 AssertReturnVoid(pHidState); 1502 1503 if (RT_FAILURE(RTSemMutexRequest(pHidState->fifoEventQueueLock, RT_INDEFINITE_WAIT))) 1504 return ; 1505 1506 /* Allocate new event data on Key-Down, find a cached one on Key-Up */ 1507 if (fKeyDown) 1508 pEvent = (VBoxKbdEvent_t *)malloc(sizeof(VBoxKbdEvent_t)); 1509 else 1510 { 1511 for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++) 1512 { 1513 VBoxKbdEvent_t *pCachedEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i); 1514 if (pCachedEvent && pCachedEvent->pKbd == pKbd && pCachedEvent->iKeyCode == usage) 1515 { 1516 pEvent = pCachedEvent; 1517 iQueue = i; 1518 break; 1519 } 1520 } 1521 } 1522 1523 if (pEvent) 1524 { 1525 if (usage == kHIDUsage_KeyboardCapsLock && pKbd->cCapsLockTimeout) 1526 { 1527 if (fKeyDown) 1528 pEvent->tsKeyDown = RTTimeSystemMilliTS(); 1529 } 1530 1531 if (fKeyDown) 1532 { 1533 LogRel2(("IOHID: KBD %d: Modifier Key-Down\n", (int)pKbd->idxPosition)); 1534 1535 pEvent->pKbd = pKbd; 1536 pEvent->iKeyCode = usage; 1537 1538 /* Append FIFO event queue */ 1539 CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent); 1540 } 1541 else if (pEvent->iKeyCode == kHIDUsage_KeyboardCapsLock) 1542 { 1543 /* An Apple keyboard */ 1544 if (pKbd->cCapsLockTimeout > 0) 1545 { 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)); 1565 } 1566 /* Non-Apple keyboard */ 1567 else 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 } 1572 } 1573 } 1574 else 1575 { 1576 if (fKeyDown) 1577 LogRel2(("IOHID: unable to find memory for KBD %d event\n", (int)pKbd->idxPosition)); 1578 else 1579 LogRel2(("IOHID: KBD %d event was successfully handled by Carbon callback\n", (int)pKbd->idxPosition)); 1580 } 1581 1582 RTSemMutexRelease(pHidState->fifoEventQueueLock); 1583 } 1584 else 1585 LogRel2(("IOHID: No KBD: A modifier key has been pressed\n")); 1586 } 1587 } 1588 1589 /** Carbon key press callback helper: CapsLock timeout checker. */ 1474 /** IOKit key press callback helper: take care about key-down event. 1475 * This code should be executed within a critical section under pHidState->fifoEventQueueLock. */ 1476 static void darwinHidInputCbKeyDown(VBoxKbdState_t *pKbd, uint32_t iKeyCode, VBoxHidsState_t *pHidState) 1477 { 1478 VBoxKbdEvent_t *pEvent = (VBoxKbdEvent_t *)malloc(sizeof(VBoxKbdEvent_t)); 1479 1480 if (pEvent) 1481 { 1482 /* Queue Key-Down event. */ 1483 pEvent->tsKeyDown = RTTimeSystemMilliTS(); 1484 pEvent->pKbd = pKbd; 1485 pEvent->iKeyCode = iKeyCode; 1486 1487 CFArrayAppendValue(pHidState->pFifoEventQueue, (void *)pEvent); 1488 1489 LogRel2(("IOHID: KBD %d: Modifier Key-Down event\n", (int)pKbd->idxPosition)); 1490 } 1491 else 1492 LogRel2(("IOHID: Modifier Key-Up event. Unable to find memory for KBD %d event\n", (int)pKbd->idxPosition)); 1493 } 1494 1495 /** IOkit and Carbon key press callbacks helper: CapsLock timeout checker. 1496 * 1497 * Returns FALSE if CAPS LOCK timeout not occurred and its state still was not switched (Apple kbd). 1498 * Returns TRUE if CAPS LOCK timeout occurred and its state was switched (Apple kbd). 1499 * Returns TRUE for non-Apple kbd. */ 1590 1500 static bool darwinKbdCapsEventMatches(VBoxKbdEvent_t *pEvent, bool fCapsLed) 1591 1501 { … … 1608 1518 1609 1519 return true; 1520 } 1521 1522 /** IOKit key press callback helper: take care about key-up event. 1523 * This code should be executed within a critical section under pHidState->fifoEventQueueLock. */ 1524 static void darwinHidInputCbKeyUp(VBoxKbdState_t *pKbd, uint32_t iKeyCode, VBoxHidsState_t *pHidState) 1525 { 1526 CFIndex iQueue = 0; 1527 VBoxKbdEvent_t *pEvent = NULL; 1528 1529 /* Key-up event assumes that key-down event occured previously. If so, an event 1530 * data should be in event queue. Attempt to find it. */ 1531 for (CFIndex i = 0; i < CFArrayGetCount(pHidState->pFifoEventQueue); i++) 1532 { 1533 VBoxKbdEvent_t *pCachedEvent = (VBoxKbdEvent_t *)CFArrayGetValueAtIndex(pHidState->pFifoEventQueue, i); 1534 1535 if (pCachedEvent && pCachedEvent->pKbd == pKbd && pCachedEvent->iKeyCode == iKeyCode) 1536 { 1537 pEvent = pCachedEvent; 1538 iQueue = i; 1539 break; 1540 } 1541 } 1542 1543 /* Event found. */ 1544 if (pEvent) 1545 { 1546 /* NUM LOCK should not have timeout and its press should immidiately trigger Carbon callback. 1547 * Therefore, if it is still in queue this is a problem because it was not handled by Carbon callback. 1548 * This mean that NUM LOCK is most likely out of sync. */ 1549 if (iKeyCode == kHIDUsage_KeypadNumLock) 1550 { 1551 LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Key-Down event was not habdled by Carbon callback. " 1552 "NUM LOCK is most likely out of sync\n", (int)pKbd->idxPosition)); 1553 } 1554 else if (iKeyCode == kHIDUsage_KeyboardCapsLock) 1555 { 1556 /* If CAPS LOCK key-press event still not match CAPS LOCK timeout criteria, Carbon callback 1557 * should not be triggered for this event at all. Threfore, event should be removed from queue. */ 1558 if (!darwinKbdCapsEventMatches(pEvent, pHidState->guestState.fCapsLockOn)) 1559 { 1560 free(pEvent); 1561 CFArrayRemoveValueAtIndex(pHidState->pFifoEventQueue, iQueue); 1562 1563 LogRel2(("IOHID: KBD %d: Modifier Key-Up event on Apple keyboard. Key-Down event was triggered %llu ms " 1564 "ago. Carbon event should not be triggered, removed from queue\n", (int)pKbd->idxPosition, 1565 RTTimeSystemMilliTS() - pEvent->tsKeyDown)); 1566 } 1567 else 1568 { 1569 /* CAPS LOCK key-press event matches to CAPS LOCK timeout criteria and still present in queue. 1570 * This might mean that Carbon callback was triggered for this event, but cached keyboard state was not updated. 1571 * It also might mean that Carbon callback still was not triggered, but it will be soon. 1572 * Threfore, CAPS LOCK might be out of sync. */ 1573 LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Key-Down event was triggered %llu ms " 1574 "ago and still was not handled by Carbon callback. CAPS LOCK might out of sync if " 1575 "Carbon will not handle this\n", (int)pKbd->idxPosition, RTTimeSystemMilliTS() - pEvent->tsKeyDown)); 1576 } 1577 } 1578 } 1579 else 1580 LogRel2(("IOHID: KBD %d: Modifier Key-Up event. Modifier state change was " 1581 "successfully handled by Carbon callback\n", (int)pKbd->idxPosition)); 1582 } 1583 1584 /** IOKit key press callback. Triggered before Carbon callback. We remember which keyboard produced a keypress here. */ 1585 static void darwinHidInputCallback(void *pData, IOReturn unused, void *unused1, IOHIDValueRef pValueRef) 1586 { 1587 (void)unused; 1588 (void)unused1; 1589 1590 AssertReturnVoid(pValueRef); 1591 1592 IOHIDElementRef pElementRef = IOHIDValueGetElement(pValueRef); 1593 AssertReturnVoid(pElementRef); 1594 1595 uint32_t usage = IOHIDElementGetUsage(pElementRef); 1596 1597 if (IOHIDElementGetUsagePage(pElementRef) == kHIDPage_KeyboardOrKeypad) /* Keyboard or keypad event */ 1598 if (usage == kHIDUsage_KeyboardCapsLock || /* CapsLock key has been pressed */ 1599 usage == kHIDUsage_KeypadNumLock) /* ... or NumLock key has been pressed */ 1600 { 1601 VBoxKbdState_t *pKbd = (VBoxKbdState_t *)pData; 1602 1603 if (pKbd && pKbd->pParentContainer) 1604 { 1605 bool fKeyDown = (IOHIDValueGetIntegerValue(pValueRef) == 1); 1606 VBoxHidsState_t *pHidState = (VBoxHidsState_t *)pKbd->pParentContainer; 1607 1608 AssertReturnVoid(pHidState); 1609 1610 if (RT_FAILURE(RTSemMutexRequest(pHidState->fifoEventQueueLock, RT_INDEFINITE_WAIT))) 1611 return ; 1612 1613 /* Handle corresponding event. */ 1614 if (fKeyDown) 1615 darwinHidInputCbKeyDown(pKbd, usage, pHidState); 1616 else 1617 darwinHidInputCbKeyUp(pKbd, usage, pHidState); 1618 1619 RTSemMutexRelease(pHidState->fifoEventQueueLock); 1620 } 1621 else 1622 LogRel2(("IOHID: No KBD: A modifier key has been pressed\n")); 1623 } 1610 1624 } 1611 1625 … … 1796 1810 (int)pKbd->idxPosition, pKbd, VBOX_BOOL_TO_STR_STATE(pKbd->LED.fNumLockOn), VBOX_BOOL_TO_STR_STATE(pKbd->LED.fCapsLockOn), 1797 1811 VBOX_BOOL_TO_STR_STATE(pKbd->LED.fScrollLockOn))); 1812 1798 1813 if (fApplyLedState) 1799 1814 {
Note:
See TracChangeset
for help on using the changeset viewer.