summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/xcb')
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp80
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp27
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp25
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h4
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();