- Timestamp:
- Jan 27, 2011 10:49:44 AM (14 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 11 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r35686 r35730 276 276 src/extensions/QIDialog.h \ 277 277 src/extensions/QIFileDialog.h \ 278 src/extensions/QIHotKeyEdit.h \279 278 src/extensions/QIHttp.h \ 280 279 src/extensions/QILabel.h \ … … 328 327 src/widgets/UIDownloaderAdditions.h \ 329 328 src/widgets/UIDownloaderUserManual.h \ 329 src/widgets/UIHotKeyEditor.h \ 330 330 src/widgets/UIPopupBox.h \ 331 331 src/widgets/UIProgressDialog.h \ … … 443 443 src/extensions/QIDialogButtonBox.cpp \ 444 444 src/extensions/QIFileDialog.cpp \ 445 src/extensions/QIHotKeyEdit.cpp \446 445 src/extensions/QILabel.cpp \ 447 446 src/extensions/QILabelSeparator.cpp \ … … 493 492 src/widgets/UIDownloaderAdditions.cpp \ 494 493 src/widgets/UIDownloaderUserManual.cpp \ 494 src/widgets/UIHotKeyEditor.cpp \ 495 495 src/widgets/UIPopupBox.cpp \ 496 496 src/widgets/UIProgressDialog.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.cpp
r33540 r35730 7 7 8 8 /* 9 * Copyright (C) 2006-20 07Oracle Corporation9 * Copyright (C) 2006-2011 Oracle Corporation 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 27 27 28 28 #include "VBoxGlobalSettings.h" 29 #include " QIHotKeyEdit.h"29 #include "UIHotKeyEditor.h" 30 30 #include "COMDefs.h" 31 31 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ … … 40 40 { 41 41 /* default settings */ 42 #if defined (Q_WS_WIN32) 43 hostkey = 0xA3; // VK_RCONTROL 44 // hostkey = 165; // VK_RMENU 45 #elif defined (Q_WS_PM) 46 hostkey = VK_CTRL; 42 #if defined (Q_WS_WIN) 43 hostCombo = "163"; // VK_RCONTROL 47 44 #elif defined (Q_WS_X11) 48 hostkey = 0xffe4; // XK_Control_R 49 // hostkey = 65514; // XK_Alt_R 45 hostCombo = "65508"; // XK_Control_R 50 46 #elif defined (Q_WS_MAC) 51 // hostkey = 0x36; // QZ_RMETA 52 hostkey = 0x37; // QZ_LMETA 53 // hostkey = 0x3e; // QZ_RCTRL 54 // hostkey = 0x3d; // QZ_RALT 47 hostCombo = "55"; // QZ_LMETA 55 48 #else 56 49 # warning "port me!" 57 hostkey = 0;58 50 #endif 59 51 autoCapture = true; … … 69 61 VBoxGlobalSettingsData::VBoxGlobalSettingsData (const VBoxGlobalSettingsData &that) 70 62 { 71 host key = that.hostkey;63 hostCombo = that.hostCombo; 72 64 autoCapture = that.autoCapture; 73 65 guiFeatures = that.guiFeatures; … … 87 79 { 88 80 return this == &that || 89 (host key == that.hostkey&&81 (hostCombo == that.hostCombo && 90 82 autoCapture == that.autoCapture && 91 83 guiFeatures == that.guiFeatures && … … 117 109 gPropertyMap[] = 118 110 { 119 { "GUI/Input/Host Key", "hostKey", "0|\\d*[1-9]\\d*", true },111 { "GUI/Input/HostCombo", "hostCombo", "0|\\d*[1-9]\\d*(,\\d*[1-9]\\d*)?(,\\d*[1-9]\\d*)?", true }, 120 112 { "GUI/Input/AutoCapture", "autoCapture", "true|false", true }, 121 113 { "GUI/Customizations", "guiFeatures", "\\S+", true }, … … 127 119 { VBoxDefs::GUI_PresentationModeEnabled, "presentationModeEnabled", "true|false", true }, 128 120 #endif /* Q_WS_MAC */ 129 { "GUI/HostScreenSaverDisabled", "hostScreenSaverDisabled", 121 { "GUI/HostScreenSaverDisabled", "hostScreenSaverDisabled", "true|false", true } 130 122 }; 131 123 132 void VBoxGlobalSettings::setHostKey (int key) 133 { 134 if (!QIHotKeyEdit::isValidKey (key)) 135 { 136 last_err = tr ("'%1 (0x%2)' is an invalid host key code.") 137 .arg (key).arg (key, 0, 16); 124 void VBoxGlobalSettings::setHostCombo (const QString &hostCombo) 125 { 126 if (!UIHotKeyCombination::isValidKeyCombo (hostCombo)) 127 { 128 last_err = tr ("'%1' is an invalid host-combination code-sequence.").arg (hostCombo); 138 129 return; 139 130 } 140 141 mData()->hostkey = key; 131 mData()->hostCombo = hostCombo; 142 132 resetError(); 143 133 } -
trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobalSettings.h
r32479 r35730 6 6 7 7 /* 8 * Copyright (C) 2006-20 07Oracle Corporation8 * Copyright (C) 2006-2011 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 38 38 private: 39 39 40 int hostkey;40 QString hostCombo; 41 41 bool autoCapture; 42 42 QString guiFeatures; … … 56 56 { 57 57 Q_OBJECT 58 Q_PROPERTY ( int hostKey READ hostKey WRITE setHostKey)58 Q_PROPERTY (QString hostCombo READ hostCombo WRITE setHostCombo) 59 59 Q_PROPERTY (bool autoCapture READ autoCapture WRITE setAutoCapture) 60 60 Q_PROPERTY (QString guiFeatures READ guiFeatures WRITE setGuiFeatures) … … 79 79 // Properties 80 80 81 int hostKey() const { return data()->hostkey; }82 void setHost Key (int key);81 QString hostCombo() const { return data()->hostCombo; } 82 void setHostCombo (const QString &hostCombo); 83 83 84 84 bool autoCapture() const { return data()->autoCapture; } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxGlobal.cpp
r35722 r35730 25 25 #include "VBoxSelectorWnd.h" 26 26 #include "VBoxProblemReporter.h" 27 #include "QIHotKeyEdit.h"28 27 #include "QIMessageBox.h" 29 28 #include "QIDialogButtonBox.h" … … 73 72 74 73 #ifdef Q_WS_X11 74 # include "UIHotKeyEditor.h" 75 75 # ifndef VBOX_OSE 76 76 # include "VBoxLicenseViewer.h" … … 3016 3016 it->refresh(); 3017 3017 3018 #if defined (Q_WS_PM) || defined (Q_WS_X11) 3019 /* As PM and X11 do not (to my knowledge) have functionality for providing 3020 * human readable key names, we keep a table of them, which must be 3021 * updated when the language is changed. */ 3022 QIHotKeyEdit::retranslateUi(); 3023 #endif 3018 #ifdef Q_WS_X11 3019 /* As X11 do not have functionality for providing human readable key names, 3020 * we keep a table of them, which must be updated when the language is changed. */ 3021 UIHotKey::retranslateKeyNames(); 3022 #endif /* Q_WS_X11 */ 3024 3023 } 3025 3024 -
trunk/src/VBox/Frontends/VirtualBox/src/globals/VBoxProblemReporter.cpp
r35587 r35730 39 39 #include "UIMachine.h" 40 40 #include "VBoxAboutDlg.h" 41 #include " QIHotKeyEdit.h"41 #include "UIHotKeyEditor.h" 42 42 #ifdef Q_WS_MAC 43 43 # include "VBoxUtils-darwin.h" … … 1677 1677 tr ("<p>The host key is currently defined as <b>%1</b>.</p>", 1678 1678 "additional message box paragraph") 1679 .arg ( QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())),1679 .arg (UIHotKeyCombination::toReadableString (vboxGlobal().settings().hostCombo())), 1680 1680 "confirmInputCapture", 1681 1681 QIMessageBox::Ok | QIMessageBox::Default, … … 1710 1710 tr ("<p>The host key is currently defined as <b>%1</b>.</p>", 1711 1711 "additional message box paragraph") 1712 .arg ( QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())),1712 .arg (UIHotKeyCombination::toReadableString (vboxGlobal().settings().hostCombo())), 1713 1713 "remindAboutAutoCapture"); 1714 1714 } … … 1878 1878 "You can access it by pressing <b>Host+Home</b>.</p>") 1879 1879 .arg (aHotKey) 1880 .arg ( QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())),1880 .arg (UIHotKeyCombination::toReadableString (vboxGlobal().settings().hostCombo())), 1881 1881 "confirmGoingFullscreen", 1882 1882 tr ("Switch", "fullscreen")); … … 1898 1898 "You can access it by pressing <b>Host+Home</b>.</p>") 1899 1899 .arg (aHotKey) 1900 .arg ( QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())),1900 .arg (UIHotKeyCombination::toReadableString (vboxGlobal().settings().hostCombo())), 1901 1901 "confirmGoingSeamless", 1902 1902 tr ("Switch", "seamless")); … … 1918 1918 "You can access it by pressing <b>Host+Home</b>.</p>") 1919 1919 .arg (aHotKey) 1920 .arg ( QIHotKeyEdit::keyName (vboxGlobal().settings().hostKey())),1920 .arg (UIHotKeyCombination::toReadableString (vboxGlobal().settings().hostCombo())), 1921 1921 "confirmGoingScale", 1922 1922 tr ("Switch", "scale")); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
r35686 r35730 34 34 #include "UIMachineWindow.h" 35 35 #include "UIMachineView.h" 36 #include "UIHotKeyEditor.h" 36 37 37 38 #ifdef Q_WS_X11 … … 64 65 65 66 #ifdef Q_WS_WIN 66 UIKeyboardHandler* UIKeyboardHandler::m_ pKeyboardHandler = 0;67 UIKeyboardHandler* UIKeyboardHandler::m_spKeyboardHandler = 0; 67 68 #endif /* Q_WS_WIN */ 68 69 … … 94 95 /* Its required to have static pointer to created handler 95 96 * because windows keyboard-hook works only with static members: */ 96 m_ pKeyboardHandler = pKeyboardHandler;97 m_spKeyboardHandler = pKeyboardHandler; 97 98 #endif /* Q_WS_WIN */ 98 99 /* Return prepared keyboard-handler: */ … … 105 106 /* Delete keyboard-handler: */ 106 107 #ifdef Q_WS_WIN 107 m_ pKeyboardHandler = 0;108 m_spKeyboardHandler = 0; 108 109 #endif /* Q_WS_WIN */ 109 110 delete pKeyboardHandler; … … 307 308 308 309 if (aReleaseHostKey) 309 m_bIsHost keyPressed = false;310 m_bIsHostComboPressed = false; 310 311 311 312 #ifdef Q_WS_MAC 312 /* Clear most of the modifiers: */ 313 m_darwinKeyModifiers &= 314 alphaLock | kEventKeyModifierNumLockMask | 315 (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask(m_globalSettings.hostKey())); 313 // TODO: To NaN: Please fix: 314 // /* Clear most of the modifiers: */ 315 // m_darwinKeyModifiers &= 316 // alphaLock | kEventKeyModifierNumLockMask | 317 // (aReleaseHostKey ? 0 : ::DarwinKeyCodeToDarwinModifierMask(m_globalSettings.hostKey())); 316 318 #endif 317 319 … … 323 325 { 324 326 return (m_fIsKeyboardCaptured ? UIViewStateType_KeyboardCaptured : 0) | 325 (m_bIsHost keyPressed ? UIViewStateType_HostKeyPressed : 0);327 (m_bIsHostComboPressed ? UIViewStateType_HostKeyPressed : 0); 326 328 } 327 329 … … 368 370 * on the host, the scancode in lParam might be 0x71/0x72 or 0xF1/0xF2. 369 371 * In either case, we must deliver 0xF1/0xF2 scancode to the guest when 370 * the key is pressed and nothing when it's released. 371 */ 372 * the key is pressed and nothing when it's released. */ 372 373 if (scan == 0x71 || scan == 0x72) 373 374 { … … 393 394 case VK_MENU: 394 395 { 395 /* Overcome stupidWin32 modifier key generalization: */396 /* Overcome Win32 modifier key generalization: */ 396 397 int keyscan = scan; 397 398 if (flags & KeyExtended) … … 631 632 , m_globalSettings(vboxGlobal().settings()) 632 633 , m_fIsKeyboardCaptured(false) 633 , m_bIsHostkeyPressed(false) 634 , m_bIsHostkeyAlone (false) 635 , m_bIsHostkeyInCapture(false) 634 , m_bIsHostComboPressed(false) 635 , m_bIsHostComboAlone (false) 636 636 , m_fPassCAD(false) 637 637 #if defined(Q_WS_WIN) 638 , m_bIsHostkeyInCapture(false) 638 639 , m_iKeyboardHookViewIndex(-1) 639 640 #elif defined(Q_WS_MAC) … … 846 847 QKeyEvent *pKeyEvent = static_cast<QKeyEvent*>(pEvent); 847 848 848 if (m_bIsHost keyPressed && pEvent->type() == QEvent::KeyPress)849 if (m_bIsHostComboPressed && pEvent->type() == QEvent::KeyPress) 849 850 { 850 851 /* Passing F1-F12 keys to the guest: */ … … 873 874 machineLogic()->actionsPool()->processHotKey(QKeySequence(pKeyEvent->key())); 874 875 } 875 else if (!m_bIsHost keyPressed && pEvent->type() == QEvent::KeyRelease)876 else if (!m_bIsHostComboPressed && pEvent->type() == QEvent::KeyRelease) 876 877 { 877 878 /* Show a possible warning on key release which seems to be more expected by the end user: */ … … 899 900 LRESULT CALLBACK UIKeyboardHandler::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 900 901 { 901 if (nCode == HC_ACTION && m_ pKeyboardHandler && m_pKeyboardHandler->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT*)lParam))902 if (nCode == HC_ACTION && m_spKeyboardHandler && m_spKeyboardHandler->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT*)lParam)) 902 903 return 1; 903 904 … … 909 910 /* Check what related machine-view was NOT unregistered yet: */ 910 911 if (!m_views.contains(m_iKeyboardHookViewIndex)) 912 return false; 913 914 if (!m_fIsKeyboardCaptured) 911 915 return false; 912 916 … … 929 933 } 930 934 931 if (!m_fIsKeyboardCaptured)932 return false;933 934 935 /* It's possible that a key has been pressed while the keyboard was not 935 936 * captured, but is being released under the capture. Detect this situation … … 938 939 uint8_t what_pressed = (event.flags & 0x01) && (event.vkCode != VK_RSHIFT) ? IsExtKeyPressed : IsKeyPressed; 939 940 if ((event.flags & 0x80) /* released */ && 940 (( event.vkCode == m_globalSettings.hostKey() && !m_bIsHostkeyInCapture) ||941 ((UIHotKeyCombination::toKeyCodeList(m_globalSettings.hostCombo()).contains(event.vkCode) && !m_bIsHostkeyInCapture) || 941 942 (m_pressedKeys[event.scanCode] & (IsKbdCaptured | what_pressed)) == what_pressed)) 942 943 return false; … … 1102 1103 #endif 1103 1104 1104 bool UIKeyboardHandler::keyEvent(int iKey, uint8_t uScan, int fFlags, ulong uScreenId, wchar_t *pUniKey /* = NULL */) 1105 { 1106 const bool isHostKey = iKey == m_globalSettings.hostKey(); 1107 1108 LONG buf[16]; 1109 LONG *codes = buf; 1110 uint count = 0; 1111 uint8_t whatPressed = 0; 1112 1113 if (!isHostKey && !m_bIsHostkeyPressed) 1114 { 1115 if (fFlags & KeyPrint) 1116 { 1117 static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 }; 1118 static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA }; 1119 if (fFlags & KeyPressed) 1120 { 1121 codes = PrintMake; 1122 count = SIZEOF_ARRAY(PrintMake); 1123 } 1124 else 1125 { 1126 codes = PrintBreak; 1127 count = SIZEOF_ARRAY(PrintBreak); 1128 } 1129 } 1130 else if (fFlags & KeyPause) 1131 { 1132 if (fFlags & KeyPressed) 1133 { 1134 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 }; 1135 codes = Pause; 1136 count = SIZEOF_ARRAY(Pause); 1137 } 1138 else 1139 { 1140 /* Pause shall not produce a break code */ 1105 bool UIKeyboardHandler::keyEvent(int iKey, uint8_t uScan, int fFlags, ulong uScreenId, wchar_t *pUniKey /* = 0 */) 1106 { 1107 /* Get host-combo key list: */ 1108 QSet<int> allHostComboKeys = UIHotKeyCombination::toKeyCodeList(m_globalSettings.hostCombo()).toSet(); 1109 1110 /* Update the map of pressed host-combo keys: */ 1111 if (fFlags & KeyPressed) 1112 { 1113 if (allHostComboKeys.contains(iKey)) 1114 { 1115 if (!m_pressedHostComboKeys.contains(iKey)) 1116 m_pressedHostComboKeys.insert(iKey, uScan); 1117 else if (m_bIsHostComboPressed) 1141 1118 return true; 1142 }1143 }1144 else1145 {1146 if (fFlags & KeyPressed)1147 {1148 /* Check if the guest has the same view on the modifier keys (NumLock,1149 * CapsLock, ScrollLock) as the X server. If not, send KeyPress events1150 * to synchronize the state. */1151 fixModifierState(codes, &count);1152 }1153 1154 /* Check if it's C-A-D and GUI/PassCAD is not true */1155 if (!m_fPassCAD &&1156 uScan == 0x53 /* Del */ &&1157 ((m_pressedKeys[0x38] & IsKeyPressed) /* Alt */ ||1158 (m_pressedKeys[0x38] & IsExtKeyPressed)) &&1159 ((m_pressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ ||1160 (m_pressedKeys[0x1d] & IsExtKeyPressed)))1161 {1162 /* Use the C-A-D combination as a last resort to get the1163 * keyboard and mouse back to the host when the user forgets1164 * the Host Key. Note that it's always possible to send C-A-D1165 * to the guest using the Host+Del combination. BTW, it would1166 * be preferable to completely ignore C-A-D in guests, but1167 * that's not possible because we cannot predict what other1168 * keys will be pressed next when one of C, A, D is held. */1169 if (uisession()->isRunning() && m_fIsKeyboardCaptured)1170 {1171 releaseKeyboard();1172 if (!uisession()->isMouseSupportsAbsolute() || !uisession()->isMouseIntegrated())1173 machineLogic()->mouseHandler()->releaseMouse();1174 }1175 return true;1176 }1177 1178 /* Process the scancode and update the table of pressed keys: */1179 whatPressed = IsKeyPressed;1180 1181 if (fFlags & KeyExtended)1182 {1183 codes[count++] = 0xE0;1184 whatPressed = IsExtKeyPressed;1185 }1186 1187 if (fFlags & KeyPressed)1188 {1189 codes[count++] = uScan;1190 m_pressedKeys[uScan] |= whatPressed;1191 }1192 else1193 {1194 /* If we haven't got this key's press message, we ignore its release: */1195 if (!(m_pressedKeys[uScan] & whatPressed))1196 return true;1197 codes[count++] = uScan | 0x80;1198 m_pressedKeys[uScan] &= ~whatPressed;1199 }1200 1201 if (m_fIsKeyboardCaptured)1202 m_pressedKeys[uScan] |= IsKbdCaptured;1203 else1204 m_pressedKeys[uScan] &= ~IsKbdCaptured;1205 1119 } 1206 1120 } 1207 1121 else 1122 { 1123 if (allHostComboKeys.contains(iKey) && m_pressedHostComboKeys.contains(iKey)) 1124 m_pressedHostComboKeys.remove(iKey); 1125 } 1126 /* Check if we are currently holding FULL host-combo: */ 1127 bool fIsFullHostComboPresent = allHostComboKeys == m_pressedHostComboKeys.keys().toSet(); 1128 /* Check if currently pressed/released key had changed host-combo state: */ 1129 const bool isHostComboStateChanged = (!m_bIsHostComboPressed && fIsFullHostComboPresent) || 1130 (m_bIsHostComboPressed && !fIsFullHostComboPresent); 1131 1132 #ifdef Q_WS_WIN 1133 if (m_bIsHostComboPressed || isHostComboStateChanged) 1208 1134 { 1209 1135 /* Currently this is used in winLowKeyboardEvent() only: */ 1210 1136 m_bIsHostkeyInCapture = m_fIsKeyboardCaptured; 1211 1137 } 1212 1213 bool emitSignal = false; 1214 int hotkey = 0; 1215 1216 /* Process the host key: */ 1138 #endif /* Q_WS_WIN */ 1139 1140 /* Check if it's C-A-D and GUI/PassCAD is not true: */ 1141 if (!m_fPassCAD && 1142 uScan == 0x53 /* Del */ && 1143 ((m_pressedKeys[0x38] & IsKeyPressed) /* Alt */ || 1144 (m_pressedKeys[0x38] & IsExtKeyPressed)) && 1145 ((m_pressedKeys[0x1d] & IsKeyPressed) /* Ctrl */ || 1146 (m_pressedKeys[0x1d] & IsExtKeyPressed))) 1147 { 1148 /* Use the C-A-D combination as a last resort to get the keyboard and mouse back 1149 * to the host when the user forgets the Host Key. Note that it's always possible 1150 * to send C-A-D to the guest using the Host+Del combination: */ 1151 if (uisession()->isRunning() && m_fIsKeyboardCaptured) 1152 { 1153 releaseKeyboard(); 1154 if (!uisession()->isMouseSupportsAbsolute() || !uisession()->isMouseIntegrated()) 1155 machineLogic()->mouseHandler()->releaseMouse(); 1156 } 1157 return true; 1158 } 1159 1160 /* Prepare empty code-buffer: */ 1161 LONG aCodesBuffer[16]; 1162 LONG *pCodes = aCodesBuffer; 1163 uint uCodesCount = 0; 1164 /* Processing usual key-presses/releases without host-key being held: */ 1165 if (!m_bIsHostComboPressed || isHostComboStateChanged) 1166 { 1167 /* Special flags handling (KeyPrint): */ 1168 if (fFlags & KeyPrint) 1169 { 1170 if (fFlags & KeyPressed) 1171 { 1172 static LONG PrintMake[] = { 0xE0, 0x2A, 0xE0, 0x37 }; 1173 pCodes = PrintMake; 1174 uCodesCount = SIZEOF_ARRAY(PrintMake); 1175 } 1176 else 1177 { 1178 static LONG PrintBreak[] = { 0xE0, 0xB7, 0xE0, 0xAA }; 1179 pCodes = PrintBreak; 1180 uCodesCount = SIZEOF_ARRAY(PrintBreak); 1181 } 1182 } 1183 /* Special flags handling (KeyPause): */ 1184 else if (fFlags & KeyPause) 1185 { 1186 if (fFlags & KeyPressed) 1187 { 1188 static LONG Pause[] = { 0xE1, 0x1D, 0x45, 0xE1, 0x9D, 0xC5 }; 1189 pCodes = Pause; 1190 uCodesCount = SIZEOF_ARRAY(Pause); 1191 } 1192 else 1193 { 1194 /* Pause shall not produce a break code: */ 1195 return true; 1196 } 1197 } 1198 /* Common flags handling: */ 1199 else 1200 { 1201 /* Get the type of key - simple or extended: */ 1202 uint8_t uWhatPressed = fFlags & KeyExtended ? IsExtKeyPressed : IsKeyPressed; 1203 1204 /* If some key was pressed or some previously pressed key was released => 1205 * we are updating the list of pressed keys and preparing scancodes: */ 1206 if ((fFlags & KeyPressed) || (m_pressedKeys[uScan] & uWhatPressed)) 1207 { 1208 /* Check if the guest has the same view on the modifier keys 1209 * (NumLock, CapsLock, ScrollLock) as the X server. 1210 * If not, send KeyPress events to synchronize the state: */ 1211 if (fFlags & KeyPressed) 1212 fixModifierState(pCodes, &uCodesCount); 1213 1214 /* Prepend 'extended' scancode if needed: */ 1215 if (fFlags & KeyExtended) 1216 pCodes[uCodesCount++] = 0xE0; 1217 1218 /* Process key-press: */ 1219 if (fFlags & KeyPressed) 1220 { 1221 /* Append scancode: */ 1222 pCodes[uCodesCount++] = uScan; 1223 m_pressedKeys[uScan] |= uWhatPressed; 1224 } 1225 /* Process key-release if that key was pressed before: */ 1226 else if (m_pressedKeys[uScan] & uWhatPressed) 1227 { 1228 /* Append scancode: */ 1229 pCodes[uCodesCount++] = uScan | 0x80; 1230 m_pressedKeys[uScan] &= ~uWhatPressed; 1231 } 1232 1233 /* Update keyboard-captured flag: */ 1234 if (m_fIsKeyboardCaptured) 1235 m_pressedKeys[uScan] |= IsKbdCaptured; 1236 else 1237 m_pressedKeys[uScan] &= ~IsKbdCaptured; 1238 } 1239 /* Ignore key-release if that key was NOT pressed before, 1240 * but only if thats not one of the host-combination keys: */ 1241 else if (!allHostComboKeys.contains(iKey)) 1242 return true; 1243 } 1244 } 1245 1246 /* Process the host-combo funtionality: */ 1217 1247 if (fFlags & KeyPressed) 1218 1248 { 1219 if (isHostKey) 1220 { 1221 if (!m_bIsHostkeyPressed) 1222 { 1223 m_bIsHostkeyPressed = m_bIsHostkeyAlone = true; 1249 if (isHostComboStateChanged) 1250 { 1251 if (!m_bIsHostComboPressed) 1252 { 1253 m_bIsHostComboPressed = true; 1254 m_bIsHostComboAlone = true; 1224 1255 if (uisession()->isRunning()) 1225 1256 saveKeyStates(); 1226 emitSignal = true;1227 1257 } 1228 1258 } 1229 1259 else 1230 1260 { 1231 if (m_bIsHostkeyPressed) 1232 { 1233 if (m_bIsHostkeyAlone) 1234 { 1235 hotkey = iKey; 1236 m_bIsHostkeyAlone = false; 1261 if (m_bIsHostComboPressed) 1262 { 1263 if (m_bIsHostComboAlone) 1264 { 1265 m_bIsHostComboAlone = false; 1266 m_pressedHostComboKeys.clear(); 1267 /* Process Host+<key> shortcuts. 1268 * Currently, <key> is limited to alphanumeric chars. 1269 * Other Host+<key> combinations are handled in Qt event(): */ 1270 return processHotKey(iKey, pUniKey); 1237 1271 } 1238 1272 } … … 1241 1275 else 1242 1276 { 1243 if (isHostKey) 1244 { 1245 if (m_bIsHostkeyPressed) 1246 { 1247 m_bIsHostkeyPressed = false; 1248 1249 if (m_bIsHostkeyAlone) 1250 { 1251 if (uisession()->isPaused()) 1252 { 1253 vboxProblem().remindAboutPausedVMInput(); 1254 } 1255 else if (uisession()->isRunning()) 1277 if (isHostComboStateChanged) 1278 { 1279 if (m_bIsHostComboPressed) 1280 { 1281 m_bIsHostComboPressed = false; 1282 if (m_bIsHostComboAlone) 1283 { 1284 /* Capturing/releasing keyboard/mouse: */ 1285 if (uisession()->isRunning()) 1256 1286 { 1257 1287 bool ok = true; 1258 1288 if (!m_fIsKeyboardCaptured) 1259 1289 { 1260 /* Temporarily disable auto capture that will take 1261 * place after this dialog is dismissed because 1262 * the capture state is to be defined by the 1263 * dialog result itself */ 1290 /* Temporarily disable auto-capture that will take place after 1291 * this dialog is dismissed because the capture state is to be 1292 * defined by the dialog result itself: */ 1264 1293 uisession()->setAutoCaptureDisabled(true); 1265 bool autoConfirmed = false;1266 ok = vboxProblem().confirmInputCapture(& autoConfirmed);1267 if ( autoConfirmed)1294 bool fIsAutoConfirmed = false; 1295 ok = vboxProblem().confirmInputCapture(&fIsAutoConfirmed); 1296 if (fIsAutoConfirmed) 1268 1297 uisession()->setAutoCaptureDisabled(false); 1269 /* Otherwise, the disable flag will be reset in 1270 * the next console view's focus in event (since 1271 * may happen asynchronously on some platforms, 1272 * after we return from this code) */ 1298 else 1299 m_pressedHostComboKeys.clear(); 1300 /* Otherwise, the disable flag will be reset in the next 1301 * machine-view's focus-in event (since may happen asynchronously 1302 * on some platforms, after we return from this code): */ 1273 1303 } 1274 1275 1304 if (ok) 1276 1305 { … … 1284 1313 /* Make sure that pending FocusOut events from the 1285 1314 * previous message box are handled, otherwise the 1286 * mouse is immediately ungrabbed .*/1315 * mouse is immediately ungrabbed: */ 1287 1316 qApp->processEvents(); 1288 #endif 1317 #endif /* Q_WS_X11 */ 1289 1318 if (m_fIsKeyboardCaptured) 1290 1319 machineLogic()->mouseHandler()->captureMouse(uScreenId); … … 1295 1324 } 1296 1325 } 1297 1298 1326 if (uisession()->isRunning()) 1299 1327 sendChangedKeyStates(); 1300 1301 emitSignal = true;1302 1328 } 1303 1329 } 1304 1330 else 1305 1331 { 1306 if (m_bIsHost keyPressed)1307 m_bIsHost keyAlone = false;1332 if (m_bIsHostComboPressed) 1333 m_bIsHostComboAlone = false; 1308 1334 } 1309 1335 } … … 1312 1338 emit keyboardStateChanged(keyboardState()); 1313 1339 1314 /* Process Host+<key> shortcuts. currently, <key> is limited to 1315 * alphanumeric chars. Other Host+<key> combinations are handled in 1316 * event(). */ 1317 if (hotkey) 1318 { 1319 bool processed = false; 1320 #if defined (Q_WS_WIN) 1321 NOREF(pUniKey); 1322 int n = GetKeyboardLayoutList(0, NULL); 1323 Assert(n); 1324 HKL *list = new HKL[n]; 1325 GetKeyboardLayoutList(n, list); 1326 for (int i = 0; i < n && !processed; i++) 1327 { 1328 wchar_t ch; 1329 static BYTE keys[256] = {0}; 1330 if (!ToUnicodeEx(hotkey, 0, keys, &ch, 1, 0, list[i]) == 1) 1331 ch = 0; 1332 if (ch) 1333 processed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(ch).toUpper().unicode()))); 1334 } 1335 delete[] list; 1336 #elif defined (Q_WS_X11) 1337 NOREF(pUniKey); 1338 Display *display = QX11Info::display(); 1339 int keysyms_per_keycode = getKeysymsPerKeycode(); 1340 KeyCode kc = XKeysymToKeycode (display, iKey); 1341 for (int i = 0; i < keysyms_per_keycode && !processed; i += 2) 1342 { 1343 KeySym ks = XKeycodeToKeysym(display, kc, i); 1344 char ch = 0; 1345 if (!XkbTranslateKeySym(display, &ks, 0, &ch, 1, NULL) == 1) 1346 ch = 0; 1347 if (ch) 1348 { 1349 QChar c = QString::fromLocal8Bit(&ch, 1)[0]; 1350 processed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(c).toUpper().unicode()))); 1351 } 1352 } 1353 #elif defined (Q_WS_MAC) 1354 if (pUniKey && pUniKey[0] && !pUniKey[1]) 1355 processed = machineLogic()->actionsPool()->processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(pUniKey[0]).toUpper().unicode())); 1356 1357 /* Don't consider the hot key as pressed since the guest never saw 1358 * it. (probably a generic thing) */ 1359 m_pressedKeys[uScan] &= ~whatPressed; 1360 #endif 1361 /* Grab the key from Qt if processed, or pass it to Qt otherwise 1362 * in order to process non-alphanumeric keys in event(), after they are 1363 * converted to Qt virtual keys. */ 1364 return processed; 1365 } 1366 1367 /* No more to do, if the host key is in action or the VM is paused: */ 1368 if (m_bIsHostkeyPressed || isHostKey || uisession()->isPaused()) 1369 { 1370 /* Grab the key from Qt and from VM if it's a host key, 1371 * otherwise just pass it to Qt */ 1372 return isHostKey; 1373 } 1374 1375 CKeyboard keyboard = session().GetConsole().GetKeyboard(); 1376 Assert(!keyboard.isNull()); 1340 /* If the VM is NOT paused and there are scancodes to send: */ 1341 if (!uisession()->isPaused() && uCodesCount) 1342 { 1343 /* Get the VM keyboard to pass key in there: */ 1344 CKeyboard keyboard = session().GetConsole().GetKeyboard(); 1345 Assert(!keyboard.isNull()); 1346 1347 /* Pass this key to the guest: */ 1348 std::vector<LONG> scancodes(pCodes, &pCodes[uCodesCount]); 1349 keyboard.PutScancodes(QVector<LONG>::fromStdVector(scancodes)); 1350 1351 /* If full host-key sequence was just finalized 1352 * and the last key of host-combination was just sent to the guest => 1353 * we have to notify guest to make it release keys from the host-combination: */ 1354 if (isHostComboStateChanged && m_bIsHostComboPressed) 1355 { 1356 QList<uint8_t> hostComboScans = m_pressedHostComboKeys.values(); 1357 for (int i = 0 ; i < hostComboScans.size(); ++i) 1358 { 1359 uint8_t uScan = hostComboScans[i]; 1360 if (m_pressedKeys[uScan] & IsKeyPressed) 1361 { 1362 keyboard.PutScancode(uScan | 0x80); 1363 } 1364 else if (m_pressedKeys[uScan] & IsExtKeyPressed) 1365 { 1366 QVector<LONG> scancodes(2); 1367 scancodes[0] = 0xE0; 1368 scancodes[1] = uScan | 0x80; 1369 keyboard.PutScancodes(scancodes); 1370 } 1371 m_pressedKeys[uScan] = 0; 1372 } 1373 } 1374 } 1375 1376 /* Prevent the key from going to Qt: */ 1377 return true; 1378 } 1379 1380 bool UIKeyboardHandler::processHotKey(int iHotKey, wchar_t *pHotKey) 1381 { 1382 /* Prepare processing result: */ 1383 bool fWasProcessed = false; 1377 1384 1378 1385 #ifdef Q_WS_WIN 1379 /* Send pending WM_PAINT events: */ 1380 ::UpdateWindow(m_views[uScreenId]->viewport()->winId()); 1386 Q_UNUSED(pHotKey); 1387 int iKeyboardLayout = GetKeyboardLayoutList(0, NULL); 1388 Assert(iKeyboardLayout); 1389 HKL *pList = new HKL[iKeyboardLayout]; 1390 GetKeyboardLayoutList(iKeyboardLayout, pList); 1391 for (int i = 0; i < iKeyboardLayout && !fWasProcessed; ++i) 1392 { 1393 wchar_t symbol; 1394 static BYTE keys[256] = {0}; 1395 if (!ToUnicodeEx(iHotKey, 0, keys, &symbol, 1, 0, pList[i]) == 1) 1396 symbol = 0; 1397 if (symbol) 1398 fWasProcessed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + QChar(symbol).toUpper().unicode()))); 1399 } 1400 delete[] pList; 1381 1401 #endif /* Q_WS_WIN */ 1382 1402 1383 std::vector <LONG> scancodes(codes, &codes[count]); 1384 keyboard.PutScancodes(QVector<LONG>::fromStdVector(scancodes)); 1385 1386 /* Grab the key from Qt: */ 1387 return true; 1403 #ifdef Q_WS_X11 1404 Q_UNUSED(pHotKey); 1405 Display *pDisplay = QX11Info::display(); 1406 int iKeysymsPerKeycode = getKeysymsPerKeycode(); 1407 KeyCode keyCode = XKeysymToKeycode(pDisplay, iHotKey); 1408 for (int i = 0; i < iKeysymsPerKeycode && !fWasProcessed; i += 2) 1409 { 1410 KeySym ks = XKeycodeToKeysym(pDisplay, keyCode, i); 1411 char symbol = 0; 1412 if (!XkbTranslateKeySym(pDisplay, &ks, 0, &symbol, 1, NULL) == 1) 1413 symbol = 0; 1414 if (symbol) 1415 { 1416 QChar qtSymbol = QString::fromLocal8Bit(&symbol, 1)[0]; 1417 fWasProcessed = machineLogic()->actionsPool()->processHotKey(QKeySequence((Qt::UNICODE_ACCEL + qtSymbol.toUpper().unicode()))); 1418 } 1419 } 1420 #endif /* Q_WS_X11 */ 1421 1422 #ifdef Q_WS_MAC 1423 Q_UNUSED(iHotKey); 1424 if (pHotKey && pHotKey[0] && !pHotKey[1]) 1425 fWasProcessed = machineLogic()->actionsPool()->processHotKey(QKeySequence(Qt::UNICODE_ACCEL + QChar(pHotKey[0]).toUpper().unicode())); 1426 #endif /* Q_WS_MAC */ 1427 1428 /* Grab the key from the Qt if it was processed, or pass it to the Qt otherwise 1429 * in order to process non-alphanumeric keys in event(), after they are converted to Qt virtual keys: */ 1430 return fWasProcessed; 1388 1431 } 1389 1432 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
r35686 r35730 71 71 72 72 /* Some getters required by side-code: */ 73 bool isHostKeyPressed() const { return m_bIsHost keyPressed; }73 bool isHostKeyPressed() const { return m_bIsHostComboPressed; } 74 74 #ifdef Q_WS_MAC 75 bool isHostKeyAlone() const { return m_bIsHost keyAlone; }75 bool isHostKeyAlone() const { return m_bIsHostComboAlone; } 76 76 bool isKeyboardGrabbed() const { return m_fKeyboardGrabbed; } 77 77 #endif /* Q_WS_MAC */ … … 126 126 /* Separate function to handle most of existing keyboard-events: */ 127 127 bool keyEvent(int iKey, uint8_t uScan, int fFlags, ulong uScreenId, wchar_t *pUniKey = 0); 128 bool processHotKey(int iHotKey, wchar_t *pUniKey); 128 129 129 130 /* Private helpers: */ … … 150 151 uint8_t m_pressedKeysCopy[128]; 151 152 153 QMap<int, uint8_t> m_pressedHostComboKeys; 154 152 155 bool m_fIsKeyboardCaptured : 1; 153 bool m_bIsHostkeyPressed : 1; 154 bool m_bIsHostkeyAlone : 1; 155 bool m_bIsHostkeyInCapture : 1; 156 bool m_bIsHostComboPressed : 1; 157 bool m_bIsHostComboAlone : 1; 156 158 bool m_fPassCAD : 1; 157 159 158 160 #if defined(Q_WS_WIN) 161 /* Currently this is used in winLowKeyboardEvent() only: */ 162 bool m_bIsHostkeyInCapture; 159 163 /* Keyboard hook required to capture keyboard event under windows. */ 160 static UIKeyboardHandler *m_ pKeyboardHandler;164 static UIKeyboardHandler *m_spKeyboardHandler; 161 165 HHOOK m_keyboardHook; 162 166 int m_iKeyboardHookViewIndex; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
r35424 r35730 45 45 #include "QIStatusBar.h" 46 46 #include "QIStateIndicator.h" 47 #include " QIHotKeyEdit.h"47 #include "UIHotKeyEditor.h" 48 48 49 49 UIMachineWindowNormal::UIMachineWindowNormal(UIMachineLogic *pMachineLogic, ulong uScreenId) … … 262 262 void UIMachineWindowNormal::sltProcessGlobalSettingChange(const char * /* aPublicName */, const char * /* aName */) 263 263 { 264 m_pNameHostkey->setText( QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey()));264 m_pNameHostkey->setText(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())); 265 265 } 266 266 … … 275 275 "capture state. It can also be used in combination with other keys " 276 276 "to quickly perform actions from the main menu.")); 277 m_pNameHostkey->setText( QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey()));277 m_pNameHostkey->setText(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())); 278 278 } 279 279 … … 443 443 pIndicatorBoxHLayout->addWidget(m_pCntHostkey); 444 444 pHostkeyLedContainerLayout->addWidget(indicatorsPool()->indicator(UIIndicatorIndex_Hostkey)); 445 m_pNameHostkey = new QLabel( QIHotKeyEdit::keyName(vboxGlobal().settings().hostKey()));445 m_pNameHostkey = new QLabel(UIHotKeyCombination::toReadableString(vboxGlobal().settings().hostCombo())); 446 446 pHostkeyLedContainerLayout->addWidget(m_pNameHostkey); 447 447 -
trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.cpp
r33960 r35730 40 40 41 41 /* Load to cache: */ 42 m_cache.m_ iHostKey = m_settings.hostKey();42 m_cache.m_strHostCombo = m_settings.hostCombo(); 43 43 m_cache.m_fAutoCapture = m_settings.autoCapture(); 44 44 … … 52 52 { 53 53 /* Fetch from cache: */ 54 m_pHostKeyEditor->set Key(m_cache.m_iHostKey);54 m_pHostKeyEditor->setCombo(m_cache.m_strHostCombo); 55 55 m_pEnableAutoGrabCheckbox->setChecked(m_cache.m_fAutoCapture); 56 56 } … … 61 61 { 62 62 /* Upload to cache: */ 63 m_cache.m_ iHostKey = m_pHostKeyEditor->key();63 m_cache.m_strHostCombo = m_pHostKeyEditor->combo(); 64 64 m_cache.m_fAutoCapture = m_pEnableAutoGrabCheckbox->isChecked(); 65 65 } … … 73 73 74 74 /* Save from cache: */ 75 m_settings.setHost Key(m_cache.m_iHostKey);75 m_settings.setHostCombo(m_cache.m_strHostCombo); 76 76 m_settings.setAutoCapture(m_cache.m_fAutoCapture); 77 77 … … 84 84 { 85 85 setTabOrder(pWidget, m_pHostKeyEditor); 86 setTabOrder(m_pHostKeyEditor, m_pResetHostKeyButton); 87 setTabOrder(m_pResetHostKeyButton, m_pEnableAutoGrabCheckbox); 86 setTabOrder(m_pHostKeyEditor, m_pEnableAutoGrabCheckbox); 88 87 } 89 88 -
trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.h
r33960 r35730 27 27 struct UISettingsCacheGlobalInput 28 28 { 29 int m_iHostKey;29 QString m_strHostCombo; 30 30 bool m_fAutoCapture; 31 31 }; -
trunk/src/VBox/Frontends/VirtualBox/src/settings/global/UIGlobalSettingsInput.ui
r34160 r35730 54 54 </item> 55 55 <item row="0" column="2"> 56 <widget class=" QIHotKeyEdit" name="m_pHostKeyEditor">56 <widget class="UIHotKeyEditor" name="m_pHostKeyEditor"> 57 57 <property name="whatsThis"> 58 58 <string>Displays the key used as a Host Key in the VM window. Activate the entry field and press a new Host Key. Note that alphanumeric, cursor movement and editing keys cannot be used.</string> … … 66 66 </widget> 67 67 </item> 68 <item row="0" column="3"> 69 <widget class="UIResetButton" name="m_pResetHostKeyButton"> 70 <property name="focusPolicy"> 71 <enum>Qt::StrongFocus</enum> 72 </property> 73 <property name="toolTip"> 74 <string>Reset Host Key</string> 75 </property> 76 <property name="whatsThis"> 77 <string>Resets the key used as a Host Key in the VM window.</string> 78 </property> 79 <property name="icon"> 80 <iconset><normaloff>:/delete_16px.png</normaloff>:/delete_16px.png</iconset> 81 </property> 82 </widget> 83 </item> 84 <item row="0" column="4"> 85 <spacer> 86 <property name="orientation"> 87 <enum>Qt::Horizontal</enum> 88 </property> 89 <property name="sizeType"> 90 <enum>QSizePolicy::Fixed</enum> 91 </property> 92 <property name="sizeHint" stdset="0"> 93 <size> 94 <width>40</width> 95 <height>20</height> 96 </size> 97 </property> 98 </spacer> 99 </item> 100 <item row="1" column="2" colspan="3"> 68 <item row="1" column="2"> 101 69 <widget class="QCheckBox" name="m_pEnableAutoGrabCheckbox"> 102 70 <property name="whatsThis"> … … 108 76 </widget> 109 77 </item> 110 <item row="2" column="0" colspan=" 5">78 <item row="2" column="0" colspan="3"> 111 79 <spacer> 112 80 <property name="orientation"> … … 125 93 <customwidgets> 126 94 <customwidget> 127 <class> QIHotKeyEdit</class>95 <class>UIHotKeyEditor</class> 128 96 <extends>QLabel</extends> 129 <header> QIHotKeyEdit.h</header>97 <header>UIHotKeyEditor.h</header> 130 98 </customwidget> 131 99 <customwidget> -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHotKeyEditor.cpp
r35698 r35730 3 3 * 4 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * VirtualBox Qt extensions: QIHotKeyEditclass implementation5 * VirtualBox Qt extensions: UIHotKeyEditor class implementation 6 6 */ 7 7 … … 19 19 20 20 /* Local includes */ 21 #include " QIHotKeyEdit.h"21 #include "UIHotKeyEditor.h" 22 22 #include "VBoxDefs.h" 23 23 #include "VBoxGlobal.h" … … 27 27 #include <QStyleOption> 28 28 #include <QStylePainter> 29 #include <QKeyEvent> 29 30 30 31 #ifdef Q_WS_WIN 31 /* VBox/cdefs.h defines these: */32 32 # undef LOWORD 33 33 # undef HIWORD … … 38 38 39 39 #ifdef Q_WS_X11 40 /* We need to capture some X11 events directly which 41 * requires the XEvent structure to be defined. However, 42 * including the Xlib header file will cause some nasty 43 * conflicts with Qt. Therefore we use the following hack 44 * to redefine those conflicting identifiers. */ 45 # define XK_XKB_KEYS 46 # define XK_MISCELLANY 47 # include <X11/Xlib.h> 40 # include <QX11Info> 48 41 # include <X11/Xutil.h> 49 # include <X11/keysymdef.h>42 # include "XKeyboard.h" 50 43 # ifdef KeyPress 51 const int XFocusOut = FocusOut; 52 const int XFocusIn = FocusIn; 53 const int XKeyPress = KeyPress; 54 const int XKeyRelease = KeyRelease; 44 const int XKeyPress = KeyPress; 45 const int XKeyRelease = KeyRelease; 46 # undef KeyPress 55 47 # undef KeyRelease 56 # undef KeyPress57 # undef FocusOut58 # undef FocusIn59 48 # endif /* KeyPress */ 60 # include "XKeyboard.h"61 QMap<QString, QString> QIHotKeyEdit::s_keyNames;62 # include <QX11Info>63 49 #endif /* Q_WS_X11 */ 64 50 … … 68 54 # include "VBoxUtils.h" 69 55 # include <Carbon/Carbon.h> 70 #endif 71 56 #endif /* Q_WS_MAC */ 57 58 59 #ifdef Q_WS_X11 60 namespace UIHotKey 61 { 62 QMap<QString, QString> m_keyNames; 63 } 64 #endif /* Q_WS_X11 */ 65 66 QString UIHotKey::toString(int iKeyCode) 67 { 68 QString strKeyName; 72 69 73 70 #ifdef Q_WS_WIN 74 /* Returns the correct modifier vkey for the *last* keyboard message, 75 * distinguishing between left and right keys. If both are pressed 76 * the left key wins. If the pressed key not a modifier, wParam is returned 77 * unchanged. */ 78 int qi_distinguish_modifier_vkey(WPARAM wParam) 79 { 80 int keyval = wParam; 81 switch (wParam) 82 { 83 case VK_SHIFT: 84 if (::GetKeyState(VK_LSHIFT) & 0x8000) keyval = VK_LSHIFT; 85 else if (::GetKeyState(VK_RSHIFT) & 0x8000) keyval = VK_RSHIFT; 86 break; 87 case VK_CONTROL: 88 if (::GetKeyState(VK_LCONTROL) & 0x8000) keyval = VK_LCONTROL; 89 else if (::GetKeyState(VK_RCONTROL) & 0x8000) keyval = VK_RCONTROL; 90 break; 91 case VK_MENU: 92 if (::GetKeyState(VK_LMENU) & 0x8000) keyval = VK_LMENU; 93 else if (::GetKeyState(VK_RMENU) & 0x8000) keyval = VK_RMENU; 94 break; 95 } 96 return keyval; 97 } 71 /* MapVirtualKey doesn't distinguish between right and left vkeys, 72 * even under XP, despite that it stated in MSDN. Do it by hands. 73 * Besides that it can't recognize such virtual keys as 74 * VK_DIVIDE & VK_PAUSE, this is also known bug. */ 75 int iScan; 76 switch (iKeyCode) 77 { 78 /* Processing special keys... */ 79 case VK_PAUSE: iScan = 0x45 << 16; break; 80 case VK_RSHIFT: iScan = 0x36 << 16; break; 81 case VK_RCONTROL: iScan = (0x1D << 16) | (1 << 24); break; 82 case VK_RMENU: iScan = (0x38 << 16) | (1 << 24); break; 83 /* Processing extended keys... */ 84 case VK_APPS: 85 case VK_LWIN: 86 case VK_RWIN: 87 case VK_NUMLOCK: iScan = (::MapVirtualKey(iKeyCode, 0) | 256) << 16; break; 88 default: iScan = ::MapVirtualKey(iKeyCode, 0) << 16; 89 } 90 TCHAR *pKeyName = new TCHAR[256]; 91 if (::GetKeyNameText(iScan, pKeyName, 256)) 92 { 93 strKeyName = QString::fromUtf16(pKeyName); 94 } 95 else 96 { 97 AssertMsgFailed(("That key have no name!\n")); 98 strKeyName = UIHotKeyEditor::tr("<key_%1>").arg(iKeyCode); 99 } 100 delete[] pKeyName; 98 101 #endif /* Q_WS_WIN */ 99 102 100 101 const char *QIHotKeyEdit::m_spNoneSymbName = "None";102 103 QIHotKeyEdit::QIHotKeyEdit(QWidget *pParent)104 : QLabel(pParent)105 {106 103 #ifdef Q_WS_X11 107 /* Initialize the X keyboard subsystem: */ 108 initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes")); 104 if (char *pNativeKeyName = ::XKeysymToString((KeySym)iKeyCode)) 105 { 106 strKeyName = m_keyNames[pNativeKeyName].isEmpty() ? 107 QString(pNativeKeyName) : m_keyNames[pNativeKeyName]; 108 } 109 else 110 { 111 AssertMsgFailed(("That key have no name!\n")); 112 strKeyName = UIHotKeyEditor::tr("<key_%1>").arg(iKeyCode); 113 } 109 114 #endif /* Q_WS_X11 */ 110 115 111 clear(); 112 116 #ifdef Q_WS_MAC 117 UInt32 modMask = DarwinKeyCodeToDarwinModifierMask(iKeyCode); 118 switch (modMask) 119 { 120 case shiftKey: 121 case optionKey: 122 case controlKey: 123 case cmdKey: 124 strKeyName = tr("Left "); 125 break; 126 case rightShiftKey: 127 case rightOptionKey: 128 case rightControlKey: 129 case kEventKeyModifierRightCmdKeyMask: 130 strKeyName = tr("Right "); 131 break; 132 default: 133 AssertMsgFailedReturn(("modMask=%#x\n", modMask), QString()); 134 } 135 switch (modMask) 136 { 137 case shiftKey: 138 case rightShiftKey: 139 strKeyName += QChar(kShiftUnicode); 140 break; 141 case optionKey: 142 case rightOptionKey: 143 strKeyName += QChar(kOptionUnicode); 144 break; 145 case controlKey: 146 case rightControlKey: 147 strKeyName += QChar(kControlUnicode); 148 break; 149 case cmdKey: 150 case kEventKeyModifierRightCmdKeyMask: 151 strKeyName += QChar(kCommandUnicode); 152 break; 153 } 154 #endif /* Q_WS_MAC */ 155 156 return strKeyName; 157 } 158 159 bool UIHotKey::isValidKey(int iKeyCode) 160 { 113 161 #ifdef Q_WS_WIN 114 /* Qt documentation hasn't mentioned this is windows-only flag, 115 * but looks like that is so, anyway it is required for winEvent() handler only: */ 116 setAttribute(Qt::WA_NativeWindow); 162 return ((iKeyCode >= VK_SHIFT && iKeyCode <= VK_CAPITAL) || 163 (iKeyCode >= VK_LSHIFT && iKeyCode <= VK_RMENU) || 164 (iKeyCode >= VK_F1 && iKeyCode <= VK_F24) || 165 iKeyCode == VK_NUMLOCK || iKeyCode == VK_SCROLL || 166 iKeyCode == VK_LWIN || iKeyCode == VK_RWIN || 167 iKeyCode == VK_APPS || 168 iKeyCode == VK_PRINT); 117 169 #endif /* Q_WS_WIN */ 118 setFrameStyle(QFrame::StyledPanel | Sunken); 119 setAlignment(Qt::AlignCenter); 120 setFocusPolicy(Qt::StrongFocus);121 setAutoFillBackground(true);122 123 QPalette p = palette();124 p.setColor(QPalette::Active, QPalette::Foreground, p.color(QPalette::Active, QPalette::Text));125 p.setColor(QPalette::Active, QPalette::Background, p.color(QPalette::Active, QPalette::Base));126 setPalette(p); 170 171 #ifdef Q_WS_X11 172 return (IsModifierKey(iKeyCode) /* allow modifiers */ || 173 IsFunctionKey(iKeyCode) /* allow function keys */ || 174 IsMiscFunctionKey(iKeyCode) /* allow miscellaneous function keys */ || 175 iKeyCode == XK_Scroll_Lock /* allow 'Scroll Lock' missed in IsModifierKey() */) && 176 (iKeyCode != NoSymbol /* ignore some special symbol */ && 177 iKeyCode != XK_Insert /* ignore 'insert' included into IsMiscFunctionKey */); 178 #endif /* Q_WS_X11 */ 127 179 128 180 #ifdef Q_WS_MAC 129 m_uDarwinKeyModifiers = GetCurrentEventKeyModifiers(); 130 UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, QIHotKeyEdit::darwinEventHandlerProc, this); 131 ::DarwinGrabKeyboard(false /* just modifiers */); 132 #endif /* Q_WS_MAC */ 133 } 134 135 QIHotKeyEdit::~QIHotKeyEdit() 136 { 137 #ifdef Q_WS_MAC 138 ::DarwinReleaseKeyboard(); 139 UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, QIHotKeyEdit::darwinEventHandlerProc, this); 140 #endif 141 } 142 143 /** 144 * Set the hot key value. O means there is no hot key. 145 * 146 * @note 147 * The key value is platform-dependent. On Win32 it is the 148 * virtual key, on Linux it is the first (0) keysym corresponding 149 * to the keycode. 150 */ 151 void QIHotKeyEdit::setKey(int iKeyVal) 152 { 153 m_iKeyVal = iKeyVal; 154 m_strSymbName = QIHotKeyEdit::keyName(iKeyVal); 155 updateText(); 156 } 157 158 /**@@ QIHotKeyEdit::key() const 159 * 160 * Returns the value of the last recorded hot key. 161 * O means there is no hot key. 162 * 163 * @note 164 * The key value is platform-dependent. On Win32 it is the 165 * virtual key, on Linux it is the first (0) keysym corresponding 166 * to the keycode. 167 */ 168 169 QSize QIHotKeyEdit::sizeHint() const 170 { 171 ensurePolished(); 172 QFontMetrics fm(font()); 173 int h = qMax(fm.lineSpacing(), 14) + 2; 174 int w = fm.width('x') * 17; 175 int m = frameWidth() * 2; 176 QStyleOption option; 177 option.initFrom(this); 178 return (style()->sizeFromContents(QStyle::CT_LineEdit, &option, 179 QSize(w + m, h + m) 180 .expandedTo(QApplication::globalStrut()), 181 this)); 182 } 183 184 QSize QIHotKeyEdit::minimumSizeHint() const 185 { 186 ensurePolished(); 187 QFontMetrics fm = fontMetrics(); 188 int h = fm.height() + qMax(2, fm.leading()); 189 int w = fm.maxWidth(); 190 int m = frameWidth() * 2; 191 return QSize(w + m, h + m); 192 } 193 194 /** 195 * Returns the string representation of a given key. 196 * 197 * @note 198 * The key value is platform-dependent. On Win32 it is the 199 * virtual key, on Linux it is the first (0) keysym corresponding 200 * to the keycode. 201 */ 202 /* static */ 203 QString QIHotKeyEdit::keyName(int iKeyVal) 204 { 205 QString strName; 206 207 if (!iKeyVal) 208 { 209 strName = tr(m_spNoneSymbName); 210 } 211 else 212 { 213 #if defined (Q_WS_WIN) 214 /* Stupid MapVirtualKey doesn't distinguish between right and left 215 * vkeys, even under XP, despite that it stated in msdn. Do it by 216 * hands. Besides that it can't recognize such virtual keys as 217 * VK_DIVIDE & VK_PAUSE, this is also known bug. */ 218 int scan; 219 switch (iKeyVal) 220 { 221 /* Processing special keys... */ 222 case VK_PAUSE: scan = 0x45 << 16; break; 223 case VK_RSHIFT: scan = 0x36 << 16; break; 224 case VK_RCONTROL: scan = (0x1D << 16) | (1 << 24); break; 225 case VK_RMENU: scan = (0x38 << 16) | (1 << 24); break; 226 /* Processing extended keys... */ 227 case VK_APPS: 228 case VK_LWIN: 229 case VK_RWIN: 230 case VK_NUMLOCK: scan = (::MapVirtualKey(iKeyVal, 0) | 256) << 16; break; 231 default: scan = ::MapVirtualKey(iKeyVal, 0) << 16; 232 } 233 TCHAR *str = new TCHAR[256]; 234 if (::GetKeyNameText(scan, str, 256)) 235 { 236 strName = QString::fromUtf16(str); 237 } 238 else 239 { 240 AssertFailed(); 241 strName = QString(tr("<key_%1>")).arg(iKeyVal); 242 } 243 delete[] str; 244 #elif defined (Q_WS_X11) 245 char *sn = ::XKeysymToString((KeySym)iKeyVal); 246 if (sn) 247 { 248 strName = s_keyNames[sn]; 249 if (strName.isEmpty()) 250 strName = sn; 251 } 252 else 253 { 254 AssertFailed(); 255 strName = QString(tr("<key_%1>")).arg(iKeyVal); 256 } 257 #elif defined(Q_WS_MAC) 258 UInt32 modMask = DarwinKeyCodeToDarwinModifierMask(iKeyVal); 259 switch (modMask) 260 { 261 case shiftKey: 262 case optionKey: 263 case controlKey: 264 case cmdKey: 265 strName = tr("Left "); 266 break; 267 case rightShiftKey: 268 case rightOptionKey: 269 case rightControlKey: 270 case kEventKeyModifierRightCmdKeyMask: 271 strName = tr("Right "); 272 break; 273 default: 274 AssertMsgFailedReturn(("modMask=%#x\n", modMask), QString()); 275 } 276 switch (modMask) 277 { 278 case shiftKey: 279 case rightShiftKey: 280 strName += QChar(kShiftUnicode); 281 break; 282 case optionKey: 283 case rightOptionKey: 284 strName += QChar(kOptionUnicode); 285 break; 286 case controlKey: 287 case rightControlKey: 288 strName += QChar(kControlUnicode); 289 break; 290 case cmdKey: 291 case kEventKeyModifierRightCmdKeyMask: 292 strName += QChar(kCommandUnicode); 293 break; 294 } 295 #else 296 AssertFailed(); 297 strName = QString(tr("<key_%1>")).arg(iKeyVal); 298 #endif 299 } 300 301 return strName; 302 } 303 304 /* static */ 305 bool QIHotKeyEdit::isValidKey(int iKeyVal) 306 { 307 /* Empty value is correct: */ 308 if (iKeyVal == 0) 309 return true; 310 #if defined(Q_WS_WIN) 311 return ((iKeyVal >= VK_SHIFT && iKeyVal <= VK_CAPITAL) || 312 iKeyVal == VK_PRINT || 313 iKeyVal == VK_LWIN || iKeyVal == VK_RWIN || 314 iKeyVal == VK_APPS || 315 (iKeyVal >= VK_F1 && iKeyVal <= VK_F24) || 316 iKeyVal == VK_NUMLOCK || iKeyVal == VK_SCROLL || 317 (iKeyVal >= VK_LSHIFT && iKeyVal <= VK_RMENU)); 318 #elif defined(Q_WS_X11) 319 KeySym ks = (KeySym)iKeyVal; 320 return (ks != NoSymbol && ks != XK_Insert) && 321 (ks == XK_Scroll_Lock || IsModifierKey(ks) || IsFunctionKey(ks) || IsMiscFunctionKey(ks)); 322 #elif defined(Q_WS_MAC) 323 UInt32 modMask = ::DarwinKeyCodeToDarwinModifierMask(iKeyVal); 181 UInt32 modMask = ::DarwinKeyCodeToDarwinModifierMask(iKeyCode); 324 182 switch (modMask) 325 183 { … … 336 194 return false; 337 195 } 338 #else 339 Q_UNUSED(iKeyVal); 196 #endif /* Q_WS_MAC */ 197 198 return false; 199 } 200 201 #ifdef Q_WS_WIN 202 int UIHotKey::distinguishModifierVKey(int wParam) 203 { 204 int iKeyCode = wParam; 205 switch (iKeyCode) 206 { 207 case VK_SHIFT: 208 if (::GetKeyState(VK_LSHIFT) & 0x8000) iKeyCode = VK_LSHIFT; 209 else if (::GetKeyState(VK_RSHIFT) & 0x8000) iKeyCode = VK_RSHIFT; 210 break; 211 case VK_CONTROL: 212 if (::GetKeyState(VK_LCONTROL) & 0x8000) iKeyCode = VK_LCONTROL; 213 else if (::GetKeyState(VK_RCONTROL) & 0x8000) iKeyCode = VK_RCONTROL; 214 break; 215 case VK_MENU: 216 if (::GetKeyState(VK_LMENU) & 0x8000) iKeyCode = VK_LMENU; 217 else if (::GetKeyState(VK_RMENU) & 0x8000) iKeyCode = VK_RMENU; 218 break; 219 } 220 return iKeyCode; 221 } 222 #endif /* Q_WS_WIN */ 223 224 #ifdef Q_WS_X11 225 void UIHotKey::retranslateKeyNames() 226 { 227 m_keyNames["Shift_L"] = UIHotKeyEditor::tr("Left Shift"); 228 m_keyNames["Shift_R"] = UIHotKeyEditor::tr("Right Shift"); 229 m_keyNames["Control_L"] = UIHotKeyEditor::tr("Left Ctrl"); 230 m_keyNames["Control_R"] = UIHotKeyEditor::tr("Right Ctrl"); 231 m_keyNames["Alt_L"] = UIHotKeyEditor::tr("Left Alt"); 232 m_keyNames["Alt_R"] = UIHotKeyEditor::tr("Right Alt"); 233 m_keyNames["Super_L"] = UIHotKeyEditor::tr("Left WinKey"); 234 m_keyNames["Super_R"] = UIHotKeyEditor::tr("Right WinKey"); 235 m_keyNames["Menu"] = UIHotKeyEditor::tr("Menu key"); 236 m_keyNames["ISO_Level3_Shift"] = UIHotKeyEditor::tr("Alt Gr"); 237 m_keyNames["Caps_Lock"] = UIHotKeyEditor::tr("Caps Lock"); 238 m_keyNames["Scroll_Lock"] = UIHotKeyEditor::tr("Scroll Lock"); 239 } 240 #endif /* Q_WS_X11 */ 241 242 243 QString UIHotKeyCombination::toReadableString(const QString &strKeyCombo) 244 { 245 QStringList encodedKeyList = strKeyCombo.split(','); 246 QStringList readableKeyList; 247 for (int i = 0; i < encodedKeyList.size(); ++i) 248 if (int iKeyCode = encodedKeyList[i].toInt()) 249 readableKeyList << UIHotKey::toString(iKeyCode); 250 return readableKeyList.isEmpty() ? UIHotKeyEditor::tr("None") : readableKeyList.join(" + "); 251 } 252 253 QList<int> UIHotKeyCombination::toKeyCodeList(const QString &strKeyCombo) 254 { 255 QStringList encodedKeyList = strKeyCombo.split(','); 256 QList<int> keyCodeList; 257 for (int i = 0; i < encodedKeyList.size(); ++i) 258 if (int iKeyCode = encodedKeyList[i].toInt()) 259 keyCodeList << iKeyCode; 260 return keyCodeList; 261 } 262 263 bool UIHotKeyCombination::isValidKeyCombo(const QString &strKeyCombo) 264 { 265 QList<int> keyCodeList = toKeyCodeList(strKeyCombo); 266 for (int i = 0; i < keyCodeList.size(); ++i) 267 if (!UIHotKey::isValidKey(keyCodeList[i])) 268 return false; 340 269 return true; 341 #endif 342 } 270 } 271 272 273 UIHotKeyEditor::UIHotKeyEditor(QWidget *pParent) 274 : QLabel(pParent) 275 , m_fStartNewSequence(true) 276 { 277 /* Configure widget: */ 278 setAttribute(Qt::WA_NativeWindow); 279 setFrameStyle(QFrame::StyledPanel | Sunken); 280 setAlignment(Qt::AlignCenter); 281 setFocusPolicy(Qt::StrongFocus); 282 setAutoFillBackground(true); 283 284 /* Setup palette: */ 285 QPalette p = palette(); 286 p.setColor(QPalette::Active, QPalette::Foreground, p.color(QPalette::Active, QPalette::Text)); 287 p.setColor(QPalette::Active, QPalette::Background, p.color(QPalette::Active, QPalette::Base)); 288 setPalette(p); 343 289 344 290 #ifdef Q_WS_X11 345 /* Updates the associative array containing the translations 346 * of X11 key strings to human readable key names. */ 347 void QIHotKeyEdit::retranslateUi() 348 { 349 /* Note: strings for the same key must match strings in retranslateUi() 350 * versions for all platforms, to keep translators happy. */ 351 352 s_keyNames["Shift_L"] = tr("Left Shift"); 353 s_keyNames["Shift_R"] = tr("Right Shift"); 354 s_keyNames["Control_L"] = tr("Left Ctrl"); 355 s_keyNames["Control_R"] = tr("Right Ctrl"); 356 s_keyNames["Alt_L"] = tr("Left Alt"); 357 s_keyNames["Alt_R"] = tr("Right Alt"); 358 s_keyNames["Super_L"] = tr("Left WinKey"); 359 s_keyNames["Super_R"] = tr("Right WinKey"); 360 s_keyNames["Menu"] = tr("Menu key"); 361 s_keyNames["ISO_Level3_Shift"] = tr("Alt Gr"); 362 s_keyNames["Caps_Lock"] = tr("Caps Lock"); 363 s_keyNames["Scroll_Lock"] = tr("Scroll Lock"); 364 } 291 /* Initialize the X keyboard subsystem: */ 292 initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes")); 365 293 #endif /* Q_WS_X11 */ 366 294 367 void QIHotKeyEdit::clear() 368 { 369 m_iKeyVal = 0; 370 m_strSymbName = tr(m_spNoneSymbName); 295 #ifdef Q_WS_MAC 296 m_uDarwinKeyModifiers = GetCurrentEventKeyModifiers(); 297 UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, UIHotKeyEditor::darwinEventHandlerProc, this); 298 ::DarwinGrabKeyboard(false /* just modifiers */); 299 #endif /* Q_WS_MAC */ 300 } 301 302 UIHotKeyEditor::~UIHotKeyEditor() 303 { 304 #ifdef Q_WS_MAC 305 ::DarwinReleaseKeyboard(); 306 UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown | NSKeyUp | | NSFlagsChanged */, UIHotKeyEditor::darwinEventHandlerProc, this); 307 #endif /* Q_WS_MAC */ 308 } 309 310 void UIHotKeyEditor::setCombo(const QString &strKeyCombo) 311 { 312 /* Cleanup old combo: */ 313 m_shownKeys.clear(); 314 /* Parse newly passed combo: */ 315 QList<int> keyCodeList = UIHotKeyCombination::toKeyCodeList(strKeyCombo); 316 for (int i = 0; i < keyCodeList.size(); ++i) 317 if (int iKeyCode = keyCodeList[i]) 318 m_shownKeys.insert(iKeyCode, UIHotKey::toString(iKeyCode)); 319 /* Update text: */ 371 320 updateText(); 372 321 } 373 322 374 #if defined (Q_WS_WIN) 375 376 bool QIHotKeyEdit::winEvent(MSG *pMsg, long* /* pResult */) 377 { 378 if (!(pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN || 379 pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP || 380 pMsg->message == WM_CHAR || pMsg->message == WM_SYSCHAR || 381 pMsg->message == WM_DEADCHAR || pMsg->message == WM_SYSDEADCHAR || 382 pMsg->message == WM_CONTEXTMENU)) 383 return false; 384 385 /* Ignore if not a valid hot key: */ 386 if (!isValidKey(pMsg->wParam)) 387 return false; 388 389 #if 0 390 LogFlow(("%WM_%04X: vk=%04X rep=%05d scan=%02X ext=%01d" 391 "rzv=%01X ctx=%01d prev=%01d tran=%01d\n", 392 pMsg->message, pMsg->wParam, 393 (pMsg->lParam & 0xFFFF), 394 ((pMsg->lParam >> 16) & 0xFF), 395 ((pMsg->lParam >> 24) & 0x1), 396 ((pMsg->lParam >> 25) & 0xF), 397 ((pMsg->lParam >> 29) & 0x1), 398 ((pMsg->lParam >> 30) & 0x1), 399 ((pMsg->lParam >> 31) & 0x1))); 400 #endif 401 402 if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) 403 { 404 /* Determine platform-dependent key: */ 405 m_iKeyVal = qi_distinguish_modifier_vkey(pMsg->wParam); 406 /* Determine symbolic name: */ 407 TCHAR *pStr = new TCHAR[256]; 408 if (::GetKeyNameText(pMsg->lParam, pStr, 256)) 323 QString UIHotKeyEditor::combo() const 324 { 325 /* Compose current combination: */ 326 QStringList keyCodeStringList; 327 QList<int> keyCodeList = m_shownKeys.keys(); 328 for (int i = 0; i < keyCodeList.size(); ++i) 329 keyCodeStringList << QString::number(keyCodeList[i]); 330 /* Return current combination or "0" for "None": */ 331 return keyCodeStringList.isEmpty() ? "0" : keyCodeStringList.join(","); 332 } 333 334 QSize UIHotKeyEditor::sizeHint() const 335 { 336 ensurePolished(); 337 QFontMetrics fm(font()); 338 int h = qMax(fm.lineSpacing(), 14) + 2; 339 int w = fm.width('x') * 17; 340 int m = frameWidth() * 2; 341 QStyleOption option; 342 option.initFrom(this); 343 return (style()->sizeFromContents(QStyle::CT_LineEdit, &option, 344 QSize(w + m, h + m).expandedTo(QApplication::globalStrut()), 345 this)); 346 } 347 348 QSize UIHotKeyEditor::minimumSizeHint() const 349 { 350 ensurePolished(); 351 QFontMetrics fm = fontMetrics(); 352 int h = fm.height() + qMax(2, fm.leading()); 353 int w = fm.maxWidth(); 354 int m = frameWidth() * 2; 355 return QSize(w + m, h + m); 356 } 357 358 #ifdef Q_WS_WIN 359 bool UIHotKeyEditor::winEvent(MSG *pMsg, long* /* pResult */) 360 { 361 switch (pMsg->message) 362 { 363 case WM_KEYDOWN: 364 case WM_SYSKEYDOWN: 365 case WM_KEYUP: 366 case WM_SYSKEYUP: 409 367 { 410 m_strSymbName = QString::fromUtf16(pStr); 368 /* Get key-code: */ 369 int iKeyCode = UIHotKey::distinguishModifierVKey((int)pMsg->wParam); 370 371 /* Check if symbol is valid else pass it to Qt: */ 372 if (!UIHotKey::isValidKey(iKeyCode)) 373 return false; 374 375 /* Key press: */ 376 if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) 377 { 378 /* Clear reflected symbols if new sequence started: */ 379 if (m_fStartNewSequence) 380 m_shownKeys.clear(); 381 382 /* Remember pressed symbol: */ 383 m_pressedKeys << pMsg->wParam; 384 m_shownKeys.insert(iKeyCode, UIHotKey::toString(iKeyCode)); 385 386 /* Remember what we already started a sequence: */ 387 m_fStartNewSequence = false; 388 } 389 /* Key release: */ 390 else if (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP) 391 { 392 /* Remove pressed symbol: */ 393 m_pressedKeys.remove(pMsg->wParam); 394 395 /* If pressed keys map is empty => start new sequence: */ 396 if (m_pressedKeys.isEmpty()) 397 m_fStartNewSequence = true; 398 } 399 400 /* Update text: */ 401 updateText(); 402 403 /* Prevent passing to Qt: */ 404 return true; 411 405 } 412 else 413 { 414 AssertFailed(); 415 m_strSymbName = QString(tr("<key_%1>")).arg(m_iKeyVal); 416 } 417 delete[] pStr; 418 /* Update the display: */ 419 updateText(); 420 } 421 422 return true; 423 } 424 425 #elif defined (Q_WS_X11) 426 427 bool QIHotKeyEdit::x11Event(XEvent *pEvent) 406 default: 407 break; 408 } 409 410 return false; 411 } 412 #endif /* Q_WS_WIN */ 413 414 #ifdef Q_WS_X11 415 bool UIHotKeyEditor::x11Event(XEvent *pEvent) 428 416 { 429 417 switch (pEvent->type) … … 432 420 case XKeyRelease: 433 421 { 422 /* Get key-code: */ 434 423 XKeyEvent *pKeyEvent = (XKeyEvent*)pEvent; 435 424 KeySym ks = ::XKeycodeToKeysym(pKeyEvent->display, pKeyEvent->keycode, 0); 436 /* Ignore if not a valid hot key: */ 437 if (!isValidKey((int)ks)) 425 int iKeySym = (int)ks; 426 427 /* Check if symbol is valid else pass it to Qt: */ 428 if (!UIHotKey::isValidKey(iKeySym)) 438 429 return false; 439 430 440 /* Skip key releases: */ 441 if (pEvent->type == XKeyRelease) 442 return true; 443 444 /* Determine platform-dependent key: */ 445 m_iKeyVal = (int)ks; 446 /* Determine symbolic name: */ 447 m_strSymbName = QIHotKeyEdit::keyName(m_iKeyVal); 448 /* Update the display: */ 431 /* Key press: */ 432 if (pEvent->type == XKeyPress) 433 { 434 /* Clear reflected symbols if new sequence started: */ 435 if (m_fStartNewSequence) 436 m_shownKeys.clear(); 437 438 /* Remember pressed symbol: */ 439 m_pressedKeys << iKeySym; 440 m_shownKeys.insert(iKeySym, UIHotKey::toString(iKeySym)); 441 442 /* Remember what we already started a sequence: */ 443 m_fStartNewSequence = false; 444 } 445 /* Key release: */ 446 else if (pEvent->type == XKeyRelease) 447 { 448 /* Remove pressed symbol: */ 449 m_pressedKeys.remove(iKeySym); 450 451 /* If pressed keys map is empty => start new sequence: */ 452 if (m_pressedKeys.isEmpty()) 453 m_fStartNewSequence = true; 454 } 455 456 /* Update text: */ 449 457 updateText(); 450 #if 0 451 LogFlow(("%s: state=%08X keycode=%08X keysym=%08X symb=%s\n", 452 pEvent->type == XKeyPress ? "XKeyPress" : "XKeyRelease", 453 pKeyEvent->state, pKeyEvent->keycode, ks, 454 symbname.latin1())); 455 #endif 458 459 /* Prevent passing to Qt: */ 456 460 return true; 457 461 } … … 460 464 return false; 461 465 } 462 463 #elif defined (Q_WS_MAC) 464 466 #endif /* Q_WS_X11 */ 467 468 #ifdef Q_WS_MAC 465 469 /* static */ 466 bool QIHotKeyEdit::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)467 { 468 QIHotKeyEdit *edit = (QIHotKeyEdit*)pvUser;470 bool UIHotKeyEditor::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser) 471 { 472 UIHotKeyEditor *edit = (UIHotKeyEditor*)pvUser; 469 473 EventRef inEvent = (EventRef)pvCarbonEvent; 470 474 UInt32 EventClass = ::GetEventClass(inEvent); … … 474 478 } 475 479 476 bool QIHotKeyEdit::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent) 477 { 478 #if 0 /* for debugging */ 479 ::darwinDebugPrintEvent("QIHotKeyEdit", inEvent); 480 #endif 481 480 bool UIHotKeyEditor::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent) 481 { 482 482 /* Ignore key changes unless we're the focus widget: */ 483 483 if (!hasFocus()) … … 487 487 switch (eventKind) 488 488 { 489 / *case kEventRawKeyDown:490 case kEventRawKeyUp:491 case kEventRawKeyRepeat:*/489 //case kEventRawKeyDown: 490 //case kEventRawKeyUp: 491 //case kEventRawKeyRepeat: 492 492 case kEventRawKeyModifiersChanged: 493 493 { 494 /* Get modifier mask: */ 494 495 UInt32 modifierMask = 0; 495 496 ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, 496 497 sizeof(modifierMask), NULL, &modifierMask); 497 498 498 modifierMask = ::DarwinAdjustModifierMask(modifierMask, pvCocoaEvent); 499 499 UInt32 changed = m_uDarwinKeyModifiers ^ modifierMask; 500 500 m_uDarwinKeyModifiers = modifierMask; 501 501 502 /* Skip key releases: */ 503 if (changed && (changed & modifierMask)) 502 /* Convert to keycode: */ 503 int iKeyCode = ::DarwinModifierMaskToDarwinKeycode(changed); 504 505 /* Check if symbol is valid else pass it to Qt: */ 506 if (!iKeyCode || iKeyCode == ~0U || !UIHotKey::isValidKey(iKeyCode)) 504 507 break; 505 508 506 /* Convert to keycode and skip keycodes we don't care about. */ 507 unsigned keyCode = ::DarwinModifierMaskToDarwinKeycode(changed); 508 if (!keyCode || keyCode == ~0U || !isValidKey(keyCode)) 509 break; 510 511 /* Update key current key: */ 512 m_iKeyVal = keyCode; 513 m_strSymbName = QIHotKeyEdit::keyName(keyCode); 509 if (changed) 510 { 511 /* Key release: */ 512 if (changed & modifierMask) 513 { 514 /* Remove pressed symbol: */ 515 m_pressedKeys.remove(iKeyCode); 516 517 /* If pressed key map is empty => start new sequence: */ 518 if (m_pressedKeys.isEmpty()) 519 m_fStartNewSequence = true; 520 } 521 /* Key press: */ 522 else 523 { 524 /* Clear reflected symbols if new sequence started: */ 525 if (m_fStartNewSequence) 526 m_shownKeys.clear(); 527 528 /* Remember pressed symbol: */ 529 m_pressedKeys << iKeyCode; 530 m_shownKeys.insert(iKeyCode, UIHotKey::toString(iKeyCode)); 531 532 /* Remember what we already started a sequence: */ 533 m_fStartNewSequence = false; 534 } 535 } 536 537 /* Update text: */ 514 538 updateText(); 515 break; //return true;516 539 } 517 540 break; … … 519 542 return false; 520 543 } 521 522 #else 523 # warning "Port me!" 524 #endif 525 526 void QIHotKeyEdit::focusInEvent(QFocusEvent *pEvent) 544 #endif /* Q_WS_MAC */ 545 546 void UIHotKeyEditor::keyPressEvent(QKeyEvent *pEvent) 547 { 548 switch (pEvent->key()) 549 { 550 case Qt::Key_Delete: 551 case Qt::Key_Backspace: 552 m_shownKeys.clear(); 553 updateText(); 554 break; 555 default: 556 QWidget::keyPressEvent(pEvent); 557 break; 558 } 559 } 560 561 void UIHotKeyEditor::focusInEvent(QFocusEvent *pEvent) 527 562 { 528 563 QLabel::focusInEvent(pEvent); … … 534 569 } 535 570 536 void QIHotKeyEdit::focusOutEvent(QFocusEvent *pEvent)571 void UIHotKeyEditor::focusOutEvent(QFocusEvent *pEvent) 537 572 { 538 573 QLabel::focusOutEvent(pEvent); … … 544 579 } 545 580 546 void QIHotKeyEdit::paintEvent(QPaintEvent *pEvent)581 void UIHotKeyEditor::paintEvent(QPaintEvent *pEvent) 547 582 { 548 583 if (hasFocus()) … … 558 593 } 559 594 560 void QIHotKeyEdit::updateText() 561 { 562 setText(QString(" %1 ").arg(m_strSymbName)); 563 } 564 595 void UIHotKeyEditor::updateText() 596 { 597 QStringList shownKeyNames(m_shownKeys.values()); 598 setText(shownKeyNames.isEmpty() ? tr("None") : shownKeyNames.join(" + ")); 599 } 600 -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHotKeyEditor.h
r35698 r35730 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * VirtualBox Qt extensions: QIHotKeyEditclass declaration4 * VirtualBox Qt extensions: UIHotKeyEditor class declaration 5 5 */ 6 6 … … 17 17 */ 18 18 19 #ifndef ___ QIHotKeyEdit_h___20 #define ___ QIHotKeyEdit_h___19 #ifndef ___UIHotKeyEditor_h___ 20 #define ___UIHotKeyEditor_h___ 21 21 22 22 /* Global includes */ 23 23 #include <QLabel> 24 #include <QMap> 25 #include <QSet> 24 26 27 /* Hot-key namespace to unify 28 * all the related hot-key processing stuff: */ 29 namespace UIHotKey 30 { 31 QString toString(int iKeyCode); 32 bool isValidKey(int iKeyCode); 33 #ifdef Q_WS_WIN 34 int distinguishModifierVKey(int wParam); 35 #endif /* Q_WS_WIN */ 25 36 #ifdef Q_WS_X11 26 # include <QMap> 37 void retranslateKeyNames(); 27 38 #endif /* Q_WS_X11 */ 39 } 28 40 29 class QIHotKeyEdit : public QLabel 41 /* Hot-combo namespace to unify 42 * all the related hot-combo processing stuff: */ 43 namespace UIHotKeyCombination 30 44 { 31 Q_OBJECT 45 QString toReadableString(const QString &strKeyCombo); 46 QList<int> toKeyCodeList(const QString &strKeyCombo); 47 bool isValidKeyCombo(const QString &strKeyCombo); 48 } 49 50 class UIHotKeyEditor : public QLabel 51 { 52 Q_OBJECT; 32 53 33 54 public: 34 55 35 QIHotKeyEdit(QWidget *pParent);36 virtual ~ QIHotKeyEdit();56 UIHotKeyEditor(QWidget *pParent); 57 virtual ~UIHotKeyEditor(); 37 58 38 void setKey(int iKeyVal); 39 int key() const { return m_iKeyVal; } 40 41 QString symbolicName() const { return m_strSymbName; } 59 void setCombo(const QString &strKeyCombo); 60 QString combo() const; 42 61 43 62 QSize sizeHint() const; 44 63 QSize minimumSizeHint() const; 45 64 46 static QString keyName(int iKeyVal);47 static bool isValidKey(int iKeyVal);48 #ifdef Q_WS_X1149 static void retranslateUi();50 #endif /* Q_WS_X11 */51 52 public slots:53 54 void clear();55 56 65 protected: 57 66 58 #if defined (Q_WS_WIN32)67 #ifdef Q_WS_WIN 59 68 bool winEvent(MSG *pMsg, long *pResult); 60 #elif defined (Q_WS_X11) 69 #endif /* Q_WS_WIN */ 70 #ifdef Q_WS_X11 61 71 bool x11Event(XEvent *pEvent); 62 #elif defined (Q_WS_MAC) 72 #endif /* Q_WS_X11 */ 73 #ifdef Q_WS_MAC 63 74 static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); 64 75 bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent); 65 #endif 76 #endif /* Q_WS_MAC */ 66 77 78 void keyPressEvent(QKeyEvent *pEvent); 67 79 void focusInEvent(QFocusEvent *pEvent); 68 80 void focusOutEvent(QFocusEvent *pEvent); … … 73 85 void updateText(); 74 86 75 int m_iKeyVal;76 Q String m_strSymbName;87 QSet<int> m_pressedKeys; 88 QMap<int, QString> m_shownKeys; 77 89 78 #ifdef Q_WS_X11 79 static QMap<QString, QString> s_keyNames; 80 #endif /* Q_WS_X11 */ 90 bool m_fStartNewSequence; 81 91 82 92 #ifdef Q_WS_MAC … … 85 95 uint32_t m_uDarwinKeyModifiers; 86 96 #endif /* Q_WS_MAC */ 87 88 static const char *m_spNoneSymbName;89 97 }; 90 98 91 #endif // !___ QIHotKeyEdit_h___99 #endif // !___UIHotKeyEditor_h___ 92 100
Note:
See TracChangeset
for help on using the changeset viewer.