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 ®ion) 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(¤t.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, ¤t.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(¤t); 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 ®ion) const 1051 { 1052 return map_helper(d->surfaceToBufferMatrix, region); 1053 } 1054 1055 QRegion SurfaceInterface::mapFromBuffer(const QRegion ®ion) 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