From 155d44016d0cb11332c454db73d59030cdbd7b13 Mon Sep 17 00:00:00 2001 From: Sungyoon Cho Date: Tue, 10 Sep 2024 22:49:10 +0900 Subject: [PATCH] textinput: handle IME resetting (#7731) --- src/managers/input/InputMethodRelay.cpp | 10 ++++++---- src/managers/input/InputMethodRelay.hpp | 4 ++-- src/managers/input/TextInput.cpp | 24 +++++++++++++++++------- src/managers/input/TextInput.hpp | 2 ++ src/protocols/TextInputV1.cpp | 1 + src/protocols/TextInputV1.hpp | 1 + src/protocols/TextInputV3.cpp | 19 ++++++++++++++----- src/protocols/TextInputV3.hpp | 7 ++++++- 8 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/managers/input/InputMethodRelay.cpp b/src/managers/input/InputMethodRelay.cpp index 1608e123..5ef7f331 100644 --- a/src/managers/input/InputMethodRelay.cpp +++ b/src/managers/input/InputMethodRelay.cpp @@ -106,20 +106,22 @@ void CInputMethodRelay::updateAllPopups() { } } -void CInputMethodRelay::activateIME(CTextInput* pInput) { +void CInputMethodRelay::activateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->activate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } -void CInputMethodRelay::deactivateIME(CTextInput* pInput) { +void CInputMethodRelay::deactivateIME(CTextInput* pInput, bool shouldCommit) { if (m_pIME.expired()) return; m_pIME->deactivate(); - commitIMEState(pInput); + if (shouldCommit) + commitIMEState(pInput); } void CInputMethodRelay::commitIMEState(CTextInput* pInput) { diff --git a/src/managers/input/InputMethodRelay.hpp b/src/managers/input/InputMethodRelay.hpp index 5ecc11a2..3d706563 100644 --- a/src/managers/input/InputMethodRelay.hpp +++ b/src/managers/input/InputMethodRelay.hpp @@ -21,8 +21,8 @@ class CInputMethodRelay { void onNewTextInput(WP tiv3); void onNewTextInput(WP pTIV1); - void activateIME(CTextInput* pInput); - void deactivateIME(CTextInput* pInput); + void activateIME(CTextInput* pInput, bool shouldCommit = true); + void deactivateIME(CTextInput* pInput, bool shouldCommit = true); void commitIMEState(CTextInput* pInput); void removeTextInput(CTextInput* pInput); diff --git a/src/managers/input/TextInput.cpp b/src/managers/input/TextInput.cpp index d488f173..2769fad0 100644 --- a/src/managers/input/TextInput.cpp +++ b/src/managers/input/TextInput.cpp @@ -22,6 +22,7 @@ void CTextInput::initCallbacks() { listeners.enable = INPUT->events.enable.registerListener([this](std::any p) { onEnabled(); }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -41,6 +42,7 @@ void CTextInput::initCallbacks() { }); listeners.disable = INPUT->events.disable.registerListener([this](std::any p) { onDisabled(); }); listeners.commit = INPUT->events.onCommit.registerListener([this](std::any p) { onCommit(); }); + listeners.reset = INPUT->events.reset.registerListener([this](std::any p) { onReset(); }); listeners.destroy = INPUT->events.destroy.registerListener([this](std::any p) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); @@ -93,13 +95,21 @@ void CTextInput::onDisabled() { g_pInputManager->m_sIMERelay.deactivateIME(this); } +void CTextInput::onReset() { + if (g_pInputManager->m_sIMERelay.m_pIME.expired()) + return; + + g_pInputManager->m_sIMERelay.deactivateIME(this, false); + g_pInputManager->m_sIMERelay.activateIME(this); +} + void CTextInput::onCommit() { if (g_pInputManager->m_sIMERelay.m_pIME.expired()) { // Debug::log(WARN, "Committing TextInput on no IME!"); return; } - if (!(isV3() ? pV3Input->current.enabled : pV1Input->active)) { + if (!(isV3() ? pV3Input->current.enabled.value : pV1Input->active)) { Debug::log(WARN, "Disabled TextInput commit?"); return; } @@ -128,8 +138,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -144,8 +154,8 @@ void CTextInput::setFocusedSurface(SP pSurface) { listeners.surfaceUnmap.reset(); listeners.surfaceDestroy.reset(); - if (isV3() && !pV3Input.expired() && pV3Input->current.enabled) - pV3Input->current.enabled = false; + if (isV3() && !pV3Input.expired() && pV3Input->current.enabled.value) + pV3Input->current.enabled.value = false; if (!g_pInputManager->m_sIMERelay.getFocusedTextInput()) g_pInputManager->m_sIMERelay.deactivateIME(this); @@ -194,8 +204,8 @@ void CTextInput::leave() { if (isV3()) { pV3Input->leave(focusedSurface()); - if (pV3Input->current.enabled) { - pV3Input->current.enabled = false; + if (pV3Input->current.enabled.value) { + pV3Input->current.enabled.value = false; onDisabled(); } } else diff --git a/src/managers/input/TextInput.hpp b/src/managers/input/TextInput.hpp index 0f69866e..f920adc7 100644 --- a/src/managers/input/TextInput.hpp +++ b/src/managers/input/TextInput.hpp @@ -29,6 +29,7 @@ class CTextInput { void onEnabled(SP surfV1 = nullptr); void onDisabled(); void onCommit(); + void onReset(); bool hasCursorRectangle(); CBox cursorBox(); @@ -47,6 +48,7 @@ class CTextInput { struct { CHyprSignalListener enable; CHyprSignalListener disable; + CHyprSignalListener reset; CHyprSignalListener commit; CHyprSignalListener destroy; CHyprSignalListener surfaceUnmap; diff --git a/src/protocols/TextInputV1.cpp b/src/protocols/TextInputV1.cpp index f25f5aca..dad74b53 100644 --- a/src/protocols/TextInputV1.cpp +++ b/src/protocols/TextInputV1.cpp @@ -31,6 +31,7 @@ CTextInputV1::CTextInputV1(SP resource_) : resource(resource_) resource->setReset([this](CZwpTextInputV1* pMgr) { pendingSurrounding.isPending = false; pendingContentType.isPending = false; + events.reset.emit(); }); resource->setSetSurroundingText( diff --git a/src/protocols/TextInputV1.hpp b/src/protocols/TextInputV1.hpp index c85a1f31..9bee452c 100644 --- a/src/protocols/TextInputV1.hpp +++ b/src/protocols/TextInputV1.hpp @@ -37,6 +37,7 @@ class CTextInputV1 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; diff --git a/src/protocols/TextInputV3.cpp b/src/protocols/TextInputV3.cpp index 42dc659e..30374104 100644 --- a/src/protocols/TextInputV3.cpp +++ b/src/protocols/TextInputV3.cpp @@ -19,17 +19,22 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setOnDestroy([this](CZwpTextInputV3* r) { PROTO::textInputV3->destroyTextInput(this); }); resource->setCommit([this](CZwpTextInputV3* r) { - bool wasEnabled = current.enabled; + bool wasEnabled = current.enabled.value; current = pending; serial++; - if (wasEnabled && !current.enabled) + if (wasEnabled && !current.enabled.value) events.disable.emit(); - else if (!wasEnabled && current.enabled) + else if (!wasEnabled && current.enabled.value) events.enable.emit(); + else if (current.enabled.value && current.enabled.isEnablePending && current.enabled.isDisablePending) + events.reset.emit(); else events.onCommit.emit(); + + pending.enabled.isEnablePending = false; + pending.enabled.isDisablePending = false; }); resource->setSetSurroundingText([this](CZwpTextInputV3* r, const char* text, int32_t cursor, int32_t anchor) { @@ -54,10 +59,14 @@ CTextInputV3::CTextInputV3(SP resource_) : resource(resource_) resource->setEnable([this](CZwpTextInputV3* r) { pending.reset(); - pending.enabled = true; + pending.enabled.value = true; + pending.enabled.isEnablePending = true; }); - resource->setDisable([this](CZwpTextInputV3* r) { pending.enabled = false; }); + resource->setDisable([this](CZwpTextInputV3* r) { + pending.enabled.value = false; + pending.enabled.isDisablePending = true; + }); } CTextInputV3::~CTextInputV3() { diff --git a/src/protocols/TextInputV3.hpp b/src/protocols/TextInputV3.hpp index 9f6284dc..ba8b75e6 100644 --- a/src/protocols/TextInputV3.hpp +++ b/src/protocols/TextInputV3.hpp @@ -31,6 +31,7 @@ class CTextInputV3 { CSignal onCommit; CSignal enable; CSignal disable; + CSignal reset; CSignal destroy; } events; @@ -53,7 +54,11 @@ class CTextInputV3 { CBox cursorBox; } box; - bool enabled = false; + struct { + bool isEnablePending = false; + bool isDisablePending = false; + bool value = false; + } enabled; zwpTextInputV3ChangeCause cause = ZWP_TEXT_INPUT_V3_CHANGE_CAUSE_INPUT_METHOD;