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
This commit is contained in:
Aleix Pol 2022-09-07 00:56:19 +02:00
parent d659f4bfd7
commit 006ee8b87a
8 changed files with 60 additions and 1 deletions

View file

@ -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();
}
}

View file

@ -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;
};
}

View file

@ -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();
}
}

View file

@ -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;

View file

@ -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);
}
}

View file

@ -13,6 +13,7 @@
struct wl_resource;
namespace KWaylandServer
{
class ClientConnection;
class Display;
class SeatInterface;
class SurfaceInterface;
@ -122,6 +123,11 @@ public:
*/
QPointer<SurfaceInterface> 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

View file

@ -496,4 +496,8 @@ bool TextInputV3Interface::isEnabled() const
return d->isEnabled();
}
bool TextInputV3Interface::clientSupportsTextInput(ClientConnection *client) const
{
return client && d->resourceMap().contains(*client);
}
}

View file

@ -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:
/**