Compare commits

..

5 Commits

Author SHA1 Message Date
de9fdb3fb7 Support XDG activation
QWaylandLayerShellIntegration has virtual hooks for Xdg Activation.

This is important to hook up in layer shell because activation using
requestActivate in Qt will go through this path. It also means we have
support for us to drop the implementation in KWindowSystem in favour of
calling into Qt.
2023-11-06 12:41:20 +00:00
00b26a196d set ecm soversion to project major
again probably not used but feels best to make them match
2023-11-03 10:19:42 +00:00
fcaf8cf95d Update PROJECT_VERSION_MAJOR to 6, this is mostly used in some internal soversions 2023-11-01 19:22:21 +00:00
1573a89aac Skip empty parts for stringToEnum template
metaEnum.keyToValue("") will results all flags get set, thus creating a
enum with empty (0) flags become impossible. This patch fixes that.
2023-09-26 17:25:20 +08:00
721c0ae334 Remove an inappropriate log message 2023-09-06 14:52:55 +03:00
11 changed files with 199 additions and 36 deletions

View File

@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.16)
project(layershellqt)
set(PROJECT_VERSION "5.27.80")
set(PROJECT_VERSION_MAJOR 5)
set(PROJECT_VERSION_MAJOR 6)
set(CMAKE_C_STANDARD 99)
@ -47,7 +47,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX LAYERSHELLQT
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/layershellqt_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/LayerShellQtConfigVersion.cmake"
SOVERSION 5)
SOVERSION ${PROJECT_VERSION_MAJOR})
file(GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES *.cpp *.h)
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})

View File

@ -6,10 +6,11 @@ remove_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS)
add_library(LayerShellQtInterface)
qt6_generate_wayland_protocol_client_sources(LayerShellQtInterface FILES
${WaylandProtocols_DATADIR}/stable/xdg-shell/xdg-shell.xml
${WaylandProtocols_DATADIR}/staging/xdg-activation/xdg-activation-v1.xml
${CMAKE_CURRENT_SOURCE_DIR}/wlr-layer-shell-unstable-v1.xml
)
ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
ecm_qt_declare_logging_category(LayerShellQtInterface
HEADER
layershellqt_logging.h
IDENTIFIER
@ -18,7 +19,14 @@ ecm_qt_declare_logging_category(LAYER_SHELL_SOURCES
layershellqt
)
target_sources(LayerShellQtInterface PRIVATE qwaylandlayersurface.cpp interfaces/window.cpp interfaces/shell.cpp qwaylandlayershellintegration.cpp ${LAYER_SHELL_SOURCES})
target_sources(LayerShellQtInterface PRIVATE
qwaylandxdgactivationv1.cpp
qwaylandlayersurface.cpp
qwaylandlayershellintegration.cpp
interfaces/window.cpp
interfaces/shell.cpp
)
target_link_libraries(LayerShellQtInterface PUBLIC Qt::Gui)
target_link_libraries(LayerShellQtInterface PRIVATE Qt::WaylandClientPrivate Wayland::Client PkgConfig::XKBCOMMON)
if (TARGET Qt::XkbCommonSupportPrivate)

View File

@ -29,7 +29,6 @@ public:
QWindow *parentWindow;
QString scope = QStringLiteral("window");
QSize desiredSize = QSize(0, 0);
Window::Anchors anchors = {Window::AnchorTop | Window::AnchorBottom | Window::AnchorLeft | Window::AnchorRight};
int32_t exclusionZone = 0;
Window::KeyboardInteractivity keyboardInteractivity = Window::KeyboardInteractivityNone;
@ -142,19 +141,6 @@ void Window::setCloseOnDismissed(bool close)
d->closeOnDismissed = close;
}
void Window::setDesiredSize(const QSize &size)
{
if (d->desiredSize != size) {
d->desiredSize = size;
Q_EMIT desiredSizeChanged();
}
}
QSize Window::desiredSize() const
{
return d->desiredSize;
}
#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
void Window::attachPopup(QWindow *window, xdg_popup *popup)
{

View File

@ -114,13 +114,6 @@ public:
void setCloseOnDismissed(bool close);
bool closeOnDismissed() const;
/**
* Sets the desired window size. This size indicates how much space the compositor is going
* to reserve for the window.
*/
void setDesiredSize(const QSize &size);
QSize desiredSize() const;
/**
* Gets the LayerShell Window for a given Qt Window
* Ownership is not transferred
@ -139,7 +132,6 @@ Q_SIGNALS:
void marginsChanged();
void keyboardInteractivityChanged();
void layerChanged();
void desiredSizeChanged();
private:
Window(QWindow *window);

View File

@ -7,6 +7,7 @@
#include "qwaylandlayershellintegration_p.h"
#include "qwaylandlayersurface_p.h"
#include "qwaylandxdgactivationv1_p.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
@ -15,6 +16,7 @@ namespace LayerShellQt
{
QWaylandLayerShellIntegration::QWaylandLayerShellIntegration()
: QWaylandShellIntegrationTemplate<QWaylandLayerShellIntegration>(4)
, m_xdgActivation(new QWaylandXdgActivationV1)
{
}

View File

@ -13,6 +13,8 @@
#include <QtWaylandClient/private/qwaylandshellintegration_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
class QWaylandXdgActivationV1;
namespace LayerShellQt
{
@ -22,7 +24,10 @@ public:
QWaylandLayerShellIntegration();
~QWaylandLayerShellIntegration() override;
QWaylandXdgActivationV1 *activation() const { return m_xdgActivation.data(); }
QtWaylandClient::QWaylandShellSurface *createShellSurface(QtWaylandClient::QWaylandWindow *window) override;
private:
QScopedPointer<QWaylandXdgActivationV1> m_xdgActivation;
};
}

View File

@ -8,16 +8,20 @@
#include "interfaces/window.h"
#include "layershellqt_logging.h"
#include "qwaylandlayersurface_p.h"
#include "qwaylandxdgactivationv1_p.h"
#include <QtWaylandClient/private/qwaylandscreen_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <QGuiApplication>
namespace LayerShellQt
{
QWaylandLayerSurface::QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window)
QWaylandLayerSurface::QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, QtWaylandClient::QWaylandWindow *window)
: QtWaylandClient::QWaylandShellSurface(window)
, QtWayland::zwlr_layer_surface_v1()
, m_shell(shell)
, m_interface(Window::get(window->window()))
{
wl_output *output = nullptr;
@ -55,10 +59,17 @@ QWaylandLayerSurface::QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell
setKeyboardInteractivity(m_interface->keyboardInteractivity());
});
setDesiredSize(m_interface->desiredSize());
connect(m_interface, &Window::desiredSizeChanged, this, [this]() {
setDesiredSize(m_interface->desiredSize());
});
QSize size = window->surfaceSize();
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()
@ -129,14 +140,73 @@ void QWaylandLayerSurface::setKeyboardInteractivity(uint32_t interactivity)
void QWaylandLayerSurface::setLayer(uint32_t layer)
{
qDebug() << "wtfffffff" << layer << zwlr_layer_surface_v1_get_version(object()) << ZWLR_LAYER_SURFACE_V1_SET_LAYER_SINCE_VERSION;
if (zwlr_layer_surface_v1_get_version(object()) >= ZWLR_LAYER_SURFACE_V1_SET_LAYER_SINCE_VERSION)
set_layer(layer);
}
void QWaylandLayerSurface::setDesiredSize(const QSize &size)
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);
QSize size = geometry.size();
if (horizontallyConstrained) {
size.setWidth(0);
}
if (verticallyConstrained) {
size.setHeight(0);
}
set_size(size.width(), size.height());
}
bool QWaylandLayerSurface::requestActivate()
{
QWaylandXdgActivationV1 *activation = m_shell->activation();
if (!activation->isActive()) {
return false;
}
if (!m_activationToken.isEmpty()) {
activation->activate(m_activationToken, window()->wlSurface());
m_activationToken = {};
return true;
} else {
const auto focusWindow = QGuiApplication::focusWindow();
const auto wlWindow = focusWindow ? static_cast<QtWaylandClient::QWaylandWindow*>(focusWindow->handle()) : window();
if (const auto seat = wlWindow->display()->lastInputDevice()) {
const auto tokenProvider = activation->requestXdgActivationToken(
wlWindow->display(), wlWindow->wlSurface(), 0, QString());
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this,
[this](const QString &token) {
m_shell->activation()->activate(token, window()->wlSurface());
});
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater);
return true;
}
}
return false;
}
void QWaylandLayerSurface::setXdgActivationToken(const QString &token)
{
m_activationToken = token;
}
void QWaylandLayerSurface::requestXdgActivationToken(quint32 serial)
{
QWaylandXdgActivationV1 *activation = m_shell->activation();
if (!activation->isActive()) {
return;
}
auto tokenProvider = activation->requestXdgActivationToken(
window()->display(), window()->wlSurface(), serial, QString());
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, this,
[this](const QString &token) {
Q_EMIT window()->xdgActivationTokenCreated(token);
});
connect(tokenProvider, &QWaylandXdgActivationTokenV1::done, tokenProvider, &QObject::deleteLater);
}
}

View File

@ -10,6 +10,8 @@
#include <wayland-client.h>
#include "qwaylandlayershellintegration_p.h"
#include "layershellqt_export.h"
#include <QtWaylandClient/private/qwaylandshellsurface_p.h>
#include <qwayland-wlr-layer-shell-unstable-v1.h>
@ -23,7 +25,7 @@ class LAYERSHELLQT_EXPORT QWaylandLayerSurface : public QtWaylandClient::QWaylan
{
Q_OBJECT
public:
QWaylandLayerSurface(QtWayland::zwlr_layer_shell_v1 *shell, QtWaylandClient::QWaylandWindow *window);
QWaylandLayerSurface(QWaylandLayerShellIntegration *shell, QtWaylandClient::QWaylandWindow *window);
~QWaylandLayerSurface() override;
bool isExposed() const override
@ -39,16 +41,22 @@ public:
void setMargins(const QMargins &margins);
void setKeyboardInteractivity(uint32_t interactivity);
void setLayer(uint32_t layer);
void setDesiredSize(const QSize &size);
void applyConfigure() override;
void setWindowGeometry(const QRect &geometry) override;
bool requestActivate() override;
void setXdgActivationToken(const QString &token) override;
void requestXdgActivationToken(quint32 serial) override;
private:
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;
QSize m_pendingSize;
QString m_activationToken;
bool m_configured = false;
};

View File

@ -0,0 +1,44 @@
/** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#include "qwaylandxdgactivationv1_p.h"
#include <QtWaylandClient/private/qwaylanddisplay_p.h>
#include <QtWaylandClient/private/qwaylandinputdevice_p.h>
QWaylandXdgActivationV1::QWaylandXdgActivationV1()
: QWaylandClientExtensionTemplate<QWaylandXdgActivationV1>(1)
{
initialize();
}
QWaylandXdgActivationV1::~QWaylandXdgActivationV1()
{
if (isActive()) {
destroy();
}
}
QWaylandXdgActivationTokenV1 *QWaylandXdgActivationV1::requestXdgActivationToken(QtWaylandClient::QWaylandDisplay *display,
struct ::wl_surface *surface,
std::optional<uint32_t> serial,
const QString &app_id)
{
auto wl = get_activation_token();
auto provider = new QWaylandXdgActivationTokenV1;
provider->init(wl);
if (surface) {
provider->set_surface(surface);
}
if (!app_id.isEmpty()) {
provider->set_app_id(app_id);
}
if (serial && display->lastInputDevice()) {
provider->set_serial(*serial, display->lastInputDevice()->wl_seat());
}
provider->commit();
return provider;
}
#include "moc_qwaylandxdgactivationv1_p.cpp"

View File

@ -0,0 +1,48 @@
/** Copyright (C) 2020 Aleix Pol Gonzalez <aleixpol@kde.org>
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#ifndef QWAYLANDXDGACTIVATIONV1_P_H
#define QWAYLANDXDGACTIVATIONV1_P_H
#include "qwayland-xdg-activation-v1.h"
#include <QObject>
#include <QtWaylandClient/QWaylandClientExtension>
namespace QtWaylandClient
{
class QWaylandDisplay;
class QWaylandSurface;
}
class QWaylandXdgActivationTokenV1 : public QObject, public QtWayland::xdg_activation_token_v1
{
Q_OBJECT
public:
~QWaylandXdgActivationTokenV1() override
{
destroy();
}
protected:
void xdg_activation_token_v1_done(const QString &token) override
{
Q_EMIT done(token);
}
Q_SIGNALS:
void done(const QString &token);
};
class QWaylandXdgActivationV1 : public QWaylandClientExtensionTemplate<QWaylandXdgActivationV1>, public QtWayland::xdg_activation_v1
{
public:
QWaylandXdgActivationV1();
~QWaylandXdgActivationV1() override;
QWaylandXdgActivationTokenV1 *
requestXdgActivationToken(QtWaylandClient::QWaylandDisplay *display, struct ::wl_surface *surface, std::optional<uint32_t> serial, const QString &app_id);
};
#endif // QWAYLANDXDGACTIVATIONV1_P_H

View File

@ -32,7 +32,7 @@ template<typename T>
T stringToEnum(QMetaEnum metaEnum, const QString &str)
{
T ret = {};
const auto splitted = str.split(QLatin1Char('|'));
const auto splitted = str.split(QLatin1Char('|'), Qt::SkipEmptyParts);
for (const auto &value : splitted) {
ret |= T(metaEnum.keyToValue(qPrintable(value)));
}