ibus: Return correct scan code to windows
authorTakao Fujiwara <takao.fujiwara1@gmail.com>
Tue, 25 Aug 2015 05:54:31 +0000 (14:54 +0900)
committerFriedemann Kleint <Friedemann.Kleint@theqtcompany.com>
Tue, 25 Aug 2015 19:41:46 +0000 (19:41 +0000)
ibus keycode is qt scancode - 8 and needs to be returned to app windows
as the right value.
Use QWindowSystemInterface::handleExtendedKeyEvent() instead of
QCoreApplication::sendEvent() in qtbase 5.6 to follow
QXcbKeyboard::handleKeyEvent().
Also qApp->focusObject() returns QMdiChild which is a QWidget and
that is not a QWindow.

Task-number: QTBUG-47833
Change-Id: Ie634a86d7790d8093cfca2dc8666f726844ae654
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp
src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h

index 4a276dc834214478be3ac74f41d783f14296d5ea..27fca7c6ed7c5ce37903cc15a7159780ef73054d 100644 (file)
@@ -301,12 +301,12 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
     quint32 sym = keyEvent->nativeVirtualKey();
     quint32 code = keyEvent->nativeScanCode();
     quint32 state = keyEvent->nativeModifiers();
+    quint32 ibusState = state;
 
     if (keyEvent->type() != QEvent::KeyPress)
-        state |= IBUS_RELEASE_MASK;
+        ibusState |= IBUS_RELEASE_MASK;
 
-    code -= 8; // ###
-    QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code, state);
+    QDBusPendingReply<bool> reply = d->context->ProcessKeyEvent(sym, code - 8, ibusState);
 
     if (m_eventFilterUseSynchronousMode || reply.isFinished()) {
         bool retval = reply.value();
@@ -315,17 +315,36 @@ bool QIBusPlatformInputContext::filterEvent(const QEvent *event)
     }
 
     Qt::KeyboardModifiers modifiers = keyEvent->modifiers();
+    const int qtcode = keyEvent->key();
+
+    // From QKeyEvent::modifiers()
+    switch (qtcode) {
+    case Qt::Key_Shift:
+        modifiers ^= Qt::ShiftModifier;
+        break;
+    case Qt::Key_Control:
+        modifiers ^= Qt::ControlModifier;
+        break;
+    case Qt::Key_Alt:
+        modifiers ^= Qt::AltModifier;
+        break;
+    case Qt::Key_Meta:
+        modifiers ^= Qt::MetaModifier;
+        break;
+    case Qt::Key_AltGr:
+        modifiers ^= Qt::GroupSwitchModifier;
+        break;
+    }
 
     QVariantList args;
     args << QVariant::fromValue(keyEvent->timestamp());
     args << QVariant::fromValue(static_cast<uint>(keyEvent->type()));
-    args << QVariant::fromValue(keyEvent->key());
+    args << QVariant::fromValue(qtcode);
     args << QVariant::fromValue(code) << QVariant::fromValue(sym) << QVariant::fromValue(state);
     args << QVariant::fromValue(keyEvent->text());
     args << QVariant::fromValue(keyEvent->isAutoRepeat());
-    args << QVariant::fromValue(keyEvent->count());
 
-    QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, qApp->focusObject(), modifiers, args);
+    QIBusFilterEventWatcher *watcher = new QIBusFilterEventWatcher(reply, this, QGuiApplication::focusWindow(), modifiers, args);
     QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, &QIBusPlatformInputContext::filterEventFinished);
 
     return true;
@@ -343,9 +362,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
 
     // Use watcher's window instead of the current focused window
     // since there is a time lag until filterEventFinished() returns.
-    QObject *input = watcher->input();
+    QWindow *window = watcher->window();
 
-    if (!input) {
+    if (!window) {
         call->deleteLater();
         return;
     }
@@ -360,13 +379,11 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
     const quint32 state = args.at(5).toUInt();
     const QString string = args.at(6).toString();
     const bool isAutoRepeat = args.at(7).toBool();
-    const int count = args.at(8).toInt();
 
     // copied from QXcbKeyboard::handleKeyEvent()
     bool retval = reply.value();
     qCDebug(qtQpaInputMethods) << "filterEventFinished return" << code << sym << state << retval;
     if (!retval) {
-        QWindow *window = dynamic_cast<QWindow *>(input);
         if (type == QEvent::KeyPress && qtcode == Qt::Key_Menu
             && window != NULL) {
             const QPoint globalPos = window->screen()->handle()->cursor()->pos();
@@ -374,10 +391,9 @@ void QIBusPlatformInputContext::filterEventFinished(QDBusPendingCallWatcher *cal
             QWindowSystemInterface::handleContextMenuEvent(window, false, pos,
                                                            globalPos, modifiers);
         }
-        QKeyEvent event(type, qtcode, modifiers, code, sym,
-                        state, string, isAutoRepeat, count);
-        event.setTimestamp(time);
-        QCoreApplication::sendEvent(input, &event);
+        QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
+                                                       code, sym, state, string, isAutoRepeat);
+
     }
     call->deleteLater();
 }
index 91f15ea1595cf9797449269ae5e73a18214fec74..127db7df8bdfae7b0e30bf36a5412bea8648a86c 100644 (file)
@@ -38,6 +38,7 @@
 #include <QtCore/qpointer.h>
 #include <QtDBus/qdbuspendingreply.h>
 #include <QLoggingCategory>
+#include <QWindow>
 
 QT_BEGIN_NAMESPACE
 
@@ -51,23 +52,23 @@ class QIBusFilterEventWatcher: public QDBusPendingCallWatcher
 public:
     explicit QIBusFilterEventWatcher(const QDBusPendingCall &call,
                                      QObject *parent = 0,
-                                     QObject *input = 0,
+                                     QWindow *window = 0,
                                      const Qt::KeyboardModifiers modifiers = 0,
                                      const QVariantList arguments = QVariantList())
     : QDBusPendingCallWatcher(call, parent)
-    , m_input(input)
+    , m_window(window)
     , m_modifiers(modifiers)
     , m_arguments(arguments)
     {}
     ~QIBusFilterEventWatcher()
     {}
 
-    inline QObject *input() const { return m_input; }
+    inline QWindow *window() const { return m_window; }
     inline const Qt::KeyboardModifiers modifiers() const { return m_modifiers; }
     inline const QVariantList arguments() const { return m_arguments; }
 
 private:
-    QPointer<QObject> m_input;
+    QPointer<QWindow> m_window;
     const Qt::KeyboardModifiers m_modifiers;
     const QVariantList m_arguments;
 };