diff --git a/src/interfaces/window.cpp b/src/interfaces/window.cpp index 0389d51..b74c597 100644 --- a/src/interfaces/window.cpp +++ b/src/interfaces/window.cpp @@ -17,6 +17,49 @@ using namespace LayerShellQt; +Margin::Margin() + : m_value(0) +{ +} + +Margin::Margin(int pixels) + : m_value(pixels) +{ +} + +Margin::Margin(qreal fraction) + : m_value(fraction) +{ +} + +Margin Margin::fromPixels(int pixels) +{ + return Margin(pixels); +} + +Margin Margin::fromFraction(qreal fraction) +{ + return Margin(fraction); +} + +std::optional Margin::pixels() const +{ + if (std::holds_alternative(m_value)) { + return std::get(m_value); + } else { + return std::nullopt; + } +} + +std::optional Margin::fraction() const +{ + if (std::holds_alternative(m_value)) { + return std::get(m_value); + } else { + return std::nullopt; + } +} + class LayerShellQt::WindowPrivate { public: @@ -32,7 +75,10 @@ public: Window::Anchor exclusiveEdge = Window::AnchorNone; Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand; Window::Layer layer = Window::LayerTop; - QMargins margins; + Margin leftMargin; + Margin topMargin; + Margin rightMargin; + Margin bottomMargin; QSize desiredSize = QSize(0, 0); Window::ScreenConfiguration screenConfiguration = Window::ScreenFromQWindow; bool closeOnDismissed = true; @@ -89,15 +135,74 @@ Window::Anchor Window::exclusiveEdge() const void Window::setMargins(const QMargins &margins) { - if (d->margins != margins) { - d->margins = margins; - Q_EMIT marginsChanged(); - } + setLeftMargin(Margin::fromPixels(margins.left())); + setTopMargin(Margin::fromPixels(margins.top())); + setRightMargin(Margin::fromPixels(margins.right())); + setBottomMargin(Margin::fromPixels(margins.bottom())); } QMargins Window::margins() const { - return d->margins; + return QMargins(d->leftMargin.pixels().value_or(0), + d->topMargin.pixels().value_or(0), + d->rightMargin.pixels().value_or(0), + d->bottomMargin.pixels().value_or(0)); +} + +void Window::setLeftMargin(Margin margin) +{ + if (d->leftMargin != margin) { + d->leftMargin = margin; + Q_EMIT leftMarginChanged(); + Q_EMIT marginsChanged(); + } +} + +Margin Window::leftMargin() const +{ + return d->leftMargin; +} + +void Window::setTopMargin(Margin margin) +{ + if (d->topMargin != margin) { + d->topMargin = margin; + Q_EMIT topMarginChanged(); + Q_EMIT marginsChanged(); + } +} + +Margin Window::topMargin() const +{ + return d->topMargin; +} + +void Window::setRightMargin(Margin margin) +{ + if (d->rightMargin != margin) { + d->rightMargin = margin; + Q_EMIT rightMarginChanged(); + Q_EMIT marginsChanged(); + } +} + +Margin Window::rightMargin() const +{ + return d->rightMargin; +} + +void Window::setBottomMargin(Margin margin) +{ + if (d->bottomMargin != margin) { + d->bottomMargin = margin; + Q_EMIT bottomMarginChanged(); + Q_EMIT marginsChanged(); + } +} + +Margin Window::bottomMargin() const +{ + return d->bottomMargin; } void Window::setDesiredSize(const QSize &size) diff --git a/src/interfaces/window.h b/src/interfaces/window.h index b9e4824..dabdbcd 100644 --- a/src/interfaces/window.h +++ b/src/interfaces/window.h @@ -18,6 +18,34 @@ namespace LayerShellQt { class WindowPrivate; +/** + * The Margin type provides a way to specify how far a layer surface should be away from a screen edge. + * + * A margin can have an absolute value or a percent value. An absolute value indicates the distance + * in pixels. A percent value indicates the distance as a percentage of the output size, for example + * this can be used to tell the compositor that the surface should be one third of the output height from + * a screen edge, etc. + */ +class LAYERSHELLQT_EXPORT Margin +{ +public: + static Margin fromPixels(int pixels); + static Margin fromFraction(qreal fraction); + + Margin(); + + std::optional pixels() const; + std::optional fraction() const; + + auto operator<=>(const Margin &other) const = default; + +private: + Margin(int pixels); + Margin(qreal fraction); + + std::variant m_value; +}; + class LAYERSHELLQT_EXPORT Window : public QObject { Q_OBJECT @@ -87,6 +115,18 @@ public: void setMargins(const QMargins &margins); QMargins margins() const; + void setLeftMargin(Margin margin); + Margin leftMargin() const; + + void setTopMargin(Margin margin); + Margin topMargin() const; + + void setRightMargin(Margin margin); + Margin rightMargin() const; + + void setBottomMargin(Margin margin); + Margin bottomMargin() const; + void setDesiredSize(const QSize &size); QSize desiredSize() const; @@ -145,6 +185,10 @@ Q_SIGNALS: void exclusionZoneChanged(); void exclusiveEdgeChanged(); void marginsChanged(); + void leftMarginChanged(); + void topMarginChanged(); + void rightMarginChanged(); + void bottomMarginChanged(); void desiredSizeChanged(); void keyboardInteractivityChanged(); void layerChanged(); diff --git a/src/qwaylandlayershellintegration.cpp b/src/qwaylandlayershellintegration.cpp index 2ae367e..b772cc9 100644 --- a/src/qwaylandlayershellintegration.cpp +++ b/src/qwaylandlayershellintegration.cpp @@ -15,7 +15,7 @@ namespace LayerShellQt { QWaylandLayerShellIntegration::QWaylandLayerShellIntegration() - : QWaylandShellIntegrationTemplate(5) + : QWaylandShellIntegrationTemplate(6) , m_xdgActivation(new QWaylandXdgActivationV1) { } diff --git a/src/qwaylandlayersurface.cpp b/src/qwaylandlayersurface.cpp index fd8851c..3103900 100644 --- a/src/qwaylandlayersurface.cpp +++ b/src/qwaylandlayersurface.cpp @@ -60,9 +60,24 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, setExclusiveEdge(m_interface->exclusiveEdge()); }); - setMargins(m_interface->margins()); - connect(m_interface, &Window::marginsChanged, this, [this]() { - setMargins(m_interface->margins()); + setLeftMargin(m_interface->leftMargin()); + connect(m_interface, &Window::leftMarginChanged, this, [this]() { + setLeftMargin(m_interface->leftMargin()); + }); + + setTopMargin(m_interface->topMargin()); + connect(m_interface, &Window::topMarginChanged, this, [this]() { + setTopMargin(m_interface->topMargin()); + }); + + setRightMargin(m_interface->rightMargin()); + connect(m_interface, &Window::rightMarginChanged, this, [this]() { + setRightMargin(m_interface->rightMargin()); + }); + + setBottomMargin(m_interface->bottomMargin()); + connect(m_interface, &Window::bottomMarginChanged, this, [this]() { + setBottomMargin(m_interface->bottomMargin()); }); connect(m_interface, &Window::desiredSizeChanged, this, [this]() { @@ -159,9 +174,68 @@ void QWaylandLayerSurface::setExclusiveEdge(uint32_t edge) } } -void QWaylandLayerSurface::setMargins(const QMargins &margins) +void QWaylandLayerSurface::setLeftMargin(const Margin &margin) { - set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); + if (zwlr_layer_surface_v1_get_version(object()) >= 6) { + if (const auto pixels = margin.pixels()) { + set_left_margin_units(*pixels); + } else if (const auto fraction = margin.fraction()) { + set_left_margin_fraction(wl_fixed_from_double(*fraction)); + } else { + qCWarning(LAYERSHELLQT) << "Unspecified left margin for" << m_window->window(); + } + } else { + const QMargins margins = m_interface->margins(); + set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); + } +} + +void QWaylandLayerSurface::setTopMargin(const Margin &margin) +{ + if (zwlr_layer_surface_v1_get_version(object()) >= 6) { + if (const auto pixels = margin.pixels()) { + set_top_margin_units(*pixels); + } else if (const auto fraction = margin.fraction()) { + set_top_margin_fraction(wl_fixed_from_double(*fraction)); + } else { + qCWarning(LAYERSHELLQT) << "Unspecified top margin for" << m_window->window(); + } + } else { + const QMargins margins = m_interface->margins(); + set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); + } +} + +void QWaylandLayerSurface::setRightMargin(const Margin &margin) +{ + if (zwlr_layer_surface_v1_get_version(object()) >= 6) { + if (const auto pixels = margin.pixels()) { + set_right_margin_units(*pixels); + } else if (const auto fraction = margin.fraction()) { + set_right_margin_fraction(wl_fixed_from_double(*fraction)); + } else { + qCWarning(LAYERSHELLQT) << "Unspecified right margin for" << m_window->window(); + } + } else { + const QMargins margins = m_interface->margins(); + set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); + } +} + +void QWaylandLayerSurface::setBottomMargin(const Margin &margin) +{ + if (zwlr_layer_surface_v1_get_version(object()) >= 6) { + if (const auto pixels = margin.pixels()) { + set_bottom_margin_units(*pixels); + } else if (const auto fraction = margin.fraction()) { + set_bottom_margin_fraction(wl_fixed_from_double(*fraction)); + } else { + qCWarning(LAYERSHELLQT) << "Unspecified bottom margin for" << m_window->window(); + } + } else { + const QMargins margins = m_interface->margins(); + set_margin(margins.top(), margins.right(), margins.bottom(), margins.left()); + } } void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity) diff --git a/src/qwaylandlayersurface_p.h b/src/qwaylandlayersurface_p.h index a48e522..ee19ba5 100644 --- a/src/qwaylandlayersurface_p.h +++ b/src/qwaylandlayersurface_p.h @@ -19,6 +19,7 @@ namespace LayerShellQt { +class Margin; class Window; class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1 @@ -38,7 +39,10 @@ public: void setAnchor(uint32_t anchor); void setExclusiveZone(int32_t zone); void setExclusiveEdge(uint32_t edge); - void setMargins(const QMargins &margins); + void setLeftMargin(const Margin &margin); + void setTopMargin(const Margin &margin); + void setRightMargin(const Margin &margin); + void setBottomMargin(const Margin &margin); void setKeyboardInteractivity(uint32_t interactivity); void setLayer(uint32_t layer); diff --git a/src/wlr-layer-shell-unstable-v1.xml b/src/wlr-layer-shell-unstable-v1.xml index ba4bb61..57dab0e 100644 --- a/src/wlr-layer-shell-unstable-v1.xml +++ b/src/wlr-layer-shell-unstable-v1.xml @@ -25,7 +25,7 @@ THIS SOFTWARE. - + Clients can use this interface to assign the surface_layer role to wl_surfaces. Such surfaces are assigned to a "layer" of the output and @@ -100,7 +100,7 @@ - + An interface that may be implemented by a wl_surface, for surfaces that are designed to be rendered as a layer of a stacked desktop-like @@ -187,7 +187,7 @@ - + Requests that the surface be placed some distance away from the anchor point on the output, in surface-local coordinates. Setting this value @@ -196,6 +196,10 @@ The exclusive zone includes the margin. Margin is double-buffered, see wl_surface.commit. + + This request is deprecated since version 6. Use set_left_margin_{units,fraction}, + set_top_margin_{units,fraction}, set_right_margin_{units,fraction}, and + set_bottom_margin_{units,fraction} requests instead. @@ -401,7 +405,141 @@ The edge must be one the surface is anchored to, otherwise the invalid_exclusive_edge protocol error will be raised. - + + + + + + + + Sets the left margin in surface-local coordinates. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The left margin specified using set_left_margin_fraction will be + overwritten by this request. + + Margins are double-buffered, see wl_surface.commit. + + + + + + + Sets the left margin as a fraction of the available area width. The + margin value is a number between 0 and 1. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The left margin specified using set_left_margin_units will be + overwritten by this request. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + Sets the top margin in surface-local coordinates. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The top margin specified using set_top_margin_fraction will be + overwritten by this request. + + Margins are double-buffered, see wl_surface.commit. + + + + + + + Sets the top margin as a fraction of the available area height. The + margin value is a number between 0 and 1. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The top margin specified using set_top_margin_units will be + overwritten by this request. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + Sets the right margin in surface-local coordinates. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The right margin specified using set_right_margin_fraction will be + overwritten by this request. + + Margins are double-buffered, see wl_surface.commit. + + + + + + + Sets the right margin as a fraction of the available area width. The + margin value is a number between 0 and 1. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The right margin specified using set_right_margin_units will be + overwritten by this request. + + Margin is double-buffered, see wl_surface.commit. + + + + + + + Sets the bottom margin in surface-local coordinates. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The bottom margin specified using set_bottom_margin_fraction will be + overwritten by this request. + + Margins are double-buffered, see wl_surface.commit. + + + + + + + Sets the bottom margin as a fraction of the available area height. The + margin value is a number between 0 and 1. + + Margins specify that the surface should be placed some distance away + from the anchor point on the output. Setting a margin for an edge + you are not anchored to has no effect. + + The bottom margin specified using set_bottom_margin_units will be + overwritten by this request. + + Margin is double-buffered, see wl_surface.commit. + +