Shrink to a floating button instead of hiding
With "Shrink to Button" on, the dismiss key shrinks the window to just itself: a see-through button that can be dragged anywhere. Tapping it grows the keyboard back around it, kept on screen. KWin moves and resizes the window through a one-off script, as Wayland clients can't place themselves. Also moves the window back on screen whenever it appears (KWin remembers where the button was), and releases the mouse after a window manager move or resize, which used to eat the next press on the grab bar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
#include "CollapseController.h"
|
||||
|
||||
#include "FloatingWindow.h"
|
||||
|
||||
#include <QQuickWindow>
|
||||
|
||||
namespace {
|
||||
constexpr int ExpandTimeoutMs = 500;
|
||||
|
||||
bool roughlyEqual(QSize a, QSize b)
|
||||
{
|
||||
return qAbs(a.width() - b.width()) <= 1 && qAbs(a.height() - b.height()) <= 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
CollapseController::CollapseController(QQuickWindow &window, FloatingWindow &placement, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_window(window)
|
||||
, m_placement(placement)
|
||||
{
|
||||
m_expanding.setSingleShot(true);
|
||||
m_expanding.setInterval(ExpandTimeoutMs);
|
||||
connect(&m_expanding, &QTimer::timeout, this, &CollapseController::finishExpanding);
|
||||
connect(&window, &QWindow::widthChanged, this, &CollapseController::windowResized);
|
||||
connect(&window, &QWindow::heightChanged, this, &CollapseController::windowResized);
|
||||
}
|
||||
|
||||
bool CollapseController::collapse()
|
||||
{
|
||||
if (m_collapsed)
|
||||
return true;
|
||||
QVariant rect;
|
||||
QMetaObject::invokeMethod(&m_window, "dismissKeyRect", Q_RETURN_ARG(QVariant, rect));
|
||||
if (rect.toRectF().isEmpty())
|
||||
return false;
|
||||
m_keyRect = rect.toRectF();
|
||||
m_expandedSize = m_window.size();
|
||||
m_collapsed = true;
|
||||
Q_EMIT collapsedChanged();
|
||||
// After the next frame, once the compositor knows the lower minimum size.
|
||||
connect(&m_window, &QQuickWindow::frameSwapped, this, [this] {
|
||||
if (m_collapsed)
|
||||
m_placement.moveResize(m_keyRect, false);
|
||||
}, Qt::SingleShotConnection);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CollapseController::expand()
|
||||
{
|
||||
if (!m_collapsed || m_expanding.isActive())
|
||||
return;
|
||||
if (roughlyEqual(m_window.size(), m_expandedSize)) {
|
||||
finishExpanding(); // never shrank: nothing to move
|
||||
return;
|
||||
}
|
||||
// Stays collapsed until the window has grown, so the keys don't flash squeezed.
|
||||
m_placement.moveResize(QRectF(-m_keyRect.topLeft(), m_expandedSize), true);
|
||||
m_expanding.start();
|
||||
}
|
||||
|
||||
void CollapseController::windowResized()
|
||||
{
|
||||
if (m_expanding.isActive() && roughlyEqual(m_window.size(), m_expandedSize))
|
||||
finishExpanding();
|
||||
}
|
||||
|
||||
void CollapseController::finishExpanding()
|
||||
{
|
||||
m_expanding.stop();
|
||||
if (!roughlyEqual(m_window.size(), m_expandedSize))
|
||||
m_window.resize(m_expandedSize); // no KWin to do it
|
||||
m_collapsed = false;
|
||||
Q_EMIT collapsedChanged();
|
||||
}
|
||||
Reference in New Issue
Block a user