File indexing completed on 2024-11-10 04:57:33
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.h" 0008 #include "display.h" 0009 #include "subsurface_p.h" 0010 #include "surface_p.h" 0011 #include "transaction.h" 0012 0013 namespace KWin 0014 { 0015 static const int s_version = 1; 0016 0017 SubCompositorInterfacePrivate::SubCompositorInterfacePrivate(Display *display, SubCompositorInterface *q) 0018 : QtWaylandServer::wl_subcompositor(*display, s_version) 0019 , q(q) 0020 { 0021 } 0022 0023 void SubCompositorInterfacePrivate::subcompositor_destroy(Resource *resource) 0024 { 0025 wl_resource_destroy(resource->handle); 0026 } 0027 0028 void SubCompositorInterfacePrivate::subcompositor_get_subsurface(Resource *resource, 0029 uint32_t id, 0030 ::wl_resource *surface_resource, 0031 ::wl_resource *parent_resource) 0032 { 0033 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0034 SurfaceInterface *parent = SurfaceInterface::get(parent_resource); 0035 0036 if (!surface) { 0037 wl_resource_post_error(resource->handle, error_bad_surface, "no surface"); 0038 return; 0039 } 0040 if (!parent) { 0041 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0042 return; 0043 } 0044 0045 if (const SurfaceRole *role = surface->role()) { 0046 if (role != SubSurfaceInterface::role()) { 0047 wl_resource_post_error(resource->handle, error_bad_surface, "the surface already has a role assigned %s", role->name().constData()); 0048 return; 0049 } 0050 } else { 0051 surface->setRole(SubSurfaceInterface::role()); 0052 } 0053 0054 if (surface == parent) { 0055 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d cannot be its own parent", wl_resource_get_id(surface_resource)); 0056 return; 0057 } 0058 if (parent->subSurface() && parent->subSurface()->mainSurface() == surface) { 0059 wl_resource_post_error(resource->handle, error_bad_surface, "wl_surface@%d is an ancestor of parent", wl_resource_get_id(surface_resource)); 0060 return; 0061 } 0062 0063 wl_resource *subsurfaceResource = wl_resource_create(resource->client(), &wl_subsurface_interface, resource->version(), id); 0064 if (!subsurfaceResource) { 0065 wl_resource_post_no_memory(resource->handle); 0066 return; 0067 } 0068 0069 Q_EMIT q->subSurfaceCreated(new SubSurfaceInterface(surface, parent, subsurfaceResource)); 0070 } 0071 0072 SubCompositorInterface::SubCompositorInterface(Display *display, QObject *parent) 0073 : QObject(parent) 0074 , d(new SubCompositorInterfacePrivate(display, this)) 0075 0076 { 0077 } 0078 0079 SubCompositorInterface::~SubCompositorInterface() 0080 { 0081 } 0082 0083 SubSurfaceInterfacePrivate *SubSurfaceInterfacePrivate::get(SubSurfaceInterface *subsurface) 0084 { 0085 return subsurface->d.get(); 0086 } 0087 0088 SubSurfaceInterfacePrivate::SubSurfaceInterfacePrivate(SubSurfaceInterface *q, SurfaceInterface *surface, SurfaceInterface *parent, ::wl_resource *resource) 0089 : QtWaylandServer::wl_subsurface(resource) 0090 , q(q) 0091 , surface(surface) 0092 , parent(parent) 0093 { 0094 } 0095 0096 void SubSurfaceInterfacePrivate::subsurface_destroy_resource(Resource *resource) 0097 { 0098 delete q; 0099 } 0100 0101 void SubSurfaceInterfacePrivate::subsurface_destroy(Resource *resource) 0102 { 0103 wl_resource_destroy(resource->handle); 0104 } 0105 0106 void SubSurfaceInterfacePrivate::subsurface_set_position(Resource *resource, int32_t x, int32_t y) 0107 { 0108 if (!parent) { 0109 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0110 return; 0111 } 0112 0113 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0114 0115 parentPrivate->pending->subsurface.position[q] = QPoint(x, y); 0116 parentPrivate->pending->subsurfacePositionChanged = true; 0117 } 0118 0119 void SubSurfaceInterfacePrivate::subsurface_place_above(Resource *resource, struct ::wl_resource *sibling_resource) 0120 { 0121 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource); 0122 if (!sibling) { 0123 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling"); 0124 return; 0125 } 0126 if (!parent) { 0127 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0128 return; 0129 } 0130 0131 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0132 if (!parentPrivate->raiseChild(q, sibling)) { 0133 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling"); 0134 } 0135 } 0136 0137 void SubSurfaceInterfacePrivate::subsurface_place_below(Resource *resource, struct ::wl_resource *sibling_resource) 0138 { 0139 SurfaceInterface *sibling = SurfaceInterface::get(sibling_resource); 0140 if (!sibling) { 0141 wl_resource_post_error(resource->handle, error_bad_surface, "no sibling"); 0142 return; 0143 } 0144 if (!parent) { 0145 wl_resource_post_error(resource->handle, error_bad_surface, "no parent"); 0146 return; 0147 } 0148 0149 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0150 if (!parentPrivate->lowerChild(q, sibling)) { 0151 wl_resource_post_error(resource->handle, error_bad_surface, "incorrect sibling"); 0152 } 0153 } 0154 0155 void SubSurfaceInterfacePrivate::subsurface_set_sync(Resource *) 0156 { 0157 if (mode == SubSurfaceInterface::Mode::Synchronized) { 0158 return; 0159 } 0160 mode = SubSurfaceInterface::Mode::Synchronized; 0161 Q_EMIT q->modeChanged(SubSurfaceInterface::Mode::Synchronized); 0162 } 0163 0164 void SubSurfaceInterfacePrivate::subsurface_set_desync(Resource *) 0165 { 0166 if (mode == SubSurfaceInterface::Mode::Desynchronized) { 0167 return; 0168 } 0169 mode = SubSurfaceInterface::Mode::Desynchronized; 0170 if (!q->isSynchronized()) { 0171 q->parentDesynchronized(); 0172 } 0173 Q_EMIT q->modeChanged(SubSurfaceInterface::Mode::Desynchronized); 0174 } 0175 0176 SubSurfaceInterface::SubSurfaceInterface(SurfaceInterface *surface, SurfaceInterface *parent, wl_resource *resource) 0177 : d(new SubSurfaceInterfacePrivate(this, surface, parent, resource)) 0178 { 0179 SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface); 0180 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(parent); 0181 surfacePrivate->subsurface.handle = this; 0182 parentPrivate->addChild(this); 0183 0184 connect(surface, &SurfaceInterface::destroyed, this, [this]() { 0185 delete this; 0186 }); 0187 } 0188 0189 SubSurfaceInterface::~SubSurfaceInterface() 0190 { 0191 if (d->parent) { 0192 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent); 0193 parentPrivate->removeChild(this); 0194 } 0195 if (d->surface) { 0196 SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(d->surface); 0197 surfacePrivate->subsurface.handle = nullptr; 0198 surfacePrivate->subsurface.transaction.reset(); 0199 } 0200 } 0201 0202 SurfaceRole *SubSurfaceInterface::role() 0203 { 0204 static SurfaceRole role(QByteArrayLiteral("wl_subsurface")); 0205 return &role; 0206 } 0207 0208 QPoint SubSurfaceInterface::position() const 0209 { 0210 return d->position; 0211 } 0212 0213 SurfaceInterface *SubSurfaceInterface::surface() const 0214 { 0215 return d->surface; 0216 } 0217 0218 SurfaceInterface *SubSurfaceInterface::parentSurface() const 0219 { 0220 return d->parent; 0221 } 0222 0223 SubSurfaceInterface::Mode SubSurfaceInterface::mode() const 0224 { 0225 return d->mode; 0226 } 0227 0228 bool SubSurfaceInterface::isSynchronized() const 0229 { 0230 if (d->mode == Mode::Synchronized) { 0231 return true; 0232 } 0233 if (!d->parent) { 0234 // that shouldn't happen, but let's assume false 0235 return false; 0236 } 0237 if (d->parent->subSurface()) { 0238 // follow parent's mode 0239 return d->parent->subSurface()->isSynchronized(); 0240 } 0241 // parent is no subsurface, thus parent is in desync mode and this surface is in desync mode 0242 return false; 0243 } 0244 0245 SurfaceInterface *SubSurfaceInterface::mainSurface() const 0246 { 0247 if (!d->parent) { 0248 return nullptr; 0249 } 0250 SurfaceInterfacePrivate *parentPrivate = SurfaceInterfacePrivate::get(d->parent); 0251 if (parentPrivate->subsurface.handle) { 0252 return parentPrivate->subsurface.handle->mainSurface(); 0253 } 0254 return d->parent; 0255 } 0256 0257 void SubSurfaceInterface::parentDesynchronized() 0258 { 0259 if (d->mode == SubSurfaceInterface::Mode::Synchronized) { 0260 return; 0261 } 0262 0263 auto surfacePrivate = SurfaceInterfacePrivate::get(d->surface); 0264 if (surfacePrivate->subsurface.transaction) { 0265 surfacePrivate->subsurface.transaction->commit(); 0266 surfacePrivate->subsurface.transaction.release(); 0267 } 0268 0269 const auto below = d->surface->below(); 0270 for (SubSurfaceInterface *child : below) { 0271 child->parentDesynchronized(); 0272 } 0273 0274 const auto above = d->surface->above(); 0275 for (SubSurfaceInterface *child : above) { 0276 child->parentDesynchronized(); 0277 } 0278 } 0279 0280 void SubSurfaceInterface::parentApplyState(quint32 serial) 0281 { 0282 auto parentPrivate = SurfaceInterfacePrivate::get(d->parent); 0283 if (parentPrivate->current->subsurfacePositionChanged) { 0284 const QPoint &pos = parentPrivate->current->subsurface.position[this]; 0285 if (d->position != pos) { 0286 d->position = pos; 0287 Q_EMIT positionChanged(pos); 0288 } 0289 } 0290 } 0291 0292 } // namespace KWin 0293 0294 #include "moc_subcompositor.cpp"