1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include "corecompositor.h"
30
31namespace MockCompositor {
32
33CoreCompositor::CoreCompositor()
34 : m_display(wl_display_create())
35 , m_socketName(wl_display_add_socket_auto(display: m_display))
36 , m_eventLoop(wl_display_get_event_loop(display: m_display))
37
38 // Start dispatching
39 , m_dispatchThread([this](){
40 while (m_running) {
41 std::this_thread::sleep_for(std::chrono::milliseconds(20));
42 dispatch();
43 }
44 })
45{
46 qputenv(varName: "WAYLAND_DISPLAY", value: m_socketName);
47 m_timer.start();
48 Q_ASSERT(isClean());
49}
50
51CoreCompositor::~CoreCompositor()
52{
53 m_running = false;
54 m_dispatchThread.join();
55 wl_display_destroy(display: m_display);
56}
57
58bool CoreCompositor::isClean()
59{
60 Lock lock(this);
61 for (auto *global : qAsConst(t&: m_globals)) {
62 if (!global->isClean())
63 return false;
64 }
65 return true;
66}
67
68QString CoreCompositor::dirtyMessage()
69{
70 Lock lock(this);
71 QStringList messages;
72 for (auto *global : qAsConst(t&: m_globals)) {
73 if (!global->isClean())
74 messages << (global->metaObject()->className() % QLatin1String(": ") % global->dirtyMessage());
75 }
76 return messages.join(sep: ", ");
77}
78
79void CoreCompositor::dispatch()
80{
81 Lock lock(this);
82 wl_display_flush_clients(display: m_display);
83 constexpr int timeout = 0; // immediate return
84 wl_event_loop_dispatch(loop: m_eventLoop, timeout);
85}
86
87/*!
88 * \brief Adds a new global interface for the compositor
89 *
90 * Takes ownership of \a global
91 */
92void CoreCompositor::add(Global *global)
93{
94 warnIfNotLockedByThread(Q_FUNC_INFO);
95 m_globals.append(t: global);
96}
97
98void CoreCompositor::remove(Global *global)
99{
100 warnIfNotLockedByThread(Q_FUNC_INFO);
101 m_globals.removeAll(t: global);
102 delete global;
103}
104
105uint CoreCompositor::nextSerial()
106{
107 warnIfNotLockedByThread(Q_FUNC_INFO);
108 return wl_display_next_serial(display: m_display);
109}
110
111uint CoreCompositor::currentTimeMilliseconds()
112{
113 warnIfNotLockedByThread(Q_FUNC_INFO);
114 return uint(m_timer.elapsed());
115}
116
117wl_client *CoreCompositor::client(int index)
118{
119 warnIfNotLockedByThread(Q_FUNC_INFO);
120 wl_list *clients = wl_display_get_client_list(display: m_display);
121 wl_client *client = nullptr;
122 int i = 0;
123 wl_client_for_each(client, clients) {
124 if (i++ == index)
125 return client;
126 }
127 return nullptr;
128}
129
130void CoreCompositor::warnIfNotLockedByThread(const char *caller)
131{
132 if (!m_lock || !m_lock->isOwnedByCurrentThread()) {
133 qWarning() << caller << "called without locking the compositor to the current thread."
134 << "This means the compositor can start dispatching at any moment,"
135 << "potentially leading to threading issues."
136 << "Unless you know what you are doing you should probably fix the test"
137 << "by locking the compositor before accessing it (see mutex()).";
138 }
139}
140
141} // namespace MockCompositor
142

source code of qtwayland/tests/auto/client/shared/corecompositor.cpp