surface_interface.cpp 31.9 KB
Newer Older
1
2
/*
    SPDX-FileCopyrightText: 2014 Martin Gräßlin <mgraesslin@kde.org>
3
    SPDX-FileCopyrightText: 2020 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4

5
6
    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
7
#include "surface_interface.h"
8
#include "surface_interface_p.h"
9
#include "buffer_interface.h"
10
#include "clientconnection.h"
11
#include "compositor_interface.h"
12
#include "display.h"
13
#include "idleinhibit_interface_p.h"
14
#include "pointerconstraints_interface_p.h"
15
#include "region_interface.h"
16
17
#include "subcompositor_interface.h"
#include "subsurface_interface_p.h"
18
#include "surfacerole_p.h"
19
20
// std
#include <algorithm>
21

22
namespace KWaylandServer
23
24
{

25
26
27
28
29
30
31
32
33
QList<SurfaceInterface *> SurfaceInterfacePrivate::surfaces;

KWaylandFrameCallback::KWaylandFrameCallback(wl_resource *resource, SurfaceInterface *surface)
    : QtWaylandServer::wl_callback(resource)
    , surface(surface)
{
}

void KWaylandFrameCallback::destroy()
34
{
35
    wl_resource_destroy(resource()->handle);
36
37
}

38
void KWaylandFrameCallback::callback_destroy_resource(Resource *)
39
{
40
41
42
43
    if (surface) {
        SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(surface);
        surfacePrivate->current.frameCallbacks.removeOne(this);
        surfacePrivate->pending.frameCallbacks.removeOne(this);
44
        surfacePrivate->cached.frameCallbacks.removeOne(this);
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
    }
    delete this;
}

SurfaceInterfacePrivate::SurfaceInterfacePrivate(SurfaceInterface *q)
    : q(q)
{
    surfaces.append(q);
}

SurfaceInterfacePrivate::~SurfaceInterfacePrivate()
{
    for (KWaylandFrameCallback *frameCallback : current.frameCallbacks) {
        frameCallback->destroy();
    }
    for (KWaylandFrameCallback *frameCallback : pending.frameCallbacks) {
        frameCallback->destroy();
    }
63
    for (KWaylandFrameCallback *frameCallback : cached.frameCallbacks) {
64
65
66
67
68
69
        frameCallback->destroy();
    }
    if (current.buffer) {
        current.buffer->unref();
    }
    surfaces.removeOne(q);
70
71
}

72
void SurfaceInterfacePrivate::addChild(QPointer<SubSurfaceInterface> child)
73
{
74
75
    // protocol is not precise on how to handle the addition of new sub surfaces
    pending.children.append(child);
76
    cached.children.append(child);
77
    current.children.append(child);
78
    emit q->childSubSurfaceAdded(child);
79
80
81
82
83
    emit q->subSurfaceTreeChanged();
    QObject::connect(child.data(), &SubSurfaceInterface::positionChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
    QObject::connect(child->surface().data(), &SurfaceInterface::damaged, q, &SurfaceInterface::subSurfaceTreeChanged);
    QObject::connect(child->surface().data(), &SurfaceInterface::unmapped, q, &SurfaceInterface::subSurfaceTreeChanged);
    QObject::connect(child->surface().data(), &SurfaceInterface::subSurfaceTreeChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
84
85
}

86
void SurfaceInterfacePrivate::removeChild(QPointer<SubSurfaceInterface> child)
87
{
88
89
    // protocol is not precise on how to handle the addition of new sub surfaces
    pending.children.removeAll(child);
90
    cached.children.removeAll(child);
91
    current.children.removeAll(child);
92
    emit q->childSubSurfaceRemoved(child);
93
94
    emit q->subSurfaceTreeChanged();
    QObject::disconnect(child.data(), &SubSurfaceInterface::positionChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
95
96
97
98
99
    if (!child->surface().isNull()) {
        QObject::disconnect(child->surface().data(), &SurfaceInterface::damaged, q, &SurfaceInterface::subSurfaceTreeChanged);
        QObject::disconnect(child->surface().data(), &SurfaceInterface::unmapped, q, &SurfaceInterface::subSurfaceTreeChanged);
        QObject::disconnect(child->surface().data(), &SurfaceInterface::subSurfaceTreeChanged, q, &SurfaceInterface::subSurfaceTreeChanged);
    }
100
101
}

102
bool SurfaceInterfacePrivate::raiseChild(QPointer<SubSurfaceInterface> subsurface, SurfaceInterface *sibling)
103
104
105
106
107
108
109
110
111
112
113
114
115
{
    auto it = std::find(pending.children.begin(), pending.children.end(), subsurface);
    if (it == pending.children.end()) {
        return false;
    }
    if (pending.children.count() == 1) {
        // nothing to do
        return true;
    }
    if (sibling == q) {
        // it's to the parent, so needs to become last item
        pending.children.append(*it);
        pending.children.erase(it);
116
        pending.childrenChanged = true;
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
        return true;
    }
    if (!sibling->subSurface()) {
        // not a sub surface
        return false;
    }
    auto siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
    if (siblingIt == pending.children.end() || siblingIt == it) {
        // not a sibling
        return false;
    }
    auto value = (*it);
    pending.children.erase(it);
    // find the iterator again
    siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
    pending.children.insert(++siblingIt, value);
133
    pending.childrenChanged = true;
134
135
136
    return true;
}

137
bool SurfaceInterfacePrivate::lowerChild(QPointer<SubSurfaceInterface> subsurface, SurfaceInterface *sibling)
138
139
140
141
142
143
144
145
146
147
148
149
150
151
{
    auto it = std::find(pending.children.begin(), pending.children.end(), subsurface);
    if (it == pending.children.end()) {
        return false;
    }
    if (pending.children.count() == 1) {
        // nothing to do
        return true;
    }
    if (sibling == q) {
        // it's to the parent, so needs to become first item
        auto value = *it;
        pending.children.erase(it);
        pending.children.prepend(value);
152
        pending.childrenChanged = true;
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
        return true;
    }
    if (!sibling->subSurface()) {
        // not a sub surface
        return false;
    }
    auto siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
    if (siblingIt == pending.children.end() || siblingIt == it) {
        // not a sibling
        return false;
    }
    auto value = (*it);
    pending.children.erase(it);
    // find the iterator again
    siblingIt = std::find(pending.children.begin(), pending.children.end(), sibling->subSurface());
    pending.children.insert(siblingIt, value);
169
    pending.childrenChanged = true;
170
171
172
    return true;
}

173
void SurfaceInterfacePrivate::setShadow(const QPointer<ShadowInterface> &shadow)
Martin Flöser's avatar
Martin Flöser committed
174
175
176
177
178
{
    pending.shadow = shadow;
    pending.shadowIsSet = true;
}

179
void SurfaceInterfacePrivate::setBlur(const QPointer<BlurInterface> &blur)
Marco Martin's avatar
Marco Martin committed
180
181
182
183
184
{
    pending.blur = blur;
    pending.blurIsSet = true;
}

185
void SurfaceInterfacePrivate::setSlide(const QPointer<SlideInterface> &slide)
Marco Martin's avatar
Marco Martin committed
186
187
188
189
190
{
    pending.slide = slide;
    pending.slideIsSet = true;
}

191
void SurfaceInterfacePrivate::setContrast(const QPointer<ContrastInterface> &contrast)
192
193
194
195
196
{
    pending.contrast = contrast;
    pending.contrastIsSet = true;
}

197
void SurfaceInterfacePrivate::installPointerConstraint(LockedPointerInterface *lock)
198
199
200
201
{
    Q_ASSERT(lockedPointer.isNull());
    Q_ASSERT(confinedPointer.isNull());
    lockedPointer = QPointer<LockedPointerInterface>(lock);
202
203
204

    auto cleanUp = [this]() {
        lockedPointer.clear();
205
        QObject::disconnect(constrainsOneShotConnection);
206
        constrainsOneShotConnection = QMetaObject::Connection();
207
        QObject::disconnect(constrainsUnboundConnection);
208
        constrainsUnboundConnection = QMetaObject::Connection();
209
        emit q->pointerConstraintsChanged();
210
211
    };

212
    if (lock->lifeTime() == LockedPointerInterface::LifeTime::OneShot) {
213
        constrainsOneShotConnection = QObject::connect(lock, &LockedPointerInterface::lockedChanged, q,
214
215
            [this, cleanUp] {
                if (lockedPointer.isNull() || lockedPointer->isLocked()) {
216
217
                    return;
                }
218
                cleanUp();
219
220
221
            }
        );
    }
222
    constrainsUnboundConnection = QObject::connect(lock, &LockedPointerInterface::unbound, q,
223
        [this, cleanUp] {
224
225
226
            if (lockedPointer.isNull()) {
                return;
            }
227
            cleanUp();
228
229
        }
    );
230
    emit q->pointerConstraintsChanged();
231
232
}

233
void SurfaceInterfacePrivate::installPointerConstraint(ConfinedPointerInterface *confinement)
234
235
236
237
{
    Q_ASSERT(lockedPointer.isNull());
    Q_ASSERT(confinedPointer.isNull());
    confinedPointer = QPointer<ConfinedPointerInterface>(confinement);
238
239
240

    auto cleanUp = [this]() {
        confinedPointer.clear();
241
        QObject::disconnect(constrainsOneShotConnection);
242
        constrainsOneShotConnection = QMetaObject::Connection();
243
        QObject::disconnect(constrainsUnboundConnection);
244
        constrainsUnboundConnection = QMetaObject::Connection();
245
        emit q->pointerConstraintsChanged();
246
247
    };

248
    if (confinement->lifeTime() == ConfinedPointerInterface::LifeTime::OneShot) {
249
        constrainsOneShotConnection = QObject::connect(confinement, &ConfinedPointerInterface::confinedChanged, q,
250
251
            [this, cleanUp] {
                if (confinedPointer.isNull() || confinedPointer->isConfined()) {
252
253
                    return;
                }
254
                cleanUp();
255
256
257
            }
        );
    }
258
    constrainsUnboundConnection = QObject::connect(confinement, &ConfinedPointerInterface::unbound, q,
259
        [this, cleanUp] {
260
261
262
            if (confinedPointer.isNull()) {
                return;
            }
263
            cleanUp();
264
265
        }
    );
266
    emit q->pointerConstraintsChanged();
267
268
}

269
void SurfaceInterfacePrivate::installIdleInhibitor(IdleInhibitorInterface *inhibitor)
270
271
272
273
274
275
{
    idleInhibitors << inhibitor;
    QObject::connect(inhibitor, &IdleInhibitorInterface::aboutToBeUnbound, q,
        [this, inhibitor] {
            idleInhibitors.removeOne(inhibitor);
            if (idleInhibitors.isEmpty()) {
276
                emit q->inhibitsIdleChanged();
277
278
279
280
            }
        }
    );
    if (idleInhibitors.count() == 1) {
281
282
283
284
285
286
        emit q->inhibitsIdleChanged();
    }
}

void SurfaceInterfacePrivate::surface_destroy_resource(Resource *)
{
287
    emit q->aboutToBeDestroyed();
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    delete q;
}

void SurfaceInterfacePrivate::surface_destroy(Resource *resource)
{
    wl_resource_destroy(resource->handle);
}

void SurfaceInterfacePrivate::surface_attach(Resource *resource, struct ::wl_resource *buffer, int32_t x, int32_t y)
{
    Q_UNUSED(resource)
    pending.bufferIsSet = true;
    pending.offset = QPoint(x, y);
    if (pending.buffer) {
        delete pending.buffer;
    }
    if (!buffer) {
        // got a null buffer, deletes content in next frame
        pending.buffer = nullptr;
        pending.damage = QRegion();
        pending.bufferDamage = QRegion();
        return;
    }
    pending.buffer = new BufferInterface(buffer, q);
    QObject::connect(pending.buffer, &BufferInterface::aboutToBeDestroyed, q,
        [this](BufferInterface *buffer) {
            if (pending.buffer == buffer) {
                pending.buffer = nullptr;
            }
317
318
            if (cached.buffer == buffer) {
                cached.buffer = nullptr;
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
            }
            if (current.buffer == buffer) {
                current.buffer->unref();
                current.buffer = nullptr;
            }
        }
    );
}

void SurfaceInterfacePrivate::surface_damage(Resource *, int32_t x, int32_t y, int32_t width, int32_t height)
{
    pending.damage = pending.damage.united(QRect(x, y, width, height));
}

void SurfaceInterfacePrivate::surface_frame(Resource *resource, uint32_t callback)
{
    wl_resource *callbackResource = wl_resource_create(resource->client(), &wl_callback_interface,
                                                       /* version */ 1, callback);
    if (!callbackResource) {
        wl_resource_post_no_memory(resource->handle);
        return;
340
    }
341
342
343
344
345
346
347
348
349
350
    pending.frameCallbacks.append(new KWaylandFrameCallback(callbackResource, q));
}

void SurfaceInterfacePrivate::surface_set_opaque_region(Resource *resource, struct ::wl_resource *region)
{
    Q_UNUSED(resource)
    RegionInterface *r = RegionInterface::get(region);
    pending.opaque = r ? r->region() : QRegion();
    pending.opaqueIsSet = true;

351
352
}

353
354
355
356
357
358
359
360
void SurfaceInterfacePrivate::surface_set_input_region(Resource *resource, struct ::wl_resource *region)
{
    Q_UNUSED(resource)
    RegionInterface *r = RegionInterface::get(region);
    pending.input = r ? r->region() : QRegion();
    pending.inputIsInfinite = !r;
    pending.inputIsSet = true;
}
361

362
void SurfaceInterfacePrivate::surface_commit(Resource *resource)
363
{
364
365
    Q_UNUSED(resource)
    commit();
366
367
}

368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
void SurfaceInterfacePrivate::surface_set_buffer_transform(Resource *resource, int32_t transform)
{
    Q_UNUSED(resource)
    pending.bufferTransform = OutputInterface::Transform(transform);
    pending.bufferTransformIsSet = true;
}

void SurfaceInterfacePrivate::surface_set_buffer_scale(Resource *resource, int32_t scale)
{
    Q_UNUSED(resource)
    pending.bufferScale = scale;
    pending.bufferScaleIsSet = true;
}

void SurfaceInterfacePrivate::surface_damage_buffer(Resource *resource, int32_t x, int32_t y, int32_t width, int32_t height)
{
    Q_UNUSED(resource)
    pending.bufferDamage = pending.bufferDamage.united(QRect(x, y, width, height));
}

SurfaceInterface::SurfaceInterface(CompositorInterface *compositor, wl_resource *resource)
    : QObject(compositor)
    , d(new SurfaceInterfacePrivate(this))
{
    d->compositor = compositor;
    d->init(resource);
394
    d->client = compositor->display()->getConnection(d->resource()->client());
395
396
397
398
399
400
401
402
403
404
405
406
407
}

SurfaceInterface::~SurfaceInterface()
{
}

uint32_t SurfaceInterface::id() const
{
    return wl_resource_get_id(resource());
}

ClientConnection *SurfaceInterface::client() const
{
408
    return d->client;
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
}

wl_resource *SurfaceInterface::resource() const
{
    return d->resource()->handle;
}

CompositorInterface *SurfaceInterface::compositor() const
{
    return d->compositor;
}

QList<SurfaceInterface *> SurfaceInterface::surfaces()
{
    return SurfaceInterfacePrivate::surfaces;
}
425

426
427
428
void SurfaceInterface::frameRendered(quint32 msec)
{
    // notify all callbacks
429
430
431
432
433
    const bool needsFlush = !d->current.frameCallbacks.isEmpty();
    while (!d->current.frameCallbacks.isEmpty()) {
        KWaylandFrameCallback *frameCallback = d->current.frameCallbacks.takeFirst();
        frameCallback->send_done(msec);
        frameCallback->destroy();
434
    }
435
436
437
438
439
440
441
    for (auto it = d->current.children.constBegin(); it != d->current.children.constEnd(); ++it) {
        const auto &subSurface = *it;
        if (subSurface.isNull() || subSurface->d_func()->surface.isNull()) {
            continue;
        }
        subSurface->d_func()->surface->frameRendered(msec);
    }
442
443
444
    if (needsFlush)  {
        client()->flush();
    }
445
446
}

447
QMatrix4x4 SurfaceInterfacePrivate::buildSurfaceToBufferMatrix(const State *state)
448
449
450
451
452
453
454
455
456
{
    // The order of transforms is reversed, i.e. the viewport transform is the first one.

    QMatrix4x4 surfaceToBufferMatrix;

    if (!state->buffer) {
        return surfaceToBufferMatrix;
    }

457
    surfaceToBufferMatrix.scale(state->bufferScale, state->bufferScale);
458

459
    switch (state->bufferTransform) {
460
461
462
463
464
    case OutputInterface::Transform::Normal:
    case OutputInterface::Transform::Flipped:
        break;
    case OutputInterface::Transform::Rotated90:
    case OutputInterface::Transform::Flipped90:
465
        surfaceToBufferMatrix.translate(0, state->buffer->height() / state->bufferScale);
466
467
468
469
        surfaceToBufferMatrix.rotate(-90, 0, 0, 1);
        break;
    case OutputInterface::Transform::Rotated180:
    case OutputInterface::Transform::Flipped180:
470
471
        surfaceToBufferMatrix.translate(state->buffer->width() / state->bufferScale,
                                        state->buffer->height() / state->bufferScale);
472
473
474
475
        surfaceToBufferMatrix.rotate(-180, 0, 0, 1);
        break;
    case OutputInterface::Transform::Rotated270:
    case OutputInterface::Transform::Flipped270:
476
        surfaceToBufferMatrix.translate(state->buffer->width() / state->bufferScale, 0);
477
478
479
480
        surfaceToBufferMatrix.rotate(-270, 0, 0, 1);
        break;
    }

481
    switch (state->bufferTransform) {
482
483
    case OutputInterface::Transform::Flipped:
    case OutputInterface::Transform::Flipped180:
484
        surfaceToBufferMatrix.translate(state->buffer->width() / state->bufferScale, 0);
485
486
487
488
        surfaceToBufferMatrix.scale(-1, 1);
        break;
    case OutputInterface::Transform::Flipped90:
    case OutputInterface::Transform::Flipped270:
489
        surfaceToBufferMatrix.translate(state->buffer->height() / state->bufferScale, 0);
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
        surfaceToBufferMatrix.scale(-1, 1);
        break;
    default:
        break;
    }

    if (state->sourceGeometry.isValid()) {
        surfaceToBufferMatrix.translate(state->sourceGeometry.x(), state->sourceGeometry.y());
        surfaceToBufferMatrix.scale(state->sourceGeometry.width() / state->size.width(),
                                    state->sourceGeometry.height() / state->size.height());
    }

    return surfaceToBufferMatrix;
}

505
void SurfaceInterfacePrivate::swapStates(State *source, State *target, bool emitChanged)
506
{
507
    const bool bufferChanged = source->bufferIsSet;
508
509
    const bool opaqueRegionChanged = source->opaqueIsSet;
    const bool inputRegionChanged = source->inputIsSet;
510
511
    const bool scaleFactorChanged = source->bufferScaleIsSet && (target->bufferScale != source->bufferScale);
    const bool transformChanged = source->bufferTransformIsSet && (target->bufferTransform != source->bufferTransform);
512
513
514
515
516
    const bool shadowChanged = source->shadowIsSet;
    const bool blurChanged = source->blurIsSet;
    const bool contrastChanged = source->contrastIsSet;
    const bool slideChanged = source->slideIsSet;
    const bool childrenChanged = source->childrenChanged;
517
    const bool visibilityChanged = bufferChanged && (bool(source->buffer) != bool(target->buffer));
518
    const QSize oldSize = target->size;
519
    const QSize oldBufferSize = bufferSize;
520
    const QMatrix4x4 oldSurfaceToBufferMatrix = surfaceToBufferMatrix;
521
    if (bufferChanged) {
522
523
524
525
526
527
528
529
        // TODO: is the reffing correct for subsurfaces?
        if (target->buffer) {
            if (emitChanged) {
                target->buffer->unref();
            } else {
                delete target->buffer;
                target->buffer = nullptr;
            }
530
        }
531
532
533
534
        if (source->buffer) {
            if (emitChanged) {
                source->buffer->ref();
            }
535
        }
536
        target->buffer = source->buffer;
537
        target->offset = source->offset;
538
        target->damage = source->damage;
539
        target->bufferDamage = source->bufferDamage;
540
541
        target->bufferIsSet = source->bufferIsSet;
    }
542
543
544
545
546
547
548
549
    if (source->sourceGeometryIsSet) {
        target->sourceGeometry = source->sourceGeometry;
        target->sourceGeometryIsSet = true;
    }
    if (source->destinationSizeIsSet) {
        target->destinationSize = source->destinationSize;
        target->destinationSizeIsSet = true;
    }
550
551
552
    if (childrenChanged) {
        target->childrenChanged = source->childrenChanged;
        target->children = source->children;
553
    }
554
    target->frameCallbacks.append(source->frameCallbacks);
555

Martin Flöser's avatar
Martin Flöser committed
556
    if (shadowChanged) {
557
558
        target->shadow = source->shadow;
        target->shadowIsSet = true;
Martin Flöser's avatar
Martin Flöser committed
559
    }
Marco Martin's avatar
Marco Martin committed
560
    if (blurChanged) {
561
562
        target->blur = source->blur;
        target->blurIsSet = true;
Marco Martin's avatar
Marco Martin committed
563
    }
564
    if (contrastChanged) {
565
566
        target->contrast = source->contrast;
        target->contrastIsSet = true;
567
    }
Marco Martin's avatar
Marco Martin committed
568
    if (slideChanged) {
569
570
        target->slide = source->slide;
        target->slideIsSet = true;
Marco Martin's avatar
Marco Martin committed
571
    }
572
573
574
575
576
577
578
579
580
581
    if (inputRegionChanged) {
        target->input = source->input;
        target->inputIsInfinite = source->inputIsInfinite;
        target->inputIsSet = true;
    }
    if (opaqueRegionChanged) {
        target->opaque = source->opaque;
        target->opaqueIsSet = true;
    }
    if (scaleFactorChanged) {
582
583
        target->bufferScale = source->bufferScale;
        target->bufferScaleIsSet = true;
584
    }
585
    if (transformChanged) {
586
587
        target->bufferTransform = source->bufferTransform;
        target->bufferTransformIsSet = true;
588
    }
589
590
591
592
593
594
    if (!lockedPointer.isNull()) {
        lockedPointer->d_func()->commit();
    }
    if (!confinedPointer.isNull()) {
        confinedPointer->d_func()->commit();
    }
595
596
597

    *source = State{};
    source->children = target->children;
598
599
600
601

    if (!emitChanged) {
        return;
    }
602
    // TODO: Refactor the state management code because it gets more clumsy.
603
    if (target->buffer) {
604
        bufferSize = target->buffer->size();
605
606
        if (target->destinationSize.isValid()) {
            target->size = target->destinationSize;
607
608
        } else if (target->sourceGeometry.isValid()) {
            target->size = target->sourceGeometry.size().toSize();
609
        } else {
610
611
            target->size = target->buffer->size() / target->bufferScale;
            switch (target->bufferTransform) {
612
613
614
615
616
617
618
619
620
621
622
623
            case OutputInterface::Transform::Rotated90:
            case OutputInterface::Transform::Rotated270:
            case OutputInterface::Transform::Flipped90:
            case OutputInterface::Transform::Flipped270:
                target->size.transpose();
                break;
            case OutputInterface::Transform::Normal:
            case OutputInterface::Transform::Rotated180:
            case OutputInterface::Transform::Flipped:
            case OutputInterface::Transform::Flipped180:
                break;
            }
624
625
626
        }
    } else {
        target->size = QSize();
627
        bufferSize = QSize();
628
    }
629
630
    surfaceToBufferMatrix = buildSurfaceToBufferMatrix(target);
    bufferToSurfaceMatrix = surfaceToBufferMatrix.inverted();
631
    if (opaqueRegionChanged) {
632
        emit q->opaqueChanged(target->opaque);
633
634
    }
    if (inputRegionChanged) {
635
        emit q->inputChanged(target->input);
636
637
    }
    if (scaleFactorChanged) {
638
        emit q->bufferScaleChanged(target->bufferScale);
639
    }
640
    if (transformChanged) {
641
        emit q->bufferTransformChanged(target->bufferTransform);
642
    }
643
644
645
646
647
648
649
650
651
652
    if (visibilityChanged) {
        if (target->buffer) {
            subSurfaceIsMapped = true;
            emit q->mapped();
        } else {
            subSurfaceIsMapped = false;
            emit q->unmapped();
        }
    }
    if (bufferChanged) {
653
        if (target->buffer && (!target->damage.isEmpty() || !target->bufferDamage.isEmpty())) {
654
            const QRegion windowRegion = QRegion(0, 0, q->size().width(), q->size().height());
655
            const QRegion bufferDamage = q->mapFromBuffer(target->bufferDamage);
656
657
658
659
660
661
662
663
664
            target->damage = windowRegion.intersected(target->damage.united(bufferDamage));
            trackedDamage = trackedDamage.united(target->damage);
            emit q->damaged(target->damage);
            // workaround for https://bugreports.qt.io/browse/QTBUG-52092
            // if the surface is a sub-surface, but the main surface is not yet mapped, fake frame rendered
            if (subSurface) {
                const auto mainSurface = subSurface->mainSurface();
                if (!mainSurface || !mainSurface->buffer()) {
                    q->frameRendered(0);
665
                }
666
            }
667
        }
668
    }
669
670
671
    if (surfaceToBufferMatrix != oldSurfaceToBufferMatrix) {
        emit q->surfaceToBufferMatrixChanged();
    }
672
673
674
    if (bufferSize != oldBufferSize) {
        emit q->bufferSizeChanged();
    }
675
    if (target->size != oldSize) {
676
677
        emit q->sizeChanged();
    }
Martin Flöser's avatar
Martin Flöser committed
678
679
680
    if (shadowChanged) {
        emit q->shadowChanged();
    }
Marco Martin's avatar
Marco Martin committed
681
682
683
    if (blurChanged) {
        emit q->blurChanged();
    }
684
685
686
    if (contrastChanged) {
        emit q->contrastChanged();
    }
Marco Martin's avatar
Marco Martin committed
687
688
689
    if (slideChanged) {
        emit q->slideOnShowHideChanged();
    }
690
691
692
    if (childrenChanged) {
        emit q->subSurfaceTreeChanged();
    }
693
694
}

695
void SurfaceInterfacePrivate::commit()
696
697
{
    if (!subSurface.isNull() && subSurface->isSynchronized()) {
698
        swapStates(&pending, &cached, false);
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
    } else {
        swapStates(&pending, &current, true);
        if (!subSurface.isNull()) {
            subSurface->d_func()->commit();
        }
        // commit all subSurfaces to apply position changes
        // "The cached state is applied to the sub-surface immediately after the parent surface's state is applied"
        for (auto it = current.children.constBegin(); it != current.children.constEnd(); ++it) {
            const auto &subSurface = *it;
            if (subSurface.isNull()) {
                continue;
            }
            subSurface->d_func()->commit();
        }
    }
714
715
716
    if (role) {
        role->commit();
    }
717
    emit q->committed();
718
719
}

720
void SurfaceInterfacePrivate::commitSubSurface()
721
722
723
724
{
    if (subSurface.isNull() || !subSurface->isSynchronized()) {
        return;
    }
725
    swapStates(&cached, &current, true);
726
727
728
729
730
731
732
733
734
735
    // "The cached state is applied to the sub-surface immediately after the parent surface's state is applied"
    for (auto it = current.children.constBegin(); it != current.children.constEnd(); ++it) {
        const auto &subSurface = *it;
        if (subSurface.isNull() || !subSurface->isSynchronized()) {
            continue;
        }
        subSurface->d_func()->commit();
    }
}

736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
QRegion SurfaceInterface::damage() const
{
    return d->current.damage;
}

QRegion SurfaceInterface::opaque() const
{
    return d->current.opaque;
}

QRegion SurfaceInterface::input() const
{
    return d->current.input;
}

751
bool SurfaceInterface::inputIsInfinite() const
752
753
754
755
{
    return d->current.inputIsInfinite;
}

756
qint32 SurfaceInterface::bufferScale() const
757
{
758
    return d->current.bufferScale;
759
760
}

761
OutputInterface::Transform SurfaceInterface::bufferTransform() const
762
{
763
    return d->current.bufferTransform;
764
765
766
767
768
769
770
771
772
773
774
775
776
777
}

BufferInterface *SurfaceInterface::buffer()
{
    return d->current.buffer;
}

QPoint SurfaceInterface::offset() const
{
    return d->current.offset;
}

SurfaceInterface *SurfaceInterface::get(wl_resource *native)
{
778
779
780
781
    if (auto surface = SurfaceInterfacePrivate::Resource::fromResource(native)) {
        return static_cast<SurfaceInterfacePrivate *>(surface->object())->q;
    }
    return nullptr;
782
783
}

784
SurfaceInterface *SurfaceInterface::get(quint32 id, const ClientConnection *client)
785
{
786
787
788
789
790
791
792
    const QList<SurfaceInterface *> candidates = surfaces();
    for (SurfaceInterface *surface : candidates) {
        if (surface->client() == client && surface->id() == id) {
            return surface;
        }
    }
    return nullptr;
793
794
}

795
796
797
798
799
800
801
802
803
804
QList< QPointer< SubSurfaceInterface > > SurfaceInterface::childSubSurfaces() const
{
    return d->current.children;
}

QPointer< SubSurfaceInterface > SurfaceInterface::subSurface() const
{
    return d->subSurface;
}

805
806
QSize SurfaceInterface::size() const
{
807
808
809
    return d->current.size;
}

810
811
812
813
814
815
816
817
818
819
820
821
822
QRect SurfaceInterface::boundingRect() const
{
    QRect rect(QPoint(0, 0), size());

    const QList<QPointer<SubSurfaceInterface>> subSurfaces = childSubSurfaces();
    for (const SubSurfaceInterface *subSurface : subSurfaces) {
        const SurfaceInterface *childSurface = subSurface->surface();
        rect |= childSurface->boundingRect().translated(subSurface->position());
    }

    return rect;
}

Martin Flöser's avatar
Martin Flöser committed
823
824
825
826
827
QPointer< ShadowInterface > SurfaceInterface::shadow() const
{
    return d->current.shadow;
}

Marco Martin's avatar
Marco Martin committed
828
829
830
831
832
QPointer< BlurInterface > SurfaceInterface::blur() const
{
    return d->current.blur;
}

833
834
835
836
837
QPointer< ContrastInterface > SurfaceInterface::contrast() const
{
    return d->current.contrast;
}

Marco Martin's avatar
Marco Martin committed
838
839
840
841
842
QPointer< SlideInterface > SurfaceInterface::slideOnShowHide() const
{
    return d->current.slide;
}

843
844
845
846
847
bool SurfaceInterface::isMapped() const
{
    if (d->subSurface) {
        // from spec:
        // "A sub-surface becomes mapped, when a non-NULL wl_buffer is applied and the parent surface is mapped."
848
        return d->subSurfaceIsMapped && !d->subSurface->parentSurface().isNull() && d->subSurface->parentSurface()->isMapped();
849
850
851
852
    }
    return d->current.buffer != nullptr;
}

853
854
855
856
857
858
859
860
861
862
QRegion SurfaceInterface::trackedDamage() const
{
    return d->trackedDamage;
}

void SurfaceInterface::resetTrackedDamage()
{
    d->trackedDamage = QRegion();
}

863
864
865
866
867
868
869
870
871
872
873
874
875
876
QVector<OutputInterface *> SurfaceInterface::outputs() const
{
    return d->outputs;
}

void SurfaceInterface::setOutputs(const QVector<OutputInterface *> &outputs)
{
    QVector<OutputInterface *> removedOutputs = d->outputs;
    for (auto it = outputs.constBegin(), end = outputs.constEnd(); it != end; ++it) {
        const auto o = *it;
        removedOutputs.removeOne(o);
    }
    for (auto it = removedOutputs.constBegin(), end = removedOutputs.constEnd(); it != end; ++it) {
        const auto resources = (*it)->clientResources(client());
877
878
        for (wl_resource *outputResource : resources) {
            d->send_leave(outputResource);
879
        }
880
        disconnect(d->outputDestroyedConnections.take(*it));
881
882
883
884
885
886
887
    }
    QVector<OutputInterface *> addedOutputsOutputs = outputs;
    for (auto it = d->outputs.constBegin(), end = d->outputs.constEnd(); it != end; ++it) {
        const auto o = *it;
        addedOutputsOutputs.removeOne(o);
    }
    for (auto it = addedOutputsOutputs.constBegin(), end = addedOutputsOutputs.constEnd(); it != end; ++it) {
888
889
        const auto o = *it;
        const auto resources = o->clientResources(client());
890
891
        for (wl_resource *outputResource : resources) {
            d->send_enter(outputResource);
892
        }
893
894
895
896
897
        d->outputDestroyedConnections[o] = connect(o, &Global::aboutToDestroyGlobal, this, [this, o] {
            auto outputs = d->outputs;
            if (outputs.removeOne(o)) {
                setOutputs(outputs);
            }});
898
899
900
901
902
903
    }
    // TODO: send enter when the client binds the OutputInterface another time

    d->outputs = outputs;
}

904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
SurfaceInterface *SurfaceInterface::surfaceAt(const QPointF &position)
{
    if (!isMapped()) {
        return nullptr;
    }
    // go from top to bottom. Top most child is last in list
    QListIterator<QPointer<SubSurfaceInterface>> it(d->current.children);
    it.toBack();
    while (it.hasPrevious()) {
        const auto &current = it.previous();
        auto surface = current->surface();
        if (surface.isNull()) {
            continue;
        }
        if (auto s = surface->surfaceAt(position - current->position())) {
            return s;
        }
    }
    // check whether the geometry contains the pos
    if (!size().isEmpty() && QRectF(QPoint(0, 0), size()).contains(position)) {
        return this;
    }
    return nullptr;
}

929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
SurfaceInterface *SurfaceInterface::inputSurfaceAt(const QPointF &position)
{
    // TODO: Most of this is very similar to SurfaceInterface::surfaceAt
    //       Is there a way to reduce the code duplication?
    if (!isMapped()) {
        return nullptr;
    }
    // go from top to bottom. Top most child is last in list
    QListIterator<QPointer<SubSurfaceInterface>> it(d->current.children);
    it.toBack();
    while (it.hasPrevious()) {
        const auto &current = it.previous();
        auto surface = current->surface();
        if (surface.isNull()) {
            continue;
        }
        if (auto s = surface->inputSurfaceAt(position - current->position())) {
            return s;
        }
    }
    // check whether the geometry and input region contain the pos
    if (!size().isEmpty() && QRectF(QPoint(0, 0), size()).contains(position) &&
            (inputIsInfinite() || input().contains(position.toPoint()))) {
        return this;
    }
    return nullptr;
}

957
958
959
960
961
962
963
964
965
966
QPointer<LockedPointerInterface> SurfaceInterface::lockedPointer() const
{
    return d->lockedPointer;
}

QPointer<ConfinedPointerInterface> SurfaceInterface::confinedPointer() const
{
    return d->confinedPointer;
}

967
968
969
970
971
bool SurfaceInterface::inhibitsIdle() const
{
    return !d->idleInhibitors.isEmpty();
}

972
973
974
975
976
977
978
979
980
981
void SurfaceInterface::setDataProxy(SurfaceInterface *surface)
{
    d->dataProxy = surface;
}

SurfaceInterface* SurfaceInterface::dataProxy() const
{
    return d->dataProxy;
}

982
983
QPointF SurfaceInterface::mapToBuffer(const QPointF &point) const
{
984
    return d->surfaceToBufferMatrix.map(point);
985
986
987
988
}

QPointF SurfaceInterface::mapFromBuffer(const QPointF &point) const
{
989
    return d->bufferToSurfaceMatrix.map(point);
990
991
}

992
static QRegion map_helper(const QMatrix4x4 &matrix, const QRegion &region)
993
{
994
995
996
997
998
    QRegion result;
    for (const QRect &rect : region) {
        result += matrix.mapRect(rect);
    }
    return result;
999
1000
}

1001
QRegion SurfaceInterface::mapToBuffer(const QRegion &region) const
1002
{
1003
    return map_helper(d->surfaceToBufferMatrix, region);
1004
1005
}

1006
QRegion SurfaceInterface::mapFromBuffer(const QRegion &region) const
1007
{
1008
    return map_helper(d->bufferToSurfaceMatrix, region);
1009
1010
}

1011
QMatrix4x4 SurfaceInterface::surfaceToBufferMatrix() const
1012
{
1013
    return d->surfaceToBufferMatrix;
1014
1015
}

1016
} // namespace KWaylandServer