iOS: send arrow keys to Qt to handle cursor movement

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ø <tor.arne.vestbo@theqtcompany.com>
This commit is contained in:
Richard Moe Gustavsen 2015-08-17 12:36:14 +02:00
parent 06be9f026f
commit 82538aebe4
2 changed files with 67 additions and 0 deletions

View File

@ -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

View File

@ -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);
}