146QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
149 QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
151 if (QGuiApplication::platformNativeInterface())
152 display =
static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration(
"server_wl_display"));
155 display = wl_display_create();
159 eventHandler.reset(
new QtWayland::WindowSystemEventHandler(compositor));
162 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
164#if QT_CONFIG(xkbcommon)
165 mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
167 qWarning(
"Failed to create a XKB context: keymap will not be supported");
173void QWaylandCompositorPrivate::init()
175 Q_Q(QWaylandCompositor);
176 QStringList arguments = QCoreApplication::instance()->arguments();
178 if (socket_name.isEmpty()) {
179 const int socketArg = arguments.indexOf(QLatin1String(
"--wayland-socket-name"));
180 if (socketArg != -1 && socketArg + 1 < arguments.size())
181 socket_name = arguments.at(socketArg + 1).toLocal8Bit();
182 if (socket_name.isEmpty())
183 socket_name = qgetenv(
"WAYLAND_DISPLAY");
185 wl_compositor::init(display, 5);
186 wl_subcompositor::init(display, 1);
188#if QT_CONFIG(wayland_datadevice)
189 data_device_manager =
new QtWayland::DataDeviceManager(q);
191 buffer_manager =
new QtWayland::BufferManager(q);
193 wl_display_init_shm(display);
195 for (QWaylandCompositor::ShmFormat format : shmFormats)
196 wl_display_add_shm_format(display, wl_shm_format(format));
198 if (!socket_name.isEmpty()) {
199 if (wl_display_add_socket(display, socket_name.constData()))
200 qFatal(
"Fatal: Failed to open server socket: \"%s\". XDG_RUNTIME_DIR is: \"%s\"\n", socket_name.constData(), getenv(
"XDG_RUNTIME_DIR"));
202 const char *autoSocketName = wl_display_add_socket_auto(display);
204 qFatal(
"Fatal: Failed to open default server socket. XDG_RUNTIME_DIR is: \"%s\"\n", getenv(
"XDG_RUNTIME_DIR"));
205 socket_name = autoSocketName;
206 emit q->socketNameChanged(socket_name);
209 connectToExternalSockets();
211 loop = wl_display_get_event_loop(display);
213 int fd = wl_event_loop_get_fd(loop);
215 QSocketNotifier *sockNot =
new QSocketNotifier(fd, QSocketNotifier::Read, q);
216 QObject::connect(sockNot, SIGNAL(activated(QSocketDescriptor)), q, SLOT(processWaylandEvents()));
218 QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
219 QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));
221 QObject::connect(
static_cast<QGuiApplication *>(QGuiApplication::instance()),
222 &QGuiApplication::applicationStateChanged,
224 &QWaylandCompositor::applicationStateChanged);
226 initializeHardwareIntegration();
231 for (
const QPointer<QObject> &object : std::exchange(polish_objects, {})) {
233 QEvent polishEvent(QEvent::Polish);
234 QCoreApplication::sendEvent(object.data(), &polishEvent);
238 emit q->createdChanged();
241QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
244 const auto clientsToDelete = clients;
245 qDeleteAll(clientsToDelete);
247 const auto outputsToDelete = outputs;
248 qDeleteAll(outputsToDelete);
250#if QT_CONFIG(wayland_datadevice)
251 delete data_device_manager;
255 qDeleteAll(client_buffer_integrations);
258 wl_display_destroy(display);
314void QWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
316 Q_Q(QWaylandCompositor);
317 QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
318 emit q->surfaceRequested(client, id, resource->version());
320 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());
322 struct wl_resource *surfResource = wl_client_get_object(client->client(), id);
324 QWaylandSurface *surface =
nullptr;
326 surface = QWaylandSurface::fromResource(surfResource);
328 surface = createDefaultSurface();
329 surface->initialize(q, client, id, resource->version());
332 all_surfaces.append(surface);
333 emit q->surfaceCreated(surface);
341void QWaylandCompositorPrivate::subcompositor_get_subsurface(wl_subcompositor::Resource *resource, uint32_t id, wl_resource *surface, wl_resource *parent)
343 Q_Q(QWaylandCompositor);
344 QWaylandSurface *childSurface = QWaylandSurface::fromResource(surface);
345 QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent);
346 QWaylandSurfacePrivate::get(childSurface)->initSubsurface(parentSurface, resource->client(), id, 1);
347 QWaylandSurfacePrivate::get(parentSurface)->subsurfaceChildren.append(childSurface);
348 emit q->subsurfaceChanged(childSurface, parentSurface);
379void QWaylandCompositorPrivate::initializeHardwareIntegration()
381 client_buffer_integrations.prepend(
new SharedMemoryClientBufferIntegration);
384 Q_Q(QWaylandCompositor);
385 if (use_hw_integration_extension)
386 hw_integration.reset(
new QtWayland::HardwareIntegration(q));
388 loadClientBufferIntegration();
389 loadServerBufferIntegration();
391 for (
auto *integration : std::as_const(client_buffer_integrations))
392 integration->initializeHardware(display);
402void QWaylandCompositorPrivate::loadClientBufferIntegration()
405 Q_Q(QWaylandCompositor);
406 QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys();
407 QStringList targetKeys;
408 QByteArray clientBufferIntegration = qgetenv(
"QT_WAYLAND_HARDWARE_INTEGRATION");
409 if (clientBufferIntegration.isEmpty())
410 clientBufferIntegration = qgetenv(
"QT_WAYLAND_CLIENT_BUFFER_INTEGRATION");
412 for (
auto b : clientBufferIntegration.split(
';')) {
413 QString s = QString::fromLocal8Bit(b);
414 if (keys.contains(s))
415 targetKeys.append(s);
418 if (!clientBufferIntegration.isEmpty() && targetKeys.isEmpty()) {
419 qCWarning(qLcWaylandCompositorHardwareIntegration)
420 <<
"Failed to find any requested client buffer integration:"
421 << clientBufferIntegration
422 <<
", available integrations:"
426 if (targetKeys.isEmpty()) {
427 if (keys.contains(QString::fromLatin1(
"wayland-egl"))) {
428 targetKeys.append(QString::fromLatin1(
"wayland-egl"));
429 }
else if (!keys.isEmpty()) {
430 targetKeys.append(keys.first());
434 QString hwIntegrationName;
436 for (
auto targetKey : std::as_const(targetKeys)) {
437 auto *integration = QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList());
439 integration->setCompositor(q);
440 client_buffer_integrations.append(integration);
441 if (hwIntegrationName.isEmpty())
442 hwIntegrationName = targetKey;
446 if (hw_integration && !hwIntegrationName.isEmpty())
447 hw_integration->setClientBufferIntegrationName(hwIntegrationName);
452void QWaylandCompositorPrivate::loadServerBufferIntegration()
455 Q_Q(QWaylandCompositor);
456 QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
458 QByteArray serverBufferIntegration = qgetenv(
"QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
459 if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
460 targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
462 if (!targetKey.isEmpty()) {
463 server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
464 if (server_buffer_integration) {
465 qCDebug(qLcWaylandCompositorHardwareIntegration)
466 <<
"Loaded server buffer integration:" << targetKey;
467 if (!server_buffer_integration->initializeHardware(q)) {
468 qCWarning(qLcWaylandCompositorHardwareIntegration)
469 <<
"Failed to initialize hardware for server buffer integration:" << targetKey;
470 server_buffer_integration.reset();
473 qCWarning(qLcWaylandCompositorHardwareIntegration)
474 <<
"Failed to load server buffer integration:" << targetKey;
478 if (server_buffer_integration && hw_integration)
479 hw_integration->setServerBufferIntegrationName(targetKey);
822void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
824 Q_D(QWaylandCompositor);
825 if (Q_UNLIKELY(!output)) {
826 qWarning(
"Changing default output to null is not supported");
829 if (d->outputs.size() && d->outputs.first() == output)
831 bool alreadyAdded = d->outputs.removeOne(output);
832 d->outputs.prepend(output);
834 emit outputAdded(output);
835 emit defaultOutputChanged();
1031void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber,
const QWaylandBufferRef &buffer)
1033 if (buffer.isSharedMemory()) {
1034 emit grabber->success(buffer.image());
1036#if QT_CONFIG(opengl)
1037 if (QOpenGLContext::currentContext()) {
1038 QOpenGLFramebufferObject fbo(buffer.size());
1040 QOpenGLTextureBlitter blitter;
1044 glViewport(0, 0, buffer.size().width(), buffer.size().height());
1046 QOpenGLTextureBlitter::Origin surfaceOrigin =
1047 buffer.origin() == QWaylandSurface::OriginTopLeft
1048 ? QOpenGLTextureBlitter::OriginTopLeft
1049 : QOpenGLTextureBlitter::OriginBottomLeft;
1051 auto texture = buffer.toOpenGLTexture();
1052 blitter.bind(texture->target());
1053 blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
1056 emit grabber->success(fbo.toImage());
1059 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);