Changeset 53221 in vbox for trunk/src/VBox/Frontends
- Timestamp:
- Nov 5, 2014 9:09:40 AM (10 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.cpp
r52730 r53221 171 171 LogRel2(("HID LEDs sync: broadcast failed\n")); 172 172 } 173 174 /** @brief doesCurrentLayoutHaveAltGr 175 * 176 * @return true if this keyboard layout has an AltGr key, false otherwise 177 * Check to see whether the current keyboard layout actually has an AltGr key 178 * by checking whether any of the keys which might do produce a symbol when 179 * AltGr (Control + Alt) is depressed. Generally this loop will exit pretty 180 * early (it exits on the first iteration for my German layout). If there is 181 * no AltGr key in the layout then it will run right through, but that should 182 * hopefully not happen very often. 183 * 184 * In theory we could do this once and cache the result, but that involves 185 * tracking layout switches to invalidate the cache, and I don't think that the 186 * added complexity is worth the price. */ 187 static bool doesCurrentLayoutHaveAltGr() 188 { 189 /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */ 190 const BYTE auKeyStates[256] = 191 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 }; 192 WORD ach; 193 unsigned i; 194 195 for (i = '0'; i <= VK_OEM_102; ++i) 196 { 197 if (ToAscii(i, 0, auKeyStates, &ach, 0)) 198 break; 199 /* Skip ranges of virtual keys which are undefined or not relevant. */ 200 if (i == '9') 201 i = 'A' - 1; 202 if (i == 'Z') 203 i = VK_OEM_1 - 1; 204 if (i == VK_OEM_3) 205 i = VK_OEM_4 - 1; 206 if (i == VK_OEM_8) 207 i = VK_OEM_102 - 1; 208 } 209 if (i > VK_OEM_102) 210 return false; 211 return true; 212 } 213 214 void WinAltGrMonitor::updateStateFromKeyEvent(unsigned iDownScanCode, 215 bool fKeyDown, bool fExtendedKey) 216 { 217 LONG messageTime = GetMessageTime(); 218 /* We do not want the make/break: */ 219 AssertRelease(~iDownScanCode & 0x80); 220 /* Depending on m_enmFakeControlDetectionState: */ 221 switch (m_enmFakeControlDetectionState) 222 { 223 case NONE: 224 case FAKE_CONTROL_DOWN: 225 if ( iDownScanCode == 0x1D /* left control */ 226 && fKeyDown 227 && !fExtendedKey) 228 m_enmFakeControlDetectionState = LAST_EVENT_WAS_LEFT_CONTROL_DOWN; 229 else 230 m_enmFakeControlDetectionState = NONE; 231 break; 232 case LAST_EVENT_WAS_LEFT_CONTROL_DOWN: 233 if ( iDownScanCode == 0x38 /* Alt */ 234 && fKeyDown 235 && fExtendedKey 236 && m_timeOfLastKeyEvent == messageTime 237 && doesCurrentLayoutHaveAltGr()) 238 { 239 m_enmFakeControlDetectionState = FAKE_CONTROL_DOWN; 240 break; 241 } 242 else 243 m_enmFakeControlDetectionState = LEFT_CONTROL_DOWN; 244 /* Fall through. */ 245 case LEFT_CONTROL_DOWN: 246 if ( iDownScanCode == 0x1D /* left control */ 247 && !fKeyDown 248 && !fExtendedKey) 249 m_enmFakeControlDetectionState = NONE; 250 break; 251 default: 252 AssertReleaseMsgFailed(("Unknown AltGr detection state.\n")); 253 } 254 m_timeOfLastKeyEvent = messageTime; 255 } 256 257 bool WinAltGrMonitor::isLeftControlReleaseNeeded() const 258 { 259 return m_enmFakeControlDetectionState == FAKE_CONTROL_DOWN; 260 } 261 262 bool WinAltGrMonitor::isCurrentEventDefinitelyFake(unsigned iDownScanCode, 263 bool fKeyDown, 264 bool fExtendedKey) const 265 { 266 MSG peekMsg; 267 LONG messageTime = GetMessageTime(); 268 269 if ( iDownScanCode != 0x1d /* scan code: Control */ || fExtendedKey) 270 return false; 271 if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE)) 272 return false; 273 274 if ( fKeyDown 275 && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN)) 276 return false; 277 if ( !fKeyDown 278 && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP)) 279 return false; 280 if ( ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */) 281 || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED)) 282 return false; 283 if (!doesCurrentLayoutHaveAltGr()) 284 return false; 285 return true; 286 } -
trunk/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.h
r52727 r53221 28 28 bool winHidLedsInSync(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn); 29 29 30 /** Helper class to deal with Windows AltGr handling. 31 * 32 * Background: Windows sends AltGr key down and up events as two events: a 33 * left control event and a right alt one. Since the left control event does 34 * not correspond to actually pressing or releasing the left control key we 35 * would like to detect it and handle it. This class monitors all key down and 36 * up events and if it detects that a left control down event has been sendt 37 * although left control should be up it tells us to insert a left control up 38 * event into the event stream. While this does not let us filter out the 39 * unwanted event at source, it should still make guest system keyboard handling 40 * work correctly. */ 41 class WinAltGrMonitor 42 { 43 public: 44 45 /** Constructor. */ 46 WinAltGrMonitor() : m_enmFakeControlDetectionState(NONE), m_timeOfLastKeyEvent(0) {} 47 48 /** All key events should be fed to this method. 49 * @param iDownScanCode the scan code stripped of the make/break bit 50 * @param fKeyDown is this a key down event? 51 * @param fExtended is this an extended scan code? */ 52 void updateStateFromKeyEvent(unsigned iDownScanCode, bool fKeyDown, bool fExtended); 53 54 /** Do we need to insert a left control up into the stream? */ 55 bool isLeftControlReleaseNeeded() const; 56 57 /** Can we tell for sure at this point that the current message is a fake 58 * control event? This method might fail to recognise a fake event, but 59 * should never incorrectly flag a non-fake one. 60 * @note We deliberately do not call this from the host combination editor 61 * in an attempt to ensure that the other code path also gets enough 62 * test coverage. 63 */ 64 bool isCurrentEventDefinitelyFake(unsigned iDownScanCode, 65 bool fKeyDown, 66 bool fExtendedKey) const; 67 68 private: 69 70 /** State detection for fake control events which we may have missed. */ 71 enum 72 { 73 /** No interesting state. */ 74 NONE, 75 /** The last keypress might be a fake control. */ 76 LAST_EVENT_WAS_LEFT_CONTROL_DOWN, 77 /** Left control is down, so we ignore fake control events. */ 78 LEFT_CONTROL_DOWN, 79 /** A fake control down event and no up was passed to the guest. */ 80 FAKE_CONTROL_DOWN 81 } m_enmFakeControlDetectionState; 82 DWORD m_timeOfLastKeyEvent; 83 }; 30 84 #endif /* __WinKeyboard_h__ */ 31 85 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
r53138 r53221 72 72 #endif /* Q_WS_MAC */ 73 73 74 74 #ifdef Q_WS_WIN 75 # include "WinKeyboard.h" 76 #endif /* Q_WS_WIN */ 77 75 78 /* Enums representing different keyboard-states: */ 76 79 enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 }; … … 413 416 } 414 417 415 /**416 * @brief isSyntheticLCtrl417 * @param pMsg Windows WM_[SYS]KEY* event message structure418 * @return true if this is a synthetic LCtrl event, false otherwise419 * This function is a heuristic to tell whether a key event is the first in420 * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr. Our421 * heuristic is in two parts. First of all, we check whether there is a pending422 * RAlt key event matching this LCtrl event (i.e. both key up or both key down)423 * and if there is, we check whether the current layout has an AltGr key. We424 * check this by looking to see if any of the layout-dependent keys has a symbol425 * associated when AltGr is pressed.426 */427 static bool isSyntheticLCtrl(MSG *pMsg)428 {429 MSG peekMsg;430 /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */431 const BYTE auKeyStates[256] =432 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };433 WORD ach;434 unsigned i;435 436 Assert( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN437 || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP);438 if ( ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */)439 || RT_HIWORD(pMsg->lParam) & KF_EXTENDED)440 return false;441 if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))442 return false;443 if ( (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)444 && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))445 return false;446 if ( (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)447 && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))448 return false;449 if ( ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)450 || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))451 return false;452 /* If we got this far then we have a key event which could potentially453 * be a synthetic left control. Now we check to see whether the current454 * keyboard layout actually has an AltGr key by checking whether any of455 * the keys which might do produce a symbol when AltGr (Control + Alt) is456 * depressed. Generally this loop will exit pretty early (it exits on the457 * first iteration for my German layout). If there is no AltGr key in the458 * layout then it will run right through, but that should not happen very459 * often as we should hardly ever reach the loop in that case.460 *461 * In theory we could do this once and cache the result, but that involves462 * tracking layout switches to invalidate the cache, and I don't think463 * that the added complexity is worth the price.464 */465 for (i = '0'; i <= VK_OEM_102; ++i)466 {467 if (ToAscii(i, 0, auKeyStates, &ach, 0))468 break;469 /* Skip ranges of virtual keys which are undefined or not relevant. */470 if (i == '9')471 i = 'A' - 1;472 if (i == 'Z')473 i = VK_OEM_1 - 1;474 if (i == VK_OEM_3)475 i = VK_OEM_4 - 1;476 if (i == VK_OEM_8)477 i = VK_OEM_102 - 1;478 }479 if (i > VK_OEM_102)480 return false;481 return true;482 }483 484 418 bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId) 485 419 { … … 505 439 pMsg->lParam &= ~(0x1 << 25); 506 440 fResult = false; 507 break;508 }509 510 if (isSyntheticLCtrl(pMsg))511 {512 fResult = true;513 441 break; 514 442 } … … 529 457 if (!(pMsg->lParam & 0x80000000)) 530 458 flags |= KeyPressed; 459 460 /* If present - why not just assert this? */ 461 if (m_pAltGrMonitor) 462 { 463 /* Bail out if we are sure that this is a fake left control. */ 464 if (m_pAltGrMonitor->isCurrentEventDefinitelyFake(scan, flags & KeyPressed, flags & KeyExtended)) 465 { 466 fResult = true; 467 break; 468 } 469 /* Update AltGR monitor state from key-event: */ 470 m_pAltGrMonitor->updateStateFromKeyEvent(scan, flags & KeyPressed, flags & KeyExtended); 471 /* And release left Ctrl key early (if required): */ 472 if (m_pAltGrMonitor->isLeftControlReleaseNeeded()) 473 keyboard().PutScancode(0x1D | 0x80); 474 } 531 475 532 476 /* Check for special Korean keys. Based on the keyboard layout selected … … 819 763 , m_iKeyboardHookViewIndex(-1) 820 764 , m_fSkipKeyboardEvents(false) 765 , m_pAltGrMonitor(0) 821 766 #elif defined(Q_WS_MAC) 822 767 , m_darwinKeyModifiers(0) 823 768 , m_fKeyboardGrabbed(false) 824 769 , m_iKeyboardGrabViewIndex(-1) 825 #endif 770 #endif /* Q_WS_MAC */ 826 771 , m_cMonitors(1) 827 772 { … … 845 790 void UIKeyboardHandler::prepareCommon() 846 791 { 792 #ifdef Q_WS_WIN 793 /* Prepare AltGR monitor: */ 794 m_pAltGrMonitor = new WinAltGrMonitor; 795 #endif /* Q_WS_WIN */ 796 847 797 /* Machine state-change updater: */ 848 798 connect(uisession(), SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged())); … … 872 822 { 873 823 #if defined(Q_WS_WIN) 824 /* Cleanup AltGR monitor: */ 825 delete m_pAltGrMonitor; 826 m_pAltGrMonitor = 0; 827 874 828 /* Cleaning keyboard-hook: */ 875 829 if (m_keyboardHook) … … 883 837 if (m_fKeyboardGrabbed) 884 838 darwinGrabKeyboardEvents(false); 885 #endif 839 #endif /* Q_WS_MAC */ 886 840 } 887 841 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
r53138 r53221 41 41 class UIMachineView; 42 42 class VBoxGlobalSettings; 43 #ifdef Q_WS_X11 43 #if defined(Q_WS_WIN) 44 class WinAltGrMonitor; 45 #elif defined(Q_WS_X11) 44 46 typedef union _XEvent XEvent; 45 47 #endif /* Q_WS_X11 */ … … 93 95 bool winEventFilter(MSG *pMsg, ulong uScreenId); 94 96 void winSkipKeyboardEvents(bool fSkip); 97 /** Holds the object monitoring key event stream for problematic AltGr events. */ 98 WinAltGrMonitor *m_pAltGrMonitor; 95 99 #elif defined(Q_WS_X11) 96 100 bool x11EventFilter(XEvent *pEvent, ulong uScreenId); … … 198 202 bool m_fKeyboardGrabbed; 199 203 int m_iKeyboardGrabViewIndex; 200 #endif 204 #endif /* Q_WS_MAC */ 201 205 202 206 ULONG m_cMonitors; -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp
r52730 r53221 42 42 # undef HIBYTE 43 43 # include <windows.h> 44 # include "WinKeyboard.h" 44 45 #endif /* Q_WS_WIN */ 45 46 … … 391 392 : m_pReleaseTimer(0) 392 393 , m_fStartNewSequence(true) 394 #ifdef Q_WS_WIN 395 , m_pAltGrMonitor(0) 396 #endif /* Q_WS_WIN */ 393 397 { 394 398 /* Configure widget: */ … … 403 407 connect(m_pReleaseTimer, SIGNAL(timeout()), this, SLOT(sltReleasePendingKeys())); 404 408 405 #ifdef Q_WS_X11 406 /* Initialize the X keyboard subsystem: */ 407 initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes")); 408 #endif /* Q_WS_X11 */ 409 410 #ifdef Q_WS_MAC 411 m_uDarwinKeyModifiers = 0; 412 UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this); 413 ::DarwinGrabKeyboard(false /* just modifiers */); 414 #endif /* Q_WS_MAC */ 409 #if defined(Q_WS_X11) 410 /* Initialize the X keyboard subsystem: */ 411 initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes")); 412 #elif defined(Q_WS_MAC) 413 m_uDarwinKeyModifiers = 0; 414 UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this); 415 ::DarwinGrabKeyboard(false /* just modifiers */); 416 #elif defined(Q_WS_WIN) 417 /* Prepare AltGR monitor: */ 418 m_pAltGrMonitor = new WinAltGrMonitor; 419 #endif /* Q_WS_WIN */ 415 420 } 416 421 417 422 UIHostComboEditorPrivate::~UIHostComboEditorPrivate() 418 423 { 419 #ifdef Q_WS_MAC 424 #if defined(Q_WS_WIN) 425 /* Cleanup AltGR monitor: */ 426 delete m_pAltGrMonitor; 427 m_pAltGrMonitor = 0; 428 #elif defined(Q_WS_MAC) 420 429 ::DarwinReleaseKeyboard(); 421 430 UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this); … … 465 474 466 475 #ifdef Q_WS_WIN 467 /**468 * @brief isSyntheticLCtrl469 * @param pMsg Windows WM_[SYS]KEY* event message structure470 * @return true if this is a synthetic LCtrl event, false otherwise471 * This function is a heuristic to tell whether a key event is the first in472 * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr. Our473 * heuristic is in two parts. First of all, we check whether there is a pending474 * RAlt key event matching this LCtrl event (i.e. both key up or both key down)475 * and if there is, we check whether the current layout has an AltGr key. We476 * check this by looking to see if any of the layout-dependent keys has a symbol477 * associated when AltGr is pressed.478 */479 static bool isSyntheticLCtrl(MSG *pMsg)480 {481 MSG peekMsg;482 /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */483 const BYTE auKeyStates[256] =484 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };485 WORD ach;486 unsigned i;487 488 Assert( pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN489 || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP);490 if ( ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */)491 || RT_HIWORD(pMsg->lParam) & KF_EXTENDED)492 return false;493 if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))494 return false;495 if ( (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)496 && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))497 return false;498 if ( (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)499 && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))500 return false;501 if ( ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)502 || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))503 return false;504 /* If we got this far then we have a key event which could potentially505 * be a synthetic left control. Now we check to see whether the current506 * keyboard layout actually has an AltGr key by checking whether any of507 * the keys which might do produce a symbol when AltGr (Control + Alt) is508 * depressed. Generally this loop will exit pretty early (it exits on the509 * first iteration for my German layout). If there is no AltGr key in the510 * layout then it will run right through, but that should not happen very511 * often as we should hardly ever reach the loop in that case.512 *513 * In theory we could do this once and cache the result, but that involves514 * tracking layout switches to invalidate the cache, and I don't think515 * that the added complexity is worth the price.516 */517 for (i = '0'; i <= VK_OEM_102; ++i)518 {519 if (ToAscii(i, 0, auKeyStates, &ach, 0))520 break;521 /* Skip ranges of virtual keys which are undefined or not relevant. */522 if (i == '9')523 i = 'A' - 1;524 if (i == 'Z')525 i = VK_OEM_1 - 1;526 if (i == VK_OEM_3)527 i = VK_OEM_4 - 1;528 if (i == VK_OEM_8)529 i = VK_OEM_102 - 1;530 }531 if (i > VK_OEM_102)532 return false;533 return true;534 }535 536 476 bool UIHostComboEditorPrivate::winEvent(MSG *pMsg, long* /* pResult */) 537 477 { … … 545 485 /* Get key-code: */ 546 486 int iKeyCode = UINativeHotKey::distinguishModifierVKey((int)pMsg->wParam, (int)pMsg->lParam); 547 548 /* If this is the first event in a synthetic AltGr = LCtrl+RAlt 549 * sequence then swallow it. */ 550 if (isSyntheticLCtrl(pMsg)) 551 return true; 487 unsigned iDownScanCode = (pMsg->lParam >> 16) & 0x7F; 488 bool fPressed = !(pMsg->lParam & 0x80000000); 489 bool fExtended = pMsg->lParam & 0x1000000; 490 491 /* If present - why not just assert this? */ 492 if (m_pAltGrMonitor) 493 { 494 /* Update AltGR monitor state from key-event: */ 495 m_pAltGrMonitor->updateStateFromKeyEvent(iDownScanCode, fPressed, fExtended); 496 /* And release left Ctrl key early (if required): */ 497 if (m_pAltGrMonitor->isLeftControlReleaseNeeded()) 498 { 499 m_pressedKeys.remove(VK_LCONTROL); 500 m_shownKeys.remove(VK_LCONTROL); 501 } 502 /* Fake LCtrl release events can also end up in the released 503 * key set. Detect them on the immediately following RAlt up. */ 504 if (!m_pressedKeys.contains(VK_LCONTROL)) 505 m_releasedKeys.remove(VK_LCONTROL); 506 } 552 507 553 508 /* Process the key event: */ -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h
r52727 r53221 30 30 class UIHostComboEditorPrivate; 31 31 class QIToolButton; 32 #ifdef Q_WS_WIN 33 class WinAltGrMonitor; 34 #endif /* Q_WS_WIN */ 32 35 33 36 /* Native hot-key namespace to unify … … 171 174 bool m_fStartNewSequence; 172 175 173 #ifdef Q_WS_MAC 174 /* The current modifier key mask. Used to figure out which modifier 175 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 176 uint32_t m_uDarwinKeyModifiers; 177 #endif /* Q_WS_MAC */ 176 #if defined(Q_WS_MAC) 177 /* The current modifier key mask. Used to figure out which modifier 178 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 179 uint32_t m_uDarwinKeyModifiers; 180 #elif defined(Q_WS_WIN) 181 /** Holds the object monitoring key event stream for problematic AltGr events. */ 182 WinAltGrMonitor *m_pAltGrMonitor; 183 #endif /* Q_WS_WIN */ 178 184 }; 179 185
Note:
See TracChangeset
for help on using the changeset viewer.