Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qt6 Removes X11Info from Qt5::X11Extras #60

Open
Zren opened this issue Jan 11, 2022 · 8 comments
Open

Qt6 Removes X11Info from Qt5::X11Extras #60

Zren opened this issue Jan 11, 2022 · 8 comments

Comments

@Zren
Copy link
Owner

Zren commented Jan 11, 2022

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 use QT += gui-private with qmake, or add a project dependency to Qt::GuiPrivate with CMake.

We use this class in:

  • Decoration::sendMoveEvent() and Decoration::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
Zren added a commit that referenced this issue Jan 11, 2022
I think you can only use them with Qt 5.15 and Kubuntu 20.04 only has
Qt 5.12.
Zren added a commit that referenced this issue Jan 19, 2022
@keithel
Copy link

keithel commented May 26, 2022

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]

@Zren
Copy link
Owner Author

Zren commented May 29, 2022

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:

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.

Looks like I'll need to have separate logic for Qt5 + Qt6.

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

@keithel
Copy link

keithel commented Jul 12, 2022

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.

@Zren
Copy link
Owner Author

Zren commented Jan 15, 2023

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

@keithel
Copy link

keithel commented Jan 17, 2023

You can do this, but it is kicking the can down the road. In Qt 7, qtx11extras_p.h won't exist.

@Zren
Copy link
Owner Author

Zren commented Aug 29, 2023

@guiodic
Copy link

guiodic commented Feb 29, 2024

Are there any instructions for compiling it with Qt6?

@guiodic
Copy link

guiodic commented Mar 7, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants