diff options
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 80 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 27 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.cpp | 12 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 25 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 4 |
8 files changed, 143 insertions, 15 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index 5fc5b4ba97..3f1c53b122 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -440,6 +440,86 @@ bool QGLXContext::isValid() const return m_context != 0; } +bool QGLXContext::m_queriedDummyContext = false; +bool QGLXContext::m_supportsThreading = true; + + +// If this list grows to any significant size, change it a +// proper string table and make the implementation below use +// binary search. +static const char *qglx_threadedgl_blacklist_renderer[] = { + "Chromium", // QTBUG-32225 (initialization fails) + "Mesa DRI Intel(R) Sandybridge Mobile", // QTBUG-34492 (flickering in fullscreen) + 0 +}; + +static const char *qglx_threadedgl_blacklist_vendor[] = { + "nouveau", // QTCREATORBUG-10875 (crash in creator) + 0 +}; + +void QGLXContext::queryDummyContext() +{ + if (m_queriedDummyContext) + return; + m_queriedDummyContext = true; + + static bool skip = qEnvironmentVariableIsSet("QT_OPENGL_NO_SANITY_CHECK"); + if (skip) + return; + + QOpenGLContext *oldContext = QOpenGLContext::currentContext(); + QSurface *oldSurface = 0; + if (oldContext) + oldSurface = oldContext->surface(); + + QScopedPointer<QSurface> surface; + const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + if (glxvendor && !strcmp(glxvendor, "ATI")) { + QWindow *window = new QWindow; + window->resize(64, 64); + window->setSurfaceType(QSurface::OpenGLSurface); + window->create(); + surface.reset(window); + } else { + QOffscreenSurface *offSurface = new QOffscreenSurface; + offSurface->create(); + surface.reset(offSurface); + } + + QOpenGLContext context; + context.create(); + context.makeCurrent(surface.data()); + + m_supportsThreading = true; + + const char *renderer = (const char *) glGetString(GL_RENDERER); + for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { + if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { + m_supportsThreading = false; + break; + } + } + + const char *vendor = (const char *) glGetString(GL_VENDOR); + for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { + if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + m_supportsThreading = false; + break; + } + } + + context.doneCurrent(); + if (oldContext && oldSurface) + oldContext->makeCurrent(oldSurface); +} + +bool QGLXContext::supportsThreading() +{ + if (!m_queriedDummyContext) + queryDummyContext(); + return m_supportsThreading; +} QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h index 1666f71060..00bba94ab3 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -72,6 +72,9 @@ public: GLXContext glxContext() const { return m_context; } + static bool supportsThreading(); + static void queryDummyContext(); + private: QXcbScreen *m_screen; GLXContext m_context; @@ -79,6 +82,8 @@ private: QSurfaceFormat m_format; bool m_isPBufferCurrent; int m_swapInterval; + static bool m_queriedDummyContext; + static bool m_supportsThreading; }; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 3f599123b9..96e6534b74 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1429,7 +1429,10 @@ static const char * xcb_atomnames = { #if XCB_USE_MAEMO_WINDOW_PROPERTIES "_MEEGOTOUCH_ORIENTATION_ANGLE\0" #endif - "_XSETTINGS_SETTINGS\0" // \0\0 terminates loop. + "_XSETTINGS_SETTINGS\0" + "_COMPIZ_DECOR_PENDING\0" + "_COMPIZ_DECOR_REQUEST\0" + "_COMPIZ_DECOR_DELETE_PIXMAP\0" // \0\0 terminates loop. }; QXcbAtom::Atom QXcbConnection::qatom(xcb_atom_t xatom) const @@ -1737,10 +1740,26 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub return true; } -bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode) +// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed: +// - "pad0" became "extension" +// - "pad1" and "pad" became "pad0" +// New and old version of this struct share the following fields: +// NOTE: API might change again in the next release of xcb in which case this comment will +// need to be updated to reflect the reality. +typedef struct qt_xcb_ge_event_t { + uint8_t response_type; + uint8_t extension; + uint16_t sequence; + uint32_t length; + uint16_t event_type; +} qt_xcb_ge_event_t; + +bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode) { - // xGenericEvent has "extension" on the second byte, xcb_ge_event_t has "pad0". - if (event->pad0 == opCode) { + qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev; + // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from + // the xcb version 1.9.3, prior to that it was called "pad0". + if (event->extension == opCode) { // xcb event structs contain stuff that wasn't on the wire, the full_sequence field // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes. // Move this data back to have the same layout in memory as it was on the wire diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 3f46f1c462..3a71eb2574 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -277,6 +277,10 @@ namespace QXcbAtom { #endif _XSETTINGS_SETTINGS, + _COMPIZ_DECOR_PENDING, + _COMPIZ_DECOR_REQUEST, + _COMPIZ_DECOR_DELETE_PIXMAP, + NPredefinedAtoms, _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 5168bd818b..ecbf28bab9 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -278,10 +278,15 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const #else case OpenGL: return false; #endif +#if defined(XCB_USE_GLX) + case ThreadedOpenGL: return m_connections.at(0)->supportsThreadedRendering() && QGLXContext::supportsThreading(); +#else case ThreadedOpenGL: return m_connections.at(0)->supportsThreadedRendering(); +#endif case WindowMasks: return true; case MultipleWindows: return true; case ForeignWindows: return true; + case SyncState: return true; default: return QPlatformIntegration::hasCapability(cap); } } @@ -458,4 +463,11 @@ QPlatformSessionManager *QXcbIntegration::createPlatformSessionManager(const QSt } #endif +void QXcbIntegration::sync() +{ + for (int i = 0; i < m_connections.size(); i++) { + m_connections.at(i)->sync(); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 79fb1965c4..6ae23125c8 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -106,6 +106,7 @@ public: QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE; #endif + void sync(); private: QList<QXcbConnection *> m_connections; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 832f871bb7..806f948cc2 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -154,7 +154,7 @@ enum QX11EmbedMessageType { XEMBED_ACTIVATE_ACCELERATOR = 14 }; -const long XEMBED_VERSION = 0; +const quint32 XEMBED_VERSION = 0; // Returns \c true if we should set WM_TRANSIENT_FOR on \a w static inline bool isTransient(const QWindow *w) @@ -403,7 +403,7 @@ void QXcbWindow::create() } // set the PID to let the WM kill the application if unresponsive - long pid = getpid(); + quint32 pid = getpid(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, 1, &pid)); @@ -422,7 +422,7 @@ void QXcbWindow::create() 1, &leader)); /* Add XEMBED info; this operation doesn't initiate the embedding. */ - long data[] = { XEMBED_VERSION, XEMBED_MAPPED }; + quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED }; Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_XEMBED_INFO), atom(QXcbAtom::_XEMBED_INFO), @@ -1544,11 +1544,18 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even #endif } else if (event->type == atom(QXcbAtom::_XEMBED)) { handleXEmbedMessage(event); - } else if (event->type == atom(QXcbAtom::MANAGER) || event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW) - || event->type == atom(QXcbAtom::_NET_WM_STATE) || event->type == atom(QXcbAtom::MANAGER) + } else if (event->type == atom(QXcbAtom::_NET_ACTIVE_WINDOW)) { + connection()->setFocusWindow(this); + QWindowSystemInterface::handleWindowActivated(window()); + } else if (event->type == atom(QXcbAtom::MANAGER) + || event->type == atom(QXcbAtom::_NET_WM_STATE) || event->type == atom(QXcbAtom::WM_CHANGE_STATE)) { - // Ignore _NET_ACTIVE_WINDOW, _NET_WM_STATE, MANAGER which are relate to tray icons + // Ignore _NET_WM_STATE, MANAGER which are relate to tray icons // and other messages. + } else if (event->type == atom(QXcbAtom::_COMPIZ_DECOR_PENDING) + || event->type == atom(QXcbAtom::_COMPIZ_DECOR_REQUEST) + || event->type == atom(QXcbAtom::_COMPIZ_DECOR_DELETE_PIXMAP)) { + //silence the _COMPIZ messages for now } else { qWarning() << "QXcbWindow: Unhandled client message:" << connection()->atomName(event->type); } @@ -1817,7 +1824,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev xcb_get_property_reply(xcb_connection(), get_cookie, NULL); if (reply && reply->format == 32 && reply->type == wmStateAtom) { - const long *data = (const long *)xcb_get_property_value(reply); + const quint32 *data = (const quint32 *)xcb_get_property_value(reply); if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0]) newState = Qt::WindowMinimized; } @@ -1988,8 +1995,8 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) } // Sends an XEmbed message. -void QXcbWindow::sendXEmbedMessage(xcb_window_t window, long message, - long detail, long data1, long data2) +void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, + quint32 detail, quint32 data1, quint32 data2) { xcb_client_message_event_t event; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 5601a115e9..45d44b213f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -169,8 +169,8 @@ private: void updateDoesNotAcceptFocus(bool doesNotAcceptFocus); QRect windowToWmGeometry(QRect r) const; - void sendXEmbedMessage(xcb_window_t window, long message, - long detail = 0, long data1 = 0, long data2 = 0); + void sendXEmbedMessage(xcb_window_t window, quint32 message, + quint32 detail = 0, quint32 data1 = 0, quint32 data2 = 0); void handleXEmbedMessage(const xcb_client_message_event_t *event); void create(); |