1 /* antimicro Gamepad to KB+M event mapper
2  * Copyright (C) 2015 Travis Nickles <nickles.travis@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13 
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "xtesteventhandler.h"
19 
20 #include <QApplication>
21 
22 #include <X11/Xlib.h>
23 #include <X11/Xutil.h>
24 #include <X11/XKBlib.h>
25 #include <X11/extensions/XTest.h>
26 #include <x11extras.h>
27 #include <antkeymapper.h>
28 
XTestEventHandler(QObject * parent)29 XTestEventHandler::XTestEventHandler(QObject *parent) :
30     BaseEventHandler(parent)
31 {
32 }
33 
init()34 bool XTestEventHandler::init()
35 {
36     X11Extras *instance = X11Extras::getInstance();
37     if (instance)
38     {
39         instance->x11ResetMouseAccelerationChange(X11Extras::xtestMouseDeviceName);
40     }
41 
42     return true;
43 }
44 
cleanup()45 bool XTestEventHandler::cleanup()
46 {
47     return true;
48 }
49 
sendKeyboardEvent(JoyButtonSlot * slot,bool pressed)50 void XTestEventHandler::sendKeyboardEvent(JoyButtonSlot *slot, bool pressed)
51 {
52     Display* display = X11Extras::getInstance()->display();
53     JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode();
54     int code = slot->getSlotCode();
55 
56     if (device == JoyButtonSlot::JoyKeyboard)
57     {
58         unsigned int tempcode = XKeysymToKeycode(display, code);
59         if (tempcode > 0)
60         {
61             XTestFakeKeyEvent(display, tempcode, pressed, 0);
62             XFlush(display);
63         }
64     }
65 }
66 
sendMouseButtonEvent(JoyButtonSlot * slot,bool pressed)67 void XTestEventHandler::sendMouseButtonEvent(JoyButtonSlot *slot, bool pressed)
68 {
69     Display* display = X11Extras::getInstance()->display();
70     JoyButtonSlot::JoySlotInputAction device = slot->getSlotMode();
71     int code = slot->getSlotCode();
72 
73     if (device == JoyButtonSlot::JoyMouseButton)
74     {
75         XTestFakeButtonEvent(display, code, pressed, 0);
76         XFlush(display);
77     }
78 }
79 
sendMouseEvent(int xDis,int yDis)80 void XTestEventHandler::sendMouseEvent(int xDis, int yDis)
81 {
82     Display* display = X11Extras::getInstance()->display();
83     XTestFakeRelativeMotionEvent(display, xDis, yDis, 0);
84     XFlush(display);
85 }
86 
sendMouseAbsEvent(int xDis,int yDis,int screen)87 void XTestEventHandler::sendMouseAbsEvent(int xDis, int yDis, int screen)
88 {
89     Display* display = X11Extras::getInstance()->display();
90     XTestFakeMotionEvent(display, screen, xDis, yDis, 0);
91     XFlush(display);
92 }
93 
getName()94 QString XTestEventHandler::getName()
95 {
96     return QString("XTest");
97 }
98 
getIdentifier()99 QString XTestEventHandler::getIdentifier()
100 {
101     return QString("xtest");
102 }
103 
sendTextEntryEvent(QString maintext)104 void XTestEventHandler::sendTextEntryEvent(QString maintext)
105 {
106     AntKeyMapper *mapper = AntKeyMapper::getInstance();
107 
108     // Populated as needed.
109     unsigned int shiftcode = 0;
110     unsigned int controlcode = 0;
111     unsigned int metacode = 0;
112     unsigned int altcode = 0;
113 
114     if (mapper && mapper->getKeyMapper())
115     {
116         //Qt::KeyboardModifiers originalModifiers = Qt::KeyboardModifiers(QApplication::keyboardModifiers());
117         //Qt::KeyboardModifiers currentModifiers = Qt::KeyboardModifiers(QApplication::keyboardModifiers());
118         Display* display = X11Extras::getInstance()->display();
119         QtX11KeyMapper *keymapper = static_cast<QtX11KeyMapper*>(mapper->getKeyMapper());
120 
121         for (int i=0; i < maintext.size(); i++)
122         {
123             QtX11KeyMapper::charKeyInformation temp = keymapper->getCharKeyInformation(maintext.at(i));
124             unsigned int tempcode = XKeysymToKeycode(display, temp.virtualkey);
125             if (tempcode > 0)
126             {
127                 QList<unsigned int> tempList;
128 
129                 if (temp.modifiers != Qt::NoModifier)
130                 {
131                     if (temp.modifiers.testFlag(Qt::ShiftModifier))
132                     {
133                         if (shiftcode == 0)
134                         {
135                             shiftcode = XKeysymToKeycode(display, XK_Shift_L);
136                         }
137 
138                         unsigned int modifiercode = shiftcode;
139                         XTestFakeKeyEvent(display, modifiercode, 1, 0);
140                         //currentModifiers |= Qt::ShiftModifier;
141                         tempList.append(modifiercode);
142                     }
143 
144                     if (temp.modifiers.testFlag(Qt::ControlModifier))
145                     {
146                         if (controlcode == 0)
147                         {
148                             controlcode = XKeysymToKeycode(display, XK_Control_L);
149                         }
150 
151                         unsigned int modifiercode = controlcode;
152                         XTestFakeKeyEvent(display, modifiercode, 1, 0);
153                         //currentModifiers |= Qt::ControlModifier;
154                         tempList.append(modifiercode);
155                     }
156 
157                     if (temp.modifiers.testFlag(Qt::AltModifier))
158                     {
159                         if (altcode == 0)
160                         {
161                             altcode = XKeysymToKeycode(display, XK_Alt_L);
162                         }
163 
164                         unsigned int modifiercode = altcode;
165                         XTestFakeKeyEvent(display, modifiercode, 1, 0);
166                         //currentModifiers |= Qt::AltModifier;
167                         tempList.append(modifiercode);
168                     }
169 
170                     if (temp.modifiers.testFlag(Qt::MetaModifier))
171                     {
172                         if (metacode == 0)
173                         {
174                             metacode = XKeysymToKeycode(display, XK_Meta_L);
175                         }
176 
177                         unsigned int modifiercode = metacode;
178                         XTestFakeKeyEvent(display, modifiercode, 1, 0);
179                         //currentModifiers |= Qt::MetaModifier;
180                         tempList.append(modifiercode);
181                     }
182                 }
183 
184                 XTestFakeKeyEvent(display, tempcode, 1, 0);
185                 tempList.append(tempcode);
186 
187                 XFlush(display);
188 
189                 if (tempList.size() > 0)
190                 {
191                     QListIterator<unsigned int> tempiter(tempList);
192                     tempiter.toBack();
193                     while (tempiter.hasPrevious())
194                     {
195                         unsigned int currentcode = tempiter.previous();
196                         XTestFakeKeyEvent(display, currentcode, 0, 0);
197                     }
198 
199                     XFlush(display);
200                 }
201             }
202         }
203 
204         // Perform a flush at the end.
205         //XFlush(display);
206 
207         // Restore modifiers in place
208         /*if (originalModifiers != currentModifiers)
209         {
210 
211         }
212         */
213     }
214 }
215