xref: /OK3568_Linux_fs/external/xserver/dix/inpututils.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2008 Daniel Stone
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission is hereby granted, free of charge, to any person obtaining a
5*4882a593Smuzhiyun  * copy of this software and associated documentation files (the "Software"),
6*4882a593Smuzhiyun  * to deal in the Software without restriction, including without limitation
7*4882a593Smuzhiyun  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*4882a593Smuzhiyun  * and/or sell copies of the Software, and to permit persons to whom the
9*4882a593Smuzhiyun  * Software is furnished to do so, subject to the following conditions:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * The above copyright notice and this permission notice (including the next
12*4882a593Smuzhiyun  * paragraph) shall be included in all copies or substantial portions of the
13*4882a593Smuzhiyun  * Software.
14*4882a593Smuzhiyun  *
15*4882a593Smuzhiyun  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*4882a593Smuzhiyun  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*4882a593Smuzhiyun  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18*4882a593Smuzhiyun  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*4882a593Smuzhiyun  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20*4882a593Smuzhiyun  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21*4882a593Smuzhiyun  * DEALINGS IN THE SOFTWARE.
22*4882a593Smuzhiyun  *
23*4882a593Smuzhiyun  * Author: Daniel Stone <daniel@fooishbar.org>
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
27*4882a593Smuzhiyun #include "dix-config.h"
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include "exevents.h"
31*4882a593Smuzhiyun #include "exglobals.h"
32*4882a593Smuzhiyun #include "misc.h"
33*4882a593Smuzhiyun #include "input.h"
34*4882a593Smuzhiyun #include "inputstr.h"
35*4882a593Smuzhiyun #include "xace.h"
36*4882a593Smuzhiyun #include "xkbsrv.h"
37*4882a593Smuzhiyun #include "xkbstr.h"
38*4882a593Smuzhiyun #include "inpututils.h"
39*4882a593Smuzhiyun #include "eventstr.h"
40*4882a593Smuzhiyun #include "scrnintstr.h"
41*4882a593Smuzhiyun #include "optionstr.h"
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* Check if a button map change is okay with the device.
44*4882a593Smuzhiyun  * Returns -1 for BadValue, as it collides with MappingBusy. */
45*4882a593Smuzhiyun static int
check_butmap_change(DeviceIntPtr dev,CARD8 * map,int len,CARD32 * errval_out,ClientPtr client)46*4882a593Smuzhiyun check_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out,
47*4882a593Smuzhiyun                     ClientPtr client)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun     int i, ret;
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun     if (!dev || !dev->button) {
52*4882a593Smuzhiyun         client->errorValue = (dev) ? dev->id : 0;
53*4882a593Smuzhiyun         return BadDevice;
54*4882a593Smuzhiyun     }
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun     ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
57*4882a593Smuzhiyun     if (ret != Success) {
58*4882a593Smuzhiyun         client->errorValue = dev->id;
59*4882a593Smuzhiyun         return ret;
60*4882a593Smuzhiyun     }
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun     for (i = 0; i < len; i++) {
63*4882a593Smuzhiyun         if (dev->button->map[i + 1] != map[i] &&
64*4882a593Smuzhiyun             button_is_down(dev, i + 1, BUTTON_PROCESSED))
65*4882a593Smuzhiyun             return MappingBusy;
66*4882a593Smuzhiyun     }
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun     return Success;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun static void
do_butmap_change(DeviceIntPtr dev,CARD8 * map,int len,ClientPtr client)72*4882a593Smuzhiyun do_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun     int i;
75*4882a593Smuzhiyun     xEvent core_mn = { .u.u.type = MappingNotify };
76*4882a593Smuzhiyun     deviceMappingNotify xi_mn;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun     /* The map in ButtonClassRec refers to button numbers, whereas the
79*4882a593Smuzhiyun      * protocol is zero-indexed.  Sigh. */
80*4882a593Smuzhiyun     memcpy(&(dev->button->map[1]), map, len);
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun     core_mn.u.mappingNotify.request = MappingPointer;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun     /* 0 is the server client. */
85*4882a593Smuzhiyun     for (i = 1; i < currentMaxClients; i++) {
86*4882a593Smuzhiyun         /* Don't send irrelevant events to naïve clients. */
87*4882a593Smuzhiyun         if (!clients[i] || clients[i]->clientState != ClientStateRunning)
88*4882a593Smuzhiyun             continue;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun         if (!XIShouldNotify(clients[i], dev))
91*4882a593Smuzhiyun             continue;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun         WriteEventsToClient(clients[i], 1, &core_mn);
94*4882a593Smuzhiyun     }
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     xi_mn = (deviceMappingNotify) {
97*4882a593Smuzhiyun         .type = DeviceMappingNotify,
98*4882a593Smuzhiyun         .request = MappingPointer,
99*4882a593Smuzhiyun         .deviceid = dev->id,
100*4882a593Smuzhiyun         .time = GetTimeInMillis()
101*4882a593Smuzhiyun     };
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun     SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /*
107*4882a593Smuzhiyun  * Does what it says on the box, both for core and Xi.
108*4882a593Smuzhiyun  *
109*4882a593Smuzhiyun  * Faithfully reports any errors encountered while trying to apply the map
110*4882a593Smuzhiyun  * to the requested device, faithfully ignores any errors encountered while
111*4882a593Smuzhiyun  * trying to apply the map to its master/slaves.
112*4882a593Smuzhiyun  */
113*4882a593Smuzhiyun int
ApplyPointerMapping(DeviceIntPtr dev,CARD8 * map,int len,ClientPtr client)114*4882a593Smuzhiyun ApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun     int ret;
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun     /* If we can't perform the change on the requested device, bail out. */
119*4882a593Smuzhiyun     ret = check_butmap_change(dev, map, len, &client->errorValue, client);
120*4882a593Smuzhiyun     if (ret != Success)
121*4882a593Smuzhiyun         return ret;
122*4882a593Smuzhiyun     do_butmap_change(dev, map, len, client);
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     return Success;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /* Check if a modifier map change is okay with the device.
128*4882a593Smuzhiyun  * Returns -1 for BadValue, as it collides with MappingBusy; this particular
129*4882a593Smuzhiyun  * caveat can be removed with LegalModifier, as we have no other reason to
130*4882a593Smuzhiyun  * set MappingFailed.  Sigh. */
131*4882a593Smuzhiyun static int
check_modmap_change(ClientPtr client,DeviceIntPtr dev,KeyCode * modmap)132*4882a593Smuzhiyun check_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun     int ret, i;
135*4882a593Smuzhiyun     XkbDescPtr xkb;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
138*4882a593Smuzhiyun     if (ret != Success)
139*4882a593Smuzhiyun         return ret;
140*4882a593Smuzhiyun 
141*4882a593Smuzhiyun     if (!dev->key)
142*4882a593Smuzhiyun         return BadMatch;
143*4882a593Smuzhiyun     xkb = dev->key->xkbInfo->desc;
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun     for (i = 0; i < MAP_LENGTH; i++) {
146*4882a593Smuzhiyun         if (!modmap[i])
147*4882a593Smuzhiyun             continue;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun         /* Check that all the new modifiers fall within the advertised
150*4882a593Smuzhiyun          * keycode range. */
151*4882a593Smuzhiyun         if (i < xkb->min_key_code || i > xkb->max_key_code) {
152*4882a593Smuzhiyun             client->errorValue = i;
153*4882a593Smuzhiyun             return -1;
154*4882a593Smuzhiyun         }
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun         /* Make sure the mapping is okay with the DDX. */
157*4882a593Smuzhiyun         if (!LegalModifier(i, dev)) {
158*4882a593Smuzhiyun             client->errorValue = i;
159*4882a593Smuzhiyun             return MappingFailed;
160*4882a593Smuzhiyun         }
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun         /* None of the new modifiers may be down while we change the
163*4882a593Smuzhiyun          * map. */
164*4882a593Smuzhiyun         if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
165*4882a593Smuzhiyun             client->errorValue = i;
166*4882a593Smuzhiyun             return MappingBusy;
167*4882a593Smuzhiyun         }
168*4882a593Smuzhiyun     }
169*4882a593Smuzhiyun 
170*4882a593Smuzhiyun     /* None of the old modifiers may be down while we change the map,
171*4882a593Smuzhiyun      * either. */
172*4882a593Smuzhiyun     for (i = xkb->min_key_code; i < xkb->max_key_code; i++) {
173*4882a593Smuzhiyun         if (!xkb->map->modmap[i])
174*4882a593Smuzhiyun             continue;
175*4882a593Smuzhiyun         if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) {
176*4882a593Smuzhiyun             client->errorValue = i;
177*4882a593Smuzhiyun             return MappingBusy;
178*4882a593Smuzhiyun         }
179*4882a593Smuzhiyun     }
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun     return Success;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static int
check_modmap_change_slave(ClientPtr client,DeviceIntPtr master,DeviceIntPtr slave,CARD8 * modmap)185*4882a593Smuzhiyun check_modmap_change_slave(ClientPtr client, DeviceIntPtr master,
186*4882a593Smuzhiyun                           DeviceIntPtr slave, CARD8 *modmap)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun     XkbDescPtr master_xkb, slave_xkb;
189*4882a593Smuzhiyun     int i, j;
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun     if (!slave->key || !master->key)
192*4882a593Smuzhiyun         return 0;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun     master_xkb = master->key->xkbInfo->desc;
195*4882a593Smuzhiyun     slave_xkb = slave->key->xkbInfo->desc;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     /* Ignore devices with a clearly different keymap. */
198*4882a593Smuzhiyun     if (slave_xkb->min_key_code != master_xkb->min_key_code ||
199*4882a593Smuzhiyun         slave_xkb->max_key_code != master_xkb->max_key_code)
200*4882a593Smuzhiyun         return 0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     for (i = 0; i < MAP_LENGTH; i++) {
203*4882a593Smuzhiyun         if (!modmap[i])
204*4882a593Smuzhiyun             continue;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun         /* If we have different symbols for any modifier on an
207*4882a593Smuzhiyun          * extended keyboard, ignore the whole remap request. */
208*4882a593Smuzhiyun         for (j = 0;
209*4882a593Smuzhiyun              j < XkbKeyNumSyms(slave_xkb, i) &&
210*4882a593Smuzhiyun              j < XkbKeyNumSyms(master_xkb, i); j++)
211*4882a593Smuzhiyun             if (XkbKeySymsPtr(slave_xkb, i)[j] !=
212*4882a593Smuzhiyun                 XkbKeySymsPtr(master_xkb, i)[j])
213*4882a593Smuzhiyun                 return 0;
214*4882a593Smuzhiyun     }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun     if (check_modmap_change(client, slave, modmap) != Success)
217*4882a593Smuzhiyun         return 0;
218*4882a593Smuzhiyun 
219*4882a593Smuzhiyun     return 1;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun /* Actually change the modifier map, and send notifications.  Cannot fail. */
223*4882a593Smuzhiyun static void
do_modmap_change(ClientPtr client,DeviceIntPtr dev,CARD8 * modmap)224*4882a593Smuzhiyun do_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun     XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun /* Rebuild modmap (key -> mod) from map (mod -> key). */
230*4882a593Smuzhiyun static int
build_modmap_from_modkeymap(CARD8 * modmap,KeyCode * modkeymap,int max_keys_per_mod)231*4882a593Smuzhiyun build_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap,
232*4882a593Smuzhiyun                             int max_keys_per_mod)
233*4882a593Smuzhiyun {
234*4882a593Smuzhiyun     int i, len = max_keys_per_mod * 8;
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     memset(modmap, 0, MAP_LENGTH);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     for (i = 0; i < len; i++) {
239*4882a593Smuzhiyun         if (!modkeymap[i])
240*4882a593Smuzhiyun             continue;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun #if MAP_LENGTH < 256
243*4882a593Smuzhiyun         if (modkeymap[i] >= MAP_LENGTH)
244*4882a593Smuzhiyun             return BadValue;
245*4882a593Smuzhiyun #endif
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun         if (modmap[modkeymap[i]])
248*4882a593Smuzhiyun             return BadValue;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun         modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod);
251*4882a593Smuzhiyun     }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun     return Success;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun int
change_modmap(ClientPtr client,DeviceIntPtr dev,KeyCode * modkeymap,int max_keys_per_mod)257*4882a593Smuzhiyun change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap,
258*4882a593Smuzhiyun               int max_keys_per_mod)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun     int ret;
261*4882a593Smuzhiyun     CARD8 modmap[MAP_LENGTH];
262*4882a593Smuzhiyun     DeviceIntPtr tmp;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun     ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod);
265*4882a593Smuzhiyun     if (ret != Success)
266*4882a593Smuzhiyun         return ret;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     /* If we can't perform the change on the requested device, bail out. */
269*4882a593Smuzhiyun     ret = check_modmap_change(client, dev, modmap);
270*4882a593Smuzhiyun     if (ret != Success)
271*4882a593Smuzhiyun         return ret;
272*4882a593Smuzhiyun     do_modmap_change(client, dev, modmap);
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun     /* Change any attached masters/slaves. */
275*4882a593Smuzhiyun     if (IsMaster(dev)) {
276*4882a593Smuzhiyun         for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
277*4882a593Smuzhiyun             if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev)
278*4882a593Smuzhiyun                 if (check_modmap_change_slave(client, dev, tmp, modmap))
279*4882a593Smuzhiyun                     do_modmap_change(client, tmp, modmap);
280*4882a593Smuzhiyun         }
281*4882a593Smuzhiyun     }
282*4882a593Smuzhiyun     else if (!IsFloating(dev) &&
283*4882a593Smuzhiyun              GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) {
284*4882a593Smuzhiyun         /* If this fails, expect the results to be weird. */
285*4882a593Smuzhiyun         if (check_modmap_change(client, dev->master, modmap) == Success)
286*4882a593Smuzhiyun             do_modmap_change(client, dev->master, modmap);
287*4882a593Smuzhiyun     }
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun     return Success;
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun int
generate_modkeymap(ClientPtr client,DeviceIntPtr dev,KeyCode ** modkeymap_out,int * max_keys_per_mod_out)293*4882a593Smuzhiyun generate_modkeymap(ClientPtr client, DeviceIntPtr dev,
294*4882a593Smuzhiyun                    KeyCode **modkeymap_out, int *max_keys_per_mod_out)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun     CARD8 keys_per_mod[8];
297*4882a593Smuzhiyun     int max_keys_per_mod;
298*4882a593Smuzhiyun     KeyCode *modkeymap = NULL;
299*4882a593Smuzhiyun     int i, j, ret;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun     ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
302*4882a593Smuzhiyun     if (ret != Success)
303*4882a593Smuzhiyun         return ret;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun     if (!dev->key)
306*4882a593Smuzhiyun         return BadMatch;
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun     /* Count the number of keys per modifier to determine how wide we
309*4882a593Smuzhiyun      * should make the map. */
310*4882a593Smuzhiyun     max_keys_per_mod = 0;
311*4882a593Smuzhiyun     for (i = 0; i < 8; i++)
312*4882a593Smuzhiyun         keys_per_mod[i] = 0;
313*4882a593Smuzhiyun     for (i = 8; i < MAP_LENGTH; i++) {
314*4882a593Smuzhiyun         for (j = 0; j < 8; j++) {
315*4882a593Smuzhiyun             if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
316*4882a593Smuzhiyun                 if (++keys_per_mod[j] > max_keys_per_mod)
317*4882a593Smuzhiyun                     max_keys_per_mod = keys_per_mod[j];
318*4882a593Smuzhiyun             }
319*4882a593Smuzhiyun         }
320*4882a593Smuzhiyun     }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun     if (max_keys_per_mod != 0) {
323*4882a593Smuzhiyun         modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode));
324*4882a593Smuzhiyun         if (!modkeymap)
325*4882a593Smuzhiyun             return BadAlloc;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun         for (i = 0; i < 8; i++)
328*4882a593Smuzhiyun             keys_per_mod[i] = 0;
329*4882a593Smuzhiyun 
330*4882a593Smuzhiyun         for (i = 8; i < MAP_LENGTH; i++) {
331*4882a593Smuzhiyun             for (j = 0; j < 8; j++) {
332*4882a593Smuzhiyun                 if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) {
333*4882a593Smuzhiyun                     modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i;
334*4882a593Smuzhiyun                     keys_per_mod[j]++;
335*4882a593Smuzhiyun                 }
336*4882a593Smuzhiyun             }
337*4882a593Smuzhiyun         }
338*4882a593Smuzhiyun     }
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun     *max_keys_per_mod_out = max_keys_per_mod;
341*4882a593Smuzhiyun     *modkeymap_out = modkeymap;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     return Success;
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun 
346*4882a593Smuzhiyun /**
347*4882a593Smuzhiyun  * Duplicate the InputAttributes in the most obvious way.
348*4882a593Smuzhiyun  * No special memory handling is used to give drivers the maximum
349*4882a593Smuzhiyun  * flexibility with the data. Drivers should be able to call realloc on the
350*4882a593Smuzhiyun  * product string if needed and perform similar operations.
351*4882a593Smuzhiyun  */
352*4882a593Smuzhiyun InputAttributes *
DuplicateInputAttributes(InputAttributes * attrs)353*4882a593Smuzhiyun DuplicateInputAttributes(InputAttributes * attrs)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun     InputAttributes *new_attr;
356*4882a593Smuzhiyun     int ntags = 0;
357*4882a593Smuzhiyun     char **tags, **new_tags;
358*4882a593Smuzhiyun 
359*4882a593Smuzhiyun     if (!attrs)
360*4882a593Smuzhiyun         return NULL;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun     if (!(new_attr = calloc(1, sizeof(InputAttributes))))
363*4882a593Smuzhiyun         goto unwind;
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     if (attrs->product && !(new_attr->product = strdup(attrs->product)))
366*4882a593Smuzhiyun         goto unwind;
367*4882a593Smuzhiyun     if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor)))
368*4882a593Smuzhiyun         goto unwind;
369*4882a593Smuzhiyun     if (attrs->device && !(new_attr->device = strdup(attrs->device)))
370*4882a593Smuzhiyun         goto unwind;
371*4882a593Smuzhiyun     if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id)))
372*4882a593Smuzhiyun         goto unwind;
373*4882a593Smuzhiyun     if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id)))
374*4882a593Smuzhiyun         goto unwind;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun     new_attr->flags = attrs->flags;
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     if ((tags = attrs->tags)) {
379*4882a593Smuzhiyun         while (*tags++)
380*4882a593Smuzhiyun             ntags++;
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun         new_attr->tags = calloc(ntags + 1, sizeof(char *));
383*4882a593Smuzhiyun         if (!new_attr->tags)
384*4882a593Smuzhiyun             goto unwind;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun         tags = attrs->tags;
387*4882a593Smuzhiyun         new_tags = new_attr->tags;
388*4882a593Smuzhiyun 
389*4882a593Smuzhiyun         while (*tags) {
390*4882a593Smuzhiyun             *new_tags = strdup(*tags);
391*4882a593Smuzhiyun             if (!*new_tags)
392*4882a593Smuzhiyun                 goto unwind;
393*4882a593Smuzhiyun 
394*4882a593Smuzhiyun             tags++;
395*4882a593Smuzhiyun             new_tags++;
396*4882a593Smuzhiyun         }
397*4882a593Smuzhiyun     }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun     return new_attr;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun  unwind:
402*4882a593Smuzhiyun     FreeInputAttributes(new_attr);
403*4882a593Smuzhiyun     return NULL;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun void
FreeInputAttributes(InputAttributes * attrs)407*4882a593Smuzhiyun FreeInputAttributes(InputAttributes * attrs)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun     char **tags;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun     if (!attrs)
412*4882a593Smuzhiyun         return;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun     free(attrs->product);
415*4882a593Smuzhiyun     free(attrs->vendor);
416*4882a593Smuzhiyun     free(attrs->device);
417*4882a593Smuzhiyun     free(attrs->pnp_id);
418*4882a593Smuzhiyun     free(attrs->usb_id);
419*4882a593Smuzhiyun 
420*4882a593Smuzhiyun     if ((tags = attrs->tags))
421*4882a593Smuzhiyun         while (*tags)
422*4882a593Smuzhiyun             free(*tags++);
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun     free(attrs->tags);
425*4882a593Smuzhiyun     free(attrs);
426*4882a593Smuzhiyun }
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun /**
429*4882a593Smuzhiyun  * Alloc a valuator mask large enough for num_valuators.
430*4882a593Smuzhiyun  */
431*4882a593Smuzhiyun ValuatorMask *
valuator_mask_new(int num_valuators)432*4882a593Smuzhiyun valuator_mask_new(int num_valuators)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun     /* alloc a fixed size mask for now and ignore num_valuators. in the
435*4882a593Smuzhiyun      * flying-car future, when we can dynamically alloc the masks and are
436*4882a593Smuzhiyun      * not constrained by signals, we can start using num_valuators */
437*4882a593Smuzhiyun     ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun     if (mask == NULL)
440*4882a593Smuzhiyun         return NULL;
441*4882a593Smuzhiyun 
442*4882a593Smuzhiyun     mask->last_bit = -1;
443*4882a593Smuzhiyun     return mask;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun void
valuator_mask_free(ValuatorMask ** mask)447*4882a593Smuzhiyun valuator_mask_free(ValuatorMask **mask)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun     free(*mask);
450*4882a593Smuzhiyun     *mask = NULL;
451*4882a593Smuzhiyun }
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun /**
454*4882a593Smuzhiyun  * Sets a range of valuators between first_valuator and num_valuators with
455*4882a593Smuzhiyun  * the data in the valuators array. All other values are set to 0.
456*4882a593Smuzhiyun  */
457*4882a593Smuzhiyun void
valuator_mask_set_range(ValuatorMask * mask,int first_valuator,int num_valuators,const int * valuators)458*4882a593Smuzhiyun valuator_mask_set_range(ValuatorMask *mask, int first_valuator,
459*4882a593Smuzhiyun                         int num_valuators, const int *valuators)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun     int i;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun     valuator_mask_zero(mask);
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     for (i = first_valuator;
466*4882a593Smuzhiyun          i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
467*4882a593Smuzhiyun         valuator_mask_set(mask, i, valuators[i - first_valuator]);
468*4882a593Smuzhiyun }
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun /**
471*4882a593Smuzhiyun  * Reset mask to zero.
472*4882a593Smuzhiyun  */
473*4882a593Smuzhiyun void
valuator_mask_zero(ValuatorMask * mask)474*4882a593Smuzhiyun valuator_mask_zero(ValuatorMask *mask)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun     memset(mask, 0, sizeof(*mask));
477*4882a593Smuzhiyun     mask->last_bit = -1;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun /**
481*4882a593Smuzhiyun  * Returns the current size of the mask (i.e. the highest number of
482*4882a593Smuzhiyun  * valuators currently set + 1).
483*4882a593Smuzhiyun  */
484*4882a593Smuzhiyun int
valuator_mask_size(const ValuatorMask * mask)485*4882a593Smuzhiyun valuator_mask_size(const ValuatorMask *mask)
486*4882a593Smuzhiyun {
487*4882a593Smuzhiyun     return mask->last_bit + 1;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun /**
491*4882a593Smuzhiyun  * Returns the number of valuators set in the given mask.
492*4882a593Smuzhiyun  */
493*4882a593Smuzhiyun int
valuator_mask_num_valuators(const ValuatorMask * mask)494*4882a593Smuzhiyun valuator_mask_num_valuators(const ValuatorMask *mask)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun     return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS));
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun /**
500*4882a593Smuzhiyun  * Return true if the valuator is set in the mask, or false otherwise.
501*4882a593Smuzhiyun  */
502*4882a593Smuzhiyun int
valuator_mask_isset(const ValuatorMask * mask,int valuator)503*4882a593Smuzhiyun valuator_mask_isset(const ValuatorMask *mask, int valuator)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun     return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
506*4882a593Smuzhiyun }
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun static inline void
_valuator_mask_set_double(ValuatorMask * mask,int valuator,double data)509*4882a593Smuzhiyun _valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
510*4882a593Smuzhiyun {
511*4882a593Smuzhiyun     mask->last_bit = max(valuator, mask->last_bit);
512*4882a593Smuzhiyun     SetBit(mask->mask, valuator);
513*4882a593Smuzhiyun     mask->valuators[valuator] = data;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun /**
517*4882a593Smuzhiyun  * Set the valuator to the given floating-point data.
518*4882a593Smuzhiyun  */
519*4882a593Smuzhiyun void
valuator_mask_set_double(ValuatorMask * mask,int valuator,double data)520*4882a593Smuzhiyun valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
521*4882a593Smuzhiyun {
522*4882a593Smuzhiyun     BUG_WARN_MSG(mask->has_unaccelerated,
523*4882a593Smuzhiyun                  "Do not mix valuator types, zero mask first\n");
524*4882a593Smuzhiyun     _valuator_mask_set_double(mask, valuator, data);
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun 
527*4882a593Smuzhiyun /**
528*4882a593Smuzhiyun  * Set the valuator to the given integer data.
529*4882a593Smuzhiyun  */
530*4882a593Smuzhiyun void
valuator_mask_set(ValuatorMask * mask,int valuator,int data)531*4882a593Smuzhiyun valuator_mask_set(ValuatorMask *mask, int valuator, int data)
532*4882a593Smuzhiyun {
533*4882a593Smuzhiyun     valuator_mask_set_double(mask, valuator, data);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun 
536*4882a593Smuzhiyun /**
537*4882a593Smuzhiyun  * Return the requested valuator value as a double. If the mask bit is not
538*4882a593Smuzhiyun  * set for the given valuator, the returned value is undefined.
539*4882a593Smuzhiyun  */
540*4882a593Smuzhiyun double
valuator_mask_get_double(const ValuatorMask * mask,int valuator)541*4882a593Smuzhiyun valuator_mask_get_double(const ValuatorMask *mask, int valuator)
542*4882a593Smuzhiyun {
543*4882a593Smuzhiyun     return mask->valuators[valuator];
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun /**
547*4882a593Smuzhiyun  * Return the requested valuator value as an integer, rounding towards zero.
548*4882a593Smuzhiyun  * If the mask bit is not set for the given valuator, the returned value is
549*4882a593Smuzhiyun  * undefined.
550*4882a593Smuzhiyun  */
551*4882a593Smuzhiyun int
valuator_mask_get(const ValuatorMask * mask,int valuator)552*4882a593Smuzhiyun valuator_mask_get(const ValuatorMask *mask, int valuator)
553*4882a593Smuzhiyun {
554*4882a593Smuzhiyun     return trunc(valuator_mask_get_double(mask, valuator));
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun /**
558*4882a593Smuzhiyun  * Set value to the requested valuator. If the mask bit is set for this
559*4882a593Smuzhiyun  * valuator, value contains the requested valuator value and TRUE is
560*4882a593Smuzhiyun  * returned.
561*4882a593Smuzhiyun  * If the mask bit is not set for this valuator, value is unchanged and
562*4882a593Smuzhiyun  * FALSE is returned.
563*4882a593Smuzhiyun  */
564*4882a593Smuzhiyun Bool
valuator_mask_fetch_double(const ValuatorMask * mask,int valuator,double * value)565*4882a593Smuzhiyun valuator_mask_fetch_double(const ValuatorMask *mask, int valuator,
566*4882a593Smuzhiyun                            double *value)
567*4882a593Smuzhiyun {
568*4882a593Smuzhiyun     if (valuator_mask_isset(mask, valuator)) {
569*4882a593Smuzhiyun         *value = valuator_mask_get_double(mask, valuator);
570*4882a593Smuzhiyun         return TRUE;
571*4882a593Smuzhiyun     }
572*4882a593Smuzhiyun     else
573*4882a593Smuzhiyun         return FALSE;
574*4882a593Smuzhiyun }
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun /**
577*4882a593Smuzhiyun  * Set value to the requested valuator. If the mask bit is set for this
578*4882a593Smuzhiyun  * valuator, value contains the requested valuator value and TRUE is
579*4882a593Smuzhiyun  * returned.
580*4882a593Smuzhiyun  * If the mask bit is not set for this valuator, value is unchanged and
581*4882a593Smuzhiyun  * FALSE is returned.
582*4882a593Smuzhiyun  */
583*4882a593Smuzhiyun Bool
valuator_mask_fetch(const ValuatorMask * mask,int valuator,int * value)584*4882a593Smuzhiyun valuator_mask_fetch(const ValuatorMask *mask, int valuator, int *value)
585*4882a593Smuzhiyun {
586*4882a593Smuzhiyun     if (valuator_mask_isset(mask, valuator)) {
587*4882a593Smuzhiyun         *value = valuator_mask_get(mask, valuator);
588*4882a593Smuzhiyun         return TRUE;
589*4882a593Smuzhiyun     }
590*4882a593Smuzhiyun     else
591*4882a593Smuzhiyun         return FALSE;
592*4882a593Smuzhiyun }
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun /**
595*4882a593Smuzhiyun  * Remove the valuator from the mask.
596*4882a593Smuzhiyun  */
597*4882a593Smuzhiyun void
valuator_mask_unset(ValuatorMask * mask,int valuator)598*4882a593Smuzhiyun valuator_mask_unset(ValuatorMask *mask, int valuator)
599*4882a593Smuzhiyun {
600*4882a593Smuzhiyun     if (mask->last_bit >= valuator) {
601*4882a593Smuzhiyun         int i, lastbit = -1;
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun         ClearBit(mask->mask, valuator);
604*4882a593Smuzhiyun         mask->valuators[valuator] = 0.0;
605*4882a593Smuzhiyun         mask->unaccelerated[valuator] = 0.0;
606*4882a593Smuzhiyun 
607*4882a593Smuzhiyun         for (i = 0; i <= mask->last_bit; i++)
608*4882a593Smuzhiyun             if (valuator_mask_isset(mask, i))
609*4882a593Smuzhiyun                 lastbit = max(lastbit, i);
610*4882a593Smuzhiyun         mask->last_bit = lastbit;
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun         if (mask->last_bit == -1)
613*4882a593Smuzhiyun             mask->has_unaccelerated = FALSE;
614*4882a593Smuzhiyun     }
615*4882a593Smuzhiyun }
616*4882a593Smuzhiyun 
617*4882a593Smuzhiyun void
valuator_mask_copy(ValuatorMask * dest,const ValuatorMask * src)618*4882a593Smuzhiyun valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
619*4882a593Smuzhiyun {
620*4882a593Smuzhiyun     if (src)
621*4882a593Smuzhiyun         memcpy(dest, src, sizeof(*dest));
622*4882a593Smuzhiyun     else
623*4882a593Smuzhiyun         valuator_mask_zero(dest);
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun Bool
valuator_mask_has_unaccelerated(const ValuatorMask * mask)627*4882a593Smuzhiyun valuator_mask_has_unaccelerated(const ValuatorMask *mask)
628*4882a593Smuzhiyun {
629*4882a593Smuzhiyun     return mask->has_unaccelerated;
630*4882a593Smuzhiyun }
631*4882a593Smuzhiyun 
632*4882a593Smuzhiyun void
valuator_mask_drop_unaccelerated(ValuatorMask * mask)633*4882a593Smuzhiyun valuator_mask_drop_unaccelerated(ValuatorMask *mask)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun     memset(mask->unaccelerated, 0, sizeof(mask->unaccelerated));
636*4882a593Smuzhiyun     mask->has_unaccelerated = FALSE;
637*4882a593Smuzhiyun }
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun void
valuator_mask_set_absolute_unaccelerated(ValuatorMask * mask,int valuator,int absolute,double unaccel)640*4882a593Smuzhiyun valuator_mask_set_absolute_unaccelerated(ValuatorMask *mask,
641*4882a593Smuzhiyun                                          int valuator,
642*4882a593Smuzhiyun                                          int absolute,
643*4882a593Smuzhiyun                                          double unaccel)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun     BUG_WARN_MSG(mask->last_bit != -1 && !mask->has_unaccelerated,
646*4882a593Smuzhiyun                  "Do not mix valuator types, zero mask first\n");
647*4882a593Smuzhiyun     _valuator_mask_set_double(mask, valuator, absolute);
648*4882a593Smuzhiyun     mask->has_unaccelerated = TRUE;
649*4882a593Smuzhiyun     mask->unaccelerated[valuator] = unaccel;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun /**
653*4882a593Smuzhiyun  * Set both accelerated and unaccelerated value for this mask.
654*4882a593Smuzhiyun  */
655*4882a593Smuzhiyun void
valuator_mask_set_unaccelerated(ValuatorMask * mask,int valuator,double accel,double unaccel)656*4882a593Smuzhiyun valuator_mask_set_unaccelerated(ValuatorMask *mask,
657*4882a593Smuzhiyun                                 int valuator,
658*4882a593Smuzhiyun                                 double accel,
659*4882a593Smuzhiyun                                 double unaccel)
660*4882a593Smuzhiyun {
661*4882a593Smuzhiyun     BUG_WARN_MSG(mask->last_bit != -1 && !mask->has_unaccelerated,
662*4882a593Smuzhiyun                  "Do not mix valuator types, zero mask first\n");
663*4882a593Smuzhiyun     _valuator_mask_set_double(mask, valuator, accel);
664*4882a593Smuzhiyun     mask->has_unaccelerated = TRUE;
665*4882a593Smuzhiyun     mask->unaccelerated[valuator] = unaccel;
666*4882a593Smuzhiyun }
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun double
valuator_mask_get_accelerated(const ValuatorMask * mask,int valuator)669*4882a593Smuzhiyun valuator_mask_get_accelerated(const ValuatorMask *mask,
670*4882a593Smuzhiyun                               int valuator)
671*4882a593Smuzhiyun {
672*4882a593Smuzhiyun     return valuator_mask_get_double(mask, valuator);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun double
valuator_mask_get_unaccelerated(const ValuatorMask * mask,int valuator)676*4882a593Smuzhiyun valuator_mask_get_unaccelerated(const ValuatorMask *mask,
677*4882a593Smuzhiyun                                 int valuator)
678*4882a593Smuzhiyun {
679*4882a593Smuzhiyun     return mask->unaccelerated[valuator];
680*4882a593Smuzhiyun }
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun Bool
valuator_mask_fetch_unaccelerated(const ValuatorMask * mask,int valuator,double * accel,double * unaccel)683*4882a593Smuzhiyun valuator_mask_fetch_unaccelerated(const ValuatorMask *mask,
684*4882a593Smuzhiyun                                   int valuator,
685*4882a593Smuzhiyun                                   double *accel,
686*4882a593Smuzhiyun                                   double *unaccel)
687*4882a593Smuzhiyun {
688*4882a593Smuzhiyun     if (valuator_mask_isset(mask, valuator)) {
689*4882a593Smuzhiyun         if (accel)
690*4882a593Smuzhiyun             *accel = valuator_mask_get_accelerated(mask, valuator);
691*4882a593Smuzhiyun         if (unaccel)
692*4882a593Smuzhiyun             *unaccel = valuator_mask_get_unaccelerated(mask, valuator);
693*4882a593Smuzhiyun         return TRUE;
694*4882a593Smuzhiyun     }
695*4882a593Smuzhiyun     else
696*4882a593Smuzhiyun         return FALSE;
697*4882a593Smuzhiyun }
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun int
CountBits(const uint8_t * mask,int len)700*4882a593Smuzhiyun CountBits(const uint8_t * mask, int len)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun     int i;
703*4882a593Smuzhiyun     int ret = 0;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun     for (i = 0; i < len; i++)
706*4882a593Smuzhiyun         if (BitIsOn(mask, i))
707*4882a593Smuzhiyun             ret++;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun     return ret;
710*4882a593Smuzhiyun }
711*4882a593Smuzhiyun 
712*4882a593Smuzhiyun /**
713*4882a593Smuzhiyun  * Verifies sanity of the event. If the event is not an internal event,
714*4882a593Smuzhiyun  * memdumps the first 32 bytes of event to the log, a backtrace, then kill
715*4882a593Smuzhiyun  * the server.
716*4882a593Smuzhiyun  */
717*4882a593Smuzhiyun void
verify_internal_event(const InternalEvent * ev)718*4882a593Smuzhiyun verify_internal_event(const InternalEvent *ev)
719*4882a593Smuzhiyun {
720*4882a593Smuzhiyun     if (ev && ev->any.header != ET_Internal) {
721*4882a593Smuzhiyun         int i;
722*4882a593Smuzhiyun         const unsigned char *data = (const unsigned char *) ev;
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun         ErrorF("dix: invalid event type %d\n", ev->any.header);
725*4882a593Smuzhiyun 
726*4882a593Smuzhiyun         for (i = 0; i < sizeof(xEvent); i++, data++) {
727*4882a593Smuzhiyun             ErrorF("%02hhx ", *data);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun             if ((i % 8) == 7)
730*4882a593Smuzhiyun                 ErrorF("\n");
731*4882a593Smuzhiyun         }
732*4882a593Smuzhiyun 
733*4882a593Smuzhiyun         xorg_backtrace();
734*4882a593Smuzhiyun         FatalError("Wrong event type %d. Aborting server\n", ev->any.header);
735*4882a593Smuzhiyun     }
736*4882a593Smuzhiyun }
737*4882a593Smuzhiyun 
738*4882a593Smuzhiyun /**
739*4882a593Smuzhiyun  * Initializes the given event to zero (or default values), for the given
740*4882a593Smuzhiyun  * device.
741*4882a593Smuzhiyun  */
742*4882a593Smuzhiyun void
init_device_event(DeviceEvent * event,DeviceIntPtr dev,Time ms,enum DeviceEventSource source_type)743*4882a593Smuzhiyun init_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms,
744*4882a593Smuzhiyun                   enum DeviceEventSource source_type)
745*4882a593Smuzhiyun {
746*4882a593Smuzhiyun     memset(event, 0, sizeof(DeviceEvent));
747*4882a593Smuzhiyun     event->header = ET_Internal;
748*4882a593Smuzhiyun     event->length = sizeof(DeviceEvent);
749*4882a593Smuzhiyun     event->time = ms;
750*4882a593Smuzhiyun     event->deviceid = dev->id;
751*4882a593Smuzhiyun     event->sourceid = dev->id;
752*4882a593Smuzhiyun     event->source_type = source_type;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun 
755*4882a593Smuzhiyun int
event_get_corestate(DeviceIntPtr mouse,DeviceIntPtr kbd)756*4882a593Smuzhiyun event_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd)
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun     int corestate;
759*4882a593Smuzhiyun 
760*4882a593Smuzhiyun     /* core state needs to be assembled BEFORE the device is updated. */
761*4882a593Smuzhiyun     corestate = (kbd &&
762*4882a593Smuzhiyun                  kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->
763*4882a593Smuzhiyun                                                   state) : 0;
764*4882a593Smuzhiyun     corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0;
765*4882a593Smuzhiyun     corestate |= (mouse && mouse->touch) ? (mouse->touch->state) : 0;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun     return corestate;
768*4882a593Smuzhiyun }
769*4882a593Smuzhiyun 
770*4882a593Smuzhiyun void
event_set_state(DeviceIntPtr mouse,DeviceIntPtr kbd,DeviceEvent * event)771*4882a593Smuzhiyun event_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event)
772*4882a593Smuzhiyun {
773*4882a593Smuzhiyun     int i;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
776*4882a593Smuzhiyun         if (BitIsOn(mouse->button->down, i))
777*4882a593Smuzhiyun             SetBit(event->buttons, mouse->button->map[i]);
778*4882a593Smuzhiyun 
779*4882a593Smuzhiyun     if (mouse && mouse->touch && mouse->touch->buttonsDown > 0)
780*4882a593Smuzhiyun         SetBit(event->buttons, mouse->button->map[1]);
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun     if (kbd && kbd->key) {
783*4882a593Smuzhiyun         XkbStatePtr state;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun         /* we need the state before the event happens */
786*4882a593Smuzhiyun         if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
787*4882a593Smuzhiyun             state = &kbd->key->xkbInfo->prev_state;
788*4882a593Smuzhiyun         else
789*4882a593Smuzhiyun             state = &kbd->key->xkbInfo->state;
790*4882a593Smuzhiyun 
791*4882a593Smuzhiyun         event->mods.base = state->base_mods;
792*4882a593Smuzhiyun         event->mods.latched = state->latched_mods;
793*4882a593Smuzhiyun         event->mods.locked = state->locked_mods;
794*4882a593Smuzhiyun         event->mods.effective = state->mods;
795*4882a593Smuzhiyun 
796*4882a593Smuzhiyun         event->group.base = state->base_group;
797*4882a593Smuzhiyun         event->group.latched = state->latched_group;
798*4882a593Smuzhiyun         event->group.locked = state->locked_group;
799*4882a593Smuzhiyun         event->group.effective = state->group;
800*4882a593Smuzhiyun     }
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun /**
804*4882a593Smuzhiyun  * Return the event filter mask for the given device and the given core or
805*4882a593Smuzhiyun  * XI1 protocol type.
806*4882a593Smuzhiyun  */
807*4882a593Smuzhiyun Mask
event_get_filter_from_type(DeviceIntPtr dev,int evtype)808*4882a593Smuzhiyun event_get_filter_from_type(DeviceIntPtr dev, int evtype)
809*4882a593Smuzhiyun {
810*4882a593Smuzhiyun     return event_filters[dev ? dev->id : 0][evtype];
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun /**
814*4882a593Smuzhiyun  * Return the event filter mask for the given device and the given core or
815*4882a593Smuzhiyun  * XI2 protocol type.
816*4882a593Smuzhiyun  */
817*4882a593Smuzhiyun Mask
event_get_filter_from_xi2type(int evtype)818*4882a593Smuzhiyun event_get_filter_from_xi2type(int evtype)
819*4882a593Smuzhiyun {
820*4882a593Smuzhiyun     return (1 << (evtype % 8));
821*4882a593Smuzhiyun }
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun Bool
point_on_screen(ScreenPtr pScreen,int x,int y)824*4882a593Smuzhiyun point_on_screen(ScreenPtr pScreen, int x, int y)
825*4882a593Smuzhiyun {
826*4882a593Smuzhiyun     return x >= pScreen->x && x < pScreen->x + pScreen->width &&
827*4882a593Smuzhiyun         y >= pScreen->y && y < pScreen->y + pScreen->height;
828*4882a593Smuzhiyun }
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun /**
831*4882a593Smuzhiyun  * Update desktop dimensions on the screenInfo struct.
832*4882a593Smuzhiyun  */
833*4882a593Smuzhiyun void
update_desktop_dimensions(void)834*4882a593Smuzhiyun update_desktop_dimensions(void)
835*4882a593Smuzhiyun {
836*4882a593Smuzhiyun     int i;
837*4882a593Smuzhiyun     int x1 = INT_MAX, y1 = INT_MAX;     /* top-left */
838*4882a593Smuzhiyun     int x2 = INT_MIN, y2 = INT_MIN;     /* bottom-right */
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun     for (i = 0; i < screenInfo.numScreens; i++) {
841*4882a593Smuzhiyun         ScreenPtr screen = screenInfo.screens[i];
842*4882a593Smuzhiyun 
843*4882a593Smuzhiyun         x1 = min(x1, screen->x);
844*4882a593Smuzhiyun         y1 = min(y1, screen->y);
845*4882a593Smuzhiyun         x2 = max(x2, screen->x + screen->width);
846*4882a593Smuzhiyun         y2 = max(y2, screen->y + screen->height);
847*4882a593Smuzhiyun     }
848*4882a593Smuzhiyun 
849*4882a593Smuzhiyun     screenInfo.x = x1;
850*4882a593Smuzhiyun     screenInfo.y = y1;
851*4882a593Smuzhiyun     screenInfo.width = x2 - x1;
852*4882a593Smuzhiyun     screenInfo.height = y2 - y1;
853*4882a593Smuzhiyun }
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun /*
856*4882a593Smuzhiyun  * Delete the element with the key from the list, freeing all memory
857*4882a593Smuzhiyun  * associated with the element..
858*4882a593Smuzhiyun  */
859*4882a593Smuzhiyun static void
input_option_free(InputOption * o)860*4882a593Smuzhiyun input_option_free(InputOption *o)
861*4882a593Smuzhiyun {
862*4882a593Smuzhiyun     free(o->opt_name);
863*4882a593Smuzhiyun     free(o->opt_val);
864*4882a593Smuzhiyun     free(o->opt_comment);
865*4882a593Smuzhiyun     free(o);
866*4882a593Smuzhiyun }
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun /*
869*4882a593Smuzhiyun  * Create a new InputOption with the key/value pair provided.
870*4882a593Smuzhiyun  * If a list is provided, the new options is added to the list and the list
871*4882a593Smuzhiyun  * is returned.
872*4882a593Smuzhiyun  *
873*4882a593Smuzhiyun  * If a new option is added to a list that already contains that option, the
874*4882a593Smuzhiyun  * previous option is overwritten.
875*4882a593Smuzhiyun  *
876*4882a593Smuzhiyun  * @param list The list to add to.
877*4882a593Smuzhiyun  * @param key Option key, will be copied.
878*4882a593Smuzhiyun  * @param value Option value, will be copied.
879*4882a593Smuzhiyun  *
880*4882a593Smuzhiyun  * @return If list is not NULL, the list with the new option added. If list
881*4882a593Smuzhiyun  * is NULL, a new option list with one element. On failure, NULL is
882*4882a593Smuzhiyun  * returned.
883*4882a593Smuzhiyun  */
884*4882a593Smuzhiyun InputOption *
input_option_new(InputOption * list,const char * key,const char * value)885*4882a593Smuzhiyun input_option_new(InputOption *list, const char *key, const char *value)
886*4882a593Smuzhiyun {
887*4882a593Smuzhiyun     InputOption *opt = NULL;
888*4882a593Smuzhiyun 
889*4882a593Smuzhiyun     if (!key)
890*4882a593Smuzhiyun         return NULL;
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun     if (list) {
893*4882a593Smuzhiyun         nt_list_for_each_entry(opt, list, list.next) {
894*4882a593Smuzhiyun             if (strcmp(input_option_get_key(opt), key) == 0) {
895*4882a593Smuzhiyun                 input_option_set_value(opt, value);
896*4882a593Smuzhiyun                 return list;
897*4882a593Smuzhiyun             }
898*4882a593Smuzhiyun         }
899*4882a593Smuzhiyun     }
900*4882a593Smuzhiyun 
901*4882a593Smuzhiyun     opt = calloc(1, sizeof(InputOption));
902*4882a593Smuzhiyun     if (!opt)
903*4882a593Smuzhiyun         return NULL;
904*4882a593Smuzhiyun 
905*4882a593Smuzhiyun     nt_list_init(opt, list.next);
906*4882a593Smuzhiyun     input_option_set_key(opt, key);
907*4882a593Smuzhiyun     input_option_set_value(opt, value);
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun     if (list) {
910*4882a593Smuzhiyun         nt_list_append(opt, list, InputOption, list.next);
911*4882a593Smuzhiyun 
912*4882a593Smuzhiyun         return list;
913*4882a593Smuzhiyun     }
914*4882a593Smuzhiyun     else
915*4882a593Smuzhiyun         return opt;
916*4882a593Smuzhiyun }
917*4882a593Smuzhiyun 
918*4882a593Smuzhiyun InputOption *
input_option_free_element(InputOption * list,const char * key)919*4882a593Smuzhiyun input_option_free_element(InputOption *list, const char *key)
920*4882a593Smuzhiyun {
921*4882a593Smuzhiyun     InputOption *element;
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun     nt_list_for_each_entry(element, list, list.next) {
924*4882a593Smuzhiyun         if (strcmp(input_option_get_key(element), key) == 0) {
925*4882a593Smuzhiyun             nt_list_del(element, list, InputOption, list.next);
926*4882a593Smuzhiyun 
927*4882a593Smuzhiyun             input_option_free(element);
928*4882a593Smuzhiyun             break;
929*4882a593Smuzhiyun         }
930*4882a593Smuzhiyun     }
931*4882a593Smuzhiyun     return list;
932*4882a593Smuzhiyun }
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun /**
935*4882a593Smuzhiyun  * Free the list pointed at by opt.
936*4882a593Smuzhiyun  */
937*4882a593Smuzhiyun void
input_option_free_list(InputOption ** opt)938*4882a593Smuzhiyun input_option_free_list(InputOption **opt)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun     InputOption *element, *tmp;
941*4882a593Smuzhiyun 
942*4882a593Smuzhiyun     nt_list_for_each_entry_safe(element, tmp, *opt, list.next) {
943*4882a593Smuzhiyun         nt_list_del(element, *opt, InputOption, list.next);
944*4882a593Smuzhiyun 
945*4882a593Smuzhiyun         input_option_free(element);
946*4882a593Smuzhiyun     }
947*4882a593Smuzhiyun     *opt = NULL;
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun /**
951*4882a593Smuzhiyun  * Find the InputOption with the given option name.
952*4882a593Smuzhiyun  *
953*4882a593Smuzhiyun  * @return The InputOption or NULL if not present.
954*4882a593Smuzhiyun  */
955*4882a593Smuzhiyun InputOption *
input_option_find(InputOption * list,const char * key)956*4882a593Smuzhiyun input_option_find(InputOption *list, const char *key)
957*4882a593Smuzhiyun {
958*4882a593Smuzhiyun     InputOption *element;
959*4882a593Smuzhiyun 
960*4882a593Smuzhiyun     nt_list_for_each_entry(element, list, list.next) {
961*4882a593Smuzhiyun         if (strcmp(input_option_get_key(element), key) == 0)
962*4882a593Smuzhiyun             return element;
963*4882a593Smuzhiyun     }
964*4882a593Smuzhiyun 
965*4882a593Smuzhiyun     return NULL;
966*4882a593Smuzhiyun }
967*4882a593Smuzhiyun 
968*4882a593Smuzhiyun const char *
input_option_get_key(const InputOption * opt)969*4882a593Smuzhiyun input_option_get_key(const InputOption *opt)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun     return opt->opt_name;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun 
974*4882a593Smuzhiyun const char *
input_option_get_value(const InputOption * opt)975*4882a593Smuzhiyun input_option_get_value(const InputOption *opt)
976*4882a593Smuzhiyun {
977*4882a593Smuzhiyun     return opt->opt_val;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun 
980*4882a593Smuzhiyun void
input_option_set_key(InputOption * opt,const char * key)981*4882a593Smuzhiyun input_option_set_key(InputOption *opt, const char *key)
982*4882a593Smuzhiyun {
983*4882a593Smuzhiyun     free(opt->opt_name);
984*4882a593Smuzhiyun     if (key)
985*4882a593Smuzhiyun         opt->opt_name = strdup(key);
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun 
988*4882a593Smuzhiyun void
input_option_set_value(InputOption * opt,const char * value)989*4882a593Smuzhiyun input_option_set_value(InputOption *opt, const char *value)
990*4882a593Smuzhiyun {
991*4882a593Smuzhiyun     free(opt->opt_val);
992*4882a593Smuzhiyun     if (value)
993*4882a593Smuzhiyun         opt->opt_val = strdup(value);
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun /* FP1616/FP3232 conversion functions.
997*4882a593Smuzhiyun  * Fixed point types are encoded as signed integral and unsigned frac. So any
998*4882a593Smuzhiyun  * negative number -n.m is encoded as floor(n) + (1 - 0.m).
999*4882a593Smuzhiyun  */
1000*4882a593Smuzhiyun double
fp1616_to_double(FP1616 in)1001*4882a593Smuzhiyun fp1616_to_double(FP1616 in)
1002*4882a593Smuzhiyun {
1003*4882a593Smuzhiyun     return pixman_fixed_to_double(in);
1004*4882a593Smuzhiyun }
1005*4882a593Smuzhiyun 
1006*4882a593Smuzhiyun double
fp3232_to_double(FP3232 in)1007*4882a593Smuzhiyun fp3232_to_double(FP3232 in)
1008*4882a593Smuzhiyun {
1009*4882a593Smuzhiyun     double ret;
1010*4882a593Smuzhiyun 
1011*4882a593Smuzhiyun     ret = (double) in.integral;
1012*4882a593Smuzhiyun     ret += (double) in.frac * (1.0 / (1ULL << 32));     /* Optimized: ldexp((double)in.frac, -32); */
1013*4882a593Smuzhiyun     return ret;
1014*4882a593Smuzhiyun }
1015*4882a593Smuzhiyun 
1016*4882a593Smuzhiyun FP1616
double_to_fp1616(double in)1017*4882a593Smuzhiyun double_to_fp1616(double in)
1018*4882a593Smuzhiyun {
1019*4882a593Smuzhiyun     return pixman_double_to_fixed(in);
1020*4882a593Smuzhiyun }
1021*4882a593Smuzhiyun 
1022*4882a593Smuzhiyun FP3232
double_to_fp3232(double in)1023*4882a593Smuzhiyun double_to_fp3232(double in)
1024*4882a593Smuzhiyun {
1025*4882a593Smuzhiyun     FP3232 ret;
1026*4882a593Smuzhiyun     int32_t integral;
1027*4882a593Smuzhiyun     double tmp;
1028*4882a593Smuzhiyun     uint32_t frac_d;
1029*4882a593Smuzhiyun 
1030*4882a593Smuzhiyun     tmp = floor(in);
1031*4882a593Smuzhiyun     integral = (int32_t) tmp;
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun     tmp = (in - integral) * (1ULL << 32);       /* Optimized: ldexp(in - integral, 32) */
1034*4882a593Smuzhiyun     frac_d = (uint32_t) tmp;
1035*4882a593Smuzhiyun 
1036*4882a593Smuzhiyun     ret.integral = integral;
1037*4882a593Smuzhiyun     ret.frac = frac_d;
1038*4882a593Smuzhiyun     return ret;
1039*4882a593Smuzhiyun }
1040*4882a593Smuzhiyun 
1041*4882a593Smuzhiyun /**
1042*4882a593Smuzhiyun  * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use
1043*4882a593Smuzhiyun  * xi2mask_new() instead to get the standard sized masks.
1044*4882a593Smuzhiyun  *
1045*4882a593Smuzhiyun  * @param nmasks The number of masks (== number of devices)
1046*4882a593Smuzhiyun  * @param size The size of the masks in bytes
1047*4882a593Smuzhiyun  * @return The new mask or NULL on allocation error.
1048*4882a593Smuzhiyun  */
1049*4882a593Smuzhiyun XI2Mask *
xi2mask_new_with_size(size_t nmasks,size_t size)1050*4882a593Smuzhiyun xi2mask_new_with_size(size_t nmasks, size_t size)
1051*4882a593Smuzhiyun {
1052*4882a593Smuzhiyun     int i;
1053*4882a593Smuzhiyun     int alloc_size;
1054*4882a593Smuzhiyun     unsigned char *cursor;
1055*4882a593Smuzhiyun     XI2Mask *mask;
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun     alloc_size = sizeof(struct _XI2Mask)
1058*4882a593Smuzhiyun 	       + nmasks * sizeof(unsigned char *)
1059*4882a593Smuzhiyun 	       + nmasks * size;
1060*4882a593Smuzhiyun 
1061*4882a593Smuzhiyun     mask = calloc(1, alloc_size);
1062*4882a593Smuzhiyun 
1063*4882a593Smuzhiyun     if (!mask)
1064*4882a593Smuzhiyun         return NULL;
1065*4882a593Smuzhiyun 
1066*4882a593Smuzhiyun     mask->nmasks = nmasks;
1067*4882a593Smuzhiyun     mask->mask_size = size;
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun     mask->masks = (unsigned char **)(mask + 1);
1070*4882a593Smuzhiyun     cursor = (unsigned char *)(mask + 1) + nmasks * sizeof(unsigned char *);
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun     for (i = 0; i < nmasks; i++) {
1073*4882a593Smuzhiyun         mask->masks[i] = cursor;
1074*4882a593Smuzhiyun 	cursor += size;
1075*4882a593Smuzhiyun     }
1076*4882a593Smuzhiyun     return mask;
1077*4882a593Smuzhiyun }
1078*4882a593Smuzhiyun 
1079*4882a593Smuzhiyun /**
1080*4882a593Smuzhiyun  * Create a new XI2 mask of the standard size, i.e. for all devices + fake
1081*4882a593Smuzhiyun  * devices and for the highest supported XI2 event type.
1082*4882a593Smuzhiyun  *
1083*4882a593Smuzhiyun  * @return The new mask or NULL on allocation error.
1084*4882a593Smuzhiyun  */
1085*4882a593Smuzhiyun XI2Mask *
xi2mask_new(void)1086*4882a593Smuzhiyun xi2mask_new(void)
1087*4882a593Smuzhiyun {
1088*4882a593Smuzhiyun     return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE);
1089*4882a593Smuzhiyun }
1090*4882a593Smuzhiyun 
1091*4882a593Smuzhiyun /**
1092*4882a593Smuzhiyun  * Frees memory associated with mask and resets mask to NULL.
1093*4882a593Smuzhiyun  */
1094*4882a593Smuzhiyun void
xi2mask_free(XI2Mask ** mask)1095*4882a593Smuzhiyun xi2mask_free(XI2Mask **mask)
1096*4882a593Smuzhiyun {
1097*4882a593Smuzhiyun     if (!(*mask))
1098*4882a593Smuzhiyun         return;
1099*4882a593Smuzhiyun 
1100*4882a593Smuzhiyun     free((*mask));
1101*4882a593Smuzhiyun     *mask = NULL;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun 
1104*4882a593Smuzhiyun /**
1105*4882a593Smuzhiyun  * Test if the bit for event type is set for this device only.
1106*4882a593Smuzhiyun  *
1107*4882a593Smuzhiyun  * @return TRUE if the bit is set, FALSE otherwise
1108*4882a593Smuzhiyun  */
1109*4882a593Smuzhiyun Bool
xi2mask_isset_for_device(XI2Mask * mask,const DeviceIntPtr dev,int event_type)1110*4882a593Smuzhiyun xi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
1111*4882a593Smuzhiyun {
1112*4882a593Smuzhiyun     BUG_WARN(dev->id < 0);
1113*4882a593Smuzhiyun     BUG_WARN(dev->id >= mask->nmasks);
1114*4882a593Smuzhiyun     BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun     return BitIsOn(mask->masks[dev->id], event_type);
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun 
1119*4882a593Smuzhiyun /**
1120*4882a593Smuzhiyun  * Test if the bit for event type is set for this device, or the
1121*4882a593Smuzhiyun  * XIAllDevices/XIAllMasterDevices (if applicable) is set.
1122*4882a593Smuzhiyun  *
1123*4882a593Smuzhiyun  * @return TRUE if the bit is set, FALSE otherwise
1124*4882a593Smuzhiyun  */
1125*4882a593Smuzhiyun Bool
xi2mask_isset(XI2Mask * mask,const DeviceIntPtr dev,int event_type)1126*4882a593Smuzhiyun xi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type)
1127*4882a593Smuzhiyun {
1128*4882a593Smuzhiyun     int set = 0;
1129*4882a593Smuzhiyun 
1130*4882a593Smuzhiyun     if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type))
1131*4882a593Smuzhiyun         set = 1;
1132*4882a593Smuzhiyun     else if (xi2mask_isset_for_device(mask, dev, event_type))
1133*4882a593Smuzhiyun         set = 1;
1134*4882a593Smuzhiyun     else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type))
1135*4882a593Smuzhiyun         set = 1;
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun     return set;
1138*4882a593Smuzhiyun }
1139*4882a593Smuzhiyun 
1140*4882a593Smuzhiyun /**
1141*4882a593Smuzhiyun  * Set the mask bit for this event type for this device.
1142*4882a593Smuzhiyun  */
1143*4882a593Smuzhiyun void
xi2mask_set(XI2Mask * mask,int deviceid,int event_type)1144*4882a593Smuzhiyun xi2mask_set(XI2Mask *mask, int deviceid, int event_type)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun     BUG_WARN(deviceid < 0);
1147*4882a593Smuzhiyun     BUG_WARN(deviceid >= mask->nmasks);
1148*4882a593Smuzhiyun     BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size);
1149*4882a593Smuzhiyun 
1150*4882a593Smuzhiyun     SetBit(mask->masks[deviceid], event_type);
1151*4882a593Smuzhiyun }
1152*4882a593Smuzhiyun 
1153*4882a593Smuzhiyun /**
1154*4882a593Smuzhiyun  * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all
1155*4882a593Smuzhiyun  * masks are zeroed.
1156*4882a593Smuzhiyun  */
1157*4882a593Smuzhiyun void
xi2mask_zero(XI2Mask * mask,int deviceid)1158*4882a593Smuzhiyun xi2mask_zero(XI2Mask *mask, int deviceid)
1159*4882a593Smuzhiyun {
1160*4882a593Smuzhiyun     int i;
1161*4882a593Smuzhiyun 
1162*4882a593Smuzhiyun     BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks);
1163*4882a593Smuzhiyun 
1164*4882a593Smuzhiyun     if (deviceid >= 0)
1165*4882a593Smuzhiyun         memset(mask->masks[deviceid], 0, mask->mask_size);
1166*4882a593Smuzhiyun     else
1167*4882a593Smuzhiyun         for (i = 0; i < mask->nmasks; i++)
1168*4882a593Smuzhiyun             memset(mask->masks[i], 0, mask->mask_size);
1169*4882a593Smuzhiyun }
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun /**
1172*4882a593Smuzhiyun  * Merge source into dest, i.e. dest |= source.
1173*4882a593Smuzhiyun  * If the masks are of different size, only the overlapping section is merged.
1174*4882a593Smuzhiyun  */
1175*4882a593Smuzhiyun void
xi2mask_merge(XI2Mask * dest,const XI2Mask * source)1176*4882a593Smuzhiyun xi2mask_merge(XI2Mask *dest, const XI2Mask *source)
1177*4882a593Smuzhiyun {
1178*4882a593Smuzhiyun     int i, j;
1179*4882a593Smuzhiyun 
1180*4882a593Smuzhiyun     for (i = 0; i < min(dest->nmasks, source->nmasks); i++)
1181*4882a593Smuzhiyun         for (j = 0; j < min(dest->mask_size, source->mask_size); j++)
1182*4882a593Smuzhiyun             dest->masks[i][j] |= source->masks[i][j];
1183*4882a593Smuzhiyun }
1184*4882a593Smuzhiyun 
1185*4882a593Smuzhiyun /**
1186*4882a593Smuzhiyun  * @return The number of masks in mask
1187*4882a593Smuzhiyun  */
1188*4882a593Smuzhiyun size_t
xi2mask_num_masks(const XI2Mask * mask)1189*4882a593Smuzhiyun xi2mask_num_masks(const XI2Mask *mask)
1190*4882a593Smuzhiyun {
1191*4882a593Smuzhiyun     return mask->nmasks;
1192*4882a593Smuzhiyun }
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun /**
1195*4882a593Smuzhiyun  * @return The size of each mask in bytes
1196*4882a593Smuzhiyun  */
1197*4882a593Smuzhiyun size_t
xi2mask_mask_size(const XI2Mask * mask)1198*4882a593Smuzhiyun xi2mask_mask_size(const XI2Mask *mask)
1199*4882a593Smuzhiyun {
1200*4882a593Smuzhiyun     return mask->mask_size;
1201*4882a593Smuzhiyun }
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun /**
1204*4882a593Smuzhiyun  * Set the mask for the given deviceid to the source mask.
1205*4882a593Smuzhiyun  * If the mask given is larger than the target memory, only the overlapping
1206*4882a593Smuzhiyun  * parts are copied.
1207*4882a593Smuzhiyun  */
1208*4882a593Smuzhiyun void
xi2mask_set_one_mask(XI2Mask * xi2mask,int deviceid,const unsigned char * mask,size_t mask_size)1209*4882a593Smuzhiyun xi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask,
1210*4882a593Smuzhiyun                      size_t mask_size)
1211*4882a593Smuzhiyun {
1212*4882a593Smuzhiyun     BUG_WARN(deviceid < 0);
1213*4882a593Smuzhiyun     BUG_WARN(deviceid >= xi2mask->nmasks);
1214*4882a593Smuzhiyun 
1215*4882a593Smuzhiyun     memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size));
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun 
1218*4882a593Smuzhiyun /**
1219*4882a593Smuzhiyun  * Get a reference to the XI2mask for this particular device.
1220*4882a593Smuzhiyun  */
1221*4882a593Smuzhiyun const unsigned char *
xi2mask_get_one_mask(const XI2Mask * mask,int deviceid)1222*4882a593Smuzhiyun xi2mask_get_one_mask(const XI2Mask *mask, int deviceid)
1223*4882a593Smuzhiyun {
1224*4882a593Smuzhiyun     BUG_WARN(deviceid < 0);
1225*4882a593Smuzhiyun     BUG_WARN(deviceid >= mask->nmasks);
1226*4882a593Smuzhiyun 
1227*4882a593Smuzhiyun     return mask->masks[deviceid];
1228*4882a593Smuzhiyun }
1229