Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2009 Red Hat, Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a | |
5 | * copy of this software and associated documentation files (the "Software"), | |
6 | * to deal in the Software without restriction, including without limitation | |
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
8 | * and/or sell copies of the Software, and to permit persons to whom the | |
9 | * Software is furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice (including the next | |
12 | * paragraph) shall be included in all copies or substantial portions of the | |
13 | * Software. | |
14 | * | |
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |
21 | * DEALINGS IN THE SOFTWARE. | |
22 | * | |
23 | */ | |
24 | ||
25 | /** | |
26 | * @file eventconvert.c | |
27 | * This file contains event conversion routines from InternalEvent to the | |
28 | * matching protocol events. | |
29 | */ | |
30 | ||
31 | #ifdef HAVE_DIX_CONFIG_H | |
32 | #include <dix-config.h> | |
33 | #endif | |
34 | ||
35 | #include <stdint.h> | |
36 | #include <X11/X.h> | |
37 | #include <X11/extensions/XIproto.h> | |
38 | #include <X11/extensions/XI2proto.h> | |
39 | #include <X11/extensions/XI.h> | |
40 | #include <X11/extensions/XI2.h> | |
41 | ||
42 | #include "dix.h" | |
43 | #include "inputstr.h" | |
44 | #include "misc.h" | |
45 | #include "eventstr.h" | |
46 | #include "exevents.h" | |
47 | #include "exglobals.h" | |
48 | #include "eventconvert.h" | |
49 | #include "inpututils.h" | |
50 | #include "xiquerydevice.h" | |
51 | #include "xkbsrv.h" | |
52 | #include "inpututils.h" | |
53 | ||
54 | static int countValuators(DeviceEvent *ev, int *first); | |
55 | static int getValuatorEvents(DeviceEvent *ev, deviceValuator * xv); | |
56 | static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); | |
57 | static int eventToDeviceChanged(DeviceChangedEvent *ev, xEvent **dcce); | |
58 | static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); | |
59 | static int eventToRawEvent(RawDeviceEvent *ev, xEvent **xi); | |
60 | static int eventToBarrierEvent(BarrierEvent *ev, xEvent **xi); | |
61 | static int eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi); | |
62 | ||
63 | /* Do not use, read comments below */ | |
64 | BOOL EventIsKeyRepeat(xEvent *event); | |
65 | ||
66 | /** | |
67 | * Hack to allow detectable autorepeat for core and XI1 events. | |
68 | * The sequence number is unused until we send to the client and can be | |
69 | * misused to store data. More or less, anyway. | |
70 | * | |
71 | * Do not use this. It may change any time without warning, eat your babies | |
72 | * and piss on your cat. | |
73 | */ | |
74 | static void | |
75 | EventSetKeyRepeatFlag(xEvent *event, BOOL on) | |
76 | { | |
77 | event->u.u.sequenceNumber = on; | |
78 | } | |
79 | ||
80 | /** | |
81 | * Check if the event was marked as a repeat event before. | |
82 | * NOTE: This is a nasty hack and should NOT be used by anyone else but | |
83 | * TryClientEvents. | |
84 | */ | |
85 | BOOL | |
86 | EventIsKeyRepeat(xEvent *event) | |
87 | { | |
88 | return ! !event->u.u.sequenceNumber; | |
89 | } | |
90 | ||
91 | /** | |
92 | * Convert the given event to the respective core event. | |
93 | * | |
94 | * Return values: | |
95 | * Success ... core contains the matching core event. | |
96 | * BadValue .. One or more values in the internal event are invalid. | |
97 | * BadMatch .. The event has no core equivalent. | |
98 | * | |
99 | * @param[in] event The event to convert into a core event. | |
100 | * @param[in] core The memory location to store the core event at. | |
101 | * @return Success or the matching error code. | |
102 | */ | |
103 | int | |
104 | EventToCore(InternalEvent *event, xEvent **core_out, int *count_out) | |
105 | { | |
106 | xEvent *core = NULL; | |
107 | int count = 0; | |
108 | int ret = BadImplementation; | |
109 | ||
110 | switch (event->any.type) { | |
111 | case ET_Motion: | |
112 | { | |
113 | DeviceEvent *e = &event->device_event; | |
114 | ||
115 | /* Don't create core motion event if neither x nor y are | |
116 | * present */ | |
117 | if (!BitIsOn(e->valuators.mask, 0) && !BitIsOn(e->valuators.mask, 1)) { | |
118 | ret = BadMatch; | |
119 | goto out; | |
120 | } | |
121 | } | |
122 | /* fallthrough */ | |
123 | case ET_ButtonPress: | |
124 | case ET_ButtonRelease: | |
125 | case ET_KeyPress: | |
126 | case ET_KeyRelease: | |
127 | { | |
128 | DeviceEvent *e = &event->device_event; | |
129 | ||
130 | if (e->detail.key > 0xFF) { | |
131 | ret = BadMatch; | |
132 | goto out; | |
133 | } | |
134 | ||
135 | core = calloc(1, sizeof(*core)); | |
136 | if (!core) | |
137 | return BadAlloc; | |
138 | count = 1; | |
139 | core->u.u.type = e->type - ET_KeyPress + KeyPress; | |
140 | core->u.u.detail = e->detail.key & 0xFF; | |
141 | core->u.keyButtonPointer.time = e->time; | |
142 | core->u.keyButtonPointer.rootX = e->root_x; | |
143 | core->u.keyButtonPointer.rootY = e->root_y; | |
144 | core->u.keyButtonPointer.state = e->corestate; | |
145 | core->u.keyButtonPointer.root = e->root; | |
146 | EventSetKeyRepeatFlag(core, (e->type == ET_KeyPress && e->key_repeat)); | |
147 | ret = Success; | |
148 | } | |
149 | break; | |
150 | case ET_ProximityIn: | |
151 | case ET_ProximityOut: | |
152 | case ET_RawKeyPress: | |
153 | case ET_RawKeyRelease: | |
154 | case ET_RawButtonPress: | |
155 | case ET_RawButtonRelease: | |
156 | case ET_RawMotion: | |
157 | case ET_RawTouchBegin: | |
158 | case ET_RawTouchUpdate: | |
159 | case ET_RawTouchEnd: | |
160 | case ET_TouchBegin: | |
161 | case ET_TouchUpdate: | |
162 | case ET_TouchEnd: | |
163 | case ET_TouchOwnership: | |
164 | case ET_BarrierHit: | |
165 | case ET_BarrierLeave: | |
166 | ret = BadMatch; | |
167 | break; | |
168 | default: | |
169 | /* XXX: */ | |
170 | ErrorF("[dix] EventToCore: Not implemented yet \n"); | |
171 | ret = BadImplementation; | |
172 | } | |
173 | ||
174 | out: | |
175 | *core_out = core; | |
176 | *count_out = count; | |
177 | return ret; | |
178 | } | |
179 | ||
180 | /** | |
181 | * Convert the given event to the respective XI 1.x event and store it in | |
182 | * xi. xi is allocated on demand and must be freed by the caller. | |
183 | * count returns the number of events in xi. If count is 1, and the type of | |
184 | * xi is GenericEvent, then xi may be larger than 32 bytes. | |
185 | * | |
186 | * Return values: | |
187 | * Success ... core contains the matching core event. | |
188 | * BadValue .. One or more values in the internal event are invalid. | |
189 | * BadMatch .. The event has no XI equivalent. | |
190 | * | |
191 | * @param[in] ev The event to convert into an XI 1 event. | |
192 | * @param[out] xi Future memory location for the XI event. | |
193 | * @param[out] count Number of elements in xi. | |
194 | * | |
195 | * @return Success or the error code. | |
196 | */ | |
197 | int | |
198 | EventToXI(InternalEvent *ev, xEvent **xi, int *count) | |
199 | { | |
200 | switch (ev->any.type) { | |
201 | case ET_Motion: | |
202 | case ET_ButtonPress: | |
203 | case ET_ButtonRelease: | |
204 | case ET_KeyPress: | |
205 | case ET_KeyRelease: | |
206 | case ET_ProximityIn: | |
207 | case ET_ProximityOut: | |
208 | return eventToKeyButtonPointer(&ev->device_event, xi, count); | |
209 | case ET_DeviceChanged: | |
210 | case ET_RawKeyPress: | |
211 | case ET_RawKeyRelease: | |
212 | case ET_RawButtonPress: | |
213 | case ET_RawButtonRelease: | |
214 | case ET_RawMotion: | |
215 | case ET_RawTouchBegin: | |
216 | case ET_RawTouchUpdate: | |
217 | case ET_RawTouchEnd: | |
218 | case ET_TouchBegin: | |
219 | case ET_TouchUpdate: | |
220 | case ET_TouchEnd: | |
221 | case ET_TouchOwnership: | |
222 | case ET_BarrierHit: | |
223 | case ET_BarrierLeave: | |
224 | *count = 0; | |
225 | *xi = NULL; | |
226 | return BadMatch; | |
227 | default: | |
228 | break; | |
229 | } | |
230 | ||
231 | ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->any.type); | |
232 | return BadImplementation; | |
233 | } | |
234 | ||
235 | /** | |
236 | * Convert the given event to the respective XI 2.x event and store it in xi. | |
237 | * xi is allocated on demand and must be freed by the caller. | |
238 | * | |
239 | * Return values: | |
240 | * Success ... core contains the matching core event. | |
241 | * BadValue .. One or more values in the internal event are invalid. | |
242 | * BadMatch .. The event has no XI2 equivalent. | |
243 | * | |
244 | * @param[in] ev The event to convert into an XI2 event | |
245 | * @param[out] xi Future memory location for the XI2 event. | |
246 | * | |
247 | * @return Success or the error code. | |
248 | */ | |
249 | int | |
250 | EventToXI2(InternalEvent *ev, xEvent **xi) | |
251 | { | |
252 | switch (ev->any.type) { | |
253 | /* Enter/FocusIn are for grabs. We don't need an actual event, since | |
254 | * the real events delivered are triggered elsewhere */ | |
255 | case ET_Enter: | |
256 | case ET_FocusIn: | |
257 | *xi = NULL; | |
258 | return Success; | |
259 | case ET_Motion: | |
260 | case ET_ButtonPress: | |
261 | case ET_ButtonRelease: | |
262 | case ET_KeyPress: | |
263 | case ET_KeyRelease: | |
264 | case ET_TouchBegin: | |
265 | case ET_TouchUpdate: | |
266 | case ET_TouchEnd: | |
267 | return eventToDeviceEvent(&ev->device_event, xi); | |
268 | case ET_TouchOwnership: | |
269 | return eventToTouchOwnershipEvent(&ev->touch_ownership_event, xi); | |
270 | case ET_ProximityIn: | |
271 | case ET_ProximityOut: | |
272 | *xi = NULL; | |
273 | return BadMatch; | |
274 | case ET_DeviceChanged: | |
275 | return eventToDeviceChanged(&ev->changed_event, xi); | |
276 | case ET_RawKeyPress: | |
277 | case ET_RawKeyRelease: | |
278 | case ET_RawButtonPress: | |
279 | case ET_RawButtonRelease: | |
280 | case ET_RawMotion: | |
281 | case ET_RawTouchBegin: | |
282 | case ET_RawTouchUpdate: | |
283 | case ET_RawTouchEnd: | |
284 | return eventToRawEvent(&ev->raw_event, xi); | |
285 | case ET_BarrierHit: | |
286 | case ET_BarrierLeave: | |
287 | return eventToBarrierEvent(&ev->barrier_event, xi); | |
288 | default: | |
289 | break; | |
290 | } | |
291 | ||
292 | ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->any.type); | |
293 | return BadImplementation; | |
294 | } | |
295 | ||
296 | static int | |
297 | eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count) | |
298 | { | |
299 | int num_events; | |
300 | int first; /* dummy */ | |
301 | deviceKeyButtonPointer *kbp; | |
302 | ||
303 | /* Sorry, XI 1.x protocol restrictions. */ | |
304 | if (ev->detail.button > 0xFF || ev->deviceid >= 0x80) { | |
305 | *count = 0; | |
306 | return Success; | |
307 | } | |
308 | ||
309 | num_events = (countValuators(ev, &first) + 5) / 6; /* valuator ev */ | |
310 | if (num_events <= 0) { | |
311 | switch (ev->type) { | |
312 | case ET_KeyPress: | |
313 | case ET_KeyRelease: | |
314 | case ET_ButtonPress: | |
315 | case ET_ButtonRelease: | |
316 | /* no axes is ok */ | |
317 | break; | |
318 | case ET_Motion: | |
319 | case ET_ProximityIn: | |
320 | case ET_ProximityOut: | |
321 | *count = 0; | |
322 | return BadMatch; | |
323 | default: | |
324 | *count = 0; | |
325 | return BadImplementation; | |
326 | } | |
327 | } | |
328 | ||
329 | num_events++; /* the actual event event */ | |
330 | ||
331 | *xi = calloc(num_events, sizeof(xEvent)); | |
332 | if (!(*xi)) { | |
333 | return BadAlloc; | |
334 | } | |
335 | ||
336 | kbp = (deviceKeyButtonPointer *) (*xi); | |
337 | kbp->detail = ev->detail.button; | |
338 | kbp->time = ev->time; | |
339 | kbp->root = ev->root; | |
340 | kbp->root_x = ev->root_x; | |
341 | kbp->root_y = ev->root_y; | |
342 | kbp->deviceid = ev->deviceid; | |
343 | kbp->state = ev->corestate; | |
344 | EventSetKeyRepeatFlag((xEvent *) kbp, | |
345 | (ev->type == ET_KeyPress && ev->key_repeat)); | |
346 | ||
347 | if (num_events > 1) | |
348 | kbp->deviceid |= MORE_EVENTS; | |
349 | ||
350 | switch (ev->type) { | |
351 | case ET_Motion: | |
352 | kbp->type = DeviceMotionNotify; | |
353 | break; | |
354 | case ET_ButtonPress: | |
355 | kbp->type = DeviceButtonPress; | |
356 | break; | |
357 | case ET_ButtonRelease: | |
358 | kbp->type = DeviceButtonRelease; | |
359 | break; | |
360 | case ET_KeyPress: | |
361 | kbp->type = DeviceKeyPress; | |
362 | break; | |
363 | case ET_KeyRelease: | |
364 | kbp->type = DeviceKeyRelease; | |
365 | break; | |
366 | case ET_ProximityIn: | |
367 | kbp->type = ProximityIn; | |
368 | break; | |
369 | case ET_ProximityOut: | |
370 | kbp->type = ProximityOut; | |
371 | break; | |
372 | default: | |
373 | break; | |
374 | } | |
375 | ||
376 | if (num_events > 1) { | |
377 | getValuatorEvents(ev, (deviceValuator *) (kbp + 1)); | |
378 | } | |
379 | ||
380 | *count = num_events; | |
381 | return Success; | |
382 | } | |
383 | ||
384 | /** | |
385 | * Set first to the first valuator in the event ev and return the number of | |
386 | * valuators from first to the last set valuator. | |
387 | */ | |
388 | static int | |
389 | countValuators(DeviceEvent *ev, int *first) | |
390 | { | |
391 | int first_valuator = -1, last_valuator = -1, num_valuators = 0; | |
392 | int i; | |
393 | ||
394 | for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) { | |
395 | if (BitIsOn(ev->valuators.mask, i)) { | |
396 | if (first_valuator == -1) | |
397 | first_valuator = i; | |
398 | last_valuator = i; | |
399 | } | |
400 | } | |
401 | ||
402 | if (first_valuator != -1) { | |
403 | num_valuators = last_valuator - first_valuator + 1; | |
404 | *first = first_valuator; | |
405 | } | |
406 | ||
407 | return num_valuators; | |
408 | } | |
409 | ||
410 | static int | |
411 | getValuatorEvents(DeviceEvent *ev, deviceValuator * xv) | |
412 | { | |
413 | int i; | |
414 | int state = 0; | |
415 | int first_valuator, num_valuators; | |
416 | ||
417 | num_valuators = countValuators(ev, &first_valuator); | |
418 | if (num_valuators > 0) { | |
419 | DeviceIntPtr dev = NULL; | |
420 | ||
421 | dixLookupDevice(&dev, ev->deviceid, serverClient, DixUseAccess); | |
422 | /* State needs to be assembled BEFORE the device is updated. */ | |
423 | state = (dev && | |
424 | dev->key) ? XkbStateFieldFromRec(&dev->key->xkbInfo-> | |
425 | state) : 0; | |
426 | state |= (dev && dev->button) ? (dev->button->state) : 0; | |
427 | } | |
428 | ||
429 | for (i = 0; i < num_valuators; i += 6, xv++) { | |
430 | INT32 *valuators = &xv->valuator0; // Treat all 6 vals as an array | |
431 | int j; | |
432 | ||
433 | xv->type = DeviceValuator; | |
434 | xv->first_valuator = first_valuator + i; | |
435 | xv->num_valuators = ((num_valuators - i) > 6) ? 6 : (num_valuators - i); | |
436 | xv->deviceid = ev->deviceid; | |
437 | xv->device_state = state; | |
438 | ||
439 | /* Unset valuators in masked valuator events have the proper data values | |
440 | * in the case of an absolute axis in between two set valuators. */ | |
441 | for (j = 0; j < xv->num_valuators; j++) | |
442 | valuators[j] = ev->valuators.data[xv->first_valuator + j]; | |
443 | ||
444 | if (i + 6 < num_valuators) | |
445 | xv->deviceid |= MORE_EVENTS; | |
446 | } | |
447 | ||
448 | return (num_valuators + 5) / 6; | |
449 | } | |
450 | ||
451 | static int | |
452 | appendKeyInfo(DeviceChangedEvent *dce, xXIKeyInfo * info) | |
453 | { | |
454 | uint32_t *kc; | |
455 | int i; | |
456 | ||
457 | info->type = XIKeyClass; | |
458 | info->num_keycodes = dce->keys.max_keycode - dce->keys.min_keycode + 1; | |
459 | info->length = sizeof(xXIKeyInfo) / 4 + info->num_keycodes; | |
460 | info->sourceid = dce->sourceid; | |
461 | ||
462 | kc = (uint32_t *) &info[1]; | |
463 | for (i = 0; i < info->num_keycodes; i++) | |
464 | *kc++ = i + dce->keys.min_keycode; | |
465 | ||
466 | return info->length * 4; | |
467 | } | |
468 | ||
469 | static int | |
470 | appendButtonInfo(DeviceChangedEvent *dce, xXIButtonInfo * info) | |
471 | { | |
472 | unsigned char *bits; | |
473 | int mask_len; | |
474 | ||
475 | mask_len = bytes_to_int32(bits_to_bytes(dce->buttons.num_buttons)); | |
476 | ||
477 | info->type = XIButtonClass; | |
478 | info->num_buttons = dce->buttons.num_buttons; | |
479 | info->length = bytes_to_int32(sizeof(xXIButtonInfo)) + | |
480 | info->num_buttons + mask_len; | |
481 | info->sourceid = dce->sourceid; | |
482 | ||
483 | bits = (unsigned char *) &info[1]; | |
484 | memset(bits, 0, mask_len * 4); | |
485 | /* FIXME: is_down? */ | |
486 | ||
487 | bits += mask_len * 4; | |
488 | memcpy(bits, dce->buttons.names, dce->buttons.num_buttons * sizeof(Atom)); | |
489 | ||
490 | return info->length * 4; | |
491 | } | |
492 | ||
493 | static int | |
494 | appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo * info, | |
495 | int axisnumber) | |
496 | { | |
497 | info->type = XIValuatorClass; | |
498 | info->length = sizeof(xXIValuatorInfo) / 4; | |
499 | info->label = dce->valuators[axisnumber].name; | |
500 | info->min.integral = dce->valuators[axisnumber].min; | |
501 | info->min.frac = 0; | |
502 | info->max.integral = dce->valuators[axisnumber].max; | |
503 | info->max.frac = 0; | |
504 | info->value = double_to_fp3232(dce->valuators[axisnumber].value); | |
505 | info->resolution = dce->valuators[axisnumber].resolution; | |
506 | info->number = axisnumber; | |
507 | info->mode = dce->valuators[axisnumber].mode; | |
508 | info->sourceid = dce->sourceid; | |
509 | ||
510 | return info->length * 4; | |
511 | } | |
512 | ||
513 | static int | |
514 | appendScrollInfo(DeviceChangedEvent *dce, xXIScrollInfo * info, int axisnumber) | |
515 | { | |
516 | if (dce->valuators[axisnumber].scroll.type == SCROLL_TYPE_NONE) | |
517 | return 0; | |
518 | ||
519 | info->type = XIScrollClass; | |
520 | info->length = sizeof(xXIScrollInfo) / 4; | |
521 | info->number = axisnumber; | |
522 | switch (dce->valuators[axisnumber].scroll.type) { | |
523 | case SCROLL_TYPE_VERTICAL: | |
524 | info->scroll_type = XIScrollTypeVertical; | |
525 | break; | |
526 | case SCROLL_TYPE_HORIZONTAL: | |
527 | info->scroll_type = XIScrollTypeHorizontal; | |
528 | break; | |
529 | default: | |
530 | ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", | |
531 | dce->valuators[axisnumber].scroll.type); | |
532 | break; | |
533 | } | |
534 | info->increment = | |
535 | double_to_fp3232(dce->valuators[axisnumber].scroll.increment); | |
536 | info->sourceid = dce->sourceid; | |
537 | ||
538 | info->flags = 0; | |
539 | ||
540 | if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_DONT_EMULATE) | |
541 | info->flags |= XIScrollFlagNoEmulation; | |
542 | if (dce->valuators[axisnumber].scroll.flags & SCROLL_FLAG_PREFERRED) | |
543 | info->flags |= XIScrollFlagPreferred; | |
544 | ||
545 | return info->length * 4; | |
546 | } | |
547 | ||
548 | static int | |
549 | eventToDeviceChanged(DeviceChangedEvent *dce, xEvent **xi) | |
550 | { | |
551 | xXIDeviceChangedEvent *dcce; | |
552 | int len = sizeof(xXIDeviceChangedEvent); | |
553 | int nkeys; | |
554 | char *ptr; | |
555 | ||
556 | if (dce->buttons.num_buttons) { | |
557 | len += sizeof(xXIButtonInfo); | |
558 | len += dce->buttons.num_buttons * sizeof(Atom); /* button names */ | |
559 | len += pad_to_int32(bits_to_bytes(dce->buttons.num_buttons)); | |
560 | } | |
561 | if (dce->num_valuators) { | |
562 | int i; | |
563 | ||
564 | len += sizeof(xXIValuatorInfo) * dce->num_valuators; | |
565 | ||
566 | for (i = 0; i < dce->num_valuators; i++) | |
567 | if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE) | |
568 | len += sizeof(xXIScrollInfo); | |
569 | } | |
570 | ||
571 | nkeys = (dce->keys.max_keycode > 0) ? | |
572 | dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; | |
573 | if (nkeys > 0) { | |
574 | len += sizeof(xXIKeyInfo); | |
575 | len += sizeof(CARD32) * nkeys; /* keycodes */ | |
576 | } | |
577 | ||
578 | dcce = calloc(1, len); | |
579 | if (!dcce) { | |
580 | ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n"); | |
581 | return BadAlloc; | |
582 | } | |
583 | ||
584 | dcce->type = GenericEvent; | |
585 | dcce->extension = IReqCode; | |
586 | dcce->evtype = XI_DeviceChanged; | |
587 | dcce->time = dce->time; | |
588 | dcce->deviceid = dce->deviceid; | |
589 | dcce->sourceid = dce->sourceid; | |
590 | dcce->reason = | |
591 | (dce->flags & DEVCHANGE_DEVICE_CHANGE) ? XIDeviceChange : XISlaveSwitch; | |
592 | dcce->num_classes = 0; | |
593 | dcce->length = bytes_to_int32(len - sizeof(xEvent)); | |
594 | ||
595 | ptr = (char *) &dcce[1]; | |
596 | if (dce->buttons.num_buttons) { | |
597 | dcce->num_classes++; | |
598 | ptr += appendButtonInfo(dce, (xXIButtonInfo *) ptr); | |
599 | } | |
600 | ||
601 | if (nkeys) { | |
602 | dcce->num_classes++; | |
603 | ptr += appendKeyInfo(dce, (xXIKeyInfo *) ptr); | |
604 | } | |
605 | ||
606 | if (dce->num_valuators) { | |
607 | int i; | |
608 | ||
609 | dcce->num_classes += dce->num_valuators; | |
610 | for (i = 0; i < dce->num_valuators; i++) | |
611 | ptr += appendValuatorInfo(dce, (xXIValuatorInfo *) ptr, i); | |
612 | ||
613 | for (i = 0; i < dce->num_valuators; i++) { | |
614 | if (dce->valuators[i].scroll.type != SCROLL_TYPE_NONE) { | |
615 | dcce->num_classes++; | |
616 | ptr += appendScrollInfo(dce, (xXIScrollInfo *) ptr, i); | |
617 | } | |
618 | } | |
619 | } | |
620 | ||
621 | *xi = (xEvent *) dcce; | |
622 | ||
623 | return Success; | |
624 | } | |
625 | ||
626 | static int | |
627 | count_bits(unsigned char *ptr, int len) | |
628 | { | |
629 | int bits = 0; | |
630 | unsigned int i; | |
631 | unsigned char x; | |
632 | ||
633 | for (i = 0; i < len; i++) { | |
634 | x = ptr[i]; | |
635 | while (x > 0) { | |
636 | bits += (x & 0x1); | |
637 | x >>= 1; | |
638 | } | |
639 | } | |
640 | return bits; | |
641 | } | |
642 | ||
643 | static int | |
644 | eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) | |
645 | { | |
646 | int len = sizeof(xXIDeviceEvent); | |
647 | xXIDeviceEvent *xde; | |
648 | int i, btlen, vallen; | |
649 | char *ptr; | |
650 | FP3232 *axisval; | |
651 | ||
652 | /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same | |
653 | * with MAX_VALUATORS below */ | |
654 | /* btlen is in 4 byte units */ | |
655 | btlen = bytes_to_int32(bits_to_bytes(MAX_BUTTONS)); | |
656 | len += btlen * 4; /* buttonmask len */ | |
657 | ||
658 | vallen = | |
659 | count_bits(ev->valuators.mask, | |
660 | sizeof(ev->valuators.mask) / sizeof(ev->valuators.mask[0])); | |
661 | len += vallen * 2 * sizeof(uint32_t); /* axisvalues */ | |
662 | vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); | |
663 | len += vallen * 4; /* valuators mask */ | |
664 | ||
665 | *xi = calloc(1, len); | |
666 | xde = (xXIDeviceEvent *) * xi; | |
667 | xde->type = GenericEvent; | |
668 | xde->extension = IReqCode; | |
669 | xde->evtype = GetXI2Type(ev->type); | |
670 | xde->time = ev->time; | |
671 | xde->length = bytes_to_int32(len - sizeof(xEvent)); | |
672 | if (IsTouchEvent((InternalEvent *) ev)) | |
673 | xde->detail = ev->touchid; | |
674 | else | |
675 | xde->detail = ev->detail.button; | |
676 | ||
677 | xde->root = ev->root; | |
678 | xde->buttons_len = btlen; | |
679 | xde->valuators_len = vallen; | |
680 | xde->deviceid = ev->deviceid; | |
681 | xde->sourceid = ev->sourceid; | |
682 | xde->root_x = double_to_fp1616(ev->root_x + ev->root_x_frac); | |
683 | xde->root_y = double_to_fp1616(ev->root_y + ev->root_y_frac); | |
684 | ||
685 | if (IsTouchEvent((InternalEvent *)ev)) { | |
686 | if (ev->type == ET_TouchUpdate) | |
687 | xde->flags |= (ev->flags & TOUCH_PENDING_END) ? XITouchPendingEnd : 0; | |
688 | ||
689 | if (ev->flags & TOUCH_POINTER_EMULATED) | |
690 | xde->flags |= XITouchEmulatingPointer; | |
691 | } else { | |
692 | xde->flags = ev->flags; | |
693 | ||
694 | if (ev->key_repeat) | |
695 | xde->flags |= XIKeyRepeat; | |
696 | } | |
697 | ||
698 | xde->mods.base_mods = ev->mods.base; | |
699 | xde->mods.latched_mods = ev->mods.latched; | |
700 | xde->mods.locked_mods = ev->mods.locked; | |
701 | xde->mods.effective_mods = ev->mods.effective; | |
702 | ||
703 | xde->group.base_group = ev->group.base; | |
704 | xde->group.latched_group = ev->group.latched; | |
705 | xde->group.locked_group = ev->group.locked; | |
706 | xde->group.effective_group = ev->group.effective; | |
707 | ||
708 | ptr = (char *) &xde[1]; | |
709 | for (i = 0; i < sizeof(ev->buttons) * 8; i++) { | |
710 | if (BitIsOn(ev->buttons, i)) | |
711 | SetBit(ptr, i); | |
712 | } | |
713 | ||
714 | ptr += xde->buttons_len * 4; | |
715 | axisval = (FP3232 *) (ptr + xde->valuators_len * 4); | |
716 | for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) { | |
717 | if (BitIsOn(ev->valuators.mask, i)) { | |
718 | SetBit(ptr, i); | |
719 | *axisval = double_to_fp3232(ev->valuators.data[i]); | |
720 | axisval++; | |
721 | } | |
722 | } | |
723 | ||
724 | return Success; | |
725 | } | |
726 | ||
727 | static int | |
728 | eventToTouchOwnershipEvent(TouchOwnershipEvent *ev, xEvent **xi) | |
729 | { | |
730 | int len = sizeof(xXITouchOwnershipEvent); | |
731 | xXITouchOwnershipEvent *xtoe; | |
732 | ||
733 | *xi = calloc(1, len); | |
734 | xtoe = (xXITouchOwnershipEvent *) * xi; | |
735 | xtoe->type = GenericEvent; | |
736 | xtoe->extension = IReqCode; | |
737 | xtoe->length = bytes_to_int32(len - sizeof(xEvent)); | |
738 | xtoe->evtype = GetXI2Type(ev->type); | |
739 | xtoe->deviceid = ev->deviceid; | |
740 | xtoe->time = ev->time; | |
741 | xtoe->sourceid = ev->sourceid; | |
742 | xtoe->touchid = ev->touchid; | |
743 | xtoe->flags = 0; /* we don't have wire flags for ownership yet */ | |
744 | ||
745 | return Success; | |
746 | } | |
747 | ||
748 | static int | |
749 | eventToRawEvent(RawDeviceEvent *ev, xEvent **xi) | |
750 | { | |
751 | xXIRawEvent *raw; | |
752 | int vallen, nvals; | |
753 | int i, len = sizeof(xXIRawEvent); | |
754 | char *ptr; | |
755 | FP3232 *axisval, *axisval_raw; | |
756 | ||
757 | nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask)); | |
758 | len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once | |
759 | raw, once processed */ | |
760 | vallen = bytes_to_int32(bits_to_bytes(MAX_VALUATORS)); | |
761 | len += vallen * 4; /* valuators mask */ | |
762 | ||
763 | *xi = calloc(1, len); | |
764 | raw = (xXIRawEvent *) * xi; | |
765 | raw->type = GenericEvent; | |
766 | raw->extension = IReqCode; | |
767 | raw->evtype = GetXI2Type(ev->type); | |
768 | raw->time = ev->time; | |
769 | raw->length = bytes_to_int32(len - sizeof(xEvent)); | |
770 | raw->detail = ev->detail.button; | |
771 | raw->deviceid = ev->deviceid; | |
772 | raw->sourceid = ev->sourceid; | |
773 | raw->valuators_len = vallen; | |
774 | raw->flags = ev->flags; | |
775 | ||
776 | ptr = (char *) &raw[1]; | |
777 | axisval = (FP3232 *) (ptr + raw->valuators_len * 4); | |
778 | axisval_raw = axisval + nvals; | |
779 | for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++) { | |
780 | if (BitIsOn(ev->valuators.mask, i)) { | |
781 | SetBit(ptr, i); | |
782 | *axisval = double_to_fp3232(ev->valuators.data[i]); | |
783 | *axisval_raw = double_to_fp3232(ev->valuators.data_raw[i]); | |
784 | axisval++; | |
785 | axisval_raw++; | |
786 | } | |
787 | } | |
788 | ||
789 | return Success; | |
790 | } | |
791 | ||
792 | static int | |
793 | eventToBarrierEvent(BarrierEvent *ev, xEvent **xi) | |
794 | { | |
795 | xXIBarrierEvent *barrier; | |
796 | int len = sizeof(xXIBarrierEvent); | |
797 | ||
798 | *xi = calloc(1, len); | |
799 | barrier = (xXIBarrierEvent*) *xi; | |
800 | barrier->type = GenericEvent; | |
801 | barrier->extension = IReqCode; | |
802 | barrier->evtype = GetXI2Type(ev->type); | |
803 | barrier->length = bytes_to_int32(len - sizeof(xEvent)); | |
804 | barrier->deviceid = ev->deviceid; | |
805 | barrier->sourceid = ev->sourceid; | |
806 | barrier->time = ev->time; | |
807 | barrier->event = ev->window; | |
808 | barrier->root = ev->root; | |
809 | barrier->dx = double_to_fp3232(ev->dx); | |
810 | barrier->dy = double_to_fp3232(ev->dy); | |
811 | barrier->dtime = ev->dt; | |
812 | barrier->flags = ev->flags; | |
813 | barrier->eventid = ev->event_id; | |
814 | barrier->barrier = ev->barrierid; | |
815 | barrier->root_x = double_to_fp1616(ev->root_x); | |
816 | barrier->root_y = double_to_fp1616(ev->root_y); | |
817 | ||
818 | return Success; | |
819 | } | |
820 | ||
821 | /** | |
822 | * Return the corresponding core type for the given event or 0 if no core | |
823 | * equivalent exists. | |
824 | */ | |
825 | int | |
826 | GetCoreType(enum EventType type) | |
827 | { | |
828 | int coretype = 0; | |
829 | ||
830 | switch (type) { | |
831 | case ET_Motion: | |
832 | coretype = MotionNotify; | |
833 | break; | |
834 | case ET_ButtonPress: | |
835 | coretype = ButtonPress; | |
836 | break; | |
837 | case ET_ButtonRelease: | |
838 | coretype = ButtonRelease; | |
839 | break; | |
840 | case ET_KeyPress: | |
841 | coretype = KeyPress; | |
842 | break; | |
843 | case ET_KeyRelease: | |
844 | coretype = KeyRelease; | |
845 | break; | |
846 | default: | |
847 | break; | |
848 | } | |
849 | return coretype; | |
850 | } | |
851 | ||
852 | /** | |
853 | * Return the corresponding XI 1.x type for the given event or 0 if no | |
854 | * equivalent exists. | |
855 | */ | |
856 | int | |
857 | GetXIType(enum EventType type) | |
858 | { | |
859 | int xitype = 0; | |
860 | ||
861 | switch (type) { | |
862 | case ET_Motion: | |
863 | xitype = DeviceMotionNotify; | |
864 | break; | |
865 | case ET_ButtonPress: | |
866 | xitype = DeviceButtonPress; | |
867 | break; | |
868 | case ET_ButtonRelease: | |
869 | xitype = DeviceButtonRelease; | |
870 | break; | |
871 | case ET_KeyPress: | |
872 | xitype = DeviceKeyPress; | |
873 | break; | |
874 | case ET_KeyRelease: | |
875 | xitype = DeviceKeyRelease; | |
876 | break; | |
877 | case ET_ProximityIn: | |
878 | xitype = ProximityIn; | |
879 | break; | |
880 | case ET_ProximityOut: | |
881 | xitype = ProximityOut; | |
882 | break; | |
883 | default: | |
884 | break; | |
885 | } | |
886 | return xitype; | |
887 | } | |
888 | ||
889 | /** | |
890 | * Return the corresponding XI 2.x type for the given event or 0 if no | |
891 | * equivalent exists. | |
892 | */ | |
893 | int | |
894 | GetXI2Type(enum EventType type) | |
895 | { | |
896 | int xi2type = 0; | |
897 | ||
898 | switch (type) { | |
899 | case ET_Motion: | |
900 | xi2type = XI_Motion; | |
901 | break; | |
902 | case ET_ButtonPress: | |
903 | xi2type = XI_ButtonPress; | |
904 | break; | |
905 | case ET_ButtonRelease: | |
906 | xi2type = XI_ButtonRelease; | |
907 | break; | |
908 | case ET_KeyPress: | |
909 | xi2type = XI_KeyPress; | |
910 | break; | |
911 | case ET_KeyRelease: | |
912 | xi2type = XI_KeyRelease; | |
913 | break; | |
914 | case ET_Enter: | |
915 | xi2type = XI_Enter; | |
916 | break; | |
917 | case ET_Leave: | |
918 | xi2type = XI_Leave; | |
919 | break; | |
920 | case ET_Hierarchy: | |
921 | xi2type = XI_HierarchyChanged; | |
922 | break; | |
923 | case ET_DeviceChanged: | |
924 | xi2type = XI_DeviceChanged; | |
925 | break; | |
926 | case ET_RawKeyPress: | |
927 | xi2type = XI_RawKeyPress; | |
928 | break; | |
929 | case ET_RawKeyRelease: | |
930 | xi2type = XI_RawKeyRelease; | |
931 | break; | |
932 | case ET_RawButtonPress: | |
933 | xi2type = XI_RawButtonPress; | |
934 | break; | |
935 | case ET_RawButtonRelease: | |
936 | xi2type = XI_RawButtonRelease; | |
937 | break; | |
938 | case ET_RawMotion: | |
939 | xi2type = XI_RawMotion; | |
940 | break; | |
941 | case ET_RawTouchBegin: | |
942 | xi2type = XI_RawTouchBegin; | |
943 | break; | |
944 | case ET_RawTouchUpdate: | |
945 | xi2type = XI_RawTouchUpdate; | |
946 | break; | |
947 | case ET_RawTouchEnd: | |
948 | xi2type = XI_RawTouchEnd; | |
949 | break; | |
950 | case ET_FocusIn: | |
951 | xi2type = XI_FocusIn; | |
952 | break; | |
953 | case ET_FocusOut: | |
954 | xi2type = XI_FocusOut; | |
955 | break; | |
956 | case ET_TouchBegin: | |
957 | xi2type = XI_TouchBegin; | |
958 | break; | |
959 | case ET_TouchEnd: | |
960 | xi2type = XI_TouchEnd; | |
961 | break; | |
962 | case ET_TouchUpdate: | |
963 | xi2type = XI_TouchUpdate; | |
964 | break; | |
965 | case ET_TouchOwnership: | |
966 | xi2type = XI_TouchOwnership; | |
967 | break; | |
968 | case ET_BarrierHit: | |
969 | xi2type = XI_BarrierHit; | |
970 | break; | |
971 | case ET_BarrierLeave: | |
972 | xi2type = XI_BarrierLeave; | |
973 | break; | |
974 | default: | |
975 | break; | |
976 | } | |
977 | return xi2type; | |
978 | } |