File indexing completed on 2024-05-19 16:35:28
0001 /* 0002 SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org> 0003 SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 #include "subcompositor_interface.h" 0008 #include "display.h" 0009 #include "subsurface_interface_p.h" 0010 #include "surface_interface_p.h" 0011 0012 namespace KWaylandServer 0013 { 0014 static const int s_version = 1; 0015 0016 SubCompositorInterfacePrivate::SubCompositorInterfacePrivate(Display *display, SubCompositorInterface *q) 0017 : QtWaylandServer::wl_subcompositor(*display, s_version) 0018 , q(q) 0019 { 0020 } 0021 0022 void SubCompositorInterfacePrivate::subcompositor_destroy(Resource *resource) 0023 { 0024 wl_resource_destroy(resource->handle); 0025 } 0026 0027 void SubCompositorInterfacePrivate::subcompositor_get_subsurface(Resource *resource, 0028 uint32_t id, 0029 ::wl_resource *surface_resource, 0030 ::wl_resource *parent_resource) 0031 { 0032 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0033 SurfaceInterface *parent = SurfaceInterface::get(parent_resource); 0034 0035 if (!surface) { 0036 wl_resource_post_error(resource->handle, error_bad_surface, "no surface"); 0037 return; 0038 } 0039 if (!parent) { 0040 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0041 return; 0042 } 0043 0044 const SurfaceRole *surfaceRole = SurfaceRole::get(surface); 0045 if (surfaceRole) { 0046 wl_resource_post_error(resource->handle, error_bad_surface, "the surface already has a role assigned %s", surfaceRole->name().constData()); 0047 return; 0048 } 0049 0050 if (surface == parent) { 0051 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d cannot be its own parent", wl_resource_get_id(surface_resource)); 0052 return; 0053 } 0054 if (parent->subSurface() && parent->subSurface()->mainSurface() == surface) { 0055 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d is an ancestor of parent", wl_resource_get_id(surface_resource)); 0056 return; 0057 } 0058 0059 wl_resource *subsurfaceResource = wl_resource_create(resource->client(), &wl_subsurface_interface, resource->version(), id); 0060 if (!subsurfaceResource) { 0061 wl_resource_post_no_memory(resource->handle); 0062 return; 0063 } 0064 0065 Q_EMIT q->subSurfaceCreated(new SubSurfaceInterface(surface, parent, subsurfaceResource)); 0066 } 0067 0068 SubCompositorInterface::SubCompositorInterface(Display *display, QObject *parent) 0069 : QObject(parent) 0070 , d(new SubCompositorInterfacePrivate(display, this)) 0071 0072 { 0073 } 0074 0075 SubCompositorInterface::~SubCompositorInterface() 0076 { 0077 } 0078 0079 SubSurfaceInterfacePrivate *SubSurfaceInterfacePrivate::get(SubSurfaceInterface *subsurface) 0080 { 0081 return subsurface->d.get(); 0082 } 0083 0084 SubSurfaceInterfacePrivate::SubSurfaceInterfacePrivate(SubSurfaceInterface *q, SurfaceInterface *surface, SurfaceInterface *parent, ::wl_resource *resource) 0085 : SurfaceRole(surface, QByteArrayLiteral("wl_subsurface")) 0086 , QtWaylandServer::wl_subsurface(resource) 0087 , q(q) 0088 , surface(surface) 0089 , parent(parent) 0090 { 0091 } 0092 0093 void SubSurfaceInterfacePrivate::subsurface_destroy_resource(Resource *resource) 0094 { 0095 delete q; 0096 } 0097 0098 void SubSurfaceInterfacePrivate::subsurface_destroy(Resource *resource) 0099 { 0100 wl_resource_destroy(resource->handle); 0101 } 0102 0103 void SubSurfaceInterfacePrivate::subsurface_set_position(Resource *resource, int32_t x, int32_t y) 0104 { 0105 if (pendingPosition == QPoint(x, y)) { 0106 return; 0107 } 0108 pendingPosition = QPoint(x, y); 0109 hasPendingPosition = true; 0110 } 0111 0112 void SubSurfaceInterfacePrivate::subsurface_place_above(Resource *resource, struct ::wl_resource *sibling_resource) 0113 { 0114 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource); 0115 if (!sibling) { 0116 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling"); 0117 return; 0118 } 0119 if (!parent) { 0120 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0121 return; 0122 } 0123 0124 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0125 if (!parentPrivate->raiseChild(q, sibling)) { 0126 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling"); 0127 } 0128 } 0129 0130 void SubSurfaceInterfacePrivate::subsurface_place_below(Resource *resource, struct ::wl_resource *sibling_resource) 0131 { 0132 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource); 0133 if (!sibling) { 0134 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling"); 0135 return; 0136 } 0137 if (!parent) { 0138 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0139 return; 0140 } 0141 0142 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0143 if (!parentPrivate->lowerChild(q, sibling)) { 0144 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling"); 0145 } 0146 } 0147 0148 void SubSurfaceInterfacePrivate::subsurface_set_sync(Resource *) 0149 { 0150 if (mode == SubSurfaceInterface::Mode::Synchronized) { 0151 return; 0152 } 0153 mode = SubSurfaceInterface::Mode::Synchronized; 0154 Q_EMIT q->modeChanged(SubSurfaceInterface::Mode::Synchronized); 0155 } 0156 0157 void SubSurfaceInterfacePrivate::subsurface_set_desync(Resource *) 0158 { 0159 if (mode == SubSurfaceInterface::Mode::Desynchronized) { 0160 return; 0161 } 0162 mode = SubSurfaceInterface::Mode::Desynchronized; 0163 if (!q->isSynchronized()) { 0164 auto surfacePrivate = SurfaceInterfacePrivate::get(surface); 0165 surfacePrivate->commitFromCache(); 0166 } 0167 Q_EMIT q->modeChanged(SubSurfaceInterface::Mode::Desynchronized); 0168 } 0169 0170 void SubSurfaceInterfacePrivate::commit() 0171 { 0172 } 0173 0174 void SubSurfaceInterfacePrivate::parentCommit() 0175 { 0176 if (hasPendingPosition) { 0177 hasPendingPosition = false; 0178 position = pendingPosition; 0179 Q_EMIT q->positionChanged(position); 0180 } 0181 0182 if (mode == SubSurfaceInterface::Mode::Synchronized) { 0183 auto surfacePrivate = SurfaceInterfacePrivate::get(surface); 0184 surfacePrivate->commitFromCache(); 0185 } 0186 } 0187 0188 SubSurfaceInterface::SubSurfaceInterface(SurfaceInterface *surface, SurfaceInterface *parent, wl_resource *resource) 0189 : d(new SubSurfaceInterfacePrivate(this, surface, parent, resource)) 0190 { 0191 SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface); 0192 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0193 surfacePrivate->subSurface = this; 0194 parentPrivate->addChild(this); 0195 0196 connect(surface, &SurfaceInterface::destroyed, this, [this]() { 0197 delete this; 0198 }); 0199 } 0200 0201 SubSurfaceInterface::~SubSurfaceInterface() 0202 { 0203 if (d->parent) { 0204 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent); 0205 parentPrivate->removeChild(this); 0206 } 0207 if (d->surface) { 0208 SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(d->surface); 0209 surfacePrivate->subSurface = nullptr; 0210 } 0211 } 0212 0213 QPoint SubSurfaceInterface::position() const 0214 { 0215 return d->position; 0216 } 0217 0218 SurfaceInterface *SubSurfaceInterface::surface() const 0219 { 0220 return d->surface; 0221 } 0222 0223 SurfaceInterface *SubSurfaceInterface::parentSurface() const 0224 { 0225 return d->parent; 0226 } 0227 0228 SubSurfaceInterface::Mode SubSurfaceInterface::mode() const 0229 { 0230 return d->mode; 0231 } 0232 0233 bool SubSurfaceInterface::isSynchronized() const 0234 { 0235 if (d->mode == Mode::Synchronized) { 0236 return true; 0237 } 0238 if (!d->parent) { 0239 // that shouldn't happen, but let's assume false 0240 return false; 0241 } 0242 if (d->parent->subSurface()) { 0243 // follow parent's mode 0244 return d->parent->subSurface()->isSynchronized(); 0245 } 0246 // parent is no subsurface, thus parent is in desync mode and this surface is in desync mode 0247 return false; 0248 } 0249 0250 SurfaceInterface *SubSurfaceInterface::mainSurface() const 0251 { 0252 if (!d->parent) { 0253 return nullptr; 0254 } 0255 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent); 0256 if (parentPrivate->subSurface) { 0257 return parentPrivate->subSurface->mainSurface(); 0258 } 0259 return d->parent; 0260 } 0261 0262 } // namespace KWaylandServer