From d80ad6a5afce75add282ea1dce0d71927c0c459b Mon Sep 17 00:00:00 2001
From: Ralf Jung <post@ralfj.de>
Date: Thu, 11 Jul 2013 22:50:43 +0200
Subject: [PATCH] Add initial qt version

---
 qt/main.cpp      | 35 +++++++++++++++++++
 qt/multikbd.cpp  | 91 ++++++++++++++++++++++++++++++++++++++++++++++++
 qt/multikbd.h    | 32 +++++++++++++++++
 qt/multikbd.ui   | 73 ++++++++++++++++++++++++++++++++++++++
 qt/multixkbd.pro | 22 ++++++++++++
 5 files changed, 253 insertions(+)
 create mode 100644 qt/main.cpp
 create mode 100644 qt/multikbd.cpp
 create mode 100644 qt/multikbd.h
 create mode 100644 qt/multikbd.ui
 create mode 100644 qt/multixkbd.pro

diff --git a/qt/main.cpp b/qt/main.cpp
new file mode 100644
index 0000000..5b77857
--- /dev/null
+++ b/qt/main.cpp
@@ -0,0 +1,35 @@
+#include "multikbd.h"
+#include <QApplication>
+
+#include <QDebug>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/Xutil.h>
+
+MultiKBD *window;
+
+class QMyApplication : public QApplication
+{
+public:
+	QMyApplication(int argc, char **argv)
+		: QApplication(argc, argv) {}
+
+	virtual bool x11EventFilter ( XEvent * event );
+};
+
+bool QMyApplication::x11EventFilter ( XEvent * event )
+{
+	if (!window) return false;
+	return window->handleX11Event(event);
+}
+
+int main(int argc, char *argv[])
+{
+	QMyApplication a(argc, argv);
+	window = new MultiKBD();
+	window->setAttribute(Qt::WA_DeleteOnClose);
+	window->show();
+	
+	return a.exec();
+}
diff --git a/qt/multikbd.cpp b/qt/multikbd.cpp
new file mode 100644
index 0000000..c43dd20
--- /dev/null
+++ b/qt/multikbd.cpp
@@ -0,0 +1,91 @@
+#include "multikbd.h"
+#include "ui_multikbd.h"
+
+#include <QX11Info>
+#include <QDebug>
+
+#include <X11/Xlib.h>
+#include <X11/extensions/XInput2.h>
+#include <X11/Xutil.h>
+
+MultiKBD::MultiKBD(QWidget *parent) :
+	QWidget(parent),
+	ui(new Ui::MultiKBD),
+	xiInited(false)
+{
+	ui->setupUi(this);
+}
+
+MultiKBD::~MultiKBD()
+{
+	delete ui;
+}
+
+void MultiKBD::showEvent ( QShowEvent * )
+{
+	if (xiInited) return;
+
+	Display *dpy = x11Info().display();
+
+	/* XInput Extension available? */
+	int eventID, errorID;
+	if (!XQueryExtension(dpy, "XInputExtension", &xiOpcode, &eventID, &errorID)) {
+	   qCritical() << "X Input extension not available";
+	}
+
+	/* Which version of XI2? We support 2.0 */
+	int major = 2, minor = 0;
+	if (XIQueryVersion(dpy, &major, &minor) == BadRequest) {
+		qCritical() << "XI2 not available. Server supports" << major << "." <<
+					minor;
+	}
+
+	qDebug() << "System is sane";
+
+
+	// Now let's listen to keypress events
+	XIEventMask eventmask;
+	unsigned char mask [1] = { 0 }; // will change
+	eventmask.deviceid = XIAllMasterDevices;
+	eventmask.mask_len = sizeof (mask); // in bytes, for whatever reason...
+	eventmask.mask = mask;
+	XISetMask(mask, XI_KeyPress);
+	XISelectEvents (dpy, winId(), &eventmask, 1);
+
+	xiInited = true;
+
+	/*activateWindow();
+	raise();
+	setFocus(Qt::OtherFocusReason);*/
+}
+
+void MultiKBD::handleKeyPress(int device, const char *string)
+{
+	qDebug() << "Device" << device << "String" << string;
+}
+
+bool MultiKBD::handleX11Event(XEvent *event)
+{
+	if (!xiInited) return false;
+	Display *dpy = x11Info().display();
+
+	if (event->xcookie.type == GenericEvent && event->xcookie.extension == xiOpcode
+		&& event->xcookie.evtype == XI_KeyPress && XGetEventData(dpy, &event->xcookie)) {
+
+		XIDeviceEvent *d_ev = (XIDeviceEvent*) event->xcookie.data;
+	    KeyCode keycode = d_ev->detail;
+	    int kbdid = d_ev->deviceid;
+
+		if (!(d_ev->flags & XIKeyRepeat)) {
+			int keysyms_per_keycode;
+			KeySym keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode)[0];
+			handleKeyPress(kbdid, XKeysymToString(keysym));
+		}
+
+		XFreeEventData(dpy, &event->xcookie);
+
+		return true;
+	}
+
+	return false;
+}
diff --git a/qt/multikbd.h b/qt/multikbd.h
new file mode 100644
index 0000000..d7fd3c9
--- /dev/null
+++ b/qt/multikbd.h
@@ -0,0 +1,32 @@
+#ifndef MULTIKBD_H
+#define MULTIKBD_H
+
+#include <QWidget>
+
+namespace Ui {
+class MultiKBD;
+}
+
+class MultiKBD : public QWidget
+{
+	Q_OBJECT
+	
+public:
+	explicit MultiKBD(QWidget *parent = 0);
+	~MultiKBD();
+
+	bool handleX11Event(XEvent *event);
+
+protected:
+	virtual void showEvent (QShowEvent *);
+
+private:
+	void handleKeyPress(int device, const char *string);
+
+private:
+	Ui::MultiKBD *ui;
+	bool xiInited;
+	int xiOpcode;
+};
+
+#endif // MULTIKBD_H
diff --git a/qt/multikbd.ui b/qt/multikbd.ui
new file mode 100644
index 0000000..552fab4
--- /dev/null
+++ b/qt/multikbd.ui
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MultiKBD</class>
+ <widget class="QWidget" name="MultiKBD">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>400</width>
+    <height>300</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>MultiKBD</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QRadioButton" name="radioButton">
+     <property name="text">
+      <string>RadioButton1</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QRadioButton" name="radioButton_2">
+     <property name="text">
+      <string>RadioButton2</string>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>211</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+   <item>
+    <widget class="QPushButton" name="pushButton">
+     <property name="text">
+      <string>Close</string>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <layoutdefault spacing="6" margin="11"/>
+ <resources/>
+ <connections>
+  <connection>
+   <sender>pushButton</sender>
+   <signal>clicked()</signal>
+   <receiver>MultiKBD</receiver>
+   <slot>close()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>199</x>
+     <y>283</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>199</x>
+     <y>149</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+</ui>
diff --git a/qt/multixkbd.pro b/qt/multixkbd.pro
new file mode 100644
index 0000000..1bea7f1
--- /dev/null
+++ b/qt/multixkbd.pro
@@ -0,0 +1,22 @@
+#-------------------------------------------------
+#
+# Project created by QtCreator 2013-07-10T20:33:44
+#
+#-------------------------------------------------
+
+QT       += core gui
+
+greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
+
+TARGET = multixkbd
+TEMPLATE = app
+
+
+SOURCES += main.cpp\
+        multikbd.cpp
+
+HEADERS  += multikbd.h
+
+FORMS    += multikbd.ui
+
+LIBS += -lX11 -lXi
-- 
2.39.5