mirror of
https://invent.kde.org/plasma/layer-shell-qt.git
synced 2025-07-14 11:04:20 -04:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
9fb17e63b2 | |||
ec1a2d02fb | |||
c902d638ec | |||
176b7648d4 | |||
cce9896e42 | |||
f7fee6e7f6 | |||
66ec181e1e | |||
1abc1f381f | |||
47539db4b3 | |||
078f36f8f3 | |||
7d3194034c | |||
e3098a660a | |||
d379bc8d8e |
@ -4,13 +4,13 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
project(layershellqt)
|
||||
set(PROJECT_VERSION "5.91.0")
|
||||
set(PROJECT_VERSION "6.0.1")
|
||||
set(PROJECT_VERSION_MAJOR 6)
|
||||
|
||||
set(CMAKE_C_STANDARD 99)
|
||||
|
||||
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(CMAKE_CXX_STANDARD 20)
|
||||
@ -30,6 +30,7 @@ include(FeatureSummary)
|
||||
include(GenerateExportHeader)
|
||||
include(KDEClangFormat)
|
||||
include(ECMQtDeclareLoggingCategory)
|
||||
include(ECMQmlModule)
|
||||
|
||||
|
||||
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient Qml)
|
||||
|
@ -1,9 +1,10 @@
|
||||
# SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleix.pol_gonzalez@mercedes-benz.com>
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
qt_add_qml_module(LayerShellQtQml
|
||||
ecm_add_qml_module(LayerShellQtQml
|
||||
URI "org.kde.layershell"
|
||||
VERSION 1.0
|
||||
SOURCES layershellqtplugin.cpp)
|
||||
target_link_libraries(LayerShellQtQml PRIVATE Qt::Qml LayerShellQtInterface)
|
||||
|
||||
ecm_finalize_qml_module(LayerShellQtQml DESTINATION ${KDE_INSTALL_QMLDIR})
|
@ -28,6 +28,7 @@ public:
|
||||
QString scope = QStringLiteral("window");
|
||||
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
|
||||
int32_t exclusionZone = 0;
|
||||
Window::Anchor exclusiveEdge = Window::AnchorNone;
|
||||
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand;
|
||||
Window::Layer layer = Window::LayerTop;
|
||||
QMargins margins;
|
||||
@ -68,6 +69,21 @@ int32_t Window::exclusionZone() const
|
||||
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)
|
||||
{
|
||||
if (d->margins != margins) {
|
||||
|
@ -33,6 +33,7 @@ public:
|
||||
~Window() override;
|
||||
|
||||
enum Anchor {
|
||||
AnchorNone = 0,
|
||||
AnchorTop = 1, ///< The top edge of the anchor rectangle
|
||||
AnchorBottom = 2, ///< The bottom edge of the anchor rectangle
|
||||
AnchorLeft = 4, ///< The left edge of the anchor rectangle
|
||||
@ -79,6 +80,9 @@ public:
|
||||
void setExclusiveZone(int32_t zone);
|
||||
int32_t exclusionZone() const;
|
||||
|
||||
void setExclusiveEdge(Window::Anchor edge);
|
||||
Window::Anchor exclusiveEdge() const;
|
||||
|
||||
void setMargins(const QMargins &margins);
|
||||
QMargins margins() const;
|
||||
|
||||
@ -121,6 +125,7 @@ public:
|
||||
Q_SIGNALS:
|
||||
void anchorsChanged();
|
||||
void exclusionZoneChanged();
|
||||
void exclusiveEdgeChanged();
|
||||
void marginsChanged();
|
||||
void keyboardInteractivityChanged();
|
||||
void layerChanged();
|
||||
|
@ -15,7 +15,7 @@
|
||||
namespace LayerShellQt
|
||||
{
|
||||
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
|
||||
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(4)
|
||||
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(5)
|
||||
, m_xdgActivation(new QWaylandXdgActivationV1)
|
||||
{
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
||||
, QtWayland::zwlr_layer_surface_v1()
|
||||
, m_shell(shell)
|
||||
, m_interface(Window::get(window->window()))
|
||||
, m_window(window)
|
||||
{
|
||||
wl_output *output = nullptr;
|
||||
if (m_interface->screenConfiguration() == Window::ScreenFromQWindow) {
|
||||
@ -48,6 +49,10 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
||||
connect(m_interface, &Window::exclusionZoneChanged, this, [this]() {
|
||||
setExclusiveZone(m_interface->exclusionZone());
|
||||
});
|
||||
setExclusiveEdge(m_interface->exclusiveEdge());
|
||||
connect(m_interface, &Window::exclusiveEdgeChanged, this, [this]() {
|
||||
setExclusiveEdge(m_interface->exclusiveEdge());
|
||||
});
|
||||
|
||||
setMargins(m_interface->margins());
|
||||
connect(m_interface, &Window::marginsChanged, this, [this]() {
|
||||
@ -74,6 +79,9 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
|
||||
|
||||
QWaylandLayerSurface::~QWaylandLayerSurface()
|
||||
{
|
||||
if (m_waitForSyncCallback) {
|
||||
wl_callback_destroy(m_waitForSyncCallback);
|
||||
}
|
||||
destroy();
|
||||
}
|
||||
|
||||
@ -92,7 +100,7 @@ void QWaylandLayerSurface::zwlr_layer_surface_v1_configure(uint32_t serial, uint
|
||||
if (!m_configured) {
|
||||
m_configured = true;
|
||||
window()->resizeFromApplyConfigure(m_pendingSize);
|
||||
window()->handleExpose(QRect(QPoint(), m_pendingSize));
|
||||
sendExpose();
|
||||
} else {
|
||||
// Later configures are resizes, so we have to queue them up for a time when we
|
||||
// are not painting to the window.
|
||||
@ -119,6 +127,7 @@ void QWaylandLayerSurface::applyConfigure()
|
||||
void QWaylandLayerSurface::setAnchor(uint anchor)
|
||||
{
|
||||
set_anchor(anchor);
|
||||
setWindowGeometry(window()->windowContentGeometry());
|
||||
}
|
||||
|
||||
void QWaylandLayerSurface::setExclusiveZone(int32_t zone)
|
||||
@ -126,6 +135,13 @@ void QWaylandLayerSurface::setExclusiveZone(int32_t 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)
|
||||
{
|
||||
set_margin(margins.top(), margins.right(), margins.bottom(), margins.left());
|
||||
@ -144,8 +160,13 @@ void QWaylandLayerSurface::setLayer(uint32_t layer)
|
||||
|
||||
void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry)
|
||||
{
|
||||
const bool horizontallyConstrained = m_interface->anchors() & (Window::AnchorLeft & Window::AnchorRight);
|
||||
const bool verticallyConstrained = m_interface->anchors() & (Window::AnchorTop & Window::AnchorBottom);
|
||||
// if we are setting it to the last size we were configured at, we don't need to do anything
|
||||
if (geometry.size() == m_pendingSize && !m_waitForSyncCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bool horizontallyConstrained = m_interface->anchors().testFlags({Window::AnchorLeft, Window::AnchorRight});
|
||||
const bool verticallyConstrained = m_interface->anchors().testFlags({Window::AnchorTop, Window::AnchorBottom});
|
||||
|
||||
QSize size = geometry.size();
|
||||
if (horizontallyConstrained) {
|
||||
@ -155,6 +176,7 @@ void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry)
|
||||
size.setHeight(0);
|
||||
}
|
||||
set_size(size.width(), size.height());
|
||||
requestWaylandSync();
|
||||
}
|
||||
|
||||
bool QWaylandLayerSurface::requestActivate()
|
||||
@ -203,7 +225,43 @@ void QWaylandLayerSurface::requestXdgActivationToken(quint32 serial)
|
||||
Q_EMIT window()->xdgActivationTokenCreated(token);
|
||||
});
|
||||
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,13 @@ public:
|
||||
|
||||
bool isExposed() const override
|
||||
{
|
||||
return m_configured;
|
||||
return m_configured && !m_waitForSyncCallback;
|
||||
}
|
||||
void attachPopup(QtWaylandClient::QWaylandShellSurface *popup) override;
|
||||
|
||||
void setAnchor(uint32_t anchor);
|
||||
void setExclusiveZone(int32_t zone);
|
||||
void setExclusiveEdge(uint32_t edge);
|
||||
void setMargins(const QMargins &margins);
|
||||
void setKeyboardInteractivity(uint32_t interactivity);
|
||||
void setLayer(uint32_t layer);
|
||||
@ -48,14 +49,22 @@ public:
|
||||
void requestXdgActivationToken(quint32 serial) override;
|
||||
|
||||
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_closed() override;
|
||||
|
||||
QWaylandLayerShellIntegration *m_shell;
|
||||
LayerShellQt::Window *m_interface;
|
||||
QtWaylandClient::QWaylandWindow *m_window;
|
||||
QSize m_pendingSize;
|
||||
QString m_activationToken;
|
||||
|
||||
bool m_configured = false;
|
||||
|
||||
static const wl_callback_listener syncCallbackListener;
|
||||
struct wl_callback *m_waitForSyncCallback = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
THIS SOFTWARE.
|
||||
</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">
|
||||
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 @@
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="zwlr_layer_surface_v1" version="4">
|
||||
<interface name="zwlr_layer_surface_v1" version="5">
|
||||
<description summary="layer metadata interface">
|
||||
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
|
||||
@ -367,6 +367,7 @@
|
||||
<entry name="invalid_size" value="1" summary="size 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_exclusive_edge" value="4" summary="exclusive edge is invalid given the surface anchors"/>
|
||||
</enum>
|
||||
|
||||
<enum name="anchor" bitfield="true">
|
||||
@ -386,5 +387,21 @@
|
||||
</description>
|
||||
<arg name="layer" type="uint" enum="zwlr_layer_shell_v1.layer" summary="layer to move this surface to"/>
|
||||
</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>
|
||||
</protocol>
|
||||
|
Reference in New Issue
Block a user