Compare commits

..

15 Commits

Author SHA1 Message Date
6ef7c56df3 Update version number for 5.25.5
GIT_SILENT
2022-09-06 12:34:03 +01:00
90569f5e67 Update version number for 5.25.4
GIT_SILENT
2022-08-02 11:17:59 +01:00
ab09e56d72 Update version number for 5.25.3
GIT_SILENT
2022-07-12 10:43:02 +01:00
424005733c Update version number for 5.25.2
GIT_SILENT
2022-06-28 11:21:22 +01:00
6e27a6ab42 Update qt5 version requirement to 5.15.2
GIT_SILENT
2022-06-27 10:31:50 +01:00
f001835a16 Update kf5 version requirement to 5.94
GIT_SILENT
2022-06-27 10:31:50 +01:00
1b5a182e2e Update version number for 5.25.1
GIT_SILENT
2022-06-21 11:29:48 +01:00
84b68ca1dd Update version number for 5.25.0
GIT_SILENT
2022-06-09 08:46:08 +00:00
9573abb542 Mark required deps as required
BUG: 454912
(cherry picked from commit 34e7c90c2d)
2022-06-06 12:40:57 +02: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
18 changed files with 229 additions and 59 deletions

View File

@ -4,3 +4,4 @@
include:
- 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

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.25.5")
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.94")
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})
@ -31,12 +30,18 @@ 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")

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")

14
metainfo.yaml Normal file
View File

@ -0,0 +1,14 @@
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 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}/>"
)
@ -26,19 +37,30 @@ set_target_properties(LayerShellQtInterface PROPERTIES VERSION ${LAYERSHELLQT_
EXPORT_NAME Interface
)
add_library(layer-shell SHARED qwaylandlayershellintegrationplugin.cpp)
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
Shell
Window
RELATIVE interfaces/
REQUIRED_HEADERS LayerShellQt_HEADERS
)
generate_export_header(LayerShellQtInterface
BASE_NAME LayerShellQtInterface
EXPORT_MACRO_NAME LAYERSHELLQT_EXPORT
EXPORT_FILE_NAME LayerShellQt/layershellqt_export.h
)
install(TARGETS layer-shell
LIBRARY DESTINATION ${KDE_INSTALL_QTPLUGINDIR}/wayland-shell-integration)
install(TARGETS LayerShellQtInterface EXPORT LayerShellQtTargets ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
install(FILES

20
src/interfaces/shell.cpp Normal file
View File

@ -0,0 +1,20 @@
/*
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "shell.h"
#include <QByteArray>
#include <layershellqt_logging.h>
#include <qglobal.h>
using namespace LayerShellQt;
void Shell::useLayerShell()
{
const bool ret = qputenv("QT_WAYLAND_SHELL_INTEGRATION", "layer-shell");
if (!ret) {
qCDebug(LAYERSHELLQT) << "Unable to set QT_WAYLAND_SHELL_INTEGRATION=layer-shell";
}
}

27
src/interfaces/shell.h Normal file
View File

@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef LAYERSHELLQTSHELL_H
#define LAYERSHELLQTSHELL_H
#include "layershellqt_export.h"
#include "window.h"
#include <QString>
namespace LayerShellQt
{
/**
* Sets the right environment so the shells created from now on use wlr-layer-shell.
*/
class LAYERSHELLQT_EXPORT Shell
{
public:
static void useLayerShell();
};
}
#endif

View File

@ -6,15 +6,12 @@
#include "window.h"
#include "../qwaylandlayersurface_p.h"
#include "../qwaylandlayershellintegration_p.h"
#include <layershellqt_logging.h>
#include <private/qwaylandshellsurface_p.h>
#include <private/qwaylandwindow_p.h>
using namespace LayerShellQt;
static const char *s_interfaceKey = "__kde_layer_window";
class LayerShellQt::WindowPrivate
{
public:
@ -31,11 +28,14 @@ public:
Window::Layer layer = Window::LayerTop;
QMargins margins;
QWaylandLayerSurface *getSurface() const;
QPointer<QScreen> desiredOutput;
};
static QMap<QWindow *, Window *> s_map;
Window::~Window()
{
d->parentWindow->setProperty(s_interfaceKey, QVariant());
s_map.remove(d->parentWindow);
}
void Window::setAnchors(Anchors anchors)
@ -114,28 +114,30 @@ Window::Layer Window::layer() const
return d->layer;
}
static QWaylandLayerShellIntegration *s_integration = nullptr;
QScreen *Window::desiredOutput() const
{
return d->desiredOutput;
}
void Window::setDesiredOutput(QScreen *output)
{
d->desiredOutput = output;
}
Window::Window(QWindow *window)
: QObject(window)
, d(new WindowPrivate(window))
{
Q_ASSERT(!Window::get(window));
window->winId(); // create platform window
QtWaylandClient::QWaylandWindow *waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window->handle());
if (waylandWindow) {
if (!s_integration) {
s_integration = new QWaylandLayerShellIntegration();
}
waylandWindow->setShellIntegration(s_integration);
window->setProperty(s_interfaceKey, QVariant::fromValue<QObject *>(this));
}
s_map.insert(d->parentWindow, this);
}
Window *Window::get(QWindow *window)
{
return qobject_cast<Window *>(qvariant_cast<QObject *>(window->property(s_interfaceKey)));
auto layerShellWindow = s_map.value(window);
if (layerShellWindow) {
return layerShellWindow;
}
return new Window(window);
}
QWaylandLayerSurface *WindowPrivate::getSurface() const

View File

@ -9,6 +9,7 @@
#define LAYERSHELLQTWINDOW_H
#include <QObject>
#include <QScreen>
#include <QWindow>
#include "layershellqt_export.h"
@ -21,14 +22,13 @@ class LAYERSHELLQT_EXPORT Window : public QObject
{
Q_OBJECT
public:
explicit Window(QWindow *window);
~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)
@ -69,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
@ -86,6 +94,7 @@ public:
static Window *get(QWindow *window);
private:
Window(QWindow *window);
QScopedPointer<WindowPrivate> d;
};

3
src/layer-shell.json Normal file
View File

@ -0,0 +1,3 @@
{
"Keys": [ "layer-shell" ]
}

View File

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@kde.org>
SPDX-License-Identifier: CC0-1.0

View File

@ -10,11 +10,9 @@
namespace LayerShellQt
{
QWaylandLayerShell::QWaylandLayerShell()
: QWaylandClientExtensionTemplate<QWaylandLayerShell>(2)
, QtWayland::zwlr_layer_shell_v1()
QWaylandLayerShell::QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version)
: QtWayland::zwlr_layer_shell_v1(registry, id, version)
{
initialize();
}
QWaylandLayerShell::~QWaylandLayerShell()
@ -23,4 +21,9 @@ QWaylandLayerShell::~QWaylandLayerShell()
zwlr_layer_shell_v1_destroy(object());
}
QWaylandLayerSurface *QWaylandLayerShell::createLayerSurface(QtWaylandClient::QWaylandWindow *window)
{
return new QWaylandLayerSurface(this, window);
}
}

View File

@ -10,7 +10,6 @@
#include <wayland-client.h>
#include <QtWaylandClient/QWaylandClientExtensionTemplate>
#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
@ -18,11 +17,14 @@
namespace LayerShellQt
{
class QWaylandLayerShell : public QWaylandClientExtensionTemplate<QWaylandLayerShell>, public QtWayland::zwlr_layer_shell_v1
class LAYERSHELLQT_EXPORT QWaylandLayerShell : public QtWayland::zwlr_layer_shell_v1
{
public:
QWaylandLayerShell();
QWaylandLayerShell(::wl_registry *registry, uint32_t id, uint32_t version);
~QWaylandLayerShell() override;
QWaylandLayerSurface *createLayerSurface(QtWaylandClient::QWaylandWindow *window);
// TODO: Popups
};
}

View File

@ -15,7 +15,6 @@
namespace LayerShellQt
{
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
: m_layerShell(new QWaylandLayerShell())
{
}
@ -23,9 +22,28 @@ QWaylandLayerShellIntegration::~QWaylandLayerShellIntegration()
{
}
bool QWaylandLayerShellIntegration::initialize(QtWaylandClient::QWaylandDisplay *display)
{
#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)
{
return new QWaylandLayerSurface(m_layerShell.data(), window);
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,6 +8,8 @@
#ifndef _LAYERSHELLINTEGRATION_P_H
#define _LAYERSHELLINTEGRATION_P_H
#include <wayland-client.h>
#include "layershellqt_export.h"
#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
@ -21,9 +23,12 @@ public:
QWaylandLayerShellIntegration();
~QWaylandLayerShellIntegration() 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

@ -0,0 +1,33 @@
/*
* SPDX-FileCopyrightText: 2021 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
* SPDX-FileCopyrightText: 2018 Drew DeVault <sir@cmpwn.com>
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "qwaylandlayershellintegration_p.h"
#include <QtWaylandClient/private/qwaylandshellintegrationplugin_p.h>
using namespace LayerShellQt;
class QWaylandLayerShellIntegrationPlugin : public QtWaylandClient::QWaylandShellIntegrationPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID QWaylandShellIntegrationFactoryInterface_iid FILE "layer-shell.json")
public:
QWaylandLayerShellIntegrationPlugin()
{
}
QtWaylandClient::QWaylandShellIntegration *create(const QString &key, const QStringList &paramList) override
{
Q_UNUSED(key);
Q_UNUSED(paramList);
return new QWaylandLayerShellIntegration();
}
};
// Q_IMPORT_PLUGIN(QWaylandLayerShellIntegrationPlugin);
#include "qwaylandlayershellintegrationplugin.moc"

View File

@ -5,10 +5,10 @@
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "interfaces/shell.h"
#include "layershellqt_logging.h"
#include "qwaylandlayershell_p.h"
#include "qwaylandlayersurface_p.h"
#include "interfaces/window.h"
#include "layershellqt_logging.h"
#include <QtWaylandClient/private/qwaylandscreen_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
@ -20,17 +20,22 @@ QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShell *shell, QtWaylandC
: QtWaylandClient::QWaylandShellSurface(window)
, QtWayland::zwlr_layer_surface_v1()
{
Window *interface = Window::get(window->window());
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()));
init(shell->get_layer_surface(window->waylandSurface()->object(), output, interface->layer(), interface->scope()));
Window::Anchors anchors = interface->anchors();

View File

@ -14,6 +14,7 @@
#include <QMetaEnum>
#include <interfaces/shell.h>
#include <interfaces/window.h>
using namespace LayerShellQt;
@ -50,6 +51,8 @@ class BasicWindow : public QRasterWindow
int main(int argc, char **argv)
{
Shell::useLayerShell();
QGuiApplication app(argc, argv);
const auto layerMetaEnum = QMetaEnum::fromType<Window::Layer>();
@ -75,7 +78,7 @@ int main(int argc, char **argv)
BasicWindow window;
LayerShellQt::Window *layerShell = new LayerShellQt::Window(&window);
LayerShellQt::Window *layerShell = LayerShellQt::Window::get(&window);
if (parser.isSet(marginsOption)) {
int margins = parser.value(marginsOption).toInt();
layerShell->setMargins({margins, margins, margins, margins});
@ -99,10 +102,6 @@ int main(int argc, char **argv)
window.show();
BasicWindow window2;
window2.resize(400, 400);
window2.show();
// just so you don't block yourself out whilst testing
QTimer::singleShot(5000, &app, &QGuiApplication::quit);
return app.exec();