Change copyrights from Nokia to Digia
[profile/ivi/qtwayland.git] / tests / auto / client / mockcompositor.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "mockcompositor.h"
43 #include "mocksurface.h"
44
45 MockCompositor::MockCompositor()
46     : m_alive(true)
47     , m_ready(false)
48     , m_compositor(0)
49 {
50     pthread_create(&m_thread, 0, run, this);
51
52     m_mutex.lock();
53     m_waitCondition.wait(&m_mutex);
54     m_mutex.unlock();
55 }
56
57 MockCompositor::~MockCompositor()
58 {
59     m_alive = false;
60     m_waitCondition.wakeOne();
61     pthread_join(m_thread, 0);
62 }
63
64 void MockCompositor::lock()
65 {
66     m_mutex.lock();
67 }
68
69 void MockCompositor::unlock()
70 {
71     m_mutex.unlock();
72 }
73
74 void MockCompositor::applicationInitialized()
75 {
76     m_ready = true;
77 }
78
79 int MockCompositor::waylandFileDescriptor() const
80 {
81     return m_compositor->fileDescriptor();
82 }
83
84 void MockCompositor::processWaylandEvents()
85 {
86     m_waitCondition.wakeOne();
87 }
88
89 void MockCompositor::setOutputGeometry(const QRect &rect)
90 {
91     Command command = makeCommand(Impl::Compositor::setOutputGeometry, m_compositor);
92     command.parameters << rect;
93     processCommand(command);
94 }
95
96 void MockCompositor::setKeyboardFocus(const QSharedPointer<MockSurface> &surface)
97 {
98     Command command = makeCommand(Impl::Compositor::setKeyboardFocus, m_compositor);
99     command.parameters << QVariant::fromValue(surface);
100     processCommand(command);
101 }
102
103 void MockCompositor::sendMousePress(const QSharedPointer<MockSurface> &surface, const QPoint &pos)
104 {
105     Command command = makeCommand(Impl::Compositor::sendMousePress, m_compositor);
106     command.parameters << QVariant::fromValue(surface) << pos;
107     processCommand(command);
108 }
109
110 void MockCompositor::sendMouseRelease(const QSharedPointer<MockSurface> &surface)
111 {
112     Command command = makeCommand(Impl::Compositor::sendMouseRelease, m_compositor);
113     command.parameters << QVariant::fromValue(surface);
114     processCommand(command);
115 }
116
117 void MockCompositor::sendKeyPress(const QSharedPointer<MockSurface> &surface, uint code)
118 {
119     Command command = makeCommand(Impl::Compositor::sendKeyPress, m_compositor);
120     command.parameters << QVariant::fromValue(surface) << code;
121     processCommand(command);
122 }
123
124 void MockCompositor::sendKeyRelease(const QSharedPointer<MockSurface> &surface, uint code)
125 {
126     Command command = makeCommand(Impl::Compositor::sendKeyRelease, m_compositor);
127     command.parameters << QVariant::fromValue(surface) << code;
128     processCommand(command);
129 }
130
131 QSharedPointer<MockSurface> MockCompositor::surface()
132 {
133     QSharedPointer<MockSurface> result;
134     lock();
135     QVector<Impl::Surface *> surfaces = m_compositor->surfaces();
136     if (!surfaces.isEmpty())
137         result = surfaces.first()->mockSurface();
138     unlock();
139     return result;
140 }
141
142 MockCompositor::Command MockCompositor::makeCommand(Command::Callback callback, void *target)
143 {
144     Command command;
145     command.callback = callback;
146     command.target = target;
147     return command;
148 }
149
150 void MockCompositor::processCommand(const Command &command)
151 {
152     lock();
153     m_commandQueue << command;
154     unlock();
155
156     m_waitCondition.wakeOne();
157 }
158
159 void MockCompositor::dispatchCommands()
160 {
161     foreach (const Command &command, m_commandQueue)
162         command.callback(command.target, command.parameters);
163     m_commandQueue.clear();
164 }
165
166 void *MockCompositor::run(void *data)
167 {
168     MockCompositor *controller = static_cast<MockCompositor *>(data);
169
170     Impl::Compositor compositor;
171
172     controller->m_compositor = &compositor;
173     controller->m_waitCondition.wakeOne();
174
175     while (!controller->m_ready) {
176         controller->dispatchCommands();
177         compositor.dispatchEvents(20);
178     }
179
180     while (controller->m_alive) {
181         QMutexLocker locker(&controller->m_mutex);
182         controller->m_waitCondition.wait(&controller->m_mutex);
183         controller->dispatchCommands();
184         compositor.dispatchEvents(20);
185     }
186
187     return 0;
188 }
189
190 namespace Impl {
191
192 Compositor::Compositor()
193     : m_display(wl_display_create())
194     , m_time(0)
195 {
196     wl_list_init(&m_outputResources);
197
198     wl_display_add_socket(m_display, 0);
199
200     wl_seat_init(&m_seat);
201     wl_pointer_init(&m_pointer);
202     wl_seat_set_pointer(&m_seat, &m_pointer);
203     wl_keyboard_init(&m_keyboard);
204     wl_seat_set_keyboard(&m_seat, &m_keyboard);
205
206     wl_display_add_global(m_display, &wl_compositor_interface, this, bindCompositor);
207     wl_display_add_global(m_display, &wl_seat_interface, this, bindSeat);
208     wl_display_add_global(m_display, &wl_output_interface, this, bindOutput);
209     wl_display_add_global(m_display, &wl_shell_interface, this, bindShell);
210
211     wl_display_init_shm(m_display);
212
213     m_loop = wl_display_get_event_loop(m_display);
214     m_fd = wl_event_loop_get_fd(m_loop);
215 }
216
217 Compositor::~Compositor()
218 {
219     wl_pointer_release(&m_pointer);
220     wl_keyboard_release(&m_keyboard);
221     wl_display_destroy(m_display);
222 }
223
224 void Compositor::dispatchEvents(int timeout)
225 {
226     wl_event_loop_dispatch(m_loop, timeout);
227 }
228
229 static void compositor_create_surface(wl_client *client, wl_resource *compositorResource, uint32_t id)
230 {
231     Compositor *compositor = static_cast<Compositor *>(compositorResource->data);
232     compositor->addSurface(new Surface(client, id, compositor));
233 }
234
235 static void compositor_create_region(wl_client *client, wl_resource *compositorResource, uint32_t id)
236 {
237     Q_UNUSED(client);
238     Q_UNUSED(compositorResource);
239     Q_UNUSED(id);
240 }
241
242 void Compositor::bindCompositor(wl_client *client, void *compositorData, uint32_t version, uint32_t id)
243 {
244     static const struct wl_compositor_interface compositorInterface = {
245         compositor_create_surface,
246         compositor_create_region
247     };
248
249     Q_UNUSED(version);
250     wl_client_add_object(client, &wl_compositor_interface, &compositorInterface, id, compositorData);
251 }
252
253 static void unregisterResourceCallback(wl_listener *listener, void *data)
254 {
255     struct wl_resource *resource = reinterpret_cast<struct wl_resource *>(data);
256     wl_list_remove(&resource->link);
257     delete listener;
258 }
259
260 void registerResource(wl_list *list, wl_resource *resource)
261 {
262     wl_list_insert(list, &resource->link);
263
264     wl_listener *listener = new wl_listener;
265     listener->notify = unregisterResourceCallback;
266
267     wl_signal_add(&resource->destroy_signal, listener);
268 }
269
270 QVector<Surface *> Compositor::surfaces() const
271 {
272     return m_surfaces;
273 }
274
275 uint32_t Compositor::nextSerial()
276 {
277     return wl_display_next_serial(m_display);
278 }
279
280 void Compositor::addSurface(Surface *surface)
281 {
282     m_surfaces << surface;
283 }
284
285 void Compositor::removeSurface(Surface *surface)
286 {
287     m_surfaces.remove(m_surfaces.indexOf(surface));
288 }
289
290 }
291