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:
@@ -14,9 +14,9 @@ void KWinInputMethodGlobal::zwp_input_method_v1_activate(::zwp_input_method_cont
|
|||||||
Q_EMIT activated(context);
|
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)
|
KWinInputMethod::KWinInputMethod(QObject *parent)
|
||||||
@@ -87,13 +87,20 @@ void KWinInputMethod::setKeyPressed(quint32 keysym, bool pressed)
|
|||||||
|
|
||||||
void KWinInputMethod::activate(::zwp_input_method_context_v1 *context)
|
void KWinInputMethod::activate(::zwp_input_method_context_v1 *context)
|
||||||
{
|
{
|
||||||
|
m_previous = std::move(m_context);
|
||||||
m_context = std::make_unique<KWinInputContext>(context);
|
m_context = std::make_unique<KWinInputContext>(context);
|
||||||
connect(m_context.get(), &KWinInputContext::contextChanged, this, &TextBackend::contextChanged);
|
connect(m_context.get(), &KWinInputContext::contextChanged, this, &TextBackend::contextChanged);
|
||||||
Q_EMIT activeChanged();
|
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();
|
m_context.reset();
|
||||||
Q_EMIT activeChanged();
|
Q_EMIT activeChanged();
|
||||||
Q_EMIT contextChanged();
|
Q_EMIT contextChanged();
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public:
|
|||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void activated(::zwp_input_method_context_v1 *context);
|
void activated(::zwp_input_method_context_v1 *context);
|
||||||
void deactivated();
|
void deactivated(::zwp_input_method_context_v1 *context);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void zwp_input_method_v1_activate(::zwp_input_method_context_v1 *context) override;
|
void zwp_input_method_v1_activate(::zwp_input_method_context_v1 *context) override;
|
||||||
@@ -57,9 +57,11 @@ Q_SIGNALS:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void activate(::zwp_input_method_context_v1 *context);
|
void activate(::zwp_input_method_context_v1 *context);
|
||||||
void deactivate();
|
void deactivate(::zwp_input_method_context_v1 *context);
|
||||||
|
|
||||||
KWinInputMethodGlobal m_global;
|
KWinInputMethodGlobal m_global;
|
||||||
KWinFakeInput m_fakeInput;
|
KWinFakeInput m_fakeInput;
|
||||||
std::unique_ptr<KWinInputContext> m_context;
|
std::unique_ptr<KWinInputContext> m_context;
|
||||||
|
// Replaced by an activate before KWin deactivated it; kept until it does.
|
||||||
|
std::unique_ptr<KWinInputContext> m_previous;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ public:
|
|||||||
virtual void setKeyPressed(quint32 keysym, bool pressed) = 0;
|
virtual void setKeyPressed(quint32 keysym, bool pressed) = 0;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
// Also when focus moves straight from one field to another.
|
||||||
void activeChanged();
|
void activeChanged();
|
||||||
void contextChanged();
|
void contextChanged();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
void VisibilityController::setFieldActive(bool active)
|
void VisibilityController::setFieldActive(bool active)
|
||||||
{
|
{
|
||||||
if (active == m_fieldActive)
|
|
||||||
return;
|
|
||||||
m_fieldActive = active;
|
m_fieldActive = active;
|
||||||
m_override.reset();
|
m_override.reset();
|
||||||
update();
|
update();
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
// - while a text field is focused
|
// - while a text field is focused
|
||||||
// - always, if the user wants it (to type into any window) or when running
|
// - always, if the user wants it (to type into any window) or when running
|
||||||
// standalone (no input-method connection)
|
// 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
|
class VisibilityController : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -17,6 +18,7 @@ public:
|
|||||||
|
|
||||||
bool isVisible() const { return m_visible; }
|
bool isVisible() const { return m_visible; }
|
||||||
|
|
||||||
|
// Called on every focus change, even when a field follows a field.
|
||||||
void setFieldActive(bool active);
|
void setFieldActive(bool active);
|
||||||
void setStandalone(bool standalone);
|
void setStandalone(bool standalone);
|
||||||
void setAlwaysVisible(bool always);
|
void setAlwaysVisible(bool always);
|
||||||
|
|||||||
@@ -27,6 +27,15 @@ private Q_SLOTS:
|
|||||||
QVERIFY(v.isVisible());
|
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()
|
void alwaysVisibleShowsWithoutField()
|
||||||
{
|
{
|
||||||
VisibilityController v;
|
VisibilityController v;
|
||||||
|
|||||||
Reference in New Issue
Block a user