File indexing completed on 2024-11-10 04:57:38

0001 /*
0002     SPDX-FileCopyrightText: 2022 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "xwaylandshell_v1.h"
0008 #include "display.h"
0009 #include "surface.h"
0010 
0011 #include "qwayland-server-xwayland-shell-v1.h"
0012 
0013 #include <QPointer>
0014 
0015 namespace KWin
0016 {
0017 
0018 static const quint32 s_version = 1;
0019 
0020 class XwaylandShellV1InterfacePrivate : public QtWaylandServer::xwayland_shell_v1
0021 {
0022 public:
0023     XwaylandShellV1InterfacePrivate(Display *display, XwaylandShellV1Interface *q);
0024 
0025     XwaylandShellV1Interface *q;
0026     QList<XwaylandSurfaceV1Interface *> m_surfaces;
0027 
0028 protected:
0029     void xwayland_shell_v1_destroy(Resource *resource) override;
0030     void xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) override;
0031 };
0032 
0033 struct XwaylandSurfaceV1Commit
0034 {
0035     std::optional<uint64_t> serial;
0036 };
0037 
0038 class XwaylandSurfaceV1InterfacePrivate : public SurfaceExtension<XwaylandSurfaceV1Commit>, public QtWaylandServer::xwayland_surface_v1
0039 {
0040 public:
0041     XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q);
0042 
0043     void apply(XwaylandSurfaceV1Commit *commit) override;
0044 
0045     XwaylandSurfaceV1Interface *q;
0046     XwaylandShellV1Interface *shell;
0047     QPointer<SurfaceInterface> surface;
0048     std::optional<uint64_t> serial;
0049 
0050 protected:
0051     void xwayland_surface_v1_destroy_resource(Resource *resource) override;
0052     void xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi) override;
0053     void xwayland_surface_v1_destroy(Resource *resource) override;
0054 };
0055 
0056 XwaylandShellV1InterfacePrivate::XwaylandShellV1InterfacePrivate(Display *display, XwaylandShellV1Interface *q)
0057     : QtWaylandServer::xwayland_shell_v1(*display, s_version)
0058     , q(q)
0059 {
0060 }
0061 
0062 void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_destroy(Resource *resource)
0063 {
0064     wl_resource_destroy(resource->handle);
0065 }
0066 
0067 void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, ::wl_resource *surface_resource)
0068 {
0069     SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
0070 
0071     if (const SurfaceRole *role = surface->role()) {
0072         if (role != XwaylandSurfaceV1Interface::role()) {
0073             wl_resource_post_error(resource->handle, error_role, "the surface already has a role assigned %s", role->name().constData());
0074             return;
0075         }
0076     } else {
0077         surface->setRole(XwaylandSurfaceV1Interface::role());
0078     }
0079 
0080     auto xwaylandSurface = new XwaylandSurfaceV1Interface(q, surface, resource->client(), id, resource->version());
0081     m_surfaces.append(xwaylandSurface);
0082     QObject::connect(xwaylandSurface, &QObject::destroyed, q, [this, xwaylandSurface]() {
0083         m_surfaces.removeOne(xwaylandSurface);
0084     });
0085 }
0086 
0087 XwaylandSurfaceV1InterfacePrivate::XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q)
0088     : SurfaceExtension(surface)
0089     , QtWaylandServer::xwayland_surface_v1(client, id, version)
0090     , q(q)
0091     , shell(shell)
0092     , surface(surface)
0093 {
0094 }
0095 
0096 void XwaylandSurfaceV1InterfacePrivate::apply(XwaylandSurfaceV1Commit *commit)
0097 {
0098     if (commit->serial.has_value()) {
0099         serial = commit->serial;
0100         Q_EMIT shell->surfaceAssociated(q);
0101     }
0102 }
0103 
0104 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy_resource(Resource *resource)
0105 {
0106     delete q;
0107 }
0108 
0109 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi)
0110 {
0111     const uint64_t serial = (uint64_t(serial_hi) << 32) | serial_lo;
0112     if (!serial) {
0113         wl_resource_post_error(resource->handle, error_invalid_serial, "given serial is 0");
0114         return;
0115     }
0116 
0117     if (this->serial.has_value()) {
0118         wl_resource_post_error(resource->handle, error_already_associated,
0119                                "xwayland_surface_v1 already has a serial assigned to it: %" PRIu64, this->serial.value());
0120         return;
0121     }
0122 
0123     pending.serial = serial;
0124 }
0125 
0126 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy(Resource *resource)
0127 {
0128     wl_resource_destroy(resource->handle);
0129 }
0130 
0131 XwaylandShellV1Interface::XwaylandShellV1Interface(Display *display, QObject *parent)
0132     : QObject(parent)
0133     , d(new XwaylandShellV1InterfacePrivate(display, this))
0134 {
0135 }
0136 
0137 XwaylandShellV1Interface::~XwaylandShellV1Interface()
0138 {
0139 }
0140 
0141 XwaylandSurfaceV1Interface *XwaylandShellV1Interface::findSurface(uint64_t serial) const
0142 {
0143     for (XwaylandSurfaceV1Interface *surface : std::as_const(d->m_surfaces)) {
0144         if (surface->serial() == serial) {
0145             return surface;
0146         }
0147     }
0148     return nullptr;
0149 }
0150 
0151 XwaylandSurfaceV1Interface::XwaylandSurfaceV1Interface(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version)
0152     : d(new XwaylandSurfaceV1InterfacePrivate(shell, surface, client, id, version, this))
0153 {
0154 }
0155 
0156 XwaylandSurfaceV1Interface::~XwaylandSurfaceV1Interface()
0157 {
0158 }
0159 
0160 SurfaceRole *XwaylandSurfaceV1Interface::role()
0161 {
0162     static SurfaceRole role(QByteArrayLiteral("xwayland_surface_v1"));
0163     return &role;
0164 }
0165 
0166 SurfaceInterface *XwaylandSurfaceV1Interface::surface() const
0167 {
0168     return d->surface;
0169 }
0170 
0171 std::optional<uint64_t> XwaylandSurfaceV1Interface::serial() const
0172 {
0173     return d->serial;
0174 }
0175 
0176 } // namespace KWin
0177 
0178 #include "moc_xwaylandshell_v1.cpp"