Compare commits

..

32 Commits

Author SHA1 Message Date
de99581bae Update version number for 5.27.10
GIT_SILENT
2023-12-05 19:10:02 +00:00
99aa6c62a7 Update version number for 5.27.9
GIT_SILENT
2023-10-24 12:42:13 +01:00
a09d4c532d Update version number for 5.27.8
GIT_SILENT
2023-09-12 11:22:08 +01:00
ee7ccc4fb8 Update version number for 5.27.7
GIT_SILENT
2023-08-01 10:03:25 +01:00
d610813bac Update version number for 5.27.6
GIT_SILENT
2023-06-20 14:02:45 +01:00
debc455bd5 Update version number for 5.27.5
GIT_SILENT
2023-05-09 12:18:32 +01:00
b2dcb1acff Update version number for 5.27.4
GIT_SILENT
2023-04-04 11:21:08 +01:00
94eb90d823 Update version number for 5.27.3
GIT_SILENT
2023-03-14 11:53:20 +00:00
dac784828f Update version number for 5.27.2
GIT_SILENT
2023-02-28 12:01:30 +00:00
ddc4aead87 Use the QScreen of the QWindow as default output
If the Window::setDesiredOutput API was not called for the QWindow, use
QWindow::screen(). This allows assigning QWindows to specific screens using
the plain Qt API.

Passing nullptr to Window::setDesiredOutput explicitly results in nil as
desired output for the layer, which lets the compositor select a screen.

(cherry picked from commit 3c85e2e889)
2023-02-23 09:38:55 +01:00
7a862bdcd4 Update version number for 5.27.1
GIT_SILENT
2023-02-21 11:05:04 +00:00
b758105bd7 Update version number for 5.27.0
GIT_SILENT
2023-02-09 11:41:27 +00:00
79441811ff Update kf5 version requirement to 5.102.0
GIT_SILENT
2023-01-21 20:17:53 +00:00
fc06e945c8 Update version number for 5.26.90
GIT_SILENT
2023-01-19 11:17:24 +00:00
b95910c086 Use ecm_set_disabled_deprecation_versions 2022-12-23 13:50:51 +01:00
70dc87f673 Use KDE_INSTALL_CMAKEPACKAGEDIR
GIT_SILENT
2022-10-22 13:59:13 +00:00
7b9c2c1db1 Update version number for 5.26.80
GIT_SILENT
2022-09-15 13:57:50 +01:00
9b5a39922b Update version number for 5.25.90
GIT_SILENT
2022-09-15 11:50:08 +01:00
91db77acc2 Update kf5 version requirement to 5.98.0
GIT_SILENT
2022-09-15 11:10:38 +01:00
5af50ac3ee Add FreeBSD Qt6 CI support 2022-08-27 14:40:53 +02:00
7bfac45da8 Make fully reuse compliant 2022-08-23 21:52:18 +02:00
7bd63669ea Use change signals on Window interface class.
QWaylandLayerSurface pulled data from the Window on startup. The Window
pushed data into the QWaylandLayerSurface on changes. Having two
patterns is a sign of something being off.

This moves everything to a single design, pulling from the public
interface. This allows us to drop a code path that meddles with
QWaylandWindow internals.
2022-06-30 08:09:21 +00:00
13961ef7b9 Update qt5 version requirement to 5.15.2
GIT_SILENT
2022-06-27 10:02:56 +01:00
ff6155a5af Update kf5 version requirement to 5.94
GIT_SILENT
2022-06-27 10:02:56 +01:00
34e7c90c2d Mark required deps as required
BUG: 454912
2022-06-06 12:26:10 +02:00
563b61c75c Update version number for 5.25.80
GIT_SILENT
2022-05-19 12:26:13 +01:00
404e9851d1 Update version number for 5.24.90
GIT_SILENT
2022-05-19 10:41:53 +01:00
345676a4a1 Minor api doc improvement for api.kde.org 2022-05-04 10:43:03 +00:00
ae883df5b1 Build with Qt6 2022-03-06 10:54:56 +01:00
9f8b8c9731 Add desiredScreen property to LayerShellQt::Window
If the property is set, the compositor will try to put the window on the
given output. If not set, the compositer will decide where to put the
window (usually the active output). The motivation for this change is the
ability for KRunner to always appear on the active output.
2022-01-26 09:04:14 +01:00
14982d6dc7 Update version number for 5.24.80
GIT_SILENT
2022-01-13 11:56:23 +00:00
e557008b56 Update version number for 5.23.90
GIT_SILENT
2022-01-13 10:34:20 +00:00
10 changed files with 161 additions and 91 deletions

View File

@ -2,5 +2,8 @@
# SPDX-License-Identifier: CC0-1.0
include:
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/reuse-lint.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
- https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd-qt6.yml

View File

@ -4,19 +4,18 @@
cmake_minimum_required(VERSION 3.16)
project(layershellqt)
set(PROJECT_VERSION "6.0.0")
set(PROJECT_VERSION_MAJOR 6)
set(PROJECT_VERSION "5.27.10")
set(PROJECT_VERSION_MAJOR 5)
set(CMAKE_C_STANDARD 99)
set(QT_MIN_VERSION "6.2.0")
set(KF5_MIN_VERSION "5.86")
set(QT_MIN_VERSION "5.15.2")
set(KF5_MIN_VERSION "5.102.0")
set(KDE_COMPILERSETTINGS_LEVEL "5.82")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient Qml)
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${ECM_MODULE_PATH})
@ -24,6 +23,7 @@ include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(ECMSetupVersion)
include(ECMDeprecationSettings)
include(ECMGenerateHeaders)
include(CMakePackageConfigHelpers)
include(FeatureSummary)
@ -31,12 +31,19 @@ include(GenerateExportHeader)
include(KDEClangFormat)
include(ECMQtDeclareLoggingCategory)
find_package(WaylandScanner)
find_package(QtWaylandScanner)
find_package(Qt${QT_MAJOR_VERSION} ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS WaylandClient Qml)
if (QT_MAJOR_VERSION EQUAL "5")
find_package(Qt5XkbCommonSupport REQUIRED PRIVATE)
find_package(QtWaylandScanner REQUIRED)
endif()
find_package(WaylandScanner REQUIRED)
find_package(Wayland 1.3 COMPONENTS Client Server)
find_package(WaylandProtocols)
find_package(WaylandProtocols REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(XKBCOMMON xkbcommon REQUIRED IMPORTED_TARGET)
set_package_properties(Wayland PROPERTIES
TYPE REQUIRED)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
@ -48,10 +55,15 @@ ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX LAYERSHELLQT
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h)
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
ecm_set_disabled_deprecation_versions(QT 5.15.2
KF 5.101
)
add_subdirectory(src)
add_subdirectory(tests)
set(CMAKECONFIG_INSTALL_DIR ${KDE_INSTALL_LIBDIR}/cmake/LayerShellQt)
set(CMAKECONFIG_INSTALL_DIR ${KDE_INSTALL_CMAKEPACKAGEDIR}/LayerShellQt)
install(EXPORT LayerShellQtTargets
NAMESPACE LayerShellQt::
DESTINATION ${CMAKECONFIG_INSTALL_DIR}

View File

@ -4,6 +4,6 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(Qt6Gui "@QT_MIN_VERSION@")
find_dependency(Qt@QT_MAJOR_VERSION@Gui "@QT_MIN_VERSION@")
include("${CMAKE_CURRENT_LIST_DIR}/LayerShellQtTargets.cmake")

17
metainfo.yaml Normal file
View File

@ -0,0 +1,17 @@
# SPDX-FileCopyrightText: None
# SPDX-License-Identifier: CC0-1.0
maintainer:
- vladz
description: Layer Shell Qt
platforms:
- name: Linux
- name: FreeBSD
portingAid: false
deprecated: false
release: true
group: Plasma
public_lib: true
public_source_dirs:
- src/interfaces

View File

@ -3,8 +3,16 @@
remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS)
ecm_add_qtwayland_client_protocol(LAYER_SHELL_SOURCES PROTOCOL ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml BASENAME xdg-shell)
ecm_add_qtwayland_client_protocol(LAYER_SHELL_SOURCES PROTOCOL wlr-layer-shell-unstable-v1.xml BASENAME wlr-layer-shell-unstable-v1)
add_library(LayerShellQtInterface)
if (QT_MAJOR_VERSION EQUAL "5")
ecm_add_qtwayland_client_protocol(LAYER_SHELL_SOURCES PROTOCOL ${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml BASENAME xdg-shell)
ecm_add_qtwayland_client_protocol(LAYER_SHELL_SOURCES PROTOCOL wlr-layer-shell-unstable-v1.xml BASENAME wlr-layer-shell-unstable-v1)
else()
qt6_generate_wayland_protocol_client_sources(LayerShellQtInterface FILES
${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml
${CMAKE_CURRENT_SOURCE_DIR}/wlr-layer-shell-unstable-v1.xml
)
endif()
ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
HEADER
@ -15,8 +23,11 @@ ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
layershellqt
)
add_library(LayerShellQtInterface SHARED qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp qwaylandlayershell.cpp ${LAYER_SHELL_SOURCES})
target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Wayland::Client)
target_sources(LayerShellQtInterface PRIVATE qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp qwaylandlayershell.cpp ${LAYER_SHELL_SOURCES})
target_link_libraries(LayerShellQtInterface PRIVATE Qt::Gui Qt::WaylandClientPrivate Wayland::Client PkgConfig::XKBCOMMON)
if (TARGET Qt::XkbCommonSupportPrivate)
target_link_libraries(LayerShellQtInterface PRIVATE Qt::XkbCommonSupportPrivate)
endif()
target_include_directories(LayerShellQtInterface PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/LayerShellQt>"
INTERFACE "$<INSTALL_INTERFACE:${KDE_INSTALL_INCLUDEDIR}/>"
)
@ -27,7 +38,10 @@ set_target_properties(LayerShellQtInterface PROPERTIES VERSION ${LAYERSHELLQT_
)
add_library(layer-shell SHARED qwaylandlayershellintegrationplugin.cpp)
target_link_libraries(layer-shell LayerShellQtInterface Qt::WaylandClient Qt::WaylandClientPrivate Wayland::Client)
target_link_libraries(layer-shell LayerShellQtInterface Qt::WaylandClient Qt::WaylandClientPrivate Wayland::Client PkgConfig::XKBCOMMON)
if (TARGET Qt::XkbCommonSupportPrivate)
target_link_libraries(layer-shell Qt::XkbCommonSupportPrivate)
endif()
ecm_generate_headers(LayerShellQt_HEADERS
HEADER_NAMES
@ -45,7 +59,7 @@ generate_export_header(LayerShellQtInterface
)
install(TARGETS layer-shell
LIBRARY DESTINATION ${QT_PLUGIN_INSTALL_DIR}/wayland-shell-integration)
LIBRARY DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/wayland-shell-integration)
install(TARGETS LayerShellQtInterface EXPORT LayerShellQtTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})

View File

@ -5,10 +5,10 @@
*/
#include "window.h"
#include "../qwaylandlayersurface_p.h"
#include <layershellqt_logging.h>
#include <private/qwaylandshellsurface_p.h>
#include <private/qwaylandwindow_p.h>
#include <QPointer>
#include <optional>
using namespace LayerShellQt;
@ -27,7 +27,7 @@ public:
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityExclusive;
Window::Layer layer = Window::LayerTop;
QMargins margins;
QWaylandLayerSurface *getSurface() const;
std::optional<QPointer<QScreen>> desiredOutput;
};
static QMap<QWindow *, Window *> s_map;
@ -40,9 +40,7 @@ Window::~Window()
void Window::setAnchors(Anchors anchors)
{
d->anchors = anchors;
if (auto surface = d->getSurface()) {
surface->setAnchor(anchors);
}
Q_EMIT anchorsChanged();
}
Window::Anchors Window::anchors() const
@ -53,9 +51,7 @@ Window::Anchors Window::anchors() const
void Window::setExclusiveZone(int32_t zone)
{
d->exclusionZone = zone;
if (auto surface = d->getSurface()) {
surface->setExclusiveZone(zone);
}
Q_EMIT exclusionZoneChanged();
}
int32_t Window::exclusionZone() const
@ -66,9 +62,7 @@ int32_t Window::exclusionZone() const
void Window::setMargins(const QMargins &margins)
{
d->margins = margins;
if (auto surface = d->getSurface()) {
surface->setMargins(margins);
}
Q_EMIT marginsChanged();
}
QMargins Window::margins() const
@ -79,9 +73,7 @@ QMargins Window::margins() const
void Window::setKeyboardInteractivity(KeyboardInteractivity interactivity)
{
d->keyboardInteractivity = interactivity;
if (auto surface = d->getSurface()) {
surface->setKeyboardInteractivity(interactivity);
}
Q_EMIT keyboardInteractivityChanged();
}
Window::KeyboardInteractivity Window::keyboardInteractivity() const
@ -92,9 +84,6 @@ Window::KeyboardInteractivity Window::keyboardInteractivity() const
void Window::setLayer(Layer layer)
{
d->layer = layer;
if (auto surface = d->getSurface()) {
surface->setLayer(layer);
}
}
void Window::setScope(const QString &scope)
@ -113,6 +102,21 @@ Window::Layer Window::layer() const
return d->layer;
}
QScreen *Window::desiredOutput() const
{
// Don't use .value_or here to avoid a temporary QPointer
if (d->desiredOutput.has_value()) {
return d->desiredOutput.value();
}
return d->parentWindow->screen();
}
void Window::setDesiredOutput(QScreen *output)
{
d->desiredOutput = output;
}
Window::Window(QWindow *window)
: QObject(window)
, d(new WindowPrivate(window))
@ -128,21 +132,3 @@ Window *Window::get(QWindow *window)
}
return new Window(window);
}
QWaylandLayerSurface *WindowPrivate::getSurface() const
{
if (!parentWindow) {
return nullptr;
}
auto ww = dynamic_cast<QtWaylandClient::QWaylandWindow *>(parentWindow->handle());
if (!ww) {
qCDebug(LAYERSHELLQT) << "window not a wayland window" << parentWindow;
return nullptr;
}
QWaylandLayerSurface *s = qobject_cast<QWaylandLayerSurface *>(ww->shellSurface());
if (!s) {
qCDebug(LAYERSHELLQT) << "window not using wlr-layer-shell" << parentWindow << ww->shellSurface();
return nullptr;
}
return s;
}

View File

@ -9,6 +9,7 @@
#define LAYERSHELLQTWINDOW_H
#include <QObject>
#include <QScreen>
#include <QWindow>
#include "layershellqt_export.h"
@ -24,10 +25,10 @@ public:
~Window() override;
enum Anchor {
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
AnchorRight = 8, // the right edge of the anchor rectangle
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
AnchorRight = 8, ///< The right edge of the anchor rectangle
};
Q_ENUM(Anchor);
Q_DECLARE_FLAGS(Anchors, Anchor)
@ -68,6 +69,14 @@ public:
void setLayer(Layer layer);
Layer layer() const;
/**
* If set, the compositor will try to put the window on the given screen.
* If its not set, then the compositor will decide where to put the window.
* Under normal circumstances, this should be the active output.
*/
void setDesiredOutput(QScreen *output);
QScreen *desiredOutput() const;
/**
* Sets a string based identifier for this window.
* This may be used by a compositor to determine stacking
@ -84,6 +93,13 @@ public:
*/
static Window *get(QWindow *window);
Q_SIGNALS:
void anchorsChanged();
void exclusionZoneChanged();
void marginsChanged();
void keyboardInteractivityChanged();
void layerChanged();
private:
Window(QWindow *window);
QScopedPointer<WindowPrivate> d;

View File

@ -22,30 +22,28 @@ QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration()
{
}
bool QWaylandLayerShellIntegration::initialize()
bool QWaylandLayerShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display)
{
if (m_layerShell) {
return true;
}
wl_registry *registry;
uint32_t id;
uint32_t version;
const bool found = findGlobal(QLatin1String("zwlr_layer_shell_v1"), &registry, &id, &version);
if (!found) {
qWarning() << "Could not find the zwlr_layer_shell_v1 global. Compositor does not support the layer shell protocol?";
return false;
}
m_layerShell.reset(new QWaylandLayerShell(registry, id, std::min(version, 4u)));
return true;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QWaylandShellIntegration::initialize(display);
#endif
display->addRegistryListener(registryLayer, this);
return m_layerShell != nullptr;
}
QtWaylandClient::QWaylandShellSurface *QWaylandLayerShellIntegration::createShellSurface(QtWaylandClient::QWaylandWindow *window)
{
if (m_layerShell) {
return m_layerShell->createLayerSurface(window);
}
return nullptr;
return m_layerShell->createLayerSurface(window);
}
void QWaylandLayerShellIntegration::registryLayer(void *data, struct wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
{
QWaylandLayerShellIntegration *shell = static_cast<QWaylandLayerShellIntegration *>(data);
if (interface == zwlr_layer_shell_v1_interface.name)
shell->m_layerShell.reset(new QWaylandLayerShell(registry, id, std::min(version, 4u)));
}
}
//#include "qwaylandlayershellintegration.moc"

View File

@ -8,9 +8,10 @@
#ifndef _LAYERSHELLINTEGRATION_P_H
#define _LAYERSHELLINTEGRATION_P_H
#include "layershellqt_export.h"
#include <wayland-client.h>
#include <QtWaylandClient/private/qwaylandclientshellapi_p.h>
#include "layershellqt_export.h"
#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
namespace LayerShellQt
{
@ -22,10 +23,12 @@ public:
QWaylandLayerShellIntegration();
~QWaylandLayerShellIntegration() override;
bool initialize() override;
bool initialize(QtWaylandClient::QWaylandDisplay *display) override;
QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override;
private:
static void registryLayer(void *data, struct wl_registry *registry, uint32_t id, const QString &interface, uint32_t version);
QScopedPointer<QWaylandLayerShell> m_layerShell;
};

View File

@ -6,9 +6,9 @@
*/
#include "interfaces/shell.h"
#include "layershellqt_logging.h"
#include "qwaylandlayershell_p.h"
#include "qwaylandlayersurface_p.h"
#include "layershellqt_logging.h"
#include <QtWaylandClient/private/qwaylandscreen_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
@ -23,23 +23,44 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandC
LayerShellQt::Window *interface = Window::get(window->window());
Q_ASSERT(interface);
// 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
QtWaylandClient::QWaylandScreen *screen = window->waylandScreen();
if (screen->isPlaceholder()) {
qCWarning(LAYERSHELLQT) << "Creating a layer shell for placeholder screen. This will be positioned incorrectly";
wl_output *output = nullptr;
QScreen *screen = interface->desiredOutput();
if (screen) {
auto waylandScreen = dynamic_cast<QtWaylandClient::QWaylandScreen *>(screen->handle());
// 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
if (!waylandScreen) {
qCWarning(LAYERSHELLQT) << "Creating a layer shell for placeholder screen. This will be positioned incorrectly";
} else {
output = waylandScreen->output();
}
}
init(shell->get_layer_surface(window->waylandSurface()->object(), screen->isPlaceholder() ? nullptr : screen->output(), interface->layer(), interface->scope()));
Window::Anchors anchors = interface->anchors();
init(shell->get_layer_surface(window->waylandSurface()->object(), output, interface->layer(), interface->scope()));
connect(interface, &Window::layerChanged, this, [this, interface]() {
setLayer(interface->layer());
});
set_anchor(interface->anchors());
setMargins(interface->margins());
setKeyboardInteractivity(interface->keyboardInteractivity());
connect(interface, &Window::anchorsChanged, this, [this, interface]() {
set_anchor(interface->anchors());
});
setExclusiveZone(interface->exclusionZone());
connect(interface, &Window::exclusionZoneChanged, this, [this, interface]() {
setExclusiveZone(interface->exclusionZone());
});
setMargins(interface->margins());
connect(interface, &Window::marginsChanged, this, [this, interface]() {
setMargins(interface->margins());
});
setKeyboardInteractivity(interface->keyboardInteractivity());
connect(interface, &Window::keyboardInteractivityChanged, this, [this, interface]() {
setKeyboardInteractivity(interface->keyboardInteractivity());
});
QSize size = window->surfaceSize();
const Window::Anchors anchors = interface->anchors();
if ((anchors & Window::AnchorLeft) && (anchors & Window::AnchorRight)) {
size.setWidth(0);
}