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