Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org> | |
3 | * | |
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |
5 | * documentation for any purpose is hereby granted without fee, provided that | |
6 | * the above copyright notice appear in all copies and that both that | |
7 | * copyright notice and this permission notice appear in supporting | |
8 | * documentation, and that the name of Frederic Lepied not be used in | |
9 | * advertising or publicity pertaining to distribution of the software without | |
10 | * specific, written prior permission. Frederic Lepied makes no | |
11 | * representations about the suitability of this software for any purpose. It | |
12 | * is provided "as is" without express or implied warranty. | |
13 | * | |
14 | * FREDERIC LEPIED DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
16 | * EVENT SHALL FREDERIC LEPIED BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
20 | * PERFORMANCE OF THIS SOFTWARE. | |
21 | * | |
22 | */ | |
23 | /* | |
24 | * Copyright (c) 2000-2002 by The XFree86 Project, Inc. | |
25 | * | |
26 | * Permission is hereby granted, free of charge, to any person obtaining a | |
27 | * copy of this software and associated documentation files (the "Software"), | |
28 | * to deal in the Software without restriction, including without limitation | |
29 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
30 | * and/or sell copies of the Software, and to permit persons to whom the | |
31 | * Software is furnished to do so, subject to the following conditions: | |
32 | * | |
33 | * The above copyright notice and this permission notice shall be included in | |
34 | * all copies or substantial portions of the Software. | |
35 | * | |
36 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
37 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
38 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
39 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
40 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
41 | * OTHER DEALINGS IN THE SOFTWARE. | |
42 | * | |
43 | * Except as contained in this notice, the name of the copyright holder(s) | |
44 | * and author(s) shall not be used in advertising or otherwise to promote | |
45 | * the sale, use or other dealings in this Software without prior written | |
46 | * authorization from the copyright holder(s) and author(s). | |
47 | */ | |
48 | ||
49 | #ifdef HAVE_XORG_CONFIG_H | |
50 | #include <xorg-config.h> | |
51 | #endif | |
52 | ||
53 | #include <X11/Xfuncproto.h> | |
54 | #include <X11/Xmd.h> | |
55 | #include <X11/extensions/XI.h> | |
56 | #include <X11/extensions/XIproto.h> | |
57 | #include <X11/Xatom.h> | |
58 | #include "xf86.h" | |
59 | #include "xf86Priv.h" | |
60 | #include "xf86Config.h" | |
61 | #include "xf86Xinput.h" | |
62 | #include "xf86Optrec.h" | |
63 | #include "mipointer.h" | |
64 | #include "extinit.h" | |
65 | #include "loaderProcs.h" | |
66 | ||
67 | #include "exevents.h" /* AddInputDevice */ | |
68 | #include "exglobals.h" | |
69 | #include "eventstr.h" | |
70 | #include "inpututils.h" | |
71 | #include "optionstr.h" | |
72 | ||
73 | #include <string.h> /* InputClassMatches */ | |
74 | #ifdef HAVE_FNMATCH_H | |
75 | #include <fnmatch.h> | |
76 | #endif | |
77 | #ifdef HAVE_SYS_UTSNAME_H | |
78 | #include <sys/utsname.h> | |
79 | #endif | |
80 | ||
81 | #include <stdarg.h> | |
82 | #include <stdint.h> /* for int64_t */ | |
83 | ||
84 | #include "mi.h" | |
85 | ||
86 | #include <ptrveloc.h> /* dix pointer acceleration */ | |
87 | #include <xserver-properties.h> | |
88 | ||
89 | #ifdef XFreeXDGA | |
90 | #include "dgaproc.h" | |
91 | #endif | |
92 | ||
93 | #include "xkbsrv.h" | |
94 | ||
95 | /* Valuator verification macro */ | |
96 | #define XI_VERIFY_VALUATORS(num_valuators) \ | |
97 | if (num_valuators > MAX_VALUATORS) { \ | |
98 | xf86Msg(X_ERROR, "%s: num_valuator %d is greater than" \ | |
99 | " MAX_VALUATORS\n", __FUNCTION__, num_valuators); \ | |
100 | return; \ | |
101 | } | |
102 | ||
103 | static int | |
104 | xf86InputDevicePostInit(DeviceIntPtr dev); | |
105 | ||
106 | /** | |
107 | * Eval config and modify DeviceVelocityRec accordingly | |
108 | */ | |
109 | static void | |
110 | ProcessVelocityConfiguration(DeviceIntPtr pDev, char *devname, pointer list, | |
111 | DeviceVelocityPtr s) | |
112 | { | |
113 | int tempi; | |
114 | float tempf; | |
115 | Atom float_prop = XIGetKnownProperty(XATOM_FLOAT); | |
116 | Atom prop; | |
117 | ||
118 | if (!s) | |
119 | return; | |
120 | ||
121 | /* common settings (available via device properties) */ | |
122 | tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); | |
123 | if (tempf > 1.0) { | |
124 | xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", | |
125 | devname, tempf); | |
126 | prop = XIGetKnownProperty(ACCEL_PROP_CONSTANT_DECELERATION); | |
127 | XIChangeDeviceProperty(pDev, prop, float_prop, 32, | |
128 | PropModeReplace, 1, &tempf, FALSE); | |
129 | } | |
130 | ||
131 | tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); | |
132 | if (tempf > 1.0) { | |
133 | xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", | |
134 | devname, tempf); | |
135 | prop = XIGetKnownProperty(ACCEL_PROP_ADAPTIVE_DECELERATION); | |
136 | XIChangeDeviceProperty(pDev, prop, float_prop, 32, | |
137 | PropModeReplace, 1, &tempf, FALSE); | |
138 | } | |
139 | ||
140 | /* select profile by number */ | |
141 | tempi = xf86SetIntOption(list, "AccelerationProfile", | |
142 | s->statistics.profile_number); | |
143 | ||
144 | prop = XIGetKnownProperty(ACCEL_PROP_PROFILE_NUMBER); | |
145 | if (XIChangeDeviceProperty(pDev, prop, XA_INTEGER, 32, | |
146 | PropModeReplace, 1, &tempi, FALSE) == Success) { | |
147 | xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i\n", devname, | |
148 | tempi); | |
149 | } | |
150 | else { | |
151 | xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n", | |
152 | devname, tempi); | |
153 | } | |
154 | ||
155 | /* set scaling */ | |
156 | tempf = xf86SetRealOption(list, "ExpectedRate", 0); | |
157 | prop = XIGetKnownProperty(ACCEL_PROP_VELOCITY_SCALING); | |
158 | if (tempf > 0) { | |
159 | tempf = 1000.0 / tempf; | |
160 | XIChangeDeviceProperty(pDev, prop, float_prop, 32, | |
161 | PropModeReplace, 1, &tempf, FALSE); | |
162 | } | |
163 | else { | |
164 | tempf = xf86SetRealOption(list, "VelocityScale", s->corr_mul); | |
165 | XIChangeDeviceProperty(pDev, prop, float_prop, 32, | |
166 | PropModeReplace, 1, &tempf, FALSE); | |
167 | } | |
168 | ||
169 | tempi = xf86SetIntOption(list, "VelocityTrackerCount", -1); | |
170 | if (tempi > 1) | |
171 | InitTrackers(s, tempi); | |
172 | ||
173 | s->initial_range = xf86SetIntOption(list, "VelocityInitialRange", | |
174 | s->initial_range); | |
175 | ||
176 | s->max_diff = xf86SetRealOption(list, "VelocityAbsDiff", s->max_diff); | |
177 | ||
178 | tempf = xf86SetRealOption(list, "VelocityRelDiff", -1); | |
179 | if (tempf >= 0) { | |
180 | xf86Msg(X_CONFIG, "%s: (accel) max rel. velocity difference: %.1f%%\n", | |
181 | devname, tempf * 100.0); | |
182 | s->max_rel_diff = tempf; | |
183 | } | |
184 | ||
185 | /* Configure softening. If const deceleration is used, this is expected | |
186 | * to provide better subpixel information so we enable | |
187 | * softening by default only if ConstantDeceleration is not used | |
188 | */ | |
189 | s->use_softening = xf86SetBoolOption(list, "Softening", | |
190 | s->const_acceleration == 1.0); | |
191 | ||
192 | s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging", | |
193 | s->average_accel); | |
194 | ||
195 | s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time); | |
196 | } | |
197 | ||
198 | static void | |
199 | ApplyAccelerationSettings(DeviceIntPtr dev) | |
200 | { | |
201 | int scheme, i; | |
202 | DeviceVelocityPtr pVel; | |
203 | InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; | |
204 | char *schemeStr; | |
205 | ||
206 | if (dev->valuator && dev->ptrfeed) { | |
207 | schemeStr = xf86SetStrOption(pInfo->options, "AccelerationScheme", ""); | |
208 | ||
209 | scheme = dev->valuator->accelScheme.number; | |
210 | ||
211 | if (!xf86NameCmp(schemeStr, "predictable")) | |
212 | scheme = PtrAccelPredictable; | |
213 | ||
214 | if (!xf86NameCmp(schemeStr, "lightweight")) | |
215 | scheme = PtrAccelLightweight; | |
216 | ||
217 | if (!xf86NameCmp(schemeStr, "none")) | |
218 | scheme = PtrAccelNoOp; | |
219 | ||
220 | /* reinit scheme if needed */ | |
221 | if (dev->valuator->accelScheme.number != scheme) { | |
222 | if (dev->valuator->accelScheme.AccelCleanupProc) { | |
223 | dev->valuator->accelScheme.AccelCleanupProc(dev); | |
224 | } | |
225 | ||
226 | if (InitPointerAccelerationScheme(dev, scheme)) { | |
227 | xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n", | |
228 | pInfo->name, schemeStr, scheme); | |
229 | } | |
230 | else { | |
231 | xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n", | |
232 | pInfo->name, schemeStr); | |
233 | scheme = dev->valuator->accelScheme.number; | |
234 | } | |
235 | } | |
236 | else { | |
237 | xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n", | |
238 | pInfo->name, scheme); | |
239 | } | |
240 | ||
241 | free(schemeStr); | |
242 | ||
243 | /* process special configuration */ | |
244 | switch (scheme) { | |
245 | case PtrAccelPredictable: | |
246 | pVel = GetDevicePredictableAccelData(dev); | |
247 | ProcessVelocityConfiguration(dev, pInfo->name, pInfo->options, | |
248 | pVel); | |
249 | break; | |
250 | } | |
251 | ||
252 | i = xf86SetIntOption(pInfo->options, "AccelerationNumerator", | |
253 | dev->ptrfeed->ctrl.num); | |
254 | if (i >= 0) | |
255 | dev->ptrfeed->ctrl.num = i; | |
256 | ||
257 | i = xf86SetIntOption(pInfo->options, "AccelerationDenominator", | |
258 | dev->ptrfeed->ctrl.den); | |
259 | if (i > 0) | |
260 | dev->ptrfeed->ctrl.den = i; | |
261 | ||
262 | i = xf86SetIntOption(pInfo->options, "AccelerationThreshold", | |
263 | dev->ptrfeed->ctrl.threshold); | |
264 | if (i >= 0) | |
265 | dev->ptrfeed->ctrl.threshold = i; | |
266 | ||
267 | xf86Msg(X_CONFIG, "%s: (accel) acceleration factor: %.3f\n", | |
268 | pInfo->name, ((float) dev->ptrfeed->ctrl.num) / | |
269 | ((float) dev->ptrfeed->ctrl.den)); | |
270 | xf86Msg(X_CONFIG, "%s: (accel) acceleration threshold: %i\n", | |
271 | pInfo->name, dev->ptrfeed->ctrl.threshold); | |
272 | } | |
273 | } | |
274 | ||
275 | static void | |
276 | ApplyTransformationMatrix(DeviceIntPtr dev) | |
277 | { | |
278 | InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; | |
279 | char *str; | |
280 | int rc; | |
281 | float matrix[9] = { 0 }; | |
282 | ||
283 | if (!dev->valuator) | |
284 | return; | |
285 | ||
286 | str = xf86SetStrOption(pInfo->options, "TransformationMatrix", NULL); | |
287 | if (!str) | |
288 | return; | |
289 | ||
290 | rc = sscanf(str, "%f %f %f %f %f %f %f %f %f", &matrix[0], &matrix[1], | |
291 | &matrix[2], &matrix[3], &matrix[4], &matrix[5], &matrix[6], | |
292 | &matrix[7], &matrix[8]); | |
293 | if (rc != 9) { | |
294 | xf86Msg(X_ERROR, | |
295 | "%s: invalid format for transformation matrix. Ignoring configuration.\n", | |
296 | pInfo->name); | |
297 | return; | |
298 | } | |
299 | ||
300 | XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM), | |
301 | XIGetKnownProperty(XATOM_FLOAT), 32, | |
302 | PropModeReplace, 9, matrix, FALSE); | |
303 | } | |
304 | ||
305 | /*********************************************************************** | |
306 | * | |
307 | * xf86ProcessCommonOptions -- | |
308 | * | |
309 | * Process global options. | |
310 | * | |
311 | *********************************************************************** | |
312 | */ | |
313 | void | |
314 | xf86ProcessCommonOptions(InputInfoPtr pInfo, XF86OptionPtr list) | |
315 | { | |
316 | if (xf86SetBoolOption(list, "Floating", 0) || | |
317 | !xf86SetBoolOption(list, "AlwaysCore", 1) || | |
318 | !xf86SetBoolOption(list, "SendCoreEvents", 1) || | |
319 | !xf86SetBoolOption(list, "CorePointer", 1) || | |
320 | !xf86SetBoolOption(list, "CoreKeyboard", 1)) { | |
321 | xf86Msg(X_CONFIG, "%s: doesn't report core events\n", pInfo->name); | |
322 | } | |
323 | else { | |
324 | pInfo->flags |= XI86_ALWAYS_CORE; | |
325 | xf86Msg(X_CONFIG, "%s: always reports core events\n", pInfo->name); | |
326 | } | |
327 | } | |
328 | ||
329 | /*********************************************************************** | |
330 | * | |
331 | * xf86ActivateDevice -- | |
332 | * | |
333 | * Initialize an input device. | |
334 | * | |
335 | * Returns TRUE on success, or FALSE otherwise. | |
336 | *********************************************************************** | |
337 | */ | |
338 | static DeviceIntPtr | |
339 | xf86ActivateDevice(InputInfoPtr pInfo) | |
340 | { | |
341 | DeviceIntPtr dev; | |
342 | Atom atom; | |
343 | ||
344 | dev = AddInputDevice(serverClient, pInfo->device_control, TRUE); | |
345 | ||
346 | if (dev == NULL) { | |
347 | xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n", pInfo->name); | |
348 | pInfo->dev = NULL; | |
349 | return NULL; | |
350 | } | |
351 | ||
352 | atom = MakeAtom(pInfo->type_name, strlen(pInfo->type_name), TRUE); | |
353 | AssignTypeAndName(dev, atom, pInfo->name); | |
354 | dev->public.devicePrivate = pInfo; | |
355 | pInfo->dev = dev; | |
356 | ||
357 | dev->coreEvents = pInfo->flags & XI86_ALWAYS_CORE; | |
358 | dev->type = SLAVE; | |
359 | dev->spriteInfo->spriteOwner = FALSE; | |
360 | ||
361 | dev->config_info = xf86SetStrOption(pInfo->options, "config_info", NULL); | |
362 | ||
363 | if (serverGeneration == 1) | |
364 | xf86Msg(X_INFO, | |
365 | "XINPUT: Adding extended input device \"%s\" (type: %s, id %d)\n", | |
366 | pInfo->name, pInfo->type_name, dev->id); | |
367 | ||
368 | return dev; | |
369 | } | |
370 | ||
371 | /**************************************************************************** | |
372 | * | |
373 | * Caller: ProcXSetDeviceMode | |
374 | * | |
375 | * Change the mode of an extension device. | |
376 | * This function is used to change the mode of a device from reporting | |
377 | * relative motion to reporting absolute positional information, and | |
378 | * vice versa. | |
379 | * The default implementation below is that no such devices are supported. | |
380 | * | |
381 | *********************************************************************** | |
382 | */ | |
383 | ||
384 | int | |
385 | SetDeviceMode(ClientPtr client, DeviceIntPtr dev, int mode) | |
386 | { | |
387 | InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; | |
388 | ||
389 | if (pInfo->switch_mode) { | |
390 | return (*pInfo->switch_mode) (client, dev, mode); | |
391 | } | |
392 | else | |
393 | return BadMatch; | |
394 | } | |
395 | ||
396 | /*********************************************************************** | |
397 | * | |
398 | * Caller: ProcXSetDeviceValuators | |
399 | * | |
400 | * Set the value of valuators on an extension input device. | |
401 | * This function is used to set the initial value of valuators on | |
402 | * those input devices that are capable of reporting either relative | |
403 | * motion or an absolute position, and allow an initial position to be set. | |
404 | * The default implementation below is that no such devices are supported. | |
405 | * | |
406 | *********************************************************************** | |
407 | */ | |
408 | ||
409 | int | |
410 | SetDeviceValuators(ClientPtr client, DeviceIntPtr dev, int *valuators, | |
411 | int first_valuator, int num_valuators) | |
412 | { | |
413 | InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; | |
414 | ||
415 | if (pInfo->set_device_valuators) | |
416 | return (*pInfo->set_device_valuators) (pInfo, valuators, first_valuator, | |
417 | num_valuators); | |
418 | ||
419 | return BadMatch; | |
420 | } | |
421 | ||
422 | /*********************************************************************** | |
423 | * | |
424 | * Caller: ProcXChangeDeviceControl | |
425 | * | |
426 | * Change the specified device controls on an extension input device. | |
427 | * | |
428 | *********************************************************************** | |
429 | */ | |
430 | ||
431 | int | |
432 | ChangeDeviceControl(ClientPtr client, DeviceIntPtr dev, xDeviceCtl * control) | |
433 | { | |
434 | InputInfoPtr pInfo = (InputInfoPtr) dev->public.devicePrivate; | |
435 | ||
436 | if (!pInfo->control_proc) { | |
437 | switch (control->control) { | |
438 | case DEVICE_CORE: | |
439 | case DEVICE_ABS_CALIB: | |
440 | case DEVICE_ABS_AREA: | |
441 | return BadMatch; | |
442 | case DEVICE_RESOLUTION: | |
443 | case DEVICE_ENABLE: | |
444 | return Success; | |
445 | default: | |
446 | return BadMatch; | |
447 | } | |
448 | } | |
449 | else { | |
450 | return (*pInfo->control_proc) (pInfo, control); | |
451 | } | |
452 | } | |
453 | ||
454 | /* | |
455 | * Get the operating system name from uname and store it statically to avoid | |
456 | * repeating the system call each time MatchOS is checked. | |
457 | */ | |
458 | static const char * | |
459 | HostOS(void) | |
460 | { | |
461 | #ifdef HAVE_SYS_UTSNAME_H | |
462 | struct utsname name; | |
463 | static char host_os[sizeof(name.sysname)] = ""; | |
464 | ||
465 | if (*host_os == '\0') { | |
466 | if (uname(&name) >= 0) | |
467 | strlcpy(host_os, name.sysname, sizeof(host_os)); | |
468 | else { | |
469 | strlcpy(host_os, "unknown", sizeof(host_os)); | |
470 | } | |
471 | } | |
472 | return host_os; | |
473 | #else | |
474 | return ""; | |
475 | #endif | |
476 | } | |
477 | ||
478 | static int | |
479 | match_substring(const char *attr, const char *pattern) | |
480 | { | |
481 | return (strstr(attr, pattern)) ? 0 : -1; | |
482 | } | |
483 | ||
484 | #ifdef HAVE_FNMATCH_H | |
485 | static int | |
486 | match_pattern(const char *attr, const char *pattern) | |
487 | { | |
488 | return fnmatch(pattern, attr, 0); | |
489 | } | |
490 | #else | |
491 | #define match_pattern match_substring | |
492 | #endif | |
493 | ||
494 | #ifdef HAVE_FNMATCH_H | |
495 | static int | |
496 | match_path_pattern(const char *attr, const char *pattern) | |
497 | { | |
498 | return fnmatch(pattern, attr, FNM_PATHNAME); | |
499 | } | |
500 | #else | |
501 | #define match_path_pattern match_substring | |
502 | #endif | |
503 | ||
504 | /* | |
505 | * If no Layout section is found, xf86ServerLayout.id becomes "(implicit)" | |
506 | * It is convenient that "" in patterns means "no explicit layout" | |
507 | */ | |
508 | static int | |
509 | match_string_implicit(const char *attr, const char *pattern) | |
510 | { | |
511 | if (strlen(pattern)) { | |
512 | return strcmp(attr, pattern); | |
513 | } | |
514 | else { | |
515 | return strcmp(attr, "(implicit)"); | |
516 | } | |
517 | } | |
518 | ||
519 | /* | |
520 | * Match an attribute against a list of NULL terminated arrays of patterns. | |
521 | * If a pattern in each list entry is matched, return TRUE. | |
522 | */ | |
523 | static Bool | |
524 | MatchAttrToken(const char *attr, struct xorg_list *patterns, | |
525 | int (*compare) (const char *attr, const char *pattern)) | |
526 | { | |
527 | const xf86MatchGroup *group; | |
528 | ||
529 | /* If there are no patterns, accept the match */ | |
530 | if (xorg_list_is_empty(patterns)) | |
531 | return TRUE; | |
532 | ||
533 | /* If there are patterns but no attribute, reject the match */ | |
534 | if (!attr) | |
535 | return FALSE; | |
536 | ||
537 | /* | |
538 | * Otherwise, iterate the list of patterns ensuring each entry has a | |
539 | * match. Each list entry is a separate Match line of the same type. | |
540 | */ | |
541 | xorg_list_for_each_entry(group, patterns, entry) { | |
542 | char *const *cur; | |
543 | Bool match = FALSE; | |
544 | ||
545 | for (cur = group->values; *cur; cur++) | |
546 | if ((*compare) (attr, *cur) == 0) { | |
547 | match = TRUE; | |
548 | break; | |
549 | } | |
550 | if (!match) | |
551 | return FALSE; | |
552 | } | |
553 | ||
554 | /* All the entries in the list matched the attribute */ | |
555 | return TRUE; | |
556 | } | |
557 | ||
558 | /* | |
559 | * Classes without any Match statements match all devices. Otherwise, all | |
560 | * statements must match. | |
561 | */ | |
562 | static Bool | |
563 | InputClassMatches(const XF86ConfInputClassPtr iclass, const InputInfoPtr idev, | |
564 | const InputAttributes * attrs) | |
565 | { | |
566 | /* MatchProduct substring */ | |
567 | if (!MatchAttrToken | |
568 | (attrs->product, &iclass->match_product, match_substring)) | |
569 | return FALSE; | |
570 | ||
571 | /* MatchVendor substring */ | |
572 | if (!MatchAttrToken(attrs->vendor, &iclass->match_vendor, match_substring)) | |
573 | return FALSE; | |
574 | ||
575 | /* MatchDevicePath pattern */ | |
576 | if (!MatchAttrToken | |
577 | (attrs->device, &iclass->match_device, match_path_pattern)) | |
578 | return FALSE; | |
579 | ||
580 | /* MatchOS case-insensitive string */ | |
581 | if (!MatchAttrToken(HostOS(), &iclass->match_os, strcasecmp)) | |
582 | return FALSE; | |
583 | ||
584 | /* MatchPnPID pattern */ | |
585 | if (!MatchAttrToken(attrs->pnp_id, &iclass->match_pnpid, match_pattern)) | |
586 | return FALSE; | |
587 | ||
588 | /* MatchUSBID pattern */ | |
589 | if (!MatchAttrToken(attrs->usb_id, &iclass->match_usbid, match_pattern)) | |
590 | return FALSE; | |
591 | ||
592 | /* MatchDriver string */ | |
593 | if (!MatchAttrToken(idev->driver, &iclass->match_driver, strcmp)) | |
594 | return FALSE; | |
595 | ||
596 | /* | |
597 | * MatchTag string | |
598 | * See if any of the device's tags match any of the MatchTag tokens. | |
599 | */ | |
600 | if (!xorg_list_is_empty(&iclass->match_tag)) { | |
601 | char *const *tag; | |
602 | Bool match; | |
603 | ||
604 | if (!attrs->tags) | |
605 | return FALSE; | |
606 | for (tag = attrs->tags, match = FALSE; *tag; tag++) { | |
607 | if (MatchAttrToken(*tag, &iclass->match_tag, strcmp)) { | |
608 | match = TRUE; | |
609 | break; | |
610 | } | |
611 | } | |
612 | if (!match) | |
613 | return FALSE; | |
614 | } | |
615 | ||
616 | /* MatchLayout string */ | |
617 | if (!xorg_list_is_empty(&iclass->match_layout)) { | |
618 | if (!MatchAttrToken(xf86ConfigLayout.id, | |
619 | &iclass->match_layout, match_string_implicit)) | |
620 | return FALSE; | |
621 | } | |
622 | ||
623 | /* MatchIs* booleans */ | |
624 | if (iclass->is_keyboard.set && | |
625 | iclass->is_keyboard.val != ! !(attrs->flags & ATTR_KEYBOARD)) | |
626 | return FALSE; | |
627 | if (iclass->is_pointer.set && | |
628 | iclass->is_pointer.val != ! !(attrs->flags & ATTR_POINTER)) | |
629 | return FALSE; | |
630 | if (iclass->is_joystick.set && | |
631 | iclass->is_joystick.val != ! !(attrs->flags & ATTR_JOYSTICK)) | |
632 | return FALSE; | |
633 | if (iclass->is_tablet.set && | |
634 | iclass->is_tablet.val != ! !(attrs->flags & ATTR_TABLET)) | |
635 | return FALSE; | |
636 | if (iclass->is_touchpad.set && | |
637 | iclass->is_touchpad.val != ! !(attrs->flags & ATTR_TOUCHPAD)) | |
638 | return FALSE; | |
639 | if (iclass->is_touchscreen.set && | |
640 | iclass->is_touchscreen.val != ! !(attrs->flags & ATTR_TOUCHSCREEN)) | |
641 | return FALSE; | |
642 | ||
643 | return TRUE; | |
644 | } | |
645 | ||
646 | /* | |
647 | * Merge in any InputClass configurations. Options in each InputClass | |
648 | * section have more priority than the original device configuration as | |
649 | * well as any previous InputClass sections. | |
650 | */ | |
651 | static int | |
652 | MergeInputClasses(const InputInfoPtr idev, const InputAttributes * attrs) | |
653 | { | |
654 | XF86ConfInputClassPtr cl; | |
655 | XF86OptionPtr classopts; | |
656 | ||
657 | for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { | |
658 | if (!InputClassMatches(cl, idev, attrs)) | |
659 | continue; | |
660 | ||
661 | /* Collect class options and driver settings */ | |
662 | classopts = xf86optionListDup(cl->option_lst); | |
663 | if (cl->driver) { | |
664 | free(idev->driver); | |
665 | idev->driver = xstrdup(cl->driver); | |
666 | if (!idev->driver) { | |
667 | xf86Msg(X_ERROR, "Failed to allocate memory while merging " | |
668 | "InputClass configuration"); | |
669 | return BadAlloc; | |
670 | } | |
671 | classopts = xf86ReplaceStrOption(classopts, "driver", idev->driver); | |
672 | } | |
673 | ||
674 | /* Apply options to device with InputClass settings preferred. */ | |
675 | xf86Msg(X_CONFIG, "%s: Applying InputClass \"%s\"\n", | |
676 | idev->name, cl->identifier); | |
677 | idev->options = xf86optionListMerge(idev->options, classopts); | |
678 | } | |
679 | ||
680 | return Success; | |
681 | } | |
682 | ||
683 | /* | |
684 | * Iterate the list of classes and look for Option "Ignore". Return the | |
685 | * value of the last matching class and holler when returning TRUE. | |
686 | */ | |
687 | static Bool | |
688 | IgnoreInputClass(const InputInfoPtr idev, const InputAttributes * attrs) | |
689 | { | |
690 | XF86ConfInputClassPtr cl; | |
691 | Bool ignore = FALSE; | |
692 | const char *ignore_class; | |
693 | ||
694 | for (cl = xf86configptr->conf_inputclass_lst; cl; cl = cl->list.next) { | |
695 | if (!InputClassMatches(cl, idev, attrs)) | |
696 | continue; | |
697 | if (xf86findOption(cl->option_lst, "Ignore")) { | |
698 | ignore = xf86CheckBoolOption(cl->option_lst, "Ignore", FALSE); | |
699 | ignore_class = cl->identifier; | |
700 | } | |
701 | } | |
702 | ||
703 | if (ignore) | |
704 | xf86Msg(X_CONFIG, "%s: Ignoring device from InputClass \"%s\"\n", | |
705 | idev->name, ignore_class); | |
706 | return ignore; | |
707 | } | |
708 | ||
709 | InputInfoPtr | |
710 | xf86AllocateInput(void) | |
711 | { | |
712 | InputInfoPtr pInfo; | |
713 | ||
714 | pInfo = calloc(sizeof(*pInfo), 1); | |
715 | if (!pInfo) | |
716 | return NULL; | |
717 | ||
718 | pInfo->fd = -1; | |
719 | pInfo->type_name = "UNKNOWN"; | |
720 | ||
721 | return pInfo; | |
722 | } | |
723 | ||
724 | /* Append InputInfoRec to the tail of xf86InputDevs. */ | |
725 | static void | |
726 | xf86AddInput(InputDriverPtr drv, InputInfoPtr pInfo) | |
727 | { | |
728 | InputInfoPtr *prev = NULL; | |
729 | ||
730 | pInfo->drv = drv; | |
731 | pInfo->module = DuplicateModule(drv->module, NULL); | |
732 | ||
733 | for (prev = &xf86InputDevs; *prev; prev = &(*prev)->next); | |
734 | ||
735 | *prev = pInfo; | |
736 | pInfo->next = NULL; | |
737 | ||
738 | xf86CollectInputOptions(pInfo, (const char **) drv->default_options); | |
739 | xf86OptionListReport(pInfo->options); | |
740 | xf86ProcessCommonOptions(pInfo, pInfo->options); | |
741 | } | |
742 | ||
743 | /* | |
744 | * Remove an entry from xf86InputDevs and free all the device's information. | |
745 | */ | |
746 | void | |
747 | xf86DeleteInput(InputInfoPtr pInp, int flags) | |
748 | { | |
749 | /* First check if the inputdev is valid. */ | |
750 | if (pInp == NULL) | |
751 | return; | |
752 | ||
753 | if (pInp->module) | |
754 | UnloadModule(pInp->module); | |
755 | ||
756 | /* This should *really* be handled in drv->UnInit(dev) call instead, but | |
757 | * if the driver forgets about it make sure we free it or at least crash | |
758 | * with flying colors */ | |
759 | free(pInp->private); | |
760 | ||
761 | FreeInputAttributes(pInp->attrs); | |
762 | ||
763 | /* Remove the entry from the list. */ | |
764 | if (pInp == xf86InputDevs) | |
765 | xf86InputDevs = pInp->next; | |
766 | else { | |
767 | InputInfoPtr p = xf86InputDevs; | |
768 | ||
769 | while (p && p->next != pInp) | |
770 | p = p->next; | |
771 | if (p) | |
772 | p->next = pInp->next; | |
773 | /* Else the entry wasn't in the xf86InputDevs list (ignore this). */ | |
774 | } | |
775 | ||
776 | free(pInp->driver); | |
777 | free(pInp->name); | |
778 | xf86optionListFree(pInp->options); | |
779 | free(pInp); | |
780 | } | |
781 | ||
782 | /* | |
783 | * Apply backend-specific initialization. Invoked after ActivateDevice(), | |
784 | * i.e. after the driver successfully completed DEVICE_INIT and the device | |
785 | * is advertised. | |
786 | * @param dev the device | |
787 | * @return Success or an error code | |
788 | */ | |
789 | static int | |
790 | xf86InputDevicePostInit(DeviceIntPtr dev) | |
791 | { | |
792 | ApplyAccelerationSettings(dev); | |
793 | ApplyTransformationMatrix(dev); | |
794 | return Success; | |
795 | } | |
796 | ||
797 | /** | |
798 | * Create a new input device, activate and enable it. | |
799 | * | |
800 | * Possible return codes: | |
801 | * BadName .. a bad driver name was supplied. | |
802 | * BadImplementation ... The driver does not have a PreInit function. This | |
803 | * is a driver bug. | |
804 | * BadMatch .. device initialization failed. | |
805 | * BadAlloc .. too many input devices | |
806 | * | |
807 | * @param idev The device, already set up with identifier, driver, and the | |
808 | * options. | |
809 | * @param pdev Pointer to the new device, if Success was reported. | |
810 | * @param enable Enable the device after activating it. | |
811 | * | |
812 | * @return Success or an error code | |
813 | */ | |
814 | _X_INTERNAL int | |
815 | xf86NewInputDevice(InputInfoPtr pInfo, DeviceIntPtr *pdev, BOOL enable) | |
816 | { | |
817 | InputDriverPtr drv = NULL; | |
818 | DeviceIntPtr dev = NULL; | |
819 | int rval; | |
820 | ||
821 | /* Memory leak for every attached device if we don't | |
822 | * test if the module is already loaded first */ | |
823 | drv = xf86LookupInputDriver(pInfo->driver); | |
824 | if (!drv) | |
825 | if (xf86LoadOneModule(pInfo->driver, NULL)) | |
826 | drv = xf86LookupInputDriver(pInfo->driver); | |
827 | if (!drv) { | |
828 | xf86Msg(X_ERROR, "No input driver matching `%s'\n", pInfo->driver); | |
829 | rval = BadName; | |
830 | goto unwind; | |
831 | } | |
832 | ||
833 | xf86Msg(X_INFO, "Using input driver '%s' for '%s'\n", drv->driverName, | |
834 | pInfo->name); | |
835 | ||
836 | if (!drv->PreInit) { | |
837 | xf86Msg(X_ERROR, | |
838 | "Input driver `%s' has no PreInit function (ignoring)\n", | |
839 | drv->driverName); | |
840 | rval = BadImplementation; | |
841 | goto unwind; | |
842 | } | |
843 | ||
844 | xf86AddInput(drv, pInfo); | |
845 | ||
846 | rval = drv->PreInit(drv, pInfo, 0); | |
847 | ||
848 | if (rval != Success) { | |
849 | xf86Msg(X_ERROR, "PreInit returned %d for \"%s\"\n", rval, pInfo->name); | |
850 | goto unwind; | |
851 | } | |
852 | ||
853 | if (!(dev = xf86ActivateDevice(pInfo))) { | |
854 | rval = BadAlloc; | |
855 | goto unwind; | |
856 | } | |
857 | ||
858 | rval = ActivateDevice(dev, TRUE); | |
859 | if (rval != Success) { | |
860 | xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); | |
861 | RemoveDevice(dev, TRUE); | |
862 | goto unwind; | |
863 | } | |
864 | ||
865 | rval = xf86InputDevicePostInit(dev); | |
866 | if (rval != Success) { | |
867 | xf86Msg(X_ERROR, "Couldn't post-init device \"%s\"\n", pInfo->name); | |
868 | RemoveDevice(dev, TRUE); | |
869 | goto unwind; | |
870 | } | |
871 | ||
872 | /* Enable it if it's properly initialised and we're currently in the VT */ | |
873 | if (enable && dev->inited && dev->startup && xf86VTOwner()) { | |
874 | OsBlockSignals(); | |
875 | EnableDevice(dev, TRUE); | |
876 | if (!dev->enabled) { | |
877 | OsReleaseSignals(); | |
878 | xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", pInfo->name); | |
879 | RemoveDevice(dev, TRUE); | |
880 | rval = BadMatch; | |
881 | goto unwind; | |
882 | } | |
883 | /* send enter/leave event, update sprite window */ | |
884 | CheckMotion(NULL, dev); | |
885 | OsReleaseSignals(); | |
886 | } | |
887 | ||
888 | *pdev = dev; | |
889 | return Success; | |
890 | ||
891 | unwind: | |
892 | if (pInfo) { | |
893 | if (drv && drv->UnInit) | |
894 | drv->UnInit(drv, pInfo, 0); | |
895 | else | |
896 | xf86DeleteInput(pInfo, 0); | |
897 | } | |
898 | return rval; | |
899 | } | |
900 | ||
901 | int | |
902 | NewInputDeviceRequest(InputOption *options, InputAttributes * attrs, | |
903 | DeviceIntPtr *pdev) | |
904 | { | |
905 | InputInfoPtr pInfo = NULL; | |
906 | InputOption *option = NULL; | |
907 | int rval = Success; | |
908 | int is_auto = 0; | |
909 | ||
910 | pInfo = xf86AllocateInput(); | |
911 | if (!pInfo) | |
912 | return BadAlloc; | |
913 | ||
914 | nt_list_for_each_entry(option, options, list.next) { | |
915 | const char *key = input_option_get_key(option); | |
916 | const char *value = input_option_get_value(option); | |
917 | ||
918 | if (strcasecmp(key, "driver") == 0) { | |
919 | if (pInfo->driver) { | |
920 | rval = BadRequest; | |
921 | goto unwind; | |
922 | } | |
923 | pInfo->driver = xstrdup(value); | |
924 | if (!pInfo->driver) { | |
925 | rval = BadAlloc; | |
926 | goto unwind; | |
927 | } | |
928 | } | |
929 | ||
930 | if (strcasecmp(key, "name") == 0 || strcasecmp(key, "identifier") == 0) { | |
931 | if (pInfo->name) { | |
932 | rval = BadRequest; | |
933 | goto unwind; | |
934 | } | |
935 | pInfo->name = xstrdup(value); | |
936 | if (!pInfo->name) { | |
937 | rval = BadAlloc; | |
938 | goto unwind; | |
939 | } | |
940 | } | |
941 | ||
942 | if (strcmp(key, "_source") == 0 && | |
943 | (strcmp(value, "server/hal") == 0 || | |
944 | strcmp(value, "server/udev") == 0 || | |
945 | strcmp(value, "server/wscons") == 0)) { | |
946 | is_auto = 1; | |
947 | if (!xf86Info.autoAddDevices) { | |
948 | rval = BadMatch; | |
949 | goto unwind; | |
950 | } | |
951 | } | |
952 | } | |
953 | ||
954 | nt_list_for_each_entry(option, options, list.next) { | |
955 | /* Copy option key/value strings from the provided list */ | |
956 | pInfo->options = xf86AddNewOption(pInfo->options, | |
957 | input_option_get_key(option), | |
958 | input_option_get_value(option)); | |
959 | } | |
960 | ||
961 | /* Apply InputClass settings */ | |
962 | if (attrs) { | |
963 | if (IgnoreInputClass(pInfo, attrs)) { | |
964 | rval = BadIDChoice; | |
965 | goto unwind; | |
966 | } | |
967 | ||
968 | rval = MergeInputClasses(pInfo, attrs); | |
969 | if (rval != Success) | |
970 | goto unwind; | |
971 | ||
972 | pInfo->attrs = DuplicateInputAttributes(attrs); | |
973 | } | |
974 | ||
975 | if (!pInfo->name) { | |
976 | xf86Msg(X_INFO, "No identifier specified, ignoring this device.\n"); | |
977 | rval = BadRequest; | |
978 | goto unwind; | |
979 | } | |
980 | ||
981 | if (!pInfo->driver) { | |
982 | xf86Msg(X_INFO, "No input driver specified, ignoring this device.\n"); | |
983 | xf86Msg(X_INFO, | |
984 | "This device may have been added with another device file.\n"); | |
985 | rval = BadRequest; | |
986 | goto unwind; | |
987 | } | |
988 | ||
989 | rval = xf86NewInputDevice(pInfo, pdev, | |
990 | (!is_auto || | |
991 | (is_auto && xf86Info.autoEnableDevices))); | |
992 | ||
993 | return rval; | |
994 | ||
995 | unwind: | |
996 | if (is_auto && !xf86Info.autoAddDevices) | |
997 | xf86Msg(X_INFO, "AutoAddDevices is off - not adding device.\n"); | |
998 | xf86DeleteInput(pInfo, 0); | |
999 | return rval; | |
1000 | } | |
1001 | ||
1002 | void | |
1003 | DeleteInputDeviceRequest(DeviceIntPtr pDev) | |
1004 | { | |
1005 | InputInfoPtr pInfo = (InputInfoPtr) pDev->public.devicePrivate; | |
1006 | InputDriverPtr drv = NULL; | |
1007 | Bool isMaster = IsMaster(pDev); | |
1008 | ||
1009 | if (pInfo) /* need to get these before RemoveDevice */ | |
1010 | drv = pInfo->drv; | |
1011 | ||
1012 | OsBlockSignals(); | |
1013 | RemoveDevice(pDev, TRUE); | |
1014 | ||
1015 | if (!isMaster && pInfo != NULL) { | |
1016 | if (drv->UnInit) | |
1017 | drv->UnInit(drv, pInfo, 0); | |
1018 | else | |
1019 | xf86DeleteInput(pInfo, 0); | |
1020 | } | |
1021 | OsReleaseSignals(); | |
1022 | } | |
1023 | ||
1024 | /* | |
1025 | * convenient functions to post events | |
1026 | */ | |
1027 | ||
1028 | void | |
1029 | xf86PostMotionEvent(DeviceIntPtr device, | |
1030 | int is_absolute, int first_valuator, int num_valuators, ...) | |
1031 | { | |
1032 | va_list var; | |
1033 | int i = 0; | |
1034 | ValuatorMask mask; | |
1035 | ||
1036 | XI_VERIFY_VALUATORS(num_valuators); | |
1037 | ||
1038 | valuator_mask_zero(&mask); | |
1039 | va_start(var, num_valuators); | |
1040 | for (i = 0; i < num_valuators; i++) | |
1041 | valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); | |
1042 | ||
1043 | va_end(var); | |
1044 | ||
1045 | xf86PostMotionEventM(device, is_absolute, &mask); | |
1046 | } | |
1047 | ||
1048 | void | |
1049 | xf86PostMotionEventP(DeviceIntPtr device, | |
1050 | int is_absolute, | |
1051 | int first_valuator, | |
1052 | int num_valuators, const int *valuators) | |
1053 | { | |
1054 | ValuatorMask mask; | |
1055 | ||
1056 | XI_VERIFY_VALUATORS(num_valuators); | |
1057 | ||
1058 | valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); | |
1059 | xf86PostMotionEventM(device, is_absolute, &mask); | |
1060 | } | |
1061 | ||
1062 | static int | |
1063 | xf86CheckMotionEvent4DGA(DeviceIntPtr device, int is_absolute, | |
1064 | const ValuatorMask *mask) | |
1065 | { | |
1066 | int stolen = 0; | |
1067 | ||
1068 | #if XFreeXDGA | |
1069 | ScreenPtr scr = NULL; | |
1070 | int idx, i; | |
1071 | ||
1072 | /* The evdev driver may not always send all axes across. */ | |
1073 | if (valuator_mask_isset(mask, 0) || valuator_mask_isset(mask, 1)) { | |
1074 | scr = miPointerGetScreen(device); | |
1075 | if (scr) { | |
1076 | int dx = 0, dy = 0; | |
1077 | ||
1078 | idx = scr->myNum; | |
1079 | ||
1080 | if (valuator_mask_isset(mask, 0)) { | |
1081 | dx = valuator_mask_get(mask, 0); | |
1082 | if (is_absolute) | |
1083 | dx -= device->last.valuators[0]; | |
1084 | } | |
1085 | ||
1086 | if (valuator_mask_isset(mask, 1)) { | |
1087 | dy = valuator_mask_get(mask, 1); | |
1088 | if (is_absolute) | |
1089 | dy -= device->last.valuators[1]; | |
1090 | } | |
1091 | ||
1092 | if (DGAStealMotionEvent(device, idx, dx, dy)) | |
1093 | stolen = 1; | |
1094 | } | |
1095 | } | |
1096 | ||
1097 | for (i = 2; i < valuator_mask_size(mask); i++) { | |
1098 | AxisInfoPtr ax; | |
1099 | double incr; | |
1100 | int val, button; | |
1101 | ||
1102 | if (i >= device->valuator->numAxes) | |
1103 | break; | |
1104 | ||
1105 | if (!valuator_mask_isset(mask, i)) | |
1106 | continue; | |
1107 | ||
1108 | ax = &device->valuator->axes[i]; | |
1109 | ||
1110 | if (ax->scroll.type == SCROLL_TYPE_NONE) | |
1111 | continue; | |
1112 | ||
1113 | if (!scr) { | |
1114 | scr = miPointerGetScreen(device); | |
1115 | if (!scr) | |
1116 | break; | |
1117 | idx = scr->myNum; | |
1118 | } | |
1119 | ||
1120 | incr = ax->scroll.increment; | |
1121 | val = valuator_mask_get(mask, i); | |
1122 | ||
1123 | if (ax->scroll.type == SCROLL_TYPE_VERTICAL) { | |
1124 | if (incr * val < 0) | |
1125 | button = 4; /* up */ | |
1126 | else | |
1127 | button = 5; /* down */ | |
1128 | } else { /* SCROLL_TYPE_HORIZONTAL */ | |
1129 | if (incr * val < 0) | |
1130 | button = 6; /* left */ | |
1131 | else | |
1132 | button = 7; /* right */ | |
1133 | } | |
1134 | ||
1135 | if (DGAStealButtonEvent(device, idx, button, 1) && | |
1136 | DGAStealButtonEvent(device, idx, button, 0)) | |
1137 | stolen = 1; | |
1138 | } | |
1139 | ||
1140 | #endif | |
1141 | ||
1142 | return stolen; | |
1143 | } | |
1144 | ||
1145 | void | |
1146 | xf86PostMotionEventM(DeviceIntPtr device, | |
1147 | int is_absolute, const ValuatorMask *mask) | |
1148 | { | |
1149 | int flags = 0; | |
1150 | ||
1151 | if (xf86CheckMotionEvent4DGA(device, is_absolute, mask)) | |
1152 | return; | |
1153 | ||
1154 | if (valuator_mask_num_valuators(mask) > 0) { | |
1155 | if (is_absolute) | |
1156 | flags = POINTER_ABSOLUTE; | |
1157 | else | |
1158 | flags = POINTER_RELATIVE | POINTER_ACCELERATE; | |
1159 | } | |
1160 | ||
1161 | QueuePointerEvents(device, MotionNotify, 0, flags, mask); | |
1162 | } | |
1163 | ||
1164 | void | |
1165 | xf86PostProximityEvent(DeviceIntPtr device, | |
1166 | int is_in, int first_valuator, int num_valuators, ...) | |
1167 | { | |
1168 | va_list var; | |
1169 | int i; | |
1170 | ValuatorMask mask; | |
1171 | ||
1172 | XI_VERIFY_VALUATORS(num_valuators); | |
1173 | ||
1174 | valuator_mask_zero(&mask); | |
1175 | va_start(var, num_valuators); | |
1176 | for (i = 0; i < num_valuators; i++) | |
1177 | valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); | |
1178 | ||
1179 | va_end(var); | |
1180 | ||
1181 | xf86PostProximityEventM(device, is_in, &mask); | |
1182 | } | |
1183 | ||
1184 | void | |
1185 | xf86PostProximityEventP(DeviceIntPtr device, | |
1186 | int is_in, | |
1187 | int first_valuator, | |
1188 | int num_valuators, const int *valuators) | |
1189 | { | |
1190 | ValuatorMask mask; | |
1191 | ||
1192 | XI_VERIFY_VALUATORS(num_valuators); | |
1193 | ||
1194 | valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); | |
1195 | xf86PostProximityEventM(device, is_in, &mask); | |
1196 | } | |
1197 | ||
1198 | void | |
1199 | xf86PostProximityEventM(DeviceIntPtr device, | |
1200 | int is_in, const ValuatorMask *mask) | |
1201 | { | |
1202 | QueueProximityEvents(device, is_in ? ProximityIn : ProximityOut, mask); | |
1203 | } | |
1204 | ||
1205 | void | |
1206 | xf86PostButtonEvent(DeviceIntPtr device, | |
1207 | int is_absolute, | |
1208 | int button, | |
1209 | int is_down, int first_valuator, int num_valuators, ...) | |
1210 | { | |
1211 | va_list var; | |
1212 | ValuatorMask mask; | |
1213 | int i = 0; | |
1214 | ||
1215 | XI_VERIFY_VALUATORS(num_valuators); | |
1216 | ||
1217 | valuator_mask_zero(&mask); | |
1218 | ||
1219 | va_start(var, num_valuators); | |
1220 | for (i = 0; i < num_valuators; i++) | |
1221 | valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); | |
1222 | ||
1223 | va_end(var); | |
1224 | ||
1225 | xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); | |
1226 | } | |
1227 | ||
1228 | void | |
1229 | xf86PostButtonEventP(DeviceIntPtr device, | |
1230 | int is_absolute, | |
1231 | int button, | |
1232 | int is_down, | |
1233 | int first_valuator, | |
1234 | int num_valuators, const int *valuators) | |
1235 | { | |
1236 | ValuatorMask mask; | |
1237 | ||
1238 | XI_VERIFY_VALUATORS(num_valuators); | |
1239 | ||
1240 | valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); | |
1241 | xf86PostButtonEventM(device, is_absolute, button, is_down, &mask); | |
1242 | } | |
1243 | ||
1244 | void | |
1245 | xf86PostButtonEventM(DeviceIntPtr device, | |
1246 | int is_absolute, | |
1247 | int button, int is_down, const ValuatorMask *mask) | |
1248 | { | |
1249 | int flags = 0; | |
1250 | ||
1251 | if (valuator_mask_num_valuators(mask) > 0) { | |
1252 | if (is_absolute) | |
1253 | flags = POINTER_ABSOLUTE; | |
1254 | else | |
1255 | flags = POINTER_RELATIVE | POINTER_ACCELERATE; | |
1256 | } | |
1257 | ||
1258 | #if XFreeXDGA | |
1259 | if (miPointerGetScreen(device)) { | |
1260 | int index = miPointerGetScreen(device)->myNum; | |
1261 | ||
1262 | if (DGAStealButtonEvent(device, index, button, is_down)) | |
1263 | return; | |
1264 | } | |
1265 | #endif | |
1266 | ||
1267 | QueuePointerEvents(device, | |
1268 | is_down ? ButtonPress : ButtonRelease, button, | |
1269 | flags, mask); | |
1270 | } | |
1271 | ||
1272 | void | |
1273 | xf86PostKeyEvent(DeviceIntPtr device, | |
1274 | unsigned int key_code, | |
1275 | int is_down, | |
1276 | int is_absolute, int first_valuator, int num_valuators, ...) | |
1277 | { | |
1278 | va_list var; | |
1279 | int i = 0; | |
1280 | ValuatorMask mask; | |
1281 | ||
1282 | XI_VERIFY_VALUATORS(num_valuators); | |
1283 | ||
1284 | valuator_mask_zero(&mask); | |
1285 | ||
1286 | va_start(var, num_valuators); | |
1287 | for (i = 0; i < num_valuators; i++) | |
1288 | valuator_mask_set(&mask, first_valuator + i, va_arg(var, int)); | |
1289 | ||
1290 | va_end(var); | |
1291 | ||
1292 | xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); | |
1293 | } | |
1294 | ||
1295 | void | |
1296 | xf86PostKeyEventP(DeviceIntPtr device, | |
1297 | unsigned int key_code, | |
1298 | int is_down, | |
1299 | int is_absolute, | |
1300 | int first_valuator, int num_valuators, const int *valuators) | |
1301 | { | |
1302 | ValuatorMask mask; | |
1303 | ||
1304 | XI_VERIFY_VALUATORS(num_valuators); | |
1305 | ||
1306 | valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators); | |
1307 | xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask); | |
1308 | } | |
1309 | ||
1310 | void | |
1311 | xf86PostKeyEventM(DeviceIntPtr device, | |
1312 | unsigned int key_code, | |
1313 | int is_down, int is_absolute, const ValuatorMask *mask) | |
1314 | { | |
1315 | #if XFreeXDGA | |
1316 | DeviceIntPtr pointer; | |
1317 | ||
1318 | /* Some pointers send key events, paired device is wrong then. */ | |
1319 | pointer = GetMaster(device, POINTER_OR_FLOAT); | |
1320 | ||
1321 | if (miPointerGetScreen(pointer)) { | |
1322 | int index = miPointerGetScreen(pointer)->myNum; | |
1323 | ||
1324 | if (DGAStealKeyEvent(device, index, key_code, is_down)) | |
1325 | return; | |
1326 | } | |
1327 | #endif | |
1328 | ||
1329 | QueueKeyboardEvents(device, | |
1330 | is_down ? KeyPress : KeyRelease, key_code, mask); | |
1331 | } | |
1332 | ||
1333 | void | |
1334 | xf86PostKeyboardEvent(DeviceIntPtr device, unsigned int key_code, int is_down) | |
1335 | { | |
1336 | ValuatorMask mask; | |
1337 | ||
1338 | valuator_mask_zero(&mask); | |
1339 | xf86PostKeyEventM(device, key_code, is_down, 0, &mask); | |
1340 | } | |
1341 | ||
1342 | InputInfoPtr | |
1343 | xf86FirstLocalDevice(void) | |
1344 | { | |
1345 | return xf86InputDevs; | |
1346 | } | |
1347 | ||
1348 | /* | |
1349 | * Cx - raw data from touch screen | |
1350 | * to_max - scaled highest dimension | |
1351 | * (remember, this is of rows - 1 because of 0 origin) | |
1352 | * to_min - scaled lowest dimension | |
1353 | * from_max - highest raw value from touch screen calibration | |
1354 | * from_min - lowest raw value from touch screen calibration | |
1355 | * | |
1356 | * This function is the same for X or Y coordinates. | |
1357 | * You may have to reverse the high and low values to compensate for | |
1358 | * different orgins on the touch screen vs X. | |
1359 | * | |
1360 | * e.g. to scale from device coordinates into screen coordinates, call | |
1361 | * xf86ScaleAxis(x, 0, screen_width, dev_min, dev_max); | |
1362 | */ | |
1363 | ||
1364 | int | |
1365 | xf86ScaleAxis(int Cx, int to_max, int to_min, int from_max, int from_min) | |
1366 | { | |
1367 | int X; | |
1368 | int64_t to_width = to_max - to_min; | |
1369 | int64_t from_width = from_max - from_min; | |
1370 | ||
1371 | if (from_width) { | |
1372 | X = (int) (((to_width * (Cx - from_min)) / from_width) + to_min); | |
1373 | } | |
1374 | else { | |
1375 | X = 0; | |
1376 | ErrorF("Divide by Zero in xf86ScaleAxis\n"); | |
1377 | } | |
1378 | ||
1379 | if (X > to_max) | |
1380 | X = to_max; | |
1381 | if (X < to_min) | |
1382 | X = to_min; | |
1383 | ||
1384 | return X; | |
1385 | } | |
1386 | ||
1387 | Bool | |
1388 | xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, | |
1389 | int maxval, int resolution, int min_res, int max_res, | |
1390 | int mode) | |
1391 | { | |
1392 | if (!dev || !dev->valuator) | |
1393 | return FALSE; | |
1394 | ||
1395 | return InitValuatorAxisStruct(dev, axnum, label, minval, maxval, resolution, | |
1396 | min_res, max_res, mode); | |
1397 | } | |
1398 | ||
1399 | /* | |
1400 | * Set the valuator values to be in sync with dix/event.c | |
1401 | * DefineInitialRootWindow(). | |
1402 | */ | |
1403 | void | |
1404 | xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) | |
1405 | { | |
1406 | if (axnum == 0) { | |
1407 | dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; | |
1408 | dev->last.valuators[0] = dev->valuator->axisVal[0]; | |
1409 | } | |
1410 | else if (axnum == 1) { | |
1411 | dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; | |
1412 | dev->last.valuators[1] = dev->valuator->axisVal[1]; | |
1413 | } | |
1414 | } | |
1415 | ||
1416 | /** | |
1417 | * Deactivate a device. Call this function from the driver if you receive a | |
1418 | * read error or something else that spoils your day. | |
1419 | * Device will be moved to the off_devices list, but it will still be there | |
1420 | * until you really clean up after it. | |
1421 | * Notifies the client about an inactive device. | |
1422 | * | |
1423 | * @param panic True if device is unrecoverable and needs to be removed. | |
1424 | */ | |
1425 | void | |
1426 | xf86DisableDevice(DeviceIntPtr dev, Bool panic) | |
1427 | { | |
1428 | if (!panic) { | |
1429 | DisableDevice(dev, TRUE); | |
1430 | } | |
1431 | else { | |
1432 | SendDevicePresenceEvent(dev->id, DeviceUnrecoverable); | |
1433 | DeleteInputDeviceRequest(dev); | |
1434 | } | |
1435 | } | |
1436 | ||
1437 | /** | |
1438 | * Reactivate a device. Call this function from the driver if you just found | |
1439 | * out that the read error wasn't quite that bad after all. | |
1440 | * Device will be re-activated, and an event sent to the client. | |
1441 | */ | |
1442 | void | |
1443 | xf86EnableDevice(DeviceIntPtr dev) | |
1444 | { | |
1445 | EnableDevice(dev, TRUE); | |
1446 | } | |
1447 | ||
1448 | /** | |
1449 | * Post a touch event with optional valuators. If this is the first touch in | |
1450 | * the sequence, at least x & y valuators must be provided. The driver is | |
1451 | * responsible for maintaining the correct event sequence (TouchBegin, TouchUpdate, | |
1452 | * TouchEnd). Submitting an update or end event for a unregistered touchid will | |
1453 | * result in errors. | |
1454 | * Touch IDs may be reused by the driver but only after a TouchEnd has been | |
1455 | * submitted for that touch ID. | |
1456 | * | |
1457 | * @param dev The device to post the event for | |
1458 | * @param touchid The touchid of the current touch event. Must be an | |
1459 | * existing ID for TouchUpdate or TouchEnd events | |
1460 | * @param type One of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd | |
1461 | * @param flags Flags for this event | |
1462 | * @param The valuator mask with all valuators set for this event. | |
1463 | */ | |
1464 | void | |
1465 | xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, uint16_t type, | |
1466 | uint32_t flags, const ValuatorMask *mask) | |
1467 | { | |
1468 | ||
1469 | QueueTouchEvents(dev, type, touchid, flags, mask); | |
1470 | } | |
1471 | ||
1472 | /* end of xf86Xinput.c */ |