summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/ios
diff options
context:
space:
mode:
authorAndy Shaw <andy.shaw@qt.io>2020-12-04 15:04:49 +0100
committerAndy Shaw <andy.shaw@qt.io>2021-01-20 12:29:38 +0100
commit15576c961047231a49afda9b9ee0159ba132c0ae (patch)
treed2ff922cd5a3f910471d69380ea12ce99155a212 /src/plugins/platforms/ios
parenta5bb7b3ca510c301baf84e1dd46d5aeeb4986eb2 (diff)
iOS: Handle keyboard events when using an external keyboard
This enables the two possible approaches for handling external keyboard events. While support still exists for before 13.4 then both approaches are needed. This ensures that all external keyboard events are handled as key events and passed on accordingly. Additionally, this accounts for possible shortcuts too, therefore a new function is added to QShortcutMap to aid that. As a result, code has now moved from QCocoaKeyMapper to be part of the gui/platforms/darwin part to make it easier to reuse this code elsewhere. Fixes: QTBUG-85727 Change-Id: I349af43468b03fd8dcb16adba02669974affe154 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
Diffstat (limited to 'src/plugins/platforms/ios')
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h2
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm33
-rw-r--r--src/plugins/platforms/ios/quiview.h1
-rw-r--r--src/plugins/platforms/ios/quiview.mm47
4 files changed, 75 insertions, 8 deletions
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index 7af4c83b48..79fe5ae3c5 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -50,6 +50,8 @@ QT_END_NAMESPACE
- (instancetype)initWithQIOSScreen:(QT_PREPEND_NAMESPACE(QIOSScreen) *)screen;
- (void)updateProperties;
+- (NSArray*)keyCommands;
+- (void)handleShortcut:(UIKeyCommand*)keyCommand;
#ifndef Q_OS_TVOS
@property (nonatomic, assign) UIInterfaceOrientation lockedOrientation;
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index cd4af46ef7..7d994f4394 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -42,12 +42,14 @@
#include <QtCore/qscopedvaluerollback.h>
#include <QtCore/private/qcore_mac_p.h>
+#include <QtGui/private/qapplekeymapper_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
#include <QtGui/QScreen>
#include <QtGui/private/qwindow_p.h>
+#include <QtGui/private/qguiapplication_p.h>
#include "qiosintegration.h"
#include "qiosscreen.h"
@@ -523,5 +525,36 @@
#endif
}
+- (NSArray*)keyCommands
+{
+ // FIXME: If we are on iOS 13.4 or later we can use UIKey instead of doing this
+ // So it should be safe to remove this entire function and handleShortcut() as
+ // a result
+ NSMutableArray<UIKeyCommand *> *keyCommands = nil;
+ QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap;
+ keyCommands = [[NSMutableArray<UIKeyCommand *> alloc] init];
+ const QList<QKeySequence> keys = shortcutMap.keySequences();
+ for (const QKeySequence &seq : keys) {
+ const QString keyString = seq.toString();
+ [keyCommands addObject:[UIKeyCommand
+ keyCommandWithInput:QString(keyString[keyString.length() - 1]).toNSString()
+ modifierFlags:QAppleKeyMapper::toUIKitModifiers(seq[0].keyboardModifiers())
+ action:@selector(handleShortcut:)]];
+ }
+ return keyCommands;
+}
+
+- (void)handleShortcut:(UIKeyCommand *)keyCommand
+{
+ const QString str = QString::fromNSString([keyCommand input]);
+ Qt::KeyboardModifiers qtMods = QAppleKeyMapper::fromUIKitModifiers(keyCommand.modifierFlags);
+ QChar ch = str.isEmpty() ? QChar() : str.at(0);
+ QShortcutMap &shortcutMap = QGuiApplicationPrivate::instance()->shortcutMap;
+ QKeyEvent keyEvent(QEvent::ShortcutOverride, Qt::Key(ch.toUpper().unicode()), qtMods, str);
+ shortcutMap.tryShortcut(&keyEvent);
+}
+
+
+
@end
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index 1ab9481dd6..6a8e5a7707 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -56,6 +56,7 @@ QT_END_NAMESPACE
- (instancetype)initWithQIOSWindow:(QT_PREPEND_NAMESPACE(QIOSWindow) *)window;
- (void)sendUpdatedExposeEvent;
- (BOOL)isActiveWindow;
+- (bool)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type;
@property (nonatomic, assign) QT_PREPEND_NAMESPACE(QIOSWindow) *platformWindow;
@end
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 4c56e03f42..5ca4d5ccc8 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -52,6 +52,7 @@
#include <QtGui/qpointingdevice.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qwindow_p.h>
+#include <QtGui/private/qapplekeymapper_p.h>
#include <qpa/qwindowsysteminterface_p.h>
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
@@ -571,7 +572,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
QWindowSystemInterface::handleTouchCancelEvent(self.platformWindow->window(), ulong(timestamp * 1000), iosIntegration->touchDevice());
}
-- (int)mapPressTypeToKey:(UIPress*)press
+- (int)mapPressTypeToKey:(UIPress*)press withModifiers:(Qt::KeyboardModifiers)qtModifiers
{
switch (press.type) {
case UIPressTypeUpArrow: return Qt::Key_Up;
@@ -582,6 +583,16 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
case UIPressTypeMenu: return Qt::Key_Menu;
case UIPressTypePlayPause: return Qt::Key_MediaTogglePlayPause;
}
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
+ if (@available(ios 13.4, *)) {
+ NSString *charactersIgnoringModifiers = press.key.charactersIgnoringModifiers;
+ Qt::Key key = QAppleKeyMapper::fromUIKitKey(charactersIgnoringModifiers);
+ if (key != Qt::Key_unknown)
+ return key;
+ return QAppleKeyMapper::fromNSString(qtModifiers, press.key.characters,
+ charactersIgnoringModifiers);
+ }
+#endif
return Qt::Key_unknown;
}
@@ -593,32 +604,52 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
bool handled = false;
for (UIPress* press in presses) {
- int key = [self mapPressTypeToKey:press];
+ Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_13_4)
+ if (@available(ios 13.4, *))
+ qtModifiers = QAppleKeyMapper::fromUIKitModifiers(press.key.modifierFlags);
+#endif
+ int key = [self mapPressTypeToKey:press withModifiers:qtModifiers];
if (key == Qt::Key_unknown)
continue;
- if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key, Qt::NoModifier))
+ if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key, qtModifiers))
handled = true;
}
return handled;
}
+- (BOOL)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
+{
+ bool handlePress = false;
+ if (qApp->focusWindow()) {
+ QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
+ if (qApp->focusObject() && QCoreApplication::sendEvent(qApp->focusObject(), &queryEvent))
+ handlePress = queryEvent.value(Qt::ImEnabled).toBool();
+ if (!handlePress && [self processPresses:presses withType:type])
+ return true;
+ }
+ return false;
+}
+
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
- if (![self processPresses:presses withType:QEvent::KeyPress])
+ if (![self handlePresses:presses eventType:QEvent::KeyPress])
[super pressesBegan:presses withEvent:event];
}
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
- if (![self processPresses:presses withType:QEvent::KeyPress])
- [super pressesChanged:presses withEvent:event];
+ if (![self handlePresses:presses eventType:QEvent::KeyPress])
+ [super pressesBegan:presses withEvent:event];
+ [super pressesChanged:presses withEvent:event];
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
- if (![self processPresses:presses withType:QEvent::KeyRelease])
- [super pressesEnded:presses withEvent:event];
+ if (![self handlePresses:presses eventType:QEvent::KeyRelease])
+ [super pressesBegan:presses withEvent:event];
+ [super pressesEnded:presses withEvent:event];
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender