Fwd: [kdelibs/frameworks] tier1/kidletime/src: Port the native event filtering to XCB, to fix compilation with Qt5.

David Faure faure at kde.org
Wed Jul 25 08:12:03 UTC 2012


Hi Fredrik,
I made progress with the port of kidletime to XCB, but I found a bug in XCB...

xcb/sync.h says (with my comments added about field size) :

typedef struct xcb_sync_systemcounter_t {
    xcb_sync_counter_t counter; /**<  */                  // 4 bytes
    xcb_sync_int64_t   resolution; /**<  */               // 8 bytes
    uint16_t           name_len; /**<  */                 // 2 bytes
} xcb_sync_systemcounter_t; // sizeof says 16 bytes due to padding

but sync.c (in the XCB sources) says:

char *
xcb_sync_systemcounter_name (const xcb_sync_systemcounter_t *R  /**< */)
{
    return (char *) (R + 1);
}

Shouldn't that be

char *
xcb_sync_systemcounter_name (const xcb_sync_systemcounter_t *R  /**< */)
{
    return (char *) (R) + 14;
}

(gdb confirms that the name is after the struct, as I expected).

Apparently this comes from c_client.py, in the code that says
        if field.prev_varsized_field == None:
            _c('    i.data = (%s *) (R + 1);', field.c_field_type)
which comes from field.type.fixed_size(), but I can't find the definition of
fixed_size() anywhere...

Well, maybe this is fixed in a more recent XCB than 1.7?

Do you know XCB developers, or where to report such issues?

If you want to give it a try, see the commit below (the code is commented out for now).

Also, the alarms don't trigger, so I wonder if this is another bug in xcb, or if my
port (which mixes the use of XCB and X11) is faulty...

If you could have a look, that would be awesome ;)

Instructions for compiling kdelibs-frameworks with Qt5 are available at
http://community.kde.org/Frameworks/Building#Building_KDE_frameworks_with_Qt_5

----------  Forwarded Message  ----------

Subject: [kdelibs/frameworks] tier1/kidletime/src: Port the native event filtering to XCB, to fix compilation with Qt5.
Date: Wednesday 25 July 2012, 09:32:35
From: David Faure <faure at kde.org>
To: kde-commits at kde.org

Git commit 65f117248744662f18ca4a03bcb7841087eda92b by David Faure.
Committed on 24/07/2012 at 22:22.
Pushed by dfaure into branch 'frameworks'.

Port the native event filtering to XCB, to fix compilation with Qt5.

Started to port the rest of the code to XCB too, but found a bug in
xcb_sync_systemcounter_name()...

Idle detection doesn't fully work, maybe due to another bug, or maybe
due to the X11/XCB mix in here.

M  +5    -2    tier1/kidletime/src/CMakeLists.txt
M  +55   -31   tier1/kidletime/src/xsyncbasedpoller.cpp
M  +5    -4    tier1/kidletime/src/xsyncbasedpoller.h

http://commits.kde.org/kdelibs/65f117248744662f18ca4a03bcb7841087eda92b

diff --git a/tier1/kidletime/src/CMakeLists.txt b/tier1/kidletime/src/CMakeLists.txt
index 4c178aa..973d623 100644
--- a/tier1/kidletime/src/CMakeLists.txt
+++ b/tier1/kidletime/src/CMakeLists.txt
@@ -17,8 +17,11 @@ else ()
    set (HAVE_XSCREENSAVER 0)
 endif ()
 
-if (X11_XSync_FOUND)
+find_package(XCB)
+find_package(X11_XCB)
+if (QT5_BUILD AND X11_XSync_FOUND AND XCB_XCB_FOUND AND X11_XCB_FOUND AND XCB_SYNC_FOUND)
    set (HAVE_XSYNC 1)
+   include_directories( ${XCB_XCB_INCLUDE_DIR} ${XCB_SYNC_INCLUDE_DIR})
 else ()
    set (HAVE_XSYNC 0)
 endif ()
@@ -56,7 +59,7 @@ if (X11_FOUND)
       target_link_libraries(kidletime ${X11_Xscreensaver_LIB} ${QT_QTDBUS_LIBRARY})
    endif ()
    if (HAVE_XSYNC)
-      target_link_libraries(kidletime ${X11_Xext_LIB})
+      target_link_libraries(kidletime ${X11_Xext_LIB} ${XCB_XCB_LIBRARIES} ${X11_XCB_LIBRARIES} ${XCB_SYNC_LIBRARIES})
    endif ()
    target_link_libraries(kidletime ${X11_LIBRARIES} ${kdeqt5staging_LIBRARY})
 endif ()
diff --git a/tier1/kidletime/src/xsyncbasedpoller.cpp b/tier1/kidletime/src/xsyncbasedpoller.cpp
index fd426f8..e43612d 100644
--- a/tier1/kidletime/src/xsyncbasedpoller.cpp
+++ b/tier1/kidletime/src/xsyncbasedpoller.cpp
@@ -16,20 +16,31 @@
    Boston, MA 02110-1301, USA.
 */
 
+// Exceptionnally, include QCoreApplication before our own header, because that one includes X11 headers (#define None...)
+#include <QCoreApplication>
+
 #include "xsyncbasedpoller.h"
 
-#include <QAbstractEventDispatcher>
+#include <QAbstractNativeEventFilter>
 #include <QX11Info>
+#include <X11/Xlib-xcb.h> // XGetXCBConnection
+#include <xcb/sync.h>
 
-class XSyncBasedPollerHelper
+class XSyncBasedPollerHelper : public QAbstractNativeEventFilter
 {
 public:
-    XSyncBasedPollerHelper() : q(0), origFilter(0), isActive(false) {}
+    XSyncBasedPollerHelper() : q(0), isActive(false) {}
     ~XSyncBasedPollerHelper() {
         delete q;
     }
+    bool nativeEventFilter(const QByteArray& eventType, void *message, long *result) {
+        Q_UNUSED(result);
+        if (isActive && eventType == "xcb_generic_event_t") {
+            q->xcbEvent(reinterpret_cast<xcb_generic_event_t *>(message));
+        }
+        return false;
+    }
     XSyncBasedPoller *q;
-    QAbstractEventDispatcher::EventFilter origFilter;
     bool isActive;
 };
 
@@ -47,19 +58,41 @@ XSyncBasedPoller *XSyncBasedPoller::instance()
 XSyncBasedPoller::XSyncBasedPoller(QWidget *parent)
         : AbstractSystemPoller(parent)
         , m_display(QX11Info::display())
+        , m_xcb_connection(XGetXCBConnection(m_display))
         , m_idleCounter(None)
         , m_resetAlarm(None)
         , m_available(true)
 {
     Q_ASSERT(!s_globalXSyncBasedPoller()->q);
     s_globalXSyncBasedPoller()->q = this;
-    s_globalXSyncBasedPoller()->origFilter = QAbstractEventDispatcher::instance()->setEventFilter(XSyncBasedPoller::eventDispatcherFilter);
+    QCoreApplication::instance()->installNativeEventFilter(s_globalXSyncBasedPoller());
 
-    int sync_major, sync_minor;
-    int ncounters;
-    XSyncSystemCounter *counters;
+    const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(m_xcb_connection, &xcb_sync_id);
+    if (!sync_reply || !sync_reply->present) {
+        qDebug() << "xcb sync extension not found";
+        m_available = false;
+        return;
+    }
+    m_sync_event = sync_reply->first_event;
+
+#if 0
+    xcb_sync_list_system_counters_cookie_t cookie = xcb_sync_list_system_counters(m_xcb_connection);
+    xcb_sync_list_system_counters_reply_t* reply = xcb_sync_list_system_counters_reply(m_xcb_connection, cookie, NULL);
+    int xcbcounters = xcb_sync_list_system_counters_counters_length(reply);
+    xcb_sync_systemcounter_iterator_t it = xcb_sync_list_system_counters_counters_iterator(reply);
+    for (int i = 0; i < xcbcounters; ++i) {
+        qDebug() << it.data->counter << it.rem << it.index;
+        qDebug() << "name length" << xcb_sync_systemcounter_name_length(it.data);
+        QByteArray name(xcb_sync_systemcounter_name(it.data), xcb_sync_systemcounter_name_length(it.data));
+        qDebug() << name;
+        xcb_sync_systemcounter_next(&it);
+    }
+    delete reply;
+#endif
 
-    if (!XSyncQueryExtension(m_display, &m_sync_event, &m_sync_error)) {
+    int sync_major, sync_minor;
+    int old_sync_event, old_sync_error;
+    if (!XSyncQueryExtension(m_display, &old_sync_event, &old_sync_error)) {
         m_available = false;
         return;
     }
@@ -69,13 +102,14 @@ XSyncBasedPoller::XSyncBasedPoller(QWidget *parent)
         return;
     }
 
-    qDebug() << sync_major << sync_minor;
-
-    counters = XSyncListSystemCounters(m_display, &ncounters);
+    int ncounters;
+    XSyncSystemCounter *counters = XSyncListSystemCounters(m_display, &ncounters);
 
     bool idleFound = false;
 
+    qDebug() << ncounters << "counters";
     for (int i = 0; i < ncounters; ++i) {
+        qDebug() << counters[i].name << counters[i].counter;
         if (!strcmp(counters[i].name, "IDLETIME")) {
             m_idleCounter = counters[i].counter;
             idleFound = true;
@@ -215,21 +249,22 @@ void XSyncBasedPoller::reloadAlarms()
     }
 }
 
-bool XSyncBasedPoller::x11Event(XEvent *event)
+bool XSyncBasedPoller::xcbEvent(xcb_generic_event_t *event)
 {
-    XSyncAlarmNotifyEvent *alarmEvent;
-
-    if (event->type != m_sync_event + XSyncAlarmNotify) {
+    //qDebug() << event->response_type << "waiting for" << m_sync_event+XCB_SYNC_ALARM_NOTIFY;
+    if (event->response_type != m_sync_event + XCB_SYNC_ALARM_NOTIFY) {
         return false;
     }
 
-    alarmEvent = (XSyncAlarmNotifyEvent *)event;
+    xcb_sync_alarm_notify_event_t* alarmEvent = reinterpret_cast<xcb_sync_alarm_notify_event_t *>(event);
 
-    if (alarmEvent->state == XSyncAlarmDestroyed) {
+    if (alarmEvent->state == XCB_SYNC_ALARMSTATE_DESTROYED) {
         return false;
     }
+    qDebug() << "alarm=" << alarmEvent->alarm;
 
     for (QHash<int, XSyncAlarm>::const_iterator i = m_timeoutAlarm.constBegin(); i != m_timeoutAlarm.constEnd(); ++i) {
+        qDebug() << "   looking at" << i.value();
         if (alarmEvent->alarm == i.value()) {
             /* Bling! Caught! */
             Q_EMIT timeoutReached(i.key());
@@ -268,9 +303,11 @@ void XSyncBasedPoller::setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter co
             XSyncCAValue | XSyncCADelta;
 
     if (*alarm) {
+        //xcb_sync_change_alarm_checked(m_xcb_connection, alarmId,  ...
         XSyncChangeAlarm(dpy, *alarm, flags, &attr);
     } else {
         *alarm = XSyncCreateAlarm(dpy, flags, &attr);
+        qDebug() << "Created alarm" << *alarm;
     }
 }
 
@@ -279,16 +316,3 @@ void XSyncBasedPoller::simulateUserActivity()
     XResetScreenSaver(QX11Info::display());
 }
 
-bool XSyncBasedPoller::eventDispatcherFilter(void *message)
-{
-    if (s_globalXSyncBasedPoller()->origFilter)
-        s_globalXSyncBasedPoller()->origFilter(message);
-
-    if (s_globalXSyncBasedPoller()->isActive) {
-        XEvent *event = reinterpret_cast<XEvent*>(message);
-        return instance()->x11Event(event);
-    } else {
-        return false;
-    }
-}
-
diff --git a/tier1/kidletime/src/xsyncbasedpoller.h b/tier1/kidletime/src/xsyncbasedpoller.h
index e2616d4..3b5e4bb 100644
--- a/tier1/kidletime/src/xsyncbasedpoller.h
+++ b/tier1/kidletime/src/xsyncbasedpoller.h
@@ -27,6 +27,7 @@
 
 #include <X11/Xlib.h>
 #include <X11/extensions/sync.h>
+#include <xcb/xcb.h>
 
 class XSyncBasedPoller : public AbstractSystemPoller
 {
@@ -41,8 +42,8 @@ public:
     bool setUpPoller();
     void unloadPoller();
 
+    bool xcbEvent(xcb_generic_event_t *event);
 protected:
-    bool x11Event(XEvent *event);
     XSyncBasedPoller(QWidget *parent = 0);
 
 public Q_SLOTS:
@@ -62,11 +63,11 @@ private:
     void setAlarm(Display *dpy, XSyncAlarm *alarm, XSyncCounter counter,
                   XSyncTestType test, XSyncValue value);
 
-    static bool eventDispatcherFilter(void *message);
-
 private:
     Display * m_display;
-    int                 m_sync_event, m_sync_error;
+    xcb_connection_t *m_xcb_connection;
+
+    int                 m_sync_event;
     XSyncCounter        m_idleCounter;
     QHash<int, XSyncAlarm>   m_timeoutAlarm;
     XSyncAlarm          m_resetAlarm;

-----------------------------------------
-- 
David Faure, faure at kde.org, http://www.davidfaure.fr
Sponsored by Nokia to work on KDE, incl. KDE Frameworks 5



More information about the Kde-frameworks-devel mailing list