inpututils.c revision 35c4bbdf
16747b715Smrg/* 26747b715Smrg * Copyright © 2008 Daniel Stone 36747b715Smrg * 46747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 56747b715Smrg * copy of this software and associated documentation files (the "Software"), 66747b715Smrg * to deal in the Software without restriction, including without limitation 76747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 86747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 96747b715Smrg * Software is furnished to do so, subject to the following conditions: 106747b715Smrg * 116747b715Smrg * The above copyright notice and this permission notice (including the next 126747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 136747b715Smrg * Software. 146747b715Smrg * 156747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 166747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 176747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 186747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 196747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 206747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 216747b715Smrg * DEALINGS IN THE SOFTWARE. 226747b715Smrg * 236747b715Smrg * Author: Daniel Stone <daniel@fooishbar.org> 246747b715Smrg */ 256747b715Smrg 266747b715Smrg#ifdef HAVE_DIX_CONFIG_H 276747b715Smrg#include "dix-config.h" 286747b715Smrg#endif 296747b715Smrg 306747b715Smrg#include "exevents.h" 316747b715Smrg#include "exglobals.h" 326747b715Smrg#include "misc.h" 336747b715Smrg#include "input.h" 346747b715Smrg#include "inputstr.h" 356747b715Smrg#include "xace.h" 366747b715Smrg#include "xkbsrv.h" 376747b715Smrg#include "xkbstr.h" 389ace9065Smrg#include "inpututils.h" 3935c4bbdfSmrg#include "eventstr.h" 4035c4bbdfSmrg#include "scrnintstr.h" 4135c4bbdfSmrg#include "optionstr.h" 426747b715Smrg 436747b715Smrg/* Check if a button map change is okay with the device. 446747b715Smrg * Returns -1 for BadValue, as it collides with MappingBusy. */ 456747b715Smrgstatic int 466747b715Smrgcheck_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, CARD32 *errval_out, 476747b715Smrg ClientPtr client) 486747b715Smrg{ 496747b715Smrg int i, ret; 506747b715Smrg 5135c4bbdfSmrg if (!dev || !dev->button) { 526747b715Smrg client->errorValue = (dev) ? dev->id : 0; 536747b715Smrg return BadDevice; 546747b715Smrg } 556747b715Smrg 566747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 5735c4bbdfSmrg if (ret != Success) { 586747b715Smrg client->errorValue = dev->id; 596747b715Smrg return ret; 606747b715Smrg } 616747b715Smrg 626747b715Smrg for (i = 0; i < len; i++) { 6335c4bbdfSmrg if (dev->button->map[i + 1] != map[i] && 6435c4bbdfSmrg button_is_down(dev, i + 1, BUTTON_PROCESSED)) 656747b715Smrg return MappingBusy; 666747b715Smrg } 676747b715Smrg 686747b715Smrg return Success; 696747b715Smrg} 706747b715Smrg 716747b715Smrgstatic void 726747b715Smrgdo_butmap_change(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 736747b715Smrg{ 746747b715Smrg int i; 7535c4bbdfSmrg xEvent core_mn = { .u.u.type = MappingNotify }; 766747b715Smrg deviceMappingNotify xi_mn; 776747b715Smrg 786747b715Smrg /* The map in ButtonClassRec refers to button numbers, whereas the 796747b715Smrg * protocol is zero-indexed. Sigh. */ 806747b715Smrg memcpy(&(dev->button->map[1]), map, len); 816747b715Smrg 826747b715Smrg core_mn.u.mappingNotify.request = MappingPointer; 836747b715Smrg 846747b715Smrg /* 0 is the server client. */ 856747b715Smrg for (i = 1; i < currentMaxClients; i++) { 866747b715Smrg /* Don't send irrelevant events to naïve clients. */ 876747b715Smrg if (!clients[i] || clients[i]->clientState != ClientStateRunning) 886747b715Smrg continue; 896747b715Smrg 906747b715Smrg if (!XIShouldNotify(clients[i], dev)) 916747b715Smrg continue; 926747b715Smrg 936747b715Smrg WriteEventsToClient(clients[i], 1, &core_mn); 946747b715Smrg } 956747b715Smrg 9635c4bbdfSmrg xi_mn = (deviceMappingNotify) { 9735c4bbdfSmrg .type = DeviceMappingNotify, 9835c4bbdfSmrg .request = MappingPointer, 9935c4bbdfSmrg .deviceid = dev->id, 10035c4bbdfSmrg .time = GetTimeInMillis() 10135c4bbdfSmrg }; 1026747b715Smrg 1036747b715Smrg SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) &xi_mn, 1); 1046747b715Smrg} 1056747b715Smrg 1066747b715Smrg/* 1076747b715Smrg * Does what it says on the box, both for core and Xi. 1086747b715Smrg * 1096747b715Smrg * Faithfully reports any errors encountered while trying to apply the map 1106747b715Smrg * to the requested device, faithfully ignores any errors encountered while 1116747b715Smrg * trying to apply the map to its master/slaves. 1126747b715Smrg */ 1136747b715Smrgint 1146747b715SmrgApplyPointerMapping(DeviceIntPtr dev, CARD8 *map, int len, ClientPtr client) 1156747b715Smrg{ 1166747b715Smrg int ret; 1176747b715Smrg 1186747b715Smrg /* If we can't perform the change on the requested device, bail out. */ 1196747b715Smrg ret = check_butmap_change(dev, map, len, &client->errorValue, client); 1206747b715Smrg if (ret != Success) 1216747b715Smrg return ret; 1226747b715Smrg do_butmap_change(dev, map, len, client); 1236747b715Smrg 1246747b715Smrg return Success; 1256747b715Smrg} 1266747b715Smrg 1276747b715Smrg/* Check if a modifier map change is okay with the device. 1286747b715Smrg * Returns -1 for BadValue, as it collides with MappingBusy; this particular 1296747b715Smrg * caveat can be removed with LegalModifier, as we have no other reason to 1306747b715Smrg * set MappingFailed. Sigh. */ 1316747b715Smrgstatic int 1326747b715Smrgcheck_modmap_change(ClientPtr client, DeviceIntPtr dev, KeyCode *modmap) 1336747b715Smrg{ 1346747b715Smrg int ret, i; 1356747b715Smrg XkbDescPtr xkb; 1366747b715Smrg 1376747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess); 1386747b715Smrg if (ret != Success) 1396747b715Smrg return ret; 1406747b715Smrg 1416747b715Smrg if (!dev->key) 1426747b715Smrg return BadMatch; 1436747b715Smrg xkb = dev->key->xkbInfo->desc; 1446747b715Smrg 1456747b715Smrg for (i = 0; i < MAP_LENGTH; i++) { 1466747b715Smrg if (!modmap[i]) 1476747b715Smrg continue; 1486747b715Smrg 1496747b715Smrg /* Check that all the new modifiers fall within the advertised 1506747b715Smrg * keycode range. */ 1516747b715Smrg if (i < xkb->min_key_code || i > xkb->max_key_code) { 1526747b715Smrg client->errorValue = i; 1536747b715Smrg return -1; 1546747b715Smrg } 1556747b715Smrg 1566747b715Smrg /* Make sure the mapping is okay with the DDX. */ 1576747b715Smrg if (!LegalModifier(i, dev)) { 1586747b715Smrg client->errorValue = i; 1596747b715Smrg return MappingFailed; 1606747b715Smrg } 1616747b715Smrg 1626747b715Smrg /* None of the new modifiers may be down while we change the 1636747b715Smrg * map. */ 1646747b715Smrg if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 1656747b715Smrg client->errorValue = i; 1666747b715Smrg return MappingBusy; 1676747b715Smrg } 1686747b715Smrg } 1696747b715Smrg 1706747b715Smrg /* None of the old modifiers may be down while we change the map, 1716747b715Smrg * either. */ 1726747b715Smrg for (i = xkb->min_key_code; i < xkb->max_key_code; i++) { 1736747b715Smrg if (!xkb->map->modmap[i]) 1746747b715Smrg continue; 1756747b715Smrg if (key_is_down(dev, i, KEY_POSTED | KEY_PROCESSED)) { 1766747b715Smrg client->errorValue = i; 1776747b715Smrg return MappingBusy; 1786747b715Smrg } 1796747b715Smrg } 1806747b715Smrg 1816747b715Smrg return Success; 1826747b715Smrg} 1836747b715Smrg 1846747b715Smrgstatic int 1856747b715Smrgcheck_modmap_change_slave(ClientPtr client, DeviceIntPtr master, 1866747b715Smrg DeviceIntPtr slave, CARD8 *modmap) 1876747b715Smrg{ 1886747b715Smrg XkbDescPtr master_xkb, slave_xkb; 1896747b715Smrg int i, j; 1906747b715Smrg 1916747b715Smrg if (!slave->key || !master->key) 1926747b715Smrg return 0; 1936747b715Smrg 1946747b715Smrg master_xkb = master->key->xkbInfo->desc; 1956747b715Smrg slave_xkb = slave->key->xkbInfo->desc; 1966747b715Smrg 1976747b715Smrg /* Ignore devices with a clearly different keymap. */ 1986747b715Smrg if (slave_xkb->min_key_code != master_xkb->min_key_code || 1996747b715Smrg slave_xkb->max_key_code != master_xkb->max_key_code) 2006747b715Smrg return 0; 2016747b715Smrg 2026747b715Smrg for (i = 0; i < MAP_LENGTH; i++) { 2036747b715Smrg if (!modmap[i]) 2046747b715Smrg continue; 2056747b715Smrg 2066747b715Smrg /* If we have different symbols for any modifier on an 2076747b715Smrg * extended keyboard, ignore the whole remap request. */ 2086747b715Smrg for (j = 0; 2096747b715Smrg j < XkbKeyNumSyms(slave_xkb, i) && 21035c4bbdfSmrg j < XkbKeyNumSyms(master_xkb, i); j++) 21135c4bbdfSmrg if (XkbKeySymsPtr(slave_xkb, i)[j] != 21235c4bbdfSmrg XkbKeySymsPtr(master_xkb, i)[j]) 2136747b715Smrg return 0; 2146747b715Smrg } 2156747b715Smrg 2166747b715Smrg if (check_modmap_change(client, slave, modmap) != Success) 2176747b715Smrg return 0; 2186747b715Smrg 2196747b715Smrg return 1; 2206747b715Smrg} 2216747b715Smrg 2226747b715Smrg/* Actually change the modifier map, and send notifications. Cannot fail. */ 2236747b715Smrgstatic void 2246747b715Smrgdo_modmap_change(ClientPtr client, DeviceIntPtr dev, CARD8 *modmap) 2256747b715Smrg{ 2266747b715Smrg XkbApplyMappingChange(dev, NULL, 0, 0, modmap, serverClient); 2276747b715Smrg} 2286747b715Smrg 2296747b715Smrg/* Rebuild modmap (key -> mod) from map (mod -> key). */ 23035c4bbdfSmrgstatic int 23135c4bbdfSmrgbuild_modmap_from_modkeymap(CARD8 *modmap, KeyCode *modkeymap, 23235c4bbdfSmrg int max_keys_per_mod) 2336747b715Smrg{ 2346747b715Smrg int i, len = max_keys_per_mod * 8; 2356747b715Smrg 2366747b715Smrg memset(modmap, 0, MAP_LENGTH); 2376747b715Smrg 2386747b715Smrg for (i = 0; i < len; i++) { 2396747b715Smrg if (!modkeymap[i]) 2406747b715Smrg continue; 2416747b715Smrg 24235c4bbdfSmrg#if MAP_LENGTH < 256 2436747b715Smrg if (modkeymap[i] >= MAP_LENGTH) 2446747b715Smrg return BadValue; 24535c4bbdfSmrg#endif 2466747b715Smrg 2476747b715Smrg if (modmap[modkeymap[i]]) 2486747b715Smrg return BadValue; 2496747b715Smrg 2506747b715Smrg modmap[modkeymap[i]] = 1 << (i / max_keys_per_mod); 2516747b715Smrg } 2526747b715Smrg 2536747b715Smrg return Success; 2546747b715Smrg} 2556747b715Smrg 2566747b715Smrgint 2576747b715Smrgchange_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *modkeymap, 2586747b715Smrg int max_keys_per_mod) 2596747b715Smrg{ 2606747b715Smrg int ret; 2616747b715Smrg CARD8 modmap[MAP_LENGTH]; 2626747b715Smrg DeviceIntPtr tmp; 2636747b715Smrg 2646747b715Smrg ret = build_modmap_from_modkeymap(modmap, modkeymap, max_keys_per_mod); 2656747b715Smrg if (ret != Success) 2666747b715Smrg return ret; 2676747b715Smrg 2686747b715Smrg /* If we can't perform the change on the requested device, bail out. */ 2696747b715Smrg ret = check_modmap_change(client, dev, modmap); 2706747b715Smrg if (ret != Success) 2716747b715Smrg return ret; 2726747b715Smrg do_modmap_change(client, dev, modmap); 2736747b715Smrg 2746747b715Smrg /* Change any attached masters/slaves. */ 2756747b715Smrg if (IsMaster(dev)) { 2766747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 27735c4bbdfSmrg if (!IsMaster(tmp) && GetMaster(tmp, MASTER_KEYBOARD) == dev) 2786747b715Smrg if (check_modmap_change_slave(client, dev, tmp, modmap)) 2796747b715Smrg do_modmap_change(client, tmp, modmap); 2806747b715Smrg } 2816747b715Smrg } 28235c4bbdfSmrg else if (!IsFloating(dev) && 28335c4bbdfSmrg GetMaster(dev, MASTER_KEYBOARD)->lastSlave == dev) { 2846747b715Smrg /* If this fails, expect the results to be weird. */ 28535c4bbdfSmrg if (check_modmap_change(client, dev->master, modmap)) 28635c4bbdfSmrg do_modmap_change(client, dev->master, modmap); 2876747b715Smrg } 2886747b715Smrg 2896747b715Smrg return Success; 2906747b715Smrg} 2916747b715Smrg 29235c4bbdfSmrgint 29335c4bbdfSmrggenerate_modkeymap(ClientPtr client, DeviceIntPtr dev, 29435c4bbdfSmrg KeyCode **modkeymap_out, int *max_keys_per_mod_out) 2956747b715Smrg{ 2966747b715Smrg CARD8 keys_per_mod[8]; 2976747b715Smrg int max_keys_per_mod; 2988223e2f2Smrg KeyCode *modkeymap = NULL; 2996747b715Smrg int i, j, ret; 3006747b715Smrg 3016747b715Smrg ret = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); 3026747b715Smrg if (ret != Success) 3036747b715Smrg return ret; 3046747b715Smrg 3056747b715Smrg if (!dev->key) 3066747b715Smrg return BadMatch; 3076747b715Smrg 3086747b715Smrg /* Count the number of keys per modifier to determine how wide we 3096747b715Smrg * should make the map. */ 3106747b715Smrg max_keys_per_mod = 0; 3116747b715Smrg for (i = 0; i < 8; i++) 3126747b715Smrg keys_per_mod[i] = 0; 3136747b715Smrg for (i = 8; i < MAP_LENGTH; i++) { 3146747b715Smrg for (j = 0; j < 8; j++) { 3156747b715Smrg if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 3166747b715Smrg if (++keys_per_mod[j] > max_keys_per_mod) 3176747b715Smrg max_keys_per_mod = keys_per_mod[j]; 3186747b715Smrg } 3196747b715Smrg } 3206747b715Smrg } 3216747b715Smrg 3228223e2f2Smrg if (max_keys_per_mod != 0) { 3238223e2f2Smrg modkeymap = calloc(max_keys_per_mod * 8, sizeof(KeyCode)); 3248223e2f2Smrg if (!modkeymap) 3258223e2f2Smrg return BadAlloc; 3266747b715Smrg 3278223e2f2Smrg for (i = 0; i < 8; i++) 3288223e2f2Smrg keys_per_mod[i] = 0; 3296747b715Smrg 3308223e2f2Smrg for (i = 8; i < MAP_LENGTH; i++) { 3318223e2f2Smrg for (j = 0; j < 8; j++) { 3328223e2f2Smrg if (dev->key->xkbInfo->desc->map->modmap[i] & (1 << j)) { 3338223e2f2Smrg modkeymap[(j * max_keys_per_mod) + keys_per_mod[j]] = i; 3348223e2f2Smrg keys_per_mod[j]++; 3358223e2f2Smrg } 3366747b715Smrg } 3376747b715Smrg } 3386747b715Smrg } 3396747b715Smrg 3406747b715Smrg *max_keys_per_mod_out = max_keys_per_mod; 3416747b715Smrg *modkeymap_out = modkeymap; 3426747b715Smrg 3436747b715Smrg return Success; 3446747b715Smrg} 3456747b715Smrg 3466747b715Smrg/** 3476747b715Smrg * Duplicate the InputAttributes in the most obvious way. 3486747b715Smrg * No special memory handling is used to give drivers the maximum 3496747b715Smrg * flexibility with the data. Drivers should be able to call realloc on the 3506747b715Smrg * product string if needed and perform similar operations. 3516747b715Smrg */ 35235c4bbdfSmrgInputAttributes * 35335c4bbdfSmrgDuplicateInputAttributes(InputAttributes * attrs) 3546747b715Smrg{ 3556747b715Smrg InputAttributes *new_attr; 3566747b715Smrg int ntags = 0; 3576747b715Smrg char **tags, **new_tags; 3586747b715Smrg 3596747b715Smrg if (!attrs) 3606747b715Smrg return NULL; 3616747b715Smrg 3626747b715Smrg if (!(new_attr = calloc(1, sizeof(InputAttributes)))) 3636747b715Smrg goto unwind; 3646747b715Smrg 3656747b715Smrg if (attrs->product && !(new_attr->product = strdup(attrs->product))) 3666747b715Smrg goto unwind; 3676747b715Smrg if (attrs->vendor && !(new_attr->vendor = strdup(attrs->vendor))) 3686747b715Smrg goto unwind; 3696747b715Smrg if (attrs->device && !(new_attr->device = strdup(attrs->device))) 3706747b715Smrg goto unwind; 3716747b715Smrg if (attrs->pnp_id && !(new_attr->pnp_id = strdup(attrs->pnp_id))) 3726747b715Smrg goto unwind; 3736747b715Smrg if (attrs->usb_id && !(new_attr->usb_id = strdup(attrs->usb_id))) 3746747b715Smrg goto unwind; 3756747b715Smrg 3766747b715Smrg new_attr->flags = attrs->flags; 3776747b715Smrg 37835c4bbdfSmrg if ((tags = attrs->tags)) { 37935c4bbdfSmrg while (*tags++) 3806747b715Smrg ntags++; 3816747b715Smrg 38235c4bbdfSmrg new_attr->tags = calloc(ntags + 1, sizeof(char *)); 3836747b715Smrg if (!new_attr->tags) 3846747b715Smrg goto unwind; 3856747b715Smrg 3866747b715Smrg tags = attrs->tags; 3876747b715Smrg new_tags = new_attr->tags; 3886747b715Smrg 38935c4bbdfSmrg while (*tags) { 3906747b715Smrg *new_tags = strdup(*tags); 3916747b715Smrg if (!*new_tags) 3926747b715Smrg goto unwind; 3936747b715Smrg 3946747b715Smrg tags++; 3956747b715Smrg new_tags++; 3966747b715Smrg } 3976747b715Smrg } 3986747b715Smrg 3996747b715Smrg return new_attr; 4006747b715Smrg 40135c4bbdfSmrg unwind: 4026747b715Smrg FreeInputAttributes(new_attr); 4036747b715Smrg return NULL; 4046747b715Smrg} 4056747b715Smrg 4066747b715Smrgvoid 40735c4bbdfSmrgFreeInputAttributes(InputAttributes * attrs) 4086747b715Smrg{ 4096747b715Smrg char **tags; 4106747b715Smrg 4116747b715Smrg if (!attrs) 4126747b715Smrg return; 4136747b715Smrg 4146747b715Smrg free(attrs->product); 4156747b715Smrg free(attrs->vendor); 4166747b715Smrg free(attrs->device); 4176747b715Smrg free(attrs->pnp_id); 4186747b715Smrg free(attrs->usb_id); 4196747b715Smrg 4206747b715Smrg if ((tags = attrs->tags)) 42135c4bbdfSmrg while (*tags) 4226747b715Smrg free(*tags++); 4236747b715Smrg 4246747b715Smrg free(attrs->tags); 4256747b715Smrg free(attrs); 4266747b715Smrg} 4276747b715Smrg 4289ace9065Smrg/** 4299ace9065Smrg * Alloc a valuator mask large enough for num_valuators. 4309ace9065Smrg */ 43135c4bbdfSmrgValuatorMask * 4329ace9065Smrgvaluator_mask_new(int num_valuators) 4339ace9065Smrg{ 4349ace9065Smrg /* alloc a fixed size mask for now and ignore num_valuators. in the 4359ace9065Smrg * flying-car future, when we can dynamically alloc the masks and are 4369ace9065Smrg * not constrained by signals, we can start using num_valuators */ 4379ace9065Smrg ValuatorMask *mask = calloc(1, sizeof(ValuatorMask)); 43835c4bbdfSmrg 43935c4bbdfSmrg if (mask == NULL) 44035c4bbdfSmrg return NULL; 44135c4bbdfSmrg 4429ace9065Smrg mask->last_bit = -1; 4439ace9065Smrg return mask; 4449ace9065Smrg} 4459ace9065Smrg 4469ace9065Smrgvoid 4479ace9065Smrgvaluator_mask_free(ValuatorMask **mask) 4489ace9065Smrg{ 4499ace9065Smrg free(*mask); 4509ace9065Smrg *mask = NULL; 4519ace9065Smrg} 4529ace9065Smrg 4539ace9065Smrg/** 4549ace9065Smrg * Sets a range of valuators between first_valuator and num_valuators with 4559ace9065Smrg * the data in the valuators array. All other values are set to 0. 4569ace9065Smrg */ 4579ace9065Smrgvoid 45835c4bbdfSmrgvaluator_mask_set_range(ValuatorMask *mask, int first_valuator, 45935c4bbdfSmrg int num_valuators, const int *valuators) 4609ace9065Smrg{ 4619ace9065Smrg int i; 4629ace9065Smrg 4639ace9065Smrg valuator_mask_zero(mask); 4649ace9065Smrg 46535c4bbdfSmrg for (i = first_valuator; 46635c4bbdfSmrg i < min(first_valuator + num_valuators, MAX_VALUATORS); i++) 4679ace9065Smrg valuator_mask_set(mask, i, valuators[i - first_valuator]); 4689ace9065Smrg} 4699ace9065Smrg 4709ace9065Smrg/** 4719ace9065Smrg * Reset mask to zero. 4729ace9065Smrg */ 4739ace9065Smrgvoid 4749ace9065Smrgvaluator_mask_zero(ValuatorMask *mask) 4759ace9065Smrg{ 4769ace9065Smrg memset(mask, 0, sizeof(*mask)); 4779ace9065Smrg mask->last_bit = -1; 4789ace9065Smrg} 4799ace9065Smrg 4809ace9065Smrg/** 4819ace9065Smrg * Returns the current size of the mask (i.e. the highest number of 4829ace9065Smrg * valuators currently set + 1). 4839ace9065Smrg */ 4849ace9065Smrgint 4859ace9065Smrgvaluator_mask_size(const ValuatorMask *mask) 4869ace9065Smrg{ 4879ace9065Smrg return mask->last_bit + 1; 4889ace9065Smrg} 4899ace9065Smrg 4909ace9065Smrg/** 4919ace9065Smrg * Returns the number of valuators set in the given mask. 4929ace9065Smrg */ 4939ace9065Smrgint 4949ace9065Smrgvaluator_mask_num_valuators(const ValuatorMask *mask) 4959ace9065Smrg{ 4969ace9065Smrg return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS)); 4979ace9065Smrg} 4989ace9065Smrg 4999ace9065Smrg/** 5009ace9065Smrg * Return true if the valuator is set in the mask, or false otherwise. 5019ace9065Smrg */ 5029ace9065Smrgint 5039ace9065Smrgvaluator_mask_isset(const ValuatorMask *mask, int valuator) 5049ace9065Smrg{ 5059ace9065Smrg return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator); 5069ace9065Smrg} 5079ace9065Smrg 50835c4bbdfSmrgstatic inline void 50935c4bbdfSmrg_valuator_mask_set_double(ValuatorMask *mask, int valuator, double data) 51035c4bbdfSmrg{ 51135c4bbdfSmrg mask->last_bit = max(valuator, mask->last_bit); 51235c4bbdfSmrg SetBit(mask->mask, valuator); 51335c4bbdfSmrg mask->valuators[valuator] = data; 51435c4bbdfSmrg} 51535c4bbdfSmrg 5169ace9065Smrg/** 51735c4bbdfSmrg * Set the valuator to the given floating-point data. 51835c4bbdfSmrg */ 51935c4bbdfSmrgvoid 52035c4bbdfSmrgvaluator_mask_set_double(ValuatorMask *mask, int valuator, double data) 52135c4bbdfSmrg{ 52235c4bbdfSmrg BUG_WARN_MSG(mask->has_unaccelerated, 52335c4bbdfSmrg "Do not mix valuator types, zero mask first\n"); 52435c4bbdfSmrg _valuator_mask_set_double(mask, valuator, data); 52535c4bbdfSmrg} 52635c4bbdfSmrg 52735c4bbdfSmrg/** 52835c4bbdfSmrg * Set the valuator to the given integer data. 5299ace9065Smrg */ 5309ace9065Smrgvoid 5319ace9065Smrgvaluator_mask_set(ValuatorMask *mask, int valuator, int data) 5329ace9065Smrg{ 53335c4bbdfSmrg valuator_mask_set_double(mask, valuator, data); 53435c4bbdfSmrg} 53535c4bbdfSmrg 53635c4bbdfSmrg/** 53735c4bbdfSmrg * Return the requested valuator value as a double. If the mask bit is not 53835c4bbdfSmrg * set for the given valuator, the returned value is undefined. 53935c4bbdfSmrg */ 54035c4bbdfSmrgdouble 54135c4bbdfSmrgvaluator_mask_get_double(const ValuatorMask *mask, int valuator) 54235c4bbdfSmrg{ 54335c4bbdfSmrg return mask->valuators[valuator]; 5449ace9065Smrg} 5459ace9065Smrg 5469ace9065Smrg/** 54735c4bbdfSmrg * Return the requested valuator value as an integer, rounding towards zero. 54835c4bbdfSmrg * If the mask bit is not set for the given valuator, the returned value is 54935c4bbdfSmrg * undefined. 5509ace9065Smrg */ 5519ace9065Smrgint 5529ace9065Smrgvaluator_mask_get(const ValuatorMask *mask, int valuator) 5539ace9065Smrg{ 55435c4bbdfSmrg return trunc(valuator_mask_get_double(mask, valuator)); 55535c4bbdfSmrg} 55635c4bbdfSmrg 55735c4bbdfSmrg/** 55835c4bbdfSmrg * Set value to the requested valuator. If the mask bit is set for this 55935c4bbdfSmrg * valuator, value contains the requested valuator value and TRUE is 56035c4bbdfSmrg * returned. 56135c4bbdfSmrg * If the mask bit is not set for this valuator, value is unchanged and 56235c4bbdfSmrg * FALSE is returned. 56335c4bbdfSmrg */ 56435c4bbdfSmrgBool 56535c4bbdfSmrgvaluator_mask_fetch_double(const ValuatorMask *mask, int valuator, 56635c4bbdfSmrg double *value) 56735c4bbdfSmrg{ 56835c4bbdfSmrg if (valuator_mask_isset(mask, valuator)) { 56935c4bbdfSmrg *value = valuator_mask_get_double(mask, valuator); 57035c4bbdfSmrg return TRUE; 57135c4bbdfSmrg } 57235c4bbdfSmrg else 57335c4bbdfSmrg return FALSE; 57435c4bbdfSmrg} 57535c4bbdfSmrg 57635c4bbdfSmrg/** 57735c4bbdfSmrg * Set value to the requested valuator. If the mask bit is set for this 57835c4bbdfSmrg * valuator, value contains the requested valuator value and TRUE is 57935c4bbdfSmrg * returned. 58035c4bbdfSmrg * If the mask bit is not set for this valuator, value is unchanged and 58135c4bbdfSmrg * FALSE is returned. 58235c4bbdfSmrg */ 58335c4bbdfSmrgBool 58435c4bbdfSmrgvaluator_mask_fetch(const ValuatorMask *mask, int valuator, int *value) 58535c4bbdfSmrg{ 58635c4bbdfSmrg if (valuator_mask_isset(mask, valuator)) { 58735c4bbdfSmrg *value = valuator_mask_get(mask, valuator); 58835c4bbdfSmrg return TRUE; 58935c4bbdfSmrg } 59035c4bbdfSmrg else 59135c4bbdfSmrg return FALSE; 5929ace9065Smrg} 5939ace9065Smrg 5949ace9065Smrg/** 5959ace9065Smrg * Remove the valuator from the mask. 5969ace9065Smrg */ 5979ace9065Smrgvoid 5989ace9065Smrgvaluator_mask_unset(ValuatorMask *mask, int valuator) 5999ace9065Smrg{ 6009ace9065Smrg if (mask->last_bit >= valuator) { 6019ace9065Smrg int i, lastbit = -1; 6029ace9065Smrg 6039ace9065Smrg ClearBit(mask->mask, valuator); 60435c4bbdfSmrg mask->valuators[valuator] = 0.0; 60535c4bbdfSmrg mask->unaccelerated[valuator] = 0.0; 6069ace9065Smrg 6079ace9065Smrg for (i = 0; i <= mask->last_bit; i++) 6089ace9065Smrg if (valuator_mask_isset(mask, i)) 6099ace9065Smrg lastbit = max(lastbit, i); 6109ace9065Smrg mask->last_bit = lastbit; 61135c4bbdfSmrg 61235c4bbdfSmrg if (mask->last_bit == -1) 61335c4bbdfSmrg mask->has_unaccelerated = FALSE; 6149ace9065Smrg } 6159ace9065Smrg} 6169ace9065Smrg 6179ace9065Smrgvoid 6189ace9065Smrgvaluator_mask_copy(ValuatorMask *dest, const ValuatorMask *src) 6199ace9065Smrg{ 6209ace9065Smrg if (src) 6219ace9065Smrg memcpy(dest, src, sizeof(*dest)); 6229ace9065Smrg else 6239ace9065Smrg valuator_mask_zero(dest); 6249ace9065Smrg} 6259ace9065Smrg 62635c4bbdfSmrgBool 62735c4bbdfSmrgvaluator_mask_has_unaccelerated(const ValuatorMask *mask) 62835c4bbdfSmrg{ 62935c4bbdfSmrg return mask->has_unaccelerated; 63035c4bbdfSmrg} 63135c4bbdfSmrg 63235c4bbdfSmrgvoid 63335c4bbdfSmrgvaluator_mask_drop_unaccelerated(ValuatorMask *mask) 63435c4bbdfSmrg{ 63535c4bbdfSmrg memset(mask->unaccelerated, 0, sizeof(mask->unaccelerated)); 63635c4bbdfSmrg mask->has_unaccelerated = FALSE; 63735c4bbdfSmrg} 63835c4bbdfSmrg 63935c4bbdfSmrg/** 64035c4bbdfSmrg * Set both accelerated and unaccelerated value for this mask. 64135c4bbdfSmrg */ 64235c4bbdfSmrgvoid 64335c4bbdfSmrgvaluator_mask_set_unaccelerated(ValuatorMask *mask, 64435c4bbdfSmrg int valuator, 64535c4bbdfSmrg double accel, 64635c4bbdfSmrg double unaccel) 64735c4bbdfSmrg{ 64835c4bbdfSmrg BUG_WARN_MSG(mask->last_bit != -1 && !mask->has_unaccelerated, 64935c4bbdfSmrg "Do not mix valuator types, zero mask first\n"); 65035c4bbdfSmrg _valuator_mask_set_double(mask, valuator, accel); 65135c4bbdfSmrg mask->has_unaccelerated = TRUE; 65235c4bbdfSmrg mask->unaccelerated[valuator] = unaccel; 65335c4bbdfSmrg} 65435c4bbdfSmrg 65535c4bbdfSmrgdouble 65635c4bbdfSmrgvaluator_mask_get_accelerated(const ValuatorMask *mask, 65735c4bbdfSmrg int valuator) 65835c4bbdfSmrg{ 65935c4bbdfSmrg return valuator_mask_get_double(mask, valuator); 66035c4bbdfSmrg} 66135c4bbdfSmrg 66235c4bbdfSmrgdouble 66335c4bbdfSmrgvaluator_mask_get_unaccelerated(const ValuatorMask *mask, 66435c4bbdfSmrg int valuator) 66535c4bbdfSmrg{ 66635c4bbdfSmrg return mask->unaccelerated[valuator]; 66735c4bbdfSmrg} 66835c4bbdfSmrg 66935c4bbdfSmrgBool 67035c4bbdfSmrgvaluator_mask_fetch_unaccelerated(const ValuatorMask *mask, 67135c4bbdfSmrg int valuator, 67235c4bbdfSmrg double *accel, 67335c4bbdfSmrg double *unaccel) 67435c4bbdfSmrg{ 67535c4bbdfSmrg if (valuator_mask_isset(mask, valuator)) { 67635c4bbdfSmrg if (accel) 67735c4bbdfSmrg *accel = valuator_mask_get_accelerated(mask, valuator); 67835c4bbdfSmrg if (unaccel) 67935c4bbdfSmrg *unaccel = valuator_mask_get_unaccelerated(mask, valuator); 68035c4bbdfSmrg return TRUE; 68135c4bbdfSmrg } 68235c4bbdfSmrg else 68335c4bbdfSmrg return FALSE; 68435c4bbdfSmrg} 68535c4bbdfSmrg 6869ace9065Smrgint 68735c4bbdfSmrgCountBits(const uint8_t * mask, int len) 6889ace9065Smrg{ 6899ace9065Smrg int i; 6909ace9065Smrg int ret = 0; 6919ace9065Smrg 6929ace9065Smrg for (i = 0; i < len; i++) 6939ace9065Smrg if (BitIsOn(mask, i)) 6949ace9065Smrg ret++; 6959ace9065Smrg 6969ace9065Smrg return ret; 6979ace9065Smrg} 69835c4bbdfSmrg 69935c4bbdfSmrg/** 70035c4bbdfSmrg * Verifies sanity of the event. If the event is not an internal event, 70135c4bbdfSmrg * memdumps the first 32 bytes of event to the log, a backtrace, then kill 70235c4bbdfSmrg * the server. 70335c4bbdfSmrg */ 70435c4bbdfSmrgvoid 70535c4bbdfSmrgverify_internal_event(const InternalEvent *ev) 70635c4bbdfSmrg{ 70735c4bbdfSmrg if (ev && ev->any.header != ET_Internal) { 70835c4bbdfSmrg int i; 70935c4bbdfSmrg const unsigned char *data = (const unsigned char *) ev; 71035c4bbdfSmrg 71135c4bbdfSmrg ErrorF("dix: invalid event type %d\n", ev->any.header); 71235c4bbdfSmrg 71335c4bbdfSmrg for (i = 0; i < sizeof(xEvent); i++, data++) { 71435c4bbdfSmrg ErrorF("%02hhx ", *data); 71535c4bbdfSmrg 71635c4bbdfSmrg if ((i % 8) == 7) 71735c4bbdfSmrg ErrorF("\n"); 71835c4bbdfSmrg } 71935c4bbdfSmrg 72035c4bbdfSmrg xorg_backtrace(); 72135c4bbdfSmrg FatalError("Wrong event type %d. Aborting server\n", ev->any.header); 72235c4bbdfSmrg } 72335c4bbdfSmrg} 72435c4bbdfSmrg 72535c4bbdfSmrg/** 72635c4bbdfSmrg * Initializes the given event to zero (or default values), for the given 72735c4bbdfSmrg * device. 72835c4bbdfSmrg */ 72935c4bbdfSmrgvoid 73035c4bbdfSmrginit_device_event(DeviceEvent *event, DeviceIntPtr dev, Time ms) 73135c4bbdfSmrg{ 73235c4bbdfSmrg memset(event, 0, sizeof(DeviceEvent)); 73335c4bbdfSmrg event->header = ET_Internal; 73435c4bbdfSmrg event->length = sizeof(DeviceEvent); 73535c4bbdfSmrg event->time = ms; 73635c4bbdfSmrg event->deviceid = dev->id; 73735c4bbdfSmrg event->sourceid = dev->id; 73835c4bbdfSmrg} 73935c4bbdfSmrg 74035c4bbdfSmrgint 74135c4bbdfSmrgevent_get_corestate(DeviceIntPtr mouse, DeviceIntPtr kbd) 74235c4bbdfSmrg{ 74335c4bbdfSmrg int corestate; 74435c4bbdfSmrg 74535c4bbdfSmrg /* core state needs to be assembled BEFORE the device is updated. */ 74635c4bbdfSmrg corestate = (kbd && 74735c4bbdfSmrg kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo-> 74835c4bbdfSmrg state) : 0; 74935c4bbdfSmrg corestate |= (mouse && mouse->button) ? (mouse->button->state) : 0; 75035c4bbdfSmrg corestate |= (mouse && mouse->touch) ? (mouse->touch->state) : 0; 75135c4bbdfSmrg 75235c4bbdfSmrg return corestate; 75335c4bbdfSmrg} 75435c4bbdfSmrg 75535c4bbdfSmrgvoid 75635c4bbdfSmrgevent_set_state(DeviceIntPtr mouse, DeviceIntPtr kbd, DeviceEvent *event) 75735c4bbdfSmrg{ 75835c4bbdfSmrg int i; 75935c4bbdfSmrg 76035c4bbdfSmrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 76135c4bbdfSmrg if (BitIsOn(mouse->button->down, i)) 76235c4bbdfSmrg SetBit(event->buttons, mouse->button->map[i]); 76335c4bbdfSmrg 76435c4bbdfSmrg if (mouse && mouse->touch && mouse->touch->buttonsDown > 0) 76535c4bbdfSmrg SetBit(event->buttons, mouse->button->map[1]); 76635c4bbdfSmrg 76735c4bbdfSmrg if (kbd && kbd->key) { 76835c4bbdfSmrg XkbStatePtr state; 76935c4bbdfSmrg 77035c4bbdfSmrg /* we need the state before the event happens */ 77135c4bbdfSmrg if (event->type == ET_KeyPress || event->type == ET_KeyRelease) 77235c4bbdfSmrg state = &kbd->key->xkbInfo->prev_state; 77335c4bbdfSmrg else 77435c4bbdfSmrg state = &kbd->key->xkbInfo->state; 77535c4bbdfSmrg 77635c4bbdfSmrg event->mods.base = state->base_mods; 77735c4bbdfSmrg event->mods.latched = state->latched_mods; 77835c4bbdfSmrg event->mods.locked = state->locked_mods; 77935c4bbdfSmrg event->mods.effective = state->mods; 78035c4bbdfSmrg 78135c4bbdfSmrg event->group.base = state->base_group; 78235c4bbdfSmrg event->group.latched = state->latched_group; 78335c4bbdfSmrg event->group.locked = state->locked_group; 78435c4bbdfSmrg event->group.effective = state->group; 78535c4bbdfSmrg } 78635c4bbdfSmrg} 78735c4bbdfSmrg 78835c4bbdfSmrg/** 78935c4bbdfSmrg * Return the event filter mask for the given device and the given core or 79035c4bbdfSmrg * XI1 protocol type. 79135c4bbdfSmrg */ 79235c4bbdfSmrgMask 79335c4bbdfSmrgevent_get_filter_from_type(DeviceIntPtr dev, int evtype) 79435c4bbdfSmrg{ 79535c4bbdfSmrg return event_filters[dev ? dev->id : 0][evtype]; 79635c4bbdfSmrg} 79735c4bbdfSmrg 79835c4bbdfSmrg/** 79935c4bbdfSmrg * Return the event filter mask for the given device and the given core or 80035c4bbdfSmrg * XI2 protocol type. 80135c4bbdfSmrg */ 80235c4bbdfSmrgMask 80335c4bbdfSmrgevent_get_filter_from_xi2type(int evtype) 80435c4bbdfSmrg{ 80535c4bbdfSmrg return (1 << (evtype % 8)); 80635c4bbdfSmrg} 80735c4bbdfSmrg 80835c4bbdfSmrgBool 80935c4bbdfSmrgpoint_on_screen(ScreenPtr pScreen, int x, int y) 81035c4bbdfSmrg{ 81135c4bbdfSmrg return x >= pScreen->x && x < pScreen->x + pScreen->width && 81235c4bbdfSmrg y >= pScreen->y && y < pScreen->y + pScreen->height; 81335c4bbdfSmrg} 81435c4bbdfSmrg 81535c4bbdfSmrg/** 81635c4bbdfSmrg * Update desktop dimensions on the screenInfo struct. 81735c4bbdfSmrg */ 81835c4bbdfSmrgvoid 81935c4bbdfSmrgupdate_desktop_dimensions(void) 82035c4bbdfSmrg{ 82135c4bbdfSmrg int i; 82235c4bbdfSmrg int x1 = INT_MAX, y1 = INT_MAX; /* top-left */ 82335c4bbdfSmrg int x2 = INT_MIN, y2 = INT_MIN; /* bottom-right */ 82435c4bbdfSmrg 82535c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 82635c4bbdfSmrg ScreenPtr screen = screenInfo.screens[i]; 82735c4bbdfSmrg 82835c4bbdfSmrg x1 = min(x1, screen->x); 82935c4bbdfSmrg y1 = min(y1, screen->y); 83035c4bbdfSmrg x2 = max(x2, screen->x + screen->width); 83135c4bbdfSmrg y2 = max(y2, screen->y + screen->height); 83235c4bbdfSmrg } 83335c4bbdfSmrg 83435c4bbdfSmrg screenInfo.x = x1; 83535c4bbdfSmrg screenInfo.y = y1; 83635c4bbdfSmrg screenInfo.width = x2 - x1; 83735c4bbdfSmrg screenInfo.height = y2 - y1; 83835c4bbdfSmrg} 83935c4bbdfSmrg 84035c4bbdfSmrg/* 84135c4bbdfSmrg * Delete the element with the key from the list, freeing all memory 84235c4bbdfSmrg * associated with the element.. 84335c4bbdfSmrg */ 84435c4bbdfSmrgstatic void 84535c4bbdfSmrginput_option_free(InputOption *o) 84635c4bbdfSmrg{ 84735c4bbdfSmrg free(o->opt_name); 84835c4bbdfSmrg free(o->opt_val); 84935c4bbdfSmrg free(o->opt_comment); 85035c4bbdfSmrg free(o); 85135c4bbdfSmrg} 85235c4bbdfSmrg 85335c4bbdfSmrg/* 85435c4bbdfSmrg * Create a new InputOption with the key/value pair provided. 85535c4bbdfSmrg * If a list is provided, the new options is added to the list and the list 85635c4bbdfSmrg * is returned. 85735c4bbdfSmrg * 85835c4bbdfSmrg * If a new option is added to a list that already contains that option, the 85935c4bbdfSmrg * previous option is overwritten. 86035c4bbdfSmrg * 86135c4bbdfSmrg * @param list The list to add to. 86235c4bbdfSmrg * @param key Option key, will be copied. 86335c4bbdfSmrg * @param value Option value, will be copied. 86435c4bbdfSmrg * 86535c4bbdfSmrg * @return If list is not NULL, the list with the new option added. If list 86635c4bbdfSmrg * is NULL, a new option list with one element. On failure, NULL is 86735c4bbdfSmrg * returned. 86835c4bbdfSmrg */ 86935c4bbdfSmrgInputOption * 87035c4bbdfSmrginput_option_new(InputOption *list, const char *key, const char *value) 87135c4bbdfSmrg{ 87235c4bbdfSmrg InputOption *opt = NULL; 87335c4bbdfSmrg 87435c4bbdfSmrg if (!key) 87535c4bbdfSmrg return NULL; 87635c4bbdfSmrg 87735c4bbdfSmrg if (list) { 87835c4bbdfSmrg nt_list_for_each_entry(opt, list, list.next) { 87935c4bbdfSmrg if (strcmp(input_option_get_key(opt), key) == 0) { 88035c4bbdfSmrg input_option_set_value(opt, value); 88135c4bbdfSmrg return list; 88235c4bbdfSmrg } 88335c4bbdfSmrg } 88435c4bbdfSmrg } 88535c4bbdfSmrg 88635c4bbdfSmrg opt = calloc(1, sizeof(InputOption)); 88735c4bbdfSmrg if (!opt) 88835c4bbdfSmrg return NULL; 88935c4bbdfSmrg 89035c4bbdfSmrg nt_list_init(opt, list.next); 89135c4bbdfSmrg input_option_set_key(opt, key); 89235c4bbdfSmrg input_option_set_value(opt, value); 89335c4bbdfSmrg 89435c4bbdfSmrg if (list) { 89535c4bbdfSmrg nt_list_append(opt, list, InputOption, list.next); 89635c4bbdfSmrg 89735c4bbdfSmrg return list; 89835c4bbdfSmrg } 89935c4bbdfSmrg else 90035c4bbdfSmrg return opt; 90135c4bbdfSmrg} 90235c4bbdfSmrg 90335c4bbdfSmrgInputOption * 90435c4bbdfSmrginput_option_free_element(InputOption *list, const char *key) 90535c4bbdfSmrg{ 90635c4bbdfSmrg InputOption *element; 90735c4bbdfSmrg 90835c4bbdfSmrg nt_list_for_each_entry(element, list, list.next) { 90935c4bbdfSmrg if (strcmp(input_option_get_key(element), key) == 0) { 91035c4bbdfSmrg nt_list_del(element, list, InputOption, list.next); 91135c4bbdfSmrg 91235c4bbdfSmrg input_option_free(element); 91335c4bbdfSmrg break; 91435c4bbdfSmrg } 91535c4bbdfSmrg } 91635c4bbdfSmrg return list; 91735c4bbdfSmrg} 91835c4bbdfSmrg 91935c4bbdfSmrg/** 92035c4bbdfSmrg * Free the list pointed at by opt. 92135c4bbdfSmrg */ 92235c4bbdfSmrgvoid 92335c4bbdfSmrginput_option_free_list(InputOption **opt) 92435c4bbdfSmrg{ 92535c4bbdfSmrg InputOption *element, *tmp; 92635c4bbdfSmrg 92735c4bbdfSmrg nt_list_for_each_entry_safe(element, tmp, *opt, list.next) { 92835c4bbdfSmrg nt_list_del(element, *opt, InputOption, list.next); 92935c4bbdfSmrg 93035c4bbdfSmrg input_option_free(element); 93135c4bbdfSmrg } 93235c4bbdfSmrg *opt = NULL; 93335c4bbdfSmrg} 93435c4bbdfSmrg 93535c4bbdfSmrg/** 93635c4bbdfSmrg * Find the InputOption with the given option name. 93735c4bbdfSmrg * 93835c4bbdfSmrg * @return The InputOption or NULL if not present. 93935c4bbdfSmrg */ 94035c4bbdfSmrgInputOption * 94135c4bbdfSmrginput_option_find(InputOption *list, const char *key) 94235c4bbdfSmrg{ 94335c4bbdfSmrg InputOption *element; 94435c4bbdfSmrg 94535c4bbdfSmrg nt_list_for_each_entry(element, list, list.next) { 94635c4bbdfSmrg if (strcmp(input_option_get_key(element), key) == 0) 94735c4bbdfSmrg return element; 94835c4bbdfSmrg } 94935c4bbdfSmrg 95035c4bbdfSmrg return NULL; 95135c4bbdfSmrg} 95235c4bbdfSmrg 95335c4bbdfSmrgconst char * 95435c4bbdfSmrginput_option_get_key(const InputOption *opt) 95535c4bbdfSmrg{ 95635c4bbdfSmrg return opt->opt_name; 95735c4bbdfSmrg} 95835c4bbdfSmrg 95935c4bbdfSmrgconst char * 96035c4bbdfSmrginput_option_get_value(const InputOption *opt) 96135c4bbdfSmrg{ 96235c4bbdfSmrg return opt->opt_val; 96335c4bbdfSmrg} 96435c4bbdfSmrg 96535c4bbdfSmrgvoid 96635c4bbdfSmrginput_option_set_key(InputOption *opt, const char *key) 96735c4bbdfSmrg{ 96835c4bbdfSmrg free(opt->opt_name); 96935c4bbdfSmrg if (key) 97035c4bbdfSmrg opt->opt_name = strdup(key); 97135c4bbdfSmrg} 97235c4bbdfSmrg 97335c4bbdfSmrgvoid 97435c4bbdfSmrginput_option_set_value(InputOption *opt, const char *value) 97535c4bbdfSmrg{ 97635c4bbdfSmrg free(opt->opt_val); 97735c4bbdfSmrg if (value) 97835c4bbdfSmrg opt->opt_val = strdup(value); 97935c4bbdfSmrg} 98035c4bbdfSmrg 98135c4bbdfSmrg/* FP1616/FP3232 conversion functions. 98235c4bbdfSmrg * Fixed point types are encoded as signed integral and unsigned frac. So any 98335c4bbdfSmrg * negative number -n.m is encoded as floor(n) + (1 - 0.m). 98435c4bbdfSmrg */ 98535c4bbdfSmrgdouble 98635c4bbdfSmrgfp1616_to_double(FP1616 in) 98735c4bbdfSmrg{ 98835c4bbdfSmrg return pixman_fixed_to_double(in); 98935c4bbdfSmrg} 99035c4bbdfSmrg 99135c4bbdfSmrgdouble 99235c4bbdfSmrgfp3232_to_double(FP3232 in) 99335c4bbdfSmrg{ 99435c4bbdfSmrg double ret; 99535c4bbdfSmrg 99635c4bbdfSmrg ret = (double) in.integral; 99735c4bbdfSmrg ret += (double) in.frac * (1.0 / (1ULL << 32)); /* Optimized: ldexp((double)in.frac, -32); */ 99835c4bbdfSmrg return ret; 99935c4bbdfSmrg} 100035c4bbdfSmrg 100135c4bbdfSmrgFP1616 100235c4bbdfSmrgdouble_to_fp1616(double in) 100335c4bbdfSmrg{ 100435c4bbdfSmrg return pixman_double_to_fixed(in); 100535c4bbdfSmrg} 100635c4bbdfSmrg 100735c4bbdfSmrgFP3232 100835c4bbdfSmrgdouble_to_fp3232(double in) 100935c4bbdfSmrg{ 101035c4bbdfSmrg FP3232 ret; 101135c4bbdfSmrg int32_t integral; 101235c4bbdfSmrg double tmp; 101335c4bbdfSmrg uint32_t frac_d; 101435c4bbdfSmrg 101535c4bbdfSmrg tmp = floor(in); 101635c4bbdfSmrg integral = (int32_t) tmp; 101735c4bbdfSmrg 101835c4bbdfSmrg tmp = (in - integral) * (1ULL << 32); /* Optimized: ldexp(in - integral, 32) */ 101935c4bbdfSmrg frac_d = (uint32_t) tmp; 102035c4bbdfSmrg 102135c4bbdfSmrg ret.integral = integral; 102235c4bbdfSmrg ret.frac = frac_d; 102335c4bbdfSmrg return ret; 102435c4bbdfSmrg} 102535c4bbdfSmrg 102635c4bbdfSmrg/** 102735c4bbdfSmrg * DO NOT USE THIS FUNCTION. It only exists for the test cases. Use 102835c4bbdfSmrg * xi2mask_new() instead to get the standard sized masks. 102935c4bbdfSmrg * 103035c4bbdfSmrg * @param nmasks The number of masks (== number of devices) 103135c4bbdfSmrg * @param size The size of the masks in bytes 103235c4bbdfSmrg * @return The new mask or NULL on allocation error. 103335c4bbdfSmrg */ 103435c4bbdfSmrgXI2Mask * 103535c4bbdfSmrgxi2mask_new_with_size(size_t nmasks, size_t size) 103635c4bbdfSmrg{ 103735c4bbdfSmrg int i; 103835c4bbdfSmrg int alloc_size; 103935c4bbdfSmrg unsigned char *cursor; 104035c4bbdfSmrg XI2Mask *mask; 104135c4bbdfSmrg 104235c4bbdfSmrg alloc_size = sizeof(struct _XI2Mask) 104335c4bbdfSmrg + nmasks * sizeof(unsigned char *) 104435c4bbdfSmrg + nmasks * size; 104535c4bbdfSmrg 104635c4bbdfSmrg mask = calloc(1, alloc_size); 104735c4bbdfSmrg 104835c4bbdfSmrg if (!mask) 104935c4bbdfSmrg return NULL; 105035c4bbdfSmrg 105135c4bbdfSmrg mask->nmasks = nmasks; 105235c4bbdfSmrg mask->mask_size = size; 105335c4bbdfSmrg 105435c4bbdfSmrg mask->masks = (unsigned char **)(mask + 1); 105535c4bbdfSmrg cursor = (unsigned char *)(mask + 1) + nmasks * sizeof(unsigned char *); 105635c4bbdfSmrg 105735c4bbdfSmrg for (i = 0; i < nmasks; i++) { 105835c4bbdfSmrg mask->masks[i] = cursor; 105935c4bbdfSmrg cursor += size; 106035c4bbdfSmrg } 106135c4bbdfSmrg return mask; 106235c4bbdfSmrg} 106335c4bbdfSmrg 106435c4bbdfSmrg/** 106535c4bbdfSmrg * Create a new XI2 mask of the standard size, i.e. for all devices + fake 106635c4bbdfSmrg * devices and for the highest supported XI2 event type. 106735c4bbdfSmrg * 106835c4bbdfSmrg * @return The new mask or NULL on allocation error. 106935c4bbdfSmrg */ 107035c4bbdfSmrgXI2Mask * 107135c4bbdfSmrgxi2mask_new(void) 107235c4bbdfSmrg{ 107335c4bbdfSmrg return xi2mask_new_with_size(EMASKSIZE, XI2MASKSIZE); 107435c4bbdfSmrg} 107535c4bbdfSmrg 107635c4bbdfSmrg/** 107735c4bbdfSmrg * Frees memory associated with mask and resets mask to NULL. 107835c4bbdfSmrg */ 107935c4bbdfSmrgvoid 108035c4bbdfSmrgxi2mask_free(XI2Mask **mask) 108135c4bbdfSmrg{ 108235c4bbdfSmrg if (!(*mask)) 108335c4bbdfSmrg return; 108435c4bbdfSmrg 108535c4bbdfSmrg free((*mask)); 108635c4bbdfSmrg *mask = NULL; 108735c4bbdfSmrg} 108835c4bbdfSmrg 108935c4bbdfSmrg/** 109035c4bbdfSmrg * Test if the bit for event type is set for this device only. 109135c4bbdfSmrg * 109235c4bbdfSmrg * @return TRUE if the bit is set, FALSE otherwise 109335c4bbdfSmrg */ 109435c4bbdfSmrgBool 109535c4bbdfSmrgxi2mask_isset_for_device(XI2Mask *mask, const DeviceIntPtr dev, int event_type) 109635c4bbdfSmrg{ 109735c4bbdfSmrg BUG_WARN(dev->id < 0); 109835c4bbdfSmrg BUG_WARN(dev->id >= mask->nmasks); 109935c4bbdfSmrg BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); 110035c4bbdfSmrg 110135c4bbdfSmrg return BitIsOn(mask->masks[dev->id], event_type); 110235c4bbdfSmrg} 110335c4bbdfSmrg 110435c4bbdfSmrg/** 110535c4bbdfSmrg * Test if the bit for event type is set for this device, or the 110635c4bbdfSmrg * XIAllDevices/XIAllMasterDevices (if applicable) is set. 110735c4bbdfSmrg * 110835c4bbdfSmrg * @return TRUE if the bit is set, FALSE otherwise 110935c4bbdfSmrg */ 111035c4bbdfSmrgBool 111135c4bbdfSmrgxi2mask_isset(XI2Mask *mask, const DeviceIntPtr dev, int event_type) 111235c4bbdfSmrg{ 111335c4bbdfSmrg int set = 0; 111435c4bbdfSmrg 111535c4bbdfSmrg if (xi2mask_isset_for_device(mask, inputInfo.all_devices, event_type)) 111635c4bbdfSmrg set = 1; 111735c4bbdfSmrg else if (xi2mask_isset_for_device(mask, dev, event_type)) 111835c4bbdfSmrg set = 1; 111935c4bbdfSmrg else if (IsMaster(dev) && xi2mask_isset_for_device(mask, inputInfo.all_master_devices, event_type)) 112035c4bbdfSmrg set = 1; 112135c4bbdfSmrg 112235c4bbdfSmrg return set; 112335c4bbdfSmrg} 112435c4bbdfSmrg 112535c4bbdfSmrg/** 112635c4bbdfSmrg * Set the mask bit for this event type for this device. 112735c4bbdfSmrg */ 112835c4bbdfSmrgvoid 112935c4bbdfSmrgxi2mask_set(XI2Mask *mask, int deviceid, int event_type) 113035c4bbdfSmrg{ 113135c4bbdfSmrg BUG_WARN(deviceid < 0); 113235c4bbdfSmrg BUG_WARN(deviceid >= mask->nmasks); 113335c4bbdfSmrg BUG_WARN(bits_to_bytes(event_type + 1) > mask->mask_size); 113435c4bbdfSmrg 113535c4bbdfSmrg SetBit(mask->masks[deviceid], event_type); 113635c4bbdfSmrg} 113735c4bbdfSmrg 113835c4bbdfSmrg/** 113935c4bbdfSmrg * Zero out the xi2mask, for the deviceid given. If the deviceid is < 0, all 114035c4bbdfSmrg * masks are zeroed. 114135c4bbdfSmrg */ 114235c4bbdfSmrgvoid 114335c4bbdfSmrgxi2mask_zero(XI2Mask *mask, int deviceid) 114435c4bbdfSmrg{ 114535c4bbdfSmrg int i; 114635c4bbdfSmrg 114735c4bbdfSmrg BUG_WARN(deviceid > 0 && deviceid >= mask->nmasks); 114835c4bbdfSmrg 114935c4bbdfSmrg if (deviceid >= 0) 115035c4bbdfSmrg memset(mask->masks[deviceid], 0, mask->mask_size); 115135c4bbdfSmrg else 115235c4bbdfSmrg for (i = 0; i < mask->nmasks; i++) 115335c4bbdfSmrg memset(mask->masks[i], 0, mask->mask_size); 115435c4bbdfSmrg} 115535c4bbdfSmrg 115635c4bbdfSmrg/** 115735c4bbdfSmrg * Merge source into dest, i.e. dest |= source. 115835c4bbdfSmrg * If the masks are of different size, only the overlapping section is merged. 115935c4bbdfSmrg */ 116035c4bbdfSmrgvoid 116135c4bbdfSmrgxi2mask_merge(XI2Mask *dest, const XI2Mask *source) 116235c4bbdfSmrg{ 116335c4bbdfSmrg int i, j; 116435c4bbdfSmrg 116535c4bbdfSmrg for (i = 0; i < min(dest->nmasks, source->nmasks); i++) 116635c4bbdfSmrg for (j = 0; j < min(dest->mask_size, source->mask_size); j++) 116735c4bbdfSmrg dest->masks[i][j] |= source->masks[i][j]; 116835c4bbdfSmrg} 116935c4bbdfSmrg 117035c4bbdfSmrg/** 117135c4bbdfSmrg * @return The number of masks in mask 117235c4bbdfSmrg */ 117335c4bbdfSmrgsize_t 117435c4bbdfSmrgxi2mask_num_masks(const XI2Mask *mask) 117535c4bbdfSmrg{ 117635c4bbdfSmrg return mask->nmasks; 117735c4bbdfSmrg} 117835c4bbdfSmrg 117935c4bbdfSmrg/** 118035c4bbdfSmrg * @return The size of each mask in bytes 118135c4bbdfSmrg */ 118235c4bbdfSmrgsize_t 118335c4bbdfSmrgxi2mask_mask_size(const XI2Mask *mask) 118435c4bbdfSmrg{ 118535c4bbdfSmrg return mask->mask_size; 118635c4bbdfSmrg} 118735c4bbdfSmrg 118835c4bbdfSmrg/** 118935c4bbdfSmrg * Set the mask for the given deviceid to the source mask. 119035c4bbdfSmrg * If the mask given is larger than the target memory, only the overlapping 119135c4bbdfSmrg * parts are copied. 119235c4bbdfSmrg */ 119335c4bbdfSmrgvoid 119435c4bbdfSmrgxi2mask_set_one_mask(XI2Mask *xi2mask, int deviceid, const unsigned char *mask, 119535c4bbdfSmrg size_t mask_size) 119635c4bbdfSmrg{ 119735c4bbdfSmrg BUG_WARN(deviceid < 0); 119835c4bbdfSmrg BUG_WARN(deviceid >= xi2mask->nmasks); 119935c4bbdfSmrg 120035c4bbdfSmrg memcpy(xi2mask->masks[deviceid], mask, min(xi2mask->mask_size, mask_size)); 120135c4bbdfSmrg} 120235c4bbdfSmrg 120335c4bbdfSmrg/** 120435c4bbdfSmrg * Get a reference to the XI2mask for this particular device. 120535c4bbdfSmrg */ 120635c4bbdfSmrgconst unsigned char * 120735c4bbdfSmrgxi2mask_get_one_mask(const XI2Mask *mask, int deviceid) 120835c4bbdfSmrg{ 120935c4bbdfSmrg BUG_WARN(deviceid < 0); 121035c4bbdfSmrg BUG_WARN(deviceid >= mask->nmasks); 121135c4bbdfSmrg 121235c4bbdfSmrg return mask->masks[deviceid]; 121335c4bbdfSmrg} 1214