diff options
-rw-r--r-- | src/gui/kernel/qscreen.cpp | 14 | ||||
-rw-r--r-- | src/gui/kernel/qscreen.h | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 91 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 184 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.h | 31 |
6 files changed, 263 insertions, 67 deletions
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 7a3854be81..13740e5c5f 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -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. diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h index 5902d8c757..588a2cb445 100644 --- a/src/gui/kernel/qscreen.h +++ b/src/gui/kernel/qscreen.h @@ -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) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 11e1cc0c17..2d64a30a51 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -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; diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index d97db9a74d..8feca95ecc 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -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]; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index d92004b1ac..315c94bb56 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -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 +QPlatformCursor *QXcbScreen::cursor() const { - return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters); + return m_cursor; } -QPlatformCursor *QXcbScreen::cursor() 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_cursor; + 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); } -qreal QXcbScreen::refreshRate() const +void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) { - return m_refreshRate; + 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 diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 7a81d8b43a..dfec3609a5 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -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; |