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