mirror of
https://invent.kde.org/plasma/layer-shell-qt.git
synced 2025-07-14 19:14:23 -04:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
2c903f3618 | |||
797c8b26ca | |||
32afbcf68a | |||
81782b38e4 | |||
4dfa7b53f1 | |||
aeb8d198ce | |||
f32b64244f | |||
9fb17e63b2 | |||
ec1a2d02fb | |||
c902d638ec | |||
176b7648d4 | |||
cce9896e42 | |||
f7fee6e7f6 | |||
66ec181e1e | |||
1abc1f381f | |||
47539db4b3 |
@ -4,13 +4,13 @@
|
|||||||
cmake_minimum_required(VERSION 3.16)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
project(layershellqt)
|
project(layershellqt)
|
||||||
set(PROJECT_VERSION "5.92.0")
|
set(PROJECT_VERSION "6.0.5")
|
||||||
set(PROJECT_VERSION_MAJOR 6)
|
set(PROJECT_VERSION_MAJOR 6)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
|
|
||||||
set(QT_MIN_VERSION "6.6.0")
|
set(QT_MIN_VERSION "6.6.0")
|
||||||
set(KF6_MIN_VERSION "5.240.0")
|
set(KF6_MIN_VERSION "6.0.0")
|
||||||
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
|
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
QString scope = QStringLiteral("window");
|
QString scope = QStringLiteral("window");
|
||||||
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
|
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
|
||||||
int32_t exclusionZone = 0;
|
int32_t exclusionZone = 0;
|
||||||
|
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;
|
QMargins margins;
|
||||||
@ -68,6 +69,21 @@ int32_t Window::exclusionZone() const
|
|||||||
return d->exclusionZone;
|
return d->exclusionZone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::setExclusiveEdge(Window::Anchor edge)
|
||||||
|
{
|
||||||
|
if (d->exclusiveEdge == edge) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->exclusiveEdge = edge;
|
||||||
|
Q_EMIT exclusiveEdgeChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::Anchor Window::exclusiveEdge() const
|
||||||
|
{
|
||||||
|
return d->exclusiveEdge;
|
||||||
|
}
|
||||||
|
|
||||||
void Window::setMargins(const QMargins &margins)
|
void Window::setMargins(const QMargins &margins)
|
||||||
{
|
{
|
||||||
if (d->margins != margins) {
|
if (d->margins != margins) {
|
||||||
|
@ -33,6 +33,7 @@ public:
|
|||||||
~Window() override;
|
~Window() override;
|
||||||
|
|
||||||
enum Anchor {
|
enum Anchor {
|
||||||
|
AnchorNone = 0,
|
||||||
AnchorTop = 1, ///< The top edge of the anchor rectangle
|
AnchorTop = 1, ///< The top edge of the anchor rectangle
|
||||||
AnchorBottom = 2, ///< The bottom edge of the anchor rectangle
|
AnchorBottom = 2, ///< The bottom edge of the anchor rectangle
|
||||||
AnchorLeft = 4, ///< The left edge of the anchor rectangle
|
AnchorLeft = 4, ///< The left edge of the anchor rectangle
|
||||||
@ -79,6 +80,9 @@ public:
|
|||||||
void setExclusiveZone(int32_t zone);
|
void setExclusiveZone(int32_t zone);
|
||||||
int32_t exclusionZone() const;
|
int32_t exclusionZone() const;
|
||||||
|
|
||||||
|
void setExclusiveEdge(Window::Anchor edge);
|
||||||
|
Window::Anchor exclusiveEdge() const;
|
||||||
|
|
||||||
void setMargins(const QMargins &margins);
|
void setMargins(const QMargins &margins);
|
||||||
QMargins margins() const;
|
QMargins margins() const;
|
||||||
|
|
||||||
@ -121,6 +125,7 @@ public:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void anchorsChanged();
|
void anchorsChanged();
|
||||||
void exclusionZoneChanged();
|
void exclusionZoneChanged();
|
||||||
|
void exclusiveEdgeChanged();
|
||||||
void marginsChanged();
|
void marginsChanged();
|
||||||
void keyboardInteractivityChanged();
|
void keyboardInteractivityChanged();
|
||||||
void layerChanged();
|
void layerChanged();
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
namespace LayerShellQt
|
namespace LayerShellQt
|
||||||
{
|
{
|
||||||
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
|
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
|
||||||
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(4)
|
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(5)
|
||||||
, m_xdgActivation(new QWaylandXdgActivationV1)
|
, m_xdgActivation(new QWaylandXdgActivationV1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
|||||||
, QtWayland::zwlr_layer_surface_v1()
|
, QtWayland::zwlr_layer_surface_v1()
|
||||||
, m_shell(shell)
|
, m_shell(shell)
|
||||||
, m_interface(Window::get(window->window()))
|
, m_interface(Window::get(window->window()))
|
||||||
|
, m_window(window)
|
||||||
{
|
{
|
||||||
wl_output *output = nullptr;
|
wl_output *output = nullptr;
|
||||||
if (m_interface->screenConfiguration() == Window::ScreenFromQWindow) {
|
if (m_interface->screenConfiguration() == Window::ScreenFromQWindow) {
|
||||||
@ -40,14 +41,20 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
|||||||
setLayer(m_interface->layer());
|
setLayer(m_interface->layer());
|
||||||
});
|
});
|
||||||
|
|
||||||
set_anchor(m_interface->anchors());
|
setAnchor(m_interface->anchors());
|
||||||
connect(m_interface, &Window::anchorsChanged, this, [this]() {
|
connect(m_interface, &Window::anchorsChanged, this, [this]() {
|
||||||
set_anchor(m_interface->anchors());
|
setAnchor(m_interface->anchors());
|
||||||
|
setDesiredSize(m_window->windowContentGeometry().size());
|
||||||
});
|
});
|
||||||
|
|
||||||
setExclusiveZone(m_interface->exclusionZone());
|
setExclusiveZone(m_interface->exclusionZone());
|
||||||
connect(m_interface, &Window::exclusionZoneChanged, this, [this]() {
|
connect(m_interface, &Window::exclusionZoneChanged, this, [this]() {
|
||||||
setExclusiveZone(m_interface->exclusionZone());
|
setExclusiveZone(m_interface->exclusionZone());
|
||||||
});
|
});
|
||||||
|
setExclusiveEdge(m_interface->exclusiveEdge());
|
||||||
|
connect(m_interface, &Window::exclusiveEdgeChanged, this, [this]() {
|
||||||
|
setExclusiveEdge(m_interface->exclusiveEdge());
|
||||||
|
});
|
||||||
|
|
||||||
setMargins(m_interface->margins());
|
setMargins(m_interface->margins());
|
||||||
connect(m_interface, &Window::marginsChanged, this, [this]() {
|
connect(m_interface, &Window::marginsChanged, this, [this]() {
|
||||||
@ -59,21 +66,14 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
|||||||
setKeyboardInteractivity(m_interface->keyboardInteractivity());
|
setKeyboardInteractivity(m_interface->keyboardInteractivity());
|
||||||
});
|
});
|
||||||
|
|
||||||
QSize size = window->surfaceSize();
|
setDesiredSize(window->windowContentGeometry().size());
|
||||||
const Window::Anchors anchors = m_interface->anchors();
|
|
||||||
if ((anchors & Window::AnchorLeft) && (anchors & Window::AnchorRight)) {
|
|
||||||
size.setWidth(0);
|
|
||||||
}
|
|
||||||
if ((anchors & Window::AnchorTop) && (anchors & Window::AnchorBottom)) {
|
|
||||||
size.setHeight(0);
|
|
||||||
}
|
|
||||||
if (size.isValid() && size != QSize(0, 0)) {
|
|
||||||
set_size(size.width(), size.height());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWaylandLayerSurface::~QWaylandLayerSurface()
|
QWaylandLayerSurface::~QWaylandLayerSurface()
|
||||||
{
|
{
|
||||||
|
if (m_waitForSyncCallback) {
|
||||||
|
wl_callback_destroy(m_waitForSyncCallback);
|
||||||
|
}
|
||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,8 +91,8 @@ void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint
|
|||||||
|
|
||||||
if (!m_configured) {
|
if (!m_configured) {
|
||||||
m_configured = true;
|
m_configured = true;
|
||||||
window()->resizeFromApplyConfigure(m_pendingSize);
|
applyConfigure();
|
||||||
window()->handleExpose(QRect(QPoint(), m_pendingSize));
|
sendExpose();
|
||||||
} else {
|
} else {
|
||||||
// Later configures are resizes, so we have to queue them up for a time when we
|
// Later configures are resizes, so we have to queue them up for a time when we
|
||||||
// are not painting to the window.
|
// are not painting to the window.
|
||||||
@ -113,13 +113,29 @@ void QWaylandLayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface *po
|
|||||||
|
|
||||||
void QWaylandLayerSurface::applyConfigure()
|
void QWaylandLayerSurface::applyConfigure()
|
||||||
{
|
{
|
||||||
|
m_configuring = true;
|
||||||
window()->resizeFromApplyConfigure(m_pendingSize);
|
window()->resizeFromApplyConfigure(m_pendingSize);
|
||||||
|
m_configuring = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandLayerSurface::setDesiredSize(const QSize &size)
|
||||||
|
{
|
||||||
|
const bool horizontallyConstrained = m_interface->anchors().testFlags({Window::AnchorLeft, Window::AnchorRight});
|
||||||
|
const bool verticallyConstrained = m_interface->anchors().testFlags({Window::AnchorTop, Window::AnchorBottom});
|
||||||
|
|
||||||
|
QSize effectiveSize = size;
|
||||||
|
if (horizontallyConstrained) {
|
||||||
|
effectiveSize.setWidth(0);
|
||||||
|
}
|
||||||
|
if (verticallyConstrained) {
|
||||||
|
effectiveSize.setHeight(0);
|
||||||
|
}
|
||||||
|
set_size(effectiveSize.width(), effectiveSize.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandLayerSurface::setAnchor(uint anchor)
|
void QWaylandLayerSurface::setAnchor(uint anchor)
|
||||||
{
|
{
|
||||||
set_anchor(anchor);
|
set_anchor(anchor);
|
||||||
setWindowGeometry(window()->windowContentGeometry());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWaylandLayerSurface::setExclusiveZone(int32_t zone)
|
void QWaylandLayerSurface::setExclusiveZone(int32_t zone)
|
||||||
@ -127,6 +143,13 @@ void QWaylandLayerSurface::setExclusiveZone(int32_t zone)
|
|||||||
set_exclusive_zone(zone);
|
set_exclusive_zone(zone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWaylandLayerSurface::setExclusiveEdge(uint32_t edge)
|
||||||
|
{
|
||||||
|
if (zwlr_layer_surface_v1_get_version(object()) >= ZWLR_LAYER_SURFACE_V1_SET_EXCLUSIVE_EDGE_SINCE_VERSION) {
|
||||||
|
set_exclusive_edge(edge);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QWaylandLayerSurface::setMargins(const QMargins &margins)
|
void QWaylandLayerSurface::setMargins(const QMargins &margins)
|
||||||
{
|
{
|
||||||
set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
|
set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
|
||||||
@ -145,17 +168,12 @@ void QWaylandLayerSurface::setLayer(uint32_t layer)
|
|||||||
|
|
||||||
void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry)
|
void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry)
|
||||||
{
|
{
|
||||||
const bool horizontallyConstrained = m_interface->anchors().testFlags({Window::AnchorLeft, Window::AnchorRight});
|
if (m_configuring) {
|
||||||
const bool verticallyConstrained = m_interface->anchors().testFlags({Window::AnchorTop, Window::AnchorBottom});
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QSize size = geometry.size();
|
setDesiredSize(geometry.size());
|
||||||
if (horizontallyConstrained) {
|
requestWaylandSync();
|
||||||
size.setWidth(0);
|
|
||||||
}
|
|
||||||
if (verticallyConstrained) {
|
|
||||||
size.setHeight(0);
|
|
||||||
}
|
|
||||||
set_size(size.width(), size.height());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWaylandLayerSurface::requestActivate()
|
bool QWaylandLayerSurface::requestActivate()
|
||||||
@ -204,7 +222,43 @@ void QWaylandLayerSurface::requestXdgActivationToken(quint32 serial)
|
|||||||
Q_EMIT window()->xdgActivationTokenCreated(token);
|
Q_EMIT window()->xdgActivationTokenCreated(token);
|
||||||
});
|
});
|
||||||
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater);
|
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater);
|
||||||
|
}
|
||||||
|
|
||||||
|
const wl_callback_listener QWaylandLayerSurface::syncCallbackListener = {
|
||||||
|
.done = [](void *data, struct wl_callback *callback, uint32_t time){
|
||||||
|
Q_UNUSED(time);
|
||||||
|
wl_callback_destroy(callback);
|
||||||
|
QWaylandLayerSurface *layerSurface = static_cast<QWaylandLayerSurface *>(data);
|
||||||
|
layerSurface->m_waitForSyncCallback = nullptr;
|
||||||
|
layerSurface->sendExpose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void QWaylandLayerSurface::requestWaylandSync()
|
||||||
|
{
|
||||||
|
if (m_waitForSyncCallback) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_waitForSyncCallback = wl_display_sync(m_window->display()->wl_display());
|
||||||
|
wl_callback_add_listener(m_waitForSyncCallback, &syncCallbackListener, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandLayerSurface::handleWaylandSyncDone()
|
||||||
|
{
|
||||||
|
if (!window()->isExposed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sendExpose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWaylandLayerSurface::sendExpose()
|
||||||
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
|
||||||
|
window()->handleExpose(QRect(QPoint(), m_pendingSize));
|
||||||
|
#else
|
||||||
|
window()->sendRecursiveExposeEvent();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -30,12 +30,14 @@ public:
|
|||||||
|
|
||||||
bool isExposed() const override
|
bool isExposed() const override
|
||||||
{
|
{
|
||||||
return m_configured;
|
return m_configured && !m_waitForSyncCallback;
|
||||||
}
|
}
|
||||||
void attachPopup(QtWaylandClient::QWaylandShellSurface *popup) override;
|
void attachPopup(QtWaylandClient::QWaylandShellSurface *popup) override;
|
||||||
|
|
||||||
|
void setDesiredSize(const QSize &size);
|
||||||
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 setMargins(const QMargins &margins);
|
void setMargins(const QMargins &margins);
|
||||||
void setKeyboardInteractivity(uint32_t interactivity);
|
void setKeyboardInteractivity(uint32_t interactivity);
|
||||||
void setLayer(uint32_t layer);
|
void setLayer(uint32_t layer);
|
||||||
@ -48,14 +50,23 @@ public:
|
|||||||
void requestXdgActivationToken(quint32 serial) override;
|
void requestXdgActivationToken(quint32 serial) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void requestWaylandSync();
|
||||||
|
void handleWaylandSyncDone();
|
||||||
|
void sendExpose();
|
||||||
void zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) override;
|
void zwlr_layer_surface_v1_configure(uint32_t serial, uint32_t width, uint32_t height) override;
|
||||||
void zwlr_layer_surface_v1_closed() override;
|
void zwlr_layer_surface_v1_closed() override;
|
||||||
|
|
||||||
QWaylandLayerShellIntegration *m_shell;
|
QWaylandLayerShellIntegration *m_shell;
|
||||||
LayerShellQt::Window *m_interface;
|
LayerShellQt::Window *m_interface;
|
||||||
|
QtWaylandClient::QWaylandWindow *m_window;
|
||||||
QSize m_pendingSize;
|
QSize m_pendingSize;
|
||||||
QString m_activationToken;
|
QString m_activationToken;
|
||||||
|
|
||||||
bool m_configured = false;
|
bool m_configured = false;
|
||||||
|
bool m_configuring = false;
|
||||||
|
|
||||||
|
static const wl_callback_listener syncCallbackListener;
|
||||||
|
struct wl_callback *m_waitForSyncCallback = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
THIS SOFTWARE.
|
THIS SOFTWARE.
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
<interface name="zwlr_layer_shell_v1" version="4">
|
<interface name="zwlr_layer_shell_v1" version="5">
|
||||||
<description summary="create surfaces that are layers of the desktop">
|
<description summary="create surfaces that are layers of the desktop">
|
||||||
Clients can use this interface to assign the surface_layer role to
|
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
|
wl_surfaces. Such surfaces are assigned to a "layer" of the output and
|
||||||
@ -100,7 +100,7 @@
|
|||||||
</request>
|
</request>
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<interface name="zwlr_layer_surface_v1" version="4">
|
<interface name="zwlr_layer_surface_v1" version="5">
|
||||||
<description summary="layer metadata interface">
|
<description summary="layer metadata interface">
|
||||||
An interface that may be implemented by a wl_surface, for surfaces that
|
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
|
are designed to be rendered as a layer of a stacked desktop-like
|
||||||
@ -367,6 +367,7 @@
|
|||||||
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
<entry name="invalid_size" value="1" summary="size is invalid"/>
|
||||||
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
<entry name="invalid_anchor" value="2" summary="anchor bitfield is invalid"/>
|
||||||
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
<entry name="invalid_keyboard_interactivity" value="3" summary="keyboard interactivity is invalid"/>
|
||||||
|
<entry name="invalid_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
<enum name="anchor" bitfield="true">
|
<enum name="anchor" bitfield="true">
|
||||||
@ -386,5 +387,21 @@
|
|||||||
</description>
|
</description>
|
||||||
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
||||||
</request>
|
</request>
|
||||||
|
|
||||||
|
<!-- Version 5 additions -->
|
||||||
|
|
||||||
|
<request name="set_exclusive_edge" since="5">
|
||||||
|
<description summary="set the edge the exclusive zone will be applied to">
|
||||||
|
Requests an edge for the exclusive zone to apply. The exclusive
|
||||||
|
edge will be automatically deduced from anchor points when possible,
|
||||||
|
but when the surface is anchored to a corner, it will be necessary
|
||||||
|
to set it explicitly to disambiguate, as it is not possible to deduce
|
||||||
|
which one of the two corner edges should be used.
|
||||||
|
|
||||||
|
The edge must be one the surface is anchored to, otherwise the
|
||||||
|
invalid_exclusive_edge protocol error will be raised.
|
||||||
|
</description>
|
||||||
|
<arg name="edge" type="uint"/>
|
||||||
|
</request>
|
||||||
</interface>
|
</interface>
|
||||||
</protocol>
|
</protocol>
|
||||||
|
Reference in New Issue
Block a user