Compare commits

..

1 Commits

Author SHA1 Message Date
33b30114a4 QDoc port 2024-09-14 16:01:55 +02:00
18 changed files with 267 additions and 345 deletions

View File

@ -7,6 +7,3 @@ include:
- /gitlab-templates/reuse-lint.yml - /gitlab-templates/reuse-lint.yml
- /gitlab-templates/linux-qt6.yml - /gitlab-templates/linux-qt6.yml
- /gitlab-templates/freebsd-qt6.yml - /gitlab-templates/freebsd-qt6.yml
- /gitlab-templates/xml-lint.yml
- /gitlab-templates/yaml-lint.yml
- /gitlab-templates/linux-qt6-next.yml

View File

@ -2,11 +2,11 @@
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
Dependencies: Dependencies:
- 'on': ['@all'] - 'on': ['@all']
'require': 'require':
'frameworks/extra-cmake-modules': '@latest-kf6' 'frameworks/extra-cmake-modules': '@latest-kf6'
'third-party/wayland': '@latest' 'third-party/wayland': '@latest'
'third-party/wayland-protocols': '@latest' 'third-party/wayland-protocols': '@latest'
Options: Options:
require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows'] require-passing-tests-on: ['Linux', 'FreeBSD', 'Windows']

View File

@ -4,13 +4,13 @@
cmake_minimum_required(VERSION 3.16) cmake_minimum_required(VERSION 3.16)
project(layershellqt) project(layershellqt)
set(PROJECT_VERSION "6.6.80") set(PROJECT_VERSION "6.1.90")
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.10.0") set(QT_MIN_VERSION "6.7.0")
set(KF6_MIN_VERSION "6.22.0") set(KF6_MIN_VERSION "6.5.0")
set(KDE_COMPILERSETTINGS_LEVEL "5.82") set(KDE_COMPILERSETTINGS_LEVEL "5.82")
set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD 20)
@ -32,14 +32,9 @@ include(KDEClangFormat)
include(ECMQtDeclareLoggingCategory) include(ECMQtDeclareLoggingCategory)
include(ECMQmlModule) include(ECMQmlModule)
include(KDEGitCommitHooks) include(KDEGitCommitHooks)
include(ECMGenerateExportHeader) include(ECMGenerateQDoc)
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient Qml) find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient Qml)
if (Qt6WaylandClient_VERSION VERSION_GREATER_EQUAL "6.10.0")
find_package(Qt6WaylandClientPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE)
endif()
find_package(WaylandScanner REQUIRED) find_package(WaylandScanner REQUIRED)
find_package(Wayland 1.3 COMPONENTS Client Server) find_package(Wayland 1.3 COMPONENTS Client Server)
find_package(WaylandProtocols REQUIRED) find_package(WaylandProtocols REQUIRED)
@ -61,8 +56,8 @@ kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT) kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
ecm_set_disabled_deprecation_versions(QT 6.8.1 ecm_set_disabled_deprecation_versions(QT 6.5
KF 6.9.0 KF 5.240
) )
add_subdirectory(src) add_subdirectory(src)

View File

@ -2,7 +2,7 @@
# SPDX-License-Identifier: CC0-1.0 # SPDX-License-Identifier: CC0-1.0
maintainer: maintainer:
- vladz - vladz
description: Layer Shell Qt description: Layer Shell Qt
platforms: platforms:
- name: Linux - name: Linux

View File

@ -5,8 +5,6 @@ remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS)
add_library(LayerShellQtInterface) add_library(LayerShellQtInterface)
qt6_extract_metatypes(LayerShellQtInterface)
if (Qt6_VERSION VERSION_GREATER_EQUAL "6.8.0") if (Qt6_VERSION VERSION_GREATER_EQUAL "6.8.0")
set(private_code_option "PRIVATE_CODE") set(private_code_option "PRIVATE_CODE")
endif() endif()
@ -64,14 +62,14 @@ ecm_generate_headers(LayerShellQt_HEADERS
) )
ecm_generate_export_header(LayerShellQtInterface generate_export_header(LayerShellQtInterface
BASE_NAME LayerShellQtInterface BASE_NAME LayerShellQtInterface
EXPORT_MACRO_NAME LAYERSHELLQT_EXPORT EXPORT_MACRO_NAME LAYERSHELLQT_EXPORT
EXPORT_FILE_NAME LayerShellQt/layershellqt_export.h EXPORT_FILE_NAME LayerShellQt/layershellqt_export.h
VERSION ${LAYERSHELLQT_VERSION}
DEPRECATION_VERSIONS 6.6
) )
ecm_generate_qdoc(LayerShellQtInterface layershellqt.qdocconf)
install(TARGETS layer-shell install(TARGETS layer-shell
LIBRARY DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/wayland-shell-integration) LIBRARY DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/wayland-shell-integration)

View File

@ -4,8 +4,7 @@
ecm_add_qml_module(LayerShellQtQml ecm_add_qml_module(LayerShellQtQml
URI "org.kde.layershell" URI "org.kde.layershell"
VERSION 1.0 VERSION 1.0
SOURCES types.h SOURCES layershellqtplugin.cpp)
GENERATE_PLUGIN_SOURCE)
target_link_libraries(LayerShellQtQml PRIVATE Qt::Qml LayerShellQtInterface) target_link_libraries(LayerShellQtQml PRIVATE Qt::Qml LayerShellQtInterface)
ecm_finalize_qml_module(LayerShellQtQml DESTINATION ${KDE_INSTALL_QMLDIR}) ecm_finalize_qml_module(LayerShellQtQml DESTINATION ${KDE_INSTALL_QMLDIR})

View File

@ -0,0 +1,51 @@
/*
* SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleix.pol_gonzalez@mercedes-benz.com>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "../interfaces/window.h"
#include <QQmlExtensionPlugin>
#include <qqml.h>
QML_DECLARE_TYPEINFO(LayerShellQt::Window, QML_HAS_ATTACHED_PROPERTIES)
class ExtQMargins
{
QMargins m_margins;
Q_GADGET
Q_PROPERTY(int left READ left WRITE setLeft FINAL)
Q_PROPERTY(int right READ right WRITE setRight FINAL)
Q_PROPERTY(int top READ top WRITE setTop FINAL)
Q_PROPERTY(int bottom READ bottom WRITE setBottom FINAL)
QML_FOREIGN(QMargins)
QML_EXTENDED(ExtQMargins)
public:
ExtQMargins(const QMargins &margins);
int left() const { return m_margins.left(); }
void setLeft(int left) { m_margins.setLeft(left); }
int right() const { return m_margins.right(); }
void setRight(int right) { m_margins.setRight(right); }
int top() const { return m_margins.top(); }
void setTop(int top) { m_margins.setTop(top); }
int bottom() const { return m_margins.bottom(); }
void setBottom(int bottom) { m_margins.setBottom(bottom); }
};
class Plugin : public QQmlExtensionPlugin
{
Q_PLUGIN_METADATA(IID "org.kde.layershellqt")
Q_OBJECT
public:
void registerTypes(const char *uri) override
{
Q_ASSERT(QLatin1String(uri) == QLatin1String("org.kde.layershell"));
qmlRegisterType<LayerShellQt::Window>(uri, 1, 0, "Window");
qmlRegisterExtendedUncreatableType<QMargins, ExtQMargins>(uri, 1, 0, "ExtQMargins", QStringLiteral("Only created from C++"));
}
};
#include "layershellqtplugin.moc"

View File

@ -1,19 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleix.pol_gonzalez@mercedes-benz.com>
*
* SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "../interfaces/window.h"
#include <qqml.h>
QML_DECLARE_TYPEINFO(LayerShellQt::Window, QML_HAS_ATTACHED_PROPERTIES)
class WindowForeign
{
Q_GADGET
QML_NAMED_ELEMENT(Window)
QML_FOREIGN(LayerShellQt::Window)
QML_UNCREATABLE("")
QML_ATTACHED(LayerShellQt::Window)
};

View File

@ -5,9 +5,6 @@
*/ */
#include "shell.h" #include "shell.h"
#if LAYERSHELLQTINTERFACE_BUILD_DEPRECATED_SINCE(6, 6)
#include <QByteArray> #include <QByteArray>
#include <layershellqt_logging.h> #include <layershellqt_logging.h>
#include <qglobal.h> #include <qglobal.h>
@ -21,4 +18,3 @@ void Shell::useLayerShell()
qCDebug(LAYERSHELLQT) << "Unable to set QT_WAYLAND_SHELL_INTEGRATION=layer-shell"; qCDebug(LAYERSHELLQT) << "Unable to set QT_WAYLAND_SHELL_INTEGRATION=layer-shell";
} }
} }
#endif

View File

@ -8,24 +8,26 @@
#define LAYERSHELLQTSHELL_H #define LAYERSHELLQTSHELL_H
#include "layershellqt_export.h" #include "layershellqt_export.h"
#include "window.h"
#if LAYERSHELLQTINTERFACE_ENABLE_DEPRECATED_SINCE(6, 6)
#include <QString> #include <QString>
namespace LayerShellQt namespace LayerShellQt
{ {
/** /*!
* Sets the right environment so the shells created from now on use wlr-layer-shell. * \class LayerShellQt::Shell
* \inmodule LayerShellQt
* \inheaderfile LayerShellQt/Shell
*
*/ */
class LAYERSHELLQT_EXPORT Shell class LAYERSHELLQT_EXPORT Shell
{ {
public: public:
LAYERSHELLQTINTERFACE_DEPRECATED_VERSION(6, 6, "Calling useLayerShell is not needed since Qt 6.5") /*!
* Sets the right environment so the shells created from now on use wlr-layer-shell.
*/
static void useLayerShell(); static void useLayerShell();
}; };
} }
#endif
#endif #endif

View File

@ -9,9 +9,7 @@
#include <layershellqt_logging.h> #include <layershellqt_logging.h>
#include <QPlatformSurfaceEvent>
#include <QPointer> #include <QPointer>
#include <mutex>
#include <optional> #include <optional>
#include <QtWaylandClient/private/qwaylandwindow_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h>
@ -34,11 +32,8 @@ public:
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand; Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityOnDemand;
Window::Layer layer = Window::LayerTop; Window::Layer layer = Window::LayerTop;
QMargins margins; QMargins margins;
QSize desiredSize = QSize(0, 0); Window::ScreenConfiguration screenConfiguration = Window::ScreenFromQWindow;
QPointer<QScreen> screen;
bool wantsToBeOnActiveScreen = false;
bool closeOnDismissed = true; bool closeOnDismissed = true;
bool activateOnShow = true;
}; };
static QMap<QWindow *, Window *> s_map; static QMap<QWindow *, Window *> s_map;
@ -102,21 +97,6 @@ QMargins Window::margins() const
return d->margins; return d->margins;
} }
void Window::setDesiredSize(const QSize &size)
{
if (size == d->desiredSize) {
return;
}
d->desiredSize = size;
Q_EMIT desiredSizeChanged();
}
QSize Window::desiredSize() const
{
return d->desiredSize;
}
void Window::setKeyboardInteractivity(KeyboardInteractivity interactivity) void Window::setKeyboardInteractivity(KeyboardInteractivity interactivity)
{ {
if (d->keyboardInteractivity != interactivity) { if (d->keyboardInteractivity != interactivity) {
@ -154,73 +134,14 @@ Window::Layer Window::layer() const
return d->layer; return d->layer;
} }
#if LAYERSHELLQTINTERFACE_BUILD_DEPRECATED_SINCE(6, 6)
Window::ScreenConfiguration Window::screenConfiguration() const Window::ScreenConfiguration Window::screenConfiguration() const
{ {
if (wantsToBeOnActiveScreen()) { return d->screenConfiguration;
return ScreenFromCompositor;
} else {
// If an explicit screen is set, it's quite inaccurate but it should be fine.
return ScreenFromQWindow;
}
} }
void Window::setScreenConfiguration(ScreenConfiguration screenConfiguration) void Window::setScreenConfiguration(Window::ScreenConfiguration screenConfiguration)
{ {
static std::once_flag deprecationFlag; d->screenConfiguration = screenConfiguration;
std::call_once(deprecationFlag, []() {
qWarning() << "LayerShellQt.Window.screenConfiguration is deprecated use screen and wantsToBeOnActiveScreen instead";
});
if (screenConfiguration == ScreenFromCompositor) {
setWantsToBeOnActiveScreen(true);
} else {
setWantsToBeOnActiveScreen(false);
setScreen(nullptr);
}
}
#endif
void Window::setWantsToBeOnActiveScreen(bool set)
{
if (d->wantsToBeOnActiveScreen == set) {
return;
}
d->wantsToBeOnActiveScreen = set;
if (d->wantsToBeOnActiveScreen && d->screen) {
d->screen = nullptr;
Q_EMIT screenChanged();
}
Q_EMIT wantsToBeOnActiveScreenChanged();
}
bool Window::wantsToBeOnActiveScreen() const
{
return d->wantsToBeOnActiveScreen;
}
void Window::setScreen(QScreen *screen)
{
if (d->screen == screen) {
return;
}
d->screen = screen;
if (d->screen && d->wantsToBeOnActiveScreen) {
d->wantsToBeOnActiveScreen = false;
Q_EMIT wantsToBeOnActiveScreenChanged();
}
Q_EMIT screenChanged();
}
QScreen *Window::screen() const
{
return d->screen;
} }
bool Window::closeOnDismissed() const bool Window::closeOnDismissed() const
@ -233,50 +154,17 @@ void Window::setCloseOnDismissed(bool close)
d->closeOnDismissed = close; d->closeOnDismissed = close;
} }
bool Window::activateOnShow() const
{
return d->activateOnShow;
}
void Window::setActivateOnShow(bool activateOnShow)
{
d->activateOnShow = activateOnShow;
}
Window::Window(QWindow *window) Window::Window(QWindow *window)
: QObject(window) : QObject(window)
, d(new WindowPrivate(window)) , d(new WindowPrivate(window))
{ {
s_map.insert(d->parentWindow, this); s_map.insert(d->parentWindow, this);
window->installEventFilter(this);
if (window->isVisible()) {
qCWarning(LAYERSHELLQT) << d->parentWindow << "already has a shell integration. Call QWindow::close() first and show it again.";
}
if (window->handle()) { window->create();
initializeShell();
}
}
bool Window::eventFilter(QObject *watched, QEvent *event) auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle());
{
auto window = qobject_cast<QWindow *>(watched);
if (!window) {
return false;
}
if (event->type() == QEvent::PlatformSurface) {
if (auto pse = static_cast<QPlatformSurfaceEvent *>(event); pse->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
initializeShell();
}
}
return false;
}
void Window::initializeShell()
{
auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(d->parentWindow->handle());
if (!waylandWindow) { if (!waylandWindow) {
qCWarning(LAYERSHELLQT) << d->parentWindow << "is not a wayland window. Not creating zwlr_layer_surface"; qCWarning(LAYERSHELLQT) << window << "is not a wayland window. Not creating zwlr_layer_surface";
return; return;
} }
@ -290,6 +178,7 @@ void Window::initializeShell()
return; return;
} }
} }
waylandWindow->setShellIntegration(shellIntegration); waylandWindow->setShellIntegration(shellIntegration);
} }

View File

@ -18,36 +18,46 @@ namespace LayerShellQt
{ {
class WindowPrivate; class WindowPrivate;
/*!
* \class LayerShellQt::Window
* \inmodule LayerShellQt
* \inheaderfile LayerShellQt/Window
*
* \brief A window.
*/
class LAYERSHELLQT_EXPORT Window : public QObject class LAYERSHELLQT_EXPORT Window : public QObject
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(Anchors anchors READ anchors WRITE setAnchors NOTIFY anchorsChanged) Q_PROPERTY(Anchors anchors READ anchors WRITE setAnchors NOTIFY anchorsChanged)
/*! \property LayerShellQt::Window::scope */
Q_PROPERTY(QString scope READ scope WRITE setScope) Q_PROPERTY(QString scope READ scope WRITE setScope)
Q_PROPERTY(QMargins margins READ margins WRITE setMargins NOTIFY marginsChanged) Q_PROPERTY(QMargins margins READ margins WRITE setMargins NOTIFY marginsChanged)
Q_PROPERTY(qint32 exclusionZone READ exclusionZone WRITE setExclusiveZone NOTIFY exclusionZoneChanged) Q_PROPERTY(qint32 exclusionZone READ exclusionZone WRITE setExclusiveZone NOTIFY exclusionZoneChanged)
Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged) Q_PROPERTY(Layer layer READ layer WRITE setLayer NOTIFY layerChanged)
Q_PROPERTY(KeyboardInteractivity keyboardInteractivity READ keyboardInteractivity WRITE setKeyboardInteractivity NOTIFY keyboardInteractivityChanged) Q_PROPERTY(KeyboardInteractivity keyboardInteractivity READ keyboardInteractivity WRITE setKeyboardInteractivity NOTIFY keyboardInteractivityChanged)
Q_PROPERTY(bool activateOnShow READ activateOnShow WRITE setActivateOnShow)
Q_PROPERTY(bool wantsToBeOnActiveScreen READ wantsToBeOnActiveScreen WRITE setWantsToBeOnActiveScreen NOTIFY wantsToBeOnActiveScreenChanged)
Q_PROPERTY(QScreen *screen READ screen WRITE setScreen NOTIFY screenChanged)
#if LAYERSHELLQTINTERFACE_ENABLE_DEPRECATED_SINCE(6, 6)
Q_PROPERTY(ScreenConfiguration screenConfiguration READ screenConfiguration WRITE setScreenConfiguration) Q_PROPERTY(ScreenConfiguration screenConfiguration READ screenConfiguration WRITE setScreenConfiguration)
#endif
public: public:
~Window() override; ~Window() override;
/*!
* \value AnchorNone
* \value AnchorTop The top edge of the anchor rectangle
* \value AnchorBottom The bottom edge of the anchor rectangle
* \value AnchorLeft The left edge of the anchor rectangle
* \value AnchorRight The right edge of the anchor rectangle
*/
enum Anchor { enum Anchor {
AnchorNone = 0, AnchorNone = 0,
AnchorTop = 1, ///< The top edge of the anchor rectangle AnchorTop = 1,
AnchorBottom = 2, ///< The bottom edge of the anchor rectangle AnchorBottom = 2,
AnchorLeft = 4, ///< The left edge of the anchor rectangle AnchorLeft = 4,
AnchorRight = 8, ///< The right edge of the anchor rectangle AnchorRight = 8,
}; };
Q_ENUM(Anchor);
Q_DECLARE_FLAGS(Anchors, Anchor) Q_DECLARE_FLAGS(Anchors, Anchor)
Q_FLAG(Anchors)
/** /*!
* This enum type is used to specify the layer where a surface can be put in. * This enum type is used to specify the layer where a surface can be put in.
*/ */
enum Layer { enum Layer {
@ -58,7 +68,7 @@ public:
}; };
Q_ENUM(Layer) Q_ENUM(Layer)
/** /*!
* This enum type is used to specify how the layer surface handles keyboard focus. * This enum type is used to specify how the layer surface handles keyboard focus.
*/ */
enum KeyboardInteractivity { enum KeyboardInteractivity {
@ -68,6 +78,17 @@ public:
}; };
Q_ENUM(KeyboardInteractivity) Q_ENUM(KeyboardInteractivity)
/*!
* This enum type is used to specify which screen to place the surface on.
* ScreenFromQWindow (the default) reads QWindow::screen() while ScreenFromCompositor
* passes nil and lets the compositor decide.
*/
enum ScreenConfiguration {
ScreenFromQWindow = 0,
ScreenFromCompositor = 1,
};
Q_ENUM(ScreenConfiguration)
void setAnchors(Anchors anchor); void setAnchors(Anchors anchor);
Anchors anchors() const; Anchors anchors() const;
@ -80,59 +101,16 @@ public:
void setMargins(const QMargins &margins); void setMargins(const QMargins &margins);
QMargins margins() const; QMargins margins() const;
void setDesiredSize(const QSize &size);
QSize desiredSize() const;
void setKeyboardInteractivity(KeyboardInteractivity interactivity); void setKeyboardInteractivity(KeyboardInteractivity interactivity);
KeyboardInteractivity keyboardInteractivity() const; KeyboardInteractivity keyboardInteractivity() const;
void setLayer(Layer layer); void setLayer(Layer layer);
Layer layer() const; Layer layer() const;
#if LAYERSHELLQTINTERFACE_ENABLE_DEPRECATED_SINCE(6, 6)
/**
* This enum type is used to specify which screen to place the surface on.
* ScreenFromQWindow (the default) reads QWindow::screen() while ScreenFromCompositor
* passes nil and lets the compositor decide.
*/
LAYERSHELLQTINTERFACE_DEPRECATED_VERSION(6, 6, "Use wantsToBeOnActiveScreen and screen instead")
enum ScreenConfiguration {
ScreenFromQWindow = 0,
ScreenFromCompositor = 1,
};
Q_ENUM(ScreenConfiguration)
LAYERSHELLQTINTERFACE_DEPRECATED_VERSION(6, 6, "Use wantsToBeOnActiveScreen and screen instead")
void setScreenConfiguration(ScreenConfiguration screenConfiguration); void setScreenConfiguration(ScreenConfiguration screenConfiguration);
LAYERSHELLQTINTERFACE_DEPRECATED_VERSION(6, 6, "Use wantsToBeOnActiveScreen and screen instead")
ScreenConfiguration screenConfiguration() const; ScreenConfiguration screenConfiguration() const;
#endif
/** /*!
* Indicates whether the layer shell surface should be placed on the active screen based on @a set.
*
* The active screen depends on the compositor policies.
*
* If the screen() is @c null and the wantsToBeOnActiveScreen() is @c false, then the
* QWindow::screen() will be used to decide what screen the layer shell surface should be placed on.
*
* The screen() will be reset if @a set is @c true.
*/
void setWantsToBeOnActiveScreen(bool set);
bool wantsToBeOnActiveScreen() const;
/**
* Indicates that the layer shell surface should be placed on the specified @a screen.
*
* If the screen() is @c null and the wantsToBeOnActiveScreen() is @c false, then the
* QWindow::screen() will be used to decide what screen the layer shell surface should be placed on.
*
* The wantsToBeOnActiveScreen() will be reset to @c false after calling this function.
*/
void setScreen(QScreen *screen);
QScreen *screen() const;
/**
* Sets a string based identifier for this window. * Sets a string based identifier for this window.
* This may be used by a compositor to determine stacking * This may be used by a compositor to determine stacking
* order within a given layer. * order within a given layer.
@ -140,9 +118,17 @@ public:
* May also be referred to as a role * May also be referred to as a role
*/ */
void setScope(const QString &scope); void setScope(const QString &scope);
/*!
* A string based identifier for this window.
* This may be used by a compositor to determine stacking
* order within a given layer.
*
* May also be referred to as a role
*/
QString scope() const; QString scope() const;
/** /*!
* Whether the QWindow should be closed when the layer surface is dismissed by the compositor. * Whether the QWindow should be closed when the layer surface is dismissed by the compositor.
* For example, if the associated screen has been removed. * For example, if the associated screen has been removed.
* *
@ -151,19 +137,7 @@ public:
void setCloseOnDismissed(bool close); void setCloseOnDismissed(bool close);
bool closeOnDismissed() const; bool closeOnDismissed() const;
/** /*!
* Whether the window should requestActivate on show.
*
* Normally, you want this enabled but in case of e.g. a desktop window, this can be disabled.
*
* It does nothing when KeyboardInteractivity is KeyboardInteractivityNone.
*
* The default is true.
*/
void setActivateOnShow(bool activateOnShow);
bool activateOnShow() const;
/**
* Gets the LayerShell Window for a given Qt Window * Gets the LayerShell Window for a given Qt Window
* Ownership is not transferred * Ownership is not transferred
*/ */
@ -171,22 +145,15 @@ public:
static Window *qmlAttachedProperties(QObject *object); static Window *qmlAttachedProperties(QObject *object);
bool eventFilter(QObject *watched, QEvent *event) override;
Q_SIGNALS: Q_SIGNALS:
void anchorsChanged(); void anchorsChanged();
void exclusionZoneChanged(); void exclusionZoneChanged();
void exclusiveEdgeChanged(); void exclusiveEdgeChanged();
void marginsChanged(); void marginsChanged();
void desiredSizeChanged();
void keyboardInteractivityChanged(); void keyboardInteractivityChanged();
void layerChanged(); void layerChanged();
void wantsToBeOnActiveScreenChanged();
void screenChanged();
private: private:
void initializeShell();
Window(QWindow *window); Window(QWindow *window);
QScopedPointer<WindowPrivate> d; QScopedPointer<WindowPrivate> d;
}; };

72
src/layershellqt.qdoc Normal file
View File

@ -0,0 +1,72 @@
/*!
\module LayerShellQt
\title LayerShellQt C++ Classes
\cmakepackage LayerShellQt
\cmaketargetitem LayerShellQt::Interface
*/
/*!
\namespace LayerShellQt
\inmodule LayerShellQt
Stuff
*/
/*!
\qmlmodule org.kde.layershell
\title LayerShellQt QML Types
*/
/*!
\qmltype Window
\inqmlmodule org.kde.layershell
\nativetype LayerShellQt::Window
*/
/*!
\qmlproperty string Window::scope
A scope.
*/
/*!
\qmlproperty int Window::margins.top
\qmlproperty int Window::margins.bottom
\qmlproperty int Window::margins.left
\qmlproperty int Window::margins.right
Margins
*/
/*!
\qmlproperty int Window::exclusionZone
*/
/*!
\page layershellqt-index.html
\title LayerShellQt
Layer Shell
\section1 Using the Module
\include {module-use.qdocinc} {using the c++ api}
\section2 Building with CMake
\include {module-use.qdocinc} {building with cmake} {Widgets}
\section1 API Reference
\list
\li \l{LayerShellQt C++ Classes}
\li \l{LayerShellQt QML Types}
\endlist
\section1 Licenses
TODO
*/

30
src/layershellqt.qdocconf Normal file
View File

@ -0,0 +1,30 @@
include($KDE_DOCS/global/qt-module-defaults.qdocconf)
project = LayerShellQt
description = Qt component to allow applications to make use of the Wayland wl-layer-shell protocol
documentationinheaders = true
headerdirs = .
headers.fileextensions = "*.qdoc *.h"
outputdir = doc/html
outputformats = HTML
depends += \
qtcore
qhp.projects = LayerShellQt
qhp.LayerShellQt.file = layershellqt.qhp
qhp.LayerShellQt.namespace = org.kde.layershellqt.$QT_VERSION_TAG
qhp.LayerShellQt.virtualFolder = layershellqt
qhp.LayerShellQt.indexTitle = LayerShellQt
qhp.LayerShellQt.indexRoot =
qhp.LayerShellQt.subprojects = classes
qhp.LayerShellQt.subprojects.classes.title = C++ Classes
qhp.LayerShellQt.subprojects.classes.indexTitle = LayerShellQt C++ Classes
qhp.LayerShellQt.subprojects.classes.selectors = class fake:headerfile
qhp.LayerShellQt.subprojects.classes.sortPages = true

View File

@ -10,7 +10,6 @@
#include "qwaylandlayersurface_p.h" #include "qwaylandlayersurface_p.h"
#include "qwaylandxdgactivationv1_p.h" #include "qwaylandxdgactivationv1_p.h"
#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
#include <QtWaylandClient/private/qwaylandscreen_p.h> #include <QtWaylandClient/private/qwaylandscreen_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h> #include <QtWaylandClient/private/qwaylandsurface_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h>
@ -27,13 +26,8 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
, m_window(window) , m_window(window)
{ {
wl_output *output = nullptr; wl_output *output = nullptr;
if (!m_interface->wantsToBeOnActiveScreen()) { if (m_interface->screenConfiguration() == Window::ScreenFromQWindow) {
QScreen *desiredScreen = m_interface->screen(); auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(window->window()->screen()->handle());
if (!desiredScreen) {
desiredScreen = window->window()->screen();
}
auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(desiredScreen->handle());
// Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created // Qt will always assign a screen to a window, but if the compositor has no screens available a dummy QScreen object is created
// this will not cast to a QWaylandScreen // this will not cast to a QWaylandScreen
if (!waylandScreen) { if (!waylandScreen) {
@ -50,11 +44,7 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
setAnchor(m_interface->anchors()); setAnchor(m_interface->anchors());
connect(m_interface, &Window::anchorsChanged, this, [this]() { connect(m_interface, &Window::anchorsChanged, this, [this]() {
setAnchor(m_interface->anchors()); setAnchor(m_interface->anchors());
if (m_interface->desiredSize().isNull()) { setDesiredSize(m_window->windowContentGeometry().size());
setDesiredSize(m_window->windowContentGeometry().size());
} else {
setDesiredSize(m_interface->desiredSize());
}
}); });
setExclusiveZone(m_interface->exclusionZone()); setExclusiveZone(m_interface->exclusionZone());
@ -71,22 +61,12 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell,
setMargins(m_interface->margins()); setMargins(m_interface->margins());
}); });
connect(m_interface, &Window::desiredSizeChanged, this, [this]() {
if (!m_interface->desiredSize().isNull()) {
setDesiredSize(m_interface->desiredSize());
}
});
setKeyboardInteractivity(m_interface->keyboardInteractivity()); setKeyboardInteractivity(m_interface->keyboardInteractivity());
connect(m_interface, &Window::keyboardInteractivityChanged, this, [this]() { connect(m_interface, &Window::keyboardInteractivityChanged, this, [this]() {
setKeyboardInteractivity(m_interface->keyboardInteractivity()); setKeyboardInteractivity(m_interface->keyboardInteractivity());
}); });
if (m_interface->desiredSize().isNull()) { setDesiredSize(window->windowContentGeometry().size());
setDesiredSize(window->windowContentGeometry().size());
} else {
setDesiredSize(m_interface->desiredSize());
}
} }
QWaylandLayerSurface::~QWaylandLayerSurface() QWaylandLayerSurface::~QWaylandLayerSurface()
@ -130,7 +110,13 @@ void QWaylandLayerSurface::attachPopup(QtWaylandClient::QWaylandShellSurface *po
void QWaylandLayerSurface::applyConfigure() void QWaylandLayerSurface::applyConfigure()
{ {
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
m_configuring = true;
#endif
window()->resizeFromApplyConfigure(m_pendingSize); window()->resizeFromApplyConfigure(m_pendingSize);
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
m_configuring = false;
#endif
} }
void QWaylandLayerSurface::setDesiredSize(const QSize &size) void QWaylandLayerSurface::setDesiredSize(const QSize &size)
@ -181,12 +167,21 @@ void QWaylandLayerSurface::setLayer(uint32_t layer)
set_layer(layer); set_layer(layer);
} }
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
void QWaylandLayerSurface::setWindowGeometry(const QRect &geometry)
{
if (m_configuring) {
return;
}
setDesiredSize(geometry.size());
}
#else
void QWaylandLayerSurface::setWindowSize(const QSize &size) void QWaylandLayerSurface::setWindowSize(const QSize &size)
{ {
if (m_interface->desiredSize().isNull()) { setDesiredSize(size);
setDesiredSize(size);
}
} }
#endif
bool QWaylandLayerSurface::requestActivate() bool QWaylandLayerSurface::requestActivate()
{ {
@ -198,15 +193,11 @@ bool QWaylandLayerSurface::requestActivate()
activation->activate(m_activationToken, window()->wlSurface()); activation->activate(m_activationToken, window()->wlSurface());
m_activationToken = {}; m_activationToken = {};
return true; return true;
} else if (const auto token = qEnvironmentVariable("XDG_ACTIVATION_TOKEN"); !token.isEmpty()) {
activation->activate(token, window()->wlSurface());
qunsetenv("XDG_ACTIVATION_TOKEN");
return true;
} else { } else {
const auto focusWindow = QGuiApplication::focusWindow(); const auto focusWindow = QGuiApplication::focusWindow();
const auto wlWindow = focusWindow ? static_cast<QtWaylandClient::QWaylandWindow *>(focusWindow->handle()) : window(); const auto wlWindow = focusWindow ? static_cast<QtWaylandClient::QWaylandWindow *>(focusWindow->handle()) : window();
if (const auto seat = wlWindow->display()->lastInputDevice()) { if (const auto seat = wlWindow->display()->lastInputDevice()) {
const auto tokenProvider = activation->requestXdgActivationToken(wlWindow->display(), wlWindow->wlSurface(), seat->serial(), QString()); const auto tokenProvider = activation->requestXdgActivationToken(wlWindow->display(), wlWindow->wlSurface(), 0, QString());
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this, [this](const QString &token) { connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this, [this](const QString &token) {
m_shell->activation()->activate(token, window()->wlSurface()); m_shell->activation()->activate(token, window()->wlSurface());
}); });
@ -217,23 +208,6 @@ bool QWaylandLayerSurface::requestActivate()
return false; return false;
} }
bool QWaylandLayerSurface::requestActivateOnShow()
{
if (!m_interface->activateOnShow()) {
return false;
}
if (m_interface->keyboardInteractivity() == Window::KeyboardInteractivityNone) {
return false;
}
if (m_window->window()->property("_q_showWithoutActivating").toBool()) {
return false;
}
return requestActivate();
}
void QWaylandLayerSurface::setXdgActivationToken(const QString &token) void QWaylandLayerSurface::setXdgActivationToken(const QString &token)
{ {
m_activationToken = token; m_activationToken = token;
@ -255,6 +229,13 @@ void QWaylandLayerSurface::requestXdgActivationToken(quint32 serial)
void QWaylandLayerSurface::sendExpose() void QWaylandLayerSurface::sendExpose()
{ {
#if QT_VERSION < QT_VERSION_CHECK(6, 7, 0)
window()->handleExpose(QRect(QPoint(), m_pendingSize));
#elif QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
window()->sendRecursiveExposeEvent();
#else
window()->updateExposure(); window()->updateExposure();
#endif
} }
} }

View File

@ -43,10 +43,13 @@ public:
void setLayer(uint32_t layer); void setLayer(uint32_t layer);
void applyConfigure() override; void applyConfigure() override;
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
void setWindowGeometry(const QRect &geometry) override;
#else
void setWindowSize(const QSize &size) override; void setWindowSize(const QSize &size) override;
#endif
bool requestActivate() override; bool requestActivate() override;
bool requestActivateOnShow() override;
void setXdgActivationToken(const QString &token) override; void setXdgActivationToken(const QString &token) override;
void requestXdgActivationToken(quint32 serial) override; void requestXdgActivationToken(quint32 serial) override;
@ -62,6 +65,9 @@ private:
QString m_activationToken; QString m_activationToken;
bool m_configured = false; bool m_configured = false;
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
bool m_configuring = false;
#endif
}; };
} }

View File

@ -1,42 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Aleix Pol i Gonzalez <aleixpol@kde.org>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
import QtQuick
import QtQuick.Controls
import org.kde.layershell 1.0 as LayerShell
Item
{
Button {
text: "Convert"
anchors.centerIn: parent
onClicked: {
win.close()
win.LayerShell.Window.anchors = LayerShell.Window.AnchorLeft;
win.LayerShell.Window.layer = LayerShell.Window.LayerTop;
win.LayerShell.Window.exclusionZone = -1;
win.show()
}
}
Window {
id: win
width: 100
height: 100
Rectangle {
anchors.fill: parent
color: "red"
Text {
anchors.centerIn: parent
text: "top"
}
}
visible: true
}
}

View File

@ -53,7 +53,7 @@ int main(int argc, char **argv)
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
const auto layerMetaEnum = QMetaEnum::fromType<Window::Layer>(); const auto layerMetaEnum = QMetaEnum::fromType<Window::Layer>();
const auto anchorMetaEnum = QMetaEnum::fromType<Window::Anchors>(); const auto anchorMetaEnum = QMetaEnum::fromType<Window::Anchor>();
QCommandLineParser parser; QCommandLineParser parser;
QCommandLineOption marginsOption(QStringLiteral("margins"), QStringLiteral("Window margins"), QStringLiteral("pixels"), QStringLiteral("0")); QCommandLineOption marginsOption(QStringLiteral("margins"), QStringLiteral("Window margins"), QStringLiteral("pixels"), QStringLiteral("0"));