First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / common / xf86Xinput.c
blobe45d44c02e9df8dc66283c510cbb9c88eac9252d
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.
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.
24 * Copyright (c) 2000-2002 by The XFree86 Project, Inc.
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:
33 * The above copyright notice and this permission notice shall be included in
34 * all copies or substantial portions of the Software.
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.
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).
49 #ifdef HAVE_XORG_CONFIG_H
50 #include <xorg-config.h>
51 #endif
53 #include <X11/Xfuncproto.h>
54 #include <X11/Xmd.h>
55 #ifdef XINPUT
56 #include <X11/extensions/XI.h>
57 #include <X11/extensions/XIproto.h>
58 #endif
59 #include "xf86.h"
60 #include "xf86Priv.h"
61 #include "xf86Xinput.h"
62 #ifdef XINPUT
63 #include "XIstubs.h"
64 #include "xf86Optrec.h"
65 #endif
66 #include "mipointer.h"
67 #include "xf86InPriv.h"
69 #ifdef DPMSExtension
70 #define DPMS_SERVER
71 #include <X11/extensions/dpms.h>
72 #include "dpmsproc.h"
73 #endif
75 #include "exevents.h" /* AddInputDevice */
76 #include "exglobals.h"
78 #define EXTENSION_PROC_ARGS void *
79 #include "extnsionst.h"
80 #include "extinit.h" /* LookupDeviceIntRec */
82 #include "windowstr.h" /* screenIsSaved */
84 #include <stdarg.h>
86 #include <X11/Xpoll.h>
88 #include "mi.h"
90 #ifdef XFreeXDGA
91 #include "dgaproc.h"
92 #endif
94 xEvent *xf86Events = NULL;
96 static Bool
97 xf86SendDragEvents(DeviceIntPtr device)
99 LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
101 if (device->button && device->button->buttonsDown > 0)
102 return (local->flags & XI86_SEND_DRAG_EVENTS);
103 else
104 return (TRUE);
107 /***********************************************************************
109 * xf86ProcessCommonOptions --
111 * Process global options.
113 ***********************************************************************
115 _X_EXPORT void
116 xf86ProcessCommonOptions(LocalDevicePtr local,
117 pointer list)
119 if (xf86SetBoolOption(list, "AlwaysCore", 0) ||
120 !xf86SetBoolOption(list, "SendCoreEvents", 1) ||
121 !xf86SetBoolOption(list, "CorePointer", 1) ||
122 !xf86SetBoolOption(list, "CoreKeyboard", 1)) {
123 xf86Msg(X_CONFIG, "%s: doesn't report core events\n", local->name);
124 } else {
125 local->flags |= XI86_ALWAYS_CORE;
126 xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
129 if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
130 local->flags |= XI86_SEND_DRAG_EVENTS;
131 } else {
132 xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name);
135 /* Backwards compatibility. */
136 local->history_size = GetMotionHistorySize();
139 /***********************************************************************
141 * xf86ActivateDevice --
143 * Initialize an input device.
145 ***********************************************************************
147 _X_EXPORT void
148 xf86ActivateDevice(LocalDevicePtr local)
150 DeviceIntPtr dev;
152 if (local->flags & XI86_CONFIGURED) {
153 dev = AddInputDevice(local->device_control, TRUE);
155 if (dev == NULL)
156 FatalError("Too many input devices");
158 local->atom = MakeAtom(local->type_name,
159 strlen(local->type_name),
160 TRUE);
161 AssignTypeAndName(dev, local->atom, local->name);
162 dev->public.devicePrivate = (pointer) local;
163 local->dev = dev;
165 dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
166 RegisterOtherDevice(dev);
168 if (serverGeneration == 1)
169 xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
170 local->name, local->type_name);
175 #ifdef XINPUT
176 /***********************************************************************
178 * Caller: ProcXOpenDevice
180 * This is the implementation-dependent routine to open an input device.
181 * Some implementations open all input devices when the server is first
182 * initialized, and never close them. Other implementations open only
183 * the X pointer and keyboard devices during server initialization,
184 * and only open other input devices when some client makes an
185 * XOpenDevice request. This entry point is for the latter type of
186 * implementation.
188 * If the physical device is not already open, do it here. In this case,
189 * you need to keep track of the fact that one or more clients has the
190 * device open, and physically close it when the last client that has
191 * it open does an XCloseDevice.
193 * The default implementation is to do nothing (assume all input devices
194 * are opened during X server initialization and kept open).
196 ***********************************************************************
199 void
200 OpenInputDevice(DeviceIntPtr dev,
201 ClientPtr client,
202 int *status)
204 if (!dev->inited)
205 ActivateDevice(dev);
207 *status = Success;
210 void
211 CloseInputDevice(DeviceIntPtr dev,
212 ClientPtr client)
216 /****************************************************************************
218 * Caller: ProcXSetDeviceMode
220 * Change the mode of an extension device.
221 * This function is used to change the mode of a device from reporting
222 * relative motion to reporting absolute positional information, and
223 * vice versa.
224 * The default implementation below is that no such devices are supported.
226 ***********************************************************************
230 SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode)
232 LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
234 if (local->switch_mode) {
235 return (*local->switch_mode)(client, dev, mode);
237 else
238 return BadMatch;
242 /***********************************************************************
244 * Caller: ProcXSetDeviceValuators
246 * Set the value of valuators on an extension input device.
247 * This function is used to set the initial value of valuators on
248 * those input devices that are capable of reporting either relative
249 * motion or an absolute position, and allow an initial position to be set.
250 * The default implementation below is that no such devices are supported.
252 ***********************************************************************
256 SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators,
257 int first_valuator, int num_valuators)
259 LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
261 if (local->set_device_valuators)
262 return (*local->set_device_valuators)(local, valuators, first_valuator,
263 num_valuators);
265 return BadMatch;
269 /***********************************************************************
271 * Caller: ProcXChangeDeviceControl
273 * Change the specified device controls on an extension input device.
275 ***********************************************************************
279 ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control)
281 LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
283 if (!local->control_proc) {
284 switch (control->control) {
285 case DEVICE_CORE:
286 case DEVICE_RESOLUTION:
287 case DEVICE_ABS_CALIB:
288 case DEVICE_ABS_AREA:
289 case DEVICE_ENABLE:
290 return Success;
291 default:
292 return BadMatch;
295 else {
296 return (*local->control_proc)(local, control);
300 void
301 AddOtherInputDevices()
304 #endif
307 NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
309 IDevRec *idev = NULL;
310 InputDriverPtr drv = NULL;
311 InputInfoPtr pInfo = NULL;
312 InputOption *option = NULL;
313 DeviceIntPtr dev = NULL;
314 int rval = Success;
315 int is_auto = 0;
317 idev = xcalloc(sizeof(*idev), 1);
318 if (!idev)
319 return BadAlloc;
321 for (option = options; option; option = option->next) {
322 if (strcasecmp(option->key, "driver") == 0) {
323 if (idev->driver) {
324 rval = BadRequest;
325 goto unwind;
327 /* Memory leak for every attached device if we don't
328 * test if the module is already loaded first */
329 drv = xf86LookupInputDriver(option->value);
330 if (!drv)
331 if (xf86LoadOneModule(option->value, NULL))
332 drv = xf86LookupInputDriver(option->value);
333 if (!drv) {
334 xf86Msg(X_ERROR, "No input driver matching `%s'\n",
335 option->value);
336 rval = BadName;
337 goto unwind;
339 idev->driver = xstrdup(option->value);
340 if (!idev->driver) {
341 rval = BadAlloc;
342 goto unwind;
346 if (strcasecmp(option->key, "name") == 0 ||
347 strcasecmp(option->key, "identifier") == 0) {
348 if (idev->identifier) {
349 rval = BadRequest;
350 goto unwind;
352 idev->identifier = xstrdup(option->value);
353 if (!idev->identifier) {
354 rval = BadAlloc;
355 goto unwind;
359 /* Right now, the only automatic config we know of is HAL. */
360 if (strcmp(option->key, "_source") == 0 &&
361 strcmp(option->value, "server/hal") == 0) {
362 if (!xf86Info.autoAddDevices) {
363 rval = BadMatch;
364 goto unwind;
367 is_auto = 1;
370 if (!idev->driver || !idev->identifier) {
371 xf86Msg(X_ERROR, "No input driver/identifier specified (ignoring)\n");
372 rval = BadRequest;
373 goto unwind;
376 if (!drv->PreInit) {
377 xf86Msg(X_ERROR,
378 "Input driver `%s' has no PreInit function (ignoring)\n",
379 drv->driverName);
380 rval = BadImplementation;
381 goto unwind;
384 for (option = options; option; option = option->next) {
385 /* Steal option key/value strings from the provided list.
386 * We need those strings, the InputOption list doesn't. */
387 idev->commonOptions = xf86addNewOption(idev->commonOptions,
388 option->key, option->value);
389 option->key = NULL;
390 option->value = NULL;
393 pInfo = drv->PreInit(drv, idev, 0);
395 if (!pInfo) {
396 xf86Msg(X_ERROR, "PreInit returned NULL for \"%s\"\n", idev->identifier);
397 rval = BadMatch;
398 goto unwind;
400 else if (!(pInfo->flags & XI86_CONFIGURED)) {
401 xf86Msg(X_ERROR, "PreInit failed for input device \"%s\"\n",
402 idev->identifier);
403 rval = BadMatch;
404 goto unwind;
407 xf86ActivateDevice(pInfo);
409 dev = pInfo->dev;
410 ActivateDevice(dev);
411 /* Enable it if it's properly initialised, we're currently in the VT, and
412 * either it's a manual request, or we're automatically enabling devices. */
413 if (dev->inited && dev->startup && xf86Screens[0]->vtSema &&
414 (!is_auto || xf86Info.autoEnableDevices))
415 EnableDevice(dev);
417 *pdev = dev;
418 return Success;
420 unwind:
421 if(pInfo) {
422 if(drv->UnInit)
423 drv->UnInit(drv, pInfo, 0);
424 else
425 xf86DeleteInput(pInfo, 0);
427 if(idev->driver)
428 xfree(idev->driver);
429 if(idev->identifier)
430 xfree(idev->identifier);
431 xf86optionListFree(idev->commonOptions);
432 xfree(idev);
433 return rval;
436 void
437 DeleteInputDeviceRequest(DeviceIntPtr pDev)
439 LocalDevicePtr pInfo = (LocalDevicePtr) pDev->public.devicePrivate;
440 InputDriverPtr drv = pInfo->drv;
441 IDevRec *idev = pInfo->conf_idev;
443 RemoveDevice(pDev);
445 if(drv->UnInit)
446 drv->UnInit(drv, pInfo, 0);
447 else
448 xf86DeleteInput(pInfo, 0);
450 xfree(idev->driver);
451 xfree(idev->identifier);
452 xf86optionListFree(idev->commonOptions);
453 xfree(idev);
457 * convenient functions to post events
460 _X_EXPORT void
461 xf86PostMotionEvent(DeviceIntPtr device,
462 int is_absolute,
463 int first_valuator,
464 int num_valuators,
465 ...)
467 va_list var;
468 int i = 0;
469 static int *valuators = NULL;
470 static int n_valuators = 0;
472 if (num_valuators > n_valuators) {
473 xfree (valuators);
474 valuators = NULL;
477 if (!valuators) {
478 valuators = xcalloc(sizeof(int), num_valuators);
479 n_valuators = num_valuators;
482 va_start(var, num_valuators);
483 for (i = 0; i < num_valuators; i++)
484 valuators[i] = va_arg(var, int);
485 va_end(var);
487 xf86PostMotionEventP(device, is_absolute, first_valuator, num_valuators, valuators);
490 _X_EXPORT void
491 xf86PostMotionEventP(DeviceIntPtr device,
492 int is_absolute,
493 int first_valuator,
494 int num_valuators,
495 int *valuators)
497 int i = 0, nevents = 0;
498 int dx, dy;
499 Bool drag = xf86SendDragEvents(device);
500 xEvent *xE = NULL;
501 int index;
502 int flags = 0;
504 if (is_absolute)
505 flags = POINTER_ABSOLUTE;
506 else
507 flags = POINTER_RELATIVE | POINTER_ACCELERATE;
509 #if XFreeXDGA
510 if (first_valuator == 0 && num_valuators >= 2) {
511 if (miPointerGetScreen(inputInfo.pointer)) {
512 index = miPointerGetScreen(inputInfo.pointer)->myNum;
513 if (is_absolute) {
514 dx = valuators[0] - device->valuator->lastx;
515 dy = valuators[1] - device->valuator->lasty;
517 else {
518 dx = valuators[0];
519 dy = valuators[1];
521 if (DGAStealMotionEvent(index, dx, dy))
522 return;
525 #endif
527 if (!xf86Events)
528 xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
529 if (!xf86Events)
530 FatalError("Couldn't allocate event store\n");
532 nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0,
533 flags, first_valuator, num_valuators,
534 valuators);
536 for (i = 0; i < nevents; i++) {
537 xE = xf86Events + i;
538 /* Don't post core motion events for devices not registered to send
539 * drag events. */
540 if (xE->u.u.type != MotionNotify || drag) {
541 mieqEnqueue(device, xf86Events + i);
546 _X_EXPORT void
547 xf86PostProximityEvent(DeviceIntPtr device,
548 int is_in,
549 int first_valuator,
550 int num_valuators,
551 ...)
553 va_list var;
554 int i, nevents, *valuators = NULL;
556 valuators = xcalloc(sizeof(int), num_valuators);
558 va_start(var, num_valuators);
559 for (i = 0; i < num_valuators; i++)
560 valuators[i] = va_arg(var, int);
561 va_end(var);
563 if (!xf86Events)
564 xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
565 if (!xf86Events)
566 FatalError("Couldn't allocate event store\n");
568 nevents = GetProximityEvents(xf86Events, device,
569 is_in ? ProximityIn : ProximityOut,
570 first_valuator, num_valuators, valuators);
571 for (i = 0; i < nevents; i++)
572 mieqEnqueue(device, xf86Events + i);
574 xfree(valuators);
577 _X_EXPORT void
578 xf86PostButtonEvent(DeviceIntPtr device,
579 int is_absolute,
580 int button,
581 int is_down,
582 int first_valuator,
583 int num_valuators,
584 ...)
586 va_list var;
587 int *valuators = NULL;
588 int i = 0, nevents = 0;
589 int index;
591 #if XFreeXDGA
592 if (miPointerGetScreen(inputInfo.pointer)) {
593 index = miPointerGetScreen(inputInfo.pointer)->myNum;
594 if (DGAStealButtonEvent(index, button, is_down))
595 return;
597 #endif
599 valuators = xcalloc(sizeof(int), num_valuators);
601 va_start(var, num_valuators);
602 for (i = 0; i < num_valuators; i++)
603 valuators[i] = va_arg(var, int);
604 va_end(var);
606 if (!xf86Events)
607 xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
608 if (!xf86Events)
609 FatalError("Couldn't allocate event store\n");
611 nevents = GetPointerEvents(xf86Events, device,
612 is_down ? ButtonPress : ButtonRelease, button,
613 is_absolute ? POINTER_ABSOLUTE :
614 POINTER_RELATIVE,
615 first_valuator, num_valuators, valuators);
617 for (i = 0; i < nevents; i++)
618 mieqEnqueue(device, xf86Events + i);
620 xfree(valuators);
623 _X_EXPORT void
624 xf86PostKeyEvent(DeviceIntPtr device,
625 unsigned int key_code,
626 int is_down,
627 int is_absolute,
628 int first_valuator,
629 int num_valuators,
630 ...)
632 va_list var;
633 int i = 0, nevents = 0, *valuators = NULL;
635 /* instil confidence in the user */
636 DebugF("this function has never been tested properly. if things go quite "
637 "badly south after this message, then xf86PostKeyEvent is "
638 "broken.\n");
640 if (!xf86Events)
641 xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
642 if (!xf86Events)
643 FatalError("Couldn't allocate event store\n");
645 if (is_absolute) {
646 valuators = xcalloc(sizeof(int), num_valuators);
647 va_start(var, num_valuators);
648 for (i = 0; i < num_valuators; i++)
649 valuators[i] = va_arg(var, int);
650 va_end(var);
652 nevents = GetKeyboardValuatorEvents(xf86Events, device,
653 is_down ? KeyPress : KeyRelease,
654 key_code, first_valuator,
655 num_valuators, valuators);
656 xfree(valuators);
658 else {
659 nevents = GetKeyboardEvents(xf86Events, device,
660 is_down ? KeyPress : KeyRelease,
661 key_code);
664 for (i = 0; i < nevents; i++)
665 mieqEnqueue(device, xf86Events + i);
668 _X_EXPORT void
669 xf86PostKeyboardEvent(DeviceIntPtr device,
670 unsigned int key_code,
671 int is_down)
673 int nevents = 0, i = 0;
674 int index;
676 #if XFreeXDGA
677 if (miPointerGetScreen(inputInfo.pointer)) {
678 index = miPointerGetScreen(inputInfo.pointer)->myNum;
679 if (DGAStealKeyEvent(index, key_code, is_down))
680 return;
682 #endif
684 if (!xf86Events)
685 xf86Events = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum());
686 if (!xf86Events)
687 FatalError("Couldn't allocate event store\n");
689 nevents = GetKeyboardEvents(xf86Events, device,
690 is_down ? KeyPress : KeyRelease, key_code);
692 for (i = 0; i < nevents; i++)
693 mieqEnqueue(device, xf86Events + i);
696 _X_EXPORT LocalDevicePtr
697 xf86FirstLocalDevice()
699 return xf86InputDevs;
703 * Cx - raw data from touch screen
704 * Sxhigh - scaled highest dimension
705 * (remember, this is of rows - 1 because of 0 origin)
706 * Sxlow - scaled lowest dimension
707 * Rxhigh - highest raw value from touch screen calibration
708 * Rxlow - lowest raw value from touch screen calibration
710 * This function is the same for X or Y coordinates.
711 * You may have to reverse the high and low values to compensate for
712 * different orgins on the touch screen vs X.
715 _X_EXPORT int
716 xf86ScaleAxis(int Cx,
717 int Sxhigh,
718 int Sxlow,
719 int Rxhigh,
720 int Rxlow )
722 int X;
723 int dSx = Sxhigh - Sxlow;
724 int dRx = Rxhigh - Rxlow;
726 dSx = Sxhigh - Sxlow;
727 if (dRx) {
728 X = ((dSx * (Cx - Rxlow)) / dRx) + Sxlow;
730 else {
731 X = 0;
732 ErrorF ("Divide by Zero in xf86ScaleAxis");
735 if (X > Sxlow)
736 X = Sxlow;
737 if (X < Sxhigh)
738 X = Sxhigh;
740 return (X);
744 * This function checks the given screen against the current screen and
745 * makes changes if appropriate. It should be called from an XInput driver's
746 * ReadInput function before any events are posted, if the device is screen
747 * specific like a touch screen.
749 _X_EXPORT void
750 xf86XInputSetScreen(LocalDevicePtr local,
751 int screen_number,
752 int x,
753 int y)
755 if (miPointerGetScreen(local->dev) !=
756 screenInfo.screens[screen_number]) {
757 miPointerSetScreen(local->dev, screen_number, x, y);
762 _X_EXPORT void
763 xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
764 int resolution, int min_res, int max_res)
766 if (!dev || !dev->valuator)
767 return;
769 InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res,
770 max_res);
774 * Set the valuator values to be in synch with dix/event.c
775 * DefineInitialRootWindow().
777 _X_EXPORT void
778 xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
780 if (axnum == 0) {
781 dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
782 dev->valuator->lastx = dev->valuator->axisVal[0];
784 else if (axnum == 1) {
785 dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
786 dev->valuator->lasty = dev->valuator->axisVal[1];
792 * Deactivate a device. Call this function from the driver if you receive a
793 * read error or something else that spoils your day.
794 * Device will be moved to the off_devices list, but it will still be there
795 * until you really clean up after it.
796 * Notifies the client about an inactive device.
798 * @param panic True if device is unrecoverable and needs to be removed.
800 _X_EXPORT void
801 xf86DisableDevice(DeviceIntPtr dev, Bool panic)
803 devicePresenceNotify ev;
804 DeviceIntRec dummyDev;
806 if(!panic)
808 DisableDevice(dev);
809 } else
811 ev.type = DevicePresenceNotify;
812 ev.time = currentTime.milliseconds;
813 ev.devchange = DeviceUnrecoverable;
814 ev.deviceid = dev->id;
815 dummyDev.id = 0;
816 SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
817 (xEvent *) &ev, 1);
819 DeleteInputDeviceRequest(dev);
824 * Reactivate a device. Call this function from the driver if you just found
825 * out that the read error wasn't quite that bad after all.
826 * Device will be re-activated, and an event sent to the client.
828 _X_EXPORT void
829 xf86EnableDevice(DeviceIntPtr dev)
831 EnableDevice(dev);
834 /* end of xf86Xinput.c */