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);
347 QWaylandSurfacePrivate::get(childSurface)->initSubsurface(parentSurface, resource->client(), id, 1);
348 QWaylandSurfacePrivate::get(parentSurface)->subsurfaceChildren.append(childSurface);
349 emit q->subsurfaceChanged(childSurface, parentSurface);
380void QWaylandCompositorPrivate::initializeHardwareIntegration()
382 client_buffer_integrations.prepend(
new SharedMemoryClientBufferIntegration);
385 Q_Q(QWaylandCompositor);
386 if (use_hw_integration_extension)
387 hw_integration.reset(
new QtWayland::HardwareIntegration(q));
389 loadClientBufferIntegration();
390 loadServerBufferIntegration();
392 for (
auto *integration : std::as_const(client_buffer_integrations))
393 integration->initializeHardware(display);
403void QWaylandCompositorPrivate::loadClientBufferIntegration()
406 Q_Q(QWaylandCompositor);
407 QStringList keys = QtWayland::ClientBufferIntegrationFactory::keys();
408 QStringList targetKeys;
409 QByteArray clientBufferIntegration = qgetenv(
"QT_WAYLAND_HARDWARE_INTEGRATION");
410 if (clientBufferIntegration.isEmpty())
411 clientBufferIntegration = qgetenv(
"QT_WAYLAND_CLIENT_BUFFER_INTEGRATION");
413 const QList<QByteArray> clientBufferIntegrations = clientBufferIntegration.split(
';');
414 for (
const auto &b : clientBufferIntegrations) {
415 QString s = QString::fromLocal8Bit(b);
416 if (keys.contains(s))
417 targetKeys.append(s);
420 if (!clientBufferIntegration.isEmpty() && targetKeys.isEmpty()) {
421 qCWarning(qLcWaylandCompositorHardwareIntegration)
422 <<
"Failed to find any requested client buffer integration:"
423 << clientBufferIntegration
424 <<
", available integrations:"
428 if (targetKeys.isEmpty()) {
429 if (keys.contains(QString::fromLatin1(
"wayland-egl"))) {
430 targetKeys.append(QString::fromLatin1(
"wayland-egl"));
431 }
else if (!keys.isEmpty()) {
432 targetKeys.append(keys.first());
436 QString hwIntegrationName;
438 for (
const auto &targetKey : std::as_const(targetKeys)) {
439 auto *integration = QtWayland::ClientBufferIntegrationFactory::create(targetKey, QStringList());
441 integration->setCompositor(q);
442 client_buffer_integrations.append(integration);
443 if (hwIntegrationName.isEmpty())
444 hwIntegrationName = targetKey;
448 if (hw_integration && !hwIntegrationName.isEmpty())
449 hw_integration->setClientBufferIntegrationName(hwIntegrationName);
454void QWaylandCompositorPrivate::loadServerBufferIntegration()
457 Q_Q(QWaylandCompositor);
458 QStringList keys = QtWayland::ServerBufferIntegrationFactory::keys();
460 QByteArray serverBufferIntegration = qgetenv(
"QT_WAYLAND_SERVER_BUFFER_INTEGRATION");
461 if (keys.contains(QString::fromLocal8Bit(serverBufferIntegration.constData()))) {
462 targetKey = QString::fromLocal8Bit(serverBufferIntegration.constData());
464 if (!targetKey.isEmpty()) {
465 server_buffer_integration.reset(QtWayland::ServerBufferIntegrationFactory::create(targetKey, QStringList()));
466 if (server_buffer_integration) {
467 qCDebug(qLcWaylandCompositorHardwareIntegration)
468 <<
"Loaded server buffer integration:" << targetKey;
469 if (!server_buffer_integration->initializeHardware(q)) {
470 qCWarning(qLcWaylandCompositorHardwareIntegration)
471 <<
"Failed to initialize hardware for server buffer integration:" << targetKey;
472 server_buffer_integration.reset();
475 qCWarning(qLcWaylandCompositorHardwareIntegration)
476 <<
"Failed to load server buffer integration:" << targetKey;
480 if (server_buffer_integration && hw_integration)
481 hw_integration->setServerBufferIntegrationName(targetKey);
825void QWaylandCompositor::setDefaultOutput(QWaylandOutput *output)
827 Q_D(QWaylandCompositor);
828 if (Q_UNLIKELY(!output)) {
829 qWarning(
"Changing default output to null is not supported");
832 if (d->outputs.size() && d->outputs.first() == output)
834 bool alreadyAdded = d->outputs.removeOne(output);
835 d->outputs.prepend(output);
837 emit outputAdded(output);
838 emit defaultOutputChanged();
1042void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber,
const QWaylandBufferRef &buffer)
1044 if (buffer.isSharedMemory()) {
1045 emit grabber->success(buffer.image());
1047#if QT_CONFIG(opengl)
1048 if (QOpenGLContext::currentContext()) {
1049 QOpenGLFramebufferObject fbo(buffer.size());
1051 QOpenGLTextureBlitter blitter;
1055 glViewport(0, 0, buffer.size().width(), buffer.size().height());
1057 QOpenGLTextureBlitter::Origin surfaceOrigin =
1058 buffer.origin() == QWaylandSurface::OriginTopLeft
1059 ? QOpenGLTextureBlitter::OriginTopLeft
1060 : QOpenGLTextureBlitter::OriginBottomLeft;
1062 auto texture = buffer.toOpenGLTexture();
1063 blitter.bind(texture->target());
1064 blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
1067 emit grabber->success(fbo.toImage());
1070 emit grabber->failed(QWaylandSurfaceGrabber::UnknownBufferType);