6 #include "surface_interface.h"
7 #include "buffer_interface.h"
8 #include "clientconnection.h"
9 #include "compositor_interface.h"
10 #include "idleinhibit_interface_p.h"
11 #include "pointerconstraints_interface_p.h"
12 #include "region_interface.h"
13 #include "subcompositor_interface.h"
14 #include "subsurface_interface_p.h"
15 #include "surface_interface_p.h"
16 #include "surfacerole_p.h"
18 #include <QListIterator>
20 #include <wayland-server.h>
28 SurfaceInterface::Private::Private(SurfaceInterface *q, CompositorInterface *c, wl_resource *parentResource)
29 :
Resource::Private(q, c, parentResource, &wl_surface_interface, &s_interface)
33 SurfaceInterface::Private::~Private()
41 pending.children.append(child);
42 subSurfacePending.children.append(child);
43 current.children.append(child);
44 Q_Q(SurfaceInterface);
45 Q_EMIT q->childSubSurfaceAdded(child);
46 Q_EMIT q->subSurfaceTreeChanged();
47 QObject::connect(child.
data(), &SubSurfaceInterface::positionChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
48 QObject::connect(child->surface().
data(), &SurfaceInterface::damaged, q, &SurfaceInterface::subSurfaceTreeChanged);
49 QObject::connect(child->surface().
data(), &SurfaceInterface::unmapped, q, &SurfaceInterface::subSurfaceTreeChanged);
50 QObject::connect(child->surface().
data(), &SurfaceInterface::subSurfaceTreeChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
56 pending.children.removeAll(child);
57 subSurfacePending.children.removeAll(child);
58 current.children.removeAll(child);
59 Q_Q(SurfaceInterface);
60 Q_EMIT q->childSubSurfaceRemoved(child);
61 Q_EMIT q->subSurfaceTreeChanged();
62 QObject::disconnect(child.
data(), &SubSurfaceInterface::positionChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
63 if (!child->surface().
isNull()) {
64 QObject::disconnect(child->surface().
data(), &SurfaceInterface::damaged, q, &SurfaceInterface::subSurfaceTreeChanged);
65 QObject::disconnect(child->surface().
data(), &SurfaceInterface::unmapped, q, &SurfaceInterface::subSurfaceTreeChanged);
66 QObject::disconnect(child->surface().
data(), &SurfaceInterface::subSurfaceTreeChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
72 Q_Q(SurfaceInterface);
73 auto it = std::find(pending.children.begin(), pending.children.end(), subsurface);
74 if (it == pending.children.end()) {
77 if (pending.children.count() == 1) {
83 pending.children.append(*it);
84 pending.children.erase(it);
85 pending.childrenChanged =
true;
88 if (!sibling->subSurface()) {
92 auto siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
93 if (siblingIt == pending.children.end() || siblingIt == it) {
98 pending.children.erase(it);
100 siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
101 pending.children.insert(++siblingIt, value);
102 pending.childrenChanged =
true;
108 Q_Q(SurfaceInterface);
109 auto it = std::find(pending.children.begin(), pending.children.end(), subsurface);
110 if (it == pending.children.end()) {
113 if (pending.children.count() == 1) {
120 pending.children.erase(it);
121 pending.children.prepend(value);
122 pending.childrenChanged =
true;
125 if (!sibling->subSurface()) {
129 auto siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
130 if (siblingIt == pending.children.end() || siblingIt == it) {
135 pending.children.erase(it);
137 siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
138 pending.children.insert(siblingIt, value);
139 pending.childrenChanged =
true;
145 pending.shadow = shadow;
146 pending.shadowIsSet =
true;
152 pending.blurIsSet =
true;
157 pending.slide = slide;
158 pending.slideIsSet =
true;
163 pending.contrast = contrast;
164 pending.contrastIsSet =
true;
167 void SurfaceInterface::Private::installPointerConstraint(LockedPointerInterface *lock)
169 Q_ASSERT(lockedPointer.isNull());
170 Q_ASSERT(confinedPointer.isNull());
173 auto cleanUp = [
this]() {
174 lockedPointer.clear();
175 disconnect(constrainsOneShotConnection);
177 disconnect(constrainsUnboundConnection);
179 Q_EMIT q_func()->pointerConstraintsChanged();
182 if (lock->lifeTime() == LockedPointerInterface::LifeTime::OneShot) {
183 constrainsOneShotConnection =
QObject::connect(lock, &LockedPointerInterface::lockedChanged, q_func(), [
this, cleanUp] {
184 if (lockedPointer.isNull() || lockedPointer->isLocked()) {
190 constrainsUnboundConnection =
QObject::connect(lock, &LockedPointerInterface::unbound, q_func(), [
this, cleanUp] {
191 if (lockedPointer.isNull()) {
196 Q_EMIT q_func()->pointerConstraintsChanged();
199 void SurfaceInterface::Private::installPointerConstraint(ConfinedPointerInterface *confinement)
201 Q_ASSERT(lockedPointer.isNull());
202 Q_ASSERT(confinedPointer.isNull());
205 auto cleanUp = [
this]() {
206 confinedPointer.clear();
207 disconnect(constrainsOneShotConnection);
209 disconnect(constrainsUnboundConnection);
211 Q_EMIT q_func()->pointerConstraintsChanged();
214 if (confinement->lifeTime() == ConfinedPointerInterface::LifeTime::OneShot) {
215 constrainsOneShotConnection =
QObject::connect(confinement, &ConfinedPointerInterface::confinedChanged, q_func(), [
this, cleanUp] {
216 if (confinedPointer.isNull() || confinedPointer->isConfined()) {
222 constrainsUnboundConnection =
QObject::connect(confinement, &ConfinedPointerInterface::unbound, q_func(), [
this, cleanUp] {
223 if (confinedPointer.isNull()) {
228 Q_EMIT q_func()->pointerConstraintsChanged();
231 void SurfaceInterface::Private::installIdleInhibitor(IdleInhibitorInterface *inhibitor)
233 idleInhibitors << inhibitor;
234 QObject::connect(inhibitor, &IdleInhibitorInterface::aboutToBeUnbound, q, [
this, inhibitor] {
235 idleInhibitors.removeOne(inhibitor);
236 if (idleInhibitors.isEmpty()) {
237 Q_EMIT q_func()->inhibitsIdleChanged();
240 if (idleInhibitors.count() == 1) {
241 Q_EMIT q_func()->inhibitsIdleChanged();
246 const struct wl_surface_interface SurfaceInterface::Private::s_interface = {resourceDestroyedCallback,
250 opaqueRegionCallback,
253 bufferTransformCallback,
255 damageBufferCallback};
258 SurfaceInterface::SurfaceInterface(CompositorInterface *parent, wl_resource *parentResource)
259 :
Resource(new Private(this, parent, parentResource))
263 SurfaceInterface::~SurfaceInterface() =
default;
265 void SurfaceInterface::frameRendered(quint32 msec)
269 const bool needsFlush = !d->current.callbacks.isEmpty();
270 while (!d->current.callbacks.isEmpty()) {
271 wl_resource *r = d->current.callbacks.takeFirst();
272 wl_callback_send_done(r, msec);
273 wl_resource_destroy(r);
275 for (
auto it = d->current.children.constBegin(); it != d->current.children.constEnd(); ++it) {
276 const auto &subSurface = *it;
277 if (subSurface.isNull() || subSurface->d_func()->surface.isNull()) {
280 subSurface->d_func()->surface->frameRendered(msec);
287 void SurfaceInterface::Private::destroy()
293 callbacksToDestroy << current.callbacks;
294 current.callbacks.
clear();
295 callbacksToDestroy << pending.callbacks;
296 pending.callbacks.
clear();
297 callbacksToDestroy << subSurfacePending.callbacks;
298 subSurfacePending.callbacks.
clear();
299 for (
auto it = callbacksToDestroy.
constBegin(), end = callbacksToDestroy.
constEnd(); it != end; it++) {
300 wl_resource_destroy(*it);
302 if (current.buffer) {
303 current.buffer->unref();
307 void SurfaceInterface::Private::swapStates(
State *source,
State *target,
bool emitChanged)
309 Q_Q(SurfaceInterface);
310 bool bufferChanged = source->bufferIsSet;
311 const bool opaqueRegionChanged = source->opaqueIsSet;
312 const bool inputRegionChanged = source->inputIsSet;
313 const bool scaleFactorChanged = source->scaleIsSet && (target->scale != source->scale);
314 const bool transformChanged = source->transformIsSet && (target->transform != source->transform);
315 const bool shadowChanged = source->shadowIsSet;
316 const bool blurChanged = source->blurIsSet;
317 const bool contrastChanged = source->contrastIsSet;
318 const bool slideChanged = source->slideIsSet;
319 const bool childrenChanged = source->childrenChanged;
320 bool sizeChanged =
false;
321 auto buffer = target->buffer;
325 if (target->buffer) {
326 oldSize = target->buffer->size();
328 target->buffer->unref();
329 QObject::disconnect(target->buffer, &BufferInterface::sizeChanged, q, &SurfaceInterface::sizeChanged);
331 delete target->buffer;
332 target->buffer =
nullptr;
335 if (source->buffer) {
337 source->buffer->ref();
338 QObject::connect(source->buffer, &BufferInterface::sizeChanged, q, &SurfaceInterface::sizeChanged);
340 const QSize newSize = source->buffer->size();
341 sizeChanged = newSize.
isValid() && newSize != oldSize;
343 if (!target->buffer && !source->buffer && emitChanged) {
345 bufferChanged =
false;
347 buffer = source->buffer;
351 target->buffer = buffer;
352 target->offset = source->offset;
353 target->damage = source->damage;
354 target->bufferDamage = source->bufferDamage;
355 target->bufferIsSet = source->bufferIsSet;
357 if (childrenChanged) {
358 target->childrenChanged = source->childrenChanged;
359 target->children = source->children;
361 target->callbacks.append(source->callbacks);
364 target->shadow = source->shadow;
365 target->shadowIsSet =
true;
368 target->blur = source->blur;
369 target->blurIsSet =
true;
371 if (contrastChanged) {
372 target->contrast = source->contrast;
373 target->contrastIsSet =
true;
376 target->slide = source->slide;
377 target->slideIsSet =
true;
379 if (inputRegionChanged) {
380 target->input = source->input;
381 target->inputIsInfinite = source->inputIsInfinite;
382 target->inputIsSet =
true;
384 if (opaqueRegionChanged) {
385 target->opaque = source->opaque;
386 target->opaqueIsSet =
true;
388 if (scaleFactorChanged) {
389 target->scale = source->scale;
390 target->scaleIsSet =
true;
392 if (transformChanged) {
393 target->transform = source->transform;
394 target->transformIsSet =
true;
396 if (!lockedPointer.isNull()) {
397 lockedPointer->d_func()->commit();
399 if (!confinedPointer.isNull()) {
400 confinedPointer->d_func()->commit();
404 source->children = target->children;
405 if (opaqueRegionChanged) {
406 Q_EMIT q->opaqueChanged(target->opaque);
408 if (inputRegionChanged) {
409 Q_EMIT q->inputChanged(target->input);
411 if (scaleFactorChanged) {
412 Q_EMIT q->scaleChanged(target->scale);
413 if (buffer && !sizeChanged) {
414 Q_EMIT q->sizeChanged();
417 if (transformChanged) {
418 Q_EMIT q->transformChanged(target->transform);
420 if (bufferChanged && emitChanged) {
421 if (target->buffer && (!target->damage.isEmpty() || !target->bufferDamage.isEmpty())) {
422 const QRegion windowRegion =
QRegion(0, 0, q->size().width(), q->size().height());
425 if (!target->bufferDamage.isEmpty()) {
426 typedef OutputInterface::Transform Tr;
427 const Tr tr = target->transform;
428 const qint32 sc = target->scale;
429 if (tr == Tr::Rotated90 || tr == Tr::Rotated270 || tr == Tr::Flipped90 || tr == Tr::Flipped270) {
431 for (
const auto &rect : target->bufferDamage) {
432 const auto add =
QRegion(rect.x() / sc, rect.y() / sc, rect.height() / sc, rect.width() / sc);
433 bufferDamage = bufferDamage.
united(add);
435 }
else if (sc != 1) {
437 for (
const auto &rect : target->bufferDamage) {
438 const auto add =
QRegion(rect.x() / sc, rect.y() / sc, rect.width() / sc, rect.height() / sc);
439 bufferDamage = bufferDamage.
united(add);
442 bufferDamage = target->bufferDamage;
445 target->damage = windowRegion.
intersected(target->damage.united(bufferDamage));
447 subSurfaceIsMapped =
true;
448 trackedDamage = trackedDamage.
united(target->damage);
449 Q_EMIT q->damaged(target->damage);
453 const auto mainSurface = subSurface->mainSurface();
454 if (!mainSurface || !mainSurface->buffer()) {
460 }
else if (!target->buffer && emitChanged) {
461 subSurfaceIsMapped =
false;
462 Q_EMIT q->unmapped();
469 Q_EMIT q->sizeChanged();
472 Q_EMIT q->shadowChanged();
475 Q_EMIT q->blurChanged();
477 if (contrastChanged) {
478 Q_EMIT q->contrastChanged();
481 Q_EMIT q->slideOnShowHideChanged();
483 if (childrenChanged) {
484 Q_EMIT q->subSurfaceTreeChanged();
488 void SurfaceInterface::Private::commit()
490 Q_Q(SurfaceInterface);
491 if (!subSurface.isNull() && subSurface->isSynchronized()) {
492 swapStates(&pending, &subSurfacePending,
false);
494 swapStates(&pending, ¤t,
true);
495 if (!subSurface.isNull()) {
496 subSurface->d_func()->commit();
500 for (
auto it = current.children.constBegin(); it != current.children.constEnd(); ++it) {
501 const auto &subSurface = *it;
502 if (subSurface.isNull()) {
505 subSurface->d_func()->commit();
511 Q_EMIT q->committed();
514 void SurfaceInterface::Private::commitSubSurface()
516 if (subSurface.isNull() || !subSurface->isSynchronized()) {
519 swapStates(&subSurfacePending, ¤t,
true);
521 for (
auto it = current.children.constBegin(); it != current.children.constEnd(); ++it) {
522 const auto &subSurface = *it;
523 if (subSurface.isNull() || !subSurface->isSynchronized()) {
526 subSurface->d_func()->commit();
530 void SurfaceInterface::Private::damage(
const QRect &rect)
532 pending.damage = pending.damage.united(rect);
535 void SurfaceInterface::Private::damageBuffer(
const QRect &rect)
537 pending.bufferDamage = pending.bufferDamage.united(rect);
540 void SurfaceInterface::Private::setScale(qint32 scale)
542 pending.scale = scale;
543 pending.scaleIsSet =
true;
546 void SurfaceInterface::Private::setTransform(OutputInterface::Transform transform)
551 void SurfaceInterface::Private::addFrameCallback(uint32_t callback)
553 wl_resource *r = client->createResource(&wl_callback_interface, 1, callback);
555 wl_resource_post_no_memory(resource);
558 wl_resource_set_implementation(r,
nullptr,
this, destroyFrameCallback);
559 pending.callbacks << r;
562 void SurfaceInterface::Private::attachBuffer(wl_resource *buffer,
const QPoint &offset)
564 pending.bufferIsSet =
true;
565 pending.offset = offset;
566 if (pending.buffer) {
567 delete pending.buffer;
571 pending.buffer =
nullptr;
573 pending.bufferDamage =
QRegion();
576 Q_Q(SurfaceInterface);
577 pending.buffer =
new BufferInterface(buffer, q);
578 QObject::connect(pending.buffer, &BufferInterface::aboutToBeDestroyed, q, [
this](BufferInterface *buffer) {
579 if (pending.buffer == buffer) {
580 pending.buffer = nullptr;
582 if (subSurfacePending.buffer == buffer) {
583 subSurfacePending.buffer = nullptr;
585 if (current.buffer == buffer) {
586 current.buffer->unref();
587 current.buffer = nullptr;
592 void SurfaceInterface::Private::destroyFrameCallback(wl_resource *r)
594 auto s = cast<Private>(r);
595 s->current.callbacks.removeAll(r);
596 s->pending.callbacks.removeAll(r);
597 s->subSurfacePending.callbacks.removeAll(r);
600 void SurfaceInterface::Private::attachCallback(wl_client *client, wl_resource *resource, wl_resource *buffer, int32_t sx, int32_t sy)
603 cast<Private>(resource)->attachBuffer(buffer,
QPoint(sx, sy));
606 void SurfaceInterface::Private::damageCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
609 cast<Private>(resource)->damage(
QRect(x, y, width, height));
612 void SurfaceInterface::Private::damageBufferCallback(wl_client *client, wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
615 cast<Private>(resource)->damageBuffer(
QRect(x, y, width, height));
618 void SurfaceInterface::Private::frameCallback(wl_client *client, wl_resource *resource, uint32_t callback)
620 auto s = cast<Private>(resource);
621 Q_ASSERT(client == *s->client);
622 s->addFrameCallback(callback);
625 void SurfaceInterface::Private::opaqueRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region)
627 auto s = cast<Private>(resource);
628 Q_ASSERT(client == *s->client);
630 s->setOpaque(r ? r->region() :
QRegion());
633 void SurfaceInterface::Private::setOpaque(
const QRegion ®ion)
635 pending.opaqueIsSet =
true;
636 pending.opaque = region;
639 void SurfaceInterface::Private::inputRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region)
641 auto s = cast<Private>(resource);
642 Q_ASSERT(client == *s->client);
644 s->setInput(r ? r->region() :
QRegion(), !r);
647 void SurfaceInterface::Private::setInput(
const QRegion ®ion,
bool isInfinite)
649 pending.inputIsSet =
true;
650 pending.inputIsInfinite = isInfinite;
651 pending.input = region;
654 void SurfaceInterface::Private::commitCallback(wl_client *client, wl_resource *resource)
657 cast<Private>(resource)->commit();
660 void SurfaceInterface::Private::bufferTransformCallback(wl_client *client, wl_resource *resource, int32_t transform)
663 cast<Private>(resource)->setTransform(OutputInterface::Transform(transform));
666 void SurfaceInterface::Private::bufferScaleCallback(wl_client *client, wl_resource *resource, int32_t scale)
669 cast<Private>(resource)->setScale(scale);
672 QRegion SurfaceInterface::damage()
const
675 return d->current.damage;
678 QRegion SurfaceInterface::opaque()
const
681 return d->current.opaque;
684 QRegion SurfaceInterface::input()
const
687 return d->current.input;
690 bool SurfaceInterface::inputIsInfitine()
const
692 return inputIsInfinite();
695 bool SurfaceInterface::inputIsInfinite()
const
698 return d->current.inputIsInfinite;
701 qint32 SurfaceInterface::scale()
const
704 return d->current.scale;
707 OutputInterface::Transform SurfaceInterface::transform()
const
710 return d->current.transform;
716 return d->current.buffer;
719 QPoint SurfaceInterface::offset()
const
722 return d->current.offset;
727 return Private::get<SurfaceInterface>(native);
732 return Private::get<SurfaceInterface>(
id, client);
738 return d->current.children;
744 return d->subSurface;
747 QSize SurfaceInterface::size()
const
751 if (d->current.buffer) {
752 return d->current.buffer->size() / scale();
757 QRect SurfaceInterface::boundingRect()
const
773 return d->current.shadow;
779 return d->current.blur;
785 return d->current.contrast;
791 return d->current.slide;
794 bool SurfaceInterface::isMapped()
const
800 return d->subSurfaceIsMapped && !d->subSurface->parentSurface().isNull() && d->subSurface->parentSurface()->isMapped();
802 return d->current.buffer !=
nullptr;
805 QRegion SurfaceInterface::trackedDamage()
const
808 return d->trackedDamage;
811 void SurfaceInterface::resetTrackedDamage()
831 for (
auto it = removedOutputs.
constBegin(), end = removedOutputs.
constEnd(); it != end; ++it) {
832 const auto resources = (*it)->clientResources(client());
833 for (wl_resource *r : resources) {
834 wl_surface_send_leave(d->resource, r);
836 disconnect(d->outputDestroyedConnections.take(*it));
839 for (
auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) {
843 for (
auto it = addedOutputsOutputs.
constBegin(), end = addedOutputsOutputs.
constEnd(); it != end; ++it) {
845 const auto resources = o->clientResources(client());
846 for (wl_resource *r : resources) {
847 wl_surface_send_enter(d->resource, r);
849 d->outputDestroyedConnections[o] = connect(o, &Global::aboutToDestroyGlobal,
this, [
this, o] {
851 auto outputs = d->outputs;
859 d->outputs = outputs;
872 const auto ¤t = it.
previous();
873 auto surface = current->surface();
874 if (surface.isNull()) {
877 if (
auto s = surface->surfaceAt(position - current->position())) {
882 if (!size().isEmpty() &&
QRectF(
QPoint(0, 0), size()).contains(position)) {
900 const auto ¤t = it.
previous();
901 auto surface = current->surface();
902 if (surface.isNull()) {
905 if (
auto s = surface->inputSurfaceAt(position - current->position())) {
910 if (!size().isEmpty() &&
QRectF(
QPoint(0, 0), size()).contains(position) && (inputIsInfinite() || input().contains(position.
toPoint()))) {
919 return d->lockedPointer;
925 return d->confinedPointer;
928 bool SurfaceInterface::inhibitsIdle()
const
931 return !d->idleInhibitors.isEmpty();
937 d->dataProxy = surface;
946 SurfaceInterface::Private *SurfaceInterface::d_func()
const
948 return reinterpret_cast<Private *
>(d.data());