Initial commit
[tmd.git] / src / tmd.c
blobd7ab75fbe8f0d7bd4dba76f97187259261decacd
1 /* gcc -o part2 `pkg-config --cflags --libs xi` part2.c */
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <X11/Xlib.h>
7 #include <X11/extensions/XInput2.h>
9 #define MD_PREFIX "TUIO "
11 typedef struct _attach_info {
12 struct _attach_info *next;
13 int slaveid;
14 char *m_name;
15 } AttachInfo, *AttachInfoPtr;
17 static AttachInfo ais;
19 /**
20 * Creates a new master device.
22 int create_master(Display* dpy, char* name)
24 XIAddMasterInfo c;
26 c.type = XIAddMaster;
27 c.name = name;
28 c.send_core = 1;
29 c.enable = 1;
31 return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
34 /**
35 * Attaches a slave device to a master device.
37 int change_attachment(Display* dpy, int slaveid, int masterid)
39 XIAttachSlaveInfo c;
41 c.type = XIAttachSlave;
42 c.deviceid = slaveid;
43 c.new_master = masterid;
45 return XIChangeHierarchy(dpy, (XIAnyHierarchyChangeInfo*)&c, 1);
48 /**
49 * Listens for the creation of slave and master devices. When a new slave
50 * device is found, a new master device will be created and attached to
51 * when the message for the new master device comes back around.
53 void listen(Display *dpy, int xi_opcode)
55 int num_devices;
56 unsigned char hmask[2] = { 0, 0 };
57 char *m_name, *s_name;
58 XIEvent ev;
59 XIEventMask evmask_h;
60 AttachInfoPtr ai;
62 Cursor m_cur;
63 m_cur = XCreateFontCursor(dpy, 88);
64 if (m_cur == BadAlloc || m_cur == BadValue) {
65 printf("Unable to create cursor\n");
68 evmask_h.mask = hmask;
69 evmask_h.mask_len = sizeof(hmask);
70 evmask_h.deviceid = XIAllDevices;
71 XISetMask(hmask, XI_HierarchyChanged);
72 //XFlush(dpy);
74 XISelectEvents(dpy, DefaultRootWindow(dpy), &evmask_h, 1);
76 while (1) {
77 XNextEvent(dpy, (XIEvent *)&ev);
78 if (ev.type != GenericEvent ||
79 ev.extension != xi_opcode)
80 continue;
82 if (ev.evtype == XI_HierarchyChanged) {
83 int i;
84 XIHierarchyEvent *event = (XIHierarchyEvent*)&ev;
85 printf("Hierarchy Event.\n");
87 /* Look for slave or masters added */
88 if (event->flags & XISlaveAdded) {
89 printf("Slave added\n");
90 for (i=0; i < event->num_info; i++) {
91 if(event->info[i].flags & XISlaveAdded) {
92 s_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name;
94 /* This is a hack. Xtst slave devices are created and
95 * attached to each new master device. If we were to
96 * actually create a new master device for this device
97 * we would end up with a recurring creation of
98 * master devices and slave devices. */
99 if (strstr(s_name, "Xtst")) continue;
101 asprintf(&m_name, MD_PREFIX"%s", s_name);
102 create_master(dpy, m_name);
103 free(m_name);
105 ai = malloc(sizeof(AttachInfo));
106 ai->next = ais.next;
107 ais.next = ai;
109 asprintf(&ai->m_name, MD_PREFIX"%s pointer", s_name);
110 ai->slaveid = event->info[i].deviceid;
113 } else if (event->flags & XIMasterAdded) {
114 printf("Master added\n");
116 for (i=0; i < event->num_info; i++) {
117 if(event->info[i].flags & XIMasterAdded) {
119 m_name = XIQueryDevice(dpy, event->info[i].deviceid, &num_devices)->name;
121 ai = ais.next;
122 while (ai != NULL) {
123 if (strcmp(ai->m_name, m_name) == 0) {
124 printf(" New Master: %d %s\n", event->info[i].deviceid,
125 m_name);
126 change_attachment(dpy, ai->slaveid, event->info[i].deviceid);
127 XIDefineCursor(dpy, event->info[i].deviceid,
128 DefaultRootWindow(dpy), m_cur);
130 ai = ai->next;
139 int main (int argc, char **argv)
141 Display *dpy;
142 int xi_opcode, event, error;
143 int major, minor;
144 int ret;
146 ais.next = NULL;
148 /* Open X display */
149 dpy = XOpenDisplay(NULL);
150 if (!dpy) {
151 printf("Failed to open display.\n");
152 return -1;
155 /* Make sure the X Input extension is available */
156 if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) {
157 printf("X Input extension not available.\n");
158 return -1;
161 /* Check XI version, need 2.0 */
162 major = 2;
163 minor = 0;
164 ret = XIQueryVersion(dpy, &major, &minor);
165 if (ret == BadRequest) {
166 printf("XInput 2.0 not supported. Server supports %i.%i.\n", major, minor);
167 return -1;
170 listen(dpy, xi_opcode);
172 XCloseDisplay(dpy);
173 return 0;