147QWaylandCompositorPrivate::QWaylandCompositorPrivate(QWaylandCompositor *compositor)
150 QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
152 if (QGuiApplication::platformNativeInterface())
153 display =
static_cast<wl_display*>(QGuiApplication::platformNativeInterface()->nativeResourceForIntegration(
"server_wl_display"));
156 display = wl_display_create();
160 eventHandler.reset(
new QtWayland::WindowSystemEventHandler(compositor));
163 QWindowSystemInterfacePrivate::installWindowSystemEventHandler(eventHandler.data());
165#if QT_CONFIG(xkbcommon)
166 mXkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_FLAGS));
168 qWarning(
"Failed to create a XKB context: keymap will not be supported");
174void QWaylandCompositorPrivate::init()
176 Q_Q(QWaylandCompositor);
177 QStringList arguments = QCoreApplication::instance()->arguments();
179 if (socket_name.isEmpty()) {
180 const int socketArg = arguments.indexOf(QLatin1String(
"--wayland-socket-name"));
181 if (socketArg != -1 && socketArg + 1 < arguments.size())
182 socket_name = arguments.at(socketArg + 1).toLocal8Bit();
183 if (socket_name.isEmpty())
184 socket_name = qgetenv(
"WAYLAND_DISPLAY");
186 wl_compositor::init(display, 5);
187 wl_subcompositor::init(display, 1);
189#if QT_CONFIG(wayland_datadevice)
190 data_device_manager =
new QtWayland::DataDeviceManager(q);
192 buffer_manager =
new QtWayland::BufferManager(q);
194 wl_display_init_shm(display);
196 for (QWaylandCompositor::ShmFormat format : std::as_const(shmFormats))
197 wl_display_add_shm_format(display, wl_shm_format(format));
199 if (!socket_name.isEmpty()) {
200 if (wl_display_add_socket(display, socket_name.constData()))
201 qFatal(
"Fatal: Failed to open server socket: \"%s\". XDG_RUNTIME_DIR is: \"%s\"\n", socket_name.constData(), getenv(
"XDG_RUNTIME_DIR"));
203 const char *autoSocketName = wl_display_add_socket_auto(display);
205 qFatal(
"Fatal: Failed to open default server socket. XDG_RUNTIME_DIR is: \"%s\"\n", getenv(
"XDG_RUNTIME_DIR"));
206 socket_name = autoSocketName;
207 emit q->socketNameChanged(socket_name);
210 connectToExternalSockets();
212 loop = wl_display_get_event_loop(display);
214 int fd = wl_event_loop_get_fd(loop);
216 QSocketNotifier *sockNot =
new QSocketNotifier(fd, QSocketNotifier::Read, q);
217 QObject::connect(sockNot, SIGNAL(activated(QSocketDescriptor)), q, SLOT(processWaylandEvents()));
219 QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher;
220 QObject::connect(dispatcher, SIGNAL(aboutToBlock()), q, SLOT(processWaylandEvents()));
222 QObject::connect(
static_cast<QGuiApplication *>(QGuiApplication::instance()),
223 &QGuiApplication::applicationStateChanged,
225 &QWaylandCompositor::applicationStateChanged);
227 initializeHardwareIntegration();
232 for (
const QPointer<QObject> &object : std::exchange(polish_objects, {})) {
234 QEvent polishEvent(QEvent::Polish);
235 QCoreApplication::sendEvent(object.data(), &polishEvent);
239 emit q->createdChanged();
242QWaylandCompositorPrivate::~QWaylandCompositorPrivate()
245 const auto clientsToDelete = clients;
246 qDeleteAll(clientsToDelete);
248 const auto outputsToDelete = outputs;
249 qDeleteAll(outputsToDelete);
251#if QT_CONFIG(wayland_datadevice)
252 delete data_device_manager;
256 qDeleteAll(client_buffer_integrations);
259 wl_display_destroy(display);
315void QWaylandCompositorPrivate::compositor_create_surface(wl_compositor::Resource *resource, uint32_t id)
317 Q_Q(QWaylandCompositor);
318 QWaylandClient *client = QWaylandClient::fromWlClient(q, resource->client());
319 emit q->surfaceRequested(client, id, resource->version());
321 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());
323 struct wl_resource *surfResource = wl_client_get_object(client->client(), id);
325 QWaylandSurface *surface =
nullptr;
327 surface = QWaylandSurface::fromResource(surfResource);
329 surface = createDefaultSurface();
330 surface->initialize(q, client, id, resource->version());
333 all_surfaces.append(surface);
334 emit q->surfaceCreated(surface);
342void QWaylandCompositorPrivate::subcompositor_get_subsurface(wl_subcompositor::Resource *resource, uint32_t id, wl_resource *surface, wl_resource *parent)
344 Q_Q(QWaylandCompositor);
345 QWaylandSurface *childSurface = QWaylandSurface::fromResource(surface);
346 QWaylandSurface *parentSurface = QWaylandSurface::fromResource(parent);
348 QWaylandSurfacePrivate *childSurface_d = QWaylandSurfacePrivate::get(childSurface);
349 QWaylandSurfacePrivate *parentSurface_d = QWaylandSurfacePrivate::get(parentSurface);
350 Q_ASSERT(childSurface_d !=
nullptr && parentSurface_d !=
nullptr);
354 for (QWaylandSurfacePrivate *ancestor = parentSurface_d;
356 ancestor = ancestor->parentSurface()) {
357 if (ancestor == childSurface_d) {
358 wl_resource_post_error(resource->handle,
359 WL_SUBCOMPOSITOR_ERROR_BAD_PARENT,
360 "surface cannot be made a transitive parent of itself");
365 QWaylandSurfacePrivate::get(childSurface)->initSubsurface(parentSurface, resource->client(), id, 1);
366 QWaylandSurfacePrivate::get(parentSurface)->subsurfaceChildren.append(childSurface);
367 emit q->subsurfaceChanged(childSurface, parentSurface);
398void QWaylandCompositorPrivate::initializeHardwareIntegration()
400 client_buffer_integrations.prepend(
new SharedMemoryClientBufferIntegration);
403 Q_Q(QWaylandCompositor);
404 if (use_hw_integration_extension)
405 hw_integration.reset(
new QtWayland::HardwareIntegration(q));
407 loadClientBufferIntegration();
408 loadServerBufferIntegration();
410 for (
auto *integration : std::as_const(client_buffer_integrations))
411 integration->initializeHardware(display);
421void QWaylandCompositorPrivate::loadClientBufferIntegration()
424 Q_Q(QWaylandCompositor);
425 QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys();
426 QStringList targetKeys;
427 QByteArray clientBufferIntegration = qgetenv(
"QT_WAYLAND_HARDWARE_INTEGRATION");
428 if (clientBufferIntegration.isEmpty())
429 clientBufferIntegration = qgetenv(
"QT_WAYLAND_CLIENT_BUFFER_INTEGRATION");
431 const QList<QByteArray> clientBufferIntegrations = clientBufferIntegration.split(
';');
432 for (
const auto &b : clientBufferIntegrations) {
433 QString s = QString::fromLocal8Bit(b);
434 if (keys.contains(s))
435 targetKeys.append(s);
438 if (!clientBufferIntegration.isEmpty() && targetKeys.isEmpty()) {
439 qCWarning(qLcWaylandCompositorHardwareIntegration)
440 <<
"Failed to find any requested client buffer integration:"
441 << clientBufferIntegration
442 <<
", available integrations:"
446 if (targetKeys.isEmpty()) {
447 if (keys.contains(QString::fromLatin1(
"wayland-egl"))) {
448 targetKeys.append(QString::fromLatin1(
"wayland-egl"));
449 }
else if (!keys.isEmpty()) {
450 targetKeys.append(keys.first());
454 QString hwIntegrationName;
456 for (
const auto &targetKey : std::as_const(targetKeys)) {
457 auto *integration = QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList());
459 integration->setCompositor(q);
460 client_buffer_integrations.append(integration);
461 if (hwIntegrationName.isEmpty())
462 hwIntegrationName = targetKey;
466 if (hw_integration && !hwIntegrationName.isEmpty())
467 hw_integration->setClientBufferIntegrationName(hwIntegrationName);
472void QWaylandCompositorPrivate::loadServerBufferIntegration()
475 Q_Q(QWaylandCompositor);
476 QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
478 QByteArray serverBufferIntegration = qgetenv(
"QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
479 if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
480 targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
482 if (!targetKey.isEmpty()) {
483 server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
484 if (server_buffer_integration) {
485 qCDebug(qLcWaylandCompositorHardwareIntegration)
486 <<
"Loaded server buffer integration:" << targetKey;
487 if (!server_buffer_integration->initializeHardware(q)) {
488 qCWarning(qLcWaylandCompositorHardwareIntegration)
489 <<
"Failed to initialize hardware for server buffer integration:" << targetKey;
490 server_buffer_integration.reset();
493 qCWarning(qLcWaylandCompositorHardwareIntegration)
494 <<
"Failed to load server buffer integration:" << targetKey;
498 if (server_buffer_integration && hw_integration)
499 hw_integration->setServerBufferIntegrationName(targetKey);
843void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
845 Q_D(QWaylandCompositor);
846 if (Q_UNLIKELY(!output)) {
847 qWarning(
"Changing default output to null is not supported");
850 if (d->outputs.size() && d->outputs.first() == output)
852 bool alreadyAdded = d->outputs.removeOne(output);
853 d->outputs.prepend(output);
855 emit outputAdded(output);
856 emit defaultOutputChanged();
1060void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber,
const QWaylandBufferRef &buffer)
1062 if (buffer.isSharedMemory()) {
1063 emit grabber->success(buffer.image());
1065#if QT_CONFIG(opengl)
1066 if (QOpenGLContext::currentContext()) {
1067 QOpenGLFramebufferObject fbo(buffer.size());
1069 QOpenGLTextureBlitter blitter;
1073 glViewport(0, 0, buffer.size().width(), buffer.size().height());
1075 QOpenGLTextureBlitter::Origin surfaceOrigin =
1076 buffer.origin() == QWaylandSurface::OriginTopLeft
1077 ? QOpenGLTextureBlitter::OriginTopLeft
1078 : QOpenGLTextureBlitter::OriginBottomLeft;
1080 auto texture = buffer.toOpenGLTexture();
1081 blitter.bind(texture->target());
1082 blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
1085 emit grabber->success(fbo.toImage());
1088 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);