e7a188638008266ef5112d501bfd1d46024cdc27
[multypo.git] / qt / multypo.cpp
1 #include "multypo.h"
2
3 #include <QX11Info>
4 #include <QDebug>
5 #include <QVBoxLayout>
6 #include <QLabel>
7
8 #include <X11/Xlib.h>
9 #include <X11/extensions/XInput2.h>
10 #include <X11/Xutil.h>
11
12 static QString colorToString(QColor col)
13 {
14         return QString("#%1%2%3").arg(col.red(), 2, 16, QChar('0'))
15                         .arg(col.green(), 2, 16, QChar('0'))
16                         .arg(col.blue(), 2, 16, QChar('0'));
17 }
18
19 MultypoWindow::MultypoWindow(QWidget *parent) :
20         QWidget(parent),
21         xiInited(false)
22 {
23         /* Prepare colors */
24         setStyleSheet("background-color: black; color: green; font-size: 30pt");
25
26         /* Prepare conents */
27         setLayout(new QVBoxLayout(this));
28
29         mainLabel = new QLabel("Hit <Esc> to quit", this);
30         layout()->addWidget(mainLabel);
31
32         /* Fullscreen, no cursor */
33         setWindowState(Qt::WindowFullScreen);
34         setCursor(QCursor(Qt::BlankCursor));
35 }
36
37 MultypoWindow::~MultypoWindow()
38 {
39 }
40
41 void MultypoWindow::handleKeyPress(int device, QString string)
42 {
43         qDebug() << "Device" << device << "String" << string;
44
45         if (string == "Escape")
46                 close();
47
48         if (!players.contains(device)) {
49                 QLabel *label = new QLabel(this);
50                 layout()->addWidget(label);
51                 players[device] = label;
52         }
53         QColor textColor = QColor(Qt::blue);
54         players[device]->setText(players[device]->text() + "<span style='color:"+colorToString(textColor)+"'>"+string+"</span>");
55 }
56
57 bool MultypoWindow::handleX11Event(XEvent *event)
58 {
59         Display *dpy = x11Info().display();
60         /* Handle the first map event: We are finally visible! */
61         if (!xiInited && event->type == MapNotify) {
62                 /* XInput Extension available? */
63                 int eventID, errorID;
64                 if (!XQueryExtension(dpy, "XInputExtension", &xiOpcode, &eventID, &errorID)) {
65                    qCritical() << "X Input extension not available";
66                 }
67
68                 /* Which version of XI2? We support 2.0 */
69                 int major = 2, minor = 0;
70                 if (XIQueryVersion(dpy, &major, &minor) == BadRequest) {
71                         qCritical() << "XI2 not available. Server supports" << major << "." <<
72                                                 minor;
73                 }
74
75                 qDebug() << "System supports XI2";
76
77
78                 // Now let's listen to keypress events
79                 XIEventMask eventmask;
80                 unsigned char mask [1] = { 0 }; // will change
81                 eventmask.deviceid = XIAllMasterDevices;
82                 eventmask.mask_len = sizeof (mask); // in bytes, for whatever reason...
83                 eventmask.mask = mask;
84                 XISetMask(mask, XI_KeyPress);
85                 XISelectEvents (dpy, winId(), &eventmask, 1);
86
87                 // finally, grab all focuses
88                 int ndevices;
89                 XIDeviceInfo* devices = XIQueryDevice(dpy, XIAllMasterDevices, &ndevices);
90                 for (int i = 0; i < ndevices; ++i) {
91                         if (devices[i].use != XIMasterKeyboard) continue;
92                         qDebug() << "Found master keyboard with ID" << devices[i].deviceid;
93                         XISetFocus(dpy, devices[i].deviceid, winId(), CurrentTime);
94                 }
95                 XIFreeDeviceInfo(devices);
96
97                 xiInited = true;
98
99                 return false;
100         }
101         else if (xiInited && event->type == GenericEvent
102                 && event->xcookie.type == GenericEvent && event->xcookie.extension == xiOpcode
103                 && event->xcookie.evtype == XI_KeyPress && XGetEventData(dpy, &event->xcookie)) {
104                 /* Handle XI event */
105                 XIDeviceEvent *d_ev = (XIDeviceEvent*) event->xcookie.data;
106             KeyCode keycode = d_ev->detail;
107             int kbdid = d_ev->deviceid;
108
109                 if (!(d_ev->flags & XIKeyRepeat)) {
110                         int keysyms_per_keycode;
111                         KeySym keysym = XGetKeyboardMapping (dpy, keycode, 1, &keysyms_per_keycode)[0];
112                         handleKeyPress(kbdid, XKeysymToString(keysym));
113                 }
114
115                 XFreeEventData(dpy, &event->xcookie);
116
117                 return true;
118         }
119         else {
120                 return false;
121         }
122 }