xf86Xinput.c revision 4642e01f
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 "xf86.h"
58#include "xf86Priv.h"
59#include "xf86Xinput.h"
60#include "XIstubs.h"
61#include "xf86Optrec.h"
62#include "mipointer.h"
63#include "xf86InPriv.h"
64#include "compiler.h"
65#include "extinit.h"
66
67#ifdef DPMSExtension
68#define DPMS_SERVER
69#include <X11/extensions/dpms.h>
70#include "dpmsproc.h"
71#endif
72
73#include "exevents.h"	/* AddInputDevice */
74#include "exglobals.h"
75
76#define EXTENSION_PROC_ARGS void *
77#include "extnsionst.h"
78
79#include "windowstr.h"	/* screenIsSaved */
80
81#include <stdarg.h>
82
83#include <X11/Xpoll.h>
84
85#include "mi.h"
86
87#include <ptrveloc.h>          /* dix pointer acceleration */
88
89#ifdef XFreeXDGA
90#include "dgaproc.h"
91#endif
92
93#ifdef XKB
94#include "xkbsrv.h"
95#endif
96
97#include "os.h"
98
99EventListPtr xf86Events = NULL;
100
101/**
102 * Eval config and modify DeviceVelocityRec accordingly
103 */
104static void
105ProcessVelocityConfiguration(char* devname, pointer list, DeviceVelocityPtr s){
106    int tempi, i;
107    float tempf, tempf2;
108
109    if(!s)
110        return;
111
112    tempf = xf86SetRealOption(list, "FilterHalflife", -1);
113    if(tempf > 0)
114        tempf = 1.0 / tempf;   /* set reciprocal if possible */
115
116    tempf2 = xf86SetRealOption(list, "FilterChainProgression", 2.0);
117    xf86Msg(X_CONFIG, "%s: (accel) filter chain progression: %.2f\n",
118            devname, tempf2);
119    if(tempf2 < 1)
120        tempf2 = 2;
121
122    tempi = xf86SetIntOption(list, "FilterChainLength", 1);
123    if(tempi < 1 || tempi > MAX_VELOCITY_FILTERS)
124	tempi = 1;
125
126    if(tempf > 0.0f && tempi >= 1 && tempf2 >= 1.0f)
127	InitFilterChain(s, tempf, tempf2, tempi, 40);
128
129    for(i = 0; i < tempi; i++)
130	xf86Msg(X_CONFIG, "%s: (accel) filter stage %i: %.2f ms\n",
131                devname, i, 1.0f / (s->filters[i].rdecay));
132
133    tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0);
134    if(tempf > 1.0){
135        xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n",
136                devname, tempf);
137        s->const_acceleration = 1.0 / tempf;   /* set reciprocal deceleration
138                                                  alias acceleration */
139    }
140
141    tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0);
142    if(tempf > 1.0){
143        xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n",
144                devname, tempf);
145        s->min_acceleration = 1.0 / tempf;   /* set minimum acceleration */
146    }
147
148    tempf = xf86SetRealOption(list, "VelocityCoupling", -1);
149    if(tempf >= 0){
150	xf86Msg(X_CONFIG, "%s: (accel) velocity coupling is %.1f%%\n", devname,
151                tempf*100.0);
152	s->coupling = tempf;
153    }
154
155    /*  Configure softening. If const deceleration is used, this is expected
156     *  to provide better subpixel information so we enable
157     *  softening by default only if ConstantDeceleration is not used
158     */
159    s->use_softening = xf86SetBoolOption(list, "Softening",
160                                         s->const_acceleration == 1.0);
161
162    s->average_accel = xf86SetBoolOption(list, "AccelerationProfileAveraging",
163                                         s->average_accel);
164
165    s->reset_time = xf86SetIntOption(list, "VelocityReset", s->reset_time);
166
167    tempf = xf86SetRealOption(list, "ExpectedRate", 0);
168    if(tempf > 0){
169        s->corr_mul = 1000.0 / tempf;
170    }else{
171        s->corr_mul = xf86SetRealOption(list, "VelocityScale", s->corr_mul);
172    }
173
174    /* select profile by number */
175    tempi= xf86SetIntOption(list, "AccelerationProfile",
176                            s->statistics.profile_number);
177
178    if(SetAccelerationProfile(s, tempi)){
179        xf86Msg(X_CONFIG, "%s: (accel) set acceleration profile %i\n", devname, tempi);
180    }else{
181        xf86Msg(X_CONFIG, "%s: (accel) acceleration profile %i is unknown\n",
182                devname, tempi);
183    }
184}
185
186static void
187ApplyAccelerationSettings(DeviceIntPtr dev){
188    int scheme;
189    DeviceVelocityPtr pVel;
190    LocalDevicePtr local = (LocalDevicePtr)dev->public.devicePrivate;
191    char* schemeStr;
192
193    if(dev->valuator){
194	schemeStr = xf86SetStrOption(local->options, "AccelerationScheme", "");
195
196	scheme = dev->valuator->accelScheme.number;
197
198	if(!xf86NameCmp(schemeStr, "predictable"))
199	    scheme = PtrAccelPredictable;
200
201	if(!xf86NameCmp(schemeStr, "lightweight"))
202	    scheme = PtrAccelLightweight;
203
204	if(!xf86NameCmp(schemeStr, "none"))
205	    scheme = PtrAccelNoOp;
206
207        /* reinit scheme if needed */
208        if(dev->valuator->accelScheme.number != scheme){
209            if(dev->valuator->accelScheme.AccelCleanupProc){
210                dev->valuator->accelScheme.AccelCleanupProc(dev);
211            }
212
213            if(InitPointerAccelerationScheme(dev, scheme)){
214		xf86Msg(X_CONFIG, "%s: (accel) selected scheme %s/%i\n",
215		        local->name, schemeStr, scheme);
216	    }else{
217        	xf86Msg(X_CONFIG, "%s: (accel) could not init scheme %s\n",
218        	        local->name, schemeStr);
219        	scheme = dev->valuator->accelScheme.number;
220            }
221        }else{
222            xf86Msg(X_CONFIG, "%s: (accel) keeping acceleration scheme %i\n",
223                    local->name, scheme);
224        }
225
226        xfree(schemeStr);
227
228        /* process special configuration */
229        switch(scheme){
230            case PtrAccelPredictable:
231                pVel = GetDevicePredictableAccelData(dev);
232                ProcessVelocityConfiguration (local->name, local->options,
233                                              pVel);
234                break;
235        }
236    }
237}
238
239static Bool
240xf86SendDragEvents(DeviceIntPtr	device)
241{
242    LocalDevicePtr local = (LocalDevicePtr) device->public.devicePrivate;
243
244    if (device->button && device->button->buttonsDown > 0)
245        return (local->flags & XI86_SEND_DRAG_EVENTS);
246    else
247        return (TRUE);
248}
249
250/***********************************************************************
251 *
252 * xf86ProcessCommonOptions --
253 *
254 *	Process global options.
255 *
256 ***********************************************************************
257 */
258_X_EXPORT void
259xf86ProcessCommonOptions(LocalDevicePtr local,
260                         pointer	list)
261{
262    if (!xf86SetBoolOption(list, "AlwaysCore", 1) ||
263        !xf86SetBoolOption(list, "SendCoreEvents", 1) ||
264        !xf86SetBoolOption(list, "CorePointer", 1) ||
265        !xf86SetBoolOption(list, "CoreKeyboard", 1)) {
266        xf86Msg(X_CONFIG, "%s: doesn't report core events\n", local->name);
267    } else {
268        local->flags |= XI86_ALWAYS_CORE;
269        xf86Msg(X_CONFIG, "%s: always reports core events\n", local->name);
270    }
271
272    if (xf86SetBoolOption(list, "SendDragEvents", 1)) {
273        local->flags |= XI86_SEND_DRAG_EVENTS;
274    } else {
275        xf86Msg(X_CONFIG, "%s: doesn't report drag events\n", local->name);
276    }
277
278    /* Backwards compatibility. */
279    local->history_size = GetMotionHistorySize();
280    /* Preallocate xEvent store */
281    if (!xf86Events)
282        GetEventList(&xf86Events);
283    if (!xf86Events)
284        FatalError("Couldn't allocate event store\n");
285}
286
287/***********************************************************************
288 *
289 * xf86ActivateDevice --
290 *
291 *	Initialize an input device.
292 *
293 * Returns TRUE on success, or FALSE otherwise.
294 ***********************************************************************
295 */
296_X_EXPORT int
297xf86ActivateDevice(LocalDevicePtr local)
298{
299    DeviceIntPtr	dev;
300
301    if (local->flags & XI86_CONFIGURED) {
302        dev = AddInputDevice(serverClient, local->device_control, TRUE);
303
304        if (dev == NULL)
305        {
306            xf86Msg(X_ERROR, "Too many input devices. Ignoring %s\n",
307                    local->name);
308            local->dev = NULL;
309            return FALSE;
310        }
311
312        local->atom = MakeAtom(local->type_name,
313                               strlen(local->type_name),
314                               TRUE);
315        AssignTypeAndName(dev, local->atom, local->name);
316        dev->public.devicePrivate = (pointer) local;
317        local->dev = dev;
318
319        dev->coreEvents = local->flags & XI86_ALWAYS_CORE;
320        dev->isMaster = FALSE;
321        dev->spriteInfo->spriteOwner = FALSE;
322
323        if (DeviceIsPointerType(dev))
324        {
325            dev->deviceGrab.ActivateGrab = ActivatePointerGrab;
326            dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
327        } else
328        {
329            dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
330            dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
331        }
332
333        RegisterOtherDevice(dev);
334#ifdef XKB
335        if (!noXkbExtension)
336            XkbSetExtension(dev, ProcessKeyboardEvent);
337#endif
338
339        if (serverGeneration == 1)
340            xf86Msg(X_INFO, "XINPUT: Adding extended input device \"%s\" (type: %s)\n",
341                    local->name, local->type_name);
342    }
343
344    return TRUE;
345}
346
347
348/***********************************************************************
349 *
350 * Caller:	ProcXOpenDevice
351 *
352 * This is the implementation-dependent routine to open an input device.
353 * Some implementations open all input devices when the server is first
354 * initialized, and never close them.  Other implementations open only
355 * the X pointer and keyboard devices during server initialization,
356 * and only open other input devices when some client makes an
357 * XOpenDevice request.  This entry point is for the latter type of
358 * implementation.
359 *
360 * If the physical device is not already open, do it here.  In this case,
361 * you need to keep track of the fact that one or more clients has the
362 * device open, and physically close it when the last client that has
363 * it open does an XCloseDevice.
364 *
365 * The default implementation is to do nothing (assume all input devices
366 * are opened during X server initialization and kept open).
367 *
368 ***********************************************************************
369 */
370
371void
372OpenInputDevice(DeviceIntPtr	dev,
373                ClientPtr	client,
374                int		*status)
375{
376    if (!dev->inited)
377        ActivateDevice(dev);
378
379    *status = Success;
380}
381
382void
383CloseInputDevice(DeviceIntPtr dev,
384                 ClientPtr client)
385{
386}
387
388/****************************************************************************
389 *
390 * Caller:	ProcXSetDeviceMode
391 *
392 * Change the mode of an extension device.
393 * This function is used to change the mode of a device from reporting
394 * relative motion to reporting absolute positional information, and
395 * vice versa.
396 * The default implementation below is that no such devices are supported.
397 *
398 ***********************************************************************
399 */
400
401int
402SetDeviceMode (ClientPtr client, DeviceIntPtr dev, int mode)
403{
404  LocalDevicePtr        local = (LocalDevicePtr)dev->public.devicePrivate;
405
406  if (local->switch_mode) {
407    return (*local->switch_mode)(client, dev, mode);
408  }
409  else
410    return BadMatch;
411}
412
413
414/***********************************************************************
415 *
416 * Caller:	ProcXSetDeviceValuators
417 *
418 * Set the value of valuators on an extension input device.
419 * This function is used to set the initial value of valuators on
420 * those input devices that are capable of reporting either relative
421 * motion or an absolute position, and allow an initial position to be set.
422 * The default implementation below is that no such devices are supported.
423 *
424 ***********************************************************************
425 */
426
427int
428SetDeviceValuators (ClientPtr client, DeviceIntPtr dev, int *valuators,
429                    int first_valuator, int num_valuators)
430{
431    LocalDevicePtr local = (LocalDevicePtr) dev->public.devicePrivate;
432
433    if (local->set_device_valuators)
434	return (*local->set_device_valuators)(local, valuators, first_valuator,
435					      num_valuators);
436
437    return BadMatch;
438}
439
440
441/***********************************************************************
442 *
443 * Caller:	ProcXChangeDeviceControl
444 *
445 * Change the specified device controls on an extension input device.
446 *
447 ***********************************************************************
448 */
449
450int
451ChangeDeviceControl (ClientPtr client, DeviceIntPtr dev, xDeviceCtl *control)
452{
453  LocalDevicePtr        local = (LocalDevicePtr)dev->public.devicePrivate;
454
455  if (!local->control_proc) {
456      switch (control->control) {
457      case DEVICE_CORE:
458          return BadMatch;
459      case DEVICE_RESOLUTION:
460      case DEVICE_ABS_CALIB:
461      case DEVICE_ABS_AREA:
462      case DEVICE_ENABLE:
463        return Success;
464      default:
465        return BadMatch;
466      }
467  }
468  else {
469      return (*local->control_proc)(local, control);
470  }
471}
472
473void
474AddOtherInputDevices()
475{
476}
477
478/**
479 * Create a new input device, activate and enable it.
480 *
481 * Possible return codes:
482 *    BadName .. a bad driver name was supplied.
483 *    BadImplementation ... The driver does not have a PreInit function. This
484 *                          is a driver bug.
485 *    BadMatch .. device initialization failed.
486 *    BadAlloc .. too many input devices
487 *
488 * @param idev The device, already set up with identifier, driver, and the
489 * options.
490 * @param pdev Pointer to the new device, if Success was reported.
491 * @param enable Enable the device after activating it.
492 *
493 * @return Success or an error code
494 */
495_X_INTERNAL int
496xf86NewInputDevice(IDevPtr idev, DeviceIntPtr *pdev, BOOL enable)
497{
498    InputDriverPtr drv = NULL;
499    InputInfoPtr pInfo = NULL;
500    DeviceIntPtr dev = NULL;
501    int rval;
502
503    /* Memory leak for every attached device if we don't
504     * test if the module is already loaded first */
505    drv = xf86LookupInputDriver(idev->driver);
506    if (!drv)
507        if (xf86LoadOneModule(idev->driver, NULL))
508            drv = xf86LookupInputDriver(idev->driver);
509    if (!drv) {
510        xf86Msg(X_ERROR, "No input driver matching `%s'\n", idev->driver);
511        rval = BadName;
512        goto unwind;
513    }
514
515    if (!drv->PreInit) {
516        xf86Msg(X_ERROR,
517                "Input driver `%s' has no PreInit function (ignoring)\n",
518                drv->driverName);
519        rval = BadImplementation;
520        goto unwind;
521    }
522
523    pInfo = drv->PreInit(drv, idev, 0);
524
525    if (!pInfo) {
526        xf86Msg(X_ERROR, "PreInit returned NULL for \"%s\"\n", idev->identifier);
527        rval = BadMatch;
528        goto unwind;
529    }
530    else if (!(pInfo->flags & XI86_CONFIGURED)) {
531        xf86Msg(X_ERROR, "PreInit failed for input device \"%s\"\n",
532                idev->identifier);
533        rval = BadMatch;
534        goto unwind;
535    }
536
537    if (!xf86ActivateDevice(pInfo))
538    {
539        rval = BadAlloc;
540        goto unwind;
541    }
542
543    dev = pInfo->dev;
544    rval = ActivateDevice(dev);
545    if (rval != Success)
546    {
547        xf86Msg(X_ERROR, "Couldn't init device \"%s\"\n", idev->identifier);
548        RemoveDevice(dev);
549        goto unwind;
550    }
551
552    /* Enable it if it's properly initialised and we're currently in the VT */
553    if (enable && dev->inited && dev->startup && xf86Screens[0]->vtSema)
554    {
555        EnableDevice(dev);
556        /* send enter/leave event, update sprite window */
557        CheckMotion(NULL, dev);
558    }
559
560    *pdev = dev;
561    return Success;
562
563unwind:
564    if(pInfo) {
565        if(drv->UnInit)
566            drv->UnInit(drv, pInfo, 0);
567        else
568            xf86DeleteInput(pInfo, 0);
569    }
570    return rval;
571}
572
573_X_EXPORT int
574NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev)
575{
576    IDevRec *idev = NULL;
577    InputOption *option = NULL;
578    int rval = Success;
579    int is_auto = 0;
580
581    idev = xcalloc(sizeof(*idev), 1);
582    if (!idev)
583        return BadAlloc;
584
585    for (option = options; option; option = option->next) {
586        if (strcasecmp(option->key, "driver") == 0) {
587            if (idev->driver) {
588                rval = BadRequest;
589                goto unwind;
590            }
591            idev->driver = xstrdup(option->value);
592            if (!idev->driver) {
593                rval = BadAlloc;
594                goto unwind;
595            }
596        }
597
598        if (strcasecmp(option->key, "name") == 0 ||
599            strcasecmp(option->key, "identifier") == 0) {
600            if (idev->identifier) {
601                rval = BadRequest;
602                goto unwind;
603            }
604            idev->identifier = xstrdup(option->value);
605            if (!idev->identifier) {
606                rval = BadAlloc;
607                goto unwind;
608            }
609        }
610
611        /* Right now, the only automatic config we know of is HAL. */
612        if (strcmp(option->key, "_source") == 0 &&
613            strcmp(option->value, "server/hal") == 0) {
614            if (!xf86Info.autoAddDevices) {
615                rval = BadMatch;
616                goto unwind;
617            }
618
619            is_auto = 1;
620        }
621    }
622    if (!idev->driver || !idev->identifier) {
623        xf86Msg(X_ERROR, "No input driver/identifier specified (ignoring)\n");
624        rval = BadRequest;
625        goto unwind;
626    }
627
628    if (!idev->identifier) {
629        xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n");
630        return BadMatch;
631    }
632
633    for (option = options; option; option = option->next) {
634        /* Steal option key/value strings from the provided list.
635         * We need those strings, the InputOption list doesn't. */
636        idev->commonOptions = xf86addNewOption(idev->commonOptions,
637                                               option->key, option->value);
638        option->key = NULL;
639        option->value = NULL;
640    }
641
642    rval = xf86NewInputDevice(idev, pdev,
643                (!is_auto || (is_auto && xf86Info.autoEnableDevices)));
644    if (rval == Success)
645        return Success;
646
647unwind:
648    if(idev->driver)
649        xfree(idev->driver);
650    if(idev->identifier)
651        xfree(idev->identifier);
652    xf86optionListFree(idev->commonOptions);
653    xfree(idev);
654    return rval;
655}
656
657_X_EXPORT void
658DeleteInputDeviceRequest(DeviceIntPtr pDev)
659{
660    LocalDevicePtr pInfo = (LocalDevicePtr) pDev->public.devicePrivate;
661    InputDriverPtr drv = NULL;
662    IDevRec *idev = NULL;
663    IDevPtr *it;
664    Bool isMaster = pDev->isMaster;
665
666    if (pInfo) /* need to get these before RemoveDevice */
667    {
668        drv = pInfo->drv;
669        idev = pInfo->conf_idev;
670    }
671
672    OsBlockSignals();
673    RemoveDevice(pDev);
674
675    if (!isMaster)
676    {
677        if(drv->UnInit)
678            drv->UnInit(drv, pInfo, 0);
679        else
680            xf86DeleteInput(pInfo, 0);
681
682        /* devices added through HAL aren't in the config layout */
683        it = xf86ConfigLayout.inputs;
684        while(*it && *it != idev)
685            it++;
686
687        if (!(*it)) /* end of list, not in the layout */
688        {
689            xfree(idev->driver);
690            xfree(idev->identifier);
691            xf86optionListFree(idev->commonOptions);
692            xfree(idev);
693        }
694    }
695    OsReleaseSignals();
696}
697
698/*
699 * convenient functions to post events
700 */
701
702_X_EXPORT void
703xf86PostMotionEvent(DeviceIntPtr	device,
704                    int			is_absolute,
705                    int			first_valuator,
706                    int			num_valuators,
707                    ...)
708{
709    va_list var;
710    int i = 0;
711    static int valuators[MAX_VALUATORS];
712
713    if (num_valuators > MAX_VALUATORS) {
714	xf86Msg(X_ERROR, "%s: num_valuator %d is greater than"
715	    " MAX_VALUATORS\n", __FUNCTION__, num_valuators);
716	return;
717    }
718
719    va_start(var, num_valuators);
720    for (i = 0; i < num_valuators; i++)
721        valuators[i] = va_arg(var, int);
722    va_end(var);
723
724    xf86PostMotionEventP(device, is_absolute, first_valuator, num_valuators, valuators);
725}
726
727_X_EXPORT void
728xf86PostMotionEventP(DeviceIntPtr	device,
729                    int			is_absolute,
730                    int			first_valuator,
731                    int			num_valuators,
732                    int			*valuators)
733{
734    int i = 0, nevents = 0;
735    int dx = 0, dy = 0;
736    Bool drag = xf86SendDragEvents(device);
737    xEvent *xE = NULL;
738    int index;
739    int flags = 0;
740
741    if (num_valuators > MAX_VALUATORS) {
742	xf86Msg(X_ERROR, "%s: num_valuator %d is greater than"
743	    " MAX_VALUATORS\n", __FUNCTION__, num_valuators);
744	return;
745    }
746
747    if (is_absolute)
748        flags = POINTER_ABSOLUTE;
749    else
750        flags = POINTER_RELATIVE | POINTER_ACCELERATE;
751
752#if XFreeXDGA
753    /* The evdev driver may not always send all axes across. */
754    if (num_valuators >= 1 && first_valuator <= 1) {
755        if (miPointerGetScreen(device)) {
756            index = miPointerGetScreen(device)->myNum;
757            if (first_valuator == 0)
758            {
759                dx = valuators[0];
760                if (is_absolute)
761                    dx -= device->last.valuators[0];
762            }
763
764            if (first_valuator == 1 || num_valuators >= 2)
765            {
766                dy = valuators[1 - first_valuator];
767                if (is_absolute)
768                    dy -= device->last.valuators[1];
769            }
770
771            if (DGAStealMotionEvent(device, index, dx, dy))
772                return;
773        }
774    }
775#endif
776
777    GetEventList(&xf86Events);
778    nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0,
779                               flags, first_valuator, num_valuators,
780                               valuators);
781
782    for (i = 0; i < nevents; i++) {
783        xE = (xf86Events + i)->event;
784        /* Don't post core motion events for devices not registered to send
785         * drag events. */
786        if (xE->u.u.type != MotionNotify || drag) {
787            mieqEnqueue(device, (xf86Events + i)->event);
788        }
789    }
790}
791
792_X_EXPORT void
793xf86PostProximityEvent(DeviceIntPtr	device,
794                       int		is_in,
795                       int		first_valuator,
796                       int		num_valuators,
797                       ...)
798{
799    va_list var;
800    int i, nevents;
801    int valuators[MAX_VALUATORS];
802
803
804    if (num_valuators > MAX_VALUATORS) {
805	xf86Msg(X_ERROR, "%s: num_valuator %d is greater than"
806	    " MAX_VALUATORS\n", __FUNCTION__, num_valuators);
807	return;
808    }
809
810    va_start(var, num_valuators);
811    for (i = 0; i < num_valuators; i++)
812        valuators[i] = va_arg(var, int);
813    va_end(var);
814
815    GetEventList(&xf86Events);
816    nevents = GetProximityEvents(xf86Events, device,
817                                 is_in ? ProximityIn : ProximityOut,
818                                 first_valuator, num_valuators, valuators);
819    for (i = 0; i < nevents; i++)
820        mieqEnqueue(device, (xf86Events + i)->event);
821
822}
823
824_X_EXPORT void
825xf86PostButtonEvent(DeviceIntPtr	device,
826                    int			is_absolute,
827                    int			button,
828                    int			is_down,
829                    int			first_valuator,
830                    int			num_valuators,
831                    ...)
832{
833    va_list var;
834    int valuators[MAX_VALUATORS];
835    int i = 0, nevents = 0;
836    int index;
837
838#if XFreeXDGA
839    if (miPointerGetScreen(device)) {
840        index = miPointerGetScreen(device)->myNum;
841        if (DGAStealButtonEvent(device, index, button, is_down))
842            return;
843    }
844#endif
845    if (num_valuators > MAX_VALUATORS) {
846	xf86Msg(X_ERROR, "%s: num_valuator %d is greater than"
847	    " MAX_VALUATORS\n", __FUNCTION__, num_valuators);
848	return;
849    }
850
851    va_start(var, num_valuators);
852    for (i = 0; i < num_valuators; i++)
853        valuators[i] = va_arg(var, int);
854    va_end(var);
855
856    GetEventList(&xf86Events);
857    nevents = GetPointerEvents(xf86Events, device,
858                               is_down ? ButtonPress : ButtonRelease, button,
859                               (is_absolute) ? POINTER_ABSOLUTE : POINTER_RELATIVE,
860                               first_valuator, num_valuators, valuators);
861
862    for (i = 0; i < nevents; i++)
863        mieqEnqueue(device, (xf86Events + i)->event);
864
865}
866
867_X_EXPORT void
868xf86PostKeyEvent(DeviceIntPtr	device,
869                 unsigned int	key_code,
870                 int		is_down,
871                 int		is_absolute,
872                 int		first_valuator,
873                 int		num_valuators,
874                 ...)
875{
876    va_list var;
877    int i = 0, nevents = 0;
878    static int valuators[MAX_VALUATORS];
879
880    /* instil confidence in the user */
881    DebugF("this function has never been tested properly.  if things go quite "
882           "badly south after this message, then xf86PostKeyEvent is "
883           "broken.\n");
884
885    if (num_valuators > MAX_VALUATORS) {
886	xf86Msg(X_ERROR, "%s: num_valuator %d is greater than"
887	    " MAX_VALUATORS\n", __FUNCTION__, num_valuators);
888	return;
889    }
890
891    if (is_absolute) {
892        va_start(var, num_valuators);
893        for (i = 0; i < num_valuators; i++)
894            valuators[i] = va_arg(var, int);
895        va_end(var);
896
897        GetEventList(&xf86Events);
898        nevents = GetKeyboardValuatorEvents(xf86Events, device,
899                                            is_down ? KeyPress : KeyRelease,
900                                            key_code, first_valuator,
901                                            num_valuators, valuators);
902    }
903    else {
904        nevents = GetKeyboardEvents(xf86Events, device,
905                                    is_down ? KeyPress : KeyRelease,
906                                    key_code);
907    }
908
909    for (i = 0; i < nevents; i++)
910        mieqEnqueue(device, (xf86Events + i)->event);
911}
912
913_X_EXPORT void
914xf86PostKeyboardEvent(DeviceIntPtr      device,
915                      unsigned int      key_code,
916                      int               is_down)
917{
918    int nevents = 0, i = 0;
919    int index;
920
921#if XFreeXDGA
922    DeviceIntPtr pointer;
923
924    /* Some pointers send key events, paired device is wrong then. */
925    pointer = IsPointerDevice(device) ? device : GetPairedDevice(device);
926
927    if (miPointerGetScreen(pointer)) {
928        index = miPointerGetScreen(pointer)->myNum;
929        if (DGAStealKeyEvent(device, index, key_code, is_down))
930            return;
931    }
932#endif
933
934    GetEventList(&xf86Events);
935    nevents = GetKeyboardEvents(xf86Events, device,
936                                is_down ? KeyPress : KeyRelease, key_code);
937
938    for (i = 0; i < nevents; i++)
939        mieqEnqueue(device, (xf86Events + i)->event);
940}
941
942_X_EXPORT LocalDevicePtr
943xf86FirstLocalDevice()
944{
945    return xf86InputDevs;
946}
947
948/*
949 * Cx     - raw data from touch screen
950 * Sxhigh - scaled highest dimension
951 *          (remember, this is of rows - 1 because of 0 origin)
952 * Sxlow  - scaled lowest dimension
953 * Rxhigh - highest raw value from touch screen calibration
954 * Rxlow  - lowest raw value from touch screen calibration
955 *
956 * This function is the same for X or Y coordinates.
957 * You may have to reverse the high and low values to compensate for
958 * different orgins on the touch screen vs X.
959 */
960
961_X_EXPORT int
962xf86ScaleAxis(int	Cx,
963              int	Sxhigh,
964              int	Sxlow,
965              int	Rxhigh,
966              int	Rxlow )
967{
968    int X;
969    int dSx = Sxhigh - Sxlow;
970    int dRx = Rxhigh - Rxlow;
971
972    dSx = Sxhigh - Sxlow;
973    if (dRx) {
974	X = ((dSx * (Cx - Rxlow)) / dRx) + Sxlow;
975    }
976    else {
977	X = 0;
978	ErrorF ("Divide by Zero in xf86ScaleAxis");
979    }
980
981    if (X > Sxhigh)
982	X = Sxhigh;
983    if (X < Sxlow)
984	X = Sxlow;
985
986    return (X);
987}
988
989/*
990 * This function checks the given screen against the current screen and
991 * makes changes if appropriate. It should be called from an XInput driver's
992 * ReadInput function before any events are posted, if the device is screen
993 * specific like a touch screen.
994 */
995_X_EXPORT void
996xf86XInputSetScreen(LocalDevicePtr	local,
997		    int			screen_number,
998		    int			x,
999		    int			y)
1000{
1001    if (miPointerGetScreen(local->dev) !=
1002          screenInfo.screens[screen_number]) {
1003	miPointerSetScreen(local->dev, screen_number, x, y);
1004    }
1005}
1006
1007
1008_X_EXPORT void
1009xf86InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
1010			   int resolution, int min_res, int max_res)
1011{
1012    if (!dev || !dev->valuator)
1013        return;
1014
1015    InitValuatorAxisStruct(dev, axnum, minval, maxval, resolution, min_res,
1016			   max_res);
1017}
1018
1019/*
1020 * Set the valuator values to be in synch with dix/event.c
1021 * DefineInitialRootWindow().
1022 */
1023_X_EXPORT void
1024xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum)
1025{
1026    if (axnum == 0) {
1027	dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
1028        dev->last.valuators[0] = dev->valuator->axisVal[0];
1029    }
1030    else if (axnum == 1) {
1031	dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
1032        dev->last.valuators[1] = dev->valuator->axisVal[1];
1033    }
1034
1035    if(axnum == 0)  /* to prevent double invocation */
1036	ApplyAccelerationSettings(dev);
1037}
1038
1039
1040/**
1041 * Deactivate a device. Call this function from the driver if you receive a
1042 * read error or something else that spoils your day.
1043 * Device will be moved to the off_devices list, but it will still be there
1044 * until you really clean up after it.
1045 * Notifies the client about an inactive device.
1046 *
1047 * @param panic True if device is unrecoverable and needs to be removed.
1048 */
1049_X_EXPORT void
1050xf86DisableDevice(DeviceIntPtr dev, Bool panic)
1051{
1052    devicePresenceNotify ev;
1053    DeviceIntRec dummyDev;
1054
1055    if(!panic)
1056    {
1057        DisableDevice(dev);
1058    } else
1059    {
1060        ev.type = DevicePresenceNotify;
1061        ev.time = currentTime.milliseconds;
1062        ev.devchange = DeviceUnrecoverable;
1063        ev.deviceid = dev->id;
1064        dummyDev.id = 0;
1065        SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
1066                (xEvent *) &ev, 1);
1067
1068        DeleteInputDeviceRequest(dev);
1069    }
1070}
1071
1072/**
1073 * Reactivate a device. Call this function from the driver if you just found
1074 * out that the read error wasn't quite that bad after all.
1075 * Device will be re-activated, and an event sent to the client.
1076 */
1077_X_EXPORT void
1078xf86EnableDevice(DeviceIntPtr dev)
1079{
1080    EnableDevice(dev);
1081}
1082
1083/* end of xf86Xinput.c */
1084