Move input keyboard filter to be just before the key is sent to application.

Features like global shortcuts should be handled before the input
method.
This commit is contained in:
Weng Xuetian 2021-12-13 09:23:23 -08:00 committed by Aleix Pol Gonzalez
parent 9e68357ce9
commit 11f6292cb5
3 changed files with 28 additions and 22 deletions

View file

@ -18,6 +18,7 @@
#include "input_event.h"
#include "input_event_spy.h"
#include "inputbackend.h"
#include "inputmethod.h"
#include "keyboard_input.h"
#include "main.h"
#include "pointer_input.h"
@ -44,6 +45,7 @@
#include <KGlobalAccel>
#include <KLocalizedString>
#include <KWaylandServer/display.h>
#include <KWaylandServer/inputmethod_v1_interface.h>
#include <KWaylandServer/seat_interface.h>
#include <KWaylandServer/shmclientbuffer.h>
#include <KWaylandServer/surface_interface.h>
@ -1487,6 +1489,23 @@ public:
}
};
class InputKeyboardFilter : public InputEventFilter
{
public:
bool keyEvent(QKeyEvent *event) override
{
if (auto keyboardGrab = InputMethod::self()->keyboardGrab()) {
if (event->isAutoRepeat()) {
return true;
}
auto newState = event->type() == QEvent::KeyPress ? KWaylandServer::KeyboardKeyState::Pressed : KWaylandServer::KeyboardKeyState::Released;
keyboardGrab->sendKey(waylandServer()->display()->nextSerial(), event->timestamp(), event->nativeScanCode(), newState);
return true;
}
return false;
}
};
/**
* The remaining default input filter which forwards events to other windows
*/
@ -2450,6 +2469,7 @@ void InputRedirection::setupInputFilters()
installInputEventFilter(new DecorationEventFilter);
installInputEventFilter(new WindowActionInputFilter);
installInputEventFilter(new InternalWindowEventFilter);
installInputEventFilter(new InputKeyboardFilter);
installInputEventFilter(new ForwardInputFilter);
installInputEventFilter(new TabletInputFilter);
}

View file

@ -630,33 +630,16 @@ bool InputMethod::isActive() const
return waylandServer()->inputMethod()->context();
}
class InputKeyboardFilter : public InputEventFilter {
public:
InputKeyboardFilter(KWaylandServer::InputMethodGrabV1 *grab)
: m_keyboardGrab(grab)
{
}
bool keyEvent(QKeyEvent *event) override {
if (event->isAutoRepeat()) {
return true;
}
auto newState = event->type() == QEvent::KeyPress ? KWaylandServer::KeyboardKeyState::Pressed : KWaylandServer::KeyboardKeyState::Released;
m_keyboardGrab->sendKey(waylandServer()->display()->nextSerial(), event->timestamp(), event->nativeScanCode(), newState);
return true;
}
InputMethodGrabV1 *const m_keyboardGrab;
};
KWaylandServer::InputMethodGrabV1 *InputMethod::keyboardGrab()
{
return isActive() ? m_keyboardGrab : nullptr;
}
void InputMethod::installKeyboardGrab(KWaylandServer::InputMethodGrabV1 *keyboardGrab)
{
auto xkb = input()->keyboard()->xkb();
auto filter = new InputKeyboardFilter(keyboardGrab);
m_keyboardGrab = keyboardGrab;
keyboardGrab->sendKeymap(xkb->keymapContents());
input()->prependInputEventFilter(filter);
connect(keyboardGrab, &QObject::destroyed, input(), [filter] {
input()->uninstallInputEventFilter(filter);
});
}
void InputMethod::updateModifiersMap(const QByteArray &modifiers)

View file

@ -57,6 +57,8 @@ public:
void setPanel(InputPanelV1Client* client);
void setInputMethodCommand(const QString &path);
KWaylandServer::InputMethodGrabV1 *keyboardGrab();
Q_SIGNALS:
void activeChanged(bool active);
void enabledChanged(bool enabled);
@ -106,6 +108,7 @@ private:
quint32 m_serial = 0;
QPointer<InputPanelV1Client> m_inputClient;
QPointer<AbstractClient> m_trackedClient;
QPointer<KWaylandServer::InputMethodGrabV1> m_keyboardGrab;
QProcess *m_inputMethodProcess = nullptr;
QTimer m_inputMethodCrashTimer;