From cd168110e0b9fbcba3f453de14131eb17c82109f Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 10 Oct 2012 18:27:04 +0200 Subject: QWindowsKeyMapper: use a more efficient data structure for 'keyLayout' Instead of allocating small chunks (40 bytes) on the heap, use a contiguous array to hold them. This always occupies 10240 bytes of memory instead of 1024 (32 bits) or 2048 (64 bits) for the pointer array (plus heap memory which depends on the number of items allocated), but is more cache-friendly and uses less memory when the array isn't sparse. To emulate the nullptr, a new bool has been added (doesn't change sizeof(KeyboardLayoutItem)). Also replace a few more magic numbers by symbolic constants. Change-Id: I7160f600faddd63deea265c89dc6fd857c7b557f Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowskeymapper.cpp | 94 ++++++++-------------- src/plugins/platforms/windows/qwindowskeymapper.h | 23 +++++- 2 files changed, 56 insertions(+), 61 deletions(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index eeba99f93b..c11bd8c53c 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -68,7 +68,6 @@ QWindowsKeyMapper::QWindowsKeyMapper() QWindowsKeyMapper::~QWindowsKeyMapper() { - deleteLayouts(); } #ifndef LANG_PASHTO @@ -437,6 +436,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::NoModifier, // Fall-back to raw Key_* }; static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl; +Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys)); /** Remap return or action key to select key for windows mobile. @@ -521,32 +521,10 @@ static inline bool isModifierKey(int code) // Keyboard map private ----------------------------------------------------------------[ start ]--- -/* - \internal - A Windows KeyboardLayoutItem has 8 possible states: - 1. Unmodified - 2. Shift - 3. Control - 4. Control + Shift - 5. Alt - 6. Alt + Shift - 7. Alt + Control - 8. Alt + Control + Shift -*/ -struct KeyboardLayoutItem { - bool dirty; - quint8 deadkeys; - quint32 qtKey[NumMods]; // Can by any Qt::Key_, or unicode character -}; - void QWindowsKeyMapper::deleteLayouts() { - for (int i = 0; i < 255; ++i) { - if (keyLayout[i]) { - delete keyLayout[i]; - keyLayout[i] = 0; - } - } + for (size_t i = 0; i < NumKeyboardLayoutItems; ++i) + keyLayout[i].exists = false; } void QWindowsKeyMapper::changeKeyboard() @@ -595,12 +573,9 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg) void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode, quint32 vk_key) { - if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty)) + if (!vk_key || (keyLayout[vk_key].exists && !keyLayout[vk_key].dirty)) return; - if (!keyLayout[vk_key]) - keyLayout[vk_key] = new KeyboardLayoutItem; - // Copy keyboard state, so we can modify and query output for each possible permutation unsigned char buffer[256]; memcpy(buffer, kbdBuffer, sizeof(buffer)); @@ -616,40 +591,41 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 buffer[VK_LMENU ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph bool isDeadKey = false; - keyLayout[vk_key]->deadkeys = 0; - keyLayout[vk_key]->dirty = false; + keyLayout[vk_key].deadkeys = 0; + keyLayout[vk_key].dirty = false; + keyLayout[vk_key].exists = true; setKbdState(buffer, false, false, false); - keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0; + keyLayout[vk_key].qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x01 : 0; setKbdState(buffer, true, false, false); - keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0; + keyLayout[vk_key].qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x02 : 0; setKbdState(buffer, false, true, false); - keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0; + keyLayout[vk_key].qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x04 : 0; setKbdState(buffer, true, true, false); - keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0; + keyLayout[vk_key].qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x08 : 0; setKbdState(buffer, false, false, true); - keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0; + keyLayout[vk_key].qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x10 : 0; setKbdState(buffer, true, false, true); - keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0; + keyLayout[vk_key].qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x20 : 0; setKbdState(buffer, false, true, true); - keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0; + keyLayout[vk_key].qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x40 : 0; setKbdState(buffer, true, true, true); - keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); - keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0; + keyLayout[vk_key].qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey); + keyLayout[vk_key].deadkeys |= isDeadKey ? 0x80 : 0; // Add a fall back key for layouts which don't do composition and show non-latin1 characters int fallbackKey = winceKeyBend(vk_key); if (!fallbackKey || fallbackKey == Qt::Key_unknown) { fallbackKey = 0; - if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) + if (vk_key != keyLayout[vk_key].qtKey[0] && vk_key < 0x5B && vk_key > 0x2F) fallbackKey = vk_key; } - keyLayout[vk_key]->qtKey[8] = fallbackKey; + keyLayout[vk_key].qtKey[8] = fallbackKey; // If this vk_key a Dead Key if (MapVirtualKey(vk_key, 2) & 0x80000000) { @@ -669,20 +645,20 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key); for (size_t i = 0; i < NumMods; ++i) { qDebug(" [%d] (%d,0x%02x,'%c') %s", int(i), - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i], - keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03, - keyLayout[vk_key]->deadkeys & (1<deadkeys & 1< QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const { QList result; - KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; - if (!kbItem) + const KeyboardLayoutItem &kbItem = keyLayout[e->nativeVirtualKey()]; + if (!kbItem.exists) return result; - quint32 baseKey = kbItem->qtKey[0]; + quint32 baseKey = kbItem.qtKey[0]; Qt::KeyboardModifiers keyMods = e->modifiers(); if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) { result << int(Qt::Key_Enter + keyMods); @@ -1138,7 +1114,7 @@ QList QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const for (int i = 1; i < NumMods; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; - quint32 key = kbItem->qtKey[i]; + quint32 key = kbItem.qtKey[i]; if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) result << int(key + (keyMods & ~neededMods)); } diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h index 7b3f18a42d..6de255facf 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.h +++ b/src/plugins/platforms/windows/qwindowskeymapper.h @@ -51,7 +51,25 @@ QT_BEGIN_NAMESPACE class QKeyEvent; class QWindow; -struct KeyboardLayoutItem; +/* + \internal + A Windows KeyboardLayoutItem has 8 possible states: + 1. Unmodified + 2. Shift + 3. Control + 4. Control + Shift + 5. Alt + 6. Alt + Shift + 7. Alt + Control + 8. Alt + Control + Shift +*/ +struct KeyboardLayoutItem { + uint dirty : 1; + uint exists : 1; // whether this item has been initialized (by updatePossibleKeyCodes) + quint8 deadkeys; + static const size_t NumQtKeys = 9; + quint32 qtKey[NumQtKeys]; // Can by any Qt::Key_, or unicode character +}; class QWindowsKeyMapper { @@ -87,8 +105,9 @@ private: bool isADeadKey(unsigned int vk_key, unsigned int modifiers); void deleteLayouts(); - KeyboardLayoutItem *keyLayout[256]; QWindow *m_keyGrabber; + static const size_t NumKeyboardLayoutItems = 256; + KeyboardLayoutItem keyLayout[NumKeyboardLayoutItems]; }; enum WindowsNativeModifiers { -- cgit v1.2.3