xref: /OK3568_Linux_fs/external/xserver/dix/getevents.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2006 Nokia Corporation
3*4882a593Smuzhiyun  * Copyright © 2006-2007 Daniel Stone
4*4882a593Smuzhiyun  * Copyright © 2008 Red Hat, Inc.
5*4882a593Smuzhiyun  * Copyright © 2011 The Chromium Authors
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
8*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
9*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
10*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
12*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the next
15*4882a593Smuzhiyun  * paragraph) shall be included in all copies or substantial portions of the
16*4882a593Smuzhiyun  * Software.
17*4882a593Smuzhiyun  *
18*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21*4882a593Smuzhiyun  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * Authors: Daniel Stone <daniel@fooishbar.org>
27*4882a593Smuzhiyun  *          Peter Hutterer <peter.hutterer@who-t.net>
28*4882a593Smuzhiyun  */
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
31*4882a593Smuzhiyun #include <dix-config.h>
32*4882a593Smuzhiyun #endif
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include <X11/X.h>
35*4882a593Smuzhiyun #include <X11/keysym.h>
36*4882a593Smuzhiyun #include <X11/Xproto.h>
37*4882a593Smuzhiyun #include <math.h>
38*4882a593Smuzhiyun #include <limits.h>
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #include "misc.h"
41*4882a593Smuzhiyun #include "resource.h"
42*4882a593Smuzhiyun #include "inputstr.h"
43*4882a593Smuzhiyun #include "scrnintstr.h"
44*4882a593Smuzhiyun #include "cursorstr.h"
45*4882a593Smuzhiyun #include "dixstruct.h"
46*4882a593Smuzhiyun #include "globals.h"
47*4882a593Smuzhiyun #include "dixevents.h"
48*4882a593Smuzhiyun #include "mipointer.h"
49*4882a593Smuzhiyun #include "eventstr.h"
50*4882a593Smuzhiyun #include "eventconvert.h"
51*4882a593Smuzhiyun #include "inpututils.h"
52*4882a593Smuzhiyun #include "mi.h"
53*4882a593Smuzhiyun #include "windowstr.h"
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #include <X11/extensions/XKBproto.h>
56*4882a593Smuzhiyun #include "xkbsrv.h"
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun #ifdef PANORAMIX
59*4882a593Smuzhiyun #include "panoramiX.h"
60*4882a593Smuzhiyun #include "panoramiXsrv.h"
61*4882a593Smuzhiyun #endif
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #include <X11/extensions/XI.h>
64*4882a593Smuzhiyun #include <X11/extensions/XI2.h>
65*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
66*4882a593Smuzhiyun #include <pixman.h>
67*4882a593Smuzhiyun #include "exglobals.h"
68*4882a593Smuzhiyun #include "exevents.h"
69*4882a593Smuzhiyun #include "extnsionst.h"
70*4882a593Smuzhiyun #include "listdev.h"            /* for sizing up DeviceClassesChangedEvent */
71*4882a593Smuzhiyun #include "probes.h"
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun /* Number of motion history events to store. */
74*4882a593Smuzhiyun #define MOTION_HISTORY_SIZE 256
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun /**
77*4882a593Smuzhiyun  * InputEventList is the storage for input events generated by
78*4882a593Smuzhiyun  * QueuePointerEvents, QueueKeyboardEvents, and QueueProximityEvents.
79*4882a593Smuzhiyun  * This list is allocated on startup by the DIX.
80*4882a593Smuzhiyun  */
81*4882a593Smuzhiyun InternalEvent *InputEventList = NULL;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun /**
84*4882a593Smuzhiyun  * Pick some arbitrary size for Xi motion history.
85*4882a593Smuzhiyun  */
86*4882a593Smuzhiyun int
GetMotionHistorySize(void)87*4882a593Smuzhiyun GetMotionHistorySize(void)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun     return MOTION_HISTORY_SIZE;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun void
set_button_down(DeviceIntPtr pDev,int button,int type)93*4882a593Smuzhiyun set_button_down(DeviceIntPtr pDev, int button, int type)
94*4882a593Smuzhiyun {
95*4882a593Smuzhiyun     if (type == BUTTON_PROCESSED)
96*4882a593Smuzhiyun         SetBit(pDev->button->down, button);
97*4882a593Smuzhiyun     else
98*4882a593Smuzhiyun         SetBit(pDev->button->postdown, button);
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun void
set_button_up(DeviceIntPtr pDev,int button,int type)102*4882a593Smuzhiyun set_button_up(DeviceIntPtr pDev, int button, int type)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun     if (type == BUTTON_PROCESSED)
105*4882a593Smuzhiyun         ClearBit(pDev->button->down, button);
106*4882a593Smuzhiyun     else
107*4882a593Smuzhiyun         ClearBit(pDev->button->postdown, button);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun Bool
button_is_down(DeviceIntPtr pDev,int button,int type)111*4882a593Smuzhiyun button_is_down(DeviceIntPtr pDev, int button, int type)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     Bool ret = FALSE;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun     if (type & BUTTON_PROCESSED)
116*4882a593Smuzhiyun         ret = ret || BitIsOn(pDev->button->down, button);
117*4882a593Smuzhiyun     if (type & BUTTON_POSTED)
118*4882a593Smuzhiyun         ret = ret || BitIsOn(pDev->button->postdown, button);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun     return ret;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun void
set_key_down(DeviceIntPtr pDev,int key_code,int type)124*4882a593Smuzhiyun set_key_down(DeviceIntPtr pDev, int key_code, int type)
125*4882a593Smuzhiyun {
126*4882a593Smuzhiyun     if (type == KEY_PROCESSED)
127*4882a593Smuzhiyun         SetBit(pDev->key->down, key_code);
128*4882a593Smuzhiyun     else
129*4882a593Smuzhiyun         SetBit(pDev->key->postdown, key_code);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun void
set_key_up(DeviceIntPtr pDev,int key_code,int type)133*4882a593Smuzhiyun set_key_up(DeviceIntPtr pDev, int key_code, int type)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun     if (type == KEY_PROCESSED)
136*4882a593Smuzhiyun         ClearBit(pDev->key->down, key_code);
137*4882a593Smuzhiyun     else
138*4882a593Smuzhiyun         ClearBit(pDev->key->postdown, key_code);
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun Bool
key_is_down(DeviceIntPtr pDev,int key_code,int type)142*4882a593Smuzhiyun key_is_down(DeviceIntPtr pDev, int key_code, int type)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun     Bool ret = FALSE;
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun     if (type & KEY_PROCESSED)
147*4882a593Smuzhiyun         ret = ret || BitIsOn(pDev->key->down, key_code);
148*4882a593Smuzhiyun     if (type & KEY_POSTED)
149*4882a593Smuzhiyun         ret = ret || BitIsOn(pDev->key->postdown, key_code);
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun     return ret;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun static Bool
key_autorepeats(DeviceIntPtr pDev,int key_code)155*4882a593Smuzhiyun key_autorepeats(DeviceIntPtr pDev, int key_code)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun     return ! !(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
158*4882a593Smuzhiyun                (1 << (key_code & 7)));
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun static void
init_touch_ownership(DeviceIntPtr dev,TouchOwnershipEvent * event,Time ms)162*4882a593Smuzhiyun init_touch_ownership(DeviceIntPtr dev, TouchOwnershipEvent *event, Time ms)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun     memset(event, 0, sizeof(TouchOwnershipEvent));
165*4882a593Smuzhiyun     event->header = ET_Internal;
166*4882a593Smuzhiyun     event->type = ET_TouchOwnership;
167*4882a593Smuzhiyun     event->length = sizeof(TouchOwnershipEvent);
168*4882a593Smuzhiyun     event->time = ms;
169*4882a593Smuzhiyun     event->deviceid = dev->id;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static void
init_raw(DeviceIntPtr dev,RawDeviceEvent * event,Time ms,int type,int detail)173*4882a593Smuzhiyun init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun     memset(event, 0, sizeof(RawDeviceEvent));
176*4882a593Smuzhiyun     event->header = ET_Internal;
177*4882a593Smuzhiyun     event->length = sizeof(RawDeviceEvent);
178*4882a593Smuzhiyun     switch (type) {
179*4882a593Smuzhiyun     case MotionNotify:
180*4882a593Smuzhiyun         event->type = ET_RawMotion;
181*4882a593Smuzhiyun         break;
182*4882a593Smuzhiyun     case ButtonPress:
183*4882a593Smuzhiyun         event->type = ET_RawButtonPress;
184*4882a593Smuzhiyun         break;
185*4882a593Smuzhiyun     case ButtonRelease:
186*4882a593Smuzhiyun         event->type = ET_RawButtonRelease;
187*4882a593Smuzhiyun         break;
188*4882a593Smuzhiyun     case KeyPress:
189*4882a593Smuzhiyun         event->type = ET_RawKeyPress;
190*4882a593Smuzhiyun         break;
191*4882a593Smuzhiyun     case KeyRelease:
192*4882a593Smuzhiyun         event->type = ET_RawKeyRelease;
193*4882a593Smuzhiyun         break;
194*4882a593Smuzhiyun     case XI_TouchBegin:
195*4882a593Smuzhiyun         event->type = ET_RawTouchBegin;
196*4882a593Smuzhiyun         break;
197*4882a593Smuzhiyun     case XI_TouchUpdate:
198*4882a593Smuzhiyun         event->type = ET_RawTouchUpdate;
199*4882a593Smuzhiyun         break;
200*4882a593Smuzhiyun     case XI_TouchEnd:
201*4882a593Smuzhiyun         event->type = ET_RawTouchEnd;
202*4882a593Smuzhiyun         break;
203*4882a593Smuzhiyun     }
204*4882a593Smuzhiyun     event->time = ms;
205*4882a593Smuzhiyun     event->deviceid = dev->id;
206*4882a593Smuzhiyun     event->sourceid = dev->id;
207*4882a593Smuzhiyun     event->detail.button = detail;
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static void
set_raw_valuators(RawDeviceEvent * event,ValuatorMask * mask,BOOL use_unaccel,double * data)211*4882a593Smuzhiyun set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask,
212*4882a593Smuzhiyun                   BOOL use_unaccel, double *data)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun     int i;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     use_unaccel = use_unaccel && valuator_mask_has_unaccelerated(mask);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++) {
219*4882a593Smuzhiyun         if (valuator_mask_isset(mask, i)) {
220*4882a593Smuzhiyun             double v;
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun             SetBit(event->valuators.mask, i);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun             if (use_unaccel)
225*4882a593Smuzhiyun                 v = valuator_mask_get_unaccelerated(mask, i);
226*4882a593Smuzhiyun             else
227*4882a593Smuzhiyun                 v = valuator_mask_get_double(mask, i);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun             data[i] = v;
230*4882a593Smuzhiyun         }
231*4882a593Smuzhiyun     }
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun static void
set_valuators(DeviceIntPtr dev,DeviceEvent * event,ValuatorMask * mask)235*4882a593Smuzhiyun set_valuators(DeviceIntPtr dev, DeviceEvent *event, ValuatorMask *mask)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun     int i;
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun     /* Set the data to the previous value for unset absolute axes. The values
240*4882a593Smuzhiyun      * may be used when sent as part of an XI 1.x valuator event. */
241*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++) {
242*4882a593Smuzhiyun         if (valuator_mask_isset(mask, i)) {
243*4882a593Smuzhiyun             SetBit(event->valuators.mask, i);
244*4882a593Smuzhiyun             if (valuator_get_mode(dev, i) == Absolute)
245*4882a593Smuzhiyun                 SetBit(event->valuators.mode, i);
246*4882a593Smuzhiyun             event->valuators.data[i] = valuator_mask_get_double(mask, i);
247*4882a593Smuzhiyun         }
248*4882a593Smuzhiyun         else
249*4882a593Smuzhiyun             event->valuators.data[i] = dev->valuator->axisVal[i];
250*4882a593Smuzhiyun     }
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun void
CreateClassesChangedEvent(InternalEvent * event,DeviceIntPtr master,DeviceIntPtr slave,int flags)254*4882a593Smuzhiyun CreateClassesChangedEvent(InternalEvent *event,
255*4882a593Smuzhiyun                           DeviceIntPtr master, DeviceIntPtr slave, int flags)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun     int i;
258*4882a593Smuzhiyun     DeviceChangedEvent *dce;
259*4882a593Smuzhiyun     CARD32 ms = GetTimeInMillis();
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun     dce = &event->changed_event;
262*4882a593Smuzhiyun     memset(dce, 0, sizeof(DeviceChangedEvent));
263*4882a593Smuzhiyun     dce->deviceid = slave->id;
264*4882a593Smuzhiyun     dce->masterid = master ? master->id : 0;
265*4882a593Smuzhiyun     dce->header = ET_Internal;
266*4882a593Smuzhiyun     dce->length = sizeof(DeviceChangedEvent);
267*4882a593Smuzhiyun     dce->type = ET_DeviceChanged;
268*4882a593Smuzhiyun     dce->time = ms;
269*4882a593Smuzhiyun     dce->flags = flags;
270*4882a593Smuzhiyun     dce->sourceid = slave->id;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun     if (slave->button) {
273*4882a593Smuzhiyun         dce->buttons.num_buttons = slave->button->numButtons;
274*4882a593Smuzhiyun         for (i = 0; i < dce->buttons.num_buttons; i++)
275*4882a593Smuzhiyun             dce->buttons.names[i] = slave->button->labels[i];
276*4882a593Smuzhiyun     }
277*4882a593Smuzhiyun     if (slave->valuator) {
278*4882a593Smuzhiyun         dce->num_valuators = slave->valuator->numAxes;
279*4882a593Smuzhiyun         for (i = 0; i < dce->num_valuators; i++) {
280*4882a593Smuzhiyun             dce->valuators[i].min = slave->valuator->axes[i].min_value;
281*4882a593Smuzhiyun             dce->valuators[i].max = slave->valuator->axes[i].max_value;
282*4882a593Smuzhiyun             dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
283*4882a593Smuzhiyun             dce->valuators[i].mode = slave->valuator->axes[i].mode;
284*4882a593Smuzhiyun             dce->valuators[i].name = slave->valuator->axes[i].label;
285*4882a593Smuzhiyun             dce->valuators[i].scroll = slave->valuator->axes[i].scroll;
286*4882a593Smuzhiyun             dce->valuators[i].value = slave->valuator->axisVal[i];
287*4882a593Smuzhiyun         }
288*4882a593Smuzhiyun     }
289*4882a593Smuzhiyun     if (slave->key) {
290*4882a593Smuzhiyun         dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
291*4882a593Smuzhiyun         dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
292*4882a593Smuzhiyun     }
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun /**
296*4882a593Smuzhiyun  * Rescale the coord between the two axis ranges.
297*4882a593Smuzhiyun  */
298*4882a593Smuzhiyun static double
rescaleValuatorAxis(double coord,AxisInfoPtr from,AxisInfoPtr to,double defmin,double defmax)299*4882a593Smuzhiyun rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
300*4882a593Smuzhiyun                     double defmin, double defmax)
301*4882a593Smuzhiyun {
302*4882a593Smuzhiyun     double fmin = defmin, fmax = defmax;
303*4882a593Smuzhiyun     double tmin = defmin, tmax = defmax;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (from && from->min_value < from->max_value) {
306*4882a593Smuzhiyun         fmin = from->min_value;
307*4882a593Smuzhiyun         fmax = from->max_value + 1;
308*4882a593Smuzhiyun     }
309*4882a593Smuzhiyun     if (to && to->min_value < to->max_value) {
310*4882a593Smuzhiyun         tmin = to->min_value;
311*4882a593Smuzhiyun         tmax = to->max_value + 1;
312*4882a593Smuzhiyun     }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun     if (fmin == tmin && fmax == tmax)
315*4882a593Smuzhiyun         return coord;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun     if (fmax == fmin)           /* avoid division by 0 */
318*4882a593Smuzhiyun         return 0.0;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun     return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun 
323*4882a593Smuzhiyun /**
324*4882a593Smuzhiyun  * Update all coordinates when changing to a different SD
325*4882a593Smuzhiyun  * to ensure that relative reporting will work as expected
326*4882a593Smuzhiyun  * without loss of precision.
327*4882a593Smuzhiyun  *
328*4882a593Smuzhiyun  * pDev->last.valuators will be in absolute device coordinates after this
329*4882a593Smuzhiyun  * function.
330*4882a593Smuzhiyun  */
331*4882a593Smuzhiyun static void
updateSlaveDeviceCoords(DeviceIntPtr master,DeviceIntPtr pDev)332*4882a593Smuzhiyun updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
333*4882a593Smuzhiyun {
334*4882a593Smuzhiyun     /* master->last.valuators[0]/[1] is in desktop-wide coords and the actual
335*4882a593Smuzhiyun      * position of the pointer */
336*4882a593Smuzhiyun     pDev->last.valuators[0] = master->last.valuators[0];
337*4882a593Smuzhiyun     pDev->last.valuators[1] = master->last.valuators[1];
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun     if (!pDev->valuator)
340*4882a593Smuzhiyun         return;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun     /* scale back to device coordinates */
343*4882a593Smuzhiyun     if (pDev->valuator->numAxes > 0) {
344*4882a593Smuzhiyun         pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
345*4882a593Smuzhiyun                                                       NULL,
346*4882a593Smuzhiyun                                                       pDev->valuator->axes + 0,
347*4882a593Smuzhiyun                                                       screenInfo.x,
348*4882a593Smuzhiyun                                                       screenInfo.width);
349*4882a593Smuzhiyun     }
350*4882a593Smuzhiyun     if (pDev->valuator->numAxes > 1) {
351*4882a593Smuzhiyun         pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
352*4882a593Smuzhiyun                                                       NULL,
353*4882a593Smuzhiyun                                                       pDev->valuator->axes + 1,
354*4882a593Smuzhiyun                                                       screenInfo.y,
355*4882a593Smuzhiyun                                                       screenInfo.height);
356*4882a593Smuzhiyun     }
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun     /* other axes are left as-is */
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun /**
362*4882a593Smuzhiyun  * Allocate the motion history buffer.
363*4882a593Smuzhiyun  */
364*4882a593Smuzhiyun void
AllocateMotionHistory(DeviceIntPtr pDev)365*4882a593Smuzhiyun AllocateMotionHistory(DeviceIntPtr pDev)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun     int size;
368*4882a593Smuzhiyun 
369*4882a593Smuzhiyun     free(pDev->valuator->motion);
370*4882a593Smuzhiyun 
371*4882a593Smuzhiyun     if (pDev->valuator->numMotionEvents < 1)
372*4882a593Smuzhiyun         return;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun     /* An MD must have a motion history size large enough to keep all
375*4882a593Smuzhiyun      * potential valuators, plus the respective range of the valuators.
376*4882a593Smuzhiyun      * 3 * INT32 for (min_val, max_val, curr_val))
377*4882a593Smuzhiyun      */
378*4882a593Smuzhiyun     if (IsMaster(pDev))
379*4882a593Smuzhiyun         size = sizeof(INT32) * 3 * MAX_VALUATORS;
380*4882a593Smuzhiyun     else {
381*4882a593Smuzhiyun         ValuatorClassPtr v = pDev->valuator;
382*4882a593Smuzhiyun         int numAxes;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun         /* XI1 doesn't understand mixed mode devices */
385*4882a593Smuzhiyun         for (numAxes = 0; numAxes < v->numAxes; numAxes++)
386*4882a593Smuzhiyun             if (valuator_get_mode(pDev, numAxes) != valuator_get_mode(pDev, 0))
387*4882a593Smuzhiyun                 break;
388*4882a593Smuzhiyun         size = sizeof(INT32) * numAxes;
389*4882a593Smuzhiyun     }
390*4882a593Smuzhiyun 
391*4882a593Smuzhiyun     size += sizeof(Time);
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun     pDev->valuator->motion = calloc(pDev->valuator->numMotionEvents, size);
394*4882a593Smuzhiyun     pDev->valuator->first_motion = 0;
395*4882a593Smuzhiyun     pDev->valuator->last_motion = 0;
396*4882a593Smuzhiyun     if (!pDev->valuator->motion)
397*4882a593Smuzhiyun         ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
398*4882a593Smuzhiyun                pDev->name, size * pDev->valuator->numMotionEvents);
399*4882a593Smuzhiyun }
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun /**
402*4882a593Smuzhiyun  * Dump the motion history between start and stop into the supplied buffer.
403*4882a593Smuzhiyun  * Only records the event for a given screen in theory, but in practice, we
404*4882a593Smuzhiyun  * sort of ignore this.
405*4882a593Smuzhiyun  *
406*4882a593Smuzhiyun  * If core is set, we only generate x/y, in INT16, scaled to screen coords.
407*4882a593Smuzhiyun  */
408*4882a593Smuzhiyun int
GetMotionHistory(DeviceIntPtr pDev,xTimecoord ** buff,unsigned long start,unsigned long stop,ScreenPtr pScreen,BOOL core)409*4882a593Smuzhiyun GetMotionHistory(DeviceIntPtr pDev, xTimecoord ** buff, unsigned long start,
410*4882a593Smuzhiyun                  unsigned long stop, ScreenPtr pScreen, BOOL core)
411*4882a593Smuzhiyun {
412*4882a593Smuzhiyun     char *ibuff = NULL, *obuff;
413*4882a593Smuzhiyun     int i = 0, ret = 0;
414*4882a593Smuzhiyun     int j, coord;
415*4882a593Smuzhiyun     Time current;
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun     /* The size of a single motion event. */
418*4882a593Smuzhiyun     int size;
419*4882a593Smuzhiyun     AxisInfo from, *to;         /* for scaling */
420*4882a593Smuzhiyun     INT32 *ocbuf, *icbuf;       /* pointer to coordinates for copying */
421*4882a593Smuzhiyun     INT16 *corebuf;
422*4882a593Smuzhiyun     AxisInfo core_axis = { 0 };
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun     if (!pDev->valuator || !pDev->valuator->numMotionEvents)
425*4882a593Smuzhiyun         return 0;
426*4882a593Smuzhiyun 
427*4882a593Smuzhiyun     if (core && !pScreen)
428*4882a593Smuzhiyun         return 0;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun     if (IsMaster(pDev))
431*4882a593Smuzhiyun         size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
432*4882a593Smuzhiyun     else
433*4882a593Smuzhiyun         size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun     *buff = malloc(size * pDev->valuator->numMotionEvents);
436*4882a593Smuzhiyun     if (!(*buff))
437*4882a593Smuzhiyun         return 0;
438*4882a593Smuzhiyun     obuff = (char *) *buff;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun     for (i = pDev->valuator->first_motion;
441*4882a593Smuzhiyun          i != pDev->valuator->last_motion;
442*4882a593Smuzhiyun          i = (i + 1) % pDev->valuator->numMotionEvents) {
443*4882a593Smuzhiyun         /* We index the input buffer by which element we're accessing, which
444*4882a593Smuzhiyun          * is not monotonic, and the output buffer by how many events we've
445*4882a593Smuzhiyun          * written so far. */
446*4882a593Smuzhiyun         ibuff = (char *) pDev->valuator->motion + (i * size);
447*4882a593Smuzhiyun         memcpy(&current, ibuff, sizeof(Time));
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun         if (current > stop) {
450*4882a593Smuzhiyun             return ret;
451*4882a593Smuzhiyun         }
452*4882a593Smuzhiyun         else if (current >= start) {
453*4882a593Smuzhiyun             if (core) {
454*4882a593Smuzhiyun                 memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun                 icbuf = (INT32 *) (ibuff + sizeof(Time));
457*4882a593Smuzhiyun                 corebuf = (INT16 *) (obuff + sizeof(Time));
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun                 /* fetch x coordinate + range */
460*4882a593Smuzhiyun                 memcpy(&from.min_value, icbuf++, sizeof(INT32));
461*4882a593Smuzhiyun                 memcpy(&from.max_value, icbuf++, sizeof(INT32));
462*4882a593Smuzhiyun                 memcpy(&coord, icbuf++, sizeof(INT32));
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun                 /* scale to screen coords */
465*4882a593Smuzhiyun                 to = &core_axis;
466*4882a593Smuzhiyun                 to->max_value = pScreen->width;
467*4882a593Smuzhiyun                 coord =
468*4882a593Smuzhiyun                     rescaleValuatorAxis(coord, &from, to, 0, pScreen->width);
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun                 memcpy(corebuf, &coord, sizeof(INT16));
471*4882a593Smuzhiyun                 corebuf++;
472*4882a593Smuzhiyun 
473*4882a593Smuzhiyun                 /* fetch y coordinate + range */
474*4882a593Smuzhiyun                 memcpy(&from.min_value, icbuf++, sizeof(INT32));
475*4882a593Smuzhiyun                 memcpy(&from.max_value, icbuf++, sizeof(INT32));
476*4882a593Smuzhiyun                 memcpy(&coord, icbuf++, sizeof(INT32));
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun                 to->max_value = pScreen->height;
479*4882a593Smuzhiyun                 coord =
480*4882a593Smuzhiyun                     rescaleValuatorAxis(coord, &from, to, 0, pScreen->height);
481*4882a593Smuzhiyun                 memcpy(corebuf, &coord, sizeof(INT16));
482*4882a593Smuzhiyun 
483*4882a593Smuzhiyun             }
484*4882a593Smuzhiyun             else if (IsMaster(pDev)) {
485*4882a593Smuzhiyun                 memcpy(obuff, ibuff, sizeof(Time));     /* copy timestamp */
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun                 ocbuf = (INT32 *) (obuff + sizeof(Time));
488*4882a593Smuzhiyun                 icbuf = (INT32 *) (ibuff + sizeof(Time));
489*4882a593Smuzhiyun                 for (j = 0; j < MAX_VALUATORS; j++) {
490*4882a593Smuzhiyun                     if (j >= pDev->valuator->numAxes)
491*4882a593Smuzhiyun                         break;
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun                     /* fetch min/max/coordinate */
494*4882a593Smuzhiyun                     memcpy(&from.min_value, icbuf++, sizeof(INT32));
495*4882a593Smuzhiyun                     memcpy(&from.max_value, icbuf++, sizeof(INT32));
496*4882a593Smuzhiyun                     memcpy(&coord, icbuf++, sizeof(INT32));
497*4882a593Smuzhiyun 
498*4882a593Smuzhiyun                     to = (j <
499*4882a593Smuzhiyun                           pDev->valuator->numAxes) ? &pDev->valuator->
500*4882a593Smuzhiyun                         axes[j] : NULL;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun                     /* x/y scaled to screen if no range is present */
503*4882a593Smuzhiyun                     if (j == 0 && (from.max_value < from.min_value))
504*4882a593Smuzhiyun                         from.max_value = pScreen->width;
505*4882a593Smuzhiyun                     else if (j == 1 && (from.max_value < from.min_value))
506*4882a593Smuzhiyun                         from.max_value = pScreen->height;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun                     /* scale from stored range into current range */
509*4882a593Smuzhiyun                     coord = rescaleValuatorAxis(coord, &from, to, 0, 0);
510*4882a593Smuzhiyun                     memcpy(ocbuf, &coord, sizeof(INT32));
511*4882a593Smuzhiyun                     ocbuf++;
512*4882a593Smuzhiyun                 }
513*4882a593Smuzhiyun             }
514*4882a593Smuzhiyun             else
515*4882a593Smuzhiyun                 memcpy(obuff, ibuff, size);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun             /* don't advance by size here. size may be different to the
518*4882a593Smuzhiyun              * actually written size if the MD has less valuators than MAX */
519*4882a593Smuzhiyun             if (core)
520*4882a593Smuzhiyun                 obuff += sizeof(INT32) + sizeof(Time);
521*4882a593Smuzhiyun             else
522*4882a593Smuzhiyun                 obuff +=
523*4882a593Smuzhiyun                     (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
524*4882a593Smuzhiyun             ret++;
525*4882a593Smuzhiyun         }
526*4882a593Smuzhiyun     }
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     return ret;
529*4882a593Smuzhiyun }
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun /**
532*4882a593Smuzhiyun  * Update the motion history for a specific device, with the list of
533*4882a593Smuzhiyun  * valuators.
534*4882a593Smuzhiyun  *
535*4882a593Smuzhiyun  * Layout of the history buffer:
536*4882a593Smuzhiyun  *   for SDs: [time] [val0] [val1] ... [valn]
537*4882a593Smuzhiyun  *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
538*4882a593Smuzhiyun  *
539*4882a593Smuzhiyun  * For events that have some valuators unset:
540*4882a593Smuzhiyun  *      min_val == max_val == val == 0.
541*4882a593Smuzhiyun  */
542*4882a593Smuzhiyun static void
updateMotionHistory(DeviceIntPtr pDev,CARD32 ms,ValuatorMask * mask,double * valuators)543*4882a593Smuzhiyun updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
544*4882a593Smuzhiyun                     double *valuators)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun     char *buff = (char *) pDev->valuator->motion;
547*4882a593Smuzhiyun     ValuatorClassPtr v;
548*4882a593Smuzhiyun     int i;
549*4882a593Smuzhiyun 
550*4882a593Smuzhiyun     if (!pDev->valuator->numMotionEvents)
551*4882a593Smuzhiyun         return;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun     v = pDev->valuator;
554*4882a593Smuzhiyun     if (IsMaster(pDev)) {
555*4882a593Smuzhiyun         buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
556*4882a593Smuzhiyun             v->last_motion;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun         memcpy(buff, &ms, sizeof(Time));
559*4882a593Smuzhiyun         buff += sizeof(Time);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun         memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun         for (i = 0; i < v->numAxes; i++) {
564*4882a593Smuzhiyun             int val;
565*4882a593Smuzhiyun 
566*4882a593Smuzhiyun             /* XI1 doesn't support mixed mode devices */
567*4882a593Smuzhiyun             if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
568*4882a593Smuzhiyun                 break;
569*4882a593Smuzhiyun             if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
570*4882a593Smuzhiyun                 buff += 3 * sizeof(INT32);
571*4882a593Smuzhiyun                 continue;
572*4882a593Smuzhiyun             }
573*4882a593Smuzhiyun             memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
574*4882a593Smuzhiyun             buff += sizeof(INT32);
575*4882a593Smuzhiyun             memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
576*4882a593Smuzhiyun             buff += sizeof(INT32);
577*4882a593Smuzhiyun             val = valuators[i];
578*4882a593Smuzhiyun             memcpy(buff, &val, sizeof(INT32));
579*4882a593Smuzhiyun             buff += sizeof(INT32);
580*4882a593Smuzhiyun         }
581*4882a593Smuzhiyun     }
582*4882a593Smuzhiyun     else {
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun         buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
585*4882a593Smuzhiyun             pDev->valuator->last_motion;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun         memcpy(buff, &ms, sizeof(Time));
588*4882a593Smuzhiyun         buff += sizeof(Time);
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun         memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun         for (i = 0; i < MAX_VALUATORS; i++) {
593*4882a593Smuzhiyun             int val;
594*4882a593Smuzhiyun 
595*4882a593Smuzhiyun             if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i)) {
596*4882a593Smuzhiyun                 buff += sizeof(INT32);
597*4882a593Smuzhiyun                 continue;
598*4882a593Smuzhiyun             }
599*4882a593Smuzhiyun             val = valuators[i];
600*4882a593Smuzhiyun             memcpy(buff, &val, sizeof(INT32));
601*4882a593Smuzhiyun             buff += sizeof(INT32);
602*4882a593Smuzhiyun         }
603*4882a593Smuzhiyun     }
604*4882a593Smuzhiyun 
605*4882a593Smuzhiyun     pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
606*4882a593Smuzhiyun         pDev->valuator->numMotionEvents;
607*4882a593Smuzhiyun     /* If we're wrapping around, just keep the circular buffer going. */
608*4882a593Smuzhiyun     if (pDev->valuator->first_motion == pDev->valuator->last_motion)
609*4882a593Smuzhiyun         pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
610*4882a593Smuzhiyun             pDev->valuator->numMotionEvents;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun     return;
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
615*4882a593Smuzhiyun /**
616*4882a593Smuzhiyun  * Returns the maximum number of events GetKeyboardEvents
617*4882a593Smuzhiyun  * and GetPointerEvents will ever return.
618*4882a593Smuzhiyun  *
619*4882a593Smuzhiyun  * This MUST be absolutely constant, from init until exit.
620*4882a593Smuzhiyun  */
621*4882a593Smuzhiyun int
GetMaximumEventsNum(void)622*4882a593Smuzhiyun GetMaximumEventsNum(void)
623*4882a593Smuzhiyun {
624*4882a593Smuzhiyun     /* One raw event
625*4882a593Smuzhiyun      * One device event
626*4882a593Smuzhiyun      * One possible device changed event
627*4882a593Smuzhiyun      * Lots of possible separate button scroll events (horiz + vert)
628*4882a593Smuzhiyun      * Lots of possible separate raw button scroll events (horiz + vert)
629*4882a593Smuzhiyun      */
630*4882a593Smuzhiyun     return 100;
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun /**
634*4882a593Smuzhiyun  * Clip an axis to its bounds, which are declared in the call to
635*4882a593Smuzhiyun  * InitValuatorAxisClassStruct.
636*4882a593Smuzhiyun  */
637*4882a593Smuzhiyun static void
clipAxis(DeviceIntPtr pDev,int axisNum,double * val)638*4882a593Smuzhiyun clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
639*4882a593Smuzhiyun {
640*4882a593Smuzhiyun     AxisInfoPtr axis;
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun     if (axisNum >= pDev->valuator->numAxes)
643*4882a593Smuzhiyun         return;
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun     axis = pDev->valuator->axes + axisNum;
646*4882a593Smuzhiyun 
647*4882a593Smuzhiyun     /* If a value range is defined, clip. If not, do nothing */
648*4882a593Smuzhiyun     if (axis->max_value <= axis->min_value)
649*4882a593Smuzhiyun         return;
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun     if (*val < axis->min_value)
652*4882a593Smuzhiyun         *val = axis->min_value;
653*4882a593Smuzhiyun     if (*val > axis->max_value)
654*4882a593Smuzhiyun         *val = axis->max_value;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun /**
658*4882a593Smuzhiyun  * Clip every axis in the list of valuators to its bounds.
659*4882a593Smuzhiyun  */
660*4882a593Smuzhiyun static void
clipValuators(DeviceIntPtr pDev,ValuatorMask * mask)661*4882a593Smuzhiyun clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun     int i;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++)
666*4882a593Smuzhiyun         if (valuator_mask_isset(mask, i)) {
667*4882a593Smuzhiyun             double val = valuator_mask_get_double(mask, i);
668*4882a593Smuzhiyun 
669*4882a593Smuzhiyun             clipAxis(pDev, i, &val);
670*4882a593Smuzhiyun             valuator_mask_set_double(mask, i, val);
671*4882a593Smuzhiyun         }
672*4882a593Smuzhiyun }
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun /**
675*4882a593Smuzhiyun  * Create the DCCE event (does not update the master's device state yet, this
676*4882a593Smuzhiyun  * is done in the event processing).
677*4882a593Smuzhiyun  * Pull in the coordinates from the MD if necessary.
678*4882a593Smuzhiyun  *
679*4882a593Smuzhiyun  * @param events Pointer to a pre-allocated event array.
680*4882a593Smuzhiyun  * @param dev The slave device that generated an event.
681*4882a593Smuzhiyun  * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
682*4882a593Smuzhiyun  * @param num_events The current number of events, returns the number of
683*4882a593Smuzhiyun  *        events if a DCCE was generated.
684*4882a593Smuzhiyun  * @return The updated @events pointer.
685*4882a593Smuzhiyun  */
686*4882a593Smuzhiyun InternalEvent *
UpdateFromMaster(InternalEvent * events,DeviceIntPtr dev,int type,int * num_events)687*4882a593Smuzhiyun UpdateFromMaster(InternalEvent *events, DeviceIntPtr dev, int type,
688*4882a593Smuzhiyun                  int *num_events)
689*4882a593Smuzhiyun {
690*4882a593Smuzhiyun     DeviceIntPtr master;
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun     master =
693*4882a593Smuzhiyun         GetMaster(dev,
694*4882a593Smuzhiyun                   (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER :
695*4882a593Smuzhiyun                   MASTER_KEYBOARD);
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun     if (master && master->last.slave != dev) {
698*4882a593Smuzhiyun         CreateClassesChangedEvent(events, master, dev,
699*4882a593Smuzhiyun                                   type | DEVCHANGE_SLAVE_SWITCH);
700*4882a593Smuzhiyun         if (IsPointerDevice(master)) {
701*4882a593Smuzhiyun             updateSlaveDeviceCoords(master, dev);
702*4882a593Smuzhiyun             master->last.numValuators = dev->last.numValuators;
703*4882a593Smuzhiyun         }
704*4882a593Smuzhiyun         master->last.slave = dev;
705*4882a593Smuzhiyun         (*num_events)++;
706*4882a593Smuzhiyun         events++;
707*4882a593Smuzhiyun     }
708*4882a593Smuzhiyun     return events;
709*4882a593Smuzhiyun }
710*4882a593Smuzhiyun 
711*4882a593Smuzhiyun /**
712*4882a593Smuzhiyun  * Move the device's pointer to the position given in the valuators.
713*4882a593Smuzhiyun  *
714*4882a593Smuzhiyun  * @param dev The device whose pointer is to be moved.
715*4882a593Smuzhiyun  * @param mask Valuator data for this event.
716*4882a593Smuzhiyun  */
717*4882a593Smuzhiyun static void
clipAbsolute(DeviceIntPtr dev,ValuatorMask * mask)718*4882a593Smuzhiyun clipAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun     int i;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++) {
723*4882a593Smuzhiyun         double val;
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun         if (!valuator_mask_isset(mask, i))
726*4882a593Smuzhiyun             continue;
727*4882a593Smuzhiyun         val = valuator_mask_get_double(mask, i);
728*4882a593Smuzhiyun         clipAxis(dev, i, &val);
729*4882a593Smuzhiyun         valuator_mask_set_double(mask, i, val);
730*4882a593Smuzhiyun     }
731*4882a593Smuzhiyun }
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun static void
add_to_scroll_valuator(DeviceIntPtr dev,ValuatorMask * mask,int valuator,double value)734*4882a593Smuzhiyun add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, double value)
735*4882a593Smuzhiyun {
736*4882a593Smuzhiyun     double v;
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun     if (!valuator_mask_fetch_double(mask, valuator, &v))
739*4882a593Smuzhiyun         return;
740*4882a593Smuzhiyun 
741*4882a593Smuzhiyun     /* protect against scrolling overflow. INT_MAX for double, because
742*4882a593Smuzhiyun      * we'll eventually write this as 32.32 fixed point */
743*4882a593Smuzhiyun     if ((value > 0 && v > INT_MAX - value) || (value < 0 && v < INT_MIN - value)) {
744*4882a593Smuzhiyun         v = 0;
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun         /* reset last.scroll to avoid a button storm */
747*4882a593Smuzhiyun         valuator_mask_set_double(dev->last.scroll, valuator, 0);
748*4882a593Smuzhiyun     }
749*4882a593Smuzhiyun     else
750*4882a593Smuzhiyun         v += value;
751*4882a593Smuzhiyun 
752*4882a593Smuzhiyun     valuator_mask_set_double(mask, valuator, v);
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun static void
scale_for_device_resolution(DeviceIntPtr dev,ValuatorMask * mask)757*4882a593Smuzhiyun scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
758*4882a593Smuzhiyun {
759*4882a593Smuzhiyun     double y;
760*4882a593Smuzhiyun     ValuatorClassPtr v = dev->valuator;
761*4882a593Smuzhiyun     int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
762*4882a593Smuzhiyun     int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun     double screen_ratio = 1.0 * screenInfo.width/screenInfo.height;
765*4882a593Smuzhiyun     double device_ratio = 1.0 * xrange/yrange;
766*4882a593Smuzhiyun     double resolution_ratio = 1.0;
767*4882a593Smuzhiyun     double ratio;
768*4882a593Smuzhiyun 
769*4882a593Smuzhiyun     if (!valuator_mask_fetch_double(mask, 1, &y))
770*4882a593Smuzhiyun         return;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun     if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0)
773*4882a593Smuzhiyun         resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun     ratio = device_ratio/resolution_ratio/screen_ratio;
776*4882a593Smuzhiyun     valuator_mask_set_double(mask, 1, y / ratio);
777*4882a593Smuzhiyun }
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun /**
780*4882a593Smuzhiyun  * Move the device's pointer by the values given in @valuators.
781*4882a593Smuzhiyun  *
782*4882a593Smuzhiyun  * @param dev The device whose pointer is to be moved.
783*4882a593Smuzhiyun  * @param[in,out] mask Valuator data for this event, modified in-place.
784*4882a593Smuzhiyun  */
785*4882a593Smuzhiyun static void
moveRelative(DeviceIntPtr dev,int flags,ValuatorMask * mask)786*4882a593Smuzhiyun moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
787*4882a593Smuzhiyun {
788*4882a593Smuzhiyun     int i;
789*4882a593Smuzhiyun     Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
790*4882a593Smuzhiyun     ValuatorClassPtr v = dev->valuator;
791*4882a593Smuzhiyun 
792*4882a593Smuzhiyun     /* for abs devices in relative mode, we've just scaled wrong, since we
793*4882a593Smuzhiyun        mapped the device's shape into the screen shape. Undo this. */
794*4882a593Smuzhiyun     if ((flags & POINTER_ABSOLUTE) == 0 && v && v->numAxes > 1 &&
795*4882a593Smuzhiyun         v->axes[0].min_value < v->axes[0].max_value &&
796*4882a593Smuzhiyun         v->axes[1].min_value < v->axes[1].max_value) {
797*4882a593Smuzhiyun         scale_for_device_resolution(dev, mask);
798*4882a593Smuzhiyun     }
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun     /* calc other axes, clip, drop back into valuators */
801*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++) {
802*4882a593Smuzhiyun         double val = dev->last.valuators[i];
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun         if (!valuator_mask_isset(mask, i))
805*4882a593Smuzhiyun             continue;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun         add_to_scroll_valuator(dev, mask, i, val);
808*4882a593Smuzhiyun 
809*4882a593Smuzhiyun         /* x & y need to go over the limits to cross screens if the SD
810*4882a593Smuzhiyun          * isn't currently attached; otherwise, clip to screen bounds. */
811*4882a593Smuzhiyun         if (valuator_get_mode(dev, i) == Absolute &&
812*4882a593Smuzhiyun             ((i != 0 && i != 1) || clip_xy)) {
813*4882a593Smuzhiyun             val = valuator_mask_get_double(mask, i);
814*4882a593Smuzhiyun             clipAxis(dev, i, &val);
815*4882a593Smuzhiyun             valuator_mask_set_double(mask, i, val);
816*4882a593Smuzhiyun         }
817*4882a593Smuzhiyun     }
818*4882a593Smuzhiyun }
819*4882a593Smuzhiyun 
820*4882a593Smuzhiyun /**
821*4882a593Smuzhiyun  * Accelerate the data in valuators based on the device's acceleration scheme.
822*4882a593Smuzhiyun  *
823*4882a593Smuzhiyun  * @param dev The device which's pointer is to be moved.
824*4882a593Smuzhiyun  * @param valuators Valuator mask
825*4882a593Smuzhiyun  * @param ms Current time.
826*4882a593Smuzhiyun  */
827*4882a593Smuzhiyun static void
accelPointer(DeviceIntPtr dev,ValuatorMask * valuators,CARD32 ms)828*4882a593Smuzhiyun accelPointer(DeviceIntPtr dev, ValuatorMask *valuators, CARD32 ms)
829*4882a593Smuzhiyun {
830*4882a593Smuzhiyun     if (dev->valuator->accelScheme.AccelSchemeProc)
831*4882a593Smuzhiyun         dev->valuator->accelScheme.AccelSchemeProc(dev, valuators, ms);
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun /**
835*4882a593Smuzhiyun  * Scale from absolute screen coordinates to absolute coordinates in the
836*4882a593Smuzhiyun  * device's coordinate range.
837*4882a593Smuzhiyun  *
838*4882a593Smuzhiyun  * @param dev The device to scale for.
839*4882a593Smuzhiyun  * @param[in, out] mask The mask in desktop/screen coordinates, modified in place
840*4882a593Smuzhiyun  * to contain device coordinate range.
841*4882a593Smuzhiyun  * @param flags If POINTER_SCREEN is set, mask is in per-screen coordinates.
842*4882a593Smuzhiyun  *              Otherwise, mask is in desktop coords.
843*4882a593Smuzhiyun  */
844*4882a593Smuzhiyun static void
scale_from_screen(DeviceIntPtr dev,ValuatorMask * mask,int flags)845*4882a593Smuzhiyun scale_from_screen(DeviceIntPtr dev, ValuatorMask *mask, int flags)
846*4882a593Smuzhiyun {
847*4882a593Smuzhiyun     double scaled;
848*4882a593Smuzhiyun     ScreenPtr scr = miPointerGetScreen(dev);
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 0)) {
851*4882a593Smuzhiyun         scaled = valuator_mask_get_double(mask, 0);
852*4882a593Smuzhiyun         if (flags & POINTER_SCREEN)
853*4882a593Smuzhiyun             scaled += scr->x;
854*4882a593Smuzhiyun         scaled = rescaleValuatorAxis(scaled,
855*4882a593Smuzhiyun                                      NULL, dev->valuator->axes + 0,
856*4882a593Smuzhiyun                                      screenInfo.x, screenInfo.width);
857*4882a593Smuzhiyun         valuator_mask_set_double(mask, 0, scaled);
858*4882a593Smuzhiyun     }
859*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 1)) {
860*4882a593Smuzhiyun         scaled = valuator_mask_get_double(mask, 1);
861*4882a593Smuzhiyun         if (flags & POINTER_SCREEN)
862*4882a593Smuzhiyun             scaled += scr->y;
863*4882a593Smuzhiyun         scaled = rescaleValuatorAxis(scaled,
864*4882a593Smuzhiyun                                      NULL, dev->valuator->axes + 1,
865*4882a593Smuzhiyun                                      screenInfo.y, screenInfo.height);
866*4882a593Smuzhiyun         valuator_mask_set_double(mask, 1, scaled);
867*4882a593Smuzhiyun     }
868*4882a593Smuzhiyun }
869*4882a593Smuzhiyun 
870*4882a593Smuzhiyun /**
871*4882a593Smuzhiyun  * Scale from (absolute) device to screen coordinates here,
872*4882a593Smuzhiyun  *
873*4882a593Smuzhiyun  * The coordinates provided are always absolute. see fill_pointer_events for
874*4882a593Smuzhiyun  * information on coordinate systems.
875*4882a593Smuzhiyun  *
876*4882a593Smuzhiyun  * @param dev The device to be moved.
877*4882a593Smuzhiyun  * @param mask Mask of axis values for this event
878*4882a593Smuzhiyun  * @param[out] devx x desktop-wide coordinate in device coordinate system
879*4882a593Smuzhiyun  * @param[out] devy y desktop-wide coordinate in device coordinate system
880*4882a593Smuzhiyun  * @param[out] screenx x coordinate in desktop coordinate system
881*4882a593Smuzhiyun  * @param[out] screeny y coordinate in desktop coordinate system
882*4882a593Smuzhiyun  */
883*4882a593Smuzhiyun static ScreenPtr
scale_to_desktop(DeviceIntPtr dev,ValuatorMask * mask,double * devx,double * devy,double * screenx,double * screeny)884*4882a593Smuzhiyun scale_to_desktop(DeviceIntPtr dev, ValuatorMask *mask,
885*4882a593Smuzhiyun                  double *devx, double *devy, double *screenx, double *screeny)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun     ScreenPtr scr = miPointerGetScreen(dev);
888*4882a593Smuzhiyun     double x, y;
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun     BUG_WARN(dev->valuator && dev->valuator->numAxes < 2);
891*4882a593Smuzhiyun     if (!dev->valuator || dev->valuator->numAxes < 2) {
892*4882a593Smuzhiyun         /* if we have no axes, last.valuators must be in screen coords
893*4882a593Smuzhiyun          * anyway */
894*4882a593Smuzhiyun         *devx = *screenx = dev->last.valuators[0];
895*4882a593Smuzhiyun         *devy = *screeny = dev->last.valuators[1];
896*4882a593Smuzhiyun         return scr;
897*4882a593Smuzhiyun     }
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 0))
900*4882a593Smuzhiyun         x = valuator_mask_get_double(mask, 0);
901*4882a593Smuzhiyun     else
902*4882a593Smuzhiyun         x = dev->last.valuators[0];
903*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 1))
904*4882a593Smuzhiyun         y = valuator_mask_get_double(mask, 1);
905*4882a593Smuzhiyun     else
906*4882a593Smuzhiyun         y = dev->last.valuators[1];
907*4882a593Smuzhiyun 
908*4882a593Smuzhiyun     /* scale x&y to desktop coordinates */
909*4882a593Smuzhiyun     *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
910*4882a593Smuzhiyun                                    screenInfo.x, screenInfo.width);
911*4882a593Smuzhiyun     *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
912*4882a593Smuzhiyun                                    screenInfo.y, screenInfo.height);
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun     *devx = x;
915*4882a593Smuzhiyun     *devy = y;
916*4882a593Smuzhiyun 
917*4882a593Smuzhiyun     return scr;
918*4882a593Smuzhiyun }
919*4882a593Smuzhiyun 
920*4882a593Smuzhiyun /**
921*4882a593Smuzhiyun  * If we have HW cursors, this actually moves the visible sprite. If not, we
922*4882a593Smuzhiyun  * just do all the screen crossing, etc.
923*4882a593Smuzhiyun  *
924*4882a593Smuzhiyun  * We use the screen coordinates here, call miPointerSetPosition() and then
925*4882a593Smuzhiyun  * scale back into device coordinates (if needed). miPSP will change x/y if
926*4882a593Smuzhiyun  * the screen was crossed.
927*4882a593Smuzhiyun  *
928*4882a593Smuzhiyun  * The coordinates provided are always absolute. The parameter mode
929*4882a593Smuzhiyun  * specifies whether it was relative or absolute movement that landed us at
930*4882a593Smuzhiyun  * those coordinates. see fill_pointer_events for information on coordinate
931*4882a593Smuzhiyun  * systems.
932*4882a593Smuzhiyun  *
933*4882a593Smuzhiyun  * @param dev The device to be moved.
934*4882a593Smuzhiyun  * @param mode Movement mode (Absolute or Relative)
935*4882a593Smuzhiyun  * @param[out] mask Mask of axis values for this event, returns the
936*4882a593Smuzhiyun  * per-screen device coordinates after confinement
937*4882a593Smuzhiyun  * @param[in,out] devx x desktop-wide coordinate in device coordinate system
938*4882a593Smuzhiyun  * @param[in,out] devy y desktop-wide coordinate in device coordinate system
939*4882a593Smuzhiyun  * @param[in,out] screenx x coordinate in desktop coordinate system
940*4882a593Smuzhiyun  * @param[in,out] screeny y coordinate in desktop coordinate system
941*4882a593Smuzhiyun  * @param[out] nevents Number of barrier events added to events
942*4882a593Smuzhiyun  * @param[in,out] events List of events barrier events are added to
943*4882a593Smuzhiyun  */
944*4882a593Smuzhiyun static ScreenPtr
positionSprite(DeviceIntPtr dev,int mode,ValuatorMask * mask,double * devx,double * devy,double * screenx,double * screeny,int * nevents,InternalEvent * events)945*4882a593Smuzhiyun positionSprite(DeviceIntPtr dev, int mode, ValuatorMask *mask,
946*4882a593Smuzhiyun                double *devx, double *devy, double *screenx, double *screeny,
947*4882a593Smuzhiyun                int *nevents, InternalEvent* events)
948*4882a593Smuzhiyun {
949*4882a593Smuzhiyun     ScreenPtr scr = miPointerGetScreen(dev);
950*4882a593Smuzhiyun     double tmpx, tmpy;
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun     if (!dev->valuator || dev->valuator->numAxes < 2)
953*4882a593Smuzhiyun         return scr;
954*4882a593Smuzhiyun 
955*4882a593Smuzhiyun     tmpx = *screenx;
956*4882a593Smuzhiyun     tmpy = *screeny;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun     /* miPointerSetPosition takes care of crossing screens for us, as well as
959*4882a593Smuzhiyun      * clipping to the current screen. Coordinates returned are in desktop
960*4882a593Smuzhiyun      * coord system */
961*4882a593Smuzhiyun     scr = miPointerSetPosition(dev, mode, screenx, screeny, nevents, events);
962*4882a593Smuzhiyun 
963*4882a593Smuzhiyun     /* If we were constrained, rescale x/y from the screen coordinates so
964*4882a593Smuzhiyun      * the device valuators reflect the correct position. For screen
965*4882a593Smuzhiyun      * crossing this doesn't matter much, the coords would be 0 or max.
966*4882a593Smuzhiyun      */
967*4882a593Smuzhiyun     if (tmpx != *screenx)
968*4882a593Smuzhiyun         *devx = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
969*4882a593Smuzhiyun                                     screenInfo.x, screenInfo.width);
970*4882a593Smuzhiyun 
971*4882a593Smuzhiyun     if (tmpy != *screeny)
972*4882a593Smuzhiyun         *devy = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
973*4882a593Smuzhiyun                                     screenInfo.y, screenInfo.height);
974*4882a593Smuzhiyun 
975*4882a593Smuzhiyun     /* Recalculate the per-screen device coordinates */
976*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 0)) {
977*4882a593Smuzhiyun         double x;
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun         x = rescaleValuatorAxis(*screenx - scr->x, NULL,
980*4882a593Smuzhiyun                                 dev->valuator->axes + 0, 0, scr->width);
981*4882a593Smuzhiyun         valuator_mask_set_double(mask, 0, x);
982*4882a593Smuzhiyun     }
983*4882a593Smuzhiyun     if (valuator_mask_isset(mask, 1)) {
984*4882a593Smuzhiyun         double y;
985*4882a593Smuzhiyun 
986*4882a593Smuzhiyun         y = rescaleValuatorAxis(*screeny - scr->y, NULL,
987*4882a593Smuzhiyun                                 dev->valuator->axes + 1, 0, scr->height);
988*4882a593Smuzhiyun         valuator_mask_set_double(mask, 1, y);
989*4882a593Smuzhiyun     }
990*4882a593Smuzhiyun 
991*4882a593Smuzhiyun     return scr;
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun /**
995*4882a593Smuzhiyun  * Update the motion history for the device and (if appropriate) for its
996*4882a593Smuzhiyun  * master device.
997*4882a593Smuzhiyun  * @param dev Slave device to update.
998*4882a593Smuzhiyun  * @param mask Bit mask of valid valuators to append to history.
999*4882a593Smuzhiyun  * @param num Total number of valuators to append to history.
1000*4882a593Smuzhiyun  * @param ms Current time
1001*4882a593Smuzhiyun  */
1002*4882a593Smuzhiyun static void
updateHistory(DeviceIntPtr dev,ValuatorMask * mask,CARD32 ms)1003*4882a593Smuzhiyun updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
1004*4882a593Smuzhiyun {
1005*4882a593Smuzhiyun     if (!dev->valuator)
1006*4882a593Smuzhiyun         return;
1007*4882a593Smuzhiyun 
1008*4882a593Smuzhiyun     updateMotionHistory(dev, ms, mask, dev->last.valuators);
1009*4882a593Smuzhiyun     if (!IsMaster(dev) && !IsFloating(dev)) {
1010*4882a593Smuzhiyun         DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
1011*4882a593Smuzhiyun 
1012*4882a593Smuzhiyun         updateMotionHistory(master, ms, mask, dev->last.valuators);
1013*4882a593Smuzhiyun     }
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun static void
queueEventList(DeviceIntPtr device,InternalEvent * events,int nevents)1017*4882a593Smuzhiyun queueEventList(DeviceIntPtr device, InternalEvent *events, int nevents)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun     int i;
1020*4882a593Smuzhiyun 
1021*4882a593Smuzhiyun     for (i = 0; i < nevents; i++)
1022*4882a593Smuzhiyun         mieqEnqueue(device, &events[i]);
1023*4882a593Smuzhiyun }
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun static void
event_set_root_coordinates(DeviceEvent * event,double x,double y)1026*4882a593Smuzhiyun event_set_root_coordinates(DeviceEvent *event, double x, double y)
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun     event->root_x = trunc(x);
1029*4882a593Smuzhiyun     event->root_y = trunc(y);
1030*4882a593Smuzhiyun     event->root_x_frac = x - trunc(x);
1031*4882a593Smuzhiyun     event->root_y_frac = y - trunc(y);
1032*4882a593Smuzhiyun }
1033*4882a593Smuzhiyun 
1034*4882a593Smuzhiyun /**
1035*4882a593Smuzhiyun  * Generate internal events representing this keyboard event and enqueue
1036*4882a593Smuzhiyun  * them on the event queue.
1037*4882a593Smuzhiyun  *
1038*4882a593Smuzhiyun  * This function is not reentrant. Disable signals before calling.
1039*4882a593Smuzhiyun  *
1040*4882a593Smuzhiyun  * @param device The device to generate the event for
1041*4882a593Smuzhiyun  * @param type Event type, one of KeyPress or KeyRelease
1042*4882a593Smuzhiyun  * @param keycode Key code of the pressed/released key
1043*4882a593Smuzhiyun  *
1044*4882a593Smuzhiyun  */
1045*4882a593Smuzhiyun void
QueueKeyboardEvents(DeviceIntPtr device,int type,int keycode)1046*4882a593Smuzhiyun QueueKeyboardEvents(DeviceIntPtr device, int type,
1047*4882a593Smuzhiyun                     int keycode)
1048*4882a593Smuzhiyun {
1049*4882a593Smuzhiyun     int nevents;
1050*4882a593Smuzhiyun 
1051*4882a593Smuzhiyun     nevents = GetKeyboardEvents(InputEventList, device, type, keycode);
1052*4882a593Smuzhiyun     queueEventList(device, InputEventList, nevents);
1053*4882a593Smuzhiyun }
1054*4882a593Smuzhiyun 
1055*4882a593Smuzhiyun /**
1056*4882a593Smuzhiyun  * Returns a set of InternalEvents for KeyPress/KeyRelease, optionally
1057*4882a593Smuzhiyun  * also with valuator events.
1058*4882a593Smuzhiyun  *
1059*4882a593Smuzhiyun  * The DDX is responsible for allocating the event list in the first
1060*4882a593Smuzhiyun  * place via InitEventList(), and for freeing it.
1061*4882a593Smuzhiyun  *
1062*4882a593Smuzhiyun  * @return the number of events written into events.
1063*4882a593Smuzhiyun  */
1064*4882a593Smuzhiyun int
GetKeyboardEvents(InternalEvent * events,DeviceIntPtr pDev,int type,int key_code)1065*4882a593Smuzhiyun GetKeyboardEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1066*4882a593Smuzhiyun                   int key_code)
1067*4882a593Smuzhiyun {
1068*4882a593Smuzhiyun     int num_events = 0;
1069*4882a593Smuzhiyun     CARD32 ms = 0;
1070*4882a593Smuzhiyun     DeviceEvent *event;
1071*4882a593Smuzhiyun     RawDeviceEvent *raw;
1072*4882a593Smuzhiyun     enum DeviceEventSource source_type = EVENT_SOURCE_NORMAL;
1073*4882a593Smuzhiyun 
1074*4882a593Smuzhiyun #if XSERVER_DTRACE
1075*4882a593Smuzhiyun     if (XSERVER_INPUT_EVENT_ENABLED()) {
1076*4882a593Smuzhiyun         XSERVER_INPUT_EVENT(pDev->id, type, key_code, 0, 0,
1077*4882a593Smuzhiyun                             NULL, NULL);
1078*4882a593Smuzhiyun     }
1079*4882a593Smuzhiyun #endif
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun     if (type == EnterNotify) {
1082*4882a593Smuzhiyun         source_type = EVENT_SOURCE_FOCUS;
1083*4882a593Smuzhiyun         type = KeyPress;
1084*4882a593Smuzhiyun     } else if (type == LeaveNotify) {
1085*4882a593Smuzhiyun         source_type = EVENT_SOURCE_FOCUS;
1086*4882a593Smuzhiyun         type = KeyRelease;
1087*4882a593Smuzhiyun     }
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun     /* refuse events from disabled devices */
1090*4882a593Smuzhiyun     if (!pDev->enabled)
1091*4882a593Smuzhiyun         return 0;
1092*4882a593Smuzhiyun 
1093*4882a593Smuzhiyun     if (!events || !pDev->key || !pDev->focus || !pDev->kbdfeed ||
1094*4882a593Smuzhiyun         (type != KeyPress && type != KeyRelease) ||
1095*4882a593Smuzhiyun         (key_code < 8 || key_code > 255))
1096*4882a593Smuzhiyun         return 0;
1097*4882a593Smuzhiyun 
1098*4882a593Smuzhiyun     num_events = 1;
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun     events =
1101*4882a593Smuzhiyun         UpdateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
1102*4882a593Smuzhiyun 
1103*4882a593Smuzhiyun     /* Handle core repeating, via press/release/press/release. */
1104*4882a593Smuzhiyun     if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
1105*4882a593Smuzhiyun         /* If autorepeating is disabled either globally or just for that key,
1106*4882a593Smuzhiyun          * or we have a modifier, don't generate a repeat event. */
1107*4882a593Smuzhiyun         if (!pDev->kbdfeed->ctrl.autoRepeat ||
1108*4882a593Smuzhiyun             !key_autorepeats(pDev, key_code) ||
1109*4882a593Smuzhiyun             pDev->key->xkbInfo->desc->map->modmap[key_code])
1110*4882a593Smuzhiyun             return 0;
1111*4882a593Smuzhiyun     }
1112*4882a593Smuzhiyun 
1113*4882a593Smuzhiyun     ms = GetTimeInMillis();
1114*4882a593Smuzhiyun 
1115*4882a593Smuzhiyun     if (source_type == EVENT_SOURCE_NORMAL) {
1116*4882a593Smuzhiyun         raw = &events->raw_event;
1117*4882a593Smuzhiyun         init_raw(pDev, raw, ms, type, key_code);
1118*4882a593Smuzhiyun         events++;
1119*4882a593Smuzhiyun         num_events++;
1120*4882a593Smuzhiyun     }
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun     event = &events->device_event;
1123*4882a593Smuzhiyun     init_device_event(event, pDev, ms, source_type);
1124*4882a593Smuzhiyun     event->detail.key = key_code;
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun     if (type == KeyPress) {
1127*4882a593Smuzhiyun         event->type = ET_KeyPress;
1128*4882a593Smuzhiyun         set_key_down(pDev, key_code, KEY_POSTED);
1129*4882a593Smuzhiyun     }
1130*4882a593Smuzhiyun     else if (type == KeyRelease) {
1131*4882a593Smuzhiyun         event->type = ET_KeyRelease;
1132*4882a593Smuzhiyun         set_key_up(pDev, key_code, KEY_POSTED);
1133*4882a593Smuzhiyun     }
1134*4882a593Smuzhiyun 
1135*4882a593Smuzhiyun     return num_events;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun 
1138*4882a593Smuzhiyun /**
1139*4882a593Smuzhiyun  * Initialize an event array large enough for num_events arrays.
1140*4882a593Smuzhiyun  * This event list is to be passed into GetPointerEvents() and
1141*4882a593Smuzhiyun  * GetKeyboardEvents().
1142*4882a593Smuzhiyun  *
1143*4882a593Smuzhiyun  * @param num_events Number of elements in list.
1144*4882a593Smuzhiyun  */
1145*4882a593Smuzhiyun InternalEvent *
InitEventList(int num_events)1146*4882a593Smuzhiyun InitEventList(int num_events)
1147*4882a593Smuzhiyun {
1148*4882a593Smuzhiyun     InternalEvent *events = calloc(num_events, sizeof(InternalEvent));
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun     return events;
1151*4882a593Smuzhiyun }
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun /**
1154*4882a593Smuzhiyun  * Free an event list.
1155*4882a593Smuzhiyun  *
1156*4882a593Smuzhiyun  * @param list The list to be freed.
1157*4882a593Smuzhiyun  * @param num_events Number of elements in list.
1158*4882a593Smuzhiyun  */
1159*4882a593Smuzhiyun void
FreeEventList(InternalEvent * list,int num_events)1160*4882a593Smuzhiyun FreeEventList(InternalEvent *list, int num_events)
1161*4882a593Smuzhiyun {
1162*4882a593Smuzhiyun     free(list);
1163*4882a593Smuzhiyun }
1164*4882a593Smuzhiyun 
1165*4882a593Smuzhiyun /**
1166*4882a593Smuzhiyun  * Transform vector x/y according to matrix m and drop the rounded coords
1167*4882a593Smuzhiyun  * back into x/y.
1168*4882a593Smuzhiyun  */
1169*4882a593Smuzhiyun static void
transform(struct pixman_f_transform * m,double * x,double * y)1170*4882a593Smuzhiyun transform(struct pixman_f_transform *m, double *x, double *y)
1171*4882a593Smuzhiyun {
1172*4882a593Smuzhiyun     struct pixman_f_vector p = {.v = {*x, *y, 1} };
1173*4882a593Smuzhiyun     pixman_f_transform_point(m, &p);
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun     *x = p.v[0];
1176*4882a593Smuzhiyun     *y = p.v[1];
1177*4882a593Smuzhiyun }
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun static void
transformRelative(DeviceIntPtr dev,ValuatorMask * mask)1180*4882a593Smuzhiyun transformRelative(DeviceIntPtr dev, ValuatorMask *mask)
1181*4882a593Smuzhiyun {
1182*4882a593Smuzhiyun     double x = 0, y = 0;
1183*4882a593Smuzhiyun 
1184*4882a593Smuzhiyun     valuator_mask_fetch_double(mask, 0, &x);
1185*4882a593Smuzhiyun     valuator_mask_fetch_double(mask, 1, &y);
1186*4882a593Smuzhiyun 
1187*4882a593Smuzhiyun     transform(&dev->relative_transform, &x, &y);
1188*4882a593Smuzhiyun 
1189*4882a593Smuzhiyun     if (x)
1190*4882a593Smuzhiyun         valuator_mask_set_double(mask, 0, x);
1191*4882a593Smuzhiyun     else
1192*4882a593Smuzhiyun         valuator_mask_unset(mask, 0);
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun     if (y)
1195*4882a593Smuzhiyun         valuator_mask_set_double(mask, 1, y);
1196*4882a593Smuzhiyun     else
1197*4882a593Smuzhiyun         valuator_mask_unset(mask, 1);
1198*4882a593Smuzhiyun }
1199*4882a593Smuzhiyun 
1200*4882a593Smuzhiyun /**
1201*4882a593Smuzhiyun  * Apply the device's transformation matrix to the valuator mask and replace
1202*4882a593Smuzhiyun  * the scaled values in mask. This transformation only applies to valuators
1203*4882a593Smuzhiyun  * 0 and 1, others will be untouched.
1204*4882a593Smuzhiyun  *
1205*4882a593Smuzhiyun  * @param dev The device the valuators came from
1206*4882a593Smuzhiyun  * @param[in,out] mask The valuator mask.
1207*4882a593Smuzhiyun  */
1208*4882a593Smuzhiyun static void
transformAbsolute(DeviceIntPtr dev,ValuatorMask * mask)1209*4882a593Smuzhiyun transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
1210*4882a593Smuzhiyun {
1211*4882a593Smuzhiyun     double x, y, ox = 0.0, oy = 0.0;
1212*4882a593Smuzhiyun     int has_x, has_y;
1213*4882a593Smuzhiyun 
1214*4882a593Smuzhiyun     has_x = valuator_mask_isset(mask, 0);
1215*4882a593Smuzhiyun     has_y = valuator_mask_isset(mask, 1);
1216*4882a593Smuzhiyun 
1217*4882a593Smuzhiyun     if (!has_x && !has_y)
1218*4882a593Smuzhiyun         return;
1219*4882a593Smuzhiyun 
1220*4882a593Smuzhiyun     if (!has_x || !has_y) {
1221*4882a593Smuzhiyun         struct pixman_f_transform invert;
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun         /* undo transformation from last event */
1224*4882a593Smuzhiyun         ox = dev->last.valuators[0];
1225*4882a593Smuzhiyun         oy = dev->last.valuators[1];
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun         pixman_f_transform_invert(&invert, &dev->scale_and_transform);
1228*4882a593Smuzhiyun         transform(&invert, &ox, &oy);
1229*4882a593Smuzhiyun     }
1230*4882a593Smuzhiyun 
1231*4882a593Smuzhiyun     if (has_x)
1232*4882a593Smuzhiyun         ox = valuator_mask_get_double(mask, 0);
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun     if (has_y)
1235*4882a593Smuzhiyun         oy = valuator_mask_get_double(mask, 1);
1236*4882a593Smuzhiyun 
1237*4882a593Smuzhiyun     x = ox;
1238*4882a593Smuzhiyun     y = oy;
1239*4882a593Smuzhiyun 
1240*4882a593Smuzhiyun     transform(&dev->scale_and_transform, &x, &y);
1241*4882a593Smuzhiyun 
1242*4882a593Smuzhiyun     if (has_x || ox != x)
1243*4882a593Smuzhiyun         valuator_mask_set_double(mask, 0, x);
1244*4882a593Smuzhiyun 
1245*4882a593Smuzhiyun     if (has_y || oy != y)
1246*4882a593Smuzhiyun         valuator_mask_set_double(mask, 1, y);
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun 
1249*4882a593Smuzhiyun static void
storeLastValuators(DeviceIntPtr dev,ValuatorMask * mask,int xaxis,int yaxis,double devx,double devy)1250*4882a593Smuzhiyun storeLastValuators(DeviceIntPtr dev, ValuatorMask *mask,
1251*4882a593Smuzhiyun                    int xaxis, int yaxis, double devx, double devy)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun     int i;
1254*4882a593Smuzhiyun 
1255*4882a593Smuzhiyun     /* store desktop-wide in last.valuators */
1256*4882a593Smuzhiyun     if (valuator_mask_isset(mask, xaxis))
1257*4882a593Smuzhiyun         dev->last.valuators[0] = devx;
1258*4882a593Smuzhiyun     if (valuator_mask_isset(mask, yaxis))
1259*4882a593Smuzhiyun         dev->last.valuators[1] = devy;
1260*4882a593Smuzhiyun 
1261*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(mask); i++) {
1262*4882a593Smuzhiyun         if (i == xaxis || i == yaxis)
1263*4882a593Smuzhiyun             continue;
1264*4882a593Smuzhiyun 
1265*4882a593Smuzhiyun         if (valuator_mask_isset(mask, i))
1266*4882a593Smuzhiyun             dev->last.valuators[i] = valuator_mask_get_double(mask, i);
1267*4882a593Smuzhiyun     }
1268*4882a593Smuzhiyun 
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun 
1271*4882a593Smuzhiyun /**
1272*4882a593Smuzhiyun  * Generate internal events representing this pointer event and enqueue them
1273*4882a593Smuzhiyun  * on the event queue.
1274*4882a593Smuzhiyun  *
1275*4882a593Smuzhiyun  * This function is not reentrant. Disable signals before calling.
1276*4882a593Smuzhiyun  *
1277*4882a593Smuzhiyun  * @param device The device to generate the event for
1278*4882a593Smuzhiyun  * @param type Event type, one of ButtonPress, ButtonRelease, MotionNotify
1279*4882a593Smuzhiyun  * @param buttons Button number of the buttons modified. Must be 0 for
1280*4882a593Smuzhiyun  * MotionNotify
1281*4882a593Smuzhiyun  * @param flags Event modification flags
1282*4882a593Smuzhiyun  * @param mask Valuator mask for valuators present for this event.
1283*4882a593Smuzhiyun  */
1284*4882a593Smuzhiyun void
QueuePointerEvents(DeviceIntPtr device,int type,int buttons,int flags,const ValuatorMask * mask)1285*4882a593Smuzhiyun QueuePointerEvents(DeviceIntPtr device, int type,
1286*4882a593Smuzhiyun                    int buttons, int flags, const ValuatorMask *mask)
1287*4882a593Smuzhiyun {
1288*4882a593Smuzhiyun     int nevents;
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun     nevents =
1291*4882a593Smuzhiyun         GetPointerEvents(InputEventList, device, type, buttons, flags, mask);
1292*4882a593Smuzhiyun     queueEventList(device, InputEventList, nevents);
1293*4882a593Smuzhiyun }
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun /**
1296*4882a593Smuzhiyun  * Helper function for GetPointerEvents, which only generates motion and
1297*4882a593Smuzhiyun  * raw motion events for the slave device: does not update the master device.
1298*4882a593Smuzhiyun  *
1299*4882a593Smuzhiyun  * Should not be called by anyone other than GetPointerEvents.
1300*4882a593Smuzhiyun  *
1301*4882a593Smuzhiyun  * We use several different coordinate systems and need to switch between
1302*4882a593Smuzhiyun  * the three in fill_pointer_events, positionSprite and
1303*4882a593Smuzhiyun  * miPointerSetPosition. "desktop" refers to the width/height of all
1304*4882a593Smuzhiyun  * screenInfo.screens[n]->width/height added up. "screen" is ScreenRec, not
1305*4882a593Smuzhiyun  * output.
1306*4882a593Smuzhiyun  *
1307*4882a593Smuzhiyun  * Coordinate systems:
1308*4882a593Smuzhiyun  * - relative events have a mask_in in relative coordinates, mapped to
1309*4882a593Smuzhiyun  *   pixels. These events are mapped to the current position±delta.
1310*4882a593Smuzhiyun  * - absolute events have a mask_in in absolute device coordinates in
1311*4882a593Smuzhiyun  *   device-specific range. This range is mapped to the desktop.
1312*4882a593Smuzhiyun  * - POINTER_SCREEN absolute events (x86WarpCursor) are in screen-relative
1313*4882a593Smuzhiyun  *   screen coordinate range.
1314*4882a593Smuzhiyun  * - rootx/rooty in events must be be relative to the current screen's
1315*4882a593Smuzhiyun  *   origin (screen coordinate system)
1316*4882a593Smuzhiyun  * - XI2 valuators must be relative to the current screen's origin. On
1317*4882a593Smuzhiyun  *   the protocol the device min/max range maps to the current screen.
1318*4882a593Smuzhiyun  *
1319*4882a593Smuzhiyun  * For screen switching we need to get the desktop coordinates for each
1320*4882a593Smuzhiyun  * event, then map that to the respective position on each screen and
1321*4882a593Smuzhiyun  * position the cursor there.
1322*4882a593Smuzhiyun  * The device's last.valuator[] stores the last position in desktop-wide
1323*4882a593Smuzhiyun  * coordinates (in device range for slave devices, desktop range for master
1324*4882a593Smuzhiyun  * devices).
1325*4882a593Smuzhiyun  *
1326*4882a593Smuzhiyun  * screen-relative device coordinates requires scaling: A device coordinate
1327*4882a593Smuzhiyun  * x/y of range [n..m] that maps to positions Sx/Sy on Screen S must be
1328*4882a593Smuzhiyun  * rescaled to match Sx/Sy for [n..m]. In the simplest example, x of (m/2-1)
1329*4882a593Smuzhiyun  * is the last coordinate on the first screen and must be rescaled for the
1330*4882a593Smuzhiyun  * event to be m. XI2 clients that do their own coordinate mapping would
1331*4882a593Smuzhiyun  * otherwise interpret the position of the device elsewere to the cursor.
1332*4882a593Smuzhiyun  * However, this scaling leads to losses:
1333*4882a593Smuzhiyun  * if we have two ScreenRecs we scale from e.g. [0..44704]  (Wacom I4) to
1334*4882a593Smuzhiyun  * [0..2048[. that gives us 2047.954 as desktop coord, or the per-screen
1335*4882a593Smuzhiyun  * coordinate 1023.954. Scaling that back into the device coordinate range
1336*4882a593Smuzhiyun  * gives us 44703. So off by one device unit. It's a bug, but we'll have to
1337*4882a593Smuzhiyun  * live with it because with all this scaling, we just cannot win.
1338*4882a593Smuzhiyun  *
1339*4882a593Smuzhiyun  * @return the number of events written into events.
1340*4882a593Smuzhiyun  */
1341*4882a593Smuzhiyun static int
fill_pointer_events(InternalEvent * events,DeviceIntPtr pDev,int type,int buttons,CARD32 ms,int flags,const ValuatorMask * mask_in)1342*4882a593Smuzhiyun fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
1343*4882a593Smuzhiyun                     int buttons, CARD32 ms, int flags,
1344*4882a593Smuzhiyun                     const ValuatorMask *mask_in)
1345*4882a593Smuzhiyun {
1346*4882a593Smuzhiyun     int num_events = 1;
1347*4882a593Smuzhiyun     DeviceEvent *event;
1348*4882a593Smuzhiyun     RawDeviceEvent *raw = NULL;
1349*4882a593Smuzhiyun     double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
1350*4882a593Smuzhiyun     double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
1351*4882a593Smuzhiyun     int sx = 0, sy = 0;                 /* for POINTER_SCREEN */
1352*4882a593Smuzhiyun     ValuatorMask mask;
1353*4882a593Smuzhiyun     ScreenPtr scr;
1354*4882a593Smuzhiyun     int num_barrier_events = 0;
1355*4882a593Smuzhiyun 
1356*4882a593Smuzhiyun     switch (type) {
1357*4882a593Smuzhiyun     case MotionNotify:
1358*4882a593Smuzhiyun         if (!pDev->valuator) {
1359*4882a593Smuzhiyun             ErrorF("[dix] motion events from device %d without valuators\n",
1360*4882a593Smuzhiyun                    pDev->id);
1361*4882a593Smuzhiyun             return 0;
1362*4882a593Smuzhiyun         }
1363*4882a593Smuzhiyun         if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0)
1364*4882a593Smuzhiyun             return 0;
1365*4882a593Smuzhiyun         break;
1366*4882a593Smuzhiyun     case ButtonPress:
1367*4882a593Smuzhiyun     case ButtonRelease:
1368*4882a593Smuzhiyun         if (!pDev->button || !buttons)
1369*4882a593Smuzhiyun             return 0;
1370*4882a593Smuzhiyun         if (mask_in && valuator_mask_size(mask_in) > 0 && !pDev->valuator) {
1371*4882a593Smuzhiyun             ErrorF
1372*4882a593Smuzhiyun                 ("[dix] button event with valuator from device %d without valuators\n",
1373*4882a593Smuzhiyun                  pDev->id);
1374*4882a593Smuzhiyun             return 0;
1375*4882a593Smuzhiyun         }
1376*4882a593Smuzhiyun         break;
1377*4882a593Smuzhiyun     default:
1378*4882a593Smuzhiyun         return 0;
1379*4882a593Smuzhiyun     }
1380*4882a593Smuzhiyun 
1381*4882a593Smuzhiyun     valuator_mask_copy(&mask, mask_in);
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun     if ((flags & POINTER_NORAW) == 0) {
1384*4882a593Smuzhiyun         raw = &events->raw_event;
1385*4882a593Smuzhiyun         events++;
1386*4882a593Smuzhiyun         num_events++;
1387*4882a593Smuzhiyun 
1388*4882a593Smuzhiyun         init_raw(pDev, raw, ms, type, buttons);
1389*4882a593Smuzhiyun         set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
1390*4882a593Smuzhiyun     }
1391*4882a593Smuzhiyun 
1392*4882a593Smuzhiyun     valuator_mask_drop_unaccelerated(&mask);
1393*4882a593Smuzhiyun 
1394*4882a593Smuzhiyun     /* valuators are in driver-native format (rel or abs) */
1395*4882a593Smuzhiyun 
1396*4882a593Smuzhiyun     if (flags & POINTER_ABSOLUTE) {
1397*4882a593Smuzhiyun         if (flags & (POINTER_SCREEN | POINTER_DESKTOP)) {    /* valuators are in screen/desktop coords */
1398*4882a593Smuzhiyun             sx = valuator_mask_get(&mask, 0);
1399*4882a593Smuzhiyun             sy = valuator_mask_get(&mask, 1);
1400*4882a593Smuzhiyun             scale_from_screen(pDev, &mask, flags);
1401*4882a593Smuzhiyun         }
1402*4882a593Smuzhiyun 
1403*4882a593Smuzhiyun         transformAbsolute(pDev, &mask);
1404*4882a593Smuzhiyun         clipAbsolute(pDev, &mask);
1405*4882a593Smuzhiyun         if ((flags & POINTER_NORAW) == 0 && raw)
1406*4882a593Smuzhiyun             set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
1407*4882a593Smuzhiyun     }
1408*4882a593Smuzhiyun     else {
1409*4882a593Smuzhiyun         transformRelative(pDev, &mask);
1410*4882a593Smuzhiyun 
1411*4882a593Smuzhiyun         if (flags & POINTER_ACCELERATE)
1412*4882a593Smuzhiyun             accelPointer(pDev, &mask, ms);
1413*4882a593Smuzhiyun         if ((flags & POINTER_NORAW) == 0 && raw)
1414*4882a593Smuzhiyun             set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
1415*4882a593Smuzhiyun 
1416*4882a593Smuzhiyun         moveRelative(pDev, flags, &mask);
1417*4882a593Smuzhiyun     }
1418*4882a593Smuzhiyun 
1419*4882a593Smuzhiyun     /* valuators are in device coordinate system in absolute coordinates */
1420*4882a593Smuzhiyun     scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny);
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun     /* #53037 XWarpPointer's scaling back and forth between screen and
1423*4882a593Smuzhiyun        device may leave us with rounding errors. End result is that the
1424*4882a593Smuzhiyun        pointer doesn't end up on the pixel it should.
1425*4882a593Smuzhiyun        Avoid this by forcing screenx/screeny back to what the input
1426*4882a593Smuzhiyun        coordinates were.
1427*4882a593Smuzhiyun      */
1428*4882a593Smuzhiyun     if (flags & POINTER_SCREEN) {
1429*4882a593Smuzhiyun         scr = miPointerGetScreen(pDev);
1430*4882a593Smuzhiyun         screenx = sx + scr->x;
1431*4882a593Smuzhiyun         screeny = sy + scr->y;
1432*4882a593Smuzhiyun     }
1433*4882a593Smuzhiyun 
1434*4882a593Smuzhiyun     scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
1435*4882a593Smuzhiyun                          &mask, &devx, &devy, &screenx, &screeny,
1436*4882a593Smuzhiyun                          &num_barrier_events, events);
1437*4882a593Smuzhiyun     num_events += num_barrier_events;
1438*4882a593Smuzhiyun     events += num_barrier_events;
1439*4882a593Smuzhiyun 
1440*4882a593Smuzhiyun     /* screenx, screeny are in desktop coordinates,
1441*4882a593Smuzhiyun        mask is in device coordinates per-screen (the event data)
1442*4882a593Smuzhiyun        devx/devy is in device coordinate desktop-wide */
1443*4882a593Smuzhiyun     updateHistory(pDev, &mask, ms);
1444*4882a593Smuzhiyun 
1445*4882a593Smuzhiyun     clipValuators(pDev, &mask);
1446*4882a593Smuzhiyun 
1447*4882a593Smuzhiyun     storeLastValuators(pDev, &mask, 0, 1, devx, devy);
1448*4882a593Smuzhiyun 
1449*4882a593Smuzhiyun     /* Update the MD's co-ordinates, which are always in desktop space. */
1450*4882a593Smuzhiyun     if (!IsMaster(pDev) && !IsFloating(pDev)) {
1451*4882a593Smuzhiyun         DeviceIntPtr master = GetMaster(pDev, MASTER_POINTER);
1452*4882a593Smuzhiyun 
1453*4882a593Smuzhiyun         master->last.valuators[0] = screenx;
1454*4882a593Smuzhiyun         master->last.valuators[1] = screeny;
1455*4882a593Smuzhiyun     }
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun     event = &events->device_event;
1458*4882a593Smuzhiyun     init_device_event(event, pDev, ms, EVENT_SOURCE_NORMAL);
1459*4882a593Smuzhiyun 
1460*4882a593Smuzhiyun     if (type == MotionNotify) {
1461*4882a593Smuzhiyun         event->type = ET_Motion;
1462*4882a593Smuzhiyun         event->detail.button = 0;
1463*4882a593Smuzhiyun     }
1464*4882a593Smuzhiyun     else {
1465*4882a593Smuzhiyun         if (type == ButtonPress) {
1466*4882a593Smuzhiyun             event->type = ET_ButtonPress;
1467*4882a593Smuzhiyun             set_button_down(pDev, buttons, BUTTON_POSTED);
1468*4882a593Smuzhiyun         }
1469*4882a593Smuzhiyun         else if (type == ButtonRelease) {
1470*4882a593Smuzhiyun             event->type = ET_ButtonRelease;
1471*4882a593Smuzhiyun             set_button_up(pDev, buttons, BUTTON_POSTED);
1472*4882a593Smuzhiyun         }
1473*4882a593Smuzhiyun         event->detail.button = buttons;
1474*4882a593Smuzhiyun     }
1475*4882a593Smuzhiyun 
1476*4882a593Smuzhiyun     /* root_x and root_y must be in per-screen co-ordinates */
1477*4882a593Smuzhiyun     event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
1478*4882a593Smuzhiyun 
1479*4882a593Smuzhiyun     if (flags & POINTER_EMULATED) {
1480*4882a593Smuzhiyun         if (raw)
1481*4882a593Smuzhiyun             raw->flags = XIPointerEmulated;
1482*4882a593Smuzhiyun         event->flags = XIPointerEmulated;
1483*4882a593Smuzhiyun     }
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun     set_valuators(pDev, event, &mask);
1486*4882a593Smuzhiyun 
1487*4882a593Smuzhiyun     return num_events;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun 
1490*4882a593Smuzhiyun /**
1491*4882a593Smuzhiyun  * Generate events for each scroll axis that changed between before/after
1492*4882a593Smuzhiyun  * for the device.
1493*4882a593Smuzhiyun  *
1494*4882a593Smuzhiyun  * @param events The pointer to the event list to fill the events
1495*4882a593Smuzhiyun  * @param dev The device to generate the events for
1496*4882a593Smuzhiyun  * @param type The real type of the event
1497*4882a593Smuzhiyun  * @param axis The axis number to generate events for
1498*4882a593Smuzhiyun  * @param mask State before this event in absolute coords
1499*4882a593Smuzhiyun  * @param[in,out] last Last scroll state posted in absolute coords (modified
1500*4882a593Smuzhiyun  * in-place)
1501*4882a593Smuzhiyun  * @param ms Current time in ms
1502*4882a593Smuzhiyun  * @param max_events Max number of events to be generated
1503*4882a593Smuzhiyun  * @return The number of events generated
1504*4882a593Smuzhiyun  */
1505*4882a593Smuzhiyun static int
emulate_scroll_button_events(InternalEvent * events,DeviceIntPtr dev,int type,int axis,const ValuatorMask * mask,ValuatorMask * last,CARD32 ms,int max_events)1506*4882a593Smuzhiyun emulate_scroll_button_events(InternalEvent *events,
1507*4882a593Smuzhiyun                              DeviceIntPtr dev,
1508*4882a593Smuzhiyun                              int type,
1509*4882a593Smuzhiyun                              int axis,
1510*4882a593Smuzhiyun                              const ValuatorMask *mask,
1511*4882a593Smuzhiyun                              ValuatorMask *last, CARD32 ms, int max_events)
1512*4882a593Smuzhiyun {
1513*4882a593Smuzhiyun     AxisInfoPtr ax;
1514*4882a593Smuzhiyun     double delta;
1515*4882a593Smuzhiyun     double incr;
1516*4882a593Smuzhiyun     int num_events = 0;
1517*4882a593Smuzhiyun     double total;
1518*4882a593Smuzhiyun     int b;
1519*4882a593Smuzhiyun     int flags = 0;
1520*4882a593Smuzhiyun 
1521*4882a593Smuzhiyun     if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
1522*4882a593Smuzhiyun         return 0;
1523*4882a593Smuzhiyun 
1524*4882a593Smuzhiyun     if (!valuator_mask_isset(mask, axis))
1525*4882a593Smuzhiyun         return 0;
1526*4882a593Smuzhiyun 
1527*4882a593Smuzhiyun     ax = &dev->valuator->axes[axis];
1528*4882a593Smuzhiyun     incr = ax->scroll.increment;
1529*4882a593Smuzhiyun 
1530*4882a593Smuzhiyun     BUG_WARN_MSG(incr == 0, "for device %s\n", dev->name);
1531*4882a593Smuzhiyun     if (incr == 0)
1532*4882a593Smuzhiyun         return 0;
1533*4882a593Smuzhiyun 
1534*4882a593Smuzhiyun     if (type != ButtonPress && type != ButtonRelease)
1535*4882a593Smuzhiyun         flags |= POINTER_EMULATED;
1536*4882a593Smuzhiyun 
1537*4882a593Smuzhiyun     if (!valuator_mask_isset(last, axis))
1538*4882a593Smuzhiyun         valuator_mask_set_double(last, axis, 0);
1539*4882a593Smuzhiyun 
1540*4882a593Smuzhiyun     delta =
1541*4882a593Smuzhiyun         valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last,
1542*4882a593Smuzhiyun                                                                         axis);
1543*4882a593Smuzhiyun     total = delta;
1544*4882a593Smuzhiyun     b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7;
1545*4882a593Smuzhiyun 
1546*4882a593Smuzhiyun     if ((incr > 0 && delta < 0) || (incr < 0 && delta > 0))
1547*4882a593Smuzhiyun         b--;                    /* we're scrolling up or left → button 4 or 6 */
1548*4882a593Smuzhiyun 
1549*4882a593Smuzhiyun     while (fabs(delta) >= fabs(incr)) {
1550*4882a593Smuzhiyun         int nev_tmp;
1551*4882a593Smuzhiyun 
1552*4882a593Smuzhiyun         if (delta > 0)
1553*4882a593Smuzhiyun             delta -= fabs(incr);
1554*4882a593Smuzhiyun         else if (delta < 0)
1555*4882a593Smuzhiyun             delta += fabs(incr);
1556*4882a593Smuzhiyun 
1557*4882a593Smuzhiyun         /* fill_pointer_events() generates four events: one normal and one raw
1558*4882a593Smuzhiyun          * event for button press and button release.
1559*4882a593Smuzhiyun          * We may get a bigger scroll delta than we can generate events
1560*4882a593Smuzhiyun          * for. In that case, we keep decreasing delta, but skip events.
1561*4882a593Smuzhiyun          */
1562*4882a593Smuzhiyun         if (num_events + 4 < max_events) {
1563*4882a593Smuzhiyun             if (type != ButtonRelease) {
1564*4882a593Smuzhiyun                 nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
1565*4882a593Smuzhiyun                                               flags, NULL);
1566*4882a593Smuzhiyun                 events += nev_tmp;
1567*4882a593Smuzhiyun                 num_events += nev_tmp;
1568*4882a593Smuzhiyun             }
1569*4882a593Smuzhiyun             if (type != ButtonPress) {
1570*4882a593Smuzhiyun                 nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
1571*4882a593Smuzhiyun                                               flags, NULL);
1572*4882a593Smuzhiyun                 events += nev_tmp;
1573*4882a593Smuzhiyun                 num_events += nev_tmp;
1574*4882a593Smuzhiyun             }
1575*4882a593Smuzhiyun         }
1576*4882a593Smuzhiyun     }
1577*4882a593Smuzhiyun 
1578*4882a593Smuzhiyun     /* We emulated, update last.scroll */
1579*4882a593Smuzhiyun     if (total != delta) {
1580*4882a593Smuzhiyun         total -= delta;
1581*4882a593Smuzhiyun         valuator_mask_set_double(last, axis,
1582*4882a593Smuzhiyun                                  valuator_mask_get_double(last, axis) + total);
1583*4882a593Smuzhiyun     }
1584*4882a593Smuzhiyun 
1585*4882a593Smuzhiyun     return num_events;
1586*4882a593Smuzhiyun }
1587*4882a593Smuzhiyun 
1588*4882a593Smuzhiyun 
1589*4882a593Smuzhiyun /**
1590*4882a593Smuzhiyun  * Generate a complete series of InternalEvents (filled into the EventList)
1591*4882a593Smuzhiyun  * representing pointer motion, or button presses.  If the device is a slave
1592*4882a593Smuzhiyun  * device, also potentially generate a DeviceClassesChangedEvent to update
1593*4882a593Smuzhiyun  * the master device.
1594*4882a593Smuzhiyun  *
1595*4882a593Smuzhiyun  * events is not NULL-terminated; the return value is the number of events.
1596*4882a593Smuzhiyun  * The DDX is responsible for allocating the event structure in the first
1597*4882a593Smuzhiyun  * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
1598*4882a593Smuzhiyun  *
1599*4882a593Smuzhiyun  * In the generated events rootX/Y will be in absolute screen coords and
1600*4882a593Smuzhiyun  * the valuator information in the absolute or relative device coords.
1601*4882a593Smuzhiyun  *
1602*4882a593Smuzhiyun  * last.valuators[x] of the device is always in absolute device coords.
1603*4882a593Smuzhiyun  * last.valuators[x] of the master device is in absolute screen coords.
1604*4882a593Smuzhiyun  *
1605*4882a593Smuzhiyun  * master->last.valuators[x] for x > 2 is undefined.
1606*4882a593Smuzhiyun  */
1607*4882a593Smuzhiyun int
GetPointerEvents(InternalEvent * events,DeviceIntPtr pDev,int type,int buttons,int flags,const ValuatorMask * mask_in)1608*4882a593Smuzhiyun GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1609*4882a593Smuzhiyun                  int buttons, int flags, const ValuatorMask *mask_in)
1610*4882a593Smuzhiyun {
1611*4882a593Smuzhiyun     CARD32 ms = GetTimeInMillis();
1612*4882a593Smuzhiyun     int num_events = 0, nev_tmp;
1613*4882a593Smuzhiyun     ValuatorMask mask;
1614*4882a593Smuzhiyun     ValuatorMask scroll;
1615*4882a593Smuzhiyun     int i;
1616*4882a593Smuzhiyun     int realtype = type;
1617*4882a593Smuzhiyun 
1618*4882a593Smuzhiyun #if XSERVER_DTRACE
1619*4882a593Smuzhiyun     if (XSERVER_INPUT_EVENT_ENABLED()) {
1620*4882a593Smuzhiyun         XSERVER_INPUT_EVENT(pDev->id, type, buttons, flags,
1621*4882a593Smuzhiyun                             mask_in ? mask_in->last_bit + 1 : 0,
1622*4882a593Smuzhiyun                             mask_in ? mask_in->mask : NULL,
1623*4882a593Smuzhiyun                             mask_in ? mask_in->valuators : NULL);
1624*4882a593Smuzhiyun     }
1625*4882a593Smuzhiyun #endif
1626*4882a593Smuzhiyun 
1627*4882a593Smuzhiyun     BUG_RETURN_VAL(buttons >= MAX_BUTTONS, 0);
1628*4882a593Smuzhiyun 
1629*4882a593Smuzhiyun     /* refuse events from disabled devices */
1630*4882a593Smuzhiyun     if (!pDev->enabled)
1631*4882a593Smuzhiyun         return 0;
1632*4882a593Smuzhiyun 
1633*4882a593Smuzhiyun     if (!miPointerGetScreen(pDev))
1634*4882a593Smuzhiyun         return 0;
1635*4882a593Smuzhiyun 
1636*4882a593Smuzhiyun     events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
1637*4882a593Smuzhiyun                               &num_events);
1638*4882a593Smuzhiyun 
1639*4882a593Smuzhiyun     valuator_mask_copy(&mask, mask_in);
1640*4882a593Smuzhiyun 
1641*4882a593Smuzhiyun     /* Turn a scroll button press into a smooth-scrolling event if
1642*4882a593Smuzhiyun      * necessary. This only needs to cater for the XIScrollFlagPreferred
1643*4882a593Smuzhiyun      * axis (if more than one scrolling axis is present) */
1644*4882a593Smuzhiyun     if (type == ButtonPress) {
1645*4882a593Smuzhiyun         double adj;
1646*4882a593Smuzhiyun         int axis;
1647*4882a593Smuzhiyun         int h_scroll_axis = -1;
1648*4882a593Smuzhiyun         int v_scroll_axis = -1;
1649*4882a593Smuzhiyun 
1650*4882a593Smuzhiyun         if (pDev->valuator) {
1651*4882a593Smuzhiyun             h_scroll_axis = pDev->valuator->h_scroll_axis;
1652*4882a593Smuzhiyun             v_scroll_axis = pDev->valuator->v_scroll_axis;
1653*4882a593Smuzhiyun         }
1654*4882a593Smuzhiyun 
1655*4882a593Smuzhiyun         /* Up is negative on valuators, down positive */
1656*4882a593Smuzhiyun         switch (buttons) {
1657*4882a593Smuzhiyun         case 4:
1658*4882a593Smuzhiyun             adj = -1.0;
1659*4882a593Smuzhiyun             axis = v_scroll_axis;
1660*4882a593Smuzhiyun             break;
1661*4882a593Smuzhiyun         case 5:
1662*4882a593Smuzhiyun             adj = 1.0;
1663*4882a593Smuzhiyun             axis = v_scroll_axis;
1664*4882a593Smuzhiyun             break;
1665*4882a593Smuzhiyun         case 6:
1666*4882a593Smuzhiyun             adj = -1.0;
1667*4882a593Smuzhiyun             axis = h_scroll_axis;
1668*4882a593Smuzhiyun             break;
1669*4882a593Smuzhiyun         case 7:
1670*4882a593Smuzhiyun             adj = 1.0;
1671*4882a593Smuzhiyun             axis = h_scroll_axis;
1672*4882a593Smuzhiyun             break;
1673*4882a593Smuzhiyun         default:
1674*4882a593Smuzhiyun             adj = 0.0;
1675*4882a593Smuzhiyun             axis = -1;
1676*4882a593Smuzhiyun             break;
1677*4882a593Smuzhiyun         }
1678*4882a593Smuzhiyun 
1679*4882a593Smuzhiyun         if (adj != 0.0 && axis != -1) {
1680*4882a593Smuzhiyun             adj *= pDev->valuator->axes[axis].scroll.increment;
1681*4882a593Smuzhiyun             if (!valuator_mask_isset(&mask, axis))
1682*4882a593Smuzhiyun                 valuator_mask_set(&mask, axis, 0);
1683*4882a593Smuzhiyun             add_to_scroll_valuator(pDev, &mask, axis, adj);
1684*4882a593Smuzhiyun             type = MotionNotify;
1685*4882a593Smuzhiyun             buttons = 0;
1686*4882a593Smuzhiyun             flags |= POINTER_EMULATED;
1687*4882a593Smuzhiyun         }
1688*4882a593Smuzhiyun     }
1689*4882a593Smuzhiyun 
1690*4882a593Smuzhiyun     /* First fill out the original event set, with smooth-scrolling axes. */
1691*4882a593Smuzhiyun     nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags,
1692*4882a593Smuzhiyun                                   &mask);
1693*4882a593Smuzhiyun     events += nev_tmp;
1694*4882a593Smuzhiyun     num_events += nev_tmp;
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun     valuator_mask_zero(&scroll);
1697*4882a593Smuzhiyun 
1698*4882a593Smuzhiyun     /* Now turn the smooth-scrolling axes back into emulated button presses
1699*4882a593Smuzhiyun      * for legacy clients, based on the integer delta between before and now */
1700*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(&mask); i++) {
1701*4882a593Smuzhiyun         if ( !pDev->valuator || (i >= pDev->valuator->numAxes))
1702*4882a593Smuzhiyun             break;
1703*4882a593Smuzhiyun 
1704*4882a593Smuzhiyun         if (!valuator_mask_isset(&mask, i))
1705*4882a593Smuzhiyun             continue;
1706*4882a593Smuzhiyun 
1707*4882a593Smuzhiyun         valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]);
1708*4882a593Smuzhiyun 
1709*4882a593Smuzhiyun         nev_tmp =
1710*4882a593Smuzhiyun             emulate_scroll_button_events(events, pDev, realtype, i, &scroll,
1711*4882a593Smuzhiyun                                          pDev->last.scroll, ms,
1712*4882a593Smuzhiyun                                          GetMaximumEventsNum() - num_events);
1713*4882a593Smuzhiyun         events += nev_tmp;
1714*4882a593Smuzhiyun         num_events += nev_tmp;
1715*4882a593Smuzhiyun     }
1716*4882a593Smuzhiyun 
1717*4882a593Smuzhiyun     return num_events;
1718*4882a593Smuzhiyun }
1719*4882a593Smuzhiyun 
1720*4882a593Smuzhiyun /**
1721*4882a593Smuzhiyun  * Generate internal events representing this proximity event and enqueue
1722*4882a593Smuzhiyun  * them on the event queue.
1723*4882a593Smuzhiyun  *
1724*4882a593Smuzhiyun  * This function is not reentrant. Disable signals before calling.
1725*4882a593Smuzhiyun  *
1726*4882a593Smuzhiyun  * @param device The device to generate the event for
1727*4882a593Smuzhiyun  * @param type Event type, one of ProximityIn or ProximityOut
1728*4882a593Smuzhiyun  * @param keycode Key code of the pressed/released key
1729*4882a593Smuzhiyun  * @param mask Valuator mask for valuators present for this event.
1730*4882a593Smuzhiyun  *
1731*4882a593Smuzhiyun  */
1732*4882a593Smuzhiyun void
QueueProximityEvents(DeviceIntPtr device,int type,const ValuatorMask * mask)1733*4882a593Smuzhiyun QueueProximityEvents(DeviceIntPtr device, int type, const ValuatorMask *mask)
1734*4882a593Smuzhiyun {
1735*4882a593Smuzhiyun     int nevents;
1736*4882a593Smuzhiyun 
1737*4882a593Smuzhiyun     nevents = GetProximityEvents(InputEventList, device, type, mask);
1738*4882a593Smuzhiyun     queueEventList(device, InputEventList, nevents);
1739*4882a593Smuzhiyun }
1740*4882a593Smuzhiyun 
1741*4882a593Smuzhiyun /**
1742*4882a593Smuzhiyun  * Generate ProximityIn/ProximityOut InternalEvents, accompanied by
1743*4882a593Smuzhiyun  * valuators.
1744*4882a593Smuzhiyun  *
1745*4882a593Smuzhiyun  * The DDX is responsible for allocating the events in the first place via
1746*4882a593Smuzhiyun  * InitEventList(), and for freeing it.
1747*4882a593Smuzhiyun  *
1748*4882a593Smuzhiyun  * @return the number of events written into events.
1749*4882a593Smuzhiyun  */
1750*4882a593Smuzhiyun int
GetProximityEvents(InternalEvent * events,DeviceIntPtr pDev,int type,const ValuatorMask * mask_in)1751*4882a593Smuzhiyun GetProximityEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
1752*4882a593Smuzhiyun                    const ValuatorMask *mask_in)
1753*4882a593Smuzhiyun {
1754*4882a593Smuzhiyun     int num_events = 1, i;
1755*4882a593Smuzhiyun     DeviceEvent *event;
1756*4882a593Smuzhiyun     ValuatorMask mask;
1757*4882a593Smuzhiyun 
1758*4882a593Smuzhiyun #if XSERVER_DTRACE
1759*4882a593Smuzhiyun     if (XSERVER_INPUT_EVENT_ENABLED()) {
1760*4882a593Smuzhiyun         XSERVER_INPUT_EVENT(pDev->id, type, 0, 0,
1761*4882a593Smuzhiyun                             mask_in ? mask_in->last_bit + 1 : 0,
1762*4882a593Smuzhiyun                             mask_in ? mask_in->mask : NULL,
1763*4882a593Smuzhiyun                             mask_in ? mask_in->valuators : NULL);
1764*4882a593Smuzhiyun     }
1765*4882a593Smuzhiyun #endif
1766*4882a593Smuzhiyun 
1767*4882a593Smuzhiyun     /* refuse events from disabled devices */
1768*4882a593Smuzhiyun     if (!pDev->enabled)
1769*4882a593Smuzhiyun         return 0;
1770*4882a593Smuzhiyun 
1771*4882a593Smuzhiyun     /* Sanity checks. */
1772*4882a593Smuzhiyun     if ((type != ProximityIn && type != ProximityOut) || !mask_in)
1773*4882a593Smuzhiyun         return 0;
1774*4882a593Smuzhiyun     if (!pDev->valuator || !pDev->proximity)
1775*4882a593Smuzhiyun         return 0;
1776*4882a593Smuzhiyun 
1777*4882a593Smuzhiyun     valuator_mask_copy(&mask, mask_in);
1778*4882a593Smuzhiyun 
1779*4882a593Smuzhiyun     /* ignore relative axes for proximity. */
1780*4882a593Smuzhiyun     for (i = 0; i < valuator_mask_size(&mask); i++) {
1781*4882a593Smuzhiyun         if (valuator_mask_isset(&mask, i) &&
1782*4882a593Smuzhiyun             valuator_get_mode(pDev, i) == Relative)
1783*4882a593Smuzhiyun             valuator_mask_unset(&mask, i);
1784*4882a593Smuzhiyun     }
1785*4882a593Smuzhiyun 
1786*4882a593Smuzhiyun     /* FIXME: posting proximity events with relative valuators only results
1787*4882a593Smuzhiyun      * in an empty event, EventToXI() will fail to convert → no event sent
1788*4882a593Smuzhiyun      * to client. */
1789*4882a593Smuzhiyun 
1790*4882a593Smuzhiyun     events =
1791*4882a593Smuzhiyun         UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
1792*4882a593Smuzhiyun 
1793*4882a593Smuzhiyun     event = &events->device_event;
1794*4882a593Smuzhiyun     init_device_event(event, pDev, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
1795*4882a593Smuzhiyun     event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
1796*4882a593Smuzhiyun 
1797*4882a593Smuzhiyun     clipValuators(pDev, &mask);
1798*4882a593Smuzhiyun 
1799*4882a593Smuzhiyun     set_valuators(pDev, event, &mask);
1800*4882a593Smuzhiyun 
1801*4882a593Smuzhiyun     return num_events;
1802*4882a593Smuzhiyun }
1803*4882a593Smuzhiyun 
1804*4882a593Smuzhiyun int
GetTouchOwnershipEvents(InternalEvent * events,DeviceIntPtr pDev,TouchPointInfoPtr ti,uint8_t reason,XID resource,uint32_t flags)1805*4882a593Smuzhiyun GetTouchOwnershipEvents(InternalEvent *events, DeviceIntPtr pDev,
1806*4882a593Smuzhiyun                         TouchPointInfoPtr ti, uint8_t reason, XID resource,
1807*4882a593Smuzhiyun                         uint32_t flags)
1808*4882a593Smuzhiyun {
1809*4882a593Smuzhiyun     TouchClassPtr t = pDev->touch;
1810*4882a593Smuzhiyun     TouchOwnershipEvent *event;
1811*4882a593Smuzhiyun     CARD32 ms = GetTimeInMillis();
1812*4882a593Smuzhiyun 
1813*4882a593Smuzhiyun     if (!pDev->enabled || !t || !ti)
1814*4882a593Smuzhiyun         return 0;
1815*4882a593Smuzhiyun 
1816*4882a593Smuzhiyun     event = &events->touch_ownership_event;
1817*4882a593Smuzhiyun     init_touch_ownership(pDev, event, ms);
1818*4882a593Smuzhiyun 
1819*4882a593Smuzhiyun     event->touchid = ti->client_id;
1820*4882a593Smuzhiyun     event->sourceid = ti->sourceid;
1821*4882a593Smuzhiyun     event->resource = resource;
1822*4882a593Smuzhiyun     event->flags = flags;
1823*4882a593Smuzhiyun     event->reason = reason;
1824*4882a593Smuzhiyun 
1825*4882a593Smuzhiyun     return 1;
1826*4882a593Smuzhiyun }
1827*4882a593Smuzhiyun 
1828*4882a593Smuzhiyun /**
1829*4882a593Smuzhiyun  * Generate internal events representing this touch event and enqueue them
1830*4882a593Smuzhiyun  * on the event queue.
1831*4882a593Smuzhiyun  *
1832*4882a593Smuzhiyun  * This function is not reentrant. Disable signals before calling.
1833*4882a593Smuzhiyun  *
1834*4882a593Smuzhiyun  * @param device The device to generate the event for
1835*4882a593Smuzhiyun  * @param type Event type, one of XI_TouchBegin, XI_TouchUpdate, XI_TouchEnd
1836*4882a593Smuzhiyun  * @param touchid Touch point ID
1837*4882a593Smuzhiyun  * @param flags Event modification flags
1838*4882a593Smuzhiyun  * @param mask Valuator mask for valuators present for this event.
1839*4882a593Smuzhiyun  */
1840*4882a593Smuzhiyun void
QueueTouchEvents(DeviceIntPtr device,int type,uint32_t ddx_touchid,int flags,const ValuatorMask * mask)1841*4882a593Smuzhiyun QueueTouchEvents(DeviceIntPtr device, int type,
1842*4882a593Smuzhiyun                  uint32_t ddx_touchid, int flags, const ValuatorMask *mask)
1843*4882a593Smuzhiyun {
1844*4882a593Smuzhiyun     int nevents;
1845*4882a593Smuzhiyun 
1846*4882a593Smuzhiyun     nevents =
1847*4882a593Smuzhiyun         GetTouchEvents(InputEventList, device, ddx_touchid, type, flags, mask);
1848*4882a593Smuzhiyun     queueEventList(device, InputEventList, nevents);
1849*4882a593Smuzhiyun }
1850*4882a593Smuzhiyun 
1851*4882a593Smuzhiyun /**
1852*4882a593Smuzhiyun  * Get events for a touch. Generates a TouchBegin event if end is not set and
1853*4882a593Smuzhiyun  * the touch id is not active. Generates a TouchUpdate event if end is not set
1854*4882a593Smuzhiyun  * and the touch id is active. Generates a TouchEnd event if end is set and the
1855*4882a593Smuzhiyun  * touch id is active.
1856*4882a593Smuzhiyun  *
1857*4882a593Smuzhiyun  * events is not NULL-terminated; the return value is the number of events.
1858*4882a593Smuzhiyun  * The DDX is responsible for allocating the event structure in the first
1859*4882a593Smuzhiyun  * place via GetMaximumEventsNum(), and for freeing it.
1860*4882a593Smuzhiyun  *
1861*4882a593Smuzhiyun  * @param[out] events The list of events generated
1862*4882a593Smuzhiyun  * @param dev The device to generate the events for
1863*4882a593Smuzhiyun  * @param ddx_touchid The touch ID as assigned by the DDX
1864*4882a593Smuzhiyun  * @param type XI_TouchBegin, XI_TouchUpdate or XI_TouchEnd
1865*4882a593Smuzhiyun  * @param flags Event flags
1866*4882a593Smuzhiyun  * @param mask_in Valuator information for this event
1867*4882a593Smuzhiyun  */
1868*4882a593Smuzhiyun int
GetTouchEvents(InternalEvent * events,DeviceIntPtr dev,uint32_t ddx_touchid,uint16_t type,uint32_t flags,const ValuatorMask * mask_in)1869*4882a593Smuzhiyun GetTouchEvents(InternalEvent *events, DeviceIntPtr dev, uint32_t ddx_touchid,
1870*4882a593Smuzhiyun                uint16_t type, uint32_t flags, const ValuatorMask *mask_in)
1871*4882a593Smuzhiyun {
1872*4882a593Smuzhiyun     ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
1873*4882a593Smuzhiyun     TouchClassPtr t = dev->touch;
1874*4882a593Smuzhiyun     ValuatorClassPtr v = dev->valuator;
1875*4882a593Smuzhiyun     DeviceEvent *event;
1876*4882a593Smuzhiyun     CARD32 ms = GetTimeInMillis();
1877*4882a593Smuzhiyun     ValuatorMask mask;
1878*4882a593Smuzhiyun     double screenx = 0.0, screeny = 0.0;        /* desktop coordinate system */
1879*4882a593Smuzhiyun     double devx = 0.0, devy = 0.0;      /* desktop-wide in device coords */
1880*4882a593Smuzhiyun     int i;
1881*4882a593Smuzhiyun     int num_events = 0;
1882*4882a593Smuzhiyun     RawDeviceEvent *raw;
1883*4882a593Smuzhiyun     DDXTouchPointInfoPtr ti;
1884*4882a593Smuzhiyun     int need_rawevent = TRUE;
1885*4882a593Smuzhiyun     Bool emulate_pointer = FALSE;
1886*4882a593Smuzhiyun     int client_id = 0;
1887*4882a593Smuzhiyun 
1888*4882a593Smuzhiyun #if XSERVER_DTRACE
1889*4882a593Smuzhiyun     if (XSERVER_INPUT_EVENT_ENABLED()) {
1890*4882a593Smuzhiyun         XSERVER_INPUT_EVENT(dev->id, type, ddx_touchid, flags,
1891*4882a593Smuzhiyun                             mask_in ? mask_in->last_bit + 1 : 0,
1892*4882a593Smuzhiyun                             mask_in ? mask_in->mask : NULL,
1893*4882a593Smuzhiyun                             mask_in ? mask_in->valuators : NULL);
1894*4882a593Smuzhiyun     }
1895*4882a593Smuzhiyun #endif
1896*4882a593Smuzhiyun 
1897*4882a593Smuzhiyun     if (!dev->enabled || !t || !v)
1898*4882a593Smuzhiyun         return 0;
1899*4882a593Smuzhiyun 
1900*4882a593Smuzhiyun     /* Find and/or create the DDX touch info */
1901*4882a593Smuzhiyun 
1902*4882a593Smuzhiyun     ti = TouchFindByDDXID(dev, ddx_touchid, (type == XI_TouchBegin));
1903*4882a593Smuzhiyun     if (!ti) {
1904*4882a593Smuzhiyun         ErrorFSigSafe("[dix] %s: unable to %s touch point %u\n", dev->name,
1905*4882a593Smuzhiyun                       type == XI_TouchBegin ? "begin" : "find", ddx_touchid);
1906*4882a593Smuzhiyun         return 0;
1907*4882a593Smuzhiyun     }
1908*4882a593Smuzhiyun     client_id = ti->client_id;
1909*4882a593Smuzhiyun 
1910*4882a593Smuzhiyun     emulate_pointer = ti->emulate_pointer;
1911*4882a593Smuzhiyun 
1912*4882a593Smuzhiyun     if (!IsMaster(dev))
1913*4882a593Smuzhiyun         events =
1914*4882a593Smuzhiyun             UpdateFromMaster(events, dev, DEVCHANGE_POINTER_EVENT, &num_events);
1915*4882a593Smuzhiyun 
1916*4882a593Smuzhiyun     valuator_mask_copy(&mask, mask_in);
1917*4882a593Smuzhiyun 
1918*4882a593Smuzhiyun     if (need_rawevent) {
1919*4882a593Smuzhiyun         raw = &events->raw_event;
1920*4882a593Smuzhiyun         events++;
1921*4882a593Smuzhiyun         num_events++;
1922*4882a593Smuzhiyun         init_raw(dev, raw, ms, type, client_id);
1923*4882a593Smuzhiyun         set_raw_valuators(raw, &mask, TRUE, raw->valuators.data_raw);
1924*4882a593Smuzhiyun     }
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun     event = &events->device_event;
1927*4882a593Smuzhiyun     num_events++;
1928*4882a593Smuzhiyun 
1929*4882a593Smuzhiyun     init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
1930*4882a593Smuzhiyun 
1931*4882a593Smuzhiyun     switch (type) {
1932*4882a593Smuzhiyun     case XI_TouchBegin:
1933*4882a593Smuzhiyun         event->type = ET_TouchBegin;
1934*4882a593Smuzhiyun         /* If we're starting a touch, we must have x & y co-ordinates. */
1935*4882a593Smuzhiyun         if (!mask_in ||
1936*4882a593Smuzhiyun             !valuator_mask_isset(mask_in, 0) ||
1937*4882a593Smuzhiyun             !valuator_mask_isset(mask_in, 1)) {
1938*4882a593Smuzhiyun             ErrorFSigSafe("%s: Attempted to start touch without x/y "
1939*4882a593Smuzhiyun                           "(driver bug)\n", dev->name);
1940*4882a593Smuzhiyun             return 0;
1941*4882a593Smuzhiyun         }
1942*4882a593Smuzhiyun         break;
1943*4882a593Smuzhiyun     case XI_TouchUpdate:
1944*4882a593Smuzhiyun         event->type = ET_TouchUpdate;
1945*4882a593Smuzhiyun         if (!mask_in || valuator_mask_num_valuators(mask_in) <= 0) {
1946*4882a593Smuzhiyun             ErrorFSigSafe("%s: TouchUpdate with no valuators? Driver bug\n",
1947*4882a593Smuzhiyun                           dev->name);
1948*4882a593Smuzhiyun         }
1949*4882a593Smuzhiyun         break;
1950*4882a593Smuzhiyun     case XI_TouchEnd:
1951*4882a593Smuzhiyun         event->type = ET_TouchEnd;
1952*4882a593Smuzhiyun         /* We can end the DDX touch here, since we don't use the active
1953*4882a593Smuzhiyun          * field below */
1954*4882a593Smuzhiyun         TouchEndDDXTouch(dev, ti);
1955*4882a593Smuzhiyun         break;
1956*4882a593Smuzhiyun     default:
1957*4882a593Smuzhiyun         return 0;
1958*4882a593Smuzhiyun     }
1959*4882a593Smuzhiyun 
1960*4882a593Smuzhiyun     /* Get our screen event co-ordinates (root_x/root_y/event_x/event_y):
1961*4882a593Smuzhiyun      * these come from the touchpoint in Absolute mode, or the sprite in
1962*4882a593Smuzhiyun      * Relative. */
1963*4882a593Smuzhiyun     if (t->mode == XIDirectTouch) {
1964*4882a593Smuzhiyun         for (i = 0; i < max(valuator_mask_size(&mask), 2); i++) {
1965*4882a593Smuzhiyun             double val;
1966*4882a593Smuzhiyun 
1967*4882a593Smuzhiyun             if (valuator_mask_fetch_double(&mask, i, &val))
1968*4882a593Smuzhiyun                 valuator_mask_set_double(ti->valuators, i, val);
1969*4882a593Smuzhiyun             /* If the device doesn't post new X and Y axis values,
1970*4882a593Smuzhiyun              * use the last values posted.
1971*4882a593Smuzhiyun              */
1972*4882a593Smuzhiyun             else if (i < 2 &&
1973*4882a593Smuzhiyun                 valuator_mask_fetch_double(ti->valuators, i, &val))
1974*4882a593Smuzhiyun                 valuator_mask_set_double(&mask, i, val);
1975*4882a593Smuzhiyun         }
1976*4882a593Smuzhiyun 
1977*4882a593Smuzhiyun         transformAbsolute(dev, &mask);
1978*4882a593Smuzhiyun         clipAbsolute(dev, &mask);
1979*4882a593Smuzhiyun     }
1980*4882a593Smuzhiyun     else {
1981*4882a593Smuzhiyun         screenx = dev->spriteInfo->sprite->hotPhys.x;
1982*4882a593Smuzhiyun         screeny = dev->spriteInfo->sprite->hotPhys.y;
1983*4882a593Smuzhiyun     }
1984*4882a593Smuzhiyun     if (need_rawevent)
1985*4882a593Smuzhiyun         set_raw_valuators(raw, &mask, FALSE, raw->valuators.data);
1986*4882a593Smuzhiyun 
1987*4882a593Smuzhiyun     /* Indirect device touch coordinates are not used for cursor positioning.
1988*4882a593Smuzhiyun      * They are merely informational, and are provided in device coordinates.
1989*4882a593Smuzhiyun      * The device sprite is used for positioning instead, and it is already
1990*4882a593Smuzhiyun      * scaled. */
1991*4882a593Smuzhiyun     if (t->mode == XIDirectTouch)
1992*4882a593Smuzhiyun         scr = scale_to_desktop(dev, &mask, &devx, &devy, &screenx, &screeny);
1993*4882a593Smuzhiyun     if (emulate_pointer)
1994*4882a593Smuzhiyun         scr = positionSprite(dev, Absolute, &mask,
1995*4882a593Smuzhiyun                              &devx, &devy, &screenx, &screeny, NULL, NULL);
1996*4882a593Smuzhiyun 
1997*4882a593Smuzhiyun     /* see fill_pointer_events for coordinate systems */
1998*4882a593Smuzhiyun     if (emulate_pointer)
1999*4882a593Smuzhiyun         updateHistory(dev, &mask, ms);
2000*4882a593Smuzhiyun 
2001*4882a593Smuzhiyun     clipValuators(dev, &mask);
2002*4882a593Smuzhiyun 
2003*4882a593Smuzhiyun     if (emulate_pointer)
2004*4882a593Smuzhiyun         storeLastValuators(dev, &mask, 0, 1, devx, devy);
2005*4882a593Smuzhiyun 
2006*4882a593Smuzhiyun     /* Update the MD's co-ordinates, which are always in desktop space. */
2007*4882a593Smuzhiyun     if (emulate_pointer && !IsMaster(dev) && !IsFloating(dev)) {
2008*4882a593Smuzhiyun 	    DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
2009*4882a593Smuzhiyun 
2010*4882a593Smuzhiyun 	    master->last.valuators[0] = screenx;
2011*4882a593Smuzhiyun 	    master->last.valuators[1] = screeny;
2012*4882a593Smuzhiyun     }
2013*4882a593Smuzhiyun 
2014*4882a593Smuzhiyun     event->root = scr->root->drawable.id;
2015*4882a593Smuzhiyun 
2016*4882a593Smuzhiyun     event_set_root_coordinates(event, screenx - scr->x, screeny - scr->y);
2017*4882a593Smuzhiyun     event->touchid = client_id;
2018*4882a593Smuzhiyun     event->flags = flags;
2019*4882a593Smuzhiyun 
2020*4882a593Smuzhiyun     if (emulate_pointer) {
2021*4882a593Smuzhiyun         event->flags |= TOUCH_POINTER_EMULATED;
2022*4882a593Smuzhiyun         event->detail.button = 1;
2023*4882a593Smuzhiyun     }
2024*4882a593Smuzhiyun 
2025*4882a593Smuzhiyun     set_valuators(dev, event, &mask);
2026*4882a593Smuzhiyun     for (i = 0; i < v->numAxes; i++) {
2027*4882a593Smuzhiyun         if (valuator_mask_isset(&mask, i))
2028*4882a593Smuzhiyun             v->axisVal[i] = valuator_mask_get(&mask, i);
2029*4882a593Smuzhiyun     }
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun     return num_events;
2032*4882a593Smuzhiyun }
2033*4882a593Smuzhiyun 
2034*4882a593Smuzhiyun void
GetDixTouchEnd(InternalEvent * ievent,DeviceIntPtr dev,TouchPointInfoPtr ti,uint32_t flags)2035*4882a593Smuzhiyun GetDixTouchEnd(InternalEvent *ievent, DeviceIntPtr dev, TouchPointInfoPtr ti,
2036*4882a593Smuzhiyun                uint32_t flags)
2037*4882a593Smuzhiyun {
2038*4882a593Smuzhiyun     ScreenPtr scr = dev->spriteInfo->sprite->hotPhys.pScreen;
2039*4882a593Smuzhiyun     DeviceEvent *event = &ievent->device_event;
2040*4882a593Smuzhiyun     CARD32 ms = GetTimeInMillis();
2041*4882a593Smuzhiyun 
2042*4882a593Smuzhiyun     BUG_WARN(!dev->enabled);
2043*4882a593Smuzhiyun 
2044*4882a593Smuzhiyun     init_device_event(event, dev, ms, EVENT_SOURCE_NORMAL);
2045*4882a593Smuzhiyun 
2046*4882a593Smuzhiyun     event->sourceid = ti->sourceid;
2047*4882a593Smuzhiyun     event->type = ET_TouchEnd;
2048*4882a593Smuzhiyun 
2049*4882a593Smuzhiyun     event->root = scr->root->drawable.id;
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun     /* Get screen event coordinates from the sprite.  Is this really the best
2052*4882a593Smuzhiyun      * we can do? */
2053*4882a593Smuzhiyun     event_set_root_coordinates(event,
2054*4882a593Smuzhiyun                                dev->last.valuators[0] - scr->x,
2055*4882a593Smuzhiyun                                dev->last.valuators[1] - scr->y);
2056*4882a593Smuzhiyun     event->touchid = ti->client_id;
2057*4882a593Smuzhiyun     event->flags = flags;
2058*4882a593Smuzhiyun 
2059*4882a593Smuzhiyun     if (flags & TOUCH_POINTER_EMULATED) {
2060*4882a593Smuzhiyun         event->flags |= TOUCH_POINTER_EMULATED;
2061*4882a593Smuzhiyun         event->detail.button = 1;
2062*4882a593Smuzhiyun     }
2063*4882a593Smuzhiyun }
2064*4882a593Smuzhiyun 
2065*4882a593Smuzhiyun /**
2066*4882a593Smuzhiyun  * Synthesize a single motion event for the core pointer.
2067*4882a593Smuzhiyun  *
2068*4882a593Smuzhiyun  * Used in cursor functions, e.g. when cursor confinement changes, and we need
2069*4882a593Smuzhiyun  * to shift the pointer to get it inside the new bounds.
2070*4882a593Smuzhiyun  */
2071*4882a593Smuzhiyun void
PostSyntheticMotion(DeviceIntPtr pDev,int x,int y,int screen,unsigned long time)2072*4882a593Smuzhiyun PostSyntheticMotion(DeviceIntPtr pDev,
2073*4882a593Smuzhiyun                     int x, int y, int screen, unsigned long time)
2074*4882a593Smuzhiyun {
2075*4882a593Smuzhiyun     DeviceEvent ev;
2076*4882a593Smuzhiyun 
2077*4882a593Smuzhiyun #ifdef PANORAMIX
2078*4882a593Smuzhiyun     /* Translate back to the sprite screen since processInputProc
2079*4882a593Smuzhiyun        will translate from sprite screen to screen 0 upon reentry
2080*4882a593Smuzhiyun        to the DIX layer. */
2081*4882a593Smuzhiyun     if (!noPanoramiXExtension) {
2082*4882a593Smuzhiyun         x += screenInfo.screens[0]->x - screenInfo.screens[screen]->x;
2083*4882a593Smuzhiyun         y += screenInfo.screens[0]->y - screenInfo.screens[screen]->y;
2084*4882a593Smuzhiyun     }
2085*4882a593Smuzhiyun #endif
2086*4882a593Smuzhiyun 
2087*4882a593Smuzhiyun     memset(&ev, 0, sizeof(DeviceEvent));
2088*4882a593Smuzhiyun     init_device_event(&ev, pDev, time, EVENT_SOURCE_NORMAL);
2089*4882a593Smuzhiyun     ev.root_x = x;
2090*4882a593Smuzhiyun     ev.root_y = y;
2091*4882a593Smuzhiyun     ev.type = ET_Motion;
2092*4882a593Smuzhiyun     ev.time = time;
2093*4882a593Smuzhiyun 
2094*4882a593Smuzhiyun     /* FIXME: MD/SD considerations? */
2095*4882a593Smuzhiyun     (*pDev->public.processInputProc) ((InternalEvent *) &ev, pDev);
2096*4882a593Smuzhiyun }
2097