summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@digia.com>2012-11-12 17:02:17 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2012-11-14 10:36:38 +0100
commit4334e0fcc60497da73671063deb68fb1661f864c (patch)
treec5dad9e23c375e4fb8879e645c7603f2aa903add
parent5055183bc5a8288976f58c65b52276ad17491cad (diff)
Added expose and configure event compression in xcb platform plugin.
We had this in 4.x to prevend swamping the event queue and causing a lot of needless processing of stale events. Task-number: QTBUG-27734 Change-Id: I020fe44885569f5a68c07220fcb44bea3e138089 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp16
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp45
2 files changed, 60 insertions, 1 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 78f1efb745..405a16d488 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -969,6 +969,22 @@ void QXcbConnection::processXcbEvents()
continue;
}
+ if (response_type == XCB_CONFIGURE_NOTIFY) {
+ // compress multiple configure notify events for the same window
+ bool found = false;
+ for (int j = i; j < eventqueue->size(); ++j) {
+ xcb_generic_event_t *other = eventqueue->at(j);
+ if (other && (other->response_type & ~0x80) == XCB_CONFIGURE_NOTIFY
+ && ((xcb_configure_notify_event_t *)other)->event == ((xcb_configure_notify_event_t *)event)->event)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (found)
+ continue;
+ }
+
QVector<PeekFunc>::iterator it = m_peekFuncs.begin();
while (it != m_peekFuncs.end()) {
// These callbacks return true if the event is what they were
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index b6bbbdcc30..e0f5dbc435 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1303,6 +1303,42 @@ QXcbEGLSurface *QXcbWindow::eglSurface() const
}
#endif
+class ExposeCompressor
+{
+public:
+ ExposeCompressor(xcb_window_t window, QRegion *region)
+ : m_window(window)
+ , m_region(region)
+ , m_pending(true)
+ {
+ }
+
+ bool checkEvent(xcb_generic_event_t *event)
+ {
+ if (!event)
+ return false;
+ if ((event->response_type & ~0x80) != XCB_EXPOSE)
+ return false;
+ xcb_expose_event_t *expose = (xcb_expose_event_t *)event;
+ if (expose->window != m_window)
+ return false;
+ if (expose->count == 0)
+ m_pending = false;
+ *m_region |= QRect(expose->x, expose->y, expose->width, expose->height);
+ return true;
+ }
+
+ bool pending() const
+ {
+ return m_pending;
+ }
+
+private:
+ xcb_window_t m_window;
+ QRegion *m_region;
+ bool m_pending;
+};
+
void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
QRect rect(event->x, event->y, event->width, event->height);
@@ -1312,8 +1348,15 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
else
m_exposeRegion |= rect;
+ ExposeCompressor compressor(m_window, &m_exposeRegion);
+ xcb_generic_event_t *filter = 0;
+ do {
+ filter = connection()->checkEvent(compressor);
+ free(filter);
+ } while (filter);
+
// if count is non-zero there are more expose events pending
- if (event->count == 0) {
+ if (event->count == 0 || !compressor.pending()) {
QWindowSystemInterface::handleExposeEvent(window(), m_exposeRegion);
m_exposeRegion = QRegion();
}