File indexing completed on 2024-11-10 04:57:34
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 ®ion) 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 ®ion) 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"