inputmethod: Use touch events to decide if the panel is shown not the state

Prefer hiding/showing the panel (i.e. the window) when not a touch event
than stopping to make the inputmethod active.
This way we remain compatible with non-virtualkeyboard inputmethods.
This commit is contained in:
Aleix Pol 2021-10-13 18:24:59 +02:00 committed by Aleix Pol Gonzalez
parent 5b9deafa14
commit 3e77907d21
4 changed files with 33 additions and 14 deletions

View file

@ -86,7 +86,6 @@ void InputMethod::init()
new TextInputManagerV2Interface(waylandServer()->display());
new TextInputManagerV3Interface(waylandServer()->display());
connect(workspace(), &Workspace::clientAdded, this, &InputMethod::clientAdded);
connect(waylandServer()->seat(), &SeatInterface::focusedTextInputSurfaceChanged, this, &InputMethod::handleFocusedSurfaceChanged);
TextInputV2Interface *textInputV2 = waylandServer()->seat()->textInputV2();
@ -118,11 +117,15 @@ void InputMethod::hide()
setActive(false);
}
void InputMethod::setActive(bool active)
bool InputMethod::touchEventTriggered() const
{
active &= input()->touch()
return input()->touch()
&& input()->touch()->lastEventTime() > input()->keyboard()->lastEventTime()
&& input()->touch()->lastEventTime() > input()->pointer()->lastEventTime();
}
void InputMethod::setActive(bool active)
{
const bool wasActive = waylandServer()->inputMethod()->context();
if (wasActive && !active) {
waylandServer()->inputMethod()->sendDeactivate();
@ -148,18 +151,14 @@ void InputMethod::setActive(bool active)
}
}
void InputMethod::clientAdded(AbstractClient *_client)
void InputMethod::setPanel(InputPanelV1Client *client)
{
if (!_client->isInputMethod()) {
return;
}
Q_ASSERT(client->isInputMethod());
if (m_inputClient) {
qCWarning(KWIN_VIRTUALKEYBOARD) << "Replacing input client" << m_inputClient << "with" << _client;
qCWarning(KWIN_VIRTUALKEYBOARD) << "Replacing input client" << m_inputClient << "with" << client;
disconnect(m_inputClient, nullptr, this, nullptr);
}
const auto client = dynamic_cast<InputPanelV1Client *>(_client);
m_inputClient = client;
connect(client->surface(), &SurfaceInterface::inputChanged, this, &InputMethod::updateInputPanelState);
connect(client, &QObject::destroyed, this, [this] {
@ -253,6 +252,9 @@ void InputMethod::textInputInterfaceV2StateUpdated(quint32 serial, KWaylandServe
if (!t2 || !t2->isEnabled()) {
return;
}
if (m_inputClient && touchEventTriggered()) {
m_inputClient->allow();
}
switch (reason) {
case KWaylandServer::TextInputV2Interface::UpdateReason::StateChange:
break;
@ -526,6 +528,10 @@ void InputMethod::updateInputPanelState()
return;
}
if (m_inputClient && touchEventTriggered()) {
m_inputClient->allow();
}
QRect overlap = QRect(0, 0, 0, 0);
if (m_trackedClient) {
const bool bottomKeyboard = m_inputClient && m_inputClient->mode() != InputPanelV1Client::Overlay && m_inputClient->isShown(false);

View file

@ -54,6 +54,7 @@ public:
bool isVisible() const;
bool isAvailable() const;
void setPanel(InputPanelV1Client* client);
void setInputMethodCommand(const QString &path);
Q_SIGNALS:
@ -63,8 +64,6 @@ Q_SIGNALS:
void availableChanged();
private Q_SLOTS:
void clientAdded(AbstractClient* client);
// textinput interface slots
void handleFocusedSurfaceChanged();
void surroundingTextChanged();
@ -94,6 +93,8 @@ private:
void setTrackedClient(AbstractClient *trackedClient);
void installKeyboardGrab(KWaylandServer::InputMethodGrabV1 *keyboardGrab);
bool touchEventTriggered() const;
struct {
QString text = QString();
quint32 begin = 0;

View file

@ -13,6 +13,7 @@
#include "workspace.h"
#include "abstract_wayland_output.h"
#include "platform.h"
#include "inputmethod.h"
#include <KWaylandServer/output_interface.h>
#include <KWaylandServer/seat_interface.h>
#include <KWaylandServer/surface_interface.h>
@ -38,6 +39,8 @@ InputPanelV1Client::InputPanelV1Client(InputPanelSurfaceV1Interface *panelSurfac
connect(panelSurface, &InputPanelSurfaceV1Interface::topLevel, this, &InputPanelV1Client::showTopLevel);
connect(panelSurface, &InputPanelSurfaceV1Interface::overlayPanel, this, &InputPanelV1Client::showOverlayPanel);
connect(panelSurface, &InputPanelSurfaceV1Interface::destroyed, this, &InputPanelV1Client::destroyClient);
InputMethod::self()->setPanel(this);
}
void InputPanelV1Client::showOverlayPanel()
@ -53,12 +56,20 @@ void InputPanelV1Client::showTopLevel(OutputInterface *output, InputPanelSurface
Q_UNUSED(position);
m_mode = Toplevel;
setOutput(output);
reposition();
}
void InputPanelV1Client::allow()
{
setReadyForPainting();
reposition();
}
void KWin::InputPanelV1Client::reposition()
{
if (!readyForPainting()) {
return;
}
switch (m_mode) {
case Toplevel: {
if (m_output) {
@ -109,7 +120,7 @@ NET::WindowType InputPanelV1Client::windowType(bool, int) const
QRect InputPanelV1Client::inputGeometry() const
{
return surface()->input().boundingRect().translated(pos());
return readyForPainting() ? surface()->input().boundingRect().translated(pos()) : QRect();
}
void InputPanelV1Client::setOutput(OutputInterface *outputIface)

View file

@ -47,6 +47,7 @@ public:
{
return m_mode;
}
void allow();
protected:
void moveResizeInternal(const QRect &rect, MoveResizeMode mode) override;