What is New in Qt 5.1: X11 Extras

What's New in Qt 5.1: X11 Extras

By Jeff Tranter

This is the first in a series of blog postings that will discuss some of the notable new features in the Qt 5.1 release. The Qt 5.1 release will contain a new module known as X11 Extras. This module provides some platform-specific features for Qt on X11-based systems. The module was available earlier as standalone code that you could check out from gitorious.org and build yourself with Qt 5.0.

It was considered useful and stable enough to be rolled into the Qt 5.1.0 release. The code is licensed in the same way as the rest of Qt (i.e. triple licensed under GPL, LGPL and Commercial licenses).

X11 Extras

The X11 Extras module provides features specific to platforms using X11, e.g. Linux and UNIX-like systems including embedded Linux systems that use the X Window System. The module provides a class QX11Info that provides information about the X display configuration. It provides ten static methods that set or get information about the display. The QX11Info class existed in Qt version 4 but was not part of the Qt 5.0 release. The Qt 5.1 QX11Info class is a subset of what was provided in Qt 4  the Qt 4 version provided some additional methods. QX11Info in Qt 5.1 also includes one method, QX11Info::connection(), that did not exist in Qt 4. The methods are all static and there is a private constructor so you cannot instantiate a QX11Info object. To use it in your qmake project file you will need to add:

QT += x11extras

Better yet, for compatibility with Qt 4, you can use this line:

greaterThan(QT_MAJOR_VERSION, 4): QT += x11extras

To use QX11Info you need to create a QApplication (not a QGuiApplication) object in order for the class to work correctly (otherwise you will get bad results and/or crashes). That means that under Qt 5 you also need to link to the qwidgets module). Several of the methods use a parameter specifying the X screen number, accepting a parameter of -1 as the current screen.

I wrote a simple example program that displays what is returned by some of the QX11Info methods. It builds and runs on both Qt 4 and Qt 5.1. Here is sample output with Qt 5:

Qt version: 5.1.0
Screen: 0
DPI X: 93
DPI Y: 94
Root window handle: 659
Time: 0
User time: 0
Display: 0x8a7cf38
XCB connection: 0x8c669e8

And here is sample output with Qt 4:

Qt version: 4.8.4 
Screen: 0 
DPI X: 93 
DPI Y: 95 
Root window handle: 659 
Time: 0 
User time: 0 
Display: 0x99d0998 
Cells: 256 
Class: X11extras 
Color map: 32 
Default color map: true 
Default visual: true 
Depth: 24 
Visual: 0x99b7110 
Is composite manager running? false 

Here is the source code for the application:

#include <QApplication>
#include <QX11Info>
#include <QDebug>

/*
  Example of using QX11Info class.
*/

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    qDebug() << "Qt version:" << QT_VERSION_STR;

    // APIs common to Qt 4 and Qt 5.1
    int screen = QX11Info::appScreen();
    qDebug() << "Screen:" << QX11Info::appScreen();
    qDebug() << "DPI X:" << QX11Info::appDpiX(screen);
    qDebug() << "DPI Y:" << QX11Info::appDpiY(screen);
    qDebug() << "Root window handle:" << QX11Info::appRootWindow(screen);
    qDebug() << "Time:" << QX11Info::appTime();
    qDebug() << "User time:" << QX11Info::appUserTime();
    qDebug() << "Display:" << QX11Info::display();

    // Qt 5.1 APIs
#if QT_VERSION >= 0x050100
    qDebug() << "XCB connection:" << QX11Info::connection();
#endif

    // Qt 4 APIs
#if QT_VERSION < 0x050000
    qDebug() << "Cells:" << QX11Info::appCells(screen);
    qDebug() << "Class:" << QX11Info::appClass();
    qDebug() << "Color map:" << QX11Info::appColormap(screen);
    qDebug() << "Default color map:" << QX11Info::appDefaultColormap(screen);
    qDebug() << "Default visual:" << QX11Info::appDefaultVisual(screen);
    qDebug() << "Depth:" << QX11Info::appDepth(screen);
    qDebug() << "Visual:" << QX11Info::appVisual(screen);
    qDebug() << "Is composite manager running?" << QX11Info::isCompositingManagerRunning();
#endif
}

I noticed one discrepancy in the output. Qt 4 reports a DPI of 93x95 while Qt 5 reports 93x94. The output of "xdpyinfo" on my system reports 93x95. I'm not sure of the reason for the difference and would have to dig further into how Qt makes this calculation. It may be due to Qt 4 using xlib and Qt 5 using xcb to access the X Window System and/or differences in how the calculation takes into account the reported display size.

You can download the source code for the example application from here.

Other Platform Extras

There are two other platform-specific extras modules that are also available as standalone code from gitorious.org: Win Extras and Mac Extras. These were originally considered for inclusion in the Qt 5.1 release but were not considered stable enough at the time of feature freeze and had to be postponed to a future release.

The Win Extras module provides features specific to the Windows platform. The module is quite small. The API is not a class, just some functions in the Qt namespace. The header file qwinfunctions.h provides six methods related to conversion between the Windows-specific HBITMAP and HICON bitmap and icon file formats and Qt's QBitmap, QPixmap and QImage formats. The source code also includes an example program that extracts Windows icons from executables, DLLs or icon files and writes them out as .png files. Obviously, these are only available when using Qt on Windows. When using the functions, take care to follow the comments in the API documentation about memory management. The code is currently maintained here.

The Mac Extras module provides features specific to the Mac OS X desktop platform. The module provides seven header files and includes five example apps. I haven't looked at it in detail as I do not have access to a Macintosh computer. It is mostly for providing native support for drag and drop and clipboard on the Mac as well as support for Mac-specific toolbars. The code is currently maintained here.

Summary

The new X11 Extras modules in Qt 5.1 can help you implement some platform-specific features in your Qt applications. You should use them with care, as they are not portable. Only use these modules if you can't achieve the same goal using cross-platform classes such as QScreen. Typically you should use them with #ifdefs in your code that check for the platform at compile time. Qt provides a set of defines prefixed with "Q_OS_" that you can use for this.

Note that the above information was based on the Qt 5.1 Alpha release so it could possibly change before Qt 5.1.0 final.