Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 2008 Daniel Stone | |
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 | * Author: Daniel Stone <daniel@fooishbar.org> | |
24 | */ | |
25 | ||
26 | #ifdef HAVE_DIX_CONFIG_H | |
27 | #include "dix-config.h" | |
28 | #endif | |
29 | ||
30 | #include "exevents.h" | |
31 | #include "exglobals.h" | |
32 | #include "misc.h" | |
33 | #include "input.h" | |
34 | #include "inputstr.h" | |
35 | #include "xace.h" | |
36 | #include "xkbsrv.h" | |
37 | #include "xkbstr.h" | |
38 | #include "inpututils.h" | |
39 | #include "eventstr.h" | |
40 | #include "scrnintstr.h" | |
41 | #include "optionstr.h" | |
42 | ||
43 | /* Check if a button map change is okay with the device. | |
44 | * Returns -1 for BadValue, as it collides with MappingBusy. */ | |
45 | static int | |
46 | check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out, | |
47 | ClientPtr client) | |
48 | { | |
49 | int i, ret; | |
50 | ||
51 | if (!dev || !dev->button) { | |
52 | client->errorValue = (dev) ? dev->id : 0; | |
53 | return BadDevice; | |
54 | } | |
55 | ||
56 | ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); | |
57 | if (ret != Success) { | |
58 | client->errorValue = dev->id; | |
59 | return ret; | |
60 | } | |
61 | ||
62 | for (i = 0; i < len; i++) { | |
63 | if (dev->button->map[i + 1] != map[i] && | |
64 | button_is_down(dev, i + 1, BUTTON_PROCESSED)) | |
65 | return MappingBusy; | |
66 | } | |
67 | ||
68 | return Success; | |
69 | } | |
70 | ||
71 | static void | |
72 | do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) | |
73 | { | |
74 | int i; | |
75 | xEvent core_mn = { .u.u.type = MappingNotify }; | |
76 | deviceMappingNotify xi_mn; | |
77 | ||
78 | /* The map in ButtonClassRec refers to button numbers, whereas the | |
79 | * protocol is zero-indexed. Sigh. */ | |
80 | memcpy(&(dev->button->map[1]), map, len); | |
81 | ||
82 | core_mn.u.mappingNotify.request = MappingPointer; | |
83 | ||
84 | /* 0 is the server client. */ | |
85 | for (i = 1; i < currentMaxClients; i++) { | |
86 | /* Don't send irrelevant events to naïve clients. */ | |
87 | if (!clients[i] || clients[i]->clientState != ClientStateRunning) | |
88 | continue; | |
89 | ||
90 | if (!XIShouldNotify(clients[i], dev)) | |
91 | continue; | |
92 | ||
93 | WriteEventsToClient(clients[i], 1, &core_mn); | |
94 | } | |
95 | ||
96 | xi_mn = (deviceMappingNotify) { | |
97 | .type = DeviceMappingNotify, | |
98 | .request = MappingPointer, | |
99 | .deviceid = dev->id, | |
100 | .time = GetTimeInMillis() | |
101 | }; | |
102 | ||
103 | SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); | |
104 | } | |
105 | ||
106 | /* | |
107 | * Does what it says on the box, both for core and Xi. | |
108 | * | |
109 | * Faithfully reports any errors encountered while trying to apply the map | |
110 | * to the requested device, faithfully ignores any errors encountered while | |
111 | * trying to apply the map to its master/slaves. | |
112 | */ | |
113 | int | |
114 | ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) | |
115 | { | |
116 | int ret; | |
117 | ||
118 | /* If we can't perform the change on the requested device, bail out. */ | |
119 | ret = check_butmap_change(dev, map, len, &client->errorValue, client); | |
120 | if (ret != Success) | |
121 | return ret; | |
122 | do_butmap_change(dev, map, len, client); | |
123 | ||
124 | return Success; | |
125 | } | |
126 | ||
127 | /* Check if a modifier map change is okay with the device. | |
128 | * Returns -1 for BadValue, as it collides with MappingBusy; this particular | |
129 | * caveat can be removed with LegalModifier, as we have no other reason to | |
130 | * set MappingFailed. Sigh. */ | |
131 | static int | |
132 | check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap) | |
133 | { | |
134 | int ret, i; | |
135 | XkbDescPtr xkb; | |
136 | ||
137 | ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); | |
138 | if (ret != Success) | |
139 | return ret; | |
140 | ||
141 | if (!dev->key) | |
142 | return BadMatch; | |
143 | xkb = dev->key->xkbInfo->desc; | |
144 | ||
145 | for (i = 0; i < MAP_LENGTH; i++) { | |
146 | if (!modmap[i]) | |
147 | continue; | |
148 | ||
149 | /* Check that all the new modifiers fall within the advertised | |
150 | * keycode range. */ | |
151 | if (i < xkb->min_key_code || i > xkb->max_key_code) { | |
152 | client->errorValue = i; | |
153 | return -1; | |
154 | } | |
155 | ||
156 | /* Make sure the mapping is okay with the DDX. */ | |
157 | if (!LegalModifier(i, dev)) { | |
158 | client->errorValue = i; | |
159 | return MappingFailed; | |
160 | } | |
161 | ||
162 | /* None of the new modifiers may be down while we change the | |
163 | * map. */ | |
164 | if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { | |
165 | client->errorValue = i; | |
166 | return MappingBusy; | |
167 | } | |
168 | } | |
169 | ||
170 | /* None of the old modifiers may be down while we change the map, | |
171 | * either. */ | |
172 | for (i = xkb->min_key_code; i < xkb->max_key_code; i++) { | |
173 | if (!xkb->map->modmap[i]) | |
174 | continue; | |
175 | if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { | |
176 | client->errorValue = i; | |
177 | return MappingBusy; | |
178 | } | |
179 | } | |
180 | ||
181 | return Success; | |
182 | } | |
183 | ||
184 | static int | |
185 | check_modmap_change_slave(ClientPtr client, DeviceIntPtr master, | |
186 | DeviceIntPtr slave, CARD8 *modmap) | |
187 | { | |
188 | XkbDescPtr master_xkb, slave_xkb; | |
189 | int i, j; | |
190 | ||
191 | if (!slave->key || !master->key) | |
192 | return 0; | |
193 | ||
194 | master_xkb = master->key->xkbInfo->desc; | |
195 | slave_xkb = slave->key->xkbInfo->desc; | |
196 | ||
197 | /* Ignore devices with a clearly different keymap. */ | |
198 | if (slave_xkb->min_key_code != master_xkb->min_key_code || | |
199 | slave_xkb->max_key_code != master_xkb->max_key_code) | |
200 | return 0; | |
201 | ||
202 | for (i = 0; i < MAP_LENGTH; i++) { | |
203 | if (!modmap[i]) | |
204 | continue; | |
205 | ||
206 | /* If we have different symbols for any modifier on an | |
207 | * extended keyboard, ignore the whole remap request. */ | |
208 | for (j = 0; | |
209 | j < XkbKeyNumSyms(slave_xkb, i) && | |
210 | j < XkbKeyNumSyms(master_xkb, i); j++) | |
211 | if (XkbKeySymsPtr(slave_xkb, i)[j] != | |
212 | XkbKeySymsPtr(master_xkb, i)[j]) | |
213 | return 0; | |
214 | } | |
215 | ||
216 | if (check_modmap_change(client, slave, modmap) != Success) | |
217 | return 0; | |
218 | ||
219 | return 1; | |
220 | } | |
221 | ||
222 | /* Actually change the modifier map, and send notifications. Cannot fail. */ | |
223 | static void | |
224 | do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) | |
225 | { | |
226 | XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient); | |
227 | } | |
228 | ||
229 | /* Rebuild modmap (key -> mod) from map (mod -> key). */ | |
230 | static int | |
231 | build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap, | |
232 | int max_keys_per_mod) | |
233 | { | |
234 | int i, len = max_keys_per_mod * 8; | |
235 | ||
236 | memset(modmap, 0, MAP_LENGTH); | |
237 | ||
238 | for (i = 0; i < len; i++) { | |
239 | if (!modkeymap[i]) | |
240 | continue; | |
241 | ||
242 | if (modkeymap[i] >= MAP_LENGTH) | |
243 | return BadValue; | |
244 | ||
245 | if (modmap[modkeymap[i]]) | |
246 | return BadValue; | |
247 | ||
248 | modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod); | |
249 | } | |
250 | ||
251 | return Success; | |
252 | } | |
253 | ||
254 | int | |
255 | change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, | |
256 | int max_keys_per_mod) | |
257 | { | |
258 | int ret; | |
259 | CARD8 modmap[MAP_LENGTH]; | |
260 | DeviceIntPtr tmp; | |
261 | ||
262 | ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); | |
263 | if (ret != Success) | |
264 | return ret; | |
265 | ||
266 | /* If we can't perform the change on the requested device, bail out. */ | |
267 | ret = check_modmap_change(client, dev, modmap); | |
268 | if (ret != Success) | |
269 | return ret; | |
270 | do_modmap_change(client, dev, modmap); | |
271 | ||
272 | /* Change any attached masters/slaves. */ | |
273 | if (IsMaster(dev)) { | |
274 | for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { | |
275 | if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev) | |
276 | if (check_modmap_change_slave(client, dev, tmp, modmap)) | |
277 | do_modmap_change(client, tmp, modmap); | |
278 | } | |
279 | } | |
280 | else if (!IsFloating(dev) && | |
281 | GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) { | |
282 | /* If this fails, expect the results to be weird. */ | |
283 | if (check_modmap_change(client, dev->master, modmap)) | |
284 | do_modmap_change(client, dev->master, modmap); | |
285 | } | |
286 | ||
287 | return Success; | |
288 | } | |
289 | ||
290 | int | |
291 | generate_modkeymap(ClientPtr client, DeviceIntPtr dev, | |
292 | KeyCode **modkeymap_out, int *max_keys_per_mod_out) | |
293 | { | |
294 | CARD8 keys_per_mod[8]; | |
295 | int max_keys_per_mod; | |
296 | KeyCode *modkeymap = NULL; | |
297 | int i, j, ret; | |
298 | ||
299 | ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); | |
300 | if (ret != Success) | |
301 | return ret; | |
302 | ||
303 | if (!dev->key) | |
304 | return BadMatch; | |
305 | ||
306 | /* Count the number of keys per modifier to determine how wide we | |
307 | * should make the map. */ | |
308 | max_keys_per_mod = 0; | |
309 | for (i = 0; i < 8; i++) | |
310 | keys_per_mod[i] = 0; | |
311 | for (i = 8; i < MAP_LENGTH; i++) { | |
312 | for (j = 0; j < 8; j++) { | |
313 | if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { | |
314 | if (++keys_per_mod[j] > max_keys_per_mod) | |
315 | max_keys_per_mod = keys_per_mod[j]; | |
316 | } | |
317 | } | |
318 | } | |
319 | ||
320 | if (max_keys_per_mod != 0) { | |
321 | modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode)); | |
322 | if (!modkeymap) | |
323 | return BadAlloc; | |
324 | ||
325 | for (i = 0; i < 8; i++) | |
326 | keys_per_mod[i] = 0; | |
327 | ||
328 | for (i = 8; i < MAP_LENGTH; i++) { | |
329 | for (j = 0; j < 8; j++) { | |
330 | if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { | |
331 | modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i; | |
332 | keys_per_mod[j]++; | |
333 | } | |
334 | } | |
335 | } | |
336 | } | |
337 | ||
338 | *max_keys_per_mod_out = max_keys_per_mod; | |
339 | *modkeymap_out = modkeymap; | |
340 | ||
341 | return Success; | |
342 | } | |
343 | ||
344 | /** | |
345 | * Duplicate the InputAttributes in the most obvious way. | |
346 | * No special memory handling is used to give drivers the maximum | |
347 | * flexibility with the data. Drivers should be able to call realloc on the | |
348 | * product string if needed and perform similar operations. | |
349 | */ | |
350 | InputAttributes * | |
351 | DuplicateInputAttributes(InputAttributes * attrs) | |
352 | { | |
353 | InputAttributes *new_attr; | |
354 | int ntags = 0; | |
355 | char **tags, **new_tags; | |
356 | ||
357 | if (!attrs) | |
358 | return NULL; | |
359 | ||
360 | if (!(new_attr = calloc(1, sizeof(InputAttributes)))) | |
361 | goto unwind; | |
362 | ||
363 | if (attrs->product && !(new_attr->product = strdup(attrs->product))) | |
364 | goto unwind; | |
365 | if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor))) | |
366 | goto unwind; | |
367 | if (attrs->device && !(new_attr->device = strdup(attrs->device))) | |
368 | goto unwind; | |
369 | if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) | |
370 | goto unwind; | |
371 | if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id))) | |
372 | goto unwind; | |
373 | ||
374 | new_attr->flags = attrs->flags; | |
375 | ||
376 | if ((tags = attrs->tags)) { | |
377 | while (*tags++) | |
378 | ntags++; | |
379 | ||
380 | new_attr->tags = calloc(ntags + 1, sizeof(char *)); | |
381 | if (!new_attr->tags) | |
382 | goto unwind; | |
383 | ||
384 | tags = attrs->tags; | |
385 | new_tags = new_attr->tags; | |
386 | ||
387 | while (*tags) { | |
388 | *new_tags = strdup(*tags); | |
389 | if (!*new_tags) | |
390 | goto unwind; | |
391 | ||
392 | tags++; | |
393 | new_tags++; | |
394 | } | |
395 | } | |
396 | ||
397 | return new_attr; | |
398 | ||
399 | unwind: | |
400 | FreeInputAttributes(new_attr); | |
401 | return NULL; | |
402 | } | |
403 | ||
404 | void | |
405 | FreeInputAttributes(InputAttributes * attrs) | |
406 | { | |
407 | char **tags; | |
408 | ||
409 | if (!attrs) | |
410 | return; | |
411 | ||
412 | free(attrs->product); | |
413 | free(attrs->vendor); | |
414 | free(attrs->device); | |
415 | free(attrs->pnp_id); | |
416 | free(attrs->usb_id); | |
417 | ||
418 | if ((tags = attrs->tags)) | |
419 | while (*tags) | |
420 | free(*tags++); | |
421 | ||
422 | free(attrs->tags); | |
423 | free(attrs); | |
424 | } | |
425 | ||
426 | /** | |
427 | * Alloc a valuator mask large enough for num_valuators. | |
428 | */ | |
429 | ValuatorMask * | |
430 | valuator_mask_new(int num_valuators) | |
431 | { | |
432 | /* alloc a fixed size mask for now and ignore num_valuators. in the | |
433 | * flying-car future, when we can dynamically alloc the masks and are | |
434 | * not constrained by signals, we can start using num_valuators */ | |
435 | ValuatorMask *mask = calloc(1, sizeof(ValuatorMask)); | |
436 | ||
437 | if (mask == NULL) | |
438 | return NULL; | |
439 | ||
440 | mask->last_bit = -1; | |
441 | return mask; | |
442 | } | |
443 | ||
444 | void | |
445 | valuator_mask_free(ValuatorMask **mask) | |
446 | { | |
447 | free(*mask); | |
448 | *mask = NULL; | |
449 | } | |
450 | ||
451 | /** | |
452 | * Sets a range of valuators between first_valuator and num_valuators with | |
453 | * the data in the valuators array. All other values are set to 0. | |
454 | */ | |
455 | void | |
456 | valuator_mask_set_range(ValuatorMask *mask, int first_valuator, | |
457 | int num_valuators, const int *valuators) | |
458 | { | |
459 | int i; | |
460 | ||
461 | valuator_mask_zero(mask); | |
462 | ||
463 | for (i = first_valuator; | |
464 | i < min(first_valuator + num_valuators, MAX_VALUATORS); i++) | |
465 | valuator_mask_set(mask, i, valuators[i - first_valuator]); | |
466 | } | |
467 | ||
468 | /** | |
469 | * Reset mask to zero. | |
470 | */ | |
471 | void | |
472 | valuator_mask_zero(ValuatorMask *mask) | |
473 | { | |
474 | memset(mask, 0, sizeof(*mask)); | |
475 | mask->last_bit = -1; | |
476 | } | |
477 | ||
478 | /** | |
479 | * Returns the current size of the mask (i.e. the highest number of | |
480 | * valuators currently set + 1). | |
481 | */ | |
482 | int | |
483 | valuator_mask_size(const ValuatorMask *mask) | |
484 | { | |
485 | return mask->last_bit + 1; | |
486 | } | |
487 | ||
488 | /** | |
489 | * Returns the number of valuators set in the given mask. | |
490 | */ | |
491 | int | |
492 | valuator_mask_num_valuators(const ValuatorMask *mask) | |
493 | { | |
494 | return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS)); | |
495 | } | |
496 | ||
497 | /** | |
498 | * Return true if the valuator is set in the mask, or false otherwise. | |
499 | */ | |
500 | int | |
501 | valuator_mask_isset(const ValuatorMask *mask, int valuator) | |
502 | { | |
503 | return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator); | |
504 | } | |
505 | ||
506 | /** | |
507 | * Set the valuator to the given floating-point data. | |
508 | */ | |
509 | void | |
510 | valuator_mask_set_double(ValuatorMask *mask, int valuator, double data) | |
511 | { | |
512 | mask->last_bit = max(valuator, mask->last_bit); | |
513 | SetBit(mask->mask, valuator); | |
514 | mask->valuators[valuator] = data; | |
515 | } | |
516 | ||
517 | /** | |
518 | * Set the valuator to the given integer data. | |
519 | */ | |
520 | void | |
521 | valuator_mask_set(ValuatorMask *mask, int valuator, int data) | |
522 | { | |
523 | valuator_mask_set_double(mask, valuator, data); | |
524 | } | |
525 | ||
526 | /** | |
527 | * Return the requested valuator value as a double. If the mask bit is not | |
528 | * set for the given valuator, the returned value is undefined. | |
529 | */ | |
530 | double | |
531 | valuator_mask_get_double(const ValuatorMask *mask, int valuator) | |
532 | { | |
533 | return mask->valuators[valuator]; | |
534 | } | |
535 | ||
536 | /** | |
537 | * Return the requested valuator value as an integer, rounding towards zero. | |
538 | * If the mask bit is not set for the given valuator, the returned value is | |
539 | * undefined. | |
540 | */ | |
541 | int | |
542 | valuator_mask_get(const ValuatorMask *mask, int valuator) | |
543 | { | |
544 | return trunc(valuator_mask_get_double(mask, valuator)); | |
545 | } | |
546 | ||
547 | /** | |
548 | * Set value to the requested valuator. If the mask bit is set for this | |
549 | * valuator, value contains the requested valuator value and TRUE is | |
550 | * returned. | |
551 | * If the mask bit is not set for this valuator, value is unchanged and | |
552 | * FALSE is returned. | |
553 | */ | |
554 | Bool | |
555 | valuator_mask_fetch_double(const ValuatorMask *mask, int valuator, | |
556 | double *value) | |
557 | { | |
558 | if (valuator_mask_isset(mask, valuator)) { | |
559 | *value = valuator_mask_get_double(mask, valuator); | |
560 | return TRUE; | |
561 | } | |
562 | else | |
563 | return FALSE; | |
564 | } | |
565 | ||
566 | /** | |
567 | * Set value to the requested valuator. If the mask bit is set for this | |
568 | * valuator, value contains the requested valuator value and TRUE is | |
569 | * returned. | |
570 | * If the mask bit is not set for this valuator, value is unchanged and | |
571 | * FALSE is returned. | |
572 | */ | |
573 | Bool | |
574 | valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value) | |
575 | { | |
576 | if (valuator_mask_isset(mask, valuator)) { | |
577 | *value = valuator_mask_get(mask, valuator); | |
578 | return TRUE; | |
579 | } | |
580 | else | |
581 | return FALSE; | |
582 | } | |
583 | ||
584 | /** | |
585 | * Remove the valuator from the mask. | |
586 | */ | |
587 | void | |
588 | valuator_mask_unset(ValuatorMask *mask, int valuator) | |
589 | { | |
590 | if (mask->last_bit >= valuator) { | |
591 | int i, lastbit = -1; | |
592 | ||
593 | ClearBit(mask->mask, valuator); | |
594 | mask->valuators[valuator] = 0.0; | |
595 | ||
596 | for (i = 0; i <= mask->last_bit; i++) | |
597 | if (valuator_mask_isset(mask, i)) | |
598 | lastbit = max(lastbit, i); | |
599 | mask->last_bit = lastbit; | |
600 | } | |
601 | } | |
602 | ||
603 | void | |
604 | valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src) | |
605 | { | |
606 | if (src) | |
607 | memcpy(dest, src, sizeof(*dest)); | |
608 | else | |
609 | valuator_mask_zero(dest); | |
610 | } | |
611 | ||
612 | int | |
613 | CountBits(const uint8_t * mask, int len) | |
614 | { | |
615 | int i; | |
616 | int ret = 0; | |
617 | ||
618 | for (i = 0; i < len; i++) | |
619 | if (BitIsOn(mask, i)) | |
620 | ret++; | |
621 | ||
622 | return ret; | |
623 | } | |
624 | ||
625 | /** | |
626 | * Verifies sanity of the event. If the event is not an internal event, | |
627 | * memdumps the first 32 bytes of event to the log, a backtrace, then kill | |
628 | * the server. | |
629 | */ | |
630 | void | |
631 | verify_internal_event(const InternalEvent *ev) | |
632 | { | |
633 | if (ev && ev->any.header != ET_Internal) { | |
634 | int i; | |
635 | const unsigned char *data = (const unsigned char *) ev; | |
636 | ||
637 | ErrorF("dix: invalid event type %d\n", ev->any.header); | |
638 | ||
639 | for (i = 0; i < sizeof(xEvent); i++, data++) { | |
640 | ErrorF("%02hhx ", *data); | |
641 | ||
642 | if ((i % 8) == 7) | |
643 | ErrorF("\n"); | |
644 | } | |
645 | ||
646 | xorg_backtrace(); | |
647 | FatalError("Wrong event type %d. Aborting server\n", ev->any.header); | |
648 | } | |
649 | } | |
650 | ||
651 | /** | |
652 | * Initializes the given event to zero (or default values), for the given | |
653 | * device. | |
654 | */ | |
655 | void | |
656 | init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms) | |
657 | { | |
658 | memset(event, 0, sizeof(DeviceEvent)); | |
659 | event->header = ET_Internal; | |
660 | event->length = sizeof(DeviceEvent); | |
661 | event->time = ms; | |
662 | event->deviceid = dev->id; | |
663 | event->sourceid = dev->id; | |
664 | } | |
665 | ||
666 | int | |
667 | event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd) | |
668 | { | |
669 | int corestate; | |
670 | ||
671 | /* core state needs to be assembled BEFORE the device is updated. */ | |
672 | corestate = (kbd && | |
673 | kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo-> | |
674 | state) : 0; | |
675 | corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0; | |
676 | corestate |= (mouse && mouse->touch) ? (mouse->touch->state) : 0; | |
677 | ||
678 | return corestate; | |
679 | } | |
680 | ||
681 | void | |
682 | event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event) | |
683 | { | |
684 | int i; | |
685 | ||
686 | for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) | |
687 | if (BitIsOn(mouse->button->down, i)) | |
688 | SetBit(event->buttons, mouse->button->map[i]); | |
689 | ||
690 | if (mouse && mouse->touch && mouse->touch->buttonsDown > 0) | |
691 | SetBit(event->buttons, mouse->button->map[1]); | |
692 | ||
693 | if (kbd && kbd->key) { | |
694 | XkbStatePtr state; | |
695 | ||
696 | /* we need the state before the event happens */ | |
697 | if (event->type == ET_KeyPress || event->type == ET_KeyRelease) | |
698 | state = &kbd->key->xkbInfo->prev_state; | |
699 | else | |
700 | state = &kbd->key->xkbInfo->state; | |
701 | ||
702 | event->mods.base = state->base_mods; | |
703 | event->mods.latched = state->latched_mods; | |
704 | event->mods.locked = state->locked_mods; | |
705 | event->mods.effective = state->mods; | |
706 | ||
707 | event->group.base = state->base_group; | |
708 | event->group.latched = state->latched_group; | |
709 | event->group.locked = state->locked_group; | |
710 | event->group.effective = state->group; | |
711 | } | |
712 | } | |
713 | ||
714 | /** | |
715 | * Return the event filter mask for the given device and the given core or | |
716 | * XI1 protocol type. | |
717 | */ | |
718 | Mask | |
719 | event_get_filter_from_type(DeviceIntPtr dev, int evtype) | |
720 | { | |
721 | return event_filters[dev ? dev->id : 0][evtype]; | |
722 | } | |
723 | ||
724 | /** | |
725 | * Return the event filter mask for the given device and the given core or | |
726 | * XI2 protocol type. | |
727 | */ | |
728 | Mask | |
729 | event_get_filter_from_xi2type(int evtype) | |
730 | { | |
731 | return (1 << (evtype % 8)); | |
732 | } | |
733 | ||
734 | Bool | |
735 | point_on_screen(ScreenPtr pScreen, int x, int y) | |
736 | { | |
737 | return x >= pScreen->x && x < pScreen->x + pScreen->width && | |
738 | y >= pScreen->y && y < pScreen->y + pScreen->height; | |
739 | } | |
740 | ||
741 | /** | |
742 | * Update desktop dimensions on the screenInfo struct. | |
743 | */ | |
744 | void | |
745 | update_desktop_dimensions(void) | |
746 | { | |
747 | int i; | |
748 | int x1 = INT_MAX, y1 = INT_MAX; /* top-left */ | |
749 | int x2 = INT_MIN, y2 = INT_MIN; /* bottom-right */ | |
750 | ||
751 | for (i = 0; i < screenInfo.numScreens; i++) { | |
752 | ScreenPtr screen = screenInfo.screens[i]; | |
753 | ||
754 | x1 = min(x1, screen->x); | |
755 | y1 = min(y1, screen->y); | |
756 | x2 = max(x2, screen->x + screen->width); | |
757 | y2 = max(y2, screen->y + screen->height); | |
758 | } | |
759 | ||
760 | screenInfo.x = x1; | |
761 | screenInfo.y = y1; | |
762 | screenInfo.width = x2 - x1; | |
763 | screenInfo.height = y2 - y1; | |
764 | } | |
765 | ||
766 | /* | |
767 | * Delete the element with the key from the list, freeing all memory | |
768 | * associated with the element.. | |
769 | */ | |
770 | static void | |
771 | input_option_free(InputOption *o) | |
772 | { | |
773 | free(o->opt_name); | |
774 | free(o->opt_val); | |
775 | free(o->opt_comment); | |
776 | free(o); | |
777 | } | |
778 | ||
779 | /* | |
780 | * Create a new InputOption with the key/value pair provided. | |
781 | * If a list is provided, the new options is added to the list and the list | |
782 | * is returned. | |
783 | * | |
784 | * If a new option is added to a list that already contains that option, the | |
785 | * previous option is overwritten. | |
786 | * | |
787 | * @param list The list to add to. | |
788 | * @param key Option key, will be copied. | |
789 | * @param value Option value, will be copied. | |
790 | * | |
791 | * @return If list is not NULL, the list with the new option added. If list | |
792 | * is NULL, a new option list with one element. On failure, NULL is | |
793 | * returned. | |
794 | */ | |
795 | InputOption * | |
796 | input_option_new(InputOption *list, const char *key, const char *value) | |
797 | { | |
798 | InputOption *opt = NULL; | |
799 | ||
800 | if (!key) | |
801 | return NULL; | |
802 | ||
803 | if (list) { | |
804 | nt_list_for_each_entry(opt, list, list.next) { | |
805 | if (strcmp(input_option_get_key(opt), key) == 0) { | |
806 | input_option_set_value(opt, value); | |
807 | return list; | |
808 | } | |
809 | } | |
810 | } | |
811 | ||
812 | opt = calloc(1, sizeof(InputOption)); | |
813 | if (!opt) | |
814 | return NULL; | |
815 | ||
816 | nt_list_init(opt, list.next); | |
817 | input_option_set_key(opt, key); | |
818 | input_option_set_value(opt, value); | |
819 | ||
820 | if (list) { | |
821 | nt_list_append(opt, list, InputOption, list.next); | |
822 | ||
823 | return list; | |
824 | } | |
825 | else | |
826 | return opt; | |
827 | } | |
828 | ||
829 | InputOption * | |
830 | input_option_free_element(InputOption *list, const char *key) | |
831 | { | |
832 | InputOption *element; | |
833 | ||
834 | nt_list_for_each_entry(element, list, list.next) { | |
835 | if (strcmp(input_option_get_key(element), key) == 0) { | |
836 | nt_list_del(element, list, InputOption, list.next); | |
837 | ||
838 | input_option_free(element); | |
839 | break; | |
840 | } | |
841 | } | |
842 | return list; | |
843 | } | |
844 | ||
845 | /** | |
846 | * Free the list pointed at by opt. | |
847 | */ | |
848 | void | |
849 | input_option_free_list(InputOption **opt) | |
850 | { | |
851 | InputOption *element, *tmp; | |
852 | ||
853 | nt_list_for_each_entry_safe(element, tmp, *opt, list.next) { | |
854 | nt_list_del(element, *opt, InputOption, list.next); | |
855 | ||
856 | input_option_free(element); | |
857 | } | |
858 | *opt = NULL; | |
859 | } | |
860 | ||
861 | /** | |
862 | * Find the InputOption with the given option name. | |
863 | * | |
864 | * @return The InputOption or NULL if not present. | |
865 | */ | |
866 | InputOption * | |
867 | input_option_find(InputOption *list, const char *key) | |
868 | { | |
869 | InputOption *element; | |
870 | ||
871 | nt_list_for_each_entry(element, list, list.next) { | |
872 | if (strcmp(input_option_get_key(element), key) == 0) | |
873 | return element; | |
874 | } | |
875 | ||
876 | return NULL; | |
877 | } | |
878 | ||
879 | const char * | |
880 | input_option_get_key(const InputOption *opt) | |
881 | { | |
882 | return opt->opt_name; | |
883 | } | |
884 | ||
885 | const char * | |
886 | input_option_get_value(const InputOption *opt) | |
887 | { | |
888 | return opt->opt_val; | |
889 | } | |
890 | ||
891 | void | |
892 | input_option_set_key(InputOption *opt, const char *key) | |
893 | { | |
894 | free(opt->opt_name); | |
895 | if (key) | |
896 | opt->opt_name = strdup(key); | |
897 | } | |
898 | ||
899 | void | |
900 | input_option_set_value(InputOption *opt, const char *value) | |
901 | { | |
902 | free(opt->opt_val); | |
903 | if (value) | |
904 | opt->opt_val = strdup(value); | |
905 | } | |
906 | ||
907 | /* FP1616/FP3232 conversion functions. | |
908 | * Fixed point types are encoded as signed integral and unsigned frac. So any | |
909 | * negative number -n.m is encoded as floor(n) + (1 - 0.m). | |
910 | */ | |
911 | double | |
912 | fp1616_to_double(FP1616 in) | |
913 | { | |
914 | return pixman_fixed_to_double(in); | |
915 | } | |
916 | ||
917 | double | |
918 | fp3232_to_double(FP3232 in) | |
919 | { | |
920 | double ret; | |
921 | ||
922 | ret = (double) in.integral; | |
923 | ret += (double) in.frac * (1.0 / (1ULL << 32)); /* Optimized: ldexp((double)in.frac, -32); */ | |
924 | return ret; | |
925 | } | |
926 | ||
927 | FP1616 | |
928 | double_to_fp1616(double in) | |
929 | { | |
930 | return pixman_double_to_fixed(in); | |
931 | } | |
932 | ||
933 | FP3232 | |
934 | double_to_fp3232(double in) | |
935 | { | |
936 | FP3232 ret; | |
937 | int32_t integral; | |
938 | double tmp; | |
939 | uint32_t frac_d; | |
940 | ||
941 | tmp = floor(in); | |
942 | integral = (int32_t) tmp; | |
943 | ||
944 | tmp = (in - integral) * (1ULL << 32); /* Optimized: ldexp(in - integral, 32) */ | |
945 | frac_d = (uint32_t) tmp; | |
946 | ||
947 | ret.integral = integral; | |
948 | ret.frac = frac_d; | |
949 | return ret; | |
950 | } | |
951 | ||
952 | /** | |
953 | * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use | |
954 | * xi2mask_new() instead to get the standard sized masks. | |
955 | * | |
956 | * @param nmasks The number of masks (== number of devices) | |
957 | * @param size The size of the masks in bytes | |
958 | * @return The new mask or NULL on allocation error. | |
959 | */ | |
960 | XI2Mask * | |
961 | xi2mask_new_with_size(size_t nmasks, size_t size) | |
962 | { | |
963 | int i; | |
964 | int alloc_size; | |
965 | unsigned char *cursor; | |
966 | XI2Mask *mask; | |
967 | ||
968 | alloc_size = sizeof(struct _XI2Mask) | |
969 | + nmasks * sizeof(unsigned char *) | |
970 | + nmasks * size; | |
971 | ||
972 | mask = calloc(1, alloc_size); | |
973 | ||
974 | if (!mask) | |
975 | return NULL; | |
976 | ||
977 | mask->nmasks = nmasks; | |
978 | mask->mask_size = size; | |
979 | ||
980 | mask->masks = (unsigned char **)(mask + 1); | |
981 | cursor = (unsigned char *)(mask + 1) + nmasks * sizeof(unsigned char *); | |
982 | ||
983 | for (i = 0; i < nmasks; i++) { | |
984 | mask->masks[i] = cursor; | |
985 | cursor += size; | |
986 | } | |
987 | return mask; | |
988 | } | |
989 | ||
990 | /** | |
991 | * Create a new XI2 mask of the standard size, i.e. for all devices + fake | |
992 | * devices and for the highest supported XI2 event type. | |
993 | * | |
994 | * @return The new mask or NULL on allocation error. | |
995 | */ | |
996 | XI2Mask * | |
997 | xi2mask_new(void) | |
998 | { | |
999 | return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE); | |
1000 | } | |
1001 | ||
1002 | /** | |
1003 | * Frees memory associated with mask and resets mask to NULL. | |
1004 | */ | |
1005 | void | |
1006 | xi2mask_free(XI2Mask **mask) | |
1007 | { | |
1008 | if (!(*mask)) | |
1009 | return; | |
1010 | ||
1011 | free((*mask)); | |
1012 | *mask = NULL; | |
1013 | } | |
1014 | ||
1015 | /** | |
1016 | * Test if the bit for event type is set for this device only. | |
1017 | * | |
1018 | * @return TRUE if the bit is set, FALSE otherwise | |
1019 | */ | |
1020 | Bool | |
1021 | xi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type) | |
1022 | { | |
1023 | BUG_WARN(dev->id < 0); | |
1024 | BUG_WARN(dev->id >= mask->nmasks); | |
1025 | BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); | |
1026 | ||
1027 | return BitIsOn(mask->masks[dev->id], event_type); | |
1028 | } | |
1029 | ||
1030 | /** | |
1031 | * Test if the bit for event type is set for this device, or the | |
1032 | * XIAllDevices/XIAllMasterDevices (if applicable) is set. | |
1033 | * | |
1034 | * @return TRUE if the bit is set, FALSE otherwise | |
1035 | */ | |
1036 | Bool | |
1037 | xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type) | |
1038 | { | |
1039 | int set = 0; | |
1040 | ||
1041 | if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type)) | |
1042 | set = 1; | |
1043 | else if (xi2mask_isset_for_device(mask, dev, event_type)) | |
1044 | set = 1; | |
1045 | else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type)) | |
1046 | set = 1; | |
1047 | ||
1048 | return set; | |
1049 | } | |
1050 | ||
1051 | /** | |
1052 | * Set the mask bit for this event type for this device. | |
1053 | */ | |
1054 | void | |
1055 | xi2mask_set(XI2Mask *mask, int deviceid, int event_type) | |
1056 | { | |
1057 | BUG_WARN(deviceid < 0); | |
1058 | BUG_WARN(deviceid >= mask->nmasks); | |
1059 | BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); | |
1060 | ||
1061 | SetBit(mask->masks[deviceid], event_type); | |
1062 | } | |
1063 | ||
1064 | /** | |
1065 | * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all | |
1066 | * masks are zeroed. | |
1067 | */ | |
1068 | void | |
1069 | xi2mask_zero(XI2Mask *mask, int deviceid) | |
1070 | { | |
1071 | int i; | |
1072 | ||
1073 | BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks); | |
1074 | ||
1075 | if (deviceid >= 0) | |
1076 | memset(mask->masks[deviceid], 0, mask->mask_size); | |
1077 | else | |
1078 | for (i = 0; i < mask->nmasks; i++) | |
1079 | memset(mask->masks[i], 0, mask->mask_size); | |
1080 | } | |
1081 | ||
1082 | /** | |
1083 | * Merge source into dest, i.e. dest |= source. | |
1084 | * If the masks are of different size, only the overlapping section is merged. | |
1085 | */ | |
1086 | void | |
1087 | xi2mask_merge(XI2Mask *dest, const XI2Mask *source) | |
1088 | { | |
1089 | int i, j; | |
1090 | ||
1091 | for (i = 0; i < min(dest->nmasks, source->nmasks); i++) | |
1092 | for (j = 0; j < min(dest->mask_size, source->mask_size); j++) | |
1093 | dest->masks[i][j] |= source->masks[i][j]; | |
1094 | } | |
1095 | ||
1096 | /** | |
1097 | * @return The number of masks in mask | |
1098 | */ | |
1099 | size_t | |
1100 | xi2mask_num_masks(const XI2Mask *mask) | |
1101 | { | |
1102 | return mask->nmasks; | |
1103 | } | |
1104 | ||
1105 | /** | |
1106 | * @return The size of each mask in bytes | |
1107 | */ | |
1108 | size_t | |
1109 | xi2mask_mask_size(const XI2Mask *mask) | |
1110 | { | |
1111 | return mask->mask_size; | |
1112 | } | |
1113 | ||
1114 | /** | |
1115 | * Set the mask for the given deviceid to the source mask. | |
1116 | * If the mask given is larger than the target memory, only the overlapping | |
1117 | * parts are copied. | |
1118 | */ | |
1119 | void | |
1120 | xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, | |
1121 | size_t mask_size) | |
1122 | { | |
1123 | BUG_WARN(deviceid < 0); | |
1124 | BUG_WARN(deviceid >= xi2mask->nmasks); | |
1125 | ||
1126 | memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size)); | |
1127 | } | |
1128 | ||
1129 | /** | |
1130 | * Get a reference to the XI2mask for this particular device. | |
1131 | */ | |
1132 | const unsigned char * | |
1133 | xi2mask_get_one_mask(const XI2Mask *mask, int deviceid) | |
1134 | { | |
1135 | BUG_WARN(deviceid < 0); | |
1136 | BUG_WARN(deviceid >= mask->nmasks); | |
1137 | ||
1138 | return mask->masks[deviceid]; | |
1139 | } |