File indexing completed on 2024-05-12 05:32: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.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"