File indexing completed on 2024-05-19 05:32:44

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