X11 (xcb) support for QScreen-per-output and runtime changes

QScreen has notifiers for its properties, but they were not being
emitted when one changes the resolution or arrangement of individual
outputs, e.g. via xrandr.  Also there should be one QScreen per
"output", e.g. laptop LCD + external monitor means 2 QScreens
which will be siblings, rather than just 1 QScreen to represent
the whole desktop.

Change-Id: Ia61bbc5e6a3506f813ab11f87c03d14cf7f4ce85
Reviewed-by: Uli Schlachter <psychon@znc.in>
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
bb10
Shawn Rutledge 2012-09-05 13:44:44 +02:00 committed by The Qt Project
parent 5ea896fbc6
commit beab941e1f
6 changed files with 264 additions and 68 deletions

View File

@ -286,6 +286,9 @@ QList<QScreen *> QScreen::virtualSiblings() const
}
/*!
\property QScreen::virtualSize
\brief the pixel size of the virtual desktop to which this screen belongs
Returns the pixel size of the virtual desktop corresponding to this screen.
This is the combined size of the virtual siblings' individual geometries.
@ -298,6 +301,9 @@ QSize QScreen::virtualSize() const
}
/*!
\property QScreen::virtualGeometry
\brief the pixel geometry of the virtual desktop to which this screen belongs
Returns the pixel geometry of the virtual desktop corresponding to this screen.
This is the union of the virtual siblings' individual geometries.
@ -313,6 +319,9 @@ QRect QScreen::virtualGeometry() const
}
/*!
\property QScreen::availableVirtualSize
\brief the available size of the virtual desktop to which this screen belongs
Returns the available pixel size of the virtual desktop corresponding to this screen.
This is the combined size of the virtual siblings' individual available geometries.
@ -325,7 +334,10 @@ QSize QScreen::availableVirtualSize() const
}
/*!
Returns the available size of the virtual desktop corresponding to this screen.
\property QScreen::availableVirtualGeometry
\brief the available geometry of the virtual desktop to which this screen belongs
Returns the available geometry of the virtual desktop corresponding to this screen.
This is the union of the virtual siblings' individual available geometries.

View File

@ -71,7 +71,13 @@ class Q_GUI_EXPORT QScreen : public QObject
Q_PROPERTY(QString name READ name CONSTANT)
Q_PROPERTY(int depth READ depth CONSTANT)
Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
Q_PROPERTY(QSize availableSize READ availableSize NOTIFY availableSizeChanged)
Q_PROPERTY(QSize virtualSize READ virtualSize NOTIFY sizeChanged)
Q_PROPERTY(QSize availableVirtualSize READ availableVirtualSize NOTIFY availableSizeChanged)
Q_PROPERTY(QRect geometry READ geometry NOTIFY geometryChanged)
Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged)
Q_PROPERTY(QRect virtualGeometry READ virtualGeometry NOTIFY sizeChanged)
Q_PROPERTY(QRect availableVirtualGeometry READ availableVirtualGeometry NOTIFY availableGeometryChanged)
Q_PROPERTY(QSizeF physicalSize READ physicalSize CONSTANT)
Q_PROPERTY(qreal physicalDotsPerInchX READ physicalDotsPerInchX NOTIFY physicalDotsPerInchXChanged)
Q_PROPERTY(qreal physicalDotsPerInchY READ physicalDotsPerInchY NOTIFY physicalDotsPerInchYChanged)
@ -79,8 +85,6 @@ class Q_GUI_EXPORT QScreen : public QObject
Q_PROPERTY(qreal logicalDotsPerInchX READ logicalDotsPerInchX NOTIFY logicalDotsPerInchXChanged)
Q_PROPERTY(qreal logicalDotsPerInchY READ logicalDotsPerInchY NOTIFY logicalDotsPerInchYChanged)
Q_PROPERTY(qreal logicalDotsPerInch READ logicalDotsPerInch NOTIFY logicalDotsPerInchChanged)
Q_PROPERTY(QSize availableSize READ availableSize NOTIFY availableSizeChanged)
Q_PROPERTY(QRect availableGeometry READ availableGeometry NOTIFY availableGeometryChanged)
Q_PROPERTY(Qt::ScreenOrientation primaryOrientation READ primaryOrientation NOTIFY primaryOrientationChanged)
Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation NOTIFY orientationChanged)
Q_PROPERTY(qreal refreshRate READ refreshRate NOTIFY refreshRateChanged)

View File

@ -60,7 +60,6 @@
#include <stdio.h>
#include <errno.h>
#include <xcb/xfixes.h>
#include <xcb/randr.h>
#ifdef XCB_USE_XLIB
#include <X11/Xlib.h>
@ -101,9 +100,27 @@ static int nullErrorHandler(Display *, XErrorEvent *)
}
#endif
QXcbScreen* QXcbConnection::createScreenWithFabricatedName(int screenNumber, xcb_screen_t* xcbScreen)
{
QByteArray displayName = m_displayName;
int dotPos = displayName.lastIndexOf('.');
if (dotPos != -1)
displayName.truncate(dotPos);
QString name = displayName + QLatin1Char('.') + QString::number(screenNumber);
QXcbScreen *screen = new QXcbScreen(this, xcbScreen, NULL, name, screenNumber);
// make sure the primary screen appears first since it is used by QGuiApplication::primaryScreen()
if (m_primaryScreen == screenNumber) {
m_screens.prepend(screen);
} else {
m_screens.append(screen);
}
return screen;
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char *displayName)
: m_connection(0)
, m_primaryScreen(0)
, m_primaryOutput(-1)
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
#ifdef XCB_USE_XINPUT2_MAEMO
@ -171,14 +188,72 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, const char
int screenNumber = 0;
while (it.rem) {
QXcbScreen *screen = new QXcbScreen(this, it.data, screenNumber);
// make sure the primary screen appears first since it is used by QGuiApplication::primaryScreen()
if (m_primaryScreen == screenNumber) {
m_screens.prepend(screen);
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
// Now iterate the individual outputs (e.g. DVI-I-1, VGA-1, etc.)
// and make a QScreen instance for each.
xcb_screen_t *xcbScreen = it.data;
QList<QPlatformScreen *> siblings;
if (has_randr_extension) {
xcb_randr_get_output_primary_cookie_t primaryCookie =
xcb_randr_get_output_primary_unchecked(xcb_connection(), xcbScreen->root);
xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), xcbScreen->root);
xcb_randr_get_output_primary_reply_t *primary =
xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, NULL);
xcb_randr_get_screen_resources_current_reply_t *resources =
xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL);
xcb_timestamp_t timestamp = resources->config_timestamp;
int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources);
xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_current_outputs(resources);
if (outputCount == 0) {
// This happens on VNC for example. But there is actually a screen anyway.
#ifdef Q_XCB_DEBUG
qDebug("Found a screen with zero outputs");
#endif
QXcbScreen *screen = createScreenWithFabricatedName(screenNumber, it.data);
siblings << screen;
++screenNumber;
}
for (int i = 0; i < outputCount; i++) {
xcb_randr_get_output_info_reply_t *output =
xcb_randr_get_output_info_reply(xcb_connection(),
xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL);
if (output == NULL)
continue;
QString outputName = QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
xcb_randr_get_output_info_name_length(output));
if (output->crtc == XCB_NONE) {
#ifdef Q_XCB_DEBUG
qDebug("Screen output %s is not connected", qPrintable(outputName));
#endif
continue;
}
QXcbScreen *screen = new QXcbScreen(this, xcbScreen, output, outputName, screenNumber);
siblings << screen;
// make sure the primary screen appears first since it is used by QGuiApplication::primaryScreen()
if (outputs[i] == primary->output && m_primaryOutput < 0) {
m_primaryOutput = screenNumber;
m_screens.prepend(screen);
} else {
m_screens.append(screen);
}
++screenNumber;
free(output);
}
free(primary);
free(resources);
} else {
m_screens.append(screen);
QXcbScreen *screen = createScreenWithFabricatedName(screenNumber, it.data);
siblings << screen;
++screenNumber;
}
++screenNumber;
foreach (QPlatformScreen* s, siblings)
((QXcbScreen*)s)->setVirtualSiblings(siblings);
xcb_screen_next(&it);
}
@ -637,8 +712,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
foreach (QXcbScreen *s, m_screens) {
if (s->root() == change_event->root ) {
s->handleScreenChange(change_event);
s->updateRefreshRate();
break;
}
}
handled = true;

View File

@ -398,6 +398,7 @@ private:
void handleGenericEventMaemo(xcb_ge_event_t *event);
#endif
void handleClientMessageEvent(const xcb_client_message_event_t *event);
QXcbScreen* createScreenWithFabricatedName(int screenNumber, xcb_screen_t* xcbScreen);
bool m_xi2Enabled;
int m_xi2Minor;
@ -442,6 +443,7 @@ private:
QList<QXcbScreen *> m_screens;
int m_primaryScreen;
int m_primaryOutput;
xcb_atom_t m_allAtoms[QXcbAtom::NAtoms];

View File

@ -43,38 +43,59 @@
#include "qxcbwindow.h"
#include "qxcbcursor.h"
#include "qxcbimage.h"
#include "qnamespace.h"
#include <stdio.h>
#include <QDebug>
#include <xcb/randr.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number)
QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
xcb_randr_get_output_info_reply_t *output, QString outputName, int number)
: QXcbObject(connection)
, m_screen(screen)
, m_screen(scr)
, m_crtc(output ? output->crtc : 0)
, m_outputName(outputName)
, m_sizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(scr->width_in_pixels, scr->height_in_pixels)
, m_virtualSizeMillimeters(scr->width_in_millimeters, scr->height_in_millimeters)
, m_orientation(Qt::PrimaryOrientation)
, m_number(number)
, m_refreshRate(60)
{
if (connection->hasXRandr())
xcb_randr_select_input(xcb_connection(), screen->root, true);
xcb_randr_select_input(xcb_connection(), screen()->root, true);
updateGeometry(output ? output->timestamp : 0);
updateRefreshRate();
// On VNC, it can be that physical size is unknown while
// virtual size is known (probably back-calculated from DPI and resolution)
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = m_virtualSizeMillimeters;
if (m_geometry.isEmpty())
m_geometry = QRect(QPoint(), m_virtualSize);
if (m_availableGeometry.isEmpty())
m_availableGeometry = QRect(QPoint(), m_virtualSize);
#ifdef Q_XCB_DEBUG
qDebug();
qDebug("Information of screen %d:", screen->root);
qDebug(" width.........: %d", screen->width_in_pixels);
qDebug(" height........: %d", screen->height_in_pixels);
qDebug(" depth.........: %d", screen->root_depth);
qDebug(" white pixel...: %x", screen->white_pixel);
qDebug(" black pixel...: %x", screen->black_pixel);
qDebug("Screen %s:", m_outputName.toUtf8().constData());
qDebug(" width..........: %lf", m_sizeMillimeters.width());
qDebug(" height.........: %lf", m_sizeMillimeters.height());
qDebug(" geometry.......: %d x %d +%d +%d", m_geometry.width(), m_geometry.height(), m_geometry.x(), m_geometry.y());
qDebug(" virtual width..: %lf", m_virtualSizeMillimeters.width());
qDebug(" virtual height.: %lf", m_virtualSizeMillimeters.height());
qDebug(" virtual geom...: %d x %d", m_virtualSize.width(), m_virtualSize.height());
qDebug(" avail virt geom: %d x %d +%d +%d", m_availableGeometry.width(), m_availableGeometry.height(), m_availableGeometry.x(), m_availableGeometry.y());
qDebug(" depth..........: %d", screen()->root_depth);
qDebug(" white pixel....: %x", screen()->white_pixel);
qDebug(" black pixel....: %x", screen()->black_pixel);
qDebug(" refresh rate...: %d", m_refreshRate);
qDebug();
qDebug(" root ID........: %x", screen()->root);
#endif
const quint32 mask = XCB_CW_EVENT_MASK;
@ -85,11 +106,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
| XCB_EVENT_MASK_PROPERTY_CHANGE
};
xcb_change_window_attributes(xcb_connection(), screen->root, mask, values);
xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values);
xcb_get_property_reply_t *reply =
xcb_get_property_reply(xcb_connection(),
xcb_get_property_unchecked(xcb_connection(), false, screen->root,
xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
XCB_ATOM_WINDOW, 0, 1024), NULL);
@ -105,14 +126,14 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
#ifdef Q_XCB_DEBUG
qDebug("Running window manager: %s", qPrintable(m_windowManagerName));
qDebug(" window manager.: %s", qPrintable(m_windowManagerName));
qDebug();
#endif
}
free(windowManagerReply);
}
}
free(reply);
const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
@ -125,11 +146,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
Q_XCB_CALL2(xcb_create_window(xcb_connection(),
XCB_COPY_FROM_PARENT,
m_clientLeader,
m_screen->root,
screen()->root,
0, 0, 1, 1,
0,
XCB_WINDOW_CLASS_INPUT_OUTPUT,
m_screen->root_visual,
screen()->root_visual,
0, 0), connection);
Q_XCB_CALL2(xcb_change_property(xcb_connection(),
@ -142,7 +163,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num
&m_clientLeader), connection);
xcb_depth_iterator_t depth_iterator =
xcb_screen_allowed_depths_iterator(screen);
xcb_screen_allowed_depths_iterator(screen());
while (depth_iterator.rem) {
xcb_depth_t *depth = depth_iterator.data;
@ -214,34 +235,113 @@ const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const
return &*it;
}
QRect QXcbScreen::geometry() const
{
return QRect(0, 0, m_screen->width_in_pixels, m_screen->height_in_pixels);
}
int QXcbScreen::depth() const
{
return m_screen->root_depth;
}
QImage::Format QXcbScreen::format() const
{
return QImage::Format_RGB32;
}
QSizeF QXcbScreen::physicalSize() const
{
return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
}
QPlatformCursor *QXcbScreen::cursor() const
{
return m_cursor;
}
qreal QXcbScreen::refreshRate() const
/*!
\brief handle the XCB screen change event and update properties
On a mobile device, the ideal use case is that the accelerometer would
drive the orientation. This could be achieved by using QSensors to read the
accelerometer and adjusting the rotation in QML, or by reading the
orientation from the QScreen object and doing the same, or in many other
ways. However, on X we have the XRandR extension, which makes it possible
to have the whole screen rotated, so that individual apps DO NOT have to
rotate themselves. Apps could optionally use the
QScreen::primaryOrientation property to optimize layout though.
Furthermore, there is no support in X for accelerometer events anyway. So
it makes more sense on a Linux system running X to just run a daemon which
monitors the accelerometer and runs xrandr automatically to do the rotation,
then apps do not have to be aware of it (but probably the window manager
would resize them accordingly). updateGeometry() is written with this
design in mind. Therefore the physical geometry, available geometry,
virtual geometry, orientation and primaryOrientation should all change at
the same time. On a system which cannot rotate the whole screen, it would
be correct for only the orientation (not the primary orientation) to
change.
*/
void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event)
{
return m_refreshRate;
updateGeometry(change_event->config_timestamp);
switch (change_event->rotation) {
case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal
m_orientation = Qt::LandscapeOrientation;
m_virtualSize.setWidth(change_event->width);
m_virtualSize.setHeight(change_event->height);
m_virtualSizeMillimeters.setWidth(change_event->mwidth);
m_virtualSizeMillimeters.setHeight(change_event->mheight);
break;
case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left
m_orientation = Qt::PortraitOrientation;
m_virtualSize.setWidth(change_event->height);
m_virtualSize.setHeight(change_event->width);
m_virtualSizeMillimeters.setWidth(change_event->mheight);
m_virtualSizeMillimeters.setHeight(change_event->mwidth);
break;
case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted
m_orientation = Qt::InvertedLandscapeOrientation;
m_virtualSize.setWidth(change_event->width);
m_virtualSize.setHeight(change_event->height);
m_virtualSizeMillimeters.setWidth(change_event->mwidth);
m_virtualSizeMillimeters.setHeight(change_event->mheight);
break;
case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right
m_orientation = Qt::InvertedPortraitOrientation;
m_virtualSize.setWidth(change_event->height);
m_virtualSize.setHeight(change_event->width);
m_virtualSizeMillimeters.setWidth(change_event->mheight);
m_virtualSizeMillimeters.setHeight(change_event->mwidth);
break;
// We don't need to do anything with these, since QScreen doesn't store reflection state,
// and Qt-based applications probably don't need to care about it anyway.
case XCB_RANDR_ROTATION_REFLECT_X: break;
case XCB_RANDR_ROTATION_REFLECT_Y: break;
}
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry());
QWindowSystemInterface::handleScreenAvailableGeometryChange(QPlatformScreen::screen(), availableGeometry());
QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), m_orientation);
}
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
{
if (connection()->hasXRandr()) {
xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(xcb_connection(),
xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp), NULL);
if (crtc) {
m_geometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height);
m_availableGeometry = m_geometry;
free(crtc);
}
}
xcb_get_property_reply_t * workArea =
xcb_get_property_reply(xcb_connection(),
xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
atom(QXcbAtom::_NET_WORKAREA),
XCB_ATOM_CARDINAL, 0, 1024), NULL);
if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) {
// If workArea->value_len > 4, the remaining ones seem to be for virtual desktops.
// But QScreen doesn't know about that concept. In reality there could be a
// "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop.
// But for now just assume the first 4 values give us the geometry of the
// "work area", AKA "available geometry"
uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea);
QRect virtualAvailableGeometry(geom[0], geom[1], geom[2], geom[3]);
// Take the intersection of the desktop's available geometry with this screen's geometry
// to get the part of the available geometry which belongs to this screen.
m_availableGeometry = m_geometry & virtualAvailableGeometry;
}
free(workArea);
}
void QXcbScreen::updateRefreshRate()
@ -267,11 +367,6 @@ void QXcbScreen::updateRefreshRate()
QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), rate);
}
int QXcbScreen::screenNumber() const
{
return m_number;
}
QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const
{
if (width == 0 || height == 0)
@ -369,13 +464,4 @@ QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height)
return result;
}
QString QXcbScreen::name() const
{
QByteArray displayName = connection()->displayName();
int dotPos = displayName.lastIndexOf('.');
if (dotPos != -1)
displayName.truncate(dotPos);
return displayName + QLatin1Char('.') + QString::number(screenNumber());
}
QT_END_NAMESPACE

View File

@ -46,6 +46,7 @@
#include <QtCore/QString>
#include <xcb/xcb.h>
#include <xcb/randr.h>
#include "qxcbobject.h"
@ -57,21 +58,26 @@ class QXcbCursor;
class QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number);
QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen,
xcb_randr_get_output_info_reply_t *output, QString outputName, int number);
~QXcbScreen();
QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
QWindow *topLevelAt(const QPoint &point) const;
QRect geometry() const;
int depth() const;
QRect geometry() const { return m_geometry; }
QRect availableGeometry() const {return m_availableGeometry;}
int depth() const { return m_screen->root_depth; }
QImage::Format format() const;
QSizeF physicalSize() const;
QSizeF physicalSize() const { return m_sizeMillimeters; }
QPlatformCursor *cursor() const;
qreal refreshRate() const;
qreal refreshRate() const { return m_refreshRate; }
Qt::ScreenOrientation orientation() const { return m_orientation; }
QList<QPlatformScreen *> virtualSiblings() const { return m_siblings; }
void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
int screenNumber() const;
int screenNumber() const { return m_number; }
xcb_screen_t *screen() const { return m_screen; }
xcb_window_t root() const { return m_screen->root; }
@ -83,12 +89,23 @@ public:
const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
QString name() const;
QString name() const { return m_outputName; }
void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event);
void updateGeometry(xcb_timestamp_t timestamp);
void updateRefreshRate();
private:
xcb_screen_t *m_screen;
xcb_randr_crtc_t m_crtc;
QString m_outputName;
QSizeF m_sizeMillimeters;
QRect m_geometry;
QRect m_availableGeometry;
QSize m_virtualSize;
QSizeF m_virtualSizeMillimeters;
QList<QPlatformScreen *> m_siblings;
Qt::ScreenOrientation m_orientation;
int m_number;
QString m_windowManagerName;
bool m_syncRequestSupported;