xiproperty.c revision 4642e01f
14642e01fSmrg/* 24642e01fSmrg * Copyright © 2006 Keith Packard 34642e01fSmrg * Copyright © 2008 Peter Hutterer 44642e01fSmrg * 54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 64642e01fSmrg * copy of this software and associated documentation files (the "Software"), 74642e01fSmrg * to deal in the Software without restriction, including without limitation 84642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 94642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the 104642e01fSmrg * Software is furnished to do so, subject to the following conditions: 114642e01fSmrg * 124642e01fSmrg * The above copyright notice and this permission notice (including the next 134642e01fSmrg * paragraph) shall be included in all copies or substantial portions of the 144642e01fSmrg * Software. 154642e01fSmrg * 164642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR 174642e01fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY, 184642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 194642e01fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 204642e01fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 214642e01fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 224642e01fSmrg * DEALINGS IN THE SOFTWARE. 234642e01fSmrg * 244642e01fSmrg */ 254642e01fSmrg 264642e01fSmrg/* This code is a modified version of randr/rrproperty.c */ 274642e01fSmrg 284642e01fSmrg#ifdef HAVE_DIX_CONFIG_H 294642e01fSmrg#include <dix-config.h> 304642e01fSmrg#endif 314642e01fSmrg 324642e01fSmrg#include "dix.h" 334642e01fSmrg#include "inputstr.h" 344642e01fSmrg#include <X11/extensions/XI.h> 354642e01fSmrg#include <X11/Xatom.h> 364642e01fSmrg#include <X11/extensions/XIproto.h> 374642e01fSmrg#include "exglobals.h" 384642e01fSmrg#include "exevents.h" 394642e01fSmrg#include "swaprep.h" 404642e01fSmrg 414642e01fSmrg#include "xiproperty.h" 424642e01fSmrg#include "xserver-properties.h" 434642e01fSmrg 444642e01fSmrg/** 454642e01fSmrg * Properties used or alloced from inside the server. 464642e01fSmrg */ 474642e01fSmrgstatic struct dev_properties 484642e01fSmrg{ 494642e01fSmrg Atom type; 504642e01fSmrg char *name; 514642e01fSmrg} dev_properties[] = { 524642e01fSmrg {0, XI_PROP_ENABLED}, 534642e01fSmrg {0, XATOM_FLOAT} 544642e01fSmrg}; 554642e01fSmrg 564642e01fSmrgstatic long XIPropHandlerID = 1; 574642e01fSmrg 584642e01fSmrg/** 594642e01fSmrg * Return the type assigned to the specified atom or 0 if the atom isn't known 604642e01fSmrg * to the DIX. 614642e01fSmrg * 624642e01fSmrg * If name is NULL, None is returned. 634642e01fSmrg */ 644642e01fSmrg_X_EXPORT Atom 654642e01fSmrgXIGetKnownProperty(char *name) 664642e01fSmrg{ 674642e01fSmrg int i; 684642e01fSmrg 694642e01fSmrg if (!name) 704642e01fSmrg return None; 714642e01fSmrg 724642e01fSmrg for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++) 734642e01fSmrg { 744642e01fSmrg if (strcmp(name, dev_properties[i].name) == 0) 754642e01fSmrg return dev_properties[i].type; 764642e01fSmrg } 774642e01fSmrg 784642e01fSmrg return 0; 794642e01fSmrg} 804642e01fSmrg 814642e01fSmrg/** 824642e01fSmrg * Convert the given property's value(s) into @nelem_return integer values and 834642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of 844642e01fSmrg * values in the property, @nelem_return is set to the number of values in the 854642e01fSmrg * property. 864642e01fSmrg * 874642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated 884642e01fSmrg * automatically and must be freed by the caller. 894642e01fSmrg * 904642e01fSmrg * Possible return codes. 914642e01fSmrg * Success ... No error. 924642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_INTEGER 934642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed. 944642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero. 954642e01fSmrg * 964642e01fSmrg * @param val The property value 974642e01fSmrg * @param nelem_return The maximum number of elements to return. 984642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values. 994642e01fSmrg * @return Success or the error code if an error occured. 1004642e01fSmrg */ 1014642e01fSmrg_X_EXPORT int 1024642e01fSmrgXIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return) 1034642e01fSmrg{ 1044642e01fSmrg int i; 1054642e01fSmrg int *buf; 1064642e01fSmrg 1074642e01fSmrg if (val->type != XA_INTEGER) 1084642e01fSmrg return BadMatch; 1094642e01fSmrg if (!*buf_return && *nelem_return) 1104642e01fSmrg return BadLength; 1114642e01fSmrg 1124642e01fSmrg switch(val->format) 1134642e01fSmrg { 1144642e01fSmrg case 8: 1154642e01fSmrg case 16: 1164642e01fSmrg case 32: 1174642e01fSmrg break; 1184642e01fSmrg default: 1194642e01fSmrg return BadValue; 1204642e01fSmrg } 1214642e01fSmrg 1224642e01fSmrg buf = *buf_return; 1234642e01fSmrg 1244642e01fSmrg if (!buf && !(*nelem_return)) 1254642e01fSmrg { 1264642e01fSmrg buf = xcalloc(val->size, sizeof(int)); 1274642e01fSmrg if (!buf) 1284642e01fSmrg return BadAlloc; 1294642e01fSmrg *buf_return = buf; 1304642e01fSmrg *nelem_return = val->size; 1314642e01fSmrg } else if (val->size < *nelem_return) 1324642e01fSmrg *nelem_return = val->size; 1334642e01fSmrg 1344642e01fSmrg for (i = 0; i < val->size && i < *nelem_return; i++) 1354642e01fSmrg { 1364642e01fSmrg switch(val->format) 1374642e01fSmrg { 1384642e01fSmrg case 8: buf[i] = ((CARD8*)val->data)[i]; break; 1394642e01fSmrg case 16: buf[i] = ((CARD16*)val->data)[i]; break; 1404642e01fSmrg case 32: buf[i] = ((CARD32*)val->data)[i]; break; 1414642e01fSmrg } 1424642e01fSmrg } 1434642e01fSmrg 1444642e01fSmrg return Success; 1454642e01fSmrg} 1464642e01fSmrg 1474642e01fSmrg/** 1484642e01fSmrg * Convert the given property's value(s) into @nelem_return float values and 1494642e01fSmrg * store them in @buf_return. If @nelem_return is larger than the number of 1504642e01fSmrg * values in the property, @nelem_return is set to the number of values in the 1514642e01fSmrg * property. 1524642e01fSmrg * 1534642e01fSmrg * If *@buf_return is NULL and @nelem_return is 0, memory is allocated 1544642e01fSmrg * automatically and must be freed by the caller. 1554642e01fSmrg * 1564642e01fSmrg * Possible errors returned: 1574642e01fSmrg * Success 1584642e01fSmrg * BadMatch ... Wrong atom type, atom is not XA_FLOAT 1594642e01fSmrg * BadValue ... Wrong format, format is not 32 1604642e01fSmrg * BadAlloc ... NULL passed as buffer and allocation failed. 1614642e01fSmrg * BadLength ... @buff is NULL but @nelem_return is non-zero. 1624642e01fSmrg * 1634642e01fSmrg * @param val The property value 1644642e01fSmrg * @param nelem_return The maximum number of elements to return. 1654642e01fSmrg * @param buf_return Pointer to an array of at least @nelem_return values. 1664642e01fSmrg * @return Success or the error code if an error occured. 1674642e01fSmrg */ 1684642e01fSmrg_X_EXPORT int 1694642e01fSmrgXIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return) 1704642e01fSmrg{ 1714642e01fSmrg int i; 1724642e01fSmrg float *buf; 1734642e01fSmrg 1744642e01fSmrg if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT)) 1754642e01fSmrg return BadMatch; 1764642e01fSmrg 1774642e01fSmrg if (val->format != 32) 1784642e01fSmrg return BadValue; 1794642e01fSmrg if (!*buf_return && *nelem_return) 1804642e01fSmrg return BadLength; 1814642e01fSmrg 1824642e01fSmrg buf = *buf_return; 1834642e01fSmrg 1844642e01fSmrg if (!buf && !(*nelem_return)) 1854642e01fSmrg { 1864642e01fSmrg buf = xcalloc(val->size, sizeof(float)); 1874642e01fSmrg if (!buf) 1884642e01fSmrg return BadAlloc; 1894642e01fSmrg *buf_return = buf; 1904642e01fSmrg *nelem_return = val->size; 1914642e01fSmrg } else if (val->size < *nelem_return) 1924642e01fSmrg *nelem_return = val->size; 1934642e01fSmrg 1944642e01fSmrg for (i = 0; i < val->size && i < *nelem_return; i++) 1954642e01fSmrg buf[i] = ((float*)val->data)[i]; 1964642e01fSmrg 1974642e01fSmrg return Success; 1984642e01fSmrg} 1994642e01fSmrg 2004642e01fSmrg/** 2014642e01fSmrg * Init those properties that are allocated by the server and most likely used 2024642e01fSmrg * by the DIX or the DDX. 2034642e01fSmrg */ 2044642e01fSmrgvoid 2054642e01fSmrgXIInitKnownProperties(void) 2064642e01fSmrg{ 2074642e01fSmrg int i; 2084642e01fSmrg for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++) 2094642e01fSmrg { 2104642e01fSmrg dev_properties[i].type = 2114642e01fSmrg MakeAtom(dev_properties[i].name, 2124642e01fSmrg strlen(dev_properties[i].name), 2134642e01fSmrg TRUE); 2144642e01fSmrg } 2154642e01fSmrg} 2164642e01fSmrg 2174642e01fSmrg 2184642e01fSmrg/* Registers a new property handler on the given device and returns a unique 2194642e01fSmrg * identifier for this handler. This identifier is required to unregister the 2204642e01fSmrg * property handler again. 2214642e01fSmrg * @return The handler's identifier or 0 if an error occured. 2224642e01fSmrg */ 2234642e01fSmrglong 2244642e01fSmrgXIRegisterPropertyHandler(DeviceIntPtr dev, 2254642e01fSmrg int (*SetProperty) (DeviceIntPtr dev, 2264642e01fSmrg Atom property, 2274642e01fSmrg XIPropertyValuePtr prop, 2284642e01fSmrg BOOL checkonly), 2294642e01fSmrg int (*GetProperty) (DeviceIntPtr dev, 2304642e01fSmrg Atom property), 2314642e01fSmrg int (*DeleteProperty) (DeviceIntPtr dev, 2324642e01fSmrg Atom property)) 2334642e01fSmrg{ 2344642e01fSmrg XIPropertyHandlerPtr new_handler; 2354642e01fSmrg 2364642e01fSmrg new_handler = xcalloc(1, sizeof(XIPropertyHandler)); 2374642e01fSmrg if (!new_handler) 2384642e01fSmrg return 0; 2394642e01fSmrg 2404642e01fSmrg new_handler->id = XIPropHandlerID++; 2414642e01fSmrg new_handler->SetProperty = SetProperty; 2424642e01fSmrg new_handler->GetProperty = GetProperty; 2434642e01fSmrg new_handler->DeleteProperty = DeleteProperty; 2444642e01fSmrg new_handler->next = dev->properties.handlers; 2454642e01fSmrg dev->properties.handlers = new_handler; 2464642e01fSmrg 2474642e01fSmrg return new_handler->id; 2484642e01fSmrg} 2494642e01fSmrg 2504642e01fSmrgvoid 2514642e01fSmrgXIUnregisterPropertyHandler(DeviceIntPtr dev, long id) 2524642e01fSmrg{ 2534642e01fSmrg XIPropertyHandlerPtr curr, prev = NULL; 2544642e01fSmrg 2554642e01fSmrg curr = dev->properties.handlers; 2564642e01fSmrg while(curr && curr->id != id) 2574642e01fSmrg { 2584642e01fSmrg prev = curr; 2594642e01fSmrg curr = curr->next; 2604642e01fSmrg } 2614642e01fSmrg 2624642e01fSmrg if (!curr) 2634642e01fSmrg return; 2644642e01fSmrg 2654642e01fSmrg if (!prev) /* first one */ 2664642e01fSmrg dev->properties.handlers = curr->next; 2674642e01fSmrg else 2684642e01fSmrg prev->next = curr->next; 2694642e01fSmrg 2704642e01fSmrg xfree(curr); 2714642e01fSmrg} 2724642e01fSmrg 2734642e01fSmrgstatic XIPropertyPtr 2744642e01fSmrgXICreateDeviceProperty (Atom property) 2754642e01fSmrg{ 2764642e01fSmrg XIPropertyPtr prop; 2774642e01fSmrg 2784642e01fSmrg prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec)); 2794642e01fSmrg if (!prop) 2804642e01fSmrg return NULL; 2814642e01fSmrg 2824642e01fSmrg prop->next = NULL; 2834642e01fSmrg prop->propertyName = property; 2844642e01fSmrg prop->value.type = None; 2854642e01fSmrg prop->value.format = 0; 2864642e01fSmrg prop->value.size = 0; 2874642e01fSmrg prop->value.data = NULL; 2884642e01fSmrg prop->deletable = TRUE; 2894642e01fSmrg 2904642e01fSmrg return prop; 2914642e01fSmrg} 2924642e01fSmrg 2934642e01fSmrgstatic XIPropertyPtr 2944642e01fSmrgXIFetchDeviceProperty(DeviceIntPtr dev, Atom property) 2954642e01fSmrg{ 2964642e01fSmrg XIPropertyPtr prop; 2974642e01fSmrg 2984642e01fSmrg for (prop = dev->properties.properties; prop; prop = prop->next) 2994642e01fSmrg if (prop->propertyName == property) 3004642e01fSmrg return prop; 3014642e01fSmrg return NULL; 3024642e01fSmrg} 3034642e01fSmrg 3044642e01fSmrgstatic void 3054642e01fSmrgXIDestroyDeviceProperty (XIPropertyPtr prop) 3064642e01fSmrg{ 3074642e01fSmrg if (prop->value.data) 3084642e01fSmrg xfree(prop->value.data); 3094642e01fSmrg xfree(prop); 3104642e01fSmrg} 3114642e01fSmrg 3124642e01fSmrg/* This function destroys all of the device's property-related stuff, 3134642e01fSmrg * including removing all device handlers. 3144642e01fSmrg * DO NOT CALL FROM THE DRIVER. 3154642e01fSmrg */ 3164642e01fSmrgvoid 3174642e01fSmrgXIDeleteAllDeviceProperties (DeviceIntPtr device) 3184642e01fSmrg{ 3194642e01fSmrg XIPropertyPtr prop, next; 3204642e01fSmrg XIPropertyHandlerPtr curr_handler, next_handler; 3214642e01fSmrg devicePropertyNotify event; 3224642e01fSmrg 3234642e01fSmrg for (prop = device->properties.properties; prop; prop = next) 3244642e01fSmrg { 3254642e01fSmrg next = prop->next; 3264642e01fSmrg 3274642e01fSmrg event.type = DevicePropertyNotify; 3284642e01fSmrg event.deviceid = device->id; 3294642e01fSmrg event.state = PropertyDelete; 3304642e01fSmrg event.atom = prop->propertyName; 3314642e01fSmrg event.time = currentTime.milliseconds; 3324642e01fSmrg SendEventToAllWindows(device, DevicePropertyNotifyMask, 3334642e01fSmrg (xEvent*)&event, 1); 3344642e01fSmrg 3354642e01fSmrg XIDestroyDeviceProperty(prop); 3364642e01fSmrg } 3374642e01fSmrg 3384642e01fSmrg /* Now free all handlers */ 3394642e01fSmrg curr_handler = device->properties.handlers; 3404642e01fSmrg while(curr_handler) 3414642e01fSmrg { 3424642e01fSmrg next_handler = curr_handler->next; 3434642e01fSmrg xfree(curr_handler); 3444642e01fSmrg curr_handler = next_handler; 3454642e01fSmrg } 3464642e01fSmrg} 3474642e01fSmrg 3484642e01fSmrg 3494642e01fSmrgint 3504642e01fSmrgXIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient) 3514642e01fSmrg{ 3524642e01fSmrg XIPropertyPtr prop, *prev; 3534642e01fSmrg devicePropertyNotify event; 3544642e01fSmrg int rc = Success; 3554642e01fSmrg 3564642e01fSmrg for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next)) 3574642e01fSmrg if (prop->propertyName == property) 3584642e01fSmrg break; 3594642e01fSmrg 3604642e01fSmrg if (fromClient && !prop->deletable) 3614642e01fSmrg return BadAccess; 3624642e01fSmrg 3634642e01fSmrg /* Ask handlers if we may delete the property */ 3644642e01fSmrg if (device->properties.handlers) 3654642e01fSmrg { 3664642e01fSmrg XIPropertyHandlerPtr handler = device->properties.handlers; 3674642e01fSmrg while(handler) 3684642e01fSmrg { 3694642e01fSmrg if (handler->DeleteProperty) 3704642e01fSmrg rc = handler->DeleteProperty(device, prop->propertyName); 3714642e01fSmrg if (rc != Success) 3724642e01fSmrg return (rc); 3734642e01fSmrg handler = handler->next; 3744642e01fSmrg } 3754642e01fSmrg } 3764642e01fSmrg 3774642e01fSmrg if (prop) 3784642e01fSmrg { 3794642e01fSmrg *prev = prop->next; 3804642e01fSmrg event.type = DevicePropertyNotify; 3814642e01fSmrg event.deviceid = device->id; 3824642e01fSmrg event.state = PropertyDelete; 3834642e01fSmrg event.atom = prop->propertyName; 3844642e01fSmrg event.time = currentTime.milliseconds; 3854642e01fSmrg SendEventToAllWindows(device, DevicePropertyNotifyMask, 3864642e01fSmrg (xEvent*)&event, 1); 3874642e01fSmrg XIDestroyDeviceProperty (prop); 3884642e01fSmrg } 3894642e01fSmrg 3904642e01fSmrg return Success; 3914642e01fSmrg} 3924642e01fSmrg 3934642e01fSmrgint 3944642e01fSmrgXIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type, 3954642e01fSmrg int format, int mode, unsigned long len, 3964642e01fSmrg pointer value, Bool sendevent) 3974642e01fSmrg{ 3984642e01fSmrg XIPropertyPtr prop; 3994642e01fSmrg devicePropertyNotify event; 4004642e01fSmrg int size_in_bytes; 4014642e01fSmrg int total_size; 4024642e01fSmrg unsigned long total_len; 4034642e01fSmrg XIPropertyValuePtr prop_value; 4044642e01fSmrg XIPropertyValueRec new_value; 4054642e01fSmrg Bool add = FALSE; 4064642e01fSmrg int rc; 4074642e01fSmrg 4084642e01fSmrg size_in_bytes = format >> 3; 4094642e01fSmrg 4104642e01fSmrg /* first see if property already exists */ 4114642e01fSmrg prop = XIFetchDeviceProperty (dev, property); 4124642e01fSmrg if (!prop) /* just add to list */ 4134642e01fSmrg { 4144642e01fSmrg prop = XICreateDeviceProperty (property); 4154642e01fSmrg if (!prop) 4164642e01fSmrg return(BadAlloc); 4174642e01fSmrg add = TRUE; 4184642e01fSmrg mode = PropModeReplace; 4194642e01fSmrg } 4204642e01fSmrg prop_value = &prop->value; 4214642e01fSmrg 4224642e01fSmrg /* To append or prepend to a property the request format and type 4234642e01fSmrg must match those of the already defined property. The 4244642e01fSmrg existing format and type are irrelevant when using the mode 4254642e01fSmrg "PropModeReplace" since they will be written over. */ 4264642e01fSmrg 4274642e01fSmrg if ((format != prop_value->format) && (mode != PropModeReplace)) 4284642e01fSmrg return(BadMatch); 4294642e01fSmrg if ((prop_value->type != type) && (mode != PropModeReplace)) 4304642e01fSmrg return(BadMatch); 4314642e01fSmrg new_value = *prop_value; 4324642e01fSmrg if (mode == PropModeReplace) 4334642e01fSmrg total_len = len; 4344642e01fSmrg else 4354642e01fSmrg total_len = prop_value->size + len; 4364642e01fSmrg 4374642e01fSmrg if (mode == PropModeReplace || len > 0) 4384642e01fSmrg { 4394642e01fSmrg pointer new_data = NULL, old_data = NULL; 4404642e01fSmrg 4414642e01fSmrg total_size = total_len * size_in_bytes; 4424642e01fSmrg new_value.data = (pointer)xalloc (total_size); 4434642e01fSmrg if (!new_value.data && total_size) 4444642e01fSmrg { 4454642e01fSmrg if (add) 4464642e01fSmrg XIDestroyDeviceProperty (prop); 4474642e01fSmrg return BadAlloc; 4484642e01fSmrg } 4494642e01fSmrg new_value.size = len; 4504642e01fSmrg new_value.type = type; 4514642e01fSmrg new_value.format = format; 4524642e01fSmrg 4534642e01fSmrg switch (mode) { 4544642e01fSmrg case PropModeReplace: 4554642e01fSmrg new_data = new_value.data; 4564642e01fSmrg old_data = NULL; 4574642e01fSmrg break; 4584642e01fSmrg case PropModeAppend: 4594642e01fSmrg new_data = (pointer) (((char *) new_value.data) + 4604642e01fSmrg (prop_value->size * size_in_bytes)); 4614642e01fSmrg old_data = new_value.data; 4624642e01fSmrg break; 4634642e01fSmrg case PropModePrepend: 4644642e01fSmrg new_data = new_value.data; 4654642e01fSmrg old_data = (pointer) (((char *) new_value.data) + 4664642e01fSmrg (prop_value->size * size_in_bytes)); 4674642e01fSmrg break; 4684642e01fSmrg } 4694642e01fSmrg if (new_data) 4704642e01fSmrg memcpy ((char *) new_data, (char *) value, len * size_in_bytes); 4714642e01fSmrg if (old_data) 4724642e01fSmrg memcpy ((char *) old_data, (char *) prop_value->data, 4734642e01fSmrg prop_value->size * size_in_bytes); 4744642e01fSmrg 4754642e01fSmrg if (dev->properties.handlers) 4764642e01fSmrg { 4774642e01fSmrg XIPropertyHandlerPtr handler; 4784642e01fSmrg BOOL checkonly = TRUE; 4794642e01fSmrg /* run through all handlers with checkonly TRUE, then again with 4804642e01fSmrg * checkonly FALSE. Handlers MUST return error codes on the 4814642e01fSmrg * checkonly run, errors on the second run are ignored */ 4824642e01fSmrg do 4834642e01fSmrg { 4844642e01fSmrg handler = dev->properties.handlers; 4854642e01fSmrg while(handler) 4864642e01fSmrg { 4874642e01fSmrg if (handler->SetProperty) 4884642e01fSmrg { 4894642e01fSmrg rc = handler->SetProperty(dev, prop->propertyName, 4904642e01fSmrg &new_value, checkonly); 4914642e01fSmrg if (checkonly && rc != Success) 4924642e01fSmrg { 4934642e01fSmrg if (new_value.data) 4944642e01fSmrg xfree (new_value.data); 4954642e01fSmrg return (rc); 4964642e01fSmrg } 4974642e01fSmrg } 4984642e01fSmrg handler = handler->next; 4994642e01fSmrg } 5004642e01fSmrg checkonly = !checkonly; 5014642e01fSmrg } while (!checkonly); 5024642e01fSmrg } 5034642e01fSmrg if (prop_value->data) 5044642e01fSmrg xfree (prop_value->data); 5054642e01fSmrg *prop_value = new_value; 5064642e01fSmrg } else if (len == 0) 5074642e01fSmrg { 5084642e01fSmrg /* do nothing */ 5094642e01fSmrg } 5104642e01fSmrg 5114642e01fSmrg if (add) 5124642e01fSmrg { 5134642e01fSmrg prop->next = dev->properties.properties; 5144642e01fSmrg dev->properties.properties = prop; 5154642e01fSmrg } 5164642e01fSmrg 5174642e01fSmrg if (sendevent) 5184642e01fSmrg { 5194642e01fSmrg event.type = DevicePropertyNotify; 5204642e01fSmrg event.deviceid = dev->id; 5214642e01fSmrg event.state = PropertyNewValue; 5224642e01fSmrg event.atom = prop->propertyName; 5234642e01fSmrg event.time = currentTime.milliseconds; 5244642e01fSmrg SendEventToAllWindows(dev, DevicePropertyNotifyMask, 5254642e01fSmrg (xEvent*)&event, 1); 5264642e01fSmrg } 5274642e01fSmrg return(Success); 5284642e01fSmrg} 5294642e01fSmrg 5304642e01fSmrgint 5314642e01fSmrgXIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value) 5324642e01fSmrg{ 5334642e01fSmrg XIPropertyPtr prop = XIFetchDeviceProperty (dev, property); 5344642e01fSmrg int rc; 5354642e01fSmrg 5364642e01fSmrg if (!prop) 5374642e01fSmrg { 5384642e01fSmrg *value = NULL; 5394642e01fSmrg return BadAtom; 5404642e01fSmrg } 5414642e01fSmrg 5424642e01fSmrg /* If we can, try to update the property value first */ 5434642e01fSmrg if (dev->properties.handlers) 5444642e01fSmrg { 5454642e01fSmrg XIPropertyHandlerPtr handler = dev->properties.handlers; 5464642e01fSmrg while(handler) 5474642e01fSmrg { 5484642e01fSmrg if (handler->GetProperty) 5494642e01fSmrg { 5504642e01fSmrg rc = handler->GetProperty(dev, prop->propertyName); 5514642e01fSmrg if (rc != Success) 5524642e01fSmrg { 5534642e01fSmrg *value = NULL; 5544642e01fSmrg return rc; 5554642e01fSmrg } 5564642e01fSmrg } 5574642e01fSmrg handler = handler->next; 5584642e01fSmrg } 5594642e01fSmrg } 5604642e01fSmrg 5614642e01fSmrg *value = &prop->value; 5624642e01fSmrg return Success; 5634642e01fSmrg} 5644642e01fSmrg 5654642e01fSmrgint 5664642e01fSmrgXISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable) 5674642e01fSmrg{ 5684642e01fSmrg XIPropertyPtr prop = XIFetchDeviceProperty(dev, property); 5694642e01fSmrg 5704642e01fSmrg if (!prop) 5714642e01fSmrg return BadAtom; 5724642e01fSmrg 5734642e01fSmrg prop->deletable = deletable; 5744642e01fSmrg return Success; 5754642e01fSmrg} 5764642e01fSmrg 5774642e01fSmrgint 5784642e01fSmrgProcXListDeviceProperties (ClientPtr client) 5794642e01fSmrg{ 5804642e01fSmrg Atom *pAtoms = NULL, *temppAtoms; 5814642e01fSmrg xListDevicePropertiesReply rep; 5824642e01fSmrg int numProps = 0; 5834642e01fSmrg DeviceIntPtr dev; 5844642e01fSmrg XIPropertyPtr prop; 5854642e01fSmrg int rc = Success; 5864642e01fSmrg 5874642e01fSmrg REQUEST(xListDevicePropertiesReq); 5884642e01fSmrg REQUEST_SIZE_MATCH(xListDevicePropertiesReq); 5894642e01fSmrg 5904642e01fSmrg rc = dixLookupDevice (&dev, stuff->deviceid, client, DixReadAccess); 5914642e01fSmrg if (rc != Success) 5924642e01fSmrg return rc; 5934642e01fSmrg 5944642e01fSmrg for (prop = dev->properties.properties; prop; prop = prop->next) 5954642e01fSmrg numProps++; 5964642e01fSmrg if (numProps) 5974642e01fSmrg if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) 5984642e01fSmrg return(BadAlloc); 5994642e01fSmrg 6004642e01fSmrg rep.repType = X_Reply; 6014642e01fSmrg rep.RepType = X_ListDeviceProperties; 6024642e01fSmrg rep.length = (numProps * sizeof(Atom)) >> 2; 6034642e01fSmrg rep.sequenceNumber = client->sequence; 6044642e01fSmrg rep.nAtoms = numProps; 6054642e01fSmrg if (client->swapped) 6064642e01fSmrg { 6074642e01fSmrg int n; 6084642e01fSmrg swaps (&rep.sequenceNumber, n); 6094642e01fSmrg swapl (&rep.length, n); 6104642e01fSmrg swaps (&rep.nAtoms, n); 6114642e01fSmrg } 6124642e01fSmrg temppAtoms = pAtoms; 6134642e01fSmrg for (prop = dev->properties.properties; prop; prop = prop->next) 6144642e01fSmrg *temppAtoms++ = prop->propertyName; 6154642e01fSmrg 6164642e01fSmrg WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); 6174642e01fSmrg if (numProps) 6184642e01fSmrg { 6194642e01fSmrg client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write; 6204642e01fSmrg WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); 6214642e01fSmrg xfree(pAtoms); 6224642e01fSmrg } 6234642e01fSmrg return rc; 6244642e01fSmrg} 6254642e01fSmrg 6264642e01fSmrgint 6274642e01fSmrgProcXChangeDeviceProperty (ClientPtr client) 6284642e01fSmrg{ 6294642e01fSmrg REQUEST(xChangeDevicePropertyReq); 6304642e01fSmrg DeviceIntPtr dev; 6314642e01fSmrg char format, mode; 6324642e01fSmrg unsigned long len; 6334642e01fSmrg int sizeInBytes; 6344642e01fSmrg int totalSize; 6354642e01fSmrg int rc; 6364642e01fSmrg 6374642e01fSmrg REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq); 6384642e01fSmrg UpdateCurrentTime(); 6394642e01fSmrg format = stuff->format; 6404642e01fSmrg mode = stuff->mode; 6414642e01fSmrg if ((mode != PropModeReplace) && (mode != PropModeAppend) && 6424642e01fSmrg (mode != PropModePrepend)) 6434642e01fSmrg { 6444642e01fSmrg client->errorValue = mode; 6454642e01fSmrg return BadValue; 6464642e01fSmrg } 6474642e01fSmrg if ((format != 8) && (format != 16) && (format != 32)) 6484642e01fSmrg { 6494642e01fSmrg client->errorValue = format; 6504642e01fSmrg return BadValue; 6514642e01fSmrg } 6524642e01fSmrg len = stuff->nUnits; 6534642e01fSmrg if (len > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2)) 6544642e01fSmrg return BadLength; 6554642e01fSmrg sizeInBytes = format>>3; 6564642e01fSmrg totalSize = len * sizeInBytes; 6574642e01fSmrg REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize); 6584642e01fSmrg 6594642e01fSmrg rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess); 6604642e01fSmrg if (rc != Success) 6614642e01fSmrg return rc; 6624642e01fSmrg 6634642e01fSmrg if (!ValidAtom(stuff->property)) 6644642e01fSmrg { 6654642e01fSmrg client->errorValue = stuff->property; 6664642e01fSmrg return(BadAtom); 6674642e01fSmrg } 6684642e01fSmrg if (!ValidAtom(stuff->type)) 6694642e01fSmrg { 6704642e01fSmrg client->errorValue = stuff->type; 6714642e01fSmrg return(BadAtom); 6724642e01fSmrg } 6734642e01fSmrg 6744642e01fSmrg rc = XIChangeDeviceProperty(dev, stuff->property, 6754642e01fSmrg stuff->type, (int)format, 6764642e01fSmrg (int)mode, len, (pointer)&stuff[1], TRUE); 6774642e01fSmrg 6784642e01fSmrg if (rc != Success) 6794642e01fSmrg client->errorValue = stuff->property; 6804642e01fSmrg return rc; 6814642e01fSmrg} 6824642e01fSmrg 6834642e01fSmrgint 6844642e01fSmrgProcXDeleteDeviceProperty (ClientPtr client) 6854642e01fSmrg{ 6864642e01fSmrg REQUEST(xDeleteDevicePropertyReq); 6874642e01fSmrg DeviceIntPtr dev; 6884642e01fSmrg int rc; 6894642e01fSmrg 6904642e01fSmrg REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); 6914642e01fSmrg UpdateCurrentTime(); 6924642e01fSmrg rc = dixLookupDevice (&dev, stuff->deviceid, client, DixWriteAccess); 6934642e01fSmrg if (rc != Success) 6944642e01fSmrg return rc; 6954642e01fSmrg 6964642e01fSmrg if (!ValidAtom(stuff->property)) 6974642e01fSmrg { 6984642e01fSmrg client->errorValue = stuff->property; 6994642e01fSmrg return (BadAtom); 7004642e01fSmrg } 7014642e01fSmrg 7024642e01fSmrg rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE); 7034642e01fSmrg return rc; 7044642e01fSmrg} 7054642e01fSmrg 7064642e01fSmrgint 7074642e01fSmrgProcXGetDeviceProperty (ClientPtr client) 7084642e01fSmrg{ 7094642e01fSmrg REQUEST(xGetDevicePropertyReq); 7104642e01fSmrg XIPropertyPtr prop, *prev; 7114642e01fSmrg XIPropertyValuePtr prop_value; 7124642e01fSmrg unsigned long n, len, ind; 7134642e01fSmrg DeviceIntPtr dev; 7144642e01fSmrg xGetDevicePropertyReply reply; 7154642e01fSmrg int rc; 7164642e01fSmrg 7174642e01fSmrg REQUEST_SIZE_MATCH(xGetDevicePropertyReq); 7184642e01fSmrg if (stuff->delete) 7194642e01fSmrg UpdateCurrentTime(); 7204642e01fSmrg rc = dixLookupDevice (&dev, stuff->deviceid, client, 7214642e01fSmrg stuff->delete ? DixWriteAccess : 7224642e01fSmrg DixReadAccess); 7234642e01fSmrg if (rc != Success) 7244642e01fSmrg return rc; 7254642e01fSmrg 7264642e01fSmrg if (!ValidAtom(stuff->property)) 7274642e01fSmrg { 7284642e01fSmrg client->errorValue = stuff->property; 7294642e01fSmrg return(BadAtom); 7304642e01fSmrg } 7314642e01fSmrg if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) 7324642e01fSmrg { 7334642e01fSmrg client->errorValue = stuff->delete; 7344642e01fSmrg return(BadValue); 7354642e01fSmrg } 7364642e01fSmrg if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) 7374642e01fSmrg { 7384642e01fSmrg client->errorValue = stuff->type; 7394642e01fSmrg return(BadAtom); 7404642e01fSmrg } 7414642e01fSmrg 7424642e01fSmrg for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next) 7434642e01fSmrg if (prop->propertyName == stuff->property) 7444642e01fSmrg break; 7454642e01fSmrg 7464642e01fSmrg reply.repType = X_Reply; 7474642e01fSmrg reply.RepType = X_GetDeviceProperty; 7484642e01fSmrg reply.sequenceNumber = client->sequence; 7494642e01fSmrg reply.deviceid = dev->id; 7504642e01fSmrg if (!prop) 7514642e01fSmrg { 7524642e01fSmrg reply.nItems = 0; 7534642e01fSmrg reply.length = 0; 7544642e01fSmrg reply.bytesAfter = 0; 7554642e01fSmrg reply.propertyType = None; 7564642e01fSmrg reply.format = 0; 7574642e01fSmrg WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply); 7584642e01fSmrg return(client->noClientException); 7594642e01fSmrg } 7604642e01fSmrg 7614642e01fSmrg rc = XIGetDeviceProperty(dev, stuff->property, &prop_value); 7624642e01fSmrg if (rc != Success) 7634642e01fSmrg { 7644642e01fSmrg client->errorValue = stuff->property; 7654642e01fSmrg return rc; 7664642e01fSmrg } 7674642e01fSmrg 7684642e01fSmrg /* If the request type and actual type don't match. Return the 7694642e01fSmrg property information, but not the data. */ 7704642e01fSmrg 7714642e01fSmrg if (((stuff->type != prop_value->type) && 7724642e01fSmrg (stuff->type != AnyPropertyType)) 7734642e01fSmrg ) 7744642e01fSmrg { 7754642e01fSmrg reply.bytesAfter = prop_value->size; 7764642e01fSmrg reply.format = prop_value->format; 7774642e01fSmrg reply.length = 0; 7784642e01fSmrg reply.nItems = 0; 7794642e01fSmrg reply.propertyType = prop_value->type; 7804642e01fSmrg WriteReplyToClient(client, sizeof(xGetDevicePropertyReply), &reply); 7814642e01fSmrg return(client->noClientException); 7824642e01fSmrg } 7834642e01fSmrg 7844642e01fSmrg/* 7854642e01fSmrg * Return type, format, value to client 7864642e01fSmrg */ 7874642e01fSmrg n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */ 7884642e01fSmrg ind = stuff->longOffset << 2; 7894642e01fSmrg 7904642e01fSmrg /* If longOffset is invalid such that it causes "len" to 7914642e01fSmrg be negative, it's a value error. */ 7924642e01fSmrg 7934642e01fSmrg if (n < ind) 7944642e01fSmrg { 7954642e01fSmrg client->errorValue = stuff->longOffset; 7964642e01fSmrg return BadValue; 7974642e01fSmrg } 7984642e01fSmrg 7994642e01fSmrg len = min(n - ind, 4 * stuff->longLength); 8004642e01fSmrg 8014642e01fSmrg reply.bytesAfter = n - (ind + len); 8024642e01fSmrg reply.format = prop_value->format; 8034642e01fSmrg reply.length = (len + 3) >> 2; 8044642e01fSmrg if (prop_value->format) 8054642e01fSmrg reply.nItems = len / (prop_value->format / 8); 8064642e01fSmrg else 8074642e01fSmrg reply.nItems = 0; 8084642e01fSmrg reply.propertyType = prop_value->type; 8094642e01fSmrg 8104642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) 8114642e01fSmrg { 8124642e01fSmrg devicePropertyNotify event; 8134642e01fSmrg 8144642e01fSmrg event.type = DevicePropertyNotify; 8154642e01fSmrg event.deviceid = dev->id; 8164642e01fSmrg event.state = PropertyDelete; 8174642e01fSmrg event.atom = prop->propertyName; 8184642e01fSmrg event.time = currentTime.milliseconds; 8194642e01fSmrg SendEventToAllWindows(dev, DevicePropertyNotifyMask, 8204642e01fSmrg (xEvent*)&event, 1); 8214642e01fSmrg } 8224642e01fSmrg 8234642e01fSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 8244642e01fSmrg if (len) 8254642e01fSmrg { 8264642e01fSmrg switch (reply.format) { 8274642e01fSmrg case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break; 8284642e01fSmrg case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break; 8294642e01fSmrg default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break; 8304642e01fSmrg } 8314642e01fSmrg WriteSwappedDataToClient(client, len, 8324642e01fSmrg (char *)prop_value->data + ind); 8334642e01fSmrg } 8344642e01fSmrg 8354642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) 8364642e01fSmrg { /* delete the Property */ 8374642e01fSmrg *prev = prop->next; 8384642e01fSmrg XIDestroyDeviceProperty (prop); 8394642e01fSmrg } 8404642e01fSmrg return(client->noClientException); 8414642e01fSmrg} 8424642e01fSmrg 8434642e01fSmrg 8444642e01fSmrgint 8454642e01fSmrgSProcXListDeviceProperties (ClientPtr client) 8464642e01fSmrg{ 8474642e01fSmrg char n; 8484642e01fSmrg REQUEST(xListDevicePropertiesReq); 8494642e01fSmrg 8504642e01fSmrg swaps(&stuff->length, n); 8514642e01fSmrg 8524642e01fSmrg REQUEST_SIZE_MATCH(xListDevicePropertiesReq); 8534642e01fSmrg return (ProcXListDeviceProperties(client)); 8544642e01fSmrg} 8554642e01fSmrg 8564642e01fSmrgint 8574642e01fSmrgSProcXChangeDeviceProperty (ClientPtr client) 8584642e01fSmrg{ 8594642e01fSmrg char n; 8604642e01fSmrg REQUEST(xChangeDevicePropertyReq); 8614642e01fSmrg 8624642e01fSmrg swaps(&stuff->length, n); 8634642e01fSmrg swapl(&stuff->property, n); 8644642e01fSmrg swapl(&stuff->type, n); 8654642e01fSmrg swapl(&stuff->nUnits, n); 8664642e01fSmrg REQUEST_SIZE_MATCH(xChangeDevicePropertyReq); 8674642e01fSmrg return (ProcXChangeDeviceProperty(client)); 8684642e01fSmrg} 8694642e01fSmrg 8704642e01fSmrgint 8714642e01fSmrgSProcXDeleteDeviceProperty (ClientPtr client) 8724642e01fSmrg{ 8734642e01fSmrg char n; 8744642e01fSmrg REQUEST(xDeleteDevicePropertyReq); 8754642e01fSmrg 8764642e01fSmrg swaps(&stuff->length, n); 8774642e01fSmrg swapl(&stuff->property, n); 8784642e01fSmrg REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); 8794642e01fSmrg return (ProcXDeleteDeviceProperty(client)); 8804642e01fSmrg} 8814642e01fSmrg 8824642e01fSmrgint 8834642e01fSmrgSProcXGetDeviceProperty (ClientPtr client) 8844642e01fSmrg{ 8854642e01fSmrg char n; 8864642e01fSmrg REQUEST(xGetDevicePropertyReq); 8874642e01fSmrg 8884642e01fSmrg swaps(&stuff->length, n); 8894642e01fSmrg swapl(&stuff->property, n); 8904642e01fSmrg swapl(&stuff->type, n); 8914642e01fSmrg swapl(&stuff->longOffset, n); 8924642e01fSmrg swapl(&stuff->longLength, n); 8934642e01fSmrg REQUEST_SIZE_MATCH(xGetDevicePropertyReq); 8944642e01fSmrg return (ProcXGetDeviceProperty(client)); 8954642e01fSmrg} 8964642e01fSmrg 8974642e01fSmrg 8984642e01fSmrg/* Reply swapping */ 8994642e01fSmrg 9004642e01fSmrgvoid 9014642e01fSmrgSRepXListDeviceProperties(ClientPtr client, int size, 9024642e01fSmrg xListDevicePropertiesReply *rep) 9034642e01fSmrg{ 9044642e01fSmrg char n; 9054642e01fSmrg swaps(&rep->sequenceNumber, n); 9064642e01fSmrg swapl(&rep->length, n); 9074642e01fSmrg swaps(&rep->nAtoms, n); 9084642e01fSmrg /* properties will be swapped later, see ProcXListDeviceProperties */ 9094642e01fSmrg WriteToClient(client, size, (char*)rep); 9104642e01fSmrg} 9114642e01fSmrg 9124642e01fSmrgvoid 9134642e01fSmrgSRepXGetDeviceProperty(ClientPtr client, int size, 9144642e01fSmrg xGetDevicePropertyReply *rep) 9154642e01fSmrg{ 9164642e01fSmrg char n; 9174642e01fSmrg 9184642e01fSmrg swaps(&rep->sequenceNumber, n); 9194642e01fSmrg swapl(&rep->length, n); 9204642e01fSmrg swapl(&rep->propertyType, n); 9214642e01fSmrg swapl(&rep->bytesAfter, n); 9224642e01fSmrg swapl(&rep->nItems, n); 9234642e01fSmrg /* data will be swapped, see ProcXGetDeviceProperty */ 9244642e01fSmrg WriteToClient(client, size, (char*)rep); 9254642e01fSmrg} 926