summaryrefslogtreecommitdiff
path: root/tests/auto/client/shared/mockcompositor.cpp
blob: 1266f7762b2cc626c8bf0bf9409ec6e3995742fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
// Copyright (C) 2021 David Edmundson <davidedmundson@kde.org>
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include "mockcompositor.h"

namespace MockCompositor {

DefaultCompositor::DefaultCompositor(CompositorType t)
    : CoreCompositor(t)
{
    {
        Lock l(this);

        // Globals: Should ideally always be at least the latest versions we support.
        // Legacy versions can override in separate tests by removing and adding.
        add<WlCompositor>();
        add<SubCompositor>();
        auto *output = add<Output>();
        output->m_data.physicalSize = output->m_data.mode.physicalSizeForDpi(96);
        add<Seat>(Seat::capability_pointer | Seat::capability_keyboard | Seat::capability_touch);
        add<WlShell>();
        add<XdgWmBase>();
        switch (m_type) {
        case CompositorType::Default:
            add<Shm>();
            break;
        case CompositorType::Legacy:
            wl_display_init_shm(m_display);
            break;
        }
        add<FullScreenShellV1>();
        add<IviApplication>();

        // TODO: other shells, viewporter, xdgoutput etc

        QObject::connect(get<WlCompositor>(), &WlCompositor::surfaceCreated, [&] (Surface *surface){
            QObject::connect(surface, &Surface::bufferCommitted, [=] {
                if (m_config.autoRelease) {
                    // Pretend we made a copy of the buffer and just release it immediately
                    surface->m_committed.buffer->send_release();
                }
                if (m_config.autoEnter && get<Output>() && surface->m_outputs.empty())
                    surface->sendEnter(get<Output>());
                wl_display_flush_clients(m_display);
            });
        });

        QObject::connect(get<XdgWmBase>(), &XdgWmBase::toplevelCreated, get<XdgWmBase>(), [&] (XdgToplevel *toplevel) {
            if (m_config.autoConfigure)
                toplevel->sendCompleteConfigure();
        }, Qt::DirectConnection);
    }
    Q_ASSERT(isClean());
}

Surface *DefaultCompositor::surface(int i)
{
    QList<Surface *> surfaces;
    switch (m_type) {
    case CompositorType::Default:
        return get<WlCompositor>()->m_surfaces.value(i, nullptr);
    case CompositorType::Legacy: {
            QList<Surface *> msurfaces = get<WlCompositor>()->m_surfaces;
            for (Surface *surface : msurfaces) {
                if (surface->isMapped()) {
                    surfaces << surface;
                }
            }
        }
        break;
    }

    if (i >= 0 && i < surfaces.size())
        return surfaces[i];

    return nullptr;
}

uint DefaultCompositor::sendXdgShellPing()
{
    warnIfNotLockedByThread(Q_FUNC_INFO);
    uint serial = nextSerial();
    auto *base = get<XdgWmBase>();
    const auto resourceMap = base->resourceMap();
    Q_ASSERT(resourceMap.size() == 1); // binding more than once shouldn't be needed
    base->send_ping(resourceMap.first()->handle, serial);
    return serial;
}

void DefaultCompositor::xdgPingAndWaitForPong()
{
    QSignalSpy pongSpy(exec([=] { return get<XdgWmBase>(); }), &XdgWmBase::pong);
    uint serial = exec([=] { return sendXdgShellPing(); });
    QTRY_COMPARE(pongSpy.size(), 1);
    QTRY_COMPARE(pongSpy.first().at(0).toUInt(), serial);
}

void DefaultCompositor::sendShellSurfaceConfigure(Surface *surface)
{
    switch (m_type) {
    case CompositorType::Default:
        break;
    case CompositorType::Legacy: {
            if (auto wlShellSurface = surface->wlShellSurface()) {
                wlShellSurface->sendConfigure(0, 0, 0);
                return;
            }
            break;
        }
    }

    qWarning() << "The mocking framework doesn't know how to send a configure event for this surface";
}

WlShellCompositor::WlShellCompositor(CompositorType t)
    : DefaultCompositor(t)
{
}

Surface *DefaultCompositor::wlSurface(int i)
{
    QList<Surface *> surfaces, msurfaces;
    msurfaces = get<WlCompositor>()->m_surfaces;
    for (Surface *surface : msurfaces) {
        if (surface->isMapped())
            surfaces << surface;
    }

    if (i >=0 && i < surfaces.size())
        return surfaces[i];

    return nullptr;
}

} // namespace MockCompositor