638114cde667c80b15703d107d4589e3e4ee3bd9
[multypo.git] / qt / multypo.cpp
1 #include "multypo.h"
2
3 #include <QX11Info>
4 #include <QDebug>
5 #include <QHBoxLayout>
6 #include <QLabel>
7
8 #include <X11/Xlib.h>
9 #include <X11/extensions/XInput2.h>
10 #include <X11/Xutil.h>
11
12 MultypoWindow::MultypoWindow(QWidget *parent) :
13         QWidget(parent),
14         xiInited(false)
15 {
16         QHBoxLayout *layout = new QHBoxLayout(this);
17         setLayout(layout);
18
19         mainLabel = new QLabel(this);
20         layout->addWidget(mainLabel);
21
22         setMinimumSize(300, 300);
23 }
24
25 MultypoWindow::~MultypoWindow()
26 {
27 }
28
29 void MultypoWindow::handleKeyPress(int device, QString string)
30 {
31         qDebug() << "Device" << device << "String" << string;
32         mainLabel->setText(QString("%1 pressed on %2").arg(string).arg(device));
33 }
34
35 bool MultypoWindow::handleX11Event(XEvent *event)
36 {
37         Display *dpy = x11Info().display();
38         /* Handle the first map event: We are finally visible! */
39         if (!xiInited && event->type == MapNotify) {
40                 /* XInput Extension available? */
41                 int eventID, errorID;
42                 if (!XQueryExtension(dpy, "XInputExtension", &xiOpcode, &eventID, &errorID)) {
43                    qCritical() << "X Input extension not available";
44                 }
45
46                 /* Which version of XI2? We support 2.0 */
47                 int major = 2, minor = 0;
48                 if (XIQueryVersion(dpy, &major, &minor) == BadRequest) {
49                         qCritical() << "XI2 not available. Server supports" << major << "." <<
50                                                 minor;
51                 }
52
53                 qDebug() << "System supports XI2";
54
55
56                 // Now let's listen to keypress events
57                 XIEventMask eventmask;
58                 unsigned char mask [1] = { 0 }; // will change
59                 eventmask.deviceid = XIAllMasterDevices;
60                 eventmask.mask_len = sizeof (mask); // in bytes, for whatever reason...
61                 eventmask.mask = mask;
62                 XISetMask(mask, XI_KeyPress);
63                 XISelectEvents (dpy, winId(), &eventmask, 1);
64
65                 // finally, grab all focuses
66                 int ndevices;
67                 XIDeviceInfo* devices = XIQueryDevice(dpy, XIAllMasterDevices, &ndevices);
68                 for (int i = 0; i < ndevices; ++i) {
69                         if (devices[i].use != XIMasterKeyboard) continue;
70                         qDebug() << "Found master keyboard with ID" << devices[i].deviceid;
71                         XISetFocus(dpy, devices[i].deviceid, winId(), CurrentTime);
72                 }
73
74                 xiInited = true;
75
76                 return false;
77         }
78         else if (xiInited && event->type == GenericEvent
79                 && event->xcookie.type == GenericEvent && event->xcookie.extension == xiOpcode
80                 && event->xcookie.evtype == XI_KeyPress && XGetEventData(dpy, &event->xcookie)) {
81                 /* Handle XI event */
82                 XIDeviceEvent *d_ev = (XIDeviceEvent*) event->xcookie.data;
83             KeyCode keycode = d_ev->detail;
84             int kbdid = d_ev->deviceid;
85
86                 if (!(d_ev->flags & XIKeyRepeat)) {
87                         int keysyms_per_keycode;
88                         KeySym keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode)[0];
89                         handleKeyPress(kbdid, XKeysymToString(keysym));
90                 }
91
92                 XFreeEventData(dpy, &event->xcookie);
93
94                 return true;
95         }
96         else {
97                 return false;
98         }
99 }