From 006ee8b87abcd0b79f0e1cb387e255ff2f65ff7a Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Wed, 7 Sep 2022 00:56:19 +0200 Subject: [PATCH] inputmethod: Allow forcing the display of the input method This makes it possible to show the input method when using a client that doesn't support Wayland input methods (e.g. Xwayland). This adds 2 dbus API entry points: - activeClientSupported property: That tells us if the current client doesn't support text-input-v* - forceActivate method: forces the activation of the input method. This configures the input method in a state that we can use to forward the input method's keystrokes to the client, emulating a hardware keyboard. BUG: 4399911 --- src/inputmethod.cpp | 23 ++++++++++++++++++++++- src/inputmethod.h | 4 ++++ src/virtualkeyboard_dbus.cpp | 10 ++++++++++ src/virtualkeyboard_dbus.h | 4 ++++ src/wayland/textinput_v2_interface.cpp | 4 ++++ src/wayland/textinput_v2_interface.h | 6 ++++++ src/wayland/textinput_v3_interface.cpp | 4 ++++ src/wayland/textinput_v3_interface.h | 6 ++++++ 8 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/inputmethod.cpp b/src/inputmethod.cpp index d7a373cf92..a44cc40e50 100644 --- a/src/inputmethod.cpp +++ b/src/inputmethod.cpp @@ -236,11 +236,21 @@ void InputMethod::setTrackedWindow(Window *trackedWindow) void InputMethod::handleFocusedSurfaceChanged() { - SurfaceInterface *focusedSurface = waylandServer()->seat()->focusedTextInputSurface(); + auto seat = waylandServer()->seat(); + SurfaceInterface *focusedSurface = seat->focusedTextInputSurface(); + setTrackedWindow(waylandServer()->findWindow(focusedSurface)); if (!focusedSurface) { setActive(false); } + + const auto client = focusedSurface ? focusedSurface->client() : nullptr; + bool ret = seat->textInputV2()->clientSupportsTextInput(client) + || seat->textInputV3()->clientSupportsTextInput(client); + if (ret != m_activeClientSupportsTextInput) { + m_activeClientSupportsTextInput = ret; + Q_EMIT activeClientSupportsTextInputChanged(); + } } void InputMethod::surroundingTextChanged() @@ -809,4 +819,15 @@ void InputMethod::resetPendingPreedit() preedit.highlightRanges.clear(); } +bool InputMethod::activeClientSupportsTextInput() const +{ + return m_activeClientSupportsTextInput; +} + +void InputMethod::forceActivate() +{ + setActive(true); + show(); +} + } diff --git a/src/inputmethod.h b/src/inputmethod.h index d5a1c137fc..ee17151786 100644 --- a/src/inputmethod.h +++ b/src/inputmethod.h @@ -72,6 +72,8 @@ public: bool shouldShowOnActive() const; void forwardModifiers(ForwardModifiersForce force); + bool activeClientSupportsTextInput() const; + void forceActivate(); Q_SIGNALS: void panelChanged(); @@ -79,6 +81,7 @@ Q_SIGNALS: void enabledChanged(bool enabled); void visibleChanged(); void availableChanged(); + void activeClientSupportsTextInputChanged(); private Q_SLOTS: // textinput interface slots @@ -134,6 +137,7 @@ private: QString m_inputMethodCommand; bool m_hasPendingModifiers = false; + bool m_activeClientSupportsTextInput = false; }; } diff --git a/src/virtualkeyboard_dbus.cpp b/src/virtualkeyboard_dbus.cpp index 81bd2e9561..cfdb65c07c 100644 --- a/src/virtualkeyboard_dbus.cpp +++ b/src/virtualkeyboard_dbus.cpp @@ -23,6 +23,7 @@ VirtualKeyboardDBus::VirtualKeyboardDBus(InputMethod *parent) connect(parent, &InputMethod::enabledChanged, this, &VirtualKeyboardDBus::enabledChanged); connect(parent, &InputMethod::visibleChanged, this, &VirtualKeyboardDBus::visibleChanged); connect(parent, &InputMethod::availableChanged, this, &VirtualKeyboardDBus::availableChanged); + connect(parent, &InputMethod::activeClientSupportsTextInputChanged, this, &VirtualKeyboardDBus::activeClientSupportsTextInputChanged); } VirtualKeyboardDBus::~VirtualKeyboardDBus() = default; @@ -57,9 +58,18 @@ bool VirtualKeyboardDBus::isAvailable() const return m_inputMethod->isAvailable(); } +bool VirtualKeyboardDBus::activeClientSupportsTextInput() const +{ + return m_inputMethod->activeClientSupportsTextInput(); +} + bool VirtualKeyboardDBus::willShowOnActive() const { return isAvailable() && isEnabled() && m_inputMethod->shouldShowOnActive(); } +void VirtualKeyboardDBus::forceActivate() +{ + m_inputMethod->forceActivate(); +} } diff --git a/src/virtualkeyboard_dbus.h b/src/virtualkeyboard_dbus.h index 92578dfda9..6fdbb5b321 100644 --- a/src/virtualkeyboard_dbus.h +++ b/src/virtualkeyboard_dbus.h @@ -22,11 +22,13 @@ class KWIN_EXPORT VirtualKeyboardDBus : public QObject Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged) Q_PROPERTY(bool active READ isActive WRITE setActive NOTIFY activeChanged) Q_PROPERTY(bool visible READ isVisible NOTIFY visibleChanged) + Q_PROPERTY(bool activeClientSupportsTextInput READ activeClientSupportsTextInput NOTIFY activeClientSupportsTextInputChanged) public: explicit VirtualKeyboardDBus(InputMethod *inputMethod); ~VirtualKeyboardDBus() override; bool isEnabled() const; + bool activeClientSupportsTextInput() const; bool isVisible() const; bool isActive() const; bool isAvailable() const; @@ -34,12 +36,14 @@ public: void setActive(bool active); Q_SCRIPTABLE bool willShowOnActive() const; + Q_SCRIPTABLE void forceActivate(); Q_SIGNALS: Q_SCRIPTABLE void enabledChanged(); Q_SCRIPTABLE void activeChanged(); Q_SCRIPTABLE void visibleChanged(); Q_SCRIPTABLE void availableChanged(); + Q_SCRIPTABLE void activeClientSupportsTextInputChanged(); private: InputMethod *const m_inputMethod; diff --git a/src/wayland/textinput_v2_interface.cpp b/src/wayland/textinput_v2_interface.cpp index 011e760196..8d296f87ed 100644 --- a/src/wayland/textinput_v2_interface.cpp +++ b/src/wayland/textinput_v2_interface.cpp @@ -561,4 +561,8 @@ bool TextInputV2Interface::isEnabled() const return d->surface && d->m_enabledSurfaces.contains(d->surface); } +bool TextInputV2Interface::clientSupportsTextInput(ClientConnection *client) const +{ + return client && d->resourceMap().contains(*client); +} } diff --git a/src/wayland/textinput_v2_interface.h b/src/wayland/textinput_v2_interface.h index 23a8eb2678..32f3259733 100644 --- a/src/wayland/textinput_v2_interface.h +++ b/src/wayland/textinput_v2_interface.h @@ -13,6 +13,7 @@ struct wl_resource; namespace KWaylandServer { +class ClientConnection; class Display; class SeatInterface; class SurfaceInterface; @@ -122,6 +123,11 @@ public: */ QPointer surface() const; + /** + * @return whether @p client supports text-input-v2 + */ + bool clientSupportsTextInput(ClientConnection *client) const; + /** * @return Whether the TextInputV2Interface is currently enabled for a SurfaceInterface. * @see surface diff --git a/src/wayland/textinput_v3_interface.cpp b/src/wayland/textinput_v3_interface.cpp index 3d1ddaf967..624c399cec 100644 --- a/src/wayland/textinput_v3_interface.cpp +++ b/src/wayland/textinput_v3_interface.cpp @@ -496,4 +496,8 @@ bool TextInputV3Interface::isEnabled() const return d->isEnabled(); } +bool TextInputV3Interface::clientSupportsTextInput(ClientConnection *client) const +{ + return client && d->resourceMap().contains(*client); +} } diff --git a/src/wayland/textinput_v3_interface.h b/src/wayland/textinput_v3_interface.h index 06df7a4572..547dfd4967 100644 --- a/src/wayland/textinput_v3_interface.h +++ b/src/wayland/textinput_v3_interface.h @@ -13,6 +13,7 @@ struct wl_resource; namespace KWaylandServer { +class ClientConnection; class Display; class SeatInterface; class SurfaceInterface; @@ -148,6 +149,11 @@ public: */ void done(); + /** + * @return whether @p client supports text-input-v3 + */ + bool clientSupportsTextInput(ClientConnection *client) const; + Q_SIGNALS: /**