diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-06 15:17:50 (GMT) |
---|---|---|
committer | Samuel Rødal <samuel.rodal@nokia.com> | 2011-04-07 11:23:35 (GMT) |
commit | 3a7a03f5ab0f927211050d2dcceb9440e2b0aeeb (patch) | |
tree | 274a88c1a714e3ef9e42f79283168bf79a6040f0 /src/plugins/platforms | |
parent | dfa586395b0dabbf6b81e77625a4f8d43ee9a80d (diff) | |
download | Qt-3a7a03f5ab0f927211050d2dcceb9440e2b0aeeb.zip Qt-3a7a03f5ab0f927211050d2dcceb9440e2b0aeeb.tar.gz Qt-3a7a03f5ab0f927211050d2dcceb9440e2b0aeeb.tar.bz2 |
Implemented _NET_WM_SYNC_REQUEST protocol in XCB plugin.
Excluded KWin for now, as it sends multiple ConfigureNotify events per
_NET_WM_SYNC_REQUEST message.
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/xcb/README | 3 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 59 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 36 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 48 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 9 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindowsurface.cpp | 13 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindowsurface.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb.pro | 2 |
10 files changed, 146 insertions, 32 deletions
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README index e88596b..17a86e6 100644 --- a/src/plugins/platforms/xcb/README +++ b/src/plugins/platforms/xcb/README @@ -1,2 +1,3 @@ Required packages: -libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev libxcb-sync0 libxcb-sync0-dev + diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 84d98e8..2413a32 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -105,6 +105,8 @@ QXcbConnection::QXcbConnection(const char *displayName) #endif //XCB_USE_XLIB m_setup = xcb_get_setup(xcb_connection()); + initializeAllAtoms(); + xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int screenNumber = 0; @@ -115,8 +117,6 @@ QXcbConnection::QXcbConnection(const char *displayName) m_keyboard = new QXcbKeyboard(this); - initializeAllAtoms(); - #ifdef XCB_USE_DRI2 initializeDri2(); #endif @@ -379,6 +379,34 @@ void QXcbConnection::log(const char *file, int line, int sequence) } #endif +void QXcbConnection::handleXcbError(xcb_generic_error_t *error) +{ + 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 + 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 +} + void QXcbConnection::processXcbEvents() { while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { @@ -387,32 +415,7 @@ void QXcbConnection::processXcbEvents() 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 - 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 + handleXcbError((xcb_generic_error_t *)event); continue; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 53846f1..e38b44e 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -252,6 +252,7 @@ public: #endif void sync(); + void handleXcbError(xcb_generic_error_t *error); private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 49ed44c..1c12ee3 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -66,6 +66,42 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int num }; xcb_change_window_attributes(xcb_connection(), screen->root, mask, values); + + xcb_generic_error_t *error; + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), + xcb_get_property(xcb_connection(), false, screen->root, + atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK), + XCB_ATOM_WINDOW, 0, 1024), &error); + + if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) { + xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply)); + + if (windowManager != XCB_WINDOW_NONE) { + xcb_get_property_reply_t *windowManagerReply = + xcb_get_property_reply(xcb_connection(), + xcb_get_property(xcb_connection(), false, windowManager, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), 0, 1024), &error); + 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)); + printf("Running window manager: %s\n", qPrintable(m_windowManagerName)); + } else if (error) { + connection->handleXcbError(error); + free(error); + } + + free(windowManagerReply); + } + } else if (error) { + connection->handleXcbError(error); + free(error); + } + + free(reply); + + m_syncRequestSupported = m_windowManagerName != QLatin1String("KWin"); } QXcbScreen::~QXcbScreen() diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 6f69fc7..9547d01 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -43,6 +43,7 @@ #define QXCBSCREEN_H #include <QtGui/QPlatformScreen> +#include <QtCore/QString> #include <xcb/xcb.h> @@ -66,9 +67,14 @@ public: xcb_screen_t *screen() const { return m_screen; } xcb_window_t root() const { return m_screen->root; } + QString windowManagerName() const { return m_windowManagerName; } + bool syncRequestSupported() const { return m_syncRequestSupported; } + private: xcb_screen_t *m_screen; int m_number; + QString m_windowManagerName; + bool m_syncRequestSupported; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4a9409c..1e9a0f8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -41,6 +41,8 @@ #include "qxcbwindow.h" +#include <QtDebug> + #include "qxcbconnection.h" #include "qxcbscreen.h" #ifdef XCB_USE_DRI2 @@ -171,6 +173,9 @@ QXcbWindow::QXcbWindow(QWidget *tlw) properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); + if (m_screen->syncRequestSupported()) + properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); + if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); @@ -178,10 +183,26 @@ QXcbWindow::QXcbWindow(QWidget *tlw) XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::WM_PROTOCOLS), - 4, + XCB_ATOM_ATOM, 32, propertyCount, properties)); + m_syncValue.hi = 0; + m_syncValue.lo = 0; + + if (m_screen->syncRequestSupported()) { + m_syncCounter = xcb_generate_id(xcb_connection()); + Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue)); + + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER), + XCB_ATOM_CARDINAL, + 32, + 1, + &m_syncCounter)); + } if (isTransient(tlw) && tlw->parentWidget()) { // ICCCM 4.1.2.6 @@ -197,6 +218,8 @@ QXcbWindow::QXcbWindow(QWidget *tlw) QXcbWindow::~QXcbWindow() { delete m_context; + if (m_screen->syncRequestSupported()) + Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter)); Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window)); } @@ -474,6 +497,13 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even xcb_send_event(xcb_connection(), 0, m_screen->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&reply); xcb_flush(xcb_connection()); + } else if (event->data.data32[0] == atom(QXcbAtom::_NET_WM_SYNC_REQUEST)) { + if (!m_hasReceivedSyncRequest) { + m_hasReceivedSyncRequest = true; + printf("Window manager supports _NET_WM_SYNC_REQUEST, syncing resizes\n"); + } + m_syncValue.lo = event->data.data32[2]; + m_syncValue.hi = event->data.data32[3]; } } } @@ -489,8 +519,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } QRect rect(xpos, ypos, event->width, event->height); - QPlatformWindow::setGeometry(rect); + if (rect == geometry()) + return; + + QPlatformWindow::setGeometry(rect); QWindowSystemInterface::handleGeometryChange(widget(), rect); #if XCB_USE_DRI2 @@ -593,3 +626,14 @@ void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) QWindowSystemInterface::handleWindowActivated(0); } +void QXcbWindow::updateSyncRequestCounter() +{ + if (m_screen->syncRequestSupported() && m_syncValue.lo != 0 || m_syncValue.hi != 0) { + Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue)); + xcb_flush(xcb_connection()); + connection()->sync(); + + m_syncValue.lo = 0; + m_syncValue.hi = 0; + } +} diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 1e9930d..0fa4d0f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -46,6 +46,7 @@ #include <QtGui/QPlatformWindowFormat> #include <xcb/xcb.h> +#include <xcb/sync.h> #include "qxcbobject.h" @@ -88,11 +89,19 @@ public: void handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global); + void updateSyncRequestCounter(); + private: + QXcbScreen *m_screen; xcb_window_t m_window; QPlatformGLContext *m_context; + + xcb_sync_int64_t m_syncValue; + xcb_sync_counter_t m_syncCounter; + + bool m_hasReceivedSyncRequest; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp index c068d1c..718f093 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp @@ -170,6 +170,7 @@ void QXcbShmImage::preparePaint(const QRegion ®ion) QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface) : QWindowSurface(widget, setDefaultSurface) , m_image(0) + , m_syncingResize(false) { QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget)); setConnection(screen->connection()); @@ -213,10 +214,20 @@ void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoi m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset)); Q_XCB_NOOP(connection()); + + if (m_syncingResize) { + xcb_flush(xcb_connection()); + connection()->sync(); + m_syncingResize = false; + window->updateSyncRequestCounter(); + } } void QXcbWindowSurface::resize(const QSize &size) { + if (size == QWindowSurface::size()) + return; + Q_XCB_NOOP(connection()); QWindowSurface::resize(size); @@ -225,6 +236,8 @@ void QXcbWindowSurface::resize(const QSize &size) delete m_image; m_image = new QXcbShmImage(screen, size); Q_XCB_NOOP(connection()); + + m_syncingResize = true; } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.h b/src/plugins/platforms/xcb/qxcbwindowsurface.h index f87e122..23d32ef 100644 --- a/src/plugins/platforms/xcb/qxcbwindowsurface.h +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.h @@ -66,6 +66,7 @@ public: private: QXcbShmImage *m_image; + bool m_syncingResize; }; #endif diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index 122cb40..101bdcd 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -62,7 +62,7 @@ contains(QT_CONFIG, opengl) { } } -LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm +LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm -lxcb-sync include (../fontdatabases/genericunix/genericunix.pri) |