material-decoration
material-decoration copied to clipboard
Qt6 Removes X11Info from Qt5::X11Extras
Changes to Qt X11 Extras
The
QX11Info
class has been removed.Clients that still rely on the functionality can include the private header
<QtGui/private/qtx11extras_p.h>
as a stopgap solution. To enable private headers useQT += gui-private
withqmake
, or add a project dependency toQt::GuiPrivate
with CMake.
- https://doc.qt.io/qt-6/extras-changes-qt6.html#changes-to-qt-x11-extras
- https://doc.qt.io/qt-5/qtx11extras-index.html
- https://doc.qt.io/qt-5/qx11info.html
We use this class in:
-
Decoration::sendMoveEvent()
andDecoration::windowPos()
to get the global cursor pos for a drag -
AppMenuModel::onWinIdChanged()
to get the x11 window properties to know the dbus interface - Some unused commented out code in
AppMenuButtonGroup
I think I can help answer how to fix this the "correct" way without having to access private headers that could go away at any time.
These places you mention all need access to the xcb_connection_t *
for the Display. QX11Info
had an accessor to get that directly, but in Qt 6, the only thing that is provided is access to the Display *
. However the means to access the Display *
is substantially different from Qt 5:
QNativeInterface::QX11Application *x11App = qApp->nativeInterface<QNativeInterface::QX11Application>();
Display *displayID = x11App->display();
To get the xcb_connection_t *
, I think you follow https://xcb.freedesktop.org/MixingCalls/ like so (this is untested - I'm just going from the aforementioned page:
#include <X11/Xlib-xcb.h>
[...]
QNativeInterface::QX11Application *x11App = qApp->nativeInterface<QNativeInterface::QX11Application>();
Display *displayID = x11App->display();
xcb_connection_t *c;
c = XGetXCBConnection(dpy);
[do your stuff that needs xcb_connection_t]
- https://doc.qt.io/qt-6/qguiapplication.html#nativeInterface
- https://doc.qt.io/qt-6/qnativeinterface-qx11application.html
There's a connection()
function. Do I need display() => Display
then XGetXCBConnection(Display) => xcb_connection_t
? There shouldn't be multiple connections for each display right?
Here's how QX11Info::connection()
works:
- Qt 6.0 dev https://github.com/qt/qtbase/blame/dev/src/gui/platform/unix/qtx11extras.cpp#L327
- Qt 5.15 https://github.com/qt/qtx11extras/blame/5.15/src/x11extras/qx11info_x11.cpp#L374-L384
xcb_connection_t *QX11Info::connection()
{
if (!qApp)
return nullptr;
QPlatformNativeInterface *native = qApp->platformNativeInterface();
if (!native)
return nullptr;
void *connection = native->nativeResourceForIntegration(QByteArray("connection"));
return reinterpret_cast<xcb_connection_t *>(connection);
}
The new Qt6 API:
Note, this is not backwards compatible, as QGuiApplication::nativeInterface()
is not in Qt5? In Qt5 there is QGuiApplication::platformNativeInterface()
but it's even less documented.
- https://doc.qt.io/qt-5/qguiapplication.html#platformNativeInterface
Looks like I'll need to have separate logic for Qt5 + Qt6.
- https://github.com/qt/qtbase/blame/dev/src/gui/kernel/qguiapplication_platform.h#L36
- https://github.com/qt/qtbase/blame/dev/src/plugins/platforms/xcb/qxcbnativeinterface.cpp#L342-L346
- https://github.com/qt/qtbase/blame/dev/src/plugins/platforms/xcb/qxcbintegration.h#L85
- https://github.com/qt/qtbase/blame/dev/src/plugins/platforms/xcb/qxcbconnection_basic.h#L35
- https://github.com/qt/qtbase/blame/dev/src/plugins/platforms/xcb/qxcbconnection_basic.cpp#L87
QXcbBasicConnection::QXcbBasicConnection(const char *displayName)
: m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
{
#if QT_CONFIG(xcb_xlib)
Display *dpy = XOpenDisplay(m_displayName.constData());
if (dpy) {
m_primaryScreenNumber = DefaultScreen(dpy);
m_xcbConnection = XGetXCBConnection(dpy);
XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
XSetErrorHandler(nullErrorHandler);
XSetIOErrorHandler(ioErrorHandler);
m_xlibDisplay = dpy;
}
#else
m_xcbConnection = xcb_connect(m_displayName.constData(), &m_primaryScreenNumber);
#endif
Hmm Not sure where I had in my head that there was no connection method... I see now that it's there...
You're definitely right that in Qt5 QGuiApplication::platformNativeInterface() is severely undocumented (but at least they show it exists in the docs!).
Here is the header for it: https://github.com/qt/qtbase/blob/v5.15.5-lts-lgpl/src/gui/kernel/qplatformnativeinterface.h
And here's the XCB implementation. https://github.com/qt/qtbase/blob/v5.15.5-lts-lgpl/src/plugins/platforms/xcb/qxcbnativeinterface.h
in a #if Q_OS_LINUX
block, you can use qobject_cast<QXcbNativeInterface *>
and then access the methods there.
You'll need to have separate Qt5 and Qt6 implementations for this to work, as far as I understand - but it'll be using stable APIs that won't change on you. I think there's a good chance that the QX11Info private APIs will be removed at some point in the near future.
TODO: I need to add #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
check to use #include <private/qtx11extras_p.h>
.
https://invent.kde.org/plasma/breeze/-/commit/59142d5b800703986c1f4f71ab150bf4b4b23f3a#0f8721806070aa2f5fd1a8c2d4f6c865f35f96ab_27_27
#if BREEZE_HAVE_QTX11EXTRAS
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <private/qtx11extras_p.h>
#else
#include <QX11Info>
#endif
#endif
You can do this, but it is kicking the can down the road. In Qt 7, qtx11extras_p.h
won't exist.
https://doc.qt.io/qt-6/extras-changes-qt6.html#changes-to-qt-x11-extras
Are there any instructions for compiling it with Qt6?
i tried to build with Qt6 but i receive this error:
CMake Error at CMakeLists.txt:24 (find_package):
Found package configuration file:
/usr/lib/cmake/Qt6/Qt6Config.cmake
but it set Qt6_FOUND to FALSE so package "Qt6" is considered to be NOT
FOUND. Reason given by package:
Failed to find required Qt component "GuiPrivate".
Expected Config file at
"/usr/lib/cmake/Qt6GuiPrivate/Qt6GuiPrivateConfig.cmake" does NOT exist
Configuring with --debug-find-pkg=Qt6GuiPrivate might reveal details why
the package was not found.
Configuring with -DQT_DEBUG_FIND_PACKAGE=ON will print the values of some
of the path variables that find_package uses to try and find the package.