diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-03-31 10:08:14 (GMT) |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-03-31 10:08:14 (GMT) |
commit | faeabd9d202b1af002cd73da148ca4c27715470d (patch) | |
tree | c75e13a68ffe8cbce256a8eaa24d30f5f8eeb9f7 /src/plugins | |
parent | ee481481bbd1d910c8a0191aa517f96186130d8b (diff) | |
download | Qt-faeabd9d202b1af002cd73da148ca4c27715470d.zip Qt-faeabd9d202b1af002cd73da148ca4c27715470d.tar.gz Qt-faeabd9d202b1af002cd73da148ca4c27715470d.tar.bz2 |
Fixed synchronizations issues in XCB platform plugin.
Use select() and xcb_poll_for_event() instead of xcb_wait_for_event(),
ad xcb_wait_for_event() will lock the XCB connection mutex, preventing
the other thread from posting events etc.
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 13 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 205 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 7 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbkeyboard.cpp | 6 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 4 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindowsurface.cpp | 33 |
6 files changed, 170 insertions, 98 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index d42cfeb..d1171b8 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -65,6 +65,7 @@ QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindo , m_drawable((Drawable)window) , m_context(0) { + Q_XCB_NOOP(m_screen->connection()); const QPlatformGLContext *sharePlatformContext; if (format.useDefaultSharedContext()) { if (!QPlatformGLContext::defaultSharedContext()) { @@ -87,6 +88,7 @@ QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindo GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),format); m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE); m_windowFormat = qglx_platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); + Q_XCB_NOOP(m_screen->connection()); } QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context) @@ -97,12 +99,15 @@ QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext conte QGLXContext::~QGLXContext() { + Q_XCB_NOOP(m_screen->connection()); if (m_context) glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::createDefaultSharedContext(QXcbScreen *screen) { + Q_XCB_NOOP(screen->connection()); int x = 0; int y = 0; int w = 3; @@ -126,30 +131,38 @@ void QGLXContext::createDefaultSharedContext(QXcbScreen *screen) } else { qWarning("Warning no shared context created"); } + Q_XCB_NOOP(screen->connection()); } void QGLXContext::makeCurrent() { + Q_XCB_NOOP(m_screen->connection()); m_screen->connection()->setEventProcessingEnabled(false); QPlatformGLContext::makeCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::doneCurrent() { + Q_XCB_NOOP(m_screen->connection()); QPlatformGLContext::doneCurrent(); glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); m_screen->connection()->setEventProcessingEnabled(true); + Q_XCB_NOOP(m_screen->connection()); } void QGLXContext::swapBuffers() { + Q_XCB_NOOP(m_screen->connection()); glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable); doneCurrent(); + Q_XCB_NOOP(m_screen->connection()); } void* QGLXContext::getProcAddress(const QString& procName) { + Q_XCB_NOOP(m_screen->connection()); typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; static bool resolved = false; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index f1d3d2b..05d3440 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -76,6 +76,7 @@ extern "C" { QXcbConnection::QXcbConnection(const char *displayName) : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) + , m_pauseId(0) , m_enabled(true) #ifdef XCB_USE_DRI2 , m_dri2_major(0) @@ -130,7 +131,7 @@ QXcbConnection::QXcbConnection(const char *displayName) start(); } -void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom atom) +void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom atom, uint id) { xcb_client_message_event_t event; memset(&event, 0, sizeof(event)); @@ -140,9 +141,9 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom atom) event.sequence = 0; event.window = m_connectionEventListener; event.type = atom; + event.data.data32[0] = id; - xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event); - + Q_XCB_CALL(xcb_send_event(xcb_connection(), false, m_connectionEventListener, XCB_EVENT_MASK_NO_EVENT, (const char *)&event)); xcb_flush(xcb_connection()); } @@ -152,10 +153,12 @@ void QXcbConnection::setEventProcessingEnabled(bool enabled) return; if (!enabled) { + sendConnectionEvent(QXcbAtom::_QT_PAUSE_CONNECTION, uint(m_pauseId)); m_connectionLock.lock(); - sendConnectionEvent(QXcbAtom::_QT_PAUSE_CONNECTION); + m_pauseId.fetchAndAddOrdered(1); } else { m_connectionLock.unlock(); + m_connectionWaitCondition.wakeAll(); } m_enabled = enabled; @@ -191,8 +194,11 @@ QXcbWindow *platformWindowFromId(xcb_window_t id) #define HANDLE_PLATFORM_WINDOW_EVENT(event_t, window, handler) \ { \ event_t *e = (event_t *)event; \ - if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) \ - platformWindow->handler(e); \ + if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) { \ + QObjectPrivate *d = QObjectPrivate::get(platformWindow->widget()); \ + if (!d->wasDeleted) \ + platformWindow->handler(e); \ + } \ } \ break; @@ -419,100 +425,118 @@ void QXcbConnection::log(const char *file, int line, int sequence) void QXcbConnection::run() { - while (xcb_generic_event_t *event = xcb_wait_for_event(xcb_connection())) { - bool handled = true; + QMutexLocker locker(&m_connectionLock); + fd_set readset; + int xcb_fd = xcb_get_file_descriptor(xcb_connection()); + FD_ZERO(&readset); + FD_SET(xcb_fd, &readset); + int result; + while (true) { + while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { + bool handled = true; + + uint response_type = event->response_type & ~0x80; + + if (!response_type) { + xcb_generic_error_t *error = (xcb_generic_error_t *)event; + + uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); + uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); + + printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n", + int(error->error_code), xcb_errors[clamped_error_code], + int(error->sequence), int(error->resource_id), + int(error->major_code), xcb_protocol_request_codes[clamped_major_code], + int(error->minor_code)); +#ifdef Q_XCB_DEBUG + QMutexLocker locker(&m_callLogMutex); + int i = 0; + for (; i < m_callLog.size(); ++i) { + if (m_callLog.at(i).sequence == error->sequence) { + printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + break; + } else if (m_callLog.at(i).sequence > error->sequence) { + printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); + if (i > 0) + printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line); + break; + } + } + if (i == m_callLog.size() && !m_callLog.isEmpty()) + printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line); +#endif + continue; + } - uint response_type = event->response_type & ~0x80; +#ifdef Q_XCB_DEBUG + { + QMutexLocker locker(&m_callLogMutex); + int i = 0; + for (; i < m_callLog.size(); ++i) + if (m_callLog.at(i).sequence >= event->sequence) + break; + m_callLog.remove(0, i); + } +#endif - if (!response_type) { - xcb_generic_error_t *error = (xcb_generic_error_t *)event; + if (response_type == XCB_CLIENT_MESSAGE) { + xcb_client_message_event_t *ev = (xcb_client_message_event_t *)event; - uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1); - uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1); + if (ev->type == QXcbAtom::_QT_CLOSE_CONNECTION) + return; - printf("XCB error: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d\n", - int(error->error_code), xcb_errors[clamped_error_code], - int(error->sequence), int(error->resource_id), - int(error->major_code), xcb_protocol_request_codes[clamped_major_code], - int(error->minor_code)); -#ifdef Q_XCB_DEBUG - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) { - if (m_callLog.at(i).sequence == error->sequence) { - printf("Caused by: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); - break; - } else if (m_callLog.at(i).sequence > error->sequence) { - printf("Caused some time before: %s:%d\n", qPrintable(m_callLog.at(i).file), m_callLog.at(i).line); - if (i > 0) - printf("and after: %s:%d\n", qPrintable(m_callLog.at(i-1).file), m_callLog.at(i-1).line); - break; + if (ev->type == QXcbAtom::_QT_PAUSE_CONNECTION) { + if (ev->data.data32[0] == uint(m_pauseId)) + m_connectionWaitCondition.wait(&m_connectionLock); + continue; } } - if (i == m_callLog.size() && !m_callLog.isEmpty()) - printf("Caused some time after: %s:%d\n", qPrintable(m_callLog.first().file), m_callLog.first().line); -#endif - continue; - } -#ifdef Q_XCB_DEBUG - { - QMutexLocker locker(&m_callLogMutex); - int i = 0; - for (; i < m_callLog.size(); ++i) - if (m_callLog.at(i).sequence >= event->sequence) - break; - m_callLog.remove(0, i); + switch (response_type) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + case XCB_BUTTON_RELEASE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + case XCB_MOTION_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_CLIENT_MESSAGE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); + case XCB_ENTER_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + case XCB_KEY_RELEASE: + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); + break; + default: + handled = false; + break; + } + if (handled) + printXcbEvent("Handled XCB event", event); + else + printXcbEvent("Unhandled XCB event", event); } -#endif - if (response_type == XCB_CLIENT_MESSAGE - && ((xcb_client_message_event_t *)event)->type == QXcbAtom::_QT_CLOSE_CONNECTION) - return; + do { + result = select(xcb_fd + 1, &readset, 0, 0, 0); + } while (result == -1 && errno == EINTR); - if (response_type == XCB_CLIENT_MESSAGE - && ((xcb_client_message_event_t *)event)->type == QXcbAtom::_QT_PAUSE_CONNECTION) - { - QMutexLocker locker(&m_connectionLock); + if (result <= 0 || !FD_ISSET(xcb_fd, &readset)) continue; - } - switch (response_type) { - case XCB_EXPOSE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - case XCB_BUTTON_PRESS: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - case XCB_BUTTON_RELEASE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - case XCB_MOTION_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); - case XCB_CONFIGURE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); - case XCB_CLIENT_MESSAGE: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); - case XCB_ENTER_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); - case XCB_LEAVE_NOTIFY: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); - case XCB_FOCUS_IN: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); - case XCB_FOCUS_OUT: - HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); - case XCB_KEY_PRESS: - HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); - case XCB_KEY_RELEASE: - HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); - case XCB_MAPPING_NOTIFY: - m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); - break; - default: - handled = false; - break; - } - if (handled) - printXcbEvent("Handled XCB event", event); - else - printXcbEvent("Unhandled XCB event", event); } fprintf(stderr, "I/O error in xcb_wait_for_event\n"); } @@ -714,8 +738,13 @@ void QXcbConnection::initializeAllAtoms() { void QXcbConnection::sync() { // from xcb_aux_sync + bool wasEnabled = m_enabled; + setEventProcessingEnabled(false); xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection())); free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0)); + + if (wasEnabled) + setEventProcessingEnabled(true); } #if defined(XCB_USE_EGL) diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 2723f26..7088184 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -46,6 +46,7 @@ #include <QList> #include <QMutex> #include <QVector> +#include <QWaitCondition> #include <QThread> #define Q_XCB_DEBUG @@ -265,7 +266,7 @@ protected: private: void initializeAllAtoms(); - void sendConnectionEvent(QXcbAtom::Atom atom); + void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); #ifdef XCB_USE_DRI2 void initializeDri2(); #endif @@ -282,6 +283,8 @@ private: xcb_window_t m_connectionEventListener; QMutex m_connectionLock; + QWaitCondition m_connectionWaitCondition; + QAtomicInt m_pauseId; bool m_enabled; QXcbKeyboard *m_keyboard; @@ -326,9 +329,11 @@ cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, } #define Q_XCB_CALL(x) q_xcb_call_template(x, connection(), __FILE__, __LINE__) #define Q_XCB_CALL2(x, connection) q_xcb_call_template(x, connection, __FILE__, __LINE__) +#define Q_XCB_NOOP(c) q_xcb_call_template(xcb_no_operation(c->xcb_connection()), c, __FILE__, __LINE__); #else #define Q_XCB_CALL(x) x #define Q_XCB_CALL2(x, connection) x +#define Q_XCB_NOOP(c) #endif diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index ec9a009..f501c00 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -921,6 +921,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod if (state & 128) col += altGrOffset; + Q_XCB_NOOP(connection()); + #ifdef XCB_KEYBOARD_DEBUG printf("key code: %d, state: %d, syms: ", code, state); for (int i = 0; i <= 5; ++i) { @@ -929,6 +931,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod printf("\n"); #endif + Q_XCB_NOOP(connection()); + xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col); if (sym == XCB_NO_SYMBOL) sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1); @@ -940,6 +944,8 @@ void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycod sym = toupper(sym); } + Q_XCB_NOOP(connection()); + QByteArray chars; Qt::KeyboardModifiers modifiers; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index e997824..7aeb557 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -222,9 +222,7 @@ void QXcbWindow::setVisible(bool visible) xcb_wm_hints_set_normal(&hints); xcb_set_wm_hints(xcb_connection(), m_window, &hints); Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); -#if defined(XCB_USE_GLX) - glXWaitX(); -#endif + connection()->sync(); } else { Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window)); diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp index dd28c31..4c0d862 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp @@ -62,7 +62,7 @@ public: QImage *image() { return &m_qimage; } void put(xcb_window_t window, const QPoint &dst, const QRect &source); - void preparePaint(const QRegion ®ion); + void preparePaint(const QRegion ®ion, QMutex *mutex); private: void destroy(); @@ -84,6 +84,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size) , m_gc(0) , m_gc_window(0) { + Q_XCB_NOOP(connection()); m_xcb_image = xcb_image_create_native(xcb_connection(), size.width(), size.height(), @@ -115,6 +116,7 @@ void QXcbShmImage::destroy() void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source) { + Q_XCB_NOOP(connection()); if (m_gc_window != window) { if (m_gc) Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); @@ -125,6 +127,7 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s m_gc_window = window; } + Q_XCB_NOOP(connection()); xcb_image_shm_put(xcb_connection(), window, m_gc, @@ -137,18 +140,23 @@ void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &s source.width(), source.height(), false); + Q_XCB_NOOP(connection()); m_dirty = m_dirty | source; xcb_flush(xcb_connection()); + Q_XCB_NOOP(connection()); } -void QXcbShmImage::preparePaint(const QRegion ®ion) +void QXcbShmImage::preparePaint(const QRegion ®ion, QMutex *mutex) { // to prevent X from reading from the image region while we're writing to it if (m_dirty.intersects(region)) { connection()->sync(); + mutex->lock(); m_dirty = QRegion(); + } else { + mutex->lock(); } } @@ -162,6 +170,8 @@ QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface) QXcbWindowSurface::~QXcbWindowSurface() { + QMutexLocker locker(&m_surfaceLock); + delete m_image; } QPaintDevice *QXcbWindowSurface::paintDevice() @@ -171,8 +181,7 @@ QPaintDevice *QXcbWindowSurface::paintDevice() void QXcbWindowSurface::beginPaint(const QRegion ®ion) { - m_surfaceLock.lock(); - m_image->preparePaint(region); + m_image->preparePaint(region, &m_surfaceLock); } void QXcbWindowSurface::endPaint(const QRegion &) @@ -185,6 +194,8 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoi Q_UNUSED(region); Q_UNUSED(offset); + Q_XCB_NOOP(connection()); + QXcbWindow *window = static_cast<QXcbWindow *>(widget->window()->platformWindow()); extern QWidgetData* qt_widget_data(QWidget *); @@ -195,18 +206,26 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoi QVector<QRect> rects = region.rects(); for (int i = 0; i < rects.size(); ++i) m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset)); + + Q_XCB_NOOP(connection()); } void QXcbWindowSurface::resize(const QSize &size) { + Q_XCB_NOOP(connection()); QWindowSurface::resize(size); QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(window())); - QMutexLocker locker(&m_surfaceLock); + connection()->setEventProcessingEnabled(false); + m_surfaceLock.lock(); delete m_image; m_image = new QXcbShmImage(screen, size); + Q_XCB_NOOP(connection()); + + m_surfaceLock.unlock(); + connection()->setEventProcessingEnabled(true); } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); @@ -216,12 +235,14 @@ bool QXcbWindowSurface::scroll(const QRegion &area, int dx, int dy) if (m_image->image()->isNull()) return false; - m_image->preparePaint(area); + m_image->preparePaint(area, &m_surfaceLock); const QVector<QRect> rects = area.rects(); for (int i = 0; i < rects.size(); ++i) qt_scrollRectInImage(*m_image->image(), rects.at(i), QPoint(dx, dy)); + m_surfaceLock.unlock(); + return true; } |