Browse Source

use qt native event filter instead of xlib directly

master
Guillaume Castagnino 2 years ago
parent
commit
40af227b7f
  1. 6
      fookb.cpp
  2. 5
      fookb.pro
  3. 23
      xcbEventFilter.cpp
  4. 14
      xcbEventFilter.h
  5. 75
      xlib_wrapper.cpp
  6. 17
      xlib_wrapper.h

6
fookb.cpp

@ -2,7 +2,7 @@
#include <QQmlApplicationEngine>
#include <QDebug>
#include "xlib_wrapper.h"
#include "xcbEventFilter.h"
int main(int argc, char *argv[])
{
@ -11,7 +11,9 @@ int main(int argc, char *argv[])
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/fookb.qml")));
XlibWrapper xlib;
// Install event filter to handle mapping change
XcbEventFilter eventFilter;
app.installNativeEventFilter(&eventFilter);
return app.exec();
}

5
fookb.pro

@ -1,8 +1,7 @@
SOURCES = fookb.cpp \
xlib_wrapper.cpp
HEADERS = xlib_wrapper.h
xcbEventFilter.cpp
HEADERS = xcbEventFilter.h
TARGET = fookb
RESOURCES = fookb.qrc
QT += widgets qml
QMAKE_LFLAGS +=-lX11

23
xcbEventFilter.cpp

@ -0,0 +1,23 @@
#include "xcbEventFilter.h"
#include <QApplication>
#include <QDebug>
#include <xcb/xcb.h>
XcbEventFilter::XcbEventFilter()
{
}
XcbEventFilter::~XcbEventFilter()
{
}
bool XcbEventFilter::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
if (eventType == "xcb_generic_event_t") {
xcb_generic_event_t* ev = static_cast<xcb_generic_event_t *>(message);
qDebug() << "XCB Event";
// ...
}
return false;
}

14
xcbEventFilter.h

@ -0,0 +1,14 @@
#ifndef XCB_EVENT_FILTER_H
#define XCB_EVENT_FILTER_H
#include <QAbstractNativeEventFilter>
class XcbEventFilter : public QAbstractNativeEventFilter
{
public:
XcbEventFilter();
~XcbEventFilter() override;
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override;
};
#endif // XCB_EVENT_FILTER_H

75
xlib_wrapper.cpp

@ -1,75 +0,0 @@
#include "xlib_wrapper.h"
#include <QApplication>
#include <QDebug>
/* X Window headers */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
/* XKB fun */
#include <X11/XKBlib.h>
XlibWrapper::XlibWrapper()
{
timer = new QTimer(this);
timer->setSingleShot(true);
connect(timer, SIGNAL(timeout()),
this, SLOT(XlibWrapperSlot()));
timer->start(1000);
}
/* Instead of this, should subscribe to the correct QEvent */
/*
* https://doc.qt.io/qt-5/qabstractnativeeventfilter.html
*
* case XCB_MAPPING_NOTIFY:
m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event);
break;
*/
void XlibWrapper::XlibWrapperSlot()
{
int event_rtrn;
int error_rtrn;
int reason_rtrn;
Display *dpy;
XkbEvent labuda;
int state = 0;
qDebug() << "Timer...";
dpy = XkbOpenDisplay(NULL,
&event_rtrn,
&error_rtrn, NULL, NULL, &reason_rtrn);
if (dpy == NULL) {
qDebug() << "Cannot open display";
qApp->quit();
}
/* We would like receive the only Xkb event: XkbStateNotify. And only
* when XkbLockGroup happens. */
if (False == XkbSelectEvents(dpy,
XkbUseCoreKbd,
XkbAllEventsMask,
0)) {
qDebug() << "Cannot XkbSelectEvents.";
qApp->quit();
}
if (False == XkbSelectEventDetails(dpy,
XkbUseCoreKbd,
XkbStateNotify,
XkbAllEventsMask,
XkbGroupLockMask)) {
qDebug() << "Cannot XkbSelectEventDetails.";
qApp->quit();
}
while (1) {
XNextEvent(dpy, &labuda.core);
state = labuda.state.group;
/* Should not be necessary, here works only with 2 keyboard dispositions */
if ((state < 0) || (state > 1))
state = 1;
qDebug() << "XNextEvent";
/* TODO: update flag depending on state */
}
}

17
xlib_wrapper.h

@ -1,17 +0,0 @@
#ifndef XLIB_WRAPPER_H
#define XLIB_WRAPPER_H
#include <QTimer>
class XlibWrapper : public QObject
{
Q_OBJECT
public:
XlibWrapper();
QTimer *timer;
public slots:
void XlibWrapperSlot();
};
#endif // XLIB_WRAPPER_H
Loading…
Cancel
Save