diff --git a/abstract_client.h b/abstract_client.h --- a/abstract_client.h +++ b/abstract_client.h @@ -481,7 +481,6 @@ * client, this function stops it. */ bool isCurrentTab() const; - virtual QRect geometryRestore() const = 0; /** * The currently applied maximize mode */ @@ -703,6 +702,9 @@ QRect inputGeometry() const override; + QRect virtualKeyboardGeometry() const; + void setVirtualKeyboardGeometry(const QRect &geo); + /** * Restores the AbstractClient after it had been hidden due to show on screen edge functionality. * The AbstractClient also gets raised (e.g. Panel mode windows can cover) and the AbstractClient @@ -806,6 +808,8 @@ **/ void tabGroupChanged(); + virtual void setGeometryRestore(const QRect &geo) = 0; + protected: AbstractClient(); void setFirstInTabBox(bool enable) { @@ -907,7 +911,8 @@ int borderTop() const; int borderBottom() const; virtual void changeMaximize(bool horizontal, bool vertical, bool adjust) = 0; - virtual void setGeometryRestore(const QRect &geo) = 0; + virtual QRect geometryRestore() const = 0; + /** * Called from move after updating the geometry. Can be reimplemented to perform specific tasks. * The base implementation does nothing. @@ -1153,6 +1158,7 @@ friend class GeometryUpdatesBlocker; QRect m_visibleRectBeforeGeometryUpdate; QRect m_geometryBeforeUpdateBlocking; + QRect m_virtualKeyboardGeometry; struct { bool enabled = false; diff --git a/abstract_client.cpp b/abstract_client.cpp --- a/abstract_client.cpp +++ b/abstract_client.cpp @@ -1871,6 +1871,19 @@ return Toplevel::inputGeometry(); } +QRect AbstractClient::virtualKeyboardGeometry() const +{ + return m_virtualKeyboardGeometry; +} + +void AbstractClient::setVirtualKeyboardGeometry(const QRect &geo) +{ + m_virtualKeyboardGeometry = geo; + if (maximizeMode() != MaximizeRestore) { + changeMaximize(false, false, true); // adjust size + } +} + bool AbstractClient::dockWantsInput() const { return false; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -825,10 +825,14 @@ return; } - const QRect clientArea = isElectricBorderMaximizing() ? + QRect clientArea = isElectricBorderMaximizing() ? workspace()->clientArea(MaximizeArea, Cursor::pos(), desktop()) : workspace()->clientArea(MaximizeArea, this); + if (!virtualKeyboardGeometry().isEmpty()) { + clientArea.setBottom(virtualKeyboardGeometry().top()); + } + const MaximizeMode oldMode = m_requestedMaximizeMode; const QRect oldGeometry = geometry(); @@ -884,7 +888,9 @@ // TODO: check rules if (m_requestedMaximizeMode == MaximizeFull) { - m_geomMaximizeRestore = oldGeometry; + if (m_requestedMaximizeMode != maximizeMode()) { + m_geomMaximizeRestore = oldGeometry; + } // TODO: Client has more checks if (options->electricBorderMaximize()) { updateQuickTileMode(QuickTileFlag::Maximize); @@ -894,7 +900,8 @@ if (quickTileMode() != oldQuickTileMode) { emit quickTileModeChanged(); } - setGeometry(workspace()->clientArea(MaximizeArea, this)); + + setGeometry(clientArea); workspace()->raiseClient(this); } else { if (m_requestedMaximizeMode == MaximizeRestore) { diff --git a/virtualkeyboard.h b/virtualkeyboard.h --- a/virtualkeyboard.h +++ b/virtualkeyboard.h @@ -25,6 +25,10 @@ #include #include +#include + +#include + class QQuickView; class QWindow; class KStatusNotifierItem; @@ -53,10 +57,14 @@ void hide(); void setEnabled(bool enable); void updateSni(); + void updateInputPanelState(); bool m_enabled = false; KStatusNotifierItem *m_sni = nullptr; QScopedPointer m_inputWindow; + QPointer m_trackedClient; + MaximizeMode m_trackedClientOriginalMaxState; + QMetaObject::Connection m_waylandShowConnection; QMetaObject::Connection m_waylandHideConnection; QMetaObject::Connection m_waylandHintsConnection; diff --git a/virtualkeyboard.cpp b/virtualkeyboard.cpp --- a/virtualkeyboard.cpp +++ b/virtualkeyboard.cpp @@ -26,6 +26,7 @@ #include "wayland_server.h" #include "workspace.h" #include "xkb.h" +#include "shell_client.h" #include #include @@ -146,8 +147,16 @@ qApp->inputMethod()->update(Qt::ImQueryAll); } ); - // TODO: calculate overlap - t->setInputPanelState(m_inputWindow->isVisible(), QRect(0, 0, 0, 0)); + + //Restore the old client maximized state if necessary + if (m_trackedClient) { + m_trackedClient->maximize(m_trackedClientOriginalMaxState); + m_trackedClient->setVirtualKeyboardGeometry(QRect()); + } + m_trackedClient = waylandServer()->findAbstractClient(waylandServer()->seat()->focusedTextInputSurface()); + m_trackedClientOriginalMaxState = m_trackedClient->maximizeMode(); + + updateInputPanelState(); } else { m_waylandShowConnection = QMetaObject::Connection(); m_waylandHideConnection = QMetaObject::Connection(); @@ -176,20 +185,10 @@ m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect()); } ); - connect(qApp->inputMethod(), &QInputMethod::visibleChanged, m_inputWindow.data(), - [this] { - m_inputWindow->setVisible(qApp->inputMethod()->isVisible()); - if (qApp->inputMethod()->isVisible()) { - m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect()); - } - if (waylandServer()) { - if (auto t = waylandServer()->seat()->focusedTextInput()) { - // TODO: calculate overlap - t->setInputPanelState(m_inputWindow->isVisible(), QRect(0, 0, 0, 0)); - } - } - } - ); + + connect(qApp->inputMethod(), &QInputMethod::visibleChanged, this, &VirtualKeyboard::updateInputPanelState); + + connect(m_inputWindow->rootObject(), &QQuickItem::childrenRectChanged, this, &VirtualKeyboard::updateInputPanelState); } void VirtualKeyboard::setEnabled(bool enabled) @@ -226,6 +225,48 @@ } } +void VirtualKeyboard::updateInputPanelState() +{ + if (!waylandServer()) { + return; + } + + auto t = waylandServer()->seat()->focusedTextInput(); + + if (!t) { + return; + } + + const bool inputPanelHasBeenOpened = !m_inputWindow->isVisible() && qApp->inputMethod()->isVisible(); + const bool inputPanelHasBeenClosed = m_inputWindow->isVisible() && !qApp->inputMethod()->isVisible(); + + m_inputWindow->setVisible(qApp->inputMethod()->isVisible()); + + if (qApp->inputMethod()->isVisible()) { + m_inputWindow->setMask(m_inputWindow->rootObject()->childrenRect().toRect()); + } + + if (m_inputWindow->isVisible() && m_trackedClient && m_inputWindow->rootObject()) { + const QRect inputPanelGeom = m_inputWindow->rootObject()->childrenRect().toRect().translated(m_inputWindow->geometry().topLeft()); + + m_trackedClient->setVirtualKeyboardGeometry(inputPanelGeom); + if (inputPanelHasBeenOpened) { + m_trackedClientOriginalMaxState = m_trackedClient->maximizeMode(); + m_trackedClient->setMaximize(true, true); + } + + t->setInputPanelState(true, QRect(0, 0, 0, 0)); + + } else { + if (inputPanelHasBeenClosed && m_trackedClient) { + m_trackedClient->maximize(m_trackedClientOriginalMaxState); + m_trackedClient->setVirtualKeyboardGeometry(QRect()); + } + + t->setInputPanelState(false, QRect(0, 0, 0, 0)); + } +} + void VirtualKeyboard::show() { if (m_inputWindow.isNull() || !m_enabled) {