File indexing completed on 2024-12-08 04:20:24

0001 /*
0002  * SPDX-License-Identifier: LGPL-2.0-or-later
0003  *
0004  * SPDX-FileCopyrightText: 2022 Aleix Pol Gonzalez <aleixpol@kde.org>
0005  */
0006 
0007 #include "xdgexporterv2.h"
0008 
0009 #include <qpa/qplatformnativeinterface.h>
0010 #include <QDebug>
0011 #include <QGuiApplication>
0012 #include <QWindow>
0013 #include <QWidget>
0014 
0015 class WidgetWatcher : public QObject
0016 {
0017 public:
0018     WidgetWatcher(XdgExporterV2 *exporter, XdgExportedV2 *toExport, QWidget *theWidget)
0019         : QObject(theWidget)
0020         , m_toExport(toExport)
0021         , m_widget(theWidget)
0022         , m_exporter(exporter)
0023     {
0024         theWidget->installEventFilter(this);
0025     }
0026 
0027     ~WidgetWatcher() {
0028         delete m_toExport;
0029     }
0030 
0031     bool eventFilter(QObject * watched, QEvent * event) override {
0032         Q_ASSERT(watched == parent());
0033         if (event->type() == QEvent::PlatformSurface) {
0034             m_toExport->setWindow(m_widget->windowHandle());
0035         }
0036         return false;
0037     }
0038 
0039     QPointer<XdgExportedV2> m_toExport;
0040     QWidget *const m_widget;
0041     XdgExporterV2 *const m_exporter;
0042 };
0043 
0044 XdgExportedV2::XdgExportedV2(XdgExporterV2* exporter)
0045     : QtWayland::zxdg_exported_v2()
0046     , m_exporter(exporter)
0047 {
0048 }
0049 
0050 XdgExportedV2::~XdgExportedV2()
0051 {
0052     destroy();
0053 }
0054 
0055 void XdgExportedV2::setWindow(QWindow* window) {
0056     Q_ASSERT(window);
0057 
0058     useWindow(window);
0059     connect(window, &QWindow::visibilityChanged, this, [this, window] (QWindow::Visibility visibility) {
0060         if (visibility != QWindow::Hidden) {
0061             useWindow(window);
0062         }
0063     });
0064     connect(window, &QWindow::destroyed, this, &QObject::deleteLater);
0065 }
0066 
0067 void XdgExportedV2::useWindow(QWindow* window)
0068 {
0069     QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
0070     auto surface = static_cast<wl_surface *>(nativeInterface->nativeResourceForWindow("surface", window));
0071     if (surface) {
0072         auto tl = m_exporter->export_toplevel(surface);
0073         if (tl) {
0074             init(tl);
0075         } else {
0076             qDebug() << "could not export top level";
0077         }
0078     } else {
0079         qDebug() << "could not get surface";
0080     }
0081 }
0082 
0083 std::optional<QString> XdgExportedV2::handle() const
0084 {
0085     return m_handle;
0086 }
0087 
0088 ///////////////////////////////////////////////////////////
0089 
0090 XdgExporterV2::XdgExporterV2()
0091     : QWaylandClientExtensionTemplate(ZXDG_EXPORTER_V2_DESTROY_SINCE_VERSION)
0092 {
0093     initialize();
0094 
0095     if (!isInitialized()) {
0096         qWarning() << "Remember requesting the interface on your desktop file: X-KDE-Wayland-Interfaces=zkde_screencast_unstable_v1";
0097     }
0098     Q_ASSERT(isInitialized());
0099 }
0100 
0101 XdgExporterV2::~XdgExporterV2()
0102 {
0103     destroy();
0104 }
0105 
0106 XdgExportedV2* XdgExporterV2::exportWindow(QWindow* window)
0107 {
0108     if (!window) {
0109         qDebug() << "no window!";
0110         return nullptr;
0111     }
0112 
0113     auto exported = new XdgExportedV2(this);
0114     exported->setWindow(window);
0115     return exported;
0116 }
0117 
0118 XdgExportedV2* XdgExporterV2::exportWidget(QWidget* widget)
0119 {
0120     if (widget->windowHandle()) {
0121         return exportWindow(widget->windowHandle());
0122     }
0123     auto nakedExporter = new XdgExportedV2(this);
0124     new WidgetWatcher(this, nakedExporter, widget);
0125     return nakedExporter;
0126 }