1 /****************************************************************************
2 **
3 ** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
4 ** Copyright (C) 2017 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:GPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU
20 ** General Public License version 3 or (at your option) any later version
21 ** approved by the KDE Free Qt Foundation. The licenses are as published by
22 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
23 ** included in the packaging of this file. Please review the following
24 ** information to ensure the GNU General Public License requirements will
25 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
26 **
27 ** $QT_END_LICENSE$
28 **
29 ****************************************************************************/
30 
31 #include "qtwaylandcompositorglobal_p.h"
32 #include "qwaylandcompositor.h"
33 #include "qwaylandcompositor_p.h"
34 
35 #include <QtWaylandCompositor/qwaylandclient.h>
36 #include <QtWaylandCompositor/qwaylandseat.h>
37 #include <QtWaylandCompositor/qwaylandoutput.h>
38 #include <QtWaylandCompositor/qwaylandview.h>
39 #include <QtWaylandCompositor/qwaylandclient.h>
40 #include <QtWaylandCompositor/qwaylandkeyboard.h>
41 #include <QtWaylandCompositor/qwaylandpointer.h>
42 #include <QtWaylandCompositor/qwaylandtouch.h>
43 #include <QtWaylandCompositor/qwaylandsurfacegrabber.h>
44 
45 #include <QtWaylandCompositor/private/qwaylandkeyboard_p.h>
46 #include <QtWaylandCompositor/private/qwaylandsurface_p.h>
47 
48 #if QT_CONFIG(wayland_datadevice)
49 #include "wayland_wrapper/qwldatadevice_p.h"
50 #include "wayland_wrapper/qwldatadevicemanager_p.h"
51 #endif
52 #include "wayland_wrapper/qwlbuffermanager_p.h"
53 
54 #include "hardware_integration/qwlclientbufferintegration_p.h"
55 #include "hardware_integration/qwlclientbufferintegrationfactory_p.h"
56 #include "hardware_integration/qwlserverbufferintegration_p.h"
57 #include "hardware_integration/qwlserverbufferintegrationfactory_p.h"
58 
59 #if QT_CONFIG(opengl)
60 #include "hardware_integration/qwlhwintegration_p.h"
61 #endif
62 
63 #include "extensions/qwaylandqtwindowmanager.h"
64 
65 #include "qwaylandsharedmemoryformathelper_p.h"
66 
67 #include <QtCore/QCoreApplication>
68 #include <QtCore/QStringList>
69 #include <QtCore/QSocketNotifier>
70 
71 #include <QtGui/QDesktopServices>
72 #include <QtGui/QScreen>
73 
74 #include <QtGui/qpa/qwindowsysteminterface_p.h>
75 #include <QtGui/qpa/qplatformnativeinterface.h>
76 #include <QtGui/private/qguiapplication_p.h>
77 
78 #if QT_CONFIG(opengl)
79 #   include <QOpenGLTextureBlitter>
80 #   include <QOpenGLTexture>
81 #   include <QOpenGLContext>
82 #   include <QOpenGLFramebufferObject>
83 #   include <QMatrix4x4>
84 #endif
85 
86 QT_BEGIN_NAMESPACE
87 
88 Q_LOGGING_CATEGORY(qLcWaylandCompositor, "qt.waylandcompositor")
89 Q_LOGGING_CATEGORY(qLcWaylandCompositorHardwareIntegration, "qt.waylandcompositor.hardwareintegration")
90 Q_LOGGING_CATEGORY(qLcWaylandCompositorInputMethods, "qt.waylandcompositor.inputmethods")
91 
92 namespace QtWayland {
93 
94 class WindowSystemEventHandler : public QWindowSystemEventHandler
95 {
96 public:
WindowSystemEventHandler(QWaylandCompositor * c)97     WindowSystemEventHandler(QWaylandCompositor *c) : compositor(c) {}
sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent * e)98     bool sendEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) override
99     {
100         if (e->type == QWindowSystemInterfacePrivate::Key) {
101             QWindowSystemInterfacePrivate::KeyEvent *keyEvent = static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e);
102             handleKeyEvent(keyEvent);
103         } else {
104             QWindowSystemEventHandler::sendEvent(e);
105         }
106         return true;
107     }
108 
handleKeyEvent(QWindowSystemInterfacePrivate::KeyEvent * ke)109     void handleKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *ke)
110     {
111         auto *seat = compositor->defaultSeat();
112         if (!seat)
113             return;
114 
115         QWaylandKeyboardPrivate *keyb = QWaylandKeyboardPrivate::get(seat->keyboard());
116 
117 #if defined(Q_OS_QNX)
118         // The QNX platform plugin delivers scan codes that haven't been adjusted to be
119         // xkbcommon compatible. xkbcommon requires that the scan codes be bumped up by
120         // 8 because that's how evdev/XKB deliver scan codes. You might think that it
121         // would've been better to remove this (odd) requirement from xkbcommon on QNX
122         // but it turns out that conforming to it has much less impact.
123         static int offset = QGuiApplication::platformName() == QStringLiteral("qnx") ? 8 : 0;
124         ke->nativeScanCode += offset;
125 #endif
126         uint32_t code = ke->nativeScanCode;
127         bool isDown = ke->keyType == QEvent::KeyPress;
128 
129 #if QT_CONFIG(xkbcommon)
130         xkb_state *xkbState = keyb->xkbState();
131         Qt::KeyboardModifiers modifiers = QXkbCommon::modifiers(xkbState);
132 
133         const xkb_keysym_t sym = xkb_state_key_get_one_sym(xkbState, code);
134         int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, xkbState, code);
135         QString text = QXkbCommon::lookupString(xkbState, code);
136 
137         ke->key = qtkey;
138         ke->modifiers = modifiers;
139         ke->nativeVirtualKey = sym;
140         ke->nativeModifiers = keyb->xkbModsMask();
141         ke->unicode = text;
142 #endif
143         if (!ke->repeat)
144             keyb->keyEvent(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
145 
146         QWindowSystemEventHandler::sendEvent(ke);
147 
148         if (!ke->repeat) {
149             keyb->maybeUpdateKeymap();
150             keyb->updateModifierState(code, isDown ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED);
151         }
152     }
153 
154     QWaylandCompositor *compositor = nullptr;
155 };
156 
157 } // namespace
158 
QWaylandCompositorPrivate(QWaylandCompositor * compositor)159 QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
160 {
161     if (QGuiApplication::platformNativeInterface())
162         display = static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration("server_wl_display"));
163 
164     if (!display) {
165         display = wl_display_create();
166         ownsDisplay = true;
167     }
168 
169     eventHandler.reset(new QtWayland::WindowSystemEventHandler(compositor));
170     timer.start();
171 
172     QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
173 
174 #if QT_CONFIG(xkbcommon)
175     mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
176     if (!mXkbContext) {
177         qWarning("Failed to create a XKB context: keymap will not be supported");
178         return;
179     }
180 #endif
181 }
182 
init()183 void QWaylandCompositorPrivate::init()
184 {
185     Q_Q(QWaylandCompositor);
186     QStringList arguments = QCoreApplication::instance()->arguments();
187 
188     if (socket_name.isEmpty()) {
189         const int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name"));
190         if (socketArg != -1 && socketArg + 1 < arguments.size())
191             socket_name = arguments.at(socketArg + 1).toLocal8Bit();
192     }
193     wl_compositor::init(display, 3);
194     wl_subcompositor::init(display, 1);
195 
196 #if QT_CONFIG(wayland_datadevice)
197     data_device_manager =  new QtWayland::DataDeviceManager(q);
198 #endif
199     buffer_manager = new QtWayland::BufferManager(q);
200 
201     wl_display_init_shm(display);
202     const QVector<wl_shm_format> formats = QWaylandSharedMemoryFormatHelper::supportedWaylandFormats();
203     for (wl_shm_format format : formats)
204         wl_display_add_shm_format(display, format);
205 
206     if (!socket_name.isEmpty()) {
207         if (wl_display_add_socket(display, socket_name.constData()))
208             qFatal("Fatal: Failed to open server socket: \"%s\". XDG_RUNTIME_DIR is: \"%s\"\n", socket_name.constData(), getenv("XDG_RUNTIME_DIR"));
209     } else {
210         const char *autoSocketName = wl_display_add_socket_auto(display);
211         if (!autoSocketName)
212             qFatal("Fatal: Failed to open default server socket. XDG_RUNTIME_DIR is: \"%s\"\n", getenv("XDG_RUNTIME_DIR"));
213         socket_name = autoSocketName;
214         emit q->socketNameChanged(socket_name);
215     }
216 
217 #if WAYLAND_VERSION_MAJOR >= 1 && (WAYLAND_VERSION_MAJOR != 1 || WAYLAND_VERSION_MINOR >= 10)
218     connectToExternalSockets();
219 #endif
220 
221     loop = wl_display_get_event_loop(display);
222 
223     int fd = wl_event_loop_get_fd(loop);
224 
225     QSocketNotifier *sockNot = new QSocketNotifier(fd, QSocketNotifier::Read, q);
226     QObject::connect(sockNot, SIGNAL(activated(QSocketDescriptor)), q, SLOT(processWaylandEvents()));
227 
228     QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
229     QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));
230 
231     initializeHardwareIntegration();
232     initializeSeats();
233 
234     initialized = true;
235 
236     for (const QPointer<QObject> &object : qExchange(polish_objects, {})) {
237         if (object) {
238             QEvent polishEvent(QEvent::Polish);
239             QCoreApplication::sendEvent(object.data(), &polishEvent);
240         }
241     }
242 
243     emit q->createdChanged();
244 }
245 
~QWaylandCompositorPrivate()246 QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
247 {
248     // Take copies, since the lists will get modified as elements are deleted
249     const auto clientsToDelete = clients;
250     qDeleteAll(clientsToDelete);
251 
252     const auto outputsToDelete = outputs;
253     qDeleteAll(outputsToDelete);
254 
255 #if QT_CONFIG(wayland_datadevice)
256     delete data_device_manager;
257 #endif
258 
259 #if QT_CONFIG(opengl)
260     // Some client buffer integrations need to clean up before the destroying the wl_display
261     client_buffer_integration.reset();
262 #endif
263 
264     if (ownsDisplay)
265         wl_display_destroy(display);
266 }
267 
preInit()268 void QWaylandCompositorPrivate::preInit()
269 {
270     Q_Q(QWaylandCompositor);
271 
272     if (preInitialized)
273         return;
274 
275     if (seats.empty())
276         seats.append(q->createSeat());
277 
278     preInitialized = true;
279 }
280 
destroySurface(QWaylandSurface * surface)281 void QWaylandCompositorPrivate::destroySurface(QWaylandSurface *surface)
282 {
283     Q_Q(QWaylandCompositor);
284     q->surfaceAboutToBeDestroyed(surface);
285 
286     delete surface;
287 }
288 
unregisterSurface(QWaylandSurface * surface)289 void QWaylandCompositorPrivate::unregisterSurface(QWaylandSurface *surface)
290 {
291     if (!all_surfaces.removeOne(surface))
292         qWarning("%s Unexpected state. Cant find registered surface\n", Q_FUNC_INFO);
293 }
294 
feedRetainedSelectionData(QMimeData * data)295 void QWaylandCompositorPrivate::feedRetainedSelectionData(QMimeData *data)
296 {
297     Q_Q(QWaylandCompositor);
298     if (retainSelection)
299         q->retainedSelectionReceived(data);
300 }
301 
addPolishObject(QObject * object)302 void QWaylandCompositorPrivate::addPolishObject(QObject *object)
303 {
304     if (initialized) {
305         QCoreApplication::postEvent(object, new QEvent(QEvent::Polish));
306     } else {
307         polish_objects.push_back(object);
308     }
309 }
310 
311 #if WAYLAND_VERSION_MAJOR >= 1 && (WAYLAND_VERSION_MAJOR != 1 || WAYLAND_VERSION_MINOR >= 10)
connectToExternalSockets()312 void QWaylandCompositorPrivate::connectToExternalSockets()
313 {
314     // Clear out any backlog of user-supplied external socket descriptors
315     for (int fd : qAsConst(externally_added_socket_fds)) {
316         if (wl_display_add_socket_fd(display, fd) != 0)
317             qWarning() << "Failed to integrate user-supplied socket fd into the Wayland event loop";
318     }
319     externally_added_socket_fds.clear();
320 }
321 #endif
322 
compositor_create_surface(wl_compositor::Resource * resource,uint32_t id)323 void QWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
324 {
325     Q_Q(QWaylandCompositor);
326     QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
327     emit q->surfaceRequested(client, id, resource->version());
328 #ifndef QT_NO_DEBUG
329     Q_ASSERT_X(!QWaylandSurfacePrivate::hasUninitializedSurface(), "QWaylandCompositor", QStringLiteral("Found uninitialized QWaylandSurface after emitting QWaylandCompositor::createSurface for id %1. All surfaces has to be initialized immediately after creation. See QWaylandSurface::initialize.").arg(id).toLocal8Bit().constData());
330 #endif
331     struct wl_resource *surfResource = wl_client_get_object(client->client(), id);
332 
333     QWaylandSurface *surface = nullptr;
334     if (surfResource) {
335         surface = QWaylandSurface::fromResource(surfResource);
336     } else {
337         surface = createDefaultSurface();
338         surface->initialize(q, client, id, resource->version());
339     }
340     Q_ASSERT(surface);
341     all_surfaces.append(surface);
342     emit q->surfaceCreated(surface);
343 }
344 
compositor_create_region(wl_compositor::Resource * resource,uint32_t id)345 void QWaylandCompositorPrivate::compositor_create_region(wl_compositor::Resource *resource, uint32_t id)
346 {
347     new QtWayland::Region(resource->client(), id);
348 }
349 
subcompositor_get_subsurface(wl_subcompositor::Resource * resource,uint32_t id,wl_resource * surface,wl_resource * parent)350 void QWaylandCompositorPrivate::subcompositor_get_subsurface(wl_subcompositor::Resource *resource, uint32_t id, wl_resource *surface, wl_resource *parent)
351 {
352     Q_Q(QWaylandCompositor);
353     QWaylandSurface *childSurface = QWaylandSurface::fromResource(surface);
354     QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent);
355     QWaylandSurfacePrivate::get(childSurface)->initSubsurface(parentSurface, resource->client(), id, 1);
356     QWaylandSurfacePrivate::get(parentSurface)->subsurfaceChildren.append(childSurface);
357     emit q->subsurfaceChanged(childSurface, parentSurface);
358 }
359 
360 /*!
361   \internal
362   Used to create a fallback QWaylandSurface when no surface was
363   created by emitting the QWaylandCompositor::createSurface signal.
364 */
createDefaultSurface()365 QWaylandSurface *QWaylandCompositorPrivate::createDefaultSurface()
366 {
367     return new QWaylandSurface();
368 }
369 
370 
initializeHardwareIntegration()371 void QWaylandCompositorPrivate::initializeHardwareIntegration()
372 {
373 #if QT_CONFIG(opengl)
374     Q_Q(QWaylandCompositor);
375     if (use_hw_integration_extension)
376         hw_integration.reset(new QtWayland::HardwareIntegration(q));
377 
378     loadClientBufferIntegration();
379     loadServerBufferIntegration();
380 
381     if (client_buffer_integration)
382         client_buffer_integration->initializeHardware(display);
383 #endif
384 }
385 
initializeSeats()386 void QWaylandCompositorPrivate::initializeSeats()
387 {
388     for (QWaylandSeat *seat : qAsConst(seats))
389         seat->initialize();
390 }
391 
loadClientBufferIntegration()392 void QWaylandCompositorPrivate::loadClientBufferIntegration()
393 {
394 #if QT_CONFIG(opengl)
395     Q_Q(QWaylandCompositor);
396     QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys();
397     QString targetKey;
398     QByteArray clientBufferIntegration = qgetenv("QT_WAYLAND_HARDWARE_INTEGRATION");
399     if (clientBufferIntegration.isEmpty())
400         clientBufferIntegration = qgetenv("QT_WAYLAND_CLIENT_BUFFER_INTEGRATION");
401     if (keys.contains(QString::fromLocal8Bit(clientBufferIntegration.constData()))) {
402         targetKey = QString::fromLocal8Bit(clientBufferIntegration.constData());
403     } else if (keys.contains(QString::fromLatin1("wayland-egl"))) {
404         targetKey = QString::fromLatin1("wayland-egl");
405     } else if (!keys.isEmpty()) {
406         targetKey = keys.first();
407     }
408 
409     if (!targetKey.isEmpty()) {
410         client_buffer_integration.reset(QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList()));
411         if (client_buffer_integration) {
412             client_buffer_integration->setCompositor(q);
413             if (hw_integration)
414                 hw_integration->setClientBufferIntegration(targetKey);
415         }
416     }
417     //BUG: if there is no client buffer integration, bad things will happen when opengl is used
418 #endif
419 }
420 
loadServerBufferIntegration()421 void QWaylandCompositorPrivate::loadServerBufferIntegration()
422 {
423 #if QT_CONFIG(opengl)
424     Q_Q(QWaylandCompositor);
425     QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
426     QString targetKey;
427     QByteArray serverBufferIntegration = qgetenv("QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
428     if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
429         targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
430     }
431     if (!targetKey.isEmpty()) {
432         server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
433         if (server_buffer_integration) {
434             qCDebug(qLcWaylandCompositorHardwareIntegration)
435                     << "Loaded server buffer integration:" << targetKey;
436             if (!server_buffer_integration->initializeHardware(q)) {
437                 qCWarning(qLcWaylandCompositorHardwareIntegration)
438                         << "Failed to initialize hardware for server buffer integration:" << targetKey;
439                 server_buffer_integration.reset();
440             }
441         } else {
442             qCWarning(qLcWaylandCompositorHardwareIntegration)
443                     << "Failed to load server buffer integration:" << targetKey;
444         }
445     }
446 
447     if (server_buffer_integration && hw_integration)
448         hw_integration->setServerBufferIntegration(targetKey);
449 #endif
450 }
451 
452 /*!
453   \qmltype WaylandCompositor
454   \inqmlmodule QtWayland.Compositor
455   \since 5.8
456   \brief Manages the Wayland display server.
457 
458   The WaylandCompositor manages the connections to the clients, as well as the different
459   \l{WaylandOutput}{outputs} and \l{QWaylandSeat}{seats}.
460 
461   Normally, a compositor application will have a single WaylandCompositor
462   instance, which can have several outputs as children. When a client
463   requests the compositor to create a surface, the request is handled by
464   the onSurfaceRequested handler.
465 
466   Extensions that are supported by the compositor should be instantiated and added to the
467   extensions property.
468 */
469 
470 
471 /*!
472    \class QWaylandCompositor
473    \inmodule QtWaylandCompositor
474    \since 5.8
475    \brief The QWaylandCompositor class manages the Wayland display server.
476 
477    The QWaylandCompositor manages the connections to the clients, as well as the different \l{QWaylandOutput}{outputs}
478    and \l{QWaylandSeat}{seats}.
479 
480    Normally, a compositor application will have a single WaylandCompositor
481    instance, which can have several outputs as children.
482 */
483 
484 /*!
485   \qmlsignal void QtWaylandCompositor::WaylandCompositor::surfaceRequested(WaylandClient client, int id, int version)
486 
487   This signal is emitted when a \a client has created a surface with id \a id.
488   The interface \a version is also available.
489 
490   The slot connecting to this signal may create and initialize a WaylandSurface
491   instance in the scope of the slot. Otherwise a default surface is created.
492 */
493 
494 /*!
495   \fn void QWaylandCompositor::surfaceRequested(QWaylandClient *client, uint id, int version)
496 
497   This signal is emitted when a \a client has created a surface with id \a id.
498   The interface \a version is also available.
499 
500   The slot connecting to this signal may create and initialize a QWaylandSurface
501   instance in the scope of the slot. Otherwise a default surface is created.
502 
503   Connections to this signal must be of Qt::DirectConnection connection type.
504 */
505 
506 /*!
507   \qmlsignal void QtWaylandCompositor::WaylandCompositor::surfaceCreated(WaylandSurface surface)
508 
509   This signal is emitted when a new WaylandSurface instance \a surface has been created.
510 */
511 
512 /*!
513   \fn void QWaylandCompositor::surfaceCreated(QWaylandSurface *surface)
514 
515   This signal is emitted when a new QWaylandSurface instance \a surface has been created.
516 */
517 
518 /*!
519  * Constructs a QWaylandCompositor with the given \a parent.
520  */
QWaylandCompositor(QObject * parent)521 QWaylandCompositor::QWaylandCompositor(QObject *parent)
522     : QWaylandObject(*new QWaylandCompositorPrivate(this), parent)
523 {
524 }
525 
526 /*!
527  * \internal
528  * Constructs a QWaylandCompositor with the private object \a dptr and \a parent.
529  */
QWaylandCompositor(QWaylandCompositorPrivate & dptr,QObject * parent)530 QWaylandCompositor::QWaylandCompositor(QWaylandCompositorPrivate &dptr, QObject *parent)
531     : QWaylandObject(dptr, parent)
532 {
533 }
534 
535 /*!
536  * Destroys the QWaylandCompositor
537  */
~QWaylandCompositor()538 QWaylandCompositor::~QWaylandCompositor()
539 {
540 }
541 
542 /*!
543  * Initializes the QWaylandCompositor.
544  * If you override this function in your subclass, be sure to call the base class implementation.
545  */
create()546 void QWaylandCompositor::create()
547 {
548     Q_D(QWaylandCompositor);
549     d->preInit();
550     d->init();
551 }
552 
553 /*!
554  * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::created
555  *
556  * This property is true if WaylandCompositor has been initialized,
557  * otherwise it's false.
558  */
559 
560 /*!
561  * \property QWaylandCompositor::created
562  *
563  * This property is true if QWaylandCompositor has been initialized,
564  * otherwise it's false.
565  */
isCreated() const566 bool QWaylandCompositor::isCreated() const
567 {
568     Q_D(const QWaylandCompositor);
569     return d->initialized;
570 }
571 
572 /*!
573  * \qmlproperty string QtWaylandCompositor::WaylandCompositor::socketName
574  *
575  * This property holds the socket name used by WaylandCompositor to communicate with
576  * clients. It must be set before the component is completed.
577  *
578  * If the socketName is empty (the default), the contents of the start argument
579  * \c --wayland-socket-name are used instead. If the argument is not set, the
580  * compositor tries to find a socket name, which is \c{wayland-0} by default.
581  */
582 
583 /*!
584  * \property QWaylandCompositor::socketName
585  *
586  * This property holds the socket name used by QWaylandCompositor to communicate with
587  * clients. This must be set before the QWaylandCompositor is \l{create()}{created}.
588  *
589  * If the socketName is empty (the default), the contents of the start argument
590  * \c --wayland-socket-name are used instead. If the argument is not set, the
591  * compositor tries to find a socket name, which is \c{wayland-0} by default.
592  */
setSocketName(const QByteArray & name)593 void QWaylandCompositor::setSocketName(const QByteArray &name)
594 {
595     Q_D(QWaylandCompositor);
596 
597     if (d->socket_name == name)
598         return;
599 
600     if (d->initialized) {
601         qWarning("%s: Changing socket name after initializing the compositor is not supported.\n", Q_FUNC_INFO);
602         return;
603     }
604 
605     d->socket_name = name;
606     emit socketNameChanged(name);
607 }
608 
socketName() const609 QByteArray QWaylandCompositor::socketName() const
610 {
611     Q_D(const QWaylandCompositor);
612     return d->socket_name;
613 }
614 
615 /*!
616  * \qmlmethod QtWaylandCompositor::WaylandCompositor::addSocketDescriptor(fd)
617  * \since 5.12
618  *
619  * Listen for client connections on a file descriptor, \a fd, referring to a
620  * server socket already bound and listening.
621  *
622  * Does not take ownership of the file descriptor; it must be closed
623  * explicitly if needed.
624  *
625  * \note This method is only available with libwayland 1.10.0 or
626  * newer. If built against an earlier libwayland runtime, this
627  * method is a noop.
628  */
629 
630 /*!
631  * Listen for client connections on a file descriptor, \a fd, referring to a
632  * server socket already bound and listening.
633  *
634  * Does not take ownership of the file descriptor; it must be closed
635  * explicitly if needed.
636  *
637  * \note This method is only available with libwayland 1.10.0 or
638  * newer. If built against an earlier libwayland runtime, this
639  * method is a noop.
640  *
641  * \since 5.12
642  */
addSocketDescriptor(int fd)643 void QWaylandCompositor::addSocketDescriptor(int fd)
644 {
645 #if WAYLAND_VERSION_MAJOR >= 1 && (WAYLAND_VERSION_MAJOR != 1 || WAYLAND_VERSION_MINOR >= 10)
646     Q_D(QWaylandCompositor);
647     d->externally_added_socket_fds.append(fd);
648     if (isCreated())
649         d->connectToExternalSockets();
650 #else
651     Q_UNUSED(fd);
652     qWarning() << "QWaylandCompositor::addSocketDescriptor() does nothing on libwayland versions prior to 1.10.0";
653 #endif
654 }
655 
656 /*!
657  * \internal
658  */
display() const659 struct wl_display *QWaylandCompositor::display() const
660 {
661     Q_D(const QWaylandCompositor);
662     return d->display;
663 }
664 
665 /*!
666  * \internal
667  */
nextSerial()668 uint32_t QWaylandCompositor::nextSerial()
669 {
670     Q_D(QWaylandCompositor);
671     return wl_display_next_serial(d->display);
672 }
673 
674 /*!
675  * \internal
676  */
clients() const677 QList<QWaylandClient *>QWaylandCompositor::clients() const
678 {
679     Q_D(const QWaylandCompositor);
680     return d->clients;
681 }
682 
683 /*!
684  * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClientForSurface(surface)
685  *
686  * Destroys the client for the WaylandSurface \a surface.
687  */
688 
689 /*!
690  * Destroys the client for the \a surface.
691  */
destroyClientForSurface(QWaylandSurface * surface)692 void QWaylandCompositor::destroyClientForSurface(QWaylandSurface *surface)
693 {
694     destroyClient(surface->client());
695 }
696 
697 /*!
698  * \qmlmethod QtWaylandCompositor::WaylandCompositor::destroyClient(client)
699  *
700  * Destroys the given WaylandClient \a client.
701  */
702 
703 /*!
704  * Destroys the \a client.
705  */
destroyClient(QWaylandClient * client)706 void QWaylandCompositor::destroyClient(QWaylandClient *client)
707 {
708     if (!client)
709         return;
710 
711     QWaylandQtWindowManager *wmExtension = QWaylandQtWindowManager::findIn(this);
712     if (wmExtension)
713         wmExtension->sendQuitMessage(client);
714 
715     wl_client_destroy(client->client());
716 }
717 
718 /*!
719  * \internal
720  */
surfacesForClient(QWaylandClient * client) const721 QList<QWaylandSurface *> QWaylandCompositor::surfacesForClient(QWaylandClient* client) const
722 {
723     Q_D(const QWaylandCompositor);
724     QList<QWaylandSurface *> surfs;
725     for (QWaylandSurface *surface : d->all_surfaces) {
726         if (surface->client() == client)
727             surfs.append(surface);
728     }
729     return surfs;
730 }
731 
732 /*!
733  * \internal
734  */
surfaces() const735 QList<QWaylandSurface *> QWaylandCompositor::surfaces() const
736 {
737     Q_D(const QWaylandCompositor);
738     return d->all_surfaces;
739 }
740 
741 /*!
742  * Returns the QWaylandOutput that is connected to the given \a window.
743  */
outputFor(QWindow * window) const744 QWaylandOutput *QWaylandCompositor::outputFor(QWindow *window) const
745 {
746     Q_D(const QWaylandCompositor);
747     for (QWaylandOutput *output : d->outputs) {
748         if (output->window() == window)
749             return output;
750     }
751 
752     return nullptr;
753 }
754 
755 /*!
756  * \qmlproperty WaylandOutput QtWaylandCompositor::WaylandCompositor::defaultOutput
757  *
758  * This property contains the first in the list of outputs added to the
759  * WaylandCompositor, or null if no outputs have been added.
760  *
761  * Setting a new default output prepends it to the output list, making
762  * it the new default, but the previous default is not removed from
763  * the list.
764  */
765 /*!
766  * \property QWaylandCompositor::defaultOutput
767  *
768  * This property contains the first in the list of outputs added to the
769  * QWaylandCompositor, or null if no outputs have been added.
770  *
771  * Setting a new default output prepends it to the output list, making
772  * it the new default, but the previous default is not removed from
773  * the list. If the new default output was already in the list of outputs,
774  * it is moved to the beginning of the list.
775  */
defaultOutput() const776 QWaylandOutput *QWaylandCompositor::defaultOutput() const
777 {
778     Q_D(const QWaylandCompositor);
779     return d->defaultOutput();
780 }
781 
setDefaultOutput(QWaylandOutput * output)782 void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
783 {
784     Q_D(QWaylandCompositor);
785     if (d->outputs.size() && d->outputs.first() == output)
786         return;
787     bool alreadyAdded = d->outputs.removeOne(output);
788     d->outputs.prepend(output);
789     emit defaultOutputChanged();
790     if (!alreadyAdded)
791         emit outputAdded(output);
792 }
793 
794 /*!
795  * \internal
796  */
outputs() const797 QList<QWaylandOutput *> QWaylandCompositor::outputs() const
798 {
799     Q_D(const QWaylandCompositor);
800     return d->outputs;
801 }
802 
803 /*!
804  * \internal
805  */
currentTimeMsecs() const806 uint QWaylandCompositor::currentTimeMsecs() const
807 {
808     Q_D(const QWaylandCompositor);
809     return d->timer.elapsed();
810 }
811 
812 /*!
813  * \internal
814  */
processWaylandEvents()815 void QWaylandCompositor::processWaylandEvents()
816 {
817     Q_D(QWaylandCompositor);
818     int ret = wl_event_loop_dispatch(d->loop, 0);
819     if (ret)
820         fprintf(stderr, "wl_event_loop_dispatch error: %d\n", ret);
821     wl_display_flush_clients(d->display);
822 }
823 
824 /*!
825  * \internal
826  */
createSeat()827 QWaylandSeat *QWaylandCompositor::createSeat()
828 {
829     return new QWaylandSeat(this);
830 }
831 
832 /*!
833  * \internal
834  */
createPointerDevice(QWaylandSeat * seat)835 QWaylandPointer *QWaylandCompositor::createPointerDevice(QWaylandSeat *seat)
836 {
837     return new QWaylandPointer(seat);
838 }
839 
840 /*!
841  * \internal
842  */
createKeyboardDevice(QWaylandSeat * seat)843 QWaylandKeyboard *QWaylandCompositor::createKeyboardDevice(QWaylandSeat *seat)
844 {
845     return new QWaylandKeyboard(seat);
846 }
847 
848 /*!
849  * \internal
850  */
createTouchDevice(QWaylandSeat * seat)851 QWaylandTouch *QWaylandCompositor::createTouchDevice(QWaylandSeat *seat)
852 {
853     return new QWaylandTouch(seat);
854 }
855 
856 /*!
857  * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::retainedSelection
858  *
859  * This property holds whether retained selection is enabled.
860  */
861 
862 /*!
863  * \property QWaylandCompositor::retainedSelection
864  *
865  * This property holds whether retained selection is enabled.
866  */
setRetainedSelectionEnabled(bool enabled)867 void QWaylandCompositor::setRetainedSelectionEnabled(bool enabled)
868 {
869     Q_D(QWaylandCompositor);
870 
871     if (d->retainSelection == enabled)
872         return;
873 
874     d->retainSelection = enabled;
875     emit retainedSelectionChanged(enabled);
876 }
877 
retainedSelectionEnabled() const878 bool QWaylandCompositor::retainedSelectionEnabled() const
879 {
880     Q_D(const QWaylandCompositor);
881     return d->retainSelection;
882 }
883 
884 /*!
885  * \internal
886  */
retainedSelectionReceived(QMimeData *)887 void QWaylandCompositor::retainedSelectionReceived(QMimeData *)
888 {
889 }
890 
891 /*!
892  * \internal
893  */
overrideSelection(const QMimeData * data)894 void QWaylandCompositor::overrideSelection(const QMimeData *data)
895 {
896     Q_D(QWaylandCompositor);
897 #if QT_CONFIG(wayland_datadevice)
898     d->data_device_manager->overrideSelection(*data);
899 #endif
900 }
901 
902 /*!
903  * \qmlproperty WaylandSeat QtWaylandCompositor::WaylandCompositor::defaultSeat
904  *
905  * This property contains the default seat for this
906  * WaylandCompositor.
907  */
908 
909 /*!
910  * \property QWaylandCompositor::defaultSeat
911  *
912  * This property contains the default seat for this
913  * QWaylandCompositor.
914  */
defaultSeat() const915 QWaylandSeat *QWaylandCompositor::defaultSeat() const
916 {
917     Q_D(const QWaylandCompositor);
918     if (d->seats.size())
919         return d->seats.first();
920     return nullptr;
921 }
922 
923 /*!
924  * \internal
925  *
926  * Currently, Qt only supports a single seat, so this exists for
927  * future proofing the APIs.
928  */
seatFor(QInputEvent * inputEvent)929 QWaylandSeat *QWaylandCompositor::seatFor(QInputEvent *inputEvent)
930 {
931     Q_D(QWaylandCompositor);
932     QWaylandSeat *dev = nullptr;
933     for (int i = 0; i < d->seats.size(); i++) {
934         QWaylandSeat *candidate = d->seats.at(i);
935         if (candidate->isOwner(inputEvent)) {
936             dev = candidate;
937             break;
938         }
939     }
940     return dev;
941 }
942 
943 /*!
944  * \qmlproperty bool QtWaylandCompositor::WaylandCompositor::useHardwareIntegrationExtension
945  *
946  * This property holds whether the hardware integration extension should be enabled for
947  * this WaylandCompositor.
948  *
949  * This property must be set before the compositor component is completed.
950  */
951 
952 /*!
953  * \property QWaylandCompositor::useHardwareIntegrationExtension
954  *
955  * This property holds whether the hardware integration extension should be enabled for
956  * this QWaylandCompositor.
957  *
958  * This property must be set before the compositor is \l{create()}{created}.
959  */
useHardwareIntegrationExtension() const960 bool QWaylandCompositor::useHardwareIntegrationExtension() const
961 {
962 #if QT_CONFIG(opengl)
963     Q_D(const QWaylandCompositor);
964     return d->use_hw_integration_extension;
965 #else
966     return false;
967 #endif
968 }
969 
setUseHardwareIntegrationExtension(bool use)970 void QWaylandCompositor::setUseHardwareIntegrationExtension(bool use)
971 {
972 #if QT_CONFIG(opengl)
973     Q_D(QWaylandCompositor);
974     if (use == d->use_hw_integration_extension)
975         return;
976 
977     if (d->initialized)
978         qWarning("Setting QWaylandCompositor::useHardwareIntegrationExtension after initialization has no effect");
979 
980     d->use_hw_integration_extension = use;
981     useHardwareIntegrationExtensionChanged();
982 #else
983     if (use)
984         qWarning() << "Hardware integration not supported without OpenGL support";
985 #endif
986 }
987 
988 /*!
989  * Grab the surface content from the given \a buffer.
990  * The default implementation requires a OpenGL context to be bound to the current thread
991  * to work. If this is not possible, reimplement this function in your compositor subclass
992  * to implement custom logic.
993  * The default implementation only grabs shared memory and OpenGL buffers, reimplement this in your
994  * compositor subclass to handle more buffer types.
995  * \note You should not call this manually, but rather use QWaylandSurfaceGrabber (\a grabber).
996  */
grabSurface(QWaylandSurfaceGrabber * grabber,const QWaylandBufferRef & buffer)997 void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWaylandBufferRef &buffer)
998 {
999     if (buffer.isSharedMemory()) {
1000         emit grabber->success(buffer.image());
1001     } else {
1002 #if QT_CONFIG(opengl)
1003         if (QOpenGLContext::currentContext()) {
1004             QOpenGLFramebufferObject fbo(buffer.size());
1005             fbo.bind();
1006             QOpenGLTextureBlitter blitter;
1007             blitter.create();
1008 
1009 
1010             glViewport(0, 0, buffer.size().width(), buffer.size().height());
1011 
1012             QOpenGLTextureBlitter::Origin surfaceOrigin =
1013                 buffer.origin() == QWaylandSurface::OriginTopLeft
1014                 ? QOpenGLTextureBlitter::OriginTopLeft
1015                 : QOpenGLTextureBlitter::OriginBottomLeft;
1016 
1017             auto texture = buffer.toOpenGLTexture();
1018             blitter.bind(texture->target());
1019             blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
1020             blitter.release();
1021 
1022             emit grabber->success(fbo.toImage());
1023         } else
1024 #endif
1025         emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);
1026     }
1027 }
1028 
1029 QT_END_NAMESPACE
1030