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, 4);
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 (targetKeys.isEmpty()) {
419 if (keys.contains(QString::fromLatin1(
"wayland-egl"))) {
420 targetKeys.append(QString::fromLatin1(
"wayland-egl"));
421 }
else if (!keys.isEmpty()) {
422 targetKeys.append(keys.first());
426 QString hwIntegrationName;
428 for (
auto targetKey : std::as_const(targetKeys)) {
429 auto *integration = QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList());
431 integration->setCompositor(q);
432 client_buffer_integrations.append(integration);
433 if (hwIntegrationName.isEmpty())
434 hwIntegrationName = targetKey;
438 if (hw_integration && !hwIntegrationName.isEmpty())
439 hw_integration->setClientBufferIntegrationName(hwIntegrationName);
444void QWaylandCompositorPrivate::loadServerBufferIntegration()
447 Q_Q(QWaylandCompositor);
448 QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
450 QByteArray serverBufferIntegration = qgetenv(
"QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
451 if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
452 targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
454 if (!targetKey.isEmpty()) {
455 server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
456 if (server_buffer_integration) {
457 qCDebug(qLcWaylandCompositorHardwareIntegration)
458 <<
"Loaded server buffer integration:" << targetKey;
459 if (!server_buffer_integration->initializeHardware(q)) {
460 qCWarning(qLcWaylandCompositorHardwareIntegration)
461 <<
"Failed to initialize hardware for server buffer integration:" << targetKey;
462 server_buffer_integration.reset();
465 qCWarning(qLcWaylandCompositorHardwareIntegration)
466 <<
"Failed to load server buffer integration:" << targetKey;
470 if (server_buffer_integration && hw_integration)
471 hw_integration->setServerBufferIntegrationName(targetKey);
814void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
816 Q_D(QWaylandCompositor);
817 if (d->outputs.size() && d->outputs.first() == output)
819 bool alreadyAdded = d->outputs.removeOne(output);
820 d->outputs.prepend(output);
821 emit defaultOutputChanged();
823 emit outputAdded(output);
1019void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber,
const QWaylandBufferRef &buffer)
1021 if (buffer.isSharedMemory()) {
1022 emit grabber->success(buffer.image());
1024#if QT_CONFIG(opengl)
1025 if (QOpenGLContext::currentContext()) {
1026 QOpenGLFramebufferObject fbo(buffer.size());
1028 QOpenGLTextureBlitter blitter;
1032 glViewport(0, 0, buffer.size().width(), buffer.size().height());
1034 QOpenGLTextureBlitter::Origin surfaceOrigin =
1035 buffer.origin() == QWaylandSurface::OriginTopLeft
1036 ? QOpenGLTextureBlitter::OriginTopLeft
1037 : QOpenGLTextureBlitter::OriginBottomLeft;
1039 auto texture = buffer.toOpenGLTexture();
1040 blitter.bind(texture->target());
1041 blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
1044 emit grabber->success(fbo.toImage());
1047 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);