Forward xkb modifier changes to input method.

Since not all the key are forwarded to input method, any modifier
changes need to be forwarded to input method as long as keyboard grab
is active.
This commit is contained in:
Weng Xuetian 2021-12-13 09:26:01 -08:00 committed by Aleix Pol Gonzalez
parent 11f6292cb5
commit d66be7b99f
4 changed files with 39 additions and 5 deletions

View file

@ -104,6 +104,8 @@ void InputMethod::init()
connect(textInputV2, &TextInputV2Interface::enabledChanged, this, &InputMethod::textInputInterfaceV2EnabledChanged);
connect(textInputV3, &TextInputV3Interface::enabledChanged, this, &InputMethod::textInputInterfaceV3EnabledChanged);
}
connect(input()->keyboard()->xkb(), &Xkb::modifierStateChanged, this, &InputMethod::forwardModifiers);
}
}
@ -484,6 +486,18 @@ void InputMethod::modifiers(quint32 serial, quint32 mods_depressed, quint32 mods
xkb->updateModifiers(mods_depressed, mods_latched, mods_locked, group);
}
void InputMethod::forwardModifiers()
{
auto xkb = input()->keyboard()->xkb();
if (m_keyboardGrab) {
m_keyboardGrab->sendModifiers(waylandServer()->display()->nextSerial(),
xkb->modifierState().depressed,
xkb->modifierState().latched,
xkb->modifierState().locked,
xkb->currentLayout());
}
}
void InputMethod::adoptInputMethodContext()
{
auto inputContext = waylandServer()->inputMethod()->context();
@ -640,6 +654,7 @@ void InputMethod::installKeyboardGrab(KWaylandServer::InputMethodGrabV1 *keyboar
auto xkb = input()->keyboard()->xkb();
m_keyboardGrab = keyboardGrab;
keyboardGrab->sendKeymap(xkb->keymapContents());
forwardModifiers();
}
void InputMethod::updateModifiersMap(const QByteArray &modifiers)

View file

@ -97,6 +97,7 @@ private:
void updateModifiersMap(const QByteArray &modifiers);
bool touchEventTriggered() const;
void forwardModifiers();
struct {
QString text = QString();

View file

@ -330,7 +330,10 @@ void Xkb::updateModifiers(uint32_t modsDepressed, uint32_t modsLatched, uint32_t
if (!m_keymap || !m_state) {
return;
}
xkb_state_update_mask(m_state, modsDepressed, modsLatched, modsLocked, 0, 0, group);
// Avoid to create a infinite loop between input method and compositor.
if (xkb_state_update_mask(m_state, modsDepressed, modsLatched, modsLocked, 0, 0, group) == 0) {
return;
}
updateModifiers();
forwardModifiers();
}
@ -400,10 +403,19 @@ void Xkb::updateModifiers()
Q_EMIT ledsChanged(m_leds);
}
m_currentLayout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
m_modifierState.depressed = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_DEPRESSED));
m_modifierState.latched = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LATCHED));
m_modifierState.locked = xkb_state_serialize_mods(m_state, xkb_state_component(XKB_STATE_MODS_LOCKED));
const uint32_t newLayout = xkb_state_serialize_layout(m_state, XKB_STATE_LAYOUT_EFFECTIVE);
const uint32_t depressed = xkb_state_serialize_mods(m_state, XKB_STATE_MODS_DEPRESSED);
const uint32_t latched = xkb_state_serialize_mods(m_state, XKB_STATE_MODS_LATCHED);
const uint32_t locked = xkb_state_serialize_mods(m_state, XKB_STATE_MODS_LOCKED);
if (newLayout != m_currentLayout || depressed != m_modifierState.depressed || latched != m_modifierState.latched || locked != m_modifierState.locked) {
m_currentLayout = newLayout;
m_modifierState.depressed = depressed;
m_modifierState.latched = latched;
m_modifierState.locked = locked;
Q_EMIT modifierStateChanged();
}
}
void Xkb::forwardModifiers()

View file

@ -81,6 +81,11 @@ public:
quint32 currentLayout() const {
return m_currentLayout;
}
const auto &modifierState() const
{
return m_modifierState;
}
QString layoutName(xkb_layout_index_t index) const;
QString layoutName() const;
QString layoutShortName(int index) const;
@ -96,6 +101,7 @@ public:
Q_SIGNALS:
void ledsChanged(const LEDs &leds);
void modifierStateChanged();
private:
void applyEnvironmentRules(xkb_rule_names &);