diff --git a/abstract_client.h b/abstract_client.h --- a/abstract_client.h +++ b/abstract_client.h @@ -806,6 +806,8 @@ **/ void tabGroupChanged(); + virtual void setGeometryRestore(const QRect &geo) = 0; + protected: AbstractClient(); void setFirstInTabBox(bool enable) { @@ -907,7 +909,7 @@ int borderTop() const; int borderBottom() const; virtual void changeMaximize(bool horizontal, bool vertical, bool adjust) = 0; - virtual void setGeometryRestore(const QRect &geo) = 0; + /** * Called from move after updating the geometry. Can be reimplemented to perform specific tasks. * The base implementation does nothing. diff --git a/virtualkeyboard.h b/virtualkeyboard.h --- a/virtualkeyboard.h +++ b/virtualkeyboard.h @@ -25,6 +25,11 @@ #include #include +#include + +#include +#include + class QQuickView; class QWindow; class KStatusNotifierItem; @@ -53,10 +58,13 @@ void hide(); void setEnabled(bool enable); void updateSni(); + void updateInputPanelState(); bool m_enabled = false; KStatusNotifierItem *m_sni = nullptr; QScopedPointer m_inputWindow; + QPointer m_trackedClient; + 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 @@ -34,6 +34,8 @@ #include #include +#include + #include #include #include @@ -146,8 +148,25 @@ qApp->inputMethod()->update(Qt::ImQueryAll); } ); - // TODO: calculate overlap - t->setInputPanelState(m_inputWindow->isVisible(), QRect(0, 0, 0, 0)); + + //Restore the old client geometry if necessary + if (m_trackedClient) { + const QRect maximizedGeom = workspace()->clientArea(MaximizeArea, m_trackedClient); + QRect restoreGeom = m_trackedClient->geometryRestore(); + + if (m_trackedClient->maximizeMode() & MaximizeVertical) { + restoreGeom.setTop(maximizedGeom.top()); + restoreGeom.setBottom(maximizedGeom.bottom()); + } + if (m_trackedClient->maximizeMode() & MaximizeHorizontal) { + restoreGeom.setLeft(maximizedGeom.left()); + restoreGeom.setRight(maximizedGeom.right()); + } + m_trackedClient->setGeometry(restoreGeom); + } + m_trackedClient = waylandServer()->findAbstractClient(waylandServer()->seat()->focusedTextInputSurface()); + + updateInputPanelState(); } else { m_waylandShowConnection = QMetaObject::Connection(); m_waylandHideConnection = QMetaObject::Connection(); @@ -176,20 +195,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 +235,70 @@ } } +void VirtualKeyboard::updateInputPanelState() +{ + 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 (waylandServer()) { + if (auto t = waylandServer()->seat()->focusedTextInput()) { + if (m_inputWindow->isVisible() && m_trackedClient && m_inputWindow->rootObject()) { + const QRect inputPanelGeom = m_inputWindow->rootObject()->childrenRect().toRect().translated(m_inputWindow->geometry().topLeft()); + + //save the geometry only for non maximized clients + if (inputPanelHasBeenOpened && m_trackedClient->maximizeMode() == MaximizeRestore) { + m_trackedClient->setGeometryRestore(m_trackedClient->geometry()); + } + + if (!inputPanelHasBeenClosed) { + QRect maximizedGeom = workspace() ->clientArea(MaximizeArea, m_trackedClient); + + QRect newGeom = m_trackedClient->geometryRestore().isNull() ? m_trackedClient->geometry() : m_trackedClient->geometryRestore(); + + if (m_trackedClient->maximizeMode() & MaximizeVertical) { + newGeom.setTop(maximizedGeom.top()); + newGeom.setBottom(maximizedGeom.bottom()); + } + + if (m_trackedClient->maximizeMode() & MaximizeHorizontal) { + newGeom.setLeft(maximizedGeom.left()); + newGeom.setRight(maximizedGeom.right()); + } + + newGeom.moveBottom(qMin(newGeom.bottom(), inputPanelGeom.top())); + newGeom.setTop(qMax(maximizedGeom.top(), newGeom.top())); + m_trackedClient->setGeometry(newGeom); + } + + t->setInputPanelState(true, QRect(0, 0, 0, 0)); + + } else { + if (inputPanelHasBeenClosed && m_trackedClient && !m_trackedClient->geometryRestore().isNull()) { + const QRect maximizedGeom = workspace()->clientArea(MaximizeArea, m_trackedClient); + QRect restoreGeom = m_trackedClient->geometryRestore(); + + if (m_trackedClient->maximizeMode() & MaximizeVertical) { + restoreGeom.setTop(maximizedGeom.top()); + restoreGeom.setBottom(maximizedGeom.bottom()); + } + if (m_trackedClient->maximizeMode() & MaximizeHorizontal) { + restoreGeom.setLeft(maximizedGeom.left()); + restoreGeom.setRight(maximizedGeom.right()); + } + m_trackedClient->setGeometry(restoreGeom); + } + t->setInputPanelState(false, QRect(0, 0, 0, 0)); + } + } + } +} + void VirtualKeyboard::show() { if (m_inputWindow.isNull() || !m_enabled) {