diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-07-21 13:50:28 +0200 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@nokia.com> | 2011-07-25 13:52:09 +0200 |
commit | c3da77798b876716ce038a30e9aa8517ec158c47 (patch) | |
tree | 99ac6cf5ce37fcb626a12857bb18cf9b444b27f2 /src/plugins | |
parent | e80b6619524a3720efb5fbe4c2307bec25a12ab8 (diff) |
Added workable QScreen API on top of QPlatformScreen.
QPlatformIntegration::screens() no longer has to be implemented,
implementations should call QPlatformIntegration::screenAdded() for each
screen instead. This is for being able to support adding screens at
run-time later on, by connecting it to a signal in QGuiApplication.
The QGuiGLContext API has changed a bit, by not sending in all the
parameters in the constructor but instead having a create() function.
The createPlatformGLContext() factory in QPlatformIntegration takes a
QGuiGLContext * instead of a QSurfaceFormat and a share context, similar
to how the window and backing store factory functions work.
The XCB plugin has experimental support for connecting to multiple X
displays simultaneously, creating one or more QScreen for each.
Change-Id: I248a22a4fd3481280710110272c04a30a8021e8f
Reviewed-on: http://codereview.qt.nokia.com/2103
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com>
Diffstat (limited to 'src/plugins')
18 files changed, 201 insertions, 236 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index a3895d0073..5a30de697e 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -76,19 +76,15 @@ public: ~QCocoaIntegration(); bool hasCapability(QPlatformIntegration::Capability cap) const; - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformGLContext *createPlatformGLContext(const QSurfaceFormat &glFormat, QPlatformGLContext *share) const; + QPlatformGLContext *createPlatformGLContext(QGuiGLContext *context) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const; QAbstractEventDispatcher *createEventDispatcher() const; - QList<QPlatformScreen *> screens() const { return mScreens; } - QPlatformFontDatabase *fontDatabase() const; QPlatformNativeInterface *nativeInterface() const; private: - QList<QPlatformScreen *> mScreens; QPlatformFontDatabase *mFontDb; QCocoaAutoReleasePool *mPool; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 95794cf452..23110583c1 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -47,7 +47,6 @@ #include "qcocoaeventdispatcher.h" #include <QtPlatformSupport/private/qbasicunixfontdatabase_p.h> -#include <private/qpixmap_raster_p.h> QT_BEGIN_NAMESPACE @@ -83,7 +82,7 @@ QCocoaIntegration::QCocoaIntegration() NSArray *screens = [NSScreen screens]; for (uint i = 0; i < [screens count]; i++) { QCocoaScreen *screen = new QCocoaScreen(i); - mScreens.append(screen); + screenAdded(screen); } } @@ -103,19 +102,14 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons -QPlatformPixmap *QCocoaIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); -} - QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const { return new QCocoaWindow(window); } -QPlatformGLContext *QCocoaIntegration::createPlatformGLContext(const QSurfaceFormat &glFormat, QPlatformGLContext *share) const +QPlatformGLContext *QCocoaIntegration::createPlatformGLContext(QGuiGLContext *context) const { - return new QCocoaGLContext(glFormat, share); + return new QCocoaGLContext(context->format(), context->shareHandle()); } QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const diff --git a/src/plugins/platforms/minimal/qminimalbackingstore.cpp b/src/plugins/platforms/minimal/qminimalbackingstore.cpp index bd4f04dfcd..08281405a4 100644 --- a/src/plugins/platforms/minimal/qminimalbackingstore.cpp +++ b/src/plugins/platforms/minimal/qminimalbackingstore.cpp @@ -41,6 +41,7 @@ #include "qminimalbackingstore.h" +#include "qscreen.h" #include <QtCore/qdebug.h> #include <private/qguiapplication_p.h> @@ -77,7 +78,7 @@ void QMinimalBackingStore::flush(QWindow *window, const QRegion ®ion, const Q void QMinimalBackingStore::resize(const QSize &size, const QRegion &) { //qDebug() << "QMinimalBackingStore::setGeometry:" << (long)this << rect; - QImage::Format format = QGuiApplicationPrivate::platformIntegration()->screens().first()->format(); + QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); if (mImage.size() != size) mImage = QImage(size, format); } diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 71bdda73aa..8d8e5e7f06 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -58,7 +58,7 @@ QMinimalIntegration::QMinimalIntegration() mPrimaryScreen->mDepth = 32; mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied; - mScreens.append(mPrimaryScreen); + screenAdded(mPrimaryScreen); } bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -69,11 +69,6 @@ bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) co } } -QPlatformPixmap *QMinimalIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); -} - QPlatformWindow *QMinimalIntegration::createPlatformWindow(QWindow *window) const { Q_UNUSED(window); diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h index 52e4c0a6f3..d64932c5e6 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.h +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -71,15 +71,10 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const; - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; - QAbstractEventDispatcher *createEventDispatcher() const; - - QList<QPlatformScreen *> screens() const { return mScreens; } + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; -private: - QList<QPlatformScreen *> mScreens; + QAbstractEventDispatcher *createEventDispatcher() const; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp index 800f1fc99c..5405a8524e 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.cpp +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -54,8 +54,6 @@ #include <QtGui/QPlatformCursor> #include <QtGui/QSurfaceFormat> -#include <QtGui/private/qpixmap_raster_p.h> - #ifdef QT_WAYLAND_GL_SUPPORT #include "gl_integration/qwaylandglintegration.h" #endif @@ -92,11 +90,6 @@ bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) co } } -QPlatformPixmap *QWaylandIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); -} - QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWindow *window) const { #ifdef QT_WAYLAND_GL_SUPPORT diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h index b9a01dab8d..0dc3b61009 100644 --- a/src/plugins/platforms/wayland/qwaylandintegration.h +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -56,7 +56,6 @@ public: QWaylandIntegration(); bool hasCapability(QPlatformIntegration::Capability cap) const; - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; QPlatformGLContext *createPlatformGLContext(const QSurfaceFormat &glFormat, QPlatformGLContext *share) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; diff --git a/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp b/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp index f6028f69b2..3158c73605 100644 --- a/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp +++ b/src/plugins/platforms/wayland/qwaylandnativeinterface.cpp @@ -44,6 +44,7 @@ #include "qwaylanddisplay.h" #include "qwaylandwindow.h" #include <QtGui/private/qguiapplication_p.h> +#include <QtGui/QScreen> void *QWaylandNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { @@ -64,9 +65,9 @@ QWaylandScreen * QWaylandNativeInterface::qPlatformScreenForWindow(QWindow *wind QWaylandScreen *screen; if (window) { - screen = static_cast<QWaylandScreen *>(QPlatformScreen::platformScreenForWindow(window)); + screen = static_cast<QWaylandScreen *>(window->screen()->handle()); } else { - screen = static_cast<QWaylandScreen *>(QGuiApplicationPrivate::platformIntegration()->screens()[0]); + screen = static_cast<QWaylandScreen *>(QGuiApplication::primaryScreen()->handle()); } return screen; } diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp index 3a63e78207..7b064bac40 100644 --- a/src/plugins/platforms/wayland/qwaylandscreen.cpp +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -53,7 +53,6 @@ QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output , mFormat(QImage::Format_ARGB32_Premultiplied) , mWaylandCursor(new QWaylandCursor(this)) { - moveToThread(waylandDisplay->thread()); } QWaylandScreen::~QWaylandScreen() diff --git a/src/plugins/platforms/xcb/main.cpp b/src/plugins/platforms/xcb/main.cpp index 7fee7455be..c544f7073d 100644 --- a/src/plugins/platforms/xcb/main.cpp +++ b/src/plugins/platforms/xcb/main.cpp @@ -58,11 +58,10 @@ QStringList QXcbIntegrationPlugin::keys() const return list; } -QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& parameters) { - Q_UNUSED(paramList); if (system.toLower() == "xcb") - return new QXcbIntegration; + return new QXcbIntegration(parameters); return 0; } diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 50407f7c9b..fadcb4d5b8 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -56,6 +56,7 @@ #include <qdebug.h> #include <qpainter.h> +#include <qscreen.h> class QXcbShmImage : public QXcbObject { @@ -213,7 +214,7 @@ QXcbBackingStore::QXcbBackingStore(QWindow *window) , m_image(0) , m_syncingResize(false) { - QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWindow(window)); + QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle()); setConnection(screen->connection()); } @@ -280,7 +281,7 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) Q_XCB_NOOP(connection()); - QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWindow(window())); + QXcbScreen *screen = static_cast<QXcbScreen *>(window()->screen()->handle()); QXcbWindow* win = static_cast<QXcbWindow *>(window()->handle()); delete m_image; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 1e18077ea2..7803b3afe9 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -109,8 +109,11 @@ QXcbConnection::QXcbConnection(const char *displayName) #endif //XCB_USE_EGL #else m_connection = xcb_connect(m_displayName.constData(), &m_primaryScreen); - #endif //XCB_USE_XLIB + + if (m_connection) + printf("Successfully connected to display %s\n", m_displayName.constData()); + xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id); m_setup = xcb_get_setup(xcb_connection()); diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 924077f00d..313a773c78 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -47,14 +47,11 @@ #include "qxcbnativeinterface.h" #include "qxcbclipboard.h" #include "qxcbdrag.h" -#include "qxcbimage.h" #include <QtPlatformSupport/private/qgenericunixprintersupport_p.h> #include <xcb/xcb.h> -#include <private/qpixmap_raster_p.h> - #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> #include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h> @@ -64,6 +61,11 @@ #include <EGL/egl.h> #endif +#define XCB_USE_IBUS +#if defined(XCB_USE_IBUS) +#include "QtPlatformSupport/qibusplatforminputcontext.h" +#endif + #if defined(XCB_USE_GLX) #include "qglxintegration.h" #elif defined(XCB_USE_EGL) @@ -71,16 +73,23 @@ #include <QtPlatformSupport/private/qeglplatformcontext_p.h> #endif -#define XCB_USE_IBUS -#if defined(XCB_USE_IBUS) -#include "QtPlatformSupport/qibusplatforminputcontext.h" -#endif +#include <QtGui/QGuiGLContext> +#include <QtGui/QScreen> -QXcbIntegration::QXcbIntegration() - : m_connection(new QXcbConnection), m_printerSupport(new QGenericUnixPrinterSupport) +QXcbIntegration::QXcbIntegration(const QStringList ¶meters) + : m_printerSupport(new QGenericUnixPrinterSupport) { - foreach (QXcbScreen *screen, m_connection->screens()) - m_screens << screen; + m_connections << new QXcbConnection; + + for (int i = 0; i < parameters.size() - 1; i += 2) { + qDebug() << parameters.at(i) << parameters.at(i+1); + QString display = parameters.at(i) + ':' + parameters.at(i+1); + m_connections << new QXcbConnection(display.toAscii().constData()); + } + + foreach (QXcbConnection *connection, m_connections) + foreach (QXcbScreen *screen, connection->screens()) + screenAdded(screen); m_fontDatabase = new QGenericUnixFontDatabase(); m_nativeInterface = new QXcbNativeInterface; @@ -90,21 +99,7 @@ QXcbIntegration::QXcbIntegration() QXcbIntegration::~QXcbIntegration() { - delete m_connection; -} - -bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case ThreadedPixmaps: return true; - case OpenGL: return hasOpenGL(); - default: return QPlatformIntegration::hasCapability(cap); - } -} - -QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const -{ - return new QRasterPlatformPixmap(type); + qDeleteAll(m_connections); } QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const @@ -128,14 +123,15 @@ public: }; #endif -QPlatformGLContext *QXcbIntegration::createPlatformGLContext(const QSurfaceFormat &glFormat, QPlatformGLContext *share) const +QPlatformGLContext *QXcbIntegration::createPlatformGLContext(QGuiGLContext *context) const { + QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); #if defined(XCB_USE_GLX) - return new QGLXContext(static_cast<QXcbScreen *>(m_screens.at(0)), glFormat, share); + return new QGLXContext(screen, context->format(), context->shareHandle()); #elif defined(XCB_USE_EGL) - return new QEGLXcbPlatformContext(glFormat, share, m_connection->egl_display()); + return new QEGLXcbPlatformContext(context->format(), context->shareHandle(), screen->connection()->egl_display()); #elif defined(XCB_USE_DRI2) - return new QDri2Context(glFormat, share); + return new QDri2Context(context->format(), context->shareHandle()); #endif } @@ -144,10 +140,21 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind return new QXcbBackingStore(window); } +bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const { QAbstractEventDispatcher *eventDispatcher = createUnixEventDispatcher(); - m_connection->setEventDispatcher(eventDispatcher); + + foreach (QXcbConnection *connection, m_connections) + connection->setEventDispatcher(eventDispatcher); #ifdef XCB_USE_IBUS // A bit hacky to do this here, but we need an eventloop before we can instantiate // the input context. @@ -156,161 +163,17 @@ QAbstractEventDispatcher *QXcbIntegration::createEventDispatcher() const return eventDispatcher; } -QList<QPlatformScreen *> QXcbIntegration::screens() const -{ - return m_screens; -} - void QXcbIntegration::moveToScreen(QWindow *window, int screen) { Q_UNUSED(window); Q_UNUSED(screen); } -bool QXcbIntegration::isVirtualDesktop() -{ - return false; -} - QPlatformFontDatabase *QXcbIntegration::fontDatabase() const { return m_fontDatabase; } -QPixmap QXcbIntegration::grabWindow(WId window, int x, int y, int width, int height) const -{ - if (width == 0 || height == 0) - return QPixmap(); - - xcb_connection_t *connection = m_connection->xcb_connection(); - - xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry(connection, window); - - xcb_generic_error_t *error; - xcb_get_geometry_reply_t *reply = - xcb_get_geometry_reply(connection, geometry_cookie, &error); - - if (!reply) { - if (error) { - m_connection->handleXcbError(error); - free(error); - } - return QPixmap(); - } - - if (width < 0) - width = reply->width - x; - if (height < 0) - height = reply->height - y; - - // TODO: handle multiple screens - QXcbScreen *screen = m_connection->screens().at(0); - xcb_window_t root = screen->root(); - geometry_cookie = xcb_get_geometry(connection, root); - xcb_get_geometry_reply_t *root_reply = - xcb_get_geometry_reply(connection, geometry_cookie, &error); - - if (!root_reply) { - if (error) { - m_connection->handleXcbError(error); - free(error); - } - free(reply); - return QPixmap(); - } - - if (reply->depth == root_reply->depth) { - // if the depth of the specified window and the root window are the - // same, grab pixels from the root window (so that we get the any - // overlapping windows and window manager frames) - - // map x and y to the root window - xcb_translate_coordinates_cookie_t translate_cookie = - xcb_translate_coordinates(connection, window, root, x, y); - - xcb_translate_coordinates_reply_t *translate_reply = - xcb_translate_coordinates_reply(connection, translate_cookie, &error); - - if (!translate_reply) { - if (error) { - m_connection->handleXcbError(error); - free(error); - } - free(reply); - free(root_reply); - return QPixmap(); - } - - x = translate_reply->dst_x; - y = translate_reply->dst_y; - - window = root; - - free(translate_reply); - free(reply); - reply = root_reply; - } else { - free(root_reply); - root_reply = 0; - } - - xcb_get_window_attributes_reply_t *attributes_reply = - xcb_get_window_attributes_reply(connection, xcb_get_window_attributes(connection, window), &error); - - if (!attributes_reply) { - if (error) { - m_connection->handleXcbError(error); - free(error); - } - free(reply); - return QPixmap(); - } - - const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); - free(attributes_reply); - - xcb_pixmap_t pixmap = xcb_generate_id(connection); - error = xcb_request_check(connection, xcb_create_pixmap_checked(connection, reply->depth, pixmap, window, width, height)); - if (error) { - m_connection->handleXcbError(error); - free(error); - } - - uint32_t gc_value_mask = XCB_GC_SUBWINDOW_MODE; - uint32_t gc_value_list[] = { XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS }; - - xcb_gcontext_t gc = xcb_generate_id(connection); - xcb_create_gc(connection, gc, pixmap, gc_value_mask, gc_value_list); - - error = xcb_request_check(connection, xcb_copy_area_checked(connection, window, pixmap, gc, x, y, 0, 0, width, height)); - if (error) { - m_connection->handleXcbError(error); - free(error); - } - - QPixmap result = qt_xcb_pixmapFromXPixmap(m_connection, pixmap, width, height, reply->depth, visual); - - free(reply); - xcb_free_gc(connection, gc); - xcb_free_pixmap(connection, pixmap); - - return result; -} - -bool QXcbIntegration::hasOpenGL() const -{ -#if defined(XCB_USE_GLX) - return true; -#elif defined(XCB_USE_EGL) - return m_connection->hasEgl(); -#elif defined(XCB_USE_DRI2) - if (m_connection->hasSupportForDri2()) { - return true; - } -#endif - return false; -} - QPlatformNativeInterface * QXcbIntegration::nativeInterface() const { return m_nativeInterface; @@ -323,12 +186,12 @@ QPlatformPrinterSupport *QXcbIntegration::printerSupport() const QPlatformClipboard *QXcbIntegration::clipboard() const { - return m_connection->clipboard(); + return m_connections.at(0)->clipboard(); } QPlatformDrag *QXcbIntegration::drag() const { - return m_connection->drag(); + return m_connections.at(0)->drag(); } QPlatformInputContext *QXcbIntegration::inputContext() const diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 725db7a53d..d62878c7af 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -53,20 +53,17 @@ class QAbstractEventDispatcher; class QXcbIntegration : public QPlatformIntegration { public: - QXcbIntegration(); + QXcbIntegration(const QStringList ¶meters); ~QXcbIntegration(); - bool hasCapability(Capability cap) const; - QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const; QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformGLContext *createPlatformGLContext(const QSurfaceFormat &glFormat, QPlatformGLContext *share) const; + QPlatformGLContext *createPlatformGLContext(QGuiGLContext *context) const; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + + bool hasCapability(Capability cap) const; QAbstractEventDispatcher *createEventDispatcher() const; - QList<QPlatformScreen *> screens() const; void moveToScreen(QWindow *window, int screen); - bool isVirtualDesktop(); - QPixmap grabWindow(WId window, int x, int y, int width, int height) const; QPlatformFontDatabase *fontDatabase() const; @@ -79,9 +76,7 @@ public: QPlatformInputContext *inputContext() const; private: - bool hasOpenGL() const; - QList<QPlatformScreen *> m_screens; - QXcbConnection *m_connection; + QList<QXcbConnection *> m_connections; QPlatformFontDatabase *m_fontDatabase; QPlatformNativeInterface *m_nativeInterface; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 28b62b3aec..217dae6bc1 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -49,6 +49,7 @@ #include <QtCore/QDebug> #include <QtGui/qguiglcontext_qpa.h> +#include <QtGui/qscreen.h> #if defined(XCB_USE_EGL) #include "QtPlatformSupport/private/qeglplatformcontext_p.h" @@ -119,9 +120,9 @@ QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window) { QXcbScreen *screen; if (window) { - screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWindow(window)); - }else { - screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens()[0]); + screen = static_cast<QXcbScreen *>(window->screen()->handle()); + } else { + screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle()); } return screen; } diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 6c3d1813b0..42259feda8 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -42,6 +42,7 @@ #include "qxcbscreen.h" #include "qxcbwindow.h" #include "qxcbcursor.h" +#include "qxcbimage.h" #include <stdio.h> @@ -150,6 +151,7 @@ QXcbScreen::~QXcbScreen() delete m_cursor; } + QWindow *QXcbScreen::topLevelAt(const QPoint &p) const { xcb_window_t root = m_screen->root; @@ -227,3 +229,126 @@ 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) + return QPixmap(); + + xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry(xcb_connection(), window); + + xcb_generic_error_t *error; + xcb_get_geometry_reply_t *reply = + xcb_get_geometry_reply(xcb_connection(), geometry_cookie, &error); + + if (!reply) { + if (error) { + connection()->handleXcbError(error); + free(error); + } + return QPixmap(); + } + + if (width < 0) + width = reply->width - x; + if (height < 0) + height = reply->height - y; + + // TODO: handle multiple screens + QXcbScreen *screen = const_cast<QXcbScreen *>(this); + xcb_window_t root = screen->root(); + geometry_cookie = xcb_get_geometry(xcb_connection(), root); + xcb_get_geometry_reply_t *root_reply = + xcb_get_geometry_reply(xcb_connection(), geometry_cookie, &error); + + if (!root_reply) { + if (error) { + connection()->handleXcbError(error); + free(error); + } + free(reply); + return QPixmap(); + } + + if (reply->depth == root_reply->depth) { + // if the depth of the specified window and the root window are the + // same, grab pixels from the root window (so that we get the any + // overlapping windows and window manager frames) + + // map x and y to the root window + xcb_translate_coordinates_cookie_t translate_cookie = + xcb_translate_coordinates(xcb_connection(), window, root, x, y); + + xcb_translate_coordinates_reply_t *translate_reply = + xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, &error); + + if (!translate_reply) { + if (error) { + connection()->handleXcbError(error); + free(error); + } + free(reply); + free(root_reply); + return QPixmap(); + } + + x = translate_reply->dst_x; + y = translate_reply->dst_y; + + window = root; + + free(translate_reply); + free(reply); + reply = root_reply; + } else { + free(root_reply); + root_reply = 0; + } + + xcb_get_window_attributes_reply_t *attributes_reply = + xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes(xcb_connection(), window), &error); + + if (!attributes_reply) { + if (error) { + connection()->handleXcbError(error); + free(error); + } + free(reply); + return QPixmap(); + } + + const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual); + free(attributes_reply); + + xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection()); + error = xcb_request_check(xcb_connection(), xcb_create_pixmap_checked(xcb_connection(), reply->depth, pixmap, window, width, height)); + if (error) { + connection()->handleXcbError(error); + free(error); + } + + uint32_t gc_value_mask = XCB_GC_SUBWINDOW_MODE; + uint32_t gc_value_list[] = { XCB_SUBWINDOW_MODE_INCLUDE_INFERIORS }; + + xcb_gcontext_t gc = xcb_generate_id(xcb_connection()); + xcb_create_gc(xcb_connection(), gc, pixmap, gc_value_mask, gc_value_list); + + error = xcb_request_check(xcb_connection(), xcb_copy_area_checked(xcb_connection(), window, pixmap, gc, x, y, 0, 0, width, height)); + if (error) { + connection()->handleXcbError(error); + free(error); + } + + QPixmap result = qt_xcb_pixmapFromXPixmap(connection(), pixmap, width, height, reply->depth, visual); + + free(reply); + xcb_free_gc(xcb_connection(), gc); + xcb_free_pixmap(xcb_connection(), pixmap); + + return result; +} + +QString QXcbScreen::name() const +{ + return connection()->displayName() + QLatin1String(".") + QString::number(screenNumber()); +} diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 5b8492faa5..07d855b398 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -58,6 +58,8 @@ public: QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, 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; @@ -77,6 +79,8 @@ public: const xcb_visualtype_t *visualForId(xcb_visualid_t) const; + QString name() const; + private: xcb_screen_t *m_screen; int m_number; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index f63cbe25e6..14ac0e6640 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -42,6 +42,7 @@ #include "qxcbwindow.h" #include <QtDebug> +#include <QScreen> #include "qxcbconnection.h" #include "qxcbscreen.h" @@ -102,7 +103,7 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_eglSurface(0) #endif { - m_screen = static_cast<QXcbScreen *>(QGuiApplicationPrivate::platformIntegration()->screens().at(0)); + m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); setConnection(m_screen->connection()); |