/* SPDX-FileCopyrightText: 2022 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "xwaylandshell_v1.h" #include "display.h" #include "surface.h" #include "qwayland-server-xwayland-shell-v1.h" #include namespace KWin { static const quint32 s_version = 1; class XwaylandShellV1InterfacePrivate : public QtWaylandServer::xwayland_shell_v1 { public: XwaylandShellV1InterfacePrivate(Display *display, XwaylandShellV1Interface *q); XwaylandShellV1Interface *q; QList m_surfaces; protected: void xwayland_shell_v1_destroy(Resource *resource) override; void xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, struct ::wl_resource *surface) override; }; struct XwaylandSurfaceV1Commit { std::optional serial; }; class XwaylandSurfaceV1InterfacePrivate : public SurfaceExtension, public QtWaylandServer::xwayland_surface_v1 { public: XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q); void apply(XwaylandSurfaceV1Commit *commit) override; XwaylandSurfaceV1Interface *q; XwaylandShellV1Interface *shell; QPointer surface; std::optional serial; protected: void xwayland_surface_v1_destroy_resource(Resource *resource) override; void xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi) override; void xwayland_surface_v1_destroy(Resource *resource) override; }; XwaylandShellV1InterfacePrivate::XwaylandShellV1InterfacePrivate(Display *display, XwaylandShellV1Interface *q) : QtWaylandServer::xwayland_shell_v1(*display, s_version) , q(q) { } void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_destroy(Resource *resource) { wl_resource_destroy(resource->handle); } void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, ::wl_resource *surface_resource) { SurfaceInterface *surface = SurfaceInterface::get(surface_resource); if (const SurfaceRole *role = surface->role()) { if (role != XwaylandSurfaceV1Interface::role()) { wl_resource_post_error(resource->handle, error_role, "the surface already has a role assigned %s", role->name().constData()); return; } } else { surface->setRole(XwaylandSurfaceV1Interface::role()); } auto xwaylandSurface = new XwaylandSurfaceV1Interface(q, surface, resource->client(), id, resource->version()); m_surfaces.append(xwaylandSurface); QObject::connect(xwaylandSurface, &QObject::destroyed, q, [this, xwaylandSurface]() { m_surfaces.removeOne(xwaylandSurface); }); } XwaylandSurfaceV1InterfacePrivate::XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q) : SurfaceExtension(surface) , QtWaylandServer::xwayland_surface_v1(client, id, version) , q(q) , shell(shell) , surface(surface) { } void XwaylandSurfaceV1InterfacePrivate::apply(XwaylandSurfaceV1Commit *commit) { if (commit->serial.has_value()) { serial = commit->serial; Q_EMIT shell->surfaceAssociated(q); } } void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy_resource(Resource *resource) { delete q; } void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi) { const uint64_t serial = (uint64_t(serial_hi) << 32) | serial_lo; if (!serial) { wl_resource_post_error(resource->handle, error_invalid_serial, "given serial is 0"); return; } if (this->serial.has_value()) { wl_resource_post_error(resource->handle, error_already_associated, "xwayland_surface_v1 already has a serial assigned to it: %" PRIu64, this->serial.value()); return; } pending.serial = serial; } void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy(Resource *resource) { wl_resource_destroy(resource->handle); } XwaylandShellV1Interface::XwaylandShellV1Interface(Display *display, QObject *parent) : QObject(parent) , d(new XwaylandShellV1InterfacePrivate(display, this)) { } XwaylandShellV1Interface::~XwaylandShellV1Interface() { } XwaylandSurfaceV1Interface *XwaylandShellV1Interface::findSurface(uint64_t serial) const { for (XwaylandSurfaceV1Interface *surface : std::as_const(d->m_surfaces)) { if (surface->serial() == serial) { return surface; } } return nullptr; } XwaylandSurfaceV1Interface::XwaylandSurfaceV1Interface(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version) : d(new XwaylandSurfaceV1InterfacePrivate(shell, surface, client, id, version, this)) { } XwaylandSurfaceV1Interface::~XwaylandSurfaceV1Interface() { } SurfaceRole *XwaylandSurfaceV1Interface::role() { static SurfaceRole role(QByteArrayLiteral("xwayland_surface_v1")); return &role; } SurfaceInterface *XwaylandSurfaceV1Interface::surface() const { return d->surface; } std::optional XwaylandSurfaceV1Interface::serial() const { return d->serial; } } // namespace KWin #include "moc_xwaylandshell_v1.cpp"