2 * Copyright 1995-1999 by Frederic Lepied, France. <Lepied@XFree86.org>
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>
53 #include <X11/Xfuncproto.h>
56 #include <X11/extensions/XI.h>
57 #include <X11/extensions/XIproto.h>
61 #include "xf86Xinput.h"
64 #include "xf86Optrec.h"
66 #include "mipointer.h"
67 #include "xf86InPriv.h"
71 #include <X11/extensions/dpms.h>
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 */
86 #include <X11/Xpoll.h>
94 xEvent
*xf86Events
= NULL
;
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
);
107 /***********************************************************************
109 * xf86ProcessCommonOptions --
111 * Process global options.
113 ***********************************************************************
116 xf86ProcessCommonOptions(LocalDevicePtr local
,
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
);
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
;
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 ***********************************************************************
148 xf86ActivateDevice(LocalDevicePtr local
)
152 if (local
->flags
& XI86_CONFIGURED
) {
153 dev
= AddInputDevice(local
->device_control
, TRUE
);
156 FatalError("Too many input devices");
158 local
->atom
= MakeAtom(local
->type_name
,
159 strlen(local
->type_name
),
161 AssignTypeAndName(dev
, local
->atom
, local
->name
);
162 dev
->public.devicePrivate
= (pointer
) local
;
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
);
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
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 ***********************************************************************
200 OpenInputDevice(DeviceIntPtr dev
,
211 CloseInputDevice(DeviceIntPtr dev
,
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
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
);
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
,
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
) {
286 case DEVICE_RESOLUTION
:
287 case DEVICE_ABS_CALIB
:
288 case DEVICE_ABS_AREA
:
296 return (*local
->control_proc
)(local
, control
);
301 AddOtherInputDevices()
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
;
317 idev
= xcalloc(sizeof(*idev
), 1);
321 for (option
= options
; option
; option
= option
->next
) {
322 if (strcasecmp(option
->key
, "driver") == 0) {
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
);
331 if (xf86LoadOneModule(option
->value
, NULL
))
332 drv
= xf86LookupInputDriver(option
->value
);
334 xf86Msg(X_ERROR
, "No input driver matching `%s'\n",
339 idev
->driver
= xstrdup(option
->value
);
346 if (strcasecmp(option
->key
, "name") == 0 ||
347 strcasecmp(option
->key
, "identifier") == 0) {
348 if (idev
->identifier
) {
352 idev
->identifier
= xstrdup(option
->value
);
353 if (!idev
->identifier
) {
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
) {
370 if (!idev
->driver
|| !idev
->identifier
) {
371 xf86Msg(X_ERROR
, "No input driver/identifier specified (ignoring)\n");
378 "Input driver `%s' has no PreInit function (ignoring)\n",
380 rval
= BadImplementation
;
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
);
390 option
->value
= NULL
;
393 pInfo
= drv
->PreInit(drv
, idev
, 0);
396 xf86Msg(X_ERROR
, "PreInit returned NULL for \"%s\"\n", idev
->identifier
);
400 else if (!(pInfo
->flags
& XI86_CONFIGURED
)) {
401 xf86Msg(X_ERROR
, "PreInit failed for input device \"%s\"\n",
407 xf86ActivateDevice(pInfo
);
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
))
423 drv
->UnInit(drv
, pInfo
, 0);
425 xf86DeleteInput(pInfo
, 0);
430 xfree(idev
->identifier
);
431 xf86optionListFree(idev
->commonOptions
);
437 DeleteInputDeviceRequest(DeviceIntPtr pDev
)
439 LocalDevicePtr pInfo
= (LocalDevicePtr
) pDev
->public.devicePrivate
;
440 InputDriverPtr drv
= pInfo
->drv
;
441 IDevRec
*idev
= pInfo
->conf_idev
;
446 drv
->UnInit(drv
, pInfo
, 0);
448 xf86DeleteInput(pInfo
, 0);
451 xfree(idev
->identifier
);
452 xf86optionListFree(idev
->commonOptions
);
457 * convenient functions to post events
461 xf86PostMotionEvent(DeviceIntPtr device
,
469 static int *valuators
= NULL
;
470 static int n_valuators
= 0;
472 if (num_valuators
> n_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);
487 xf86PostMotionEventP(device
, is_absolute
, first_valuator
, num_valuators
, valuators
);
491 xf86PostMotionEventP(DeviceIntPtr device
,
497 int i
= 0, nevents
= 0;
499 Bool drag
= xf86SendDragEvents(device
);
505 flags
= POINTER_ABSOLUTE
;
507 flags
= POINTER_RELATIVE
| POINTER_ACCELERATE
;
510 if (first_valuator
== 0 && num_valuators
>= 2) {
511 if (miPointerGetScreen(inputInfo
.pointer
)) {
512 index
= miPointerGetScreen(inputInfo
.pointer
)->myNum
;
514 dx
= valuators
[0] - device
->valuator
->lastx
;
515 dy
= valuators
[1] - device
->valuator
->lasty
;
521 if (DGAStealMotionEvent(index
, dx
, dy
))
528 xf86Events
= (xEvent
*)xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
530 FatalError("Couldn't allocate event store\n");
532 nevents
= GetPointerEvents(xf86Events
, device
, MotionNotify
, 0,
533 flags
, first_valuator
, num_valuators
,
536 for (i
= 0; i
< nevents
; i
++) {
538 /* Don't post core motion events for devices not registered to send
540 if (xE
->u
.u
.type
!= MotionNotify
|| drag
) {
541 mieqEnqueue(device
, xf86Events
+ i
);
547 xf86PostProximityEvent(DeviceIntPtr device
,
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);
564 xf86Events
= (xEvent
*)xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
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
);
578 xf86PostButtonEvent(DeviceIntPtr device
,
587 int *valuators
= NULL
;
588 int i
= 0, nevents
= 0;
592 if (miPointerGetScreen(inputInfo
.pointer
)) {
593 index
= miPointerGetScreen(inputInfo
.pointer
)->myNum
;
594 if (DGAStealButtonEvent(index
, button
, is_down
))
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);
607 xf86Events
= (xEvent
*)xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
609 FatalError("Couldn't allocate event store\n");
611 nevents
= GetPointerEvents(xf86Events
, device
,
612 is_down
? ButtonPress
: ButtonRelease
, button
,
613 is_absolute
? POINTER_ABSOLUTE
:
615 first_valuator
, num_valuators
, valuators
);
617 for (i
= 0; i
< nevents
; i
++)
618 mieqEnqueue(device
, xf86Events
+ i
);
624 xf86PostKeyEvent(DeviceIntPtr device
,
625 unsigned int key_code
,
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 "
641 xf86Events
= (xEvent
*)xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
643 FatalError("Couldn't allocate event store\n");
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);
652 nevents
= GetKeyboardValuatorEvents(xf86Events
, device
,
653 is_down
? KeyPress
: KeyRelease
,
654 key_code
, first_valuator
,
655 num_valuators
, valuators
);
659 nevents
= GetKeyboardEvents(xf86Events
, device
,
660 is_down
? KeyPress
: KeyRelease
,
664 for (i
= 0; i
< nevents
; i
++)
665 mieqEnqueue(device
, xf86Events
+ i
);
669 xf86PostKeyboardEvent(DeviceIntPtr device
,
670 unsigned int key_code
,
673 int nevents
= 0, i
= 0;
677 if (miPointerGetScreen(inputInfo
.pointer
)) {
678 index
= miPointerGetScreen(inputInfo
.pointer
)->myNum
;
679 if (DGAStealKeyEvent(index
, key_code
, is_down
))
685 xf86Events
= (xEvent
*)xcalloc(sizeof(xEvent
), GetMaximumEventsNum());
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.
716 xf86ScaleAxis(int Cx
,
723 int dSx
= Sxhigh
- Sxlow
;
724 int dRx
= Rxhigh
- Rxlow
;
726 dSx
= Sxhigh
- Sxlow
;
728 X
= ((dSx
* (Cx
- Rxlow
)) / dRx
) + Sxlow
;
732 ErrorF ("Divide by Zero in xf86ScaleAxis");
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.
750 xf86XInputSetScreen(LocalDevicePtr local
,
755 if (miPointerGetScreen(local
->dev
) !=
756 screenInfo
.screens
[screen_number
]) {
757 miPointerSetScreen(local
->dev
, screen_number
, x
, y
);
763 xf86InitValuatorAxisStruct(DeviceIntPtr dev
, int axnum
, int minval
, int maxval
,
764 int resolution
, int min_res
, int max_res
)
766 if (!dev
|| !dev
->valuator
)
769 InitValuatorAxisStruct(dev
, axnum
, minval
, maxval
, resolution
, min_res
,
774 * Set the valuator values to be in synch with dix/event.c
775 * DefineInitialRootWindow().
778 xf86InitValuatorDefaults(DeviceIntPtr dev
, int axnum
)
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.
801 xf86DisableDevice(DeviceIntPtr dev
, Bool panic
)
803 devicePresenceNotify ev
;
804 DeviceIntRec dummyDev
;
811 ev
.type
= DevicePresenceNotify
;
812 ev
.time
= currentTime
.milliseconds
;
813 ev
.devchange
= DeviceUnrecoverable
;
814 ev
.deviceid
= dev
->id
;
816 SendEventToAllWindows(&dummyDev
, DevicePresenceNotifyMask
,
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.
829 xf86EnableDevice(DeviceIntPtr dev
)
834 /* end of xf86Xinput.c */