mirror of
https://invent.kde.org/plasma/layer-shell-qt.git
synced 2025-11-26 11:42:43 -05:00
RFC: Allow specifying margins in percents
Absolute margin values pose a problem if you want to place a surface certain distance away from a screen edge (in percents) but you also want the compositor to place the surface on the active output. At the moment, this issue is worked around by using kwin dbus api to query the active output. This is not good. This change is a take on allowing to specify margin values in percents. It can be used to drop a dbus call in krunner and assist us with porting other components to layer shell, e.g. OSDs, they also need to be placed one third away the bottom screen edge.
This commit is contained in:
@ -17,6 +17,49 @@
|
|||||||
|
|
||||||
using namespace LayerShellQt;
|
using namespace LayerShellQt;
|
||||||
|
|
||||||
|
Margin::Margin()
|
||||||
|
: m_value(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Margin::Margin(int pixels)
|
||||||
|
: m_value(pixels)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Margin::Margin(qreal percents)
|
||||||
|
: m_value(percents)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Margin Margin::fromPixels(int pixels)
|
||||||
|
{
|
||||||
|
return Margin(pixels);
|
||||||
|
}
|
||||||
|
|
||||||
|
Margin Margin::fromPercents(qreal percents)
|
||||||
|
{
|
||||||
|
return Margin(percents);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<int> Margin::pixels() const
|
||||||
|
{
|
||||||
|
if (std::holds_alternative<int>(m_value)) {
|
||||||
|
return std::get<int>(m_value);
|
||||||
|
} else {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<qreal> Margin::percents() const
|
||||||
|
{
|
||||||
|
if (std::holds_alternative<qreal>(m_value)) {
|
||||||
|
return std::get<qreal>(m_value);
|
||||||
|
} else {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class LayerShellQt::WindowPrivate
|
class LayerShellQt::WindowPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -32,7 +75,10 @@ public:
|
|||||||
Window::Anchor exclusiveEdge = Window::AnchorNone;
|
Window::Anchor exclusiveEdge = Window::AnchorNone;
|
||||||
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand;
|
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand;
|
||||||
Window::Layer layer = Window::LayerTop;
|
Window::Layer layer = Window::LayerTop;
|
||||||
QMargins margins;
|
Margin leftMargin;
|
||||||
|
Margin topMargin;
|
||||||
|
Margin rightMargin;
|
||||||
|
Margin bottomMargin;
|
||||||
QSize desiredSize = QSize(0, 0);
|
QSize desiredSize = QSize(0, 0);
|
||||||
Window::ScreenConfiguration screenConfiguration = Window::ScreenFromQWindow;
|
Window::ScreenConfiguration screenConfiguration = Window::ScreenFromQWindow;
|
||||||
bool closeOnDismissed = true;
|
bool closeOnDismissed = true;
|
||||||
@ -89,15 +135,74 @@ Window::Anchor Window::exclusiveEdge() const
|
|||||||
|
|
||||||
void Window::setMargins(const QMargins &margins)
|
void Window::setMargins(const QMargins &margins)
|
||||||
{
|
{
|
||||||
if (d->margins != margins) {
|
setLeftMargin(Margin::fromPixels(margins.left()));
|
||||||
d->margins = margins;
|
setTopMargin(Margin::fromPixels(margins.top()));
|
||||||
Q_EMIT marginsChanged();
|
setRightMargin(Margin::fromPixels(margins.right()));
|
||||||
}
|
setBottomMargin(Margin::fromPixels(margins.bottom()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QMargins Window::margins() const
|
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)
|
void Window::setDesiredSize(const QSize &size)
|
||||||
|
|||||||
@ -18,6 +18,34 @@ namespace LayerShellQt
|
|||||||
{
|
{
|
||||||
class WindowPrivate;
|
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 fromPercents(qreal percents);
|
||||||
|
|
||||||
|
Margin();
|
||||||
|
|
||||||
|
std::optional<int> pixels() const;
|
||||||
|
std::optional<qreal> percents() const;
|
||||||
|
|
||||||
|
auto operator<=>(const Margin &other) const = default;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Margin(int pixels);
|
||||||
|
Margin(qreal percents);
|
||||||
|
|
||||||
|
std::variant<int, qreal> m_value;
|
||||||
|
};
|
||||||
|
|
||||||
class LAYERSHELLQT_EXPORT Window : public QObject
|
class LAYERSHELLQT_EXPORT Window : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -87,6 +115,18 @@ public:
|
|||||||
void setMargins(const QMargins &margins);
|
void setMargins(const QMargins &margins);
|
||||||
QMargins margins() const;
|
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);
|
void setDesiredSize(const QSize &size);
|
||||||
QSize desiredSize() const;
|
QSize desiredSize() const;
|
||||||
|
|
||||||
@ -145,6 +185,10 @@ Q_SIGNALS:
|
|||||||
void exclusionZoneChanged();
|
void exclusionZoneChanged();
|
||||||
void exclusiveEdgeChanged();
|
void exclusiveEdgeChanged();
|
||||||
void marginsChanged();
|
void marginsChanged();
|
||||||
|
void leftMarginChanged();
|
||||||
|
void topMarginChanged();
|
||||||
|
void rightMarginChanged();
|
||||||
|
void bottomMarginChanged();
|
||||||
void desiredSizeChanged();
|
void desiredSizeChanged();
|
||||||
void keyboardInteractivityChanged();
|
void keyboardInteractivityChanged();
|
||||||
void layerChanged();
|
void layerChanged();
|
||||||
|
|||||||
@ -60,9 +60,24 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
|||||||
setExclusiveEdge(m_interface->exclusiveEdge());
|
setExclusiveEdge(m_interface->exclusiveEdge());
|
||||||
});
|
});
|
||||||
|
|
||||||
setMargins(m_interface->margins());
|
setLeftMargin(m_interface->leftMargin());
|
||||||
connect(m_interface, &Window::marginsChanged, this, [this]() {
|
connect(m_interface, &Window::leftMarginChanged, this, [this]() {
|
||||||
setMargins(m_interface->margins());
|
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]() {
|
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_absolute(*pixels);
|
||||||
|
} else if (const auto percents = margin.percents()) {
|
||||||
|
set_left_margin_percents(wl_fixed_from_double(*percents));
|
||||||
|
} 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_absolute(*pixels);
|
||||||
|
} else if (const auto percents = margin.percents()) {
|
||||||
|
set_top_margin_percents(wl_fixed_from_double(*percents));
|
||||||
|
} 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_absolute(*pixels);
|
||||||
|
} else if (const auto percents = margin.percents()) {
|
||||||
|
set_right_margin_percents(wl_fixed_from_double(*percents));
|
||||||
|
} 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_absolute(*pixels);
|
||||||
|
} else if (const auto percents = margin.percents()) {
|
||||||
|
set_bottom_margin_percents(wl_fixed_from_double(*percents));
|
||||||
|
} 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)
|
void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity)
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
namespace LayerShellQt
|
namespace LayerShellQt
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class Margin;
|
||||||
class Window;
|
class Window;
|
||||||
|
|
||||||
class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1
|
class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylandShellSurface, public QtWayland::zwlr_layer_surface_v1
|
||||||
@ -38,7 +39,10 @@ public:
|
|||||||
void setAnchor(uint32_t anchor);
|
void setAnchor(uint32_t anchor);
|
||||||
void setExclusiveZone(int32_t zone);
|
void setExclusiveZone(int32_t zone);
|
||||||
void setExclusiveEdge(uint32_t edge);
|
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 setKeyboardInteractivity(uint32_t interactivity);
|
||||||
void setLayer(uint32_t layer);
|
void setLayer(uint32_t layer);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user