File indexing completed on 2024-05-19 16:35:34
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_interface.h" 0008 0009 #include "display.h" 0010 #include "surfacerole_p.h" 0011 #include "surface_interface.h" 0012 0013 #include "qwayland-server-xwayland-shell-v1.h" 0014 0015 namespace KWaylandServer 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 XwaylandSurfaceV1State 0034 { 0035 std::optional<uint64_t> serial; 0036 }; 0037 0038 class XwaylandSurfaceV1InterfacePrivate : public SurfaceRole, 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 commit() override; 0044 0045 XwaylandSurfaceV1Interface *q; 0046 XwaylandShellV1Interface *shell; 0047 0048 XwaylandSurfaceV1State current; 0049 XwaylandSurfaceV1State pending; 0050 0051 protected: 0052 void xwayland_surface_v1_destroy_resource(Resource *resource) override; 0053 void xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi) override; 0054 void xwayland_surface_v1_destroy(Resource *resource) override; 0055 }; 0056 0057 XwaylandShellV1InterfacePrivate::XwaylandShellV1InterfacePrivate(Display *display, XwaylandShellV1Interface *q) 0058 : QtWaylandServer::xwayland_shell_v1(*display, s_version) 0059 , q(q) 0060 { 0061 } 0062 0063 void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_destroy(Resource *resource) 0064 { 0065 wl_resource_destroy(resource->handle); 0066 } 0067 0068 void XwaylandShellV1InterfacePrivate::xwayland_shell_v1_get_xwayland_surface(Resource *resource, uint32_t id, ::wl_resource *surface_resource) 0069 { 0070 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0071 if (auto role = SurfaceRole::get(surface)) { 0072 wl_resource_post_error(resource->handle, error_role, "the surface already has a role assigned %s", role->name().constData()); 0073 return; 0074 } 0075 0076 auto xwaylandSurface = new XwaylandSurfaceV1Interface(q, surface, resource->client(), id, resource->version()); 0077 m_surfaces.append(xwaylandSurface); 0078 QObject::connect(xwaylandSurface, &QObject::destroyed, q, [this, xwaylandSurface]() { 0079 m_surfaces.removeOne(xwaylandSurface); 0080 }); 0081 } 0082 0083 XwaylandSurfaceV1InterfacePrivate::XwaylandSurfaceV1InterfacePrivate(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version, XwaylandSurfaceV1Interface *q) 0084 : SurfaceRole(surface, QByteArrayLiteral("xwayland_surface_v1")) 0085 , QtWaylandServer::xwayland_surface_v1(client, id, version) 0086 , q(q) 0087 , shell(shell) 0088 { 0089 } 0090 0091 void XwaylandSurfaceV1InterfacePrivate::commit() 0092 { 0093 if (pending.serial.has_value()) { 0094 current.serial = std::exchange(pending.serial, std::nullopt); 0095 Q_EMIT shell->surfaceAssociated(q); 0096 } 0097 } 0098 0099 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy_resource(Resource *resource) 0100 { 0101 delete q; 0102 } 0103 0104 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_set_serial(Resource *resource, uint32_t serial_lo, uint32_t serial_hi) 0105 { 0106 const uint64_t serial = (uint64_t(serial_hi) << 32) | serial_lo; 0107 if (!serial) { 0108 wl_resource_post_error(resource->handle, error_invalid_serial, "given serial is 0"); 0109 return; 0110 } 0111 0112 if (current.serial.has_value()) { 0113 wl_resource_post_error(resource->handle, error_already_associated, 0114 "xwayland_surface_v1 already has a serial assigned to it: %" PRIu64, current.serial.value()); 0115 return; 0116 } 0117 0118 pending.serial = serial; 0119 } 0120 0121 void XwaylandSurfaceV1InterfacePrivate::xwayland_surface_v1_destroy(Resource *resource) 0122 { 0123 wl_resource_destroy(resource->handle); 0124 } 0125 0126 XwaylandShellV1Interface::XwaylandShellV1Interface(Display *display, QObject *parent) 0127 : QObject(parent) 0128 , d(new XwaylandShellV1InterfacePrivate(display, this)) 0129 { 0130 } 0131 0132 XwaylandShellV1Interface::~XwaylandShellV1Interface() 0133 { 0134 } 0135 0136 XwaylandSurfaceV1Interface *XwaylandShellV1Interface::findSurface(uint64_t serial) const 0137 { 0138 for (XwaylandSurfaceV1Interface *surface : std::as_const(d->m_surfaces)) { 0139 if (surface->serial() == serial) { 0140 return surface; 0141 } 0142 } 0143 return nullptr; 0144 } 0145 0146 XwaylandSurfaceV1Interface::XwaylandSurfaceV1Interface(XwaylandShellV1Interface *shell, SurfaceInterface *surface, wl_client *client, uint32_t id, int version) 0147 : d(new XwaylandSurfaceV1InterfacePrivate(shell, surface, client, id, version, this)) 0148 { 0149 } 0150 0151 XwaylandSurfaceV1Interface::~XwaylandSurfaceV1Interface() 0152 { 0153 } 0154 0155 SurfaceInterface *XwaylandSurfaceV1Interface::surface() const 0156 { 0157 return d->surface(); 0158 } 0159 0160 std::optional<uint64_t> XwaylandSurfaceV1Interface::serial() const 0161 { 0162 return d->current.serial; 0163 } 0164 0165 } // namespace KWaylandServer