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 "surface_interface.h"
0008 #include "clientbuffer.h"
0009 #include "clientconnection.h"
0010 #include "compositor_interface.h"
0011 #include "contenttype_v1_interface.h"
0012 #include "display.h"
0013 #include "fractionalscale_v1_interface_p.h"
0014 #include "idleinhibit_v1_interface_p.h"
0015 #include "linuxdmabufv1clientbuffer.h"
0016 #include "pointerconstraints_v1_interface_p.h"
0017 #include "region_interface_p.h"
0018 #include "subcompositor_interface.h"
0019 #include "subsurface_interface_p.h"
0020 #include "surface_interface_p.h"
0021 #include "surfacerole_p.h"
0022 #include "utils.h"
0023 
0024 #include <wayland-server.h>
0025 // std
0026 #include <algorithm>
0027 #include <cmath>
0028 
0029 namespace KWaylandServer
0030 {
0031 
0032 static QRegion map_helper(const QMatrix4x4 &matrix, const QRegion &region)
0033 {
0034     QRegion result;
0035     for (const QRect &rect : region) {
0036         result += matrix.mapRect(QRectF(rect)).toAlignedRect();
0037     }
0038     return result;
0039 }
0040 
0041 SurfaceInterfacePrivate::SurfaceInterfacePrivate(SurfaceInterface *q)
0042     : q(q)
0043 {
0044     wl_list_init(&current.frameCallbacks);
0045     wl_list_init(&pending.frameCallbacks);
0046     wl_list_init(&cached.frameCallbacks);
0047 }
0048 
0049 SurfaceInterfacePrivate::~SurfaceInterfacePrivate()
0050 {
0051     wl_resource *resource;
0052     wl_resource *tmp;
0053 
0054     wl_resource_for_each_safe (resource, tmp, &current.frameCallbacks) {
0055         wl_resource_destroy(resource);
0056     }
0057     wl_resource_for_each_safe (resource, tmp, &pending.frameCallbacks) {
0058         wl_resource_destroy(resource);
0059     }
0060     wl_resource_for_each_safe (resource, tmp, &cached.frameCallbacks) {
0061         wl_resource_destroy(resource);
0062     }
0063 
0064     if (current.buffer) {
0065         current.buffer->unref();
0066     }
0067 }
0068 
0069 void SurfaceInterfacePrivate::addChild(SubSurfaceInterface *child)
0070 {
0071     // protocol is not precise on how to handle the addition of new sub surfaces
0072     pending.above.append(child);
0073     cached.above.append(child);
0074     current.above.append(child);
0075     child->surface()->setOutputs(outputs);
0076     child->surface()->setPreferredScale(preferredScale);
0077 
0078     Q_EMIT q->childSubSurfaceAdded(child);
0079     Q_EMIT q->childSubSurfacesChanged();
0080 }
0081 
0082 void SurfaceInterfacePrivate::removeChild(SubSurfaceInterface *child)
0083 {
0084     // protocol is not precise on how to handle the addition of new sub surfaces
0085     pending.below.removeAll(child);
0086     pending.above.removeAll(child);
0087     cached.below.removeAll(child);
0088     cached.above.removeAll(child);
0089     current.below.removeAll(child);
0090     current.above.removeAll(child);
0091     Q_EMIT q->childSubSurfaceRemoved(child);
0092     Q_EMIT q->childSubSurfacesChanged();
0093 }
0094 
0095 bool SurfaceInterfacePrivate::raiseChild(SubSurfaceInterface *subsurface, SurfaceInterface *anchor)
0096 {
0097     Q_ASSERT(subsurface->parentSurface() == q);
0098 
0099     QList<SubSurfaceInterface *> *anchorList;
0100     int anchorIndex;
0101 
0102     pending.below.removeOne(subsurface);
0103     pending.above.removeOne(subsurface);
0104 
0105     if (anchor == q) {
0106         // Pretend as if the parent surface were before the first child in the above list.
0107         anchorList = &pending.above;
0108         anchorIndex = -1;
0109     } else if (anchorIndex = pending.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
0110         anchorList = &pending.above;
0111     } else if (anchorIndex = pending.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
0112         anchorList = &pending.below;
0113     } else {
0114         return false; // The anchor belongs to other sub-surface tree.
0115     }
0116 
0117     anchorList->insert(anchorIndex + 1, subsurface);
0118     pending.childrenChanged = true;
0119     return true;
0120 }
0121 
0122 bool SurfaceInterfacePrivate::lowerChild(SubSurfaceInterface *subsurface, SurfaceInterface *anchor)
0123 {
0124     Q_ASSERT(subsurface->parentSurface() == q);
0125 
0126     QList<SubSurfaceInterface *> *anchorList;
0127     int anchorIndex;
0128 
0129     pending.below.removeOne(subsurface);
0130     pending.above.removeOne(subsurface);
0131 
0132     if (anchor == q) {
0133         // Pretend as if the parent surface were after the last child in the below list.
0134         anchorList = &pending.below;
0135         anchorIndex = pending.below.count();
0136     } else if (anchorIndex = pending.above.indexOf(anchor->subSurface()); anchorIndex != -1) {
0137         anchorList = &pending.above;
0138     } else if (anchorIndex = pending.below.indexOf(anchor->subSurface()); anchorIndex != -1) {
0139         anchorList = &pending.below;
0140     } else {
0141         return false; // The anchor belongs to other sub-surface tree.
0142     }
0143 
0144     anchorList->insert(anchorIndex, subsurface);
0145     pending.childrenChanged = true;
0146     return true;
0147 }
0148 
0149 void SurfaceInterfacePrivate::setShadow(const QPointer<ShadowInterface> &shadow)
0150 {
0151     pending.shadow = shadow;
0152     pending.shadowIsSet = true;
0153 }
0154 
0155 void SurfaceInterfacePrivate::setBlur(const QPointer<BlurInterface> &blur)
0156 {
0157     pending.blur = blur;
0158     pending.blurIsSet = true;
0159 }
0160 
0161 void SurfaceInterfacePrivate::setSlide(const QPointer<SlideInterface> &slide)
0162 {
0163     pending.slide = slide;
0164     pending.slideIsSet = true;
0165 }
0166 
0167 void SurfaceInterfacePrivate::setContrast(const QPointer<ContrastInterface> &contrast)
0168 {
0169     pending.contrast = contrast;
0170     pending.contrastIsSet = true;
0171 }
0172 
0173 void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerV1Interface *lock)
0174 {
0175     Q_ASSERT(!lockedPointer);
0176     Q_ASSERT(!confinedPointer);
0177 
0178     lockedPointer = lock;
0179 
0180     auto cleanUp = [this]() {
0181         lockedPointer = nullptr;
0182         QObject::disconnect(constrainsOneShotConnection);
0183         constrainsOneShotConnection = QMetaObject::Connection();
0184         QObject::disconnect(constrainsUnboundConnection);
0185         constrainsUnboundConnection = QMetaObject::Connection();
0186         Q_EMIT q->pointerConstraintsChanged();
0187     };
0188 
0189     if (lock->lifeTime() == LockedPointerV1Interface::LifeTime::OneShot) {
0190         constrainsOneShotConnection = QObject::connect(lock, &LockedPointerV1Interface::lockedChanged, q, [this, cleanUp] {
0191             if (lockedPointer->isLocked()) {
0192                 return;
0193             }
0194             cleanUp();
0195         });
0196     }
0197     constrainsUnboundConnection = QObject::connect(lock, &LockedPointerV1Interface::destroyed, q, cleanUp);
0198     Q_EMIT q->pointerConstraintsChanged();
0199 }
0200 
0201 void SurfaceInterfacePrivate::installPointerConstraint(ConfinedPointerV1Interface *confinement)
0202 {
0203     Q_ASSERT(!lockedPointer);
0204     Q_ASSERT(!confinedPointer);
0205 
0206     confinedPointer = confinement;
0207 
0208     auto cleanUp = [this]() {
0209         confinedPointer = nullptr;
0210         QObject::disconnect(constrainsOneShotConnection);
0211         constrainsOneShotConnection = QMetaObject::Connection();
0212         QObject::disconnect(constrainsUnboundConnection);
0213         constrainsUnboundConnection = QMetaObject::Connection();
0214         Q_EMIT q->pointerConstraintsChanged();
0215     };
0216 
0217     if (confinement->lifeTime() == ConfinedPointerV1Interface::LifeTime::OneShot) {
0218         constrainsOneShotConnection = QObject::connect(confinement, &ConfinedPointerV1Interface::confinedChanged, q, [this, cleanUp] {
0219             if (confinedPointer->isConfined()) {
0220                 return;
0221             }
0222             cleanUp();
0223         });
0224     }
0225     constrainsUnboundConnection = QObject::connect(confinement, &ConfinedPointerV1Interface::destroyed, q, cleanUp);
0226     Q_EMIT q->pointerConstraintsChanged();
0227 }
0228 
0229 void SurfaceInterfacePrivate::installIdleInhibitor(IdleInhibitorV1Interface *inhibitor)
0230 {
0231     idleInhibitors << inhibitor;
0232     QObject::connect(inhibitor, &IdleInhibitorV1Interface::destroyed, q, [this, inhibitor] {
0233         idleInhibitors.removeOne(inhibitor);
0234         if (idleInhibitors.isEmpty()) {
0235             Q_EMIT q->inhibitsIdleChanged();
0236         }
0237     });
0238     if (idleInhibitors.count() == 1) {
0239         Q_EMIT q->inhibitsIdleChanged();
0240     }
0241 }
0242 
0243 void SurfaceInterfacePrivate::surface_destroy_resource(Resource *)
0244 {
0245     Q_EMIT q->aboutToBeDestroyed();
0246     delete q;
0247 }
0248 
0249 void SurfaceInterfacePrivate::surface_destroy(Resource *resource)
0250 {
0251     wl_resource_destroy(resource->handle);
0252 }
0253 
0254 void SurfaceInterfacePrivate::surface_attach(Resource *resource, struct ::wl_resource *buffer, int32_t x, int32_t y)
0255 {
0256     if (wl_resource_get_version(resource->handle) >= WL_SURFACE_OFFSET_SINCE_VERSION) {
0257         if (x != 0 || y != 0) {
0258             wl_resource_post_error(resource->handle, error_invalid_offset, "wl_surface.attach offset must be 0");
0259             return;
0260         }
0261     } else {
0262         pending.offset = QPoint(x, y);
0263     }
0264 
0265     pending.bufferIsSet = true;
0266     if (!buffer) {
0267         // got a null buffer, deletes content in next frame
0268         pending.buffer = nullptr;
0269         pending.damage = QRegion();
0270         pending.bufferDamage = QRegion();
0271         return;
0272     }
0273     pending.buffer = compositor->display()->clientBufferForResource(buffer);
0274 }
0275 
0276 void SurfaceInterfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
0277 {
0278     pending.damage |= QRect(x, y, width, height);
0279 }
0280 
0281 void SurfaceInterfacePrivate::surface_frame(Resource *resource, uint32_t callback)
0282 {
0283     wl_resource *callbackResource = wl_resource_create(resource->client(),
0284                                                        &wl_callback_interface,
0285                                                        /* version */ 1,
0286                                                        callback);
0287     if (!callbackResource) {
0288         wl_resource_post_no_memory(resource->handle);
0289         return;
0290     }
0291 
0292     wl_resource_set_implementation(callbackResource, nullptr, nullptr, [](wl_resource *resource) {
0293         wl_list_remove(wl_resource_get_link(resource));
0294     });
0295 
0296     wl_list_insert(pending.frameCallbacks.prev, wl_resource_get_link(callbackResource));
0297 }
0298 
0299 void SurfaceInterfacePrivate::surface_set_opaque_region(Resource *resource, struct ::wl_resource *region)
0300 {
0301     RegionInterface *r = RegionInterface::get(region);
0302     pending.opaque = r ? r->region() : QRegion();
0303     pending.opaqueIsSet = true;
0304 }
0305 
0306 void SurfaceInterfacePrivate::surface_set_input_region(Resource *resource, struct ::wl_resource *region)
0307 {
0308     RegionInterface *r = RegionInterface::get(region);
0309     pending.input = r ? r->region() : infiniteRegion();
0310     pending.inputIsSet = true;
0311 }
0312 
0313 void SurfaceInterfacePrivate::surface_commit(Resource *resource)
0314 {
0315     if (subSurface) {
0316         commitSubSurface();
0317     } else {
0318         applyState(&pending);
0319     }
0320 }
0321 
0322 void SurfaceInterfacePrivate::surface_set_buffer_transform(Resource *resource, int32_t transform)
0323 {
0324     if (transform < 0 || transform > WL_OUTPUT_TRANSFORM_FLIPPED_270) {
0325         wl_resource_post_error(resource->handle, error_invalid_transform, "buffer transform must be a valid transform (%d specified)", transform);
0326         return;
0327     }
0328     pending.bufferTransform = KWin::Output::Transform(transform);
0329     pending.bufferTransformIsSet = true;
0330 }
0331 
0332 void SurfaceInterfacePrivate::surface_set_buffer_scale(Resource *resource, int32_t scale)
0333 {
0334     if (scale < 1) {
0335         wl_resource_post_error(resource->handle, error_invalid_scale, "buffer scale must be at least one (%d specified)", scale);
0336         return;
0337     }
0338     pending.bufferScale = scale;
0339     pending.bufferScaleIsSet = true;
0340 }
0341 
0342 void SurfaceInterfacePrivate::surface_damage_buffer(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
0343 {
0344     pending.bufferDamage |= QRect(x, y, width, height);
0345 }
0346 
0347 void SurfaceInterfacePrivate::surface_offset(Resource *resource, int32_t x, int32_t y)
0348 {
0349     pending.offset = QPoint(x, y);
0350 }
0351 
0352 SurfaceInterface::SurfaceInterface(CompositorInterface *compositor, wl_resource *resource)
0353     : QObject(compositor)
0354     , d(new SurfaceInterfacePrivate(this))
0355 {
0356     d->compositor = compositor;
0357     d->init(resource);
0358     d->client = compositor->display()->getConnection(d->resource()->client());
0359 
0360     d->pendingScaleOverride = d->client->scaleOverride();
0361     d->scaleOverride = d->pendingScaleOverride;
0362     connect(d->client, &ClientConnection::scaleOverrideChanged, this, [this]() {
0363         d->pendingScaleOverride = d->client->scaleOverride();
0364     });
0365 }
0366 
0367 SurfaceInterface::~SurfaceInterface()
0368 {
0369 }
0370 
0371 uint32_t SurfaceInterface::id() const
0372 {
0373     return wl_resource_get_id(resource());
0374 }
0375 
0376 ClientConnection *SurfaceInterface::client() const
0377 {
0378     return d->client;
0379 }
0380 
0381 wl_resource *SurfaceInterface::resource() const
0382 {
0383     return d->resource()->handle;
0384 }
0385 
0386 CompositorInterface *SurfaceInterface::compositor() const
0387 {
0388     return d->compositor;
0389 }
0390 
0391 void SurfaceInterface::frameRendered(quint32 msec)
0392 {
0393     // notify all callbacks
0394     wl_resource *resource;
0395     wl_resource *tmp;
0396 
0397     wl_resource_for_each_safe (resource, tmp, &d->current.frameCallbacks) {
0398         wl_callback_send_done(resource, msec);
0399         wl_resource_destroy(resource);
0400     }
0401 
0402     for (SubSurfaceInterface *subsurface : std::as_const(d->current.below)) {
0403         subsurface->surface()->frameRendered(msec);
0404     }
0405     for (SubSurfaceInterface *subsurface : std::as_const(d->current.above)) {
0406         subsurface->surface()->frameRendered(msec);
0407     }
0408 }
0409 
0410 bool SurfaceInterface::hasFrameCallbacks() const
0411 {
0412     return !wl_list_empty(&d->current.frameCallbacks);
0413 }
0414 
0415 QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix()
0416 {
0417     // The order of transforms is reversed, i.e. the viewport transform is the first one.
0418 
0419     QMatrix4x4 surfaceToBufferMatrix;
0420 
0421     if (!current.buffer) {
0422         return surfaceToBufferMatrix;
0423     }
0424 
0425     surfaceToBufferMatrix.scale(current.bufferScale, current.bufferScale);
0426     surfaceToBufferMatrix.scale(scaleOverride, scaleOverride);
0427 
0428     switch (current.bufferTransform) {
0429     case KWin::Output::Transform::Normal:
0430     case KWin::Output::Transform::Flipped:
0431         break;
0432     case KWin::Output::Transform::Rotated90:
0433     case KWin::Output::Transform::Flipped90:
0434         surfaceToBufferMatrix.translate(0, bufferSize.height() / current.bufferScale);
0435         surfaceToBufferMatrix.rotate(-90, 0, 0, 1);
0436         break;
0437     case KWin::Output::Transform::Rotated180:
0438     case KWin::Output::Transform::Flipped180:
0439         surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, bufferSize.height() / current.bufferScale);
0440         surfaceToBufferMatrix.rotate(-180, 0, 0, 1);
0441         break;
0442     case KWin::Output::Transform::Rotated270:
0443     case KWin::Output::Transform::Flipped270:
0444         surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, 0);
0445         surfaceToBufferMatrix.rotate(-270, 0, 0, 1);
0446         break;
0447     }
0448 
0449     switch (current.bufferTransform) {
0450     case KWin::Output::Transform::Flipped:
0451     case KWin::Output::Transform::Flipped180:
0452         surfaceToBufferMatrix.translate(bufferSize.width() / current.bufferScale, 0);
0453         surfaceToBufferMatrix.scale(-1, 1);
0454         break;
0455     case KWin::Output::Transform::Flipped90:
0456     case KWin::Output::Transform::Flipped270:
0457         surfaceToBufferMatrix.translate(bufferSize.height() / current.bufferScale, 0);
0458         surfaceToBufferMatrix.scale(-1, 1);
0459         break;
0460     default:
0461         break;
0462     }
0463 
0464     if (current.viewport.sourceGeometry.isValid()) {
0465         surfaceToBufferMatrix.translate(current.viewport.sourceGeometry.x(), current.viewport.sourceGeometry.y());
0466     }
0467 
0468     QSizeF sourceSize;
0469     if (current.viewport.sourceGeometry.isValid()) {
0470         sourceSize = current.viewport.sourceGeometry.size();
0471     } else {
0472         sourceSize = implicitSurfaceSize;
0473     }
0474 
0475     if (sourceSize != surfaceSize) {
0476         surfaceToBufferMatrix.scale(sourceSize.width() / surfaceSize.width(), sourceSize.height() / surfaceSize.height());
0477     }
0478 
0479     return surfaceToBufferMatrix;
0480 }
0481 
0482 void SurfaceState::mergeInto(SurfaceState *target)
0483 {
0484     if (bufferIsSet) {
0485         target->buffer = buffer;
0486         target->offset = offset;
0487         target->damage = damage;
0488         target->bufferDamage = bufferDamage;
0489         target->bufferIsSet = bufferIsSet;
0490     }
0491     if (viewport.sourceGeometryIsSet) {
0492         target->viewport.sourceGeometry = viewport.sourceGeometry;
0493         target->viewport.sourceGeometryIsSet = true;
0494     }
0495     if (viewport.destinationSizeIsSet) {
0496         target->viewport.destinationSize = viewport.destinationSize;
0497         target->viewport.destinationSizeIsSet = true;
0498     }
0499     if (childrenChanged) {
0500         target->below = below;
0501         target->above = above;
0502         target->childrenChanged = true;
0503     }
0504     wl_list_insert_list(&target->frameCallbacks, &frameCallbacks);
0505 
0506     if (shadowIsSet) {
0507         target->shadow = shadow;
0508         target->shadowIsSet = true;
0509     }
0510     if (blurIsSet) {
0511         target->blur = blur;
0512         target->blurIsSet = true;
0513     }
0514     if (contrastIsSet) {
0515         target->contrast = contrast;
0516         target->contrastIsSet = true;
0517     }
0518     if (slideIsSet) {
0519         target->slide = slide;
0520         target->slideIsSet = true;
0521     }
0522     if (inputIsSet) {
0523         target->input = input;
0524         target->inputIsSet = true;
0525     }
0526     if (opaqueIsSet) {
0527         target->opaque = opaque;
0528         target->opaqueIsSet = true;
0529     }
0530     if (bufferScaleIsSet) {
0531         target->bufferScale = bufferScale;
0532         target->bufferScaleIsSet = true;
0533     }
0534     if (bufferTransformIsSet) {
0535         target->bufferTransform = bufferTransform;
0536         target->bufferTransformIsSet = true;
0537     }
0538     if (contentTypeIsSet) {
0539         target->contentType = contentType;
0540         target->contentTypeIsSet = true;
0541     }
0542     if (tearingIsSet) {
0543         target->presentationHint = presentationHint;
0544         target->tearingIsSet = true;
0545     }
0546 
0547     *this = SurfaceState{};
0548     below = target->below;
0549     above = target->above;
0550     wl_list_init(&frameCallbacks);
0551 }
0552 
0553 void SurfaceInterfacePrivate::applyState(SurfaceState *next)
0554 {
0555     const bool bufferChanged = next->bufferIsSet;
0556     const bool opaqueRegionChanged = next->opaqueIsSet;
0557     const bool scaleFactorChanged = next->bufferScaleIsSet && (current.bufferScale != next->bufferScale);
0558     const bool transformChanged = next->bufferTransformIsSet && (current.bufferTransform != next->bufferTransform);
0559     const bool shadowChanged = next->shadowIsSet;
0560     const bool blurChanged = next->blurIsSet;
0561     const bool contrastChanged = next->contrastIsSet;
0562     const bool slideChanged = next->slideIsSet;
0563     const bool childrenChanged = next->childrenChanged;
0564     const bool visibilityChanged = bufferChanged && bool(current.buffer) != bool(next->buffer);
0565 
0566     const QSizeF oldSurfaceSize = surfaceSize;
0567     const QSize oldBufferSize = bufferSize;
0568     const QMatrix4x4 oldSurfaceToBufferMatrix = surfaceToBufferMatrix;
0569     const QRegion oldInputRegion = inputRegion;
0570 
0571     next->mergeInto(&current);
0572     scaleOverride = pendingScaleOverride;
0573 
0574     if (lockedPointer) {
0575         auto lockedPointerPrivate = LockedPointerV1InterfacePrivate::get(lockedPointer);
0576         lockedPointerPrivate->commit();
0577     }
0578     if (confinedPointer) {
0579         auto confinedPointerPrivate = ConfinedPointerV1InterfacePrivate::get(confinedPointer);
0580         confinedPointerPrivate->commit();
0581     }
0582 
0583     if (bufferRef != current.buffer) {
0584         if (bufferRef) {
0585             bufferRef->unref();
0586         }
0587         bufferRef = current.buffer;
0588         if (bufferRef) {
0589             bufferRef->ref();
0590         }
0591     }
0592 
0593     // TODO: Refactor the state management code because it gets more clumsy.
0594     if (current.buffer) {
0595         bufferSize = current.buffer->size();
0596 
0597         implicitSurfaceSize = current.buffer->size() / current.bufferScale;
0598         switch (current.bufferTransform) {
0599         case KWin::Output::Transform::Rotated90:
0600         case KWin::Output::Transform::Rotated270:
0601         case KWin::Output::Transform::Flipped90:
0602         case KWin::Output::Transform::Flipped270:
0603             implicitSurfaceSize.transpose();
0604             break;
0605         case KWin::Output::Transform::Normal:
0606         case KWin::Output::Transform::Rotated180:
0607         case KWin::Output::Transform::Flipped:
0608         case KWin::Output::Transform::Flipped180:
0609             break;
0610         }
0611 
0612         if (current.viewport.destinationSize.isValid()) {
0613             surfaceSize = current.viewport.destinationSize;
0614         } else if (current.viewport.sourceGeometry.isValid()) {
0615             surfaceSize = current.viewport.sourceGeometry.size().toSize();
0616         } else {
0617             surfaceSize = implicitSurfaceSize;
0618         }
0619 
0620         const QRectF surfaceRect(QPoint(0, 0), surfaceSize);
0621         inputRegion = current.input & surfaceRect.toAlignedRect();
0622 
0623         if (!current.buffer->hasAlphaChannel()) {
0624             opaqueRegion = surfaceRect.toAlignedRect();
0625         } else {
0626             opaqueRegion = current.opaque & surfaceRect.toAlignedRect();
0627         }
0628 
0629         QMatrix4x4 scaleOverrideMatrix;
0630         if (scaleOverride != 1.) {
0631             scaleOverrideMatrix.scale(1. / scaleOverride, 1. / scaleOverride);
0632         }
0633 
0634         opaqueRegion = map_helper(scaleOverrideMatrix, opaqueRegion);
0635         inputRegion = map_helper(scaleOverrideMatrix, inputRegion);
0636         surfaceSize = surfaceSize / scaleOverride;
0637         implicitSurfaceSize = implicitSurfaceSize / scaleOverride;
0638     } else {
0639         surfaceSize = QSizeF(0, 0);
0640         implicitSurfaceSize = QSizeF(0, 0);
0641         bufferSize = QSize(0, 0);
0642         inputRegion = QRegion();
0643         opaqueRegion = QRegion();
0644     }
0645 
0646     surfaceToBufferMatrix = buildSurfaceToBufferMatrix();
0647     bufferToSurfaceMatrix = surfaceToBufferMatrix.inverted();
0648     if (opaqueRegionChanged) {
0649         Q_EMIT q->opaqueChanged(opaqueRegion);
0650     }
0651     if (oldInputRegion != inputRegion) {
0652         Q_EMIT q->inputChanged(inputRegion);
0653     }
0654     if (scaleFactorChanged) {
0655         Q_EMIT q->bufferScaleChanged(current.bufferScale);
0656     }
0657     if (transformChanged) {
0658         Q_EMIT q->bufferTransformChanged(current.bufferTransform);
0659     }
0660     if (visibilityChanged) {
0661         updateEffectiveMapped();
0662     }
0663     if (bufferChanged) {
0664         if (current.buffer && (!current.damage.isEmpty() || !current.bufferDamage.isEmpty())) {
0665             const QRegion windowRegion = QRegion(0, 0, q->size().width(), q->size().height());
0666             const QRegion bufferDamage = q->mapFromBuffer(current.bufferDamage);
0667             current.damage = windowRegion.intersected(current.damage.united(bufferDamage));
0668             Q_EMIT q->damaged(current.damage);
0669         }
0670     }
0671     if (surfaceToBufferMatrix != oldSurfaceToBufferMatrix) {
0672         Q_EMIT q->surfaceToBufferMatrixChanged();
0673     }
0674     if (bufferSize != oldBufferSize) {
0675         Q_EMIT q->bufferSizeChanged();
0676     }
0677     if (surfaceSize != oldSurfaceSize) {
0678         Q_EMIT q->sizeChanged();
0679     }
0680     if (shadowChanged) {
0681         Q_EMIT q->shadowChanged();
0682     }
0683     if (blurChanged) {
0684         Q_EMIT q->blurChanged();
0685     }
0686     if (contrastChanged) {
0687         Q_EMIT q->contrastChanged();
0688     }
0689     if (slideChanged) {
0690         Q_EMIT q->slideOnShowHideChanged();
0691     }
0692     if (childrenChanged) {
0693         Q_EMIT q->childSubSurfacesChanged();
0694     }
0695     // The position of a sub-surface is applied when its parent is committed.
0696     for (SubSurfaceInterface *subsurface : std::as_const(current.below)) {
0697         auto subsurfacePrivate = SubSurfaceInterfacePrivate::get(subsurface);
0698         subsurfacePrivate->parentCommit();
0699     }
0700     for (SubSurfaceInterface *subsurface : std::as_const(current.above)) {
0701         auto subsurfacePrivate = SubSurfaceInterfacePrivate::get(subsurface);
0702         subsurfacePrivate->parentCommit();
0703     }
0704     if (role) {
0705         role->commit();
0706     }
0707     Q_EMIT q->committed();
0708 }
0709 
0710 void SurfaceInterfacePrivate::commitSubSurface()
0711 {
0712     if (subSurface->isSynchronized()) {
0713         commitToCache();
0714     } else {
0715         if (hasCacheState) {
0716             commitToCache();
0717             commitFromCache();
0718         } else {
0719             applyState(&pending);
0720         }
0721     }
0722 }
0723 
0724 void SurfaceInterfacePrivate::commitToCache()
0725 {
0726     pending.mergeInto(&cached);
0727     hasCacheState = true;
0728 }
0729 
0730 void SurfaceInterfacePrivate::commitFromCache()
0731 {
0732     applyState(&cached);
0733     hasCacheState = false;
0734 }
0735 
0736 bool SurfaceInterfacePrivate::computeEffectiveMapped() const
0737 {
0738     if (!bufferRef) {
0739         return false;
0740     }
0741     if (subSurface) {
0742         return subSurface->parentSurface() && subSurface->parentSurface()->isMapped();
0743     }
0744     return true;
0745 }
0746 
0747 void SurfaceInterfacePrivate::updateEffectiveMapped()
0748 {
0749     const bool effectiveMapped = computeEffectiveMapped();
0750     if (mapped == effectiveMapped) {
0751         return;
0752     }
0753 
0754     mapped = effectiveMapped;
0755 
0756     if (mapped) {
0757         Q_EMIT q->mapped();
0758     } else {
0759         Q_EMIT q->unmapped();
0760     }
0761 
0762     for (SubSurfaceInterface *subsurface : std::as_const(current.below)) {
0763         auto surfacePrivate = SurfaceInterfacePrivate::get(subsurface->surface());
0764         surfacePrivate->updateEffectiveMapped();
0765     }
0766     for (SubSurfaceInterface *subsurface : std::as_const(current.above)) {
0767         auto surfacePrivate = SurfaceInterfacePrivate::get(subsurface->surface());
0768         surfacePrivate->updateEffectiveMapped();
0769     }
0770 }
0771 
0772 bool SurfaceInterfacePrivate::contains(const QPointF &position) const
0773 {
0774     // avoid QRectF::contains as that includes all edges
0775     const qreal x = position.x();
0776     const qreal y = position.y();
0777 
0778     return mapped && x >= 0 && y >= 0 && x < surfaceSize.width() && y < surfaceSize.height();
0779 }
0780 
0781 bool SurfaceInterfacePrivate::inputContains(const QPointF &position) const
0782 {
0783     return contains(position) && inputRegion.contains(QPoint(std::floor(position.x()), std::floor(position.y())));
0784 }
0785 
0786 QRegion SurfaceInterface::damage() const
0787 {
0788     return d->current.damage;
0789 }
0790 
0791 QRegion SurfaceInterface::opaque() const
0792 {
0793     return d->opaqueRegion;
0794 }
0795 
0796 QRegion SurfaceInterface::input() const
0797 {
0798     return d->inputRegion;
0799 }
0800 
0801 qint32 SurfaceInterface::bufferScale() const
0802 {
0803     return d->current.bufferScale;
0804 }
0805 
0806 KWin::Output::Transform SurfaceInterface::bufferTransform() const
0807 {
0808     return d->current.bufferTransform;
0809 }
0810 
0811 ClientBuffer *SurfaceInterface::buffer() const
0812 {
0813     return d->bufferRef;
0814 }
0815 
0816 QPoint SurfaceInterface::offset() const
0817 {
0818     return d->current.offset / d->scaleOverride;
0819 }
0820 
0821 SurfaceInterface *SurfaceInterface::get(wl_resource *native)
0822 {
0823     if (auto surfacePrivate = resource_cast<SurfaceInterfacePrivate *>(native)) {
0824         return surfacePrivate->q;
0825     }
0826     return nullptr;
0827 }
0828 
0829 SurfaceInterface *SurfaceInterface::get(quint32 id, const ClientConnection *client)
0830 {
0831     if (client) {
0832         return get(client->getResource(id));
0833     }
0834     return nullptr;
0835 }
0836 
0837 QList<SubSurfaceInterface *> SurfaceInterface::below() const
0838 {
0839     return d->current.below;
0840 }
0841 
0842 QList<SubSurfaceInterface *> SurfaceInterface::above() const
0843 {
0844     return d->current.above;
0845 }
0846 
0847 SubSurfaceInterface *SurfaceInterface::subSurface() const
0848 {
0849     return d->subSurface;
0850 }
0851 
0852 QSizeF SurfaceInterface::size() const
0853 {
0854     return d->surfaceSize;
0855 }
0856 
0857 QRectF SurfaceInterface::boundingRect() const
0858 {
0859     QRectF rect(QPoint(0, 0), size());
0860 
0861     for (const SubSurfaceInterface *subSurface : std::as_const(d->current.below)) {
0862         const SurfaceInterface *childSurface = subSurface->surface();
0863         rect |= childSurface->boundingRect().translated(subSurface->position());
0864     }
0865     for (const SubSurfaceInterface *subSurface : std::as_const(d->current.above)) {
0866         const SurfaceInterface *childSurface = subSurface->surface();
0867         rect |= childSurface->boundingRect().translated(subSurface->position());
0868     }
0869 
0870     return rect;
0871 }
0872 
0873 QPointer<ShadowInterface> SurfaceInterface::shadow() const
0874 {
0875     return d->current.shadow;
0876 }
0877 
0878 QPointer<BlurInterface> SurfaceInterface::blur() const
0879 {
0880     return d->current.blur;
0881 }
0882 
0883 QPointer<ContrastInterface> SurfaceInterface::contrast() const
0884 {
0885     return d->current.contrast;
0886 }
0887 
0888 QPointer<SlideInterface> SurfaceInterface::slideOnShowHide() const
0889 {
0890     return d->current.slide;
0891 }
0892 
0893 bool SurfaceInterface::isMapped() const
0894 {
0895     return d->mapped;
0896 }
0897 
0898 QVector<OutputInterface *> SurfaceInterface::outputs() const
0899 {
0900     return d->outputs;
0901 }
0902 
0903 void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
0904 {
0905     QVector<OutputInterface *> removedOutputs = d->outputs;
0906     for (auto it = outputs.constBegin(), end = outputs.constEnd(); it != end; ++it) {
0907         const auto o = *it;
0908         removedOutputs.removeOne(o);
0909     }
0910     for (auto it = removedOutputs.constBegin(), end = removedOutputs.constEnd(); it != end; ++it) {
0911         const auto resources = (*it)->clientResources(client());
0912         for (wl_resource *outputResource : resources) {
0913             d->send_leave(outputResource);
0914         }
0915         disconnect(d->outputDestroyedConnections.take(*it));
0916         disconnect(d->outputBoundConnections.take(*it));
0917     }
0918     QVector<OutputInterface *> addedOutputsOutputs = outputs;
0919     for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) {
0920         const auto o = *it;
0921         addedOutputsOutputs.removeOne(o);
0922     }
0923     for (auto it = addedOutputsOutputs.constBegin(), end = addedOutputsOutputs.constEnd(); it != end; ++it) {
0924         const auto o = *it;
0925         const auto resources = o->clientResources(client());
0926         for (wl_resource *outputResource : resources) {
0927             d->send_enter(outputResource);
0928         }
0929         d->outputDestroyedConnections[o] = connect(o, &OutputInterface::removed, this, [this, o] {
0930             auto outputs = d->outputs;
0931             if (outputs.removeOne(o)) {
0932                 setOutputs(outputs);
0933             }
0934         });
0935 
0936         Q_ASSERT(!d->outputBoundConnections.contains(o));
0937         d->outputBoundConnections[o] = connect(o, &OutputInterface::bound, this, [this](ClientConnection *c, wl_resource *outputResource) {
0938             if (c != client()) {
0939                 return;
0940             }
0941             d->send_enter(outputResource);
0942         });
0943     }
0944 
0945     d->outputs = outputs;
0946     for (auto child : std::as_const(d->current.below)) {
0947         child->surface()->setOutputs(outputs);
0948     }
0949     for (auto child : std::as_const(d->current.above)) {
0950         child->surface()->setOutputs(outputs);
0951     }
0952 }
0953 
0954 SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position)
0955 {
0956     if (!isMapped()) {
0957         return nullptr;
0958     }
0959 
0960     for (auto it = d->current.above.crbegin(); it != d->current.above.crend(); ++it) {
0961         const SubSurfaceInterface *current = *it;
0962         SurfaceInterface *surface = current->surface();
0963         if (auto s = surface->surfaceAt(position - current->position())) {
0964             return s;
0965         }
0966     }
0967 
0968     // check whether the geometry contains the pos
0969     if (d->contains(position)) {
0970         return this;
0971     }
0972 
0973     for (auto it = d->current.below.crbegin(); it != d->current.below.crend(); ++it) {
0974         const SubSurfaceInterface *current = *it;
0975         SurfaceInterface *surface = current->surface();
0976         if (auto s = surface->surfaceAt(position - current->position())) {
0977             return s;
0978         }
0979     }
0980     return nullptr;
0981 }
0982 
0983 SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
0984 {
0985     // TODO: Most of this is very similar to SurfaceInterface::surfaceAt
0986     //       Is there a way to reduce the code duplication?
0987     if (!isMapped()) {
0988         return nullptr;
0989     }
0990 
0991     for (auto it = d->current.above.crbegin(); it != d->current.above.crend(); ++it) {
0992         const SubSurfaceInterface *current = *it;
0993         auto surface = current->surface();
0994         if (auto s = surface->inputSurfaceAt(position - current->position())) {
0995             return s;
0996         }
0997     }
0998 
0999     // check whether the geometry and input region contain the pos
1000     if (d->inputContains(position)) {
1001         return this;
1002     }
1003 
1004     for (auto it = d->current.below.crbegin(); it != d->current.below.crend(); ++it) {
1005         const SubSurfaceInterface *current = *it;
1006         auto surface = current->surface();
1007         if (auto s = surface->inputSurfaceAt(position - current->position())) {
1008             return s;
1009         }
1010     }
1011 
1012     return nullptr;
1013 }
1014 
1015 LockedPointerV1Interface *SurfaceInterface::lockedPointer() const
1016 {
1017     return d->lockedPointer;
1018 }
1019 
1020 ConfinedPointerV1Interface *SurfaceInterface::confinedPointer() const
1021 {
1022     return d->confinedPointer;
1023 }
1024 
1025 bool SurfaceInterface::inhibitsIdle() const
1026 {
1027     return !d->idleInhibitors.isEmpty();
1028 }
1029 
1030 LinuxDmaBufV1Feedback *SurfaceInterface::dmabufFeedbackV1() const
1031 {
1032     return d->dmabufFeedbackV1.get();
1033 }
1034 
1035 KWin::ContentType SurfaceInterface::contentType() const
1036 {
1037     return d->current.contentType;
1038 }
1039 
1040 QPointF SurfaceInterface::mapToBuffer(const QPointF &point) const
1041 {
1042     return d->surfaceToBufferMatrix.map(point);
1043 }
1044 
1045 QPointF SurfaceInterface::mapFromBuffer(const QPointF &point) const
1046 {
1047     return d->bufferToSurfaceMatrix.map(point);
1048 }
1049 
1050 QRegion SurfaceInterface::mapToBuffer(const QRegion &region) const
1051 {
1052     return map_helper(d->surfaceToBufferMatrix, region);
1053 }
1054 
1055 QRegion SurfaceInterface::mapFromBuffer(const QRegion &region) const
1056 {
1057     return map_helper(d->bufferToSurfaceMatrix, region);
1058 }
1059 
1060 QMatrix4x4 SurfaceInterface::surfaceToBufferMatrix() const
1061 {
1062     return d->surfaceToBufferMatrix;
1063 }
1064 
1065 QPointF SurfaceInterface::mapToChild(SurfaceInterface *child, const QPointF &point) const
1066 {
1067     QPointF local = point;
1068     SurfaceInterface *surface = child;
1069 
1070     while (true) {
1071         if (surface == this) {
1072             return local;
1073         }
1074 
1075         SubSurfaceInterface *subsurface = surface->subSurface();
1076         if (Q_UNLIKELY(!subsurface)) {
1077             return QPointF();
1078         }
1079 
1080         local -= subsurface->position();
1081         surface = subsurface->parentSurface();
1082     }
1083 
1084     return QPointF();
1085 }
1086 
1087 QSize SurfaceInterface::bufferSize() const
1088 {
1089     return d->bufferSize;
1090 }
1091 
1092 qreal SurfaceInterface::scaleOverride() const
1093 {
1094     return d->scaleOverride;
1095 }
1096 
1097 QPoint SurfaceInterface::toSurfaceLocal(const QPoint &point) const
1098 {
1099     return QPoint(point.x() * d->scaleOverride, point.y() * d->scaleOverride);
1100 }
1101 
1102 QPointF SurfaceInterface::toSurfaceLocal(const QPointF &point) const
1103 {
1104     return QPointF(point.x() * d->scaleOverride, point.y() * d->scaleOverride);
1105 }
1106 
1107 PresentationHint SurfaceInterface::presentationHint() const
1108 {
1109     return d->current.presentationHint;
1110 }
1111 
1112 void SurfaceInterface::setPreferredScale(qreal scale)
1113 {
1114     if (scale == d->preferredScale) {
1115         return;
1116     }
1117     d->preferredScale = scale;
1118 
1119     if (d->fractionalScaleExtension) {
1120         d->fractionalScaleExtension->setPreferredScale(scale);
1121     }
1122     for (auto child : qAsConst(d->current.below)) {
1123         child->surface()->setPreferredScale(scale);
1124     }
1125     for (auto child : qAsConst(d->current.above)) {
1126         child->surface()->setPreferredScale(scale);
1127     }
1128 }
1129 
1130 } // namespace KWaylandServer