#include "FloatingWindow.h" #include #include #include #include namespace { bool isWayland() { return QGuiApplication::platformName().startsWith(QLatin1String("wayland")); } constexpr int BottomGap = 24; } // namespace FloatingWindow::FloatingWindow(QWindow *window, QObject *parent) : QObject(parent) , m_window(window) { if (isWayland()) { m_layerSurface = LayerShellQt::Window::get(window); m_layerSurface->setLayer(LayerShellQt::Window::LayerOverlay); m_layerSurface->setKeyboardInteractivity(LayerShellQt::Window::KeyboardInteractivityNone); m_layerSurface->setAnchors({LayerShellQt::Window::AnchorTop | LayerShellQt::Window::AnchorLeft}); m_layerSurface->setExclusiveZone(-1); m_layerSurface->setScope(QStringLiteral("sloposk-keyboard")); m_layerSurface->setActivateOnShow(false); } else { window->setFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus); } m_position = defaultPosition(); apply(); } QRect FloatingWindow::geometry() const { 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(); } QString FloatingWindow::screenName() const { return m_window->screen()->name(); } void FloatingWindow::moveBy(qreal dx, qreal 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) { m_window->setMask(QRegion(region.toAlignedRect())); } void FloatingWindow::show() { m_window->setVisible(true); } void FloatingWindow::hide() { m_window->setVisible(false); } QRect FloatingWindow::screenArea() const { 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 = screenArea(); return clamped({(area.width() - m_window->width()) / 2, area.height() - m_window->height() - BottomGap}, m_window->size()); } void FloatingWindow::apply() { if (m_layerSurface) m_layerSurface->setMargins({m_position.x(), m_position.y(), 0, 0}); else m_window->setPosition(screenArea().topLeft() + m_position); }