summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2018-08-01 12:40:30 +0200
committerJüri Valdmann <juri.valdmann@qt.io>2018-08-27 14:30:17 +0000
commit44b2bcef7e7774de6f1a7e9a6b2d28047cf6b7a9 (patch)
tree39db844c74673189a5bc5d923a03e5134a61951d /src/core
parent088df145283d32d671f2c7d58193b684cc0d4e1f (diff)
WebEventFactory: Use QKeyEvent::key() if QKeyEvent::text() is empty
Fixes missing dom_key issue when ControlModifier is used on Linux and macOS. Task-number: QTBUG-69442 Change-Id: Icd644d019494fd3c95269b42c71efd747507a3ea Reviewed-by: Kai Koehne <kai.koehne@qt.io>
Diffstat (limited to 'src/core')
-rw-r--r--src/core/web_event_factory.cpp65
1 files changed, 52 insertions, 13 deletions
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index e20ad9da6..6358f6830 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -153,6 +153,38 @@ static Qt::KeyboardModifiers qtModifiersForEvent(const QInputEvent *ev)
return modifiers;
}
+// QKeyEvent::text() has some limits that we need to work around.
+//
+// On Linux, the Control modifier transformation is applied [1]. For example,
+// pressing Ctrl+@ generates the text "\u0000". We would like "@" instead.
+//
+// [1]: https://www.x.org/releases/current/doc/kbproto/xkbproto.html#Interpreting_the_Control_Modifier
+//
+// On macOS, if the Control modifier is used, then no text is generated at all.
+// We need some text.
+//
+// The workaround is to use QKeyEvent::key() instead, when needed. Contrary to
+// the documentation, QKeyEvent::key() is not at all limited to the values
+// listed in the Qt::Key enum: it can actually contain any Unicode codepoint.
+// The only drawback is that letters are always upper cased.
+static QString qtTextForKeyEvent(const QKeyEvent *ev, int qtKey, Qt::KeyboardModifiers qtModifiers)
+{
+ QString text = ev->text();
+
+ if ((qtModifiers & Qt::ControlModifier) && keyboardDriver() == KeyboardDriver::Xkb)
+ text.clear();
+
+ if (!text.isEmpty() || qtKey >= Qt::Key_Escape)
+ return text;
+
+ QChar ch(qtKey);
+ if (!(qtModifiers & Qt::ShiftModifier)) // No way to check for caps lock
+ ch = ch.toLower();
+
+ text.append(ch);
+ return text;
+}
+
// The 'native key code' in Chromium refers to
//
// - On Windows: the Windows OEM scancode.
@@ -177,11 +209,11 @@ static quint32 nativeKeyCodeForKeyEvent(const QKeyEvent *ev)
#endif
}
-static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad)
+static int windowsKeyCodeForQtKey(int qtKey, bool isKeypad)
{
// Determine wheter the event comes from the keypad
if (isKeypad) {
- switch (keycode) {
+ switch (qtKey) {
case Qt::Key_0:
return VK_NUMPAD0; // (60) Numeric keypad 0 key
case Qt::Key_1:
@@ -248,7 +280,7 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad)
}
} else {
- switch (keycode) {
+ switch (qtKey) {
case Qt::Key_Backspace:
return VK_BACK; // (08) BACKSPACE key
case Qt::Key_Backtab:
@@ -741,12 +773,10 @@ static int windowsKeyCodeForKeyEvent(unsigned int keycode, bool isKeypad)
* - ui::DomKey::VIDEO_MODE_NEXT
* - ui::DomKey::WINK
*/
-static ui::DomKey getDomKeyFromQKeyEvent(QKeyEvent *ev)
+static ui::DomKey domKeyForQtKey(int qtKey)
{
- if (!ev->text().isEmpty())
- return ui::DomKey::FromCharacter(ev->text().toUcs4().first());
-
- switch (qtKeyForKeyEvent(ev)) {
+ Q_ASSERT(qtKey >= Qt::Key_Escape);
+ switch (qtKey) {
case Qt::Key_Backspace:
return ui::DomKey::BACKSPACE;
case Qt::Key_Tab:
@@ -1456,9 +1486,17 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e
webKitEvent.SetModifiers(modifiersForEvent(ev));
webKitEvent.SetType(webEventTypeForEvent(ev));
+ int qtKey = qtKeyForKeyEvent(ev);
+ Qt::KeyboardModifiers qtModifiers = qtModifiersForEvent(ev);
+ QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers);
+
webKitEvent.native_key_code = nativeKeyCodeForKeyEvent(ev);
- webKitEvent.windows_key_code = windowsKeyCodeForKeyEvent(qtKeyForKeyEvent(ev), ev->modifiers() & Qt::KeypadModifier);
- webKitEvent.dom_key = getDomKeyFromQKeyEvent(ev);
+ webKitEvent.windows_key_code = windowsKeyCodeForQtKey(qtKey, qtModifiers & Qt::KeypadModifier);
+
+ if (qtKey >= Qt::Key_Escape)
+ webKitEvent.dom_key = domKeyForQtKey(qtKey);
+ else if (!qtText.isEmpty())
+ webKitEvent.dom_key = ui::DomKey::FromCharacter(qtText.toUcs4().first());
// The dom_code field should contain the USB keycode of the *physical* key
// that was pressed. Physical meaning independent of layout and modifiers.
@@ -1474,9 +1512,10 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e
webKitEvent.dom_code = static_cast<int>(
ui::UsLayoutKeyboardCodeToDomCode(static_cast<ui::KeyboardCode>(webKitEvent.windows_key_code)));
- const ushort* text = ev->text().utf16();
- memcpy(&webKitEvent.text, text, std::min(sizeof(webKitEvent.text), size_t(ev->text().length() * 2)));
- memcpy(&webKitEvent.unmodified_text, text, std::min(sizeof(webKitEvent.unmodified_text), size_t(ev->text().length() * 2)));
+ const ushort* text = qtText.utf16();
+ size_t textSize = std::min(sizeof(webKitEvent.text), size_t(qtText.length() * 2));
+ memcpy(&webKitEvent.text, text, textSize);
+ memcpy(&webKitEvent.unmodified_text, text, textSize);
if (webKitEvent.windows_key_code == VK_RETURN) {
// This is the same behavior as GTK: