7#include "windowsystem.h"
9#include "surfacehelper.h"
10#include "waylandxdgactivationv1_p.h"
11#include "waylandxdgdialogv1_p.h"
12#include "waylandxdgforeignv2_p.h"
14#include <KWaylandExtras>
15#include <KWindowSystem>
17#include "qwayland-plasma-window-management.h"
19#include <QGuiApplication>
20#include <QLibraryInfo>
25#include <QVersionNumber>
26#include <QWaylandClientExtensionTemplate>
28#include <qpa/qplatformnativeinterface.h>
29#include <qpa/qplatformwindow_p.h>
31constexpr const char *c_kdeXdgForeignExportedProperty(
"_kde_xdg_foreign_exported_v2");
32constexpr const char *c_kdeXdgForeignImportedProperty(
"_kde_xdg_foreign_imported_v2");
33constexpr const char *c_kdeXdgForeignPendingHandleProperty(
"_kde_xdg_foreign_pending_handle");
35class WindowManagement :
public QWaylandClientExtensionTemplate<WindowManagement>,
public QtWayland::org_kde_plasma_window_management
39 : QWaylandClientExtensionTemplate<WindowManagement>(17)
43 void org_kde_plasma_window_management_show_desktop_changed(uint32_t state)
override
45 showingDesktop = state == show_desktop_enabled;
49 bool showingDesktop =
false;
52WindowSystem::WindowSystem()
54 , KWindowSystemPrivateV2()
55 , m_lastToken(qEnvironmentVariable(
"XDG_ACTIVATION_TOKEN"))
57 m_windowManagement =
new WindowManagement;
60WindowSystem::~WindowSystem()
62 delete m_windowManagement;
65void WindowSystem::activateWindow(
QWindow *win,
long int time)
68 auto s = surfaceForWindow(win);
72 WaylandXdgActivationV1 *activation = WaylandXdgActivationV1::self();
73 if (!activation->isActive()) {
76 activation->activate(m_lastToken, s);
79void WindowSystem::requestToken(
QWindow *window, uint32_t serial,
const QString &app_id)
84 wl_surface *wlSurface = surfaceForWindow(window);
86 WaylandXdgActivationV1 *activation = WaylandXdgActivationV1::self();
87 if (!activation->isActive()) {
95 auto waylandApp = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>();
96 auto seat = waylandApp ? waylandApp->lastInputSeat() :
nullptr;
97 auto tokenReq = activation->requestXdgActivationToken(seat, wlSurface, serial, app_id);
106void WindowSystem::setCurrentToken(
const QString &token)
111quint32 WindowSystem::lastInputSerial(
QWindow *window)
114 if (
auto waylandApp = qGuiApp->nativeInterface<QNativeInterface::QWaylandApplication>()) {
115 return waylandApp->lastInputSerial();
120void WindowSystem::setShowingDesktop(
bool showing)
122 if (!m_windowManagement->isActive()) {
125 m_windowManagement->show_desktop(showing ? WindowManagement::show_desktop_enabled : WindowManagement::show_desktop_disabled);
128bool WindowSystem::showingDesktop()
130 if (!m_windowManagement->isActive()) {
133 return m_windowManagement->showingDesktop;
136void WindowSystem::exportWindow(
QWindow *window)
138 auto emitHandle = [
window](
const QString &handle) {
154 auto waylandWindow =
window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
155 if (!waylandWindow) {
160 auto &exporter = WaylandXdgForeignExporterV2::self();
161 if (!exporter.isActive()) {
168 WaylandXdgForeignExportedV2 *exported = waylandWindow->property(c_kdeXdgForeignExportedProperty).value<WaylandXdgForeignExportedV2 *>();
170 exported = exporter.exportToplevel(surfaceForWindow(window));
171 exported->setParent(waylandWindow);
173 waylandWindow->setProperty(c_kdeXdgForeignExportedProperty,
QVariant::fromValue(exported));
175 waylandWindow->setProperty(c_kdeXdgForeignExportedProperty, QVariant());
178 connect(exported, &WaylandXdgForeignExportedV2::handleReceived, window, [window](
const QString &handle) {
183 if (!exported->handle().isEmpty()) {
184 emitHandle(exported->handle());
188void WindowSystem::unexportWindow(
QWindow *window)
190 auto waylandWindow =
window ?
window->nativeInterface<QNativeInterface::Private::QWaylandWindow>() : nullptr;
191 if (!waylandWindow) {
195 WaylandXdgForeignExportedV2 *exported = waylandWindow->property(c_kdeXdgForeignExportedProperty).value<WaylandXdgForeignExportedV2 *>();
197 Q_ASSERT(!waylandWindow->property(c_kdeXdgForeignExportedProperty).isValid());
200void WindowSystem::setMainWindow(
QWindow *window,
const QString &handle)
207 auto waylandWindow =
window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
208 if (!waylandWindow) {
214 auto *imported = waylandWindow->
property(c_kdeXdgForeignImportedProperty).
value<WaylandXdgForeignImportedV2 *>();
216 if (imported && imported->handle() != handle) {
219 Q_ASSERT(!waylandWindow->property(c_kdeXdgForeignImportedProperty).isValid());
227 if (
window->isExposed()) {
228 doSetMainWindow(window, handle);
234#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0)
238 connect(waylandWindow, &QNativeInterface::Private::QWaylandWindow::surfaceRoleCreated, window, [window, handle] {
239 doSetMainWindow(window, handle);
245bool WindowSystem::eventFilter(
QObject *watched,
QEvent *event)
247#if QT_VERSION < QT_VERSION_CHECK(6, 8, 0)
249 auto *
window =
static_cast<QWindow *
>(watched);
250 if (
window->isExposed()) {
253 doSetMainWindow(window, handle);
265void WindowSystem::doSetMainWindow(
QWindow *window,
const QString &handle)
270 auto waylandWindow =
window->nativeInterface<QNativeInterface::Private::QWaylandWindow>();
271 if (!waylandWindow) {
275 auto &importer = WaylandXdgForeignImporterV2::self();
276 if (!importer.isActive()) {
280 Q_ASSERT(!waylandWindow->property(c_kdeXdgForeignImportedProperty).isValid());
282 WaylandXdgForeignImportedV2 *imported = importer.importToplevel(handle);
283 imported->set_parent_of(surfaceForWindow(window));
284 imported->setParent(waylandWindow);
286 waylandWindow->setProperty(c_kdeXdgForeignImportedProperty,
QVariant::fromValue(imported));
288 waylandWindow->setProperty(c_kdeXdgForeignImportedProperty, QVariant());
293 auto *oldDialog = waylandWindow->findChild<WaylandXdgDialogV1 *>();
295 auto &xdgDialog = WaylandXdgDialogWmV1::self();
296 if (xdgDialog.isActive()) {
297 if (
auto *xdgToplevel = xdgToplevelForWindow(window)) {
298 auto *dialog = xdgDialog.getDialog(xdgToplevel);
300 dialog->setParent(waylandWindow);
309#include "moc_windowsystem.cpp"
void xdgActivationTokenArrived(int serial, const QString &token)
Activation token to pass to the client.
void windowExported(QWindow *window, const QString &handle)
Window handle to pass to the client.
void showingDesktopChanged(bool showing)
The state of showing the desktop has changed.
static KWindowSystem * self()
Access to the singleton instance.
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void destroyed(QObject *obj)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
QVariant property(const char *name) const const
void removeEventFilter(QObject *obj)
bool setProperty(const char *name, QVariant &&value)
bool isEmpty() const const
QVariant fromValue(T &&value)
QString toString() const const