Floating polish: visibility, resize, saved geometry, D-Bus, desktop entry
- VisibilityController: show on field focus, dismiss until next focus, manual show/hide/toggle overrides - FloatingWindow: resize from the corner grip, clamp to screen - WindowSettings: geometry per screen, debounced saves - DBusControl: org.sloposk.Keyboard Show/Hide/Toggle for global shortcuts - org.sloposk.keyboard.desktop so System Settings lists it as a virtual keyboard - README with build/run/layout docs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -36,19 +36,44 @@ FloatingWindow::FloatingWindow(QWindow *window, QObject *parent)
|
||||
apply();
|
||||
}
|
||||
|
||||
void FloatingWindow::setPosition(QPoint position)
|
||||
QRect FloatingWindow::geometry() const
|
||||
{
|
||||
position = clamped(position);
|
||||
if (position == m_position)
|
||||
return;
|
||||
m_position = position;
|
||||
return {m_position, m_window->size()};
|
||||
}
|
||||
|
||||
void FloatingWindow::setGeometry(const QRect &geometry)
|
||||
{
|
||||
const QSize size = geometry.size().expandedTo(m_window->minimumSize()).boundedTo(screenArea().size());
|
||||
m_window->resize(size);
|
||||
m_position = clamped(geometry.topLeft(), size);
|
||||
apply();
|
||||
Q_EMIT positionChanged();
|
||||
}
|
||||
|
||||
QString FloatingWindow::screenName() const
|
||||
{
|
||||
return m_window->screen()->name();
|
||||
}
|
||||
|
||||
void FloatingWindow::moveBy(qreal dx, qreal dy)
|
||||
{
|
||||
setPosition(m_position + QPoint(qRound(dx), qRound(dy)));
|
||||
const QPoint position = clamped(m_position + QPoint(qRound(dx), qRound(dy)), m_window->size());
|
||||
if (position == m_position)
|
||||
return;
|
||||
m_position = position;
|
||||
apply();
|
||||
Q_EMIT geometryChanged();
|
||||
}
|
||||
|
||||
void FloatingWindow::resizeBy(qreal dw, qreal dh)
|
||||
{
|
||||
const QSize maximum = screenArea().size() - QSize(m_position.x(), m_position.y());
|
||||
const QSize size = (m_window->size() + QSize(qRound(dw), qRound(dh)))
|
||||
.expandedTo(m_window->minimumSize())
|
||||
.boundedTo(maximum);
|
||||
if (size == m_window->size())
|
||||
return;
|
||||
m_window->resize(size);
|
||||
Q_EMIT geometryChanged();
|
||||
}
|
||||
|
||||
void FloatingWindow::setInputRegion(const QRectF ®ion)
|
||||
@@ -66,19 +91,24 @@ void FloatingWindow::hide()
|
||||
m_window->setVisible(false);
|
||||
}
|
||||
|
||||
QPoint FloatingWindow::clamped(QPoint position) const
|
||||
QRect FloatingWindow::screenArea() const
|
||||
{
|
||||
const QRect area = m_window->screen()->geometry();
|
||||
const int maxX = qMax(0, area.width() - m_window->width());
|
||||
const int maxY = qMax(0, area.height() - m_window->height());
|
||||
return m_window->screen()->geometry();
|
||||
}
|
||||
|
||||
QPoint FloatingWindow::clamped(QPoint position, QSize size) const
|
||||
{
|
||||
const QRect area = screenArea();
|
||||
const int maxX = qMax(0, area.width() - size.width());
|
||||
const int maxY = qMax(0, area.height() - size.height());
|
||||
return {qBound(0, position.x(), maxX), qBound(0, position.y(), maxY)};
|
||||
}
|
||||
|
||||
QPoint FloatingWindow::defaultPosition() const
|
||||
{
|
||||
const QRect area = m_window->screen()->geometry();
|
||||
return clamped({(area.width() - m_window->width()) / 2,
|
||||
area.height() - m_window->height() - BottomGap});
|
||||
const QRect area = screenArea();
|
||||
return clamped({(area.width() - m_window->width()) / 2, area.height() - m_window->height() - BottomGap},
|
||||
m_window->size());
|
||||
}
|
||||
|
||||
void FloatingWindow::apply()
|
||||
@@ -86,5 +116,5 @@ void FloatingWindow::apply()
|
||||
if (m_layerSurface)
|
||||
m_layerSurface->setMargins({m_position.x(), m_position.y(), 0, 0});
|
||||
else
|
||||
m_window->setPosition(m_window->screen()->geometry().topLeft() + m_position);
|
||||
m_window->setPosition(screenArea().topLeft() + m_position);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user