iOS: send control keys to Qt, even if IM is enabled

Perhaps dating as far back as 829e421ddc (Qt 5.8), using
the arrow keys on a bluetooth keyboard to navigate the cursor
around in a TextArea/QTextEdit has been broken. Some work
was done to remedy this with 15576c9610 (Qt 6.1) it seems, but
still, using the arrow keys is broken in 5.15, 6.2 and dev.

This patch will ensure that we send control key events, such as
Qt::Key_Up and Qt::Key_Down, to Qt, also when the focus object
accepts Input Methods.

Fixes: QTBUG-101339
Pick-to: 6.4 6.2 5.15
Change-Id: I2d12438a822a607646080ab2edb17de8ea6d337c
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Richard Moe Gustavsen 2022-09-22 12:56:56 +02:00
parent 65c40615d1
commit f7e4987966

View File

@ -615,13 +615,33 @@ inline ulong getTimeStamp(UIEvent *event)
return Qt::Key_unknown;
}
- (bool)processPresses:(NSSet *)presses withType:(QEvent::Type)type {
- (bool)isControlKey:(Qt::Key)key
{
switch (key) {
case Qt::Key_Up:
case Qt::Key_Down:
case Qt::Key_Left:
case Qt::Key_Right:
return true;
default:
break;
}
return false;
}
- (bool)handlePresses:(NSSet<UIPress *> *)presses eventType:(QEvent::Type)type
{
// Presses on Menu button will generate a Menu key event. By default, not handling
// this event will cause the application to return to Headboard (tvOS launcher).
// When handling the event (for example, as a back button), both press and
// release events must be handled accordingly.
if (!qApp->focusWindow())
return false;
bool eventHandled = false;
const bool imEnabled = QIOSInputContext::instance()->inputMethodAccepted();
bool handled = false;
for (UIPress* press in presses) {
Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
if (@available(ios 13.4, *))
@ -630,26 +650,15 @@ inline ulong getTimeStamp(UIEvent *event)
int key = [self mapPressTypeToKey:press withModifiers:qtModifiers text:text];
if (key == Qt::Key_unknown)
continue;
if (QWindowSystemInterface::handleKeyEvent(self.platformWindow->window(), type, key,
qtModifiers, text)) {
handled = true;
}
if (imEnabled && ![self isControlKey:Qt::Key(key)])
continue;
bool keyHandled = QWindowSystemInterface::handleKeyEvent(
self.platformWindow->window(), type, key, qtModifiers, text);
eventHandled = eventHandled || keyHandled;
}
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;
return eventHandled;
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
@ -661,14 +670,14 @@ inline ulong getTimeStamp(UIEvent *event)
- (void)pressesChanged:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyPress])
[super pressesBegan:presses withEvent:event];
[super pressesChanged:presses withEvent:event];
[super pressesChanged:presses withEvent:event];
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event
{
if (![self handlePresses:presses eventType:QEvent::KeyRelease])
[super pressesBegan:presses withEvent:event];
[super pressesEnded:presses withEvent:event];
[super pressesEnded:presses withEvent:event];
}