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
;
15 } AttachInfo
, *AttachInfoPtr
;
17 static AttachInfo ais
;
21 * Creates a new master device.
23 int create_master(Display
* dpy
, char* name
)
32 return XIChangeHierarchy(dpy
, (XIAnyHierarchyChangeInfo
*)&c
, 1);
36 * Attaches a slave device to a master device.
38 int change_attachment(Display
* dpy
, int slaveid
, int masterid
)
42 c
.type
= XIAttachSlave
;
44 c
.new_master
= masterid
;
46 return XIChangeHierarchy(dpy
, (XIAnyHierarchyChangeInfo
*)&c
, 1);
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
)
57 unsigned char hmask
[2] = { 0, 0 };
58 char *m_name
, *s_name
;
64 //m_cur = XCreateFontCursor(dpy, 88);
65 //if (m_cur == BadAlloc || m_cur == BadValue) {
66 //printf("Unable to create cursor\n");
69 evmask_h
.mask
= hmask
;
70 evmask_h
.mask_len
= sizeof(hmask
);
71 evmask_h
.deviceid
= XIAllDevices
;
72 XISetMask(hmask
, XI_HierarchyChanged
);
75 XISelectEvents(dpy
, DefaultRootWindow(dpy
), &evmask_h
, 1);
78 XGenericEventCookie
*cookie
;
82 if (!XGetEventData(dpy
, cookie
))
85 PDEBUG("Event Received\n");
87 if (cookie
->type
!= GenericEvent
||
88 cookie
->extension
!= xi_opcode
)
91 if (cookie
->evtype
== XI_HierarchyChanged
) {
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");
114 asprintf(&m_name
, MD_PREFIX
"%s", s_name
);
115 create_master(dpy
, m_name
);
118 ai
= malloc(sizeof(AttachInfo
));
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
;
138 if (strcmp(ai
->m_name
, m_name
) == 0) {
139 PDEBUG(" New Master: %d %s\n", event
->info
[i
].deviceid
,
141 change_attachment(dpy
, ai
->slaveid
, event
->info
[i
].deviceid
);
142 //XIDefineCursor(dpy, event->info[i].deviceid,
143 //DefaultRootWindow(dpy), m_cur);
151 XFreeEventData(dpy
, cookie
);
155 void printHelp(char* bin_name
) {
156 printf("Usage: %s [OPTION...]\n", bin_name
);
158 printf(" -d\tenables debugging output\n");
159 printf(" -h\tprints this help message\n");
162 void processArgs(int argc
, char **argv
) {
165 for (i
=1; i
<argc
; i
++) {
166 if (strcmp(argv
[i
], "-d") == 0) {
168 PDEBUG("Debug on\n");
169 } else if (strcmp(argv
[i
], "-h") == 0) {
176 int main (int argc
, char **argv
)
179 int xi_opcode
, event
, error
;
185 processArgs(argc
, argv
);
191 dpy
= XOpenDisplay(NULL
);
193 printf("Failed to open display.\n");
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");
203 /* Check XI version, need 2.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
);
212 listen(dpy
, xi_opcode
);