From 82538aebe4b22978a6f7735924f5451304c3e2a8 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Mon, 17 Aug 2015 12:36:14 +0200 Subject: iOS: send arrow keys to Qt to handle cursor movement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Controlling cursor position through input methods in Qt is very limited. You cannot e.g move the cursor vertically, or select text that spans several paragraphs. The reason for the latter is that Qt works with input methods on a per-paragraph basis, which effectively locks UIKit to only being able to move the cursor and select text within a single paragraph. Fixing up input methods to support more advanced navigation means changing the whole design (working on a whole document, instead of per paragraph), and is out of scope. Instead we choose to listen for arrow keys and forward them to Qt in the same fashing as we already do for backspace and enter. This will make the iOS port on-par with the other platforms, which also sends control characters like these on the side of IM events. Note that registering shortcuts and overriding default IM navigation behavior will only take effect when a hardware keyboard is connected. Only then will [UIresponder keyCommands] be called from UIKit. Change-Id: I634205e0578447c4aa6e9fdff342ee3b281901ea Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiostextresponder.mm | 65 ++++++++++++++++++++++++++ src/plugins/platforms/ios/qiostheme.mm | 2 + 2 files changed, 67 insertions(+) diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 68364d3c77..d16ad40414 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -328,6 +328,8 @@ QWindowSystemInterface::handleKeyEvent(qApp->focusWindow(), QEvent::KeyRelease, key, modifiers); } +#ifndef QT_NO_SHORTCUT + - (void)cut:(id)sender { Q_UNUSED(sender); @@ -360,6 +362,69 @@ // ------------------------------------------------------------------------- +- (void)keyCommandTriggered:(UIKeyCommand *)keyCommand +{ + Qt::Key key = Qt::Key_unknown; + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + if (keyCommand.input == UIKeyInputLeftArrow) + key = Qt::Key_Left; + else if (keyCommand.input == UIKeyInputRightArrow) + key = Qt::Key_Right; + else if (keyCommand.input == UIKeyInputUpArrow) + key = Qt::Key_Up; + else if (keyCommand.input == UIKeyInputDownArrow) + key = Qt::Key_Down; + else + Q_UNREACHABLE(); + + if (keyCommand.modifierFlags & UIKeyModifierAlternate) + modifiers |= Qt::AltModifier; + if (keyCommand.modifierFlags & UIKeyModifierShift) + modifiers |= Qt::ShiftModifier; + if (keyCommand.modifierFlags & UIKeyModifierCommand) + modifiers |= Qt::ControlModifier; + + [self sendKeyPressRelease:key modifiers:modifiers]; +} + +- (void)addKeyCommandsToArray:(NSMutableArray *)array key:(NSString *)key +{ + SEL s = @selector(keyCommandTriggered:); + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:0 action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierShift action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierAlternate|UIKeyModifierShift action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand action:s]]; + [array addObject:[UIKeyCommand keyCommandWithInput:key modifierFlags:UIKeyModifierCommand|UIKeyModifierShift action:s]]; +} + +- (NSArray *)keyCommands +{ + // Since keyCommands is called for every key + // press/release, we cache the result + static dispatch_once_t once; + static NSMutableArray *array; + + dispatch_once(&once, ^{ + // We let Qt move the cursor around when the arrow keys are being used. This + // is normally implemented through UITextInput, but since IM in Qt have poor + // support for moving the cursor vertically, and even less support for selecting + // text across multiple paragraphs, we do this through key events. + array = [NSMutableArray new]; + [self addKeyCommandsToArray:array key:UIKeyInputUpArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputDownArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputLeftArrow]; + [self addKeyCommandsToArray:array key:UIKeyInputRightArrow]; + }); + + return array; +} + +#endif // QT_NO_SHORTCUT + +// ------------------------------------------------------------------------- + - (void)notifyInputDelegate:(Qt::InputMethodQueries)updatedProperties { // As documented, we should not report textWillChange/textDidChange unless the text diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm index edeabf66dc..bc40069670 100644 --- a/src/plugins/platforms/ios/qiostheme.mm +++ b/src/plugins/platforms/ios/qiostheme.mm @@ -107,6 +107,8 @@ QVariant QIOSTheme::themeHint(ThemeHint hint) const switch (hint) { case QPlatformTheme::StyleNames: return QStringList(QStringLiteral("fusion")); + case KeyboardScheme: + return QVariant(int(MacKeyboardScheme)); default: return QPlatformTheme::themeHint(hint); } -- cgit v1.2.3