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"