16#if QT_CONFIG(draganddrop)
21#ifndef QT_NO_SESSIONMANAGER
28#include <QtGui/private/qgenericunixfontdatabase_p.h>
29#include <QtGui/private/qdesktopunixservices_p.h>
33#include <QtGui/private/qguiapplication_p.h>
35#if QT_CONFIG(xcb_xlib)
40#if QT_CONFIG(xcb_native_painting)
41#include "qxcbnativepainting.h"
42#include "qpixmap_x11_p.h"
43#include "qbackingstore_x11_p.h"
46#include <qpa/qplatforminputcontextfactory_p.h>
47#include <private/qgenericunixtheme_p.h>
49#include <private/qkdetheme_p.h>
51#include <qpa/qplatforminputcontext.h>
53#include <QtGui/QOpenGLContext>
54#include <QtGui/QScreen>
55#include <QtGui/QOffscreenSurface>
56#if QT_CONFIG(accessibility)
57#include <qpa/qplatformaccessibility.h>
58#if QT_CONFIG(accessibility_atspi_bridge)
59#include <QtGui/private/qspiaccessiblebridge_p.h>
63#include <QtCore/QFileInfo>
66#include "qxcbvulkaninstance.h"
67#include "qxcbvulkanwindow.h"
72using namespace Qt::StringLiterals;
78#if defined(Q_OS_LINUX)
79 const QString parentProc =
"/proc/"_L1 + QString::number(getppid());
80 const QFileInfo parentProcExe(parentProc +
"/exe"_L1);
81 if (parentProcExe.isSymLink())
82 return parentProcExe.symLinkTarget().endsWith(
"/gdb"_L1);
83 QFile f(parentProc +
"/cmdline"_L1);
84 if (!f.open(QIODevice::ReadOnly))
88 while (f.getChar(&c) && c) {
109QXcbIntegration *QXcbIntegration::m_instance =
nullptr;
111QXcbIntegration::QXcbIntegration(
const QStringList ¶meters,
int &argc,
char **argv)
112 : m_services(
new QXcbUnixServices)
113 , m_instanceName(
nullptr)
115 , m_defaultVisualId(UINT_MAX)
117 Q_UNUSED(parameters);
120 qApp->setAttribute(Qt::AA_CompressHighFrequencyEvents,
true);
122 qRegisterMetaType<QXcbWindow*>();
123#if QT_CONFIG(xcb_xlib)
126 m_nativeInterface.reset(
new QXcbNativeInterface);
129 const char *displayName =
nullptr;
130 bool noGrabArg =
false;
131 bool doGrabArg =
false;
134 for (
int i = 1; i < argc; i++) {
135 QByteArray arg(argv[i]);
136 if (arg.startsWith(
"--"))
138 if (arg ==
"-display" && i < argc - 1)
139 displayName = argv[++i];
140 else if (arg ==
"-name" && i < argc - 1)
141 m_instanceName = argv[++i];
142 else if (arg ==
"-nograb")
144 else if (arg ==
"-dograb")
146 else if (arg ==
"-visual" && i < argc - 1) {
148 m_defaultVisualId = QByteArray(argv[++i]).toUInt(&ok, 0);
150 m_defaultVisualId = UINT_MAX;
158 bool underDebugger = runningUnderDebugger();
159 if (noGrabArg && doGrabArg && underDebugger) {
160 qWarning(
"Both -nograb and -dograb command line arguments specified. Please pick one. -nograb takes precedence");
164 if (!noGrabArg && !doGrabArg && underDebugger) {
165 qCDebug(lcQpaXcb,
"Qt: gdb: -nograb added to command-line options.\n"
166 "\t Use the -dograb option to enforce grabbing.");
168 m_canGrab = (!underDebugger && !noGrabArg) || (underDebugger && doGrabArg);
170 static bool canNotGrabEnv = qEnvironmentVariableIsSet(
"QT_XCB_NO_GRAB_SERVER");
174 m_connection =
new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, displayName);
175 if (!m_connection->isConnected()) {
177 m_connection =
nullptr;
180 m_services->setConnection(m_connection);
182 m_fontDatabase.reset(
new QGenericUnixFontDatabase());
184#if QT_CONFIG(xcb_native_painting)
185 if (nativePaintingEnabled()) {
186 qCDebug(lcQpaXcb,
"QXCB USING NATIVE PAINTING");
187 qt_xcb_native_x11_info_init(connection());
192QXcbIntegration::~QXcbIntegration()
195 m_connection =
nullptr;
196 m_instance =
nullptr;
199QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type)
const
201#if QT_CONFIG(xcb_native_painting)
202 if (nativePaintingEnabled())
203 return new QX11PlatformPixmap(type);
206 return QPlatformIntegration::createPlatformPixmap(type);
209QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window)
const
211 QXcbGlIntegration *glIntegration =
nullptr;
212 const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);
213 if (!isTrayIconWindow) {
214 if (window->supportsOpenGL()) {
215 glIntegration = connection()->glIntegration();
217 QXcbWindow *xcbWindow = glIntegration->createWindow(window);
222 }
else if (window->surfaceType() == QSurface::VulkanSurface) {
223 QXcbWindow *xcbWindow =
new QXcbVulkanWindow(window);
230 Q_ASSERT(isTrayIconWindow || !window->supportsOpenGL()
231 || (!glIntegration && window->surfaceType() == QSurface::RasterSurface));
232 QXcbWindow *xcbWindow =
new QXcbWindow(window);
237QPlatformWindow *QXcbIntegration::createForeignWindow(QWindow *window, WId nativeHandle)
const
239 return new QXcbForeignWindow(window, nativeHandle);
243QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context)
const
245 QXcbGlIntegration *glIntegration = m_connection->glIntegration();
246 if (!glIntegration) {
247 qWarning(
"QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled");
250 return glIntegration->createPlatformOpenGLContext(context);
253# if QT_CONFIG(xcb_glx_plugin)
254QOpenGLContext *QXcbIntegration::createOpenGLContext(GLXContext context,
void *visualInfo, QOpenGLContext *shareContext)
const
256 using namespace QNativeInterface::Private;
257 if (
auto *glxIntegration =
dynamic_cast<QGLXIntegration*>(m_connection->glIntegration()))
258 return glxIntegration->createOpenGLContext(context, visualInfo, shareContext);
265QOpenGLContext *QXcbIntegration::createOpenGLContext(EGLContext context, EGLDisplay display, QOpenGLContext *shareContext)
const
267 using namespace QNativeInterface::Private;
268 if (
auto *eglIntegration =
dynamic_cast<QEGLIntegration*>(m_connection->glIntegration()))
269 return eglIntegration->createOpenGLContext(context, display, shareContext);
277QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *window)
const
279 QPlatformBackingStore *backingStore =
nullptr;
281 const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);
282 if (isTrayIconWindow) {
283 backingStore =
new QXcbSystemTrayBackingStore(window);
284#if QT_CONFIG(xcb_native_painting)
285 }
else if (nativePaintingEnabled()) {
286 backingStore =
new QXcbNativeBackingStore(window);
289 backingStore =
new QXcbBackingStore(window);
291 Q_ASSERT(backingStore);
295QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface)
const
297 QXcbScreen *screen =
static_cast<QXcbScreen *>(surface->screen()->handle());
298 QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
299 if (!glIntegration) {
300 qWarning(
"QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled");
303 return glIntegration->createPlatformOffscreenSurface(surface);
306bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap)
const
312 if (
const auto *integration = connection()->glIntegration())
313 return cap != ThreadedOpenGL || integration->supportsThreadedOpenGL();
317 case ThreadedPixmaps:
319 case MultipleWindows:
324 case SwitchableWidgetComposition:
326 return m_connection->glIntegration()
327 && m_connection->glIntegration()->supportsSwitchableWidgetComposition();
330 default:
return QPlatformIntegration::hasCapability(cap);
334QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher()
const
336 return QXcbEventDispatcher::createEventDispatcher(connection());
345void QXcbIntegration::initialize()
347 const auto defaultInputContext =
"compose"_L1;
350 auto icStrs = QPlatformInputContextFactory::requested();
351 if (icStrs.isEmpty())
352 icStrs = { defaultInputContext };
353 m_inputContext.reset(QPlatformInputContextFactory::create(icStrs));
354 if (!m_inputContext && !icStrs.contains(defaultInputContext)
355 && icStrs != QStringList{
"none"_L1})
356 m_inputContext.reset(QPlatformInputContextFactory::create(defaultInputContext));
358 connection()->keyboard()->initialize();
360 auto notifyThemeChanged = [](QXcbVirtualDesktop *,
const QByteArray &,
const QVariant &,
void *) {
361 QWindowSystemInterface::handleThemeChange();
364 auto *xsettings = connection()->primaryScreen()->xSettings();
365 xsettings->registerCallbackForProperty(xsNetCursorBlink, notifyThemeChanged,
this);
366 xsettings->registerCallbackForProperty(xsNetCursorBlinkTime, notifyThemeChanged,
this);
367 xsettings->registerCallbackForProperty(xsNetDoubleClickTime, notifyThemeChanged,
this);
368 xsettings->registerCallbackForProperty(xsNetDoubleClickDistance, notifyThemeChanged,
this);
369 xsettings->registerCallbackForProperty(xsNetDndDragThreshold, notifyThemeChanged,
this);
372void QXcbIntegration::moveToScreen(QWindow *window,
int screen)
378QPlatformFontDatabase *QXcbIntegration::fontDatabase()
const
380 return m_fontDatabase.data();
383QPlatformNativeInterface * QXcbIntegration::nativeInterface()
const
385 return m_nativeInterface.data();
388#ifndef QT_NO_CLIPBOARD
389QPlatformClipboard *QXcbIntegration::clipboard()
const
391 return m_connection->clipboard();
395#if QT_CONFIG(draganddrop)
396#include <private/qsimpledrag_p.h>
397QPlatformDrag *QXcbIntegration::drag()
const
399 static const bool useSimpleDrag = qEnvironmentVariableIsSet(
"QT_XCB_USE_SIMPLE_DRAG");
400 if (Q_UNLIKELY(useSimpleDrag)) {
401 static QSimpleDrag *simpleDrag =
nullptr;
403 simpleDrag =
new QSimpleDrag();
407 return m_connection->drag();
411QPlatformInputContext *QXcbIntegration::inputContext()
const
413 return m_inputContext.data();
416#if QT_CONFIG(accessibility)
417QPlatformAccessibility *QXcbIntegration::accessibility()
const
419#if !defined(QT_NO_ACCESSIBILITY_ATSPI_BRIDGE)
420 if (!m_accessibility) {
421 Q_ASSERT_X(QCoreApplication::eventDispatcher(),
"QXcbIntegration",
422 "Initializing accessibility without event-dispatcher!");
423 m_accessibility.reset(
new QSpiAccessibleBridge());
427 return m_accessibility.data();
431QPlatformServices *QXcbIntegration::services()
const
433 return m_services.data();
436QPlatformKeyMapper *QXcbIntegration::keyMapper()
const
438 return m_connection->keyboard();
441QStringList QXcbIntegration::themeNames()
const
443 return QGenericUnixTheme::themeNames();
446QPlatformTheme *QXcbIntegration::createPlatformTheme(
const QString &name)
const
448 return QGenericUnixTheme::createUnixTheme(name);
451#define RETURN_VALID_XSETTINGS(key) {
452 auto value = connection()->primaryScreen()->xSettings()->setting(key);
453 if (value.isValid()) return value; \
454}
456QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint)
const
459 case QPlatformIntegration::CursorFlashTime: {
462 if (connection()->primaryScreen()->xSettings()->setting(xsNetCursorBlink).toInt(&ok) == 0 && ok)
468 case QPlatformIntegration::MouseDoubleClickInterval:
471 case QPlatformIntegration::MouseDoubleClickDistance:
474 case QPlatformIntegration::KeyboardInputInterval:
475 case QPlatformIntegration::StartDragTime:
476 case QPlatformIntegration::KeyboardAutoRepeatRate:
477 case QPlatformIntegration::PasswordMaskDelay:
478 case QPlatformIntegration::StartDragVelocity:
479 case QPlatformIntegration::UseRtlExtensions:
480 case QPlatformIntegration::PasswordMaskCharacter:
481 case QPlatformIntegration::FlickMaximumVelocity:
482 case QPlatformIntegration::FlickDeceleration:
485 case QPlatformIntegration::FlickStartDistance:
486 case QPlatformIntegration::StartDragDistance: {
491 if (
const QXcbScreen *screen = connection()->primaryScreen()) {
492 if (screen->logicalDpi().first > dpi)
493 dpi = screen->logicalDpi().first;
494 if (screen->logicalDpi().second > dpi)
495 dpi = screen->logicalDpi().second;
497 return (hint == QPlatformIntegration::FlickStartDistance ? qreal(15) : qreal(10)) * dpi / qreal(100);
499 case QPlatformIntegration::ShowIsFullScreen:
503 case QPlatformIntegration::ReplayMousePressOutsidePopup:
508 return QPlatformIntegration::styleHint(hint);
514 const QStringList arguments = QCoreApplication::arguments();
515 if (!arguments.isEmpty() && !arguments.front().isEmpty()) {
516 result = arguments.front();
517 const int lastSlashPos = result.lastIndexOf(u'/');
518 if (lastSlashPos != -1)
519 result.remove(0, lastSlashPos + 1);
526QByteArray QXcbIntegration::wmClass()
const
528 if (m_wmClass.isEmpty()) {
532 name = QString::fromLocal8Bit(m_instanceName);
533 if (name.isEmpty() && qEnvironmentVariableIsSet(resourceNameVar))
534 name = qEnvironmentVariable(resourceNameVar);
536 name = argv0BaseName();
540 QString className = QCoreApplication::applicationName();
541 if (className.isEmpty()) {
542 className = argv0BaseName();
543 if (!className.isEmpty() && className.at(0).isLower())
544 className[0] = className.at(0).toUpper();
547 if (!name.isEmpty() && !className.isEmpty())
548 m_wmClass = std::move(name).toLocal8Bit() +
'\0' + std::move(className).toLocal8Bit() +
'\0';
554QPlatformSessionManager *QXcbIntegration::createPlatformSessionManager(
const QString &id,
const QString &key)
const
556 return new QXcbSessionManager(id, key);
560void QXcbIntegration::sync()
562 m_connection->sync();
566void QXcbIntegration::beep()
const
568 QScreen *priScreen = QGuiApplication::primaryScreen();
571 QPlatformScreen *screen = priScreen->handle();
574 xcb_connection_t *connection =
static_cast<QXcbScreen *>(screen)->xcb_connection();
575 xcb_bell(connection, 0);
576 xcb_flush(connection);
579bool QXcbIntegration::nativePaintingEnabled()
const
581#if QT_CONFIG(xcb_native_painting)
582 static bool enabled = qEnvironmentVariableIsSet(
"QT_XCB_NATIVE_PAINTING");
590QPlatformVulkanInstance *QXcbIntegration::createPlatformVulkanInstance(QVulkanInstance *instance)
const
592 return new QXcbVulkanInstance(instance);
596void QXcbIntegration::setApplicationBadge(qint64 number)
598 auto unixServices =
dynamic_cast<QDesktopUnixServices *>(services());
599 unixServices->setApplicationBadge(number);
604 return "x11:"_L1 + QString::number(window->winId(), 16);
609 const QByteArray serviceValue = service.toLatin1();
610 const QByteArray pathValue = path.toLatin1();
613 XCB_PROP_MODE_REPLACE, window->winId(),
616 serviceValue.length(),
617 serviceValue.constData());
620 XCB_PROP_MODE_REPLACE, window->winId(),
624 pathValue.constData());
@ Atom_KDE_NET_WM_APPMENU_SERVICE_NAME
@ Atom_KDE_NET_WM_APPMENU_OBJECT_PATH
xcb_connection_t * xcb_connection() const
xcb_atom_t atom(QXcbAtom::Atom atom) const
QString portalWindowIdentifier(QWindow *window) override
void unregisterDBusMenuForWindow(QWindow *window) override
void registerDBusMenuForWindow(QWindow *window, const QString &service, const QString &path) override
static const auto xsNetDoubleClickDistance
static QString argv0BaseName()
static const auto xsNetCursorBlink
static const auto xsNetDoubleClickTime
static bool runningUnderDebugger()
static const auto xsNetDndDragThreshold
static const auto xsNetCursorBlinkTime
#define RETURN_VALID_XSETTINGS(key)
static const char resourceNameVar[]