~ubuntu-branches/ubuntu/wily/kwin/wily-proposed

« back to all changes in this revision

Viewing changes to backends/wayland/wayland_backend.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2015-08-10 23:16:37 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20150810231637-5zb2tstjkez93hml
Tags: 4:5.3.95-0ubuntu1
new upstream beta release

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/********************************************************************
 
2
 KWin - the KDE window manager
 
3
 This file is part of the KDE project.
 
4
 
 
5
Copyright (C) 2013 Martin Gräßlin <mgraesslin@kde.org>
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or
 
10
(at your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful,
 
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
GNU General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
*********************************************************************/
 
20
// own
 
21
#include "wayland_backend.h"
 
22
// KWin
 
23
#include "cursor.h"
 
24
#include "logging.h"
 
25
#include "main.h"
 
26
#include "scene_qpainter_wayland_backend.h"
 
27
#include "screens_wayland.h"
 
28
#include "wayland_server.h"
 
29
#if HAVE_WAYLAND_CURSOR
 
30
#include "wayland_cursor_theme.h"
 
31
#endif
 
32
#if HAVE_WAYLAND_EGL
 
33
#include "egl_wayland_backend.h"
 
34
#endif
 
35
#include <KWayland/Client/buffer.h>
 
36
#include <KWayland/Client/compositor.h>
 
37
#include <KWayland/Client/connection_thread.h>
 
38
#include <KWayland/Client/event_queue.h>
 
39
#include <KWayland/Client/fullscreen_shell.h>
 
40
#include <KWayland/Client/keyboard.h>
 
41
#include <KWayland/Client/output.h>
 
42
#include <KWayland/Client/pointer.h>
 
43
#include <KWayland/Client/region.h>
 
44
#include <KWayland/Client/registry.h>
 
45
#include <KWayland/Client/seat.h>
 
46
#include <KWayland/Client/shell.h>
 
47
#include <KWayland/Client/shm_pool.h>
 
48
#include <KWayland/Client/subcompositor.h>
 
49
#include <KWayland/Client/subsurface.h>
 
50
#include <KWayland/Client/surface.h>
 
51
#include <KWayland/Client/touch.h>
 
52
#include <KWayland/Server/buffer_interface.h>
 
53
#include <KWayland/Server/seat_interface.h>
 
54
#include <KWayland/Server/surface_interface.h>
 
55
// Qt
 
56
#include <QMetaMethod>
 
57
#include <QThread>
 
58
// Wayland
 
59
#if HAVE_WAYLAND_CURSOR
 
60
#include <wayland-cursor.h>
 
61
#endif
 
62
 
 
63
namespace KWin
 
64
{
 
65
namespace Wayland
 
66
{
 
67
 
 
68
using namespace KWayland::Client;
 
69
 
 
70
WaylandSeat::WaylandSeat(wl_seat *seat, WaylandBackend *backend)
 
71
    : QObject(NULL)
 
72
    , m_seat(new Seat(this))
 
73
    , m_pointer(NULL)
 
74
    , m_keyboard(NULL)
 
75
    , m_touch(nullptr)
 
76
    , m_cursor(NULL)
 
77
#if HAVE_WAYLAND_CURSOR
 
78
    , m_theme(new WaylandCursorTheme(backend->shmPool(), this))
 
79
#endif
 
80
    , m_enteredSerial(0)
 
81
    , m_backend(backend)
 
82
    , m_installCursor(false)
 
83
{
 
84
    m_seat->setup(seat);
 
85
    connect(m_seat, &Seat::hasKeyboardChanged, this,
 
86
        [this](bool hasKeyboard) {
 
87
            if (hasKeyboard) {
 
88
                m_keyboard = m_seat->createKeyboard(this);
 
89
                connect(m_keyboard, &Keyboard::keyChanged, this,
 
90
                    [this](quint32 key, Keyboard::KeyState state, quint32 time) {
 
91
                        switch (state) {
 
92
                        case Keyboard::KeyState::Pressed:
 
93
                            m_backend->keyboardKeyPressed(key, time);
 
94
                            break;
 
95
                        case Keyboard::KeyState::Released:
 
96
                            m_backend->keyboardKeyReleased(key, time);
 
97
                            break;
 
98
                        default:
 
99
                            Q_UNREACHABLE();
 
100
                        }
 
101
                    }
 
102
                );
 
103
                connect(m_keyboard, &Keyboard::modifiersChanged, this,
 
104
                    [this](quint32 depressed, quint32 latched, quint32 locked, quint32 group) {
 
105
                        m_backend->keyboardModifiers(depressed, latched, locked, group);
 
106
                    }
 
107
                );
 
108
                connect(m_keyboard, &Keyboard::keymapChanged, this,
 
109
                    [this](int fd, quint32 size) {
 
110
                        m_backend->keymapChange(fd, size);
 
111
                    }
 
112
                );
 
113
            } else {
 
114
                destroyKeyboard();
 
115
            }
 
116
        }
 
117
    );
 
118
    connect(m_seat, &Seat::hasPointerChanged, this,
 
119
        [this](bool hasPointer) {
 
120
            if (hasPointer && !m_pointer) {
 
121
                m_pointer = m_seat->createPointer(this);
 
122
                connect(m_pointer, &Pointer::entered, this,
 
123
                    [this](quint32 serial) {
 
124
                        m_enteredSerial = serial;
 
125
                        if (!m_installCursor) {
 
126
                            // explicitly hide cursor
 
127
                            m_pointer->hideCursor();
 
128
                        }
 
129
                    }
 
130
                );
 
131
                connect(m_pointer, &Pointer::motion, this,
 
132
                    [this](const QPointF &relativeToSurface, quint32 time) {
 
133
                        m_backend->pointerMotion(relativeToSurface, time);
 
134
                    }
 
135
                );
 
136
                connect(m_pointer, &Pointer::buttonStateChanged, this,
 
137
                    [this](quint32 serial, quint32 time, quint32 button, Pointer::ButtonState state) {
 
138
                        Q_UNUSED(serial)
 
139
                        switch (state) {
 
140
                        case Pointer::ButtonState::Pressed:
 
141
                            m_backend->pointerButtonPressed(button, time);
 
142
                            break;
 
143
                        case Pointer::ButtonState::Released:
 
144
                            m_backend->pointerButtonReleased(button, time);
 
145
                            break;
 
146
                        default:
 
147
                            Q_UNREACHABLE();
 
148
                        }
 
149
                    }
 
150
                );
 
151
                connect(m_pointer, &Pointer::axisChanged, this,
 
152
                    [this](quint32 time, Pointer::Axis axis, qreal delta) {
 
153
                        switch (axis) {
 
154
                        case Pointer::Axis::Horizontal:
 
155
                            m_backend->pointerAxisHorizontal(delta, time);
 
156
                            break;
 
157
                        case Pointer::Axis::Vertical:
 
158
                            m_backend->pointerAxisVertical(delta, time);
 
159
                            break;
 
160
                        default:
 
161
                            Q_UNREACHABLE();
 
162
                        }
 
163
                    }
 
164
                );
 
165
            } else {
 
166
                destroyPointer();
 
167
            }
 
168
        }
 
169
    );
 
170
    connect(m_seat, &Seat::hasTouchChanged,
 
171
        [this] (bool hasTouch) {
 
172
            if (hasTouch && !m_touch) {
 
173
                m_touch = m_seat->createTouch(this);
 
174
                connect(m_touch, &Touch::sequenceCanceled, m_backend, &AbstractBackend::touchCancel);
 
175
                connect(m_touch, &Touch::frameEnded, m_backend, &AbstractBackend::touchFrame);
 
176
                connect(m_touch, &Touch::sequenceStarted, this,
 
177
                    [this] (TouchPoint *tp) {
 
178
                        m_backend->touchDown(tp->id(), tp->position(), tp->time());
 
179
                    }
 
180
                );
 
181
                connect(m_touch, &Touch::pointAdded, this,
 
182
                    [this] (TouchPoint *tp) {
 
183
                        m_backend->touchDown(tp->id(), tp->position(), tp->time());
 
184
                    }
 
185
                );
 
186
                connect(m_touch, &Touch::pointRemoved, this,
 
187
                    [this] (TouchPoint *tp) {
 
188
                        m_backend->touchUp(tp->id(), tp->time());
 
189
                    }
 
190
                );
 
191
                connect(m_touch, &Touch::pointMoved, this,
 
192
                    [this] (TouchPoint *tp) {
 
193
                        m_backend->touchMotion(tp->id(), tp->position(), tp->time());
 
194
                    }
 
195
                );
 
196
            } else {
 
197
                destroyTouch();
 
198
            }
 
199
        }
 
200
    );
 
201
    WaylandServer *server = waylandServer();
 
202
    if (server) {
 
203
        using namespace KWayland::Server;
 
204
        SeatInterface *si = server->seat();
 
205
        connect(m_seat, &Seat::hasKeyboardChanged, si, &SeatInterface::setHasKeyboard);
 
206
        connect(m_seat, &Seat::hasPointerChanged, si, &SeatInterface::setHasPointer);
 
207
        connect(m_seat, &Seat::hasTouchChanged, si, &SeatInterface::setHasTouch);
 
208
        connect(m_seat, &Seat::nameChanged, si, &SeatInterface::setName);
 
209
    }
 
210
}
 
211
 
 
212
WaylandSeat::~WaylandSeat()
 
213
{
 
214
    destroyPointer();
 
215
    destroyKeyboard();
 
216
    destroyTouch();
 
217
}
 
218
 
 
219
void WaylandSeat::destroyPointer()
 
220
{
 
221
    delete m_pointer;
 
222
    m_pointer = nullptr;
 
223
}
 
224
 
 
225
void WaylandSeat::destroyKeyboard()
 
226
{
 
227
    delete m_keyboard;
 
228
    m_keyboard = nullptr;
 
229
}
 
230
 
 
231
void WaylandSeat::destroyTouch()
 
232
{
 
233
    delete m_touch;
 
234
    m_touch = nullptr;
 
235
}
 
236
 
 
237
void WaylandSeat::installCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotSpot)
 
238
{
 
239
    if (!m_installCursor) {
 
240
        return;
 
241
    }
 
242
    if (!m_pointer || !m_pointer->isValid()) {
 
243
        return;
 
244
    }
 
245
    if (!m_cursor) {
 
246
        m_cursor = m_backend->compositor()->createSurface(this);
 
247
    }
 
248
    if (!m_cursor || !m_cursor->isValid()) {
 
249
        return;
 
250
    }
 
251
    m_pointer->setCursor(m_cursor, hotSpot);
 
252
    m_cursor->attachBuffer(image);
 
253
    m_cursor->damage(QRect(QPoint(0,0), size));
 
254
    m_cursor->commit(Surface::CommitFlag::None);
 
255
}
 
256
 
 
257
void WaylandSeat::installCursorImage(Qt::CursorShape shape)
 
258
{
 
259
#if HAVE_WAYLAND_CURSOR
 
260
    wl_cursor_image *image = m_theme->get(shape);
 
261
    if (!image) {
 
262
        return;
 
263
    }
 
264
    installCursorImage(wl_cursor_image_get_buffer(image),
 
265
                       QSize(image->width, image->height),
 
266
                       QPoint(image->hotspot_x, image->hotspot_y));
 
267
#endif
 
268
}
 
269
 
 
270
void WaylandSeat::installCursorImage(const QImage &image, const QPoint &hotSpot)
 
271
{
 
272
    installCursorImage(*(m_backend->shmPool()->createBuffer(image).data()), image.size(), hotSpot);
 
273
}
 
274
 
 
275
void WaylandSeat::setInstallCursor(bool install)
 
276
{
 
277
    // TODO: remove, add?
 
278
    m_installCursor = install;
 
279
}
 
280
 
 
281
WaylandCursor::WaylandCursor(Surface *parentSurface, WaylandBackend *backend)
 
282
    : QObject(backend)
 
283
    , m_backend(backend)
 
284
#if HAVE_WAYLAND_CURSOR
 
285
    , m_theme(new WaylandCursorTheme(backend->shmPool(), this))
 
286
#endif
 
287
{
 
288
    auto surface = backend->compositor()->createSurface(this);
 
289
    m_subSurface = backend->subCompositor()->createSubSurface(QPointer<Surface>(surface), QPointer<Surface>(parentSurface), this);
 
290
 
 
291
    connect(Cursor::self(), &Cursor::posChanged, this,
 
292
        [this](const QPoint &pos) {
 
293
            m_subSurface->setPosition(pos - m_hotSpot);
 
294
            QPointer<Surface> parent = m_subSurface->parentSurface();
 
295
            if (parent.isNull()) {
 
296
                return;
 
297
            }
 
298
            parent->commit(Surface::CommitFlag::None);
 
299
        }
 
300
    );
 
301
 
 
302
    // install a default cursor image:
 
303
    setCursorImage(Qt::ArrowCursor);
 
304
}
 
305
 
 
306
void WaylandCursor::setHotSpot(const QPoint &pos)
 
307
{
 
308
    if (m_hotSpot == pos) {
 
309
        return;
 
310
    }
 
311
    m_hotSpot = pos;
 
312
    emit hotSpotChanged(m_hotSpot);
 
313
}
 
314
 
 
315
void WaylandCursor::setCursorImage(wl_buffer *image, const QSize &size, const QPoint &hotspot)
 
316
{
 
317
    QPointer<Surface> cursor = m_subSurface->surface();
 
318
    if (cursor.isNull()) {
 
319
        return;
 
320
    }
 
321
    cursor->attachBuffer(image);
 
322
    cursor->damage(QRect(QPoint(0,0), size));
 
323
    cursor->setInputRegion(m_backend->compositor()->createRegion(QRegion()).get());
 
324
    cursor->commit(Surface::CommitFlag::None);
 
325
    setHotSpot(hotspot);
 
326
    m_subSurface->setPosition(Cursor::pos() - m_hotSpot);
 
327
    QPointer<Surface> parent = m_subSurface->parentSurface();
 
328
    if (parent.isNull()) {
 
329
        return;
 
330
    }
 
331
    parent->commit(Surface::CommitFlag::None);
 
332
}
 
333
 
 
334
void WaylandCursor::setCursorImage(const QImage &image, const QPoint &hotspot)
 
335
{
 
336
    setCursorImage(*(m_backend->shmPool()->createBuffer(image).data()), image.size(), hotspot);
 
337
}
 
338
 
 
339
void WaylandCursor::setCursorImage(Qt::CursorShape shape)
 
340
{
 
341
#if HAVE_WAYLAND_CURSOR
 
342
    wl_cursor_image *image = m_theme->get(shape);
 
343
    if (!image) {
 
344
        return;
 
345
    }
 
346
    setCursorImage(wl_cursor_image_get_buffer(image),
 
347
                   QSize(image->width, image->height),
 
348
                   QPoint(image->hotspot_x, image->hotspot_y));
 
349
#endif
 
350
}
 
351
 
 
352
WaylandBackend::WaylandBackend(QObject *parent)
 
353
    : AbstractBackend(parent)
 
354
    , m_display(nullptr)
 
355
    , m_eventQueue(new EventQueue(this))
 
356
    , m_registry(new Registry(this))
 
357
    , m_compositor(new Compositor(this))
 
358
    , m_shell(new Shell(this))
 
359
    , m_surface(nullptr)
 
360
    , m_shellSurface(NULL)
 
361
    , m_seat()
 
362
    , m_shm(new ShmPool(this))
 
363
    , m_connectionThreadObject(new ConnectionThread(nullptr))
 
364
    , m_connectionThread(nullptr)
 
365
    , m_fullscreenShell(new FullscreenShell(this))
 
366
    , m_subCompositor(new SubCompositor(this))
 
367
    , m_cursor(nullptr)
 
368
{
 
369
    connect(this, &WaylandBackend::outputsChanged, this, &WaylandBackend::screensQueried);
 
370
    connect(this, &WaylandBackend::connectionFailed, this, &WaylandBackend::initFailed);
 
371
}
 
372
 
 
373
WaylandBackend::~WaylandBackend()
 
374
{
 
375
    destroyOutputs();
 
376
    if (m_shellSurface) {
 
377
        m_shellSurface->release();
 
378
    }
 
379
    m_fullscreenShell->release();
 
380
    if (m_surface) {
 
381
        m_surface->release();
 
382
    }
 
383
    m_shell->release();
 
384
    m_compositor->release();
 
385
    m_registry->release();
 
386
    m_seat.reset();
 
387
    m_shm->release();
 
388
    m_eventQueue->release();
 
389
 
 
390
    m_connectionThreadObject->deleteLater();
 
391
    m_connectionThread->quit();
 
392
    m_connectionThread->wait();
 
393
 
 
394
    qCDebug(KWIN_WAYLAND_BACKEND) << "Destroyed Wayland display";
 
395
}
 
396
 
 
397
void WaylandBackend::init()
 
398
{
 
399
    connect(this, &WaylandBackend::shellSurfaceSizeChanged, this, &WaylandBackend::checkBackendReady);
 
400
    connect(m_registry, &Registry::compositorAnnounced, this,
 
401
        [this](quint32 name) {
 
402
            m_compositor->setup(m_registry->bindCompositor(name, 1));
 
403
        }
 
404
    );
 
405
    connect(m_registry, &Registry::shellAnnounced, this,
 
406
        [this](quint32 name) {
 
407
            m_shell->setup(m_registry->bindShell(name, 1));
 
408
        }
 
409
    );
 
410
    connect(m_registry, &Registry::outputAnnounced, this,
 
411
        [this](quint32 name) {
 
412
            Output *output = new Output(this);
 
413
            output->setup(m_registry->bindOutput(name, 2));
 
414
            m_outputs.append(output);
 
415
            connect(output, &Output::changed, this, &WaylandBackend::outputsChanged);
 
416
        }
 
417
    );
 
418
    connect(m_registry, &Registry::seatAnnounced, this,
 
419
        [this](quint32 name) {
 
420
            if (Application::usesLibinput()) {
 
421
                return;
 
422
            }
 
423
            m_seat.reset(new WaylandSeat(m_registry->bindSeat(name, 2), this));
 
424
        }
 
425
    );
 
426
    connect(m_registry, &Registry::shmAnnounced, this,
 
427
        [this](quint32 name) {
 
428
            m_shm->setup(m_registry->bindShm(name, 1));
 
429
        }
 
430
    );
 
431
    connect(m_registry, &Registry::fullscreenShellAnnounced, this,
 
432
        [this](quint32 name, quint32 version) {
 
433
            m_fullscreenShell->setup(m_registry->bindFullscreenShell(name, version));
 
434
        }
 
435
    );
 
436
    connect(m_registry, &Registry::subCompositorAnnounced, this,
 
437
        [this](quint32 name, quint32 version) {
 
438
            m_subCompositor->setup(m_registry->bindSubCompositor(name, version));
 
439
        }
 
440
    );
 
441
    connect(m_registry, &Registry::interfacesAnnounced, this, &WaylandBackend::createSurface);
 
442
    m_connectionThreadObject->setSocketName(deviceIdentifier());
 
443
    initConnection();
 
444
}
 
445
 
 
446
void WaylandBackend::destroyOutputs()
 
447
{
 
448
    qDeleteAll(m_outputs);
 
449
    m_outputs.clear();
 
450
}
 
451
 
 
452
void WaylandBackend::initConnection()
 
453
{
 
454
    connect(m_connectionThreadObject, &ConnectionThread::connected, this,
 
455
        [this]() {
 
456
            // create the event queue for the main gui thread
 
457
            m_display = m_connectionThreadObject->display();
 
458
            m_eventQueue->setup(m_connectionThreadObject);
 
459
            m_registry->setEventQueue(m_eventQueue);
 
460
            // setup registry
 
461
            m_registry->create(m_display);
 
462
            m_registry->setup();
 
463
        },
 
464
        Qt::QueuedConnection);
 
465
    connect(m_connectionThreadObject, &ConnectionThread::connectionDied, this,
 
466
        [this]() {
 
467
            setReady(false);
 
468
            emit systemCompositorDied();
 
469
            m_seat.reset();
 
470
            m_shm->destroy();
 
471
            destroyOutputs();
 
472
            if (m_shellSurface) {
 
473
                m_shellSurface->destroy();
 
474
                delete m_shellSurface;
 
475
                m_shellSurface = nullptr;
 
476
            }
 
477
            m_fullscreenShell->destroy();
 
478
            if (m_surface) {
 
479
                m_surface->destroy();
 
480
                delete m_surface;
 
481
                m_surface = nullptr;
 
482
            }
 
483
            if (m_shell) {
 
484
                m_shell->destroy();
 
485
            }
 
486
            m_compositor->destroy();
 
487
            m_registry->destroy();
 
488
            m_eventQueue->destroy();
 
489
            if (m_display) {
 
490
                m_display = nullptr;
 
491
            }
 
492
        },
 
493
        Qt::QueuedConnection);
 
494
    connect(m_connectionThreadObject, &ConnectionThread::failed, this, &WaylandBackend::connectionFailed, Qt::QueuedConnection);
 
495
 
 
496
    m_connectionThread = new QThread(this);
 
497
    m_connectionThreadObject->moveToThread(m_connectionThread);
 
498
    m_connectionThread->start();
 
499
 
 
500
    m_connectionThreadObject->initConnection();
 
501
}
 
502
 
 
503
void WaylandBackend::installCursorImage(Qt::CursorShape shape)
 
504
{
 
505
    if (!m_seat.isNull() && m_seat->isInstallCursor()) {
 
506
        m_seat->installCursorImage(shape);
 
507
    } else if (m_cursor) {
 
508
        m_cursor->setCursorImage(shape);
 
509
    }
 
510
}
 
511
 
 
512
void WaylandBackend::installCursorFromServer()
 
513
{
 
514
    if (!waylandServer() || !waylandServer()->seat()->focusedPointer()) {
 
515
        return;
 
516
    }
 
517
    auto c = waylandServer()->seat()->focusedPointer()->cursor();
 
518
    if (c) {
 
519
        auto cursorSurface = c->surface();
 
520
        if (!cursorSurface.isNull()) {
 
521
            auto buffer = cursorSurface.data()->buffer();
 
522
            if (buffer) {
 
523
                // set cursor
 
524
                if (!m_seat.isNull() && m_seat->isInstallCursor()) {
 
525
                    m_seat->installCursorImage(buffer->data(), c->hotspot());
 
526
                } else if (m_cursor) {
 
527
                    m_cursor->setCursorImage(buffer->data(), c->hotspot());
 
528
                }
 
529
                return;
 
530
            }
 
531
        }
 
532
    }
 
533
    // TODO: unset cursor
 
534
}
 
535
 
 
536
void WaylandBackend::createSurface()
 
537
{
 
538
    m_surface = m_compositor->createSurface(this);
 
539
    if (!m_surface || !m_surface->isValid()) {
 
540
        qCCritical(KWIN_WAYLAND_BACKEND) << "Creating Wayland Surface failed";
 
541
        return;
 
542
    }
 
543
    if (m_subCompositor->isValid()) {
 
544
        // we have a sub compositor - let's use it for mouse cursor
 
545
        m_cursor = new WaylandCursor(m_surface, this);
 
546
    } else {
 
547
        // no sub-compositor - use the seat for setting the cursor image
 
548
        if (m_seat) {
 
549
            m_seat->setInstallCursor(true);
 
550
        }
 
551
    }
 
552
    if (m_fullscreenShell->isValid()) {
 
553
        Output *o = m_outputs.first();
 
554
        m_fullscreenShell->present(m_surface, o);
 
555
        if (o->pixelSize().isValid()) {
 
556
            emit shellSurfaceSizeChanged(o->pixelSize());
 
557
        }
 
558
        connect(o, &Output::changed, this,
 
559
            [this, o]() {
 
560
                if (o->pixelSize().isValid()) {
 
561
                    emit shellSurfaceSizeChanged(o->pixelSize());
 
562
                }
 
563
            }
 
564
        );
 
565
    } else if (m_shell->isValid()) {
 
566
        // map the surface as fullscreen
 
567
        m_shellSurface = m_shell->createSurface(m_surface, this);
 
568
        m_shellSurface->setFullscreen();
 
569
        connect(m_shellSurface, &ShellSurface::sizeChanged, this, &WaylandBackend::shellSurfaceSizeChanged);
 
570
    }
 
571
}
 
572
 
 
573
QSize WaylandBackend::shellSurfaceSize() const
 
574
{
 
575
    if (m_shellSurface) {
 
576
        return m_shellSurface->size();
 
577
    }
 
578
    if (m_fullscreenShell->isValid()) {
 
579
        return m_outputs.first()->pixelSize();
 
580
    }
 
581
    return QSize();
 
582
}
 
583
 
 
584
void WaylandBackend::checkBackendReady()
 
585
{
 
586
    if (!shellSurfaceSize().isValid()) {
 
587
        return;
 
588
    }
 
589
    disconnect(this, &WaylandBackend::shellSurfaceSizeChanged, this, &WaylandBackend::checkBackendReady);
 
590
    setReady(true);
 
591
}
 
592
 
 
593
Screens *WaylandBackend::createScreens(QObject *parent)
 
594
{
 
595
    return new WaylandScreens(this, parent);
 
596
}
 
597
 
 
598
OpenGLBackend *WaylandBackend::createOpenGLBackend()
 
599
{
 
600
#if HAVE_WAYLAND_EGL
 
601
    return new EglWaylandBackend(this);
 
602
#else
 
603
    return nullptr;
 
604
#endif
 
605
}
 
606
 
 
607
QPainterBackend *WaylandBackend::createQPainterBackend()
 
608
{
 
609
    return new WaylandQPainterBackend(this);
 
610
}
 
611
 
 
612
}
 
613
 
 
614
} // KWin