Fixed debug messages and added help switch
[tmd.git] / src / tmd.c
blob4a547554fbd7543ad2ae1e26a4b28f71e86654da
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <X11/Xlib.h>
6 #include <X11/extensions/XInput2.h>
8 #define MD_PREFIX "TUIO "
9 #define PDEBUG(msg, ...) if(debug) printf("TMD: "msg,##__VA_ARGS__);
11 typedef struct _attach_info {
12 struct _attach_info *next;
13 int slaveid;
14 char *m_name;
15 } AttachInfo, *AttachInfoPtr;
17 static AttachInfo ais;
18 static int debug = 0;
20 /**
21 * Creates a new master device.
23 int create_master(Display* dpy, char* name)
25 XIAddMasterInfo c;
27 c.type = XIAddMaster;
28 c.name = name;
29 c.send_core = 1;
30 c.enable = 1;
32 return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
35 /**
36 * Attaches a slave device to a master device.
38 int change_attachment(Display* dpy, int slaveid, int masterid)
40 XIAttachSlaveInfo c;
42 c.type = XIAttachSlave;
43 c.deviceid = slaveid;
44 c.new_master = masterid;
46 return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
49 /**
50 * Listens for the creation of slave and master devices. When a new slave
51 * device is found, a new master device will be created and attached to
52 * when the message for the new master device comes back around.
54 void listen(Display *dpy, int xi_opcode)
56 int num_devices;
57 unsigned char hmask[2] = { 0, 0 };
58 char *m_name, *s_name;
59 XEvent ev;
60 XIEventMask evmask_h;
61 AttachInfoPtr ai;
63 //Cursor m_cur;
64 //m_cur = XCreateFontCursor(dpy, 88);
65 //if (m_cur == BadAlloc || m_cur == BadValue) {
66 //printf("Unable to create cursor\n");
67 //}
69 evmask_h.mask = hmask;
70 evmask_h.mask_len = sizeof(hmask);
71 evmask_h.deviceid = XIAllDevices;
72 XISetMask(hmask, XI_HierarchyChanged);
73 //XFlush(dpy);
75 XISelectEvents(dpy, DefaultRootWindow(dpy), &evmask_h, 1);
77 while (1) {
78 XGenericEventCookie *cookie;
79 cookie = &ev.xcookie;
80 XNextEvent(dpy, &ev);
82 if (!XGetEventData(dpy, cookie))
83 continue;
85 PDEBUG("Event Received\n");
87 if (cookie->type != GenericEvent ||
88 cookie->extension != xi_opcode)
89 continue;
91 if (cookie->evtype == XI_HierarchyChanged) {
92 int i;
93 XIHierarchyEvent *event = cookie->data;
95 /* Look for slave or masters added */
96 if (event->flags & XISlaveAdded) {
97 PDEBUG("Slave added\n");
98 for (i=0; i < event->num_info; i++) {
99 if (event->info[i].flags & XISlaveAdded) {
100 s_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name;
102 /* This is a hack. Xtst slave devices are created and
103 * attached to each new master device. If we were to
104 * actually create a new master device for this device
105 * we would end up with a recurring creation of
106 * master devices and slave devices. */
107 if (strstr(s_name, "Xtst") ||
108 !strstr(s_name, "subdev")) {
109 PDEBUG("Device not a tuio subdevice\n");
110 continue;
114 asprintf(&m_name, MD_PREFIX "%s", s_name);
115 create_master(dpy, m_name);
116 free(m_name);
118 ai = malloc(sizeof(AttachInfo));
119 ai->next = ais.next;
120 ais.next = ai;
122 asprintf(&ai->m_name, MD_PREFIX "%s pointer", s_name);
123 ai->slaveid = event->info[i].deviceid;
128 if (event->flags & XIMasterAdded) {
129 PDEBUG("Master added\n");
131 for (i=0; i < event->num_info; i++) {
132 if(event->info[i].flags & XIMasterAdded) {
134 m_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name;
136 ai = ais.next;
137 while (ai != NULL) {
138 if (strcmp(ai->m_name, m_name) == 0) {
139 PDEBUG(" New Master: %d %s\n", event->info[i].deviceid,
140 m_name);
141 change_attachment(dpy, ai->slaveid, event->info[i].deviceid);
142 //XIDefineCursor(dpy, event->info[i].deviceid,
143 //DefaultRootWindow(dpy), m_cur);
145 ai = ai->next;
151 XFreeEventData(dpy, cookie);
155 void printHelp(char* bin_name) {
156 printf("Usage: %s [OPTION...]\n", bin_name);
157 printf("\n");
158 printf(" -d\tenables debugging output\n");
159 printf(" -h\tprints this help message\n");
162 void processArgs(int argc, char **argv) {
163 int i;
165 for (i=1; i<argc; i++) {
166 if (strcmp(argv[i], "-d") == 0) {
167 debug = 1;
168 PDEBUG("Debug on\n");
169 } else if (strcmp(argv[i], "-h") == 0) {
170 printHelp(argv[0]);
171 exit(0);
176 int main (int argc, char **argv)
178 Display *dpy;
179 int xi_opcode, event, error;
180 int major, minor;
181 int ret;
183 ais.next = NULL;
185 processArgs(argc, argv);
187 debug = 1;
190 /* Open X display */
191 dpy = XOpenDisplay(NULL);
192 if (!dpy) {
193 printf("Failed to open display.\n");
194 return -1;
197 /* Make sure the X Input extension is available */
198 if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) {
199 printf("X Input extension not available.\n");
200 return -1;
203 /* Check XI version, need 2.0 */
204 major = 2;
205 minor = 0;
206 ret = XIQueryVersion(dpy, &major, &minor);
207 if (ret == BadRequest) {
208 printf("XInput 2.0 not supported. Server supports %i.%i.\n", major, minor);
209 return -1;
212 listen(dpy, xi_opcode);
214 XCloseDisplay(dpy);
215 return 0;