Track input-method contexts by identity

- deactivate only drops the context it names; one replaced by an activate
  is kept until KWin deactivates it
- Moving focus straight from one field to another ends a manual hide

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-15 10:13:27 +02:00
co-authored by Claude Opus 5.5
parent d44aab7772
commit 139a845151
6 changed files with 27 additions and 8 deletions
+10 -3
View File
@@ -14,9 +14,9 @@ void KWinInputMethodGlobal::zwp_input_method_v1_activate(::zwp_input_method_cont
Q_EMIT activated(context);
}
void KWinInputMethodGlobal::zwp_input_method_v1_deactivate(::zwp_input_method_context_v1 *)
void KWinInputMethodGlobal::zwp_input_method_v1_deactivate(::zwp_input_method_context_v1 *context)
{
Q_EMIT deactivated();
Q_EMIT deactivated(context);
}
KWinInputMethod::KWinInputMethod(QObject *parent)
@@ -87,13 +87,20 @@ void KWinInputMethod::setKeyPressed(quint32 keysym, bool pressed)
void KWinInputMethod::activate(::zwp_input_method_context_v1 *context)
{
m_previous = std::move(m_context);
m_context = std::make_unique<KWinInputContext>(context);
connect(m_context.get(), &KWinInputContext::contextChanged, this, &TextBackend::contextChanged);
Q_EMIT activeChanged();
}
void KWinInputMethod::deactivate()
void KWinInputMethod::deactivate(::zwp_input_method_context_v1 *context)
{
if (m_previous && m_previous->object() == context) {
m_previous.reset();
return;
}
if (!m_context || m_context->object() != context)
return;
m_context.reset();
Q_EMIT activeChanged();
Q_EMIT contextChanged();
+4 -2
View File
@@ -22,7 +22,7 @@ public:
Q_SIGNALS:
void activated(::zwp_input_method_context_v1 *context);
void deactivated();
void deactivated(::zwp_input_method_context_v1 *context);
protected:
void zwp_input_method_v1_activate(::zwp_input_method_context_v1 *context) override;
@@ -57,9 +57,11 @@ Q_SIGNALS:
private:
void activate(::zwp_input_method_context_v1 *context);
void deactivate();
void deactivate(::zwp_input_method_context_v1 *context);
KWinInputMethodGlobal m_global;
KWinFakeInput m_fakeInput;
std::unique_ptr<KWinInputContext> m_context;
// Replaced by an activate before KWin deactivated it; kept until it does.
std::unique_ptr<KWinInputContext> m_previous;
};
+1
View File
@@ -34,6 +34,7 @@ public:
virtual void setKeyPressed(quint32 keysym, bool pressed) = 0;
Q_SIGNALS:
// Also when focus moves straight from one field to another.
void activeChanged();
void contextChanged();
};
-2
View File
@@ -2,8 +2,6 @@
void VisibilityController::setFieldActive(bool active)
{
if (active == m_fieldActive)
return;
m_fieldActive = active;
m_override.reset();
update();
+3 -1
View File
@@ -7,7 +7,8 @@
// - while a text field is focused
// - always, if the user wants it (to type into any window) or when running
// standalone (no input-method connection)
// - show()/hide()/toggle() override that until the focus changes
// - show()/hide()/toggle() override that until the focus changes, also
// from one field straight to another
class VisibilityController : public QObject
{
Q_OBJECT
@@ -17,6 +18,7 @@ public:
bool isVisible() const { return m_visible; }
// Called on every focus change, even when a field follows a field.
void setFieldActive(bool active);
void setStandalone(bool standalone);
void setAlwaysVisible(bool always);
+9
View File
@@ -27,6 +27,15 @@ private Q_SLOTS:
QVERIFY(v.isVisible());
}
void dismissEndsWhenAnotherFieldIsFocused()
{
VisibilityController v;
v.setFieldActive(true);
v.hide();
v.setFieldActive(true); // activated straight from one field to the next
QVERIFY(v.isVisible());
}
void alwaysVisibleShowsWithoutField()
{
VisibilityController v;