1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324 |
- /*
- * Copyright © 2006 Keith Packard
- * Copyright © 2008 Peter Hutterer
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WAXIANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- */
- /* This code is a modified version of randr/rrproperty.c */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include "dix.h"
- #include "inputstr.h"
- #include <X11/extensions/XI.h>
- #include <X11/Xatom.h>
- #include <X11/extensions/XIproto.h>
- #include <X11/extensions/XI2proto.h>
- #include "exglobals.h"
- #include "exevents.h"
- #include "swaprep.h"
- #include "xiproperty.h"
- #include "xserver-properties.h"
- /**
- * Properties used or alloced from inside the server.
- */
- static struct dev_properties {
- Atom type;
- const char *name;
- } dev_properties[] = {
- {0, XI_PROP_ENABLED},
- {0, XI_PROP_XTEST_DEVICE},
- {0, XATOM_FLOAT},
- {0, ACCEL_PROP_PROFILE_NUMBER},
- {0, ACCEL_PROP_CONSTANT_DECELERATION},
- {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
- {0, ACCEL_PROP_VELOCITY_SCALING},
- {0, AXIS_LABEL_PROP},
- {0, AXIS_LABEL_PROP_REL_X},
- {0, AXIS_LABEL_PROP_REL_Y},
- {0, AXIS_LABEL_PROP_REL_Z},
- {0, AXIS_LABEL_PROP_REL_RX},
- {0, AXIS_LABEL_PROP_REL_RY},
- {0, AXIS_LABEL_PROP_REL_RZ},
- {0, AXIS_LABEL_PROP_REL_HWHEEL},
- {0, AXIS_LABEL_PROP_REL_DIAL},
- {0, AXIS_LABEL_PROP_REL_WHEEL},
- {0, AXIS_LABEL_PROP_REL_MISC},
- {0, AXIS_LABEL_PROP_REL_VSCROLL},
- {0, AXIS_LABEL_PROP_REL_HSCROLL},
- {0, AXIS_LABEL_PROP_ABS_X},
- {0, AXIS_LABEL_PROP_ABS_Y},
- {0, AXIS_LABEL_PROP_ABS_Z},
- {0, AXIS_LABEL_PROP_ABS_RX},
- {0, AXIS_LABEL_PROP_ABS_RY},
- {0, AXIS_LABEL_PROP_ABS_RZ},
- {0, AXIS_LABEL_PROP_ABS_THROTTLE},
- {0, AXIS_LABEL_PROP_ABS_RUDDER},
- {0, AXIS_LABEL_PROP_ABS_WHEEL},
- {0, AXIS_LABEL_PROP_ABS_GAS},
- {0, AXIS_LABEL_PROP_ABS_BRAKE},
- {0, AXIS_LABEL_PROP_ABS_HAT0X},
- {0, AXIS_LABEL_PROP_ABS_HAT0Y},
- {0, AXIS_LABEL_PROP_ABS_HAT1X},
- {0, AXIS_LABEL_PROP_ABS_HAT1Y},
- {0, AXIS_LABEL_PROP_ABS_HAT2X},
- {0, AXIS_LABEL_PROP_ABS_HAT2Y},
- {0, AXIS_LABEL_PROP_ABS_HAT3X},
- {0, AXIS_LABEL_PROP_ABS_HAT3Y},
- {0, AXIS_LABEL_PROP_ABS_PRESSURE},
- {0, AXIS_LABEL_PROP_ABS_DISTANCE},
- {0, AXIS_LABEL_PROP_ABS_TILT_X},
- {0, AXIS_LABEL_PROP_ABS_TILT_Y},
- {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
- {0, AXIS_LABEL_PROP_ABS_VOLUME},
- {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
- {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
- {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
- {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
- {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
- {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
- {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
- {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
- {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
- {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
- {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
- {0, AXIS_LABEL_PROP_ABS_MT_DISTANCE},
- {0, AXIS_LABEL_PROP_ABS_MT_TOOL_X},
- {0, AXIS_LABEL_PROP_ABS_MT_TOOL_Y},
- {0, AXIS_LABEL_PROP_ABS_MISC},
- {0, BTN_LABEL_PROP},
- {0, BTN_LABEL_PROP_BTN_UNKNOWN},
- {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
- {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
- {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
- {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
- {0, BTN_LABEL_PROP_BTN_0},
- {0, BTN_LABEL_PROP_BTN_1},
- {0, BTN_LABEL_PROP_BTN_2},
- {0, BTN_LABEL_PROP_BTN_3},
- {0, BTN_LABEL_PROP_BTN_4},
- {0, BTN_LABEL_PROP_BTN_5},
- {0, BTN_LABEL_PROP_BTN_6},
- {0, BTN_LABEL_PROP_BTN_7},
- {0, BTN_LABEL_PROP_BTN_8},
- {0, BTN_LABEL_PROP_BTN_9},
- {0, BTN_LABEL_PROP_BTN_LEFT},
- {0, BTN_LABEL_PROP_BTN_RIGHT},
- {0, BTN_LABEL_PROP_BTN_MIDDLE},
- {0, BTN_LABEL_PROP_BTN_SIDE},
- {0, BTN_LABEL_PROP_BTN_EXTRA},
- {0, BTN_LABEL_PROP_BTN_FORWARD},
- {0, BTN_LABEL_PROP_BTN_BACK},
- {0, BTN_LABEL_PROP_BTN_TASK},
- {0, BTN_LABEL_PROP_BTN_TRIGGER},
- {0, BTN_LABEL_PROP_BTN_THUMB},
- {0, BTN_LABEL_PROP_BTN_THUMB2},
- {0, BTN_LABEL_PROP_BTN_TOP},
- {0, BTN_LABEL_PROP_BTN_TOP2},
- {0, BTN_LABEL_PROP_BTN_PINKIE},
- {0, BTN_LABEL_PROP_BTN_BASE},
- {0, BTN_LABEL_PROP_BTN_BASE2},
- {0, BTN_LABEL_PROP_BTN_BASE3},
- {0, BTN_LABEL_PROP_BTN_BASE4},
- {0, BTN_LABEL_PROP_BTN_BASE5},
- {0, BTN_LABEL_PROP_BTN_BASE6},
- {0, BTN_LABEL_PROP_BTN_DEAD},
- {0, BTN_LABEL_PROP_BTN_A},
- {0, BTN_LABEL_PROP_BTN_B},
- {0, BTN_LABEL_PROP_BTN_C},
- {0, BTN_LABEL_PROP_BTN_X},
- {0, BTN_LABEL_PROP_BTN_Y},
- {0, BTN_LABEL_PROP_BTN_Z},
- {0, BTN_LABEL_PROP_BTN_TL},
- {0, BTN_LABEL_PROP_BTN_TR},
- {0, BTN_LABEL_PROP_BTN_TL2},
- {0, BTN_LABEL_PROP_BTN_TR2},
- {0, BTN_LABEL_PROP_BTN_SELECT},
- {0, BTN_LABEL_PROP_BTN_START},
- {0, BTN_LABEL_PROP_BTN_MODE},
- {0, BTN_LABEL_PROP_BTN_THUMBL},
- {0, BTN_LABEL_PROP_BTN_THUMBR},
- {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
- {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
- {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
- {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
- {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
- {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
- {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
- {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
- {0, BTN_LABEL_PROP_BTN_TOUCH},
- {0, BTN_LABEL_PROP_BTN_STYLUS},
- {0, BTN_LABEL_PROP_BTN_STYLUS2},
- {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
- {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
- {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
- {0, BTN_LABEL_PROP_BTN_GEAR_UP},
- {0, XI_PROP_TRANSFORM}
- };
- static long XIPropHandlerID = 1;
- static void
- send_property_event(DeviceIntPtr dev, Atom property, int what)
- {
- int state = (what == XIPropertyDeleted) ? PropertyDelete : PropertyNewValue;
- devicePropertyNotify event = {
- .type = DevicePropertyNotify,
- .deviceid = dev->id,
- .state = state,
- .atom = property,
- .time = currentTime.milliseconds
- };
- xXIPropertyEvent xi2 = {
- .type = GenericEvent,
- .extension = IReqCode,
- .length = 0,
- .evtype = XI_PropertyEvent,
- .deviceid = dev->id,
- .time = currentTime.milliseconds,
- .property = property,
- .what = what
- };
- SendEventToAllWindows(dev, DevicePropertyNotifyMask, (xEvent *) &event, 1);
- SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent *) &xi2),
- (xEvent *) &xi2, 1);
- }
- static int
- list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
- {
- XIPropertyPtr prop;
- Atom *atoms = NULL;
- int nprops = 0;
- for (prop = dev->properties.properties; prop; prop = prop->next)
- nprops++;
- if (nprops) {
- Atom *a;
- atoms = malloc(nprops * sizeof(Atom));
- if (!atoms)
- return BadAlloc;
- a = atoms;
- for (prop = dev->properties.properties; prop; prop = prop->next, a++)
- *a = prop->propertyName;
- }
- *natoms = nprops;
- *atoms_return = atoms;
- return Success;
- }
- static int
- get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
- BOOL delete, int offset, int length,
- int *bytes_after, Atom *type_return, int *format, int *nitems,
- int *length_return, char **data)
- {
- unsigned long n, len, ind;
- int rc;
- XIPropertyPtr prop;
- XIPropertyValuePtr prop_value;
- if (!ValidAtom(property)) {
- client->errorValue = property;
- return BadAtom;
- }
- if ((delete != xTrue) && (delete != xFalse)) {
- client->errorValue = delete;
- return BadValue;
- }
- if ((type != AnyPropertyType) && !ValidAtom(type)) {
- client->errorValue = type;
- return BadAtom;
- }
- for (prop = dev->properties.properties; prop; prop = prop->next)
- if (prop->propertyName == property)
- break;
- if (!prop) {
- *bytes_after = 0;
- *type_return = None;
- *format = 0;
- *nitems = 0;
- *length_return = 0;
- return Success;
- }
- rc = XIGetDeviceProperty(dev, property, &prop_value);
- if (rc != Success) {
- client->errorValue = property;
- return rc;
- }
- /* If the request type and actual type don't match. Return the
- property information, but not the data. */
- if (((type != prop_value->type) && (type != AnyPropertyType))) {
- *bytes_after = prop_value->size;
- *format = prop_value->format;
- *length_return = 0;
- *nitems = 0;
- *type_return = prop_value->type;
- return Success;
- }
- /* Return type, format, value to client */
- n = (prop_value->format / 8) * prop_value->size; /* size (bytes) of prop */
- ind = offset << 2;
- /* If offset is invalid such that it causes "len" to
- be negative, it's a value error. */
- if (n < ind) {
- client->errorValue = offset;
- return BadValue;
- }
- len = min(n - ind, 4 * length);
- *bytes_after = n - (ind + len);
- *format = prop_value->format;
- *length_return = len;
- if (prop_value->format)
- *nitems = len / (prop_value->format / 8);
- else
- *nitems = 0;
- *type_return = prop_value->type;
- *data = (char *) prop_value->data + ind;
- return Success;
- }
- static int
- check_change_property(ClientPtr client, Atom property, Atom type, int format,
- int mode, int nitems)
- {
- if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
- (mode != PropModePrepend)) {
- client->errorValue = mode;
- return BadValue;
- }
- if ((format != 8) && (format != 16) && (format != 32)) {
- client->errorValue = format;
- return BadValue;
- }
- if (!ValidAtom(property)) {
- client->errorValue = property;
- return BadAtom;
- }
- if (!ValidAtom(type)) {
- client->errorValue = type;
- return BadAtom;
- }
- return Success;
- }
- static int
- change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
- int format, int mode, int len, void *data)
- {
- int rc = Success;
- rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data,
- TRUE);
- if (rc != Success)
- client->errorValue = property;
- return rc;
- }
- /**
- * Return the atom assigned to the specified string or 0 if the atom isn't known
- * to the DIX.
- *
- * If name is NULL, None is returned.
- */
- Atom
- XIGetKnownProperty(const char *name)
- {
- int i;
- if (!name)
- return None;
- for (i = 0; i < (sizeof(dev_properties) / sizeof(struct dev_properties));
- i++) {
- if (strcmp(name, dev_properties[i].name) == 0) {
- if (dev_properties[i].type == None) {
- dev_properties[i].type =
- MakeAtom(dev_properties[i].name,
- strlen(dev_properties[i].name), TRUE);
- }
- return dev_properties[i].type;
- }
- }
- return 0;
- }
- void
- XIResetProperties(void)
- {
- int i;
- for (i = 0; i < (sizeof(dev_properties) / sizeof(struct dev_properties));
- i++)
- dev_properties[i].type = None;
- }
- /**
- * Convert the given property's value(s) into @nelem_return integer values and
- * store them in @buf_return. If @nelem_return is larger than the number of
- * values in the property, @nelem_return is set to the number of values in the
- * property.
- *
- * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
- * automatically and must be freed by the caller.
- *
- * Possible return codes.
- * Success ... No error.
- * BadMatch ... Wrong atom type, atom is not XA_INTEGER
- * BadAlloc ... NULL passed as buffer and allocation failed.
- * BadLength ... @buff is NULL but @nelem_return is non-zero.
- *
- * @param val The property value
- * @param nelem_return The maximum number of elements to return.
- * @param buf_return Pointer to an array of at least @nelem_return values.
- * @return Success or the error code if an error occured.
- */
- _X_EXPORT int
- XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
- {
- int i;
- int *buf;
- if (val->type != XA_INTEGER)
- return BadMatch;
- if (!*buf_return && *nelem_return)
- return BadLength;
- switch (val->format) {
- case 8:
- case 16:
- case 32:
- break;
- default:
- return BadValue;
- }
- buf = *buf_return;
- if (!buf && !(*nelem_return)) {
- buf = calloc(val->size, sizeof(int));
- if (!buf)
- return BadAlloc;
- *buf_return = buf;
- *nelem_return = val->size;
- }
- else if (val->size < *nelem_return)
- *nelem_return = val->size;
- for (i = 0; i < val->size && i < *nelem_return; i++) {
- switch (val->format) {
- case 8:
- buf[i] = ((CARD8 *) val->data)[i];
- break;
- case 16:
- buf[i] = ((CARD16 *) val->data)[i];
- break;
- case 32:
- buf[i] = ((CARD32 *) val->data)[i];
- break;
- }
- }
- return Success;
- }
- /**
- * Convert the given property's value(s) into @nelem_return float values and
- * store them in @buf_return. If @nelem_return is larger than the number of
- * values in the property, @nelem_return is set to the number of values in the
- * property.
- *
- * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
- * automatically and must be freed by the caller.
- *
- * Possible errors returned:
- * Success
- * BadMatch ... Wrong atom type, atom is not XA_FLOAT
- * BadValue ... Wrong format, format is not 32
- * BadAlloc ... NULL passed as buffer and allocation failed.
- * BadLength ... @buff is NULL but @nelem_return is non-zero.
- *
- * @param val The property value
- * @param nelem_return The maximum number of elements to return.
- * @param buf_return Pointer to an array of at least @nelem_return values.
- * @return Success or the error code if an error occured.
- */
- _X_EXPORT int
- XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
- {
- int i;
- float *buf;
- if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
- return BadMatch;
- if (val->format != 32)
- return BadValue;
- if (!*buf_return && *nelem_return)
- return BadLength;
- buf = *buf_return;
- if (!buf && !(*nelem_return)) {
- buf = calloc(val->size, sizeof(float));
- if (!buf)
- return BadAlloc;
- *buf_return = buf;
- *nelem_return = val->size;
- }
- else if (val->size < *nelem_return)
- *nelem_return = val->size;
- for (i = 0; i < val->size && i < *nelem_return; i++)
- buf[i] = ((float *) val->data)[i];
- return Success;
- }
- /* Registers a new property handler on the given device and returns a unique
- * identifier for this handler. This identifier is required to unregister the
- * property handler again.
- * @return The handler's identifier or 0 if an error occured.
- */
- long
- XIRegisterPropertyHandler(DeviceIntPtr dev,
- int (*SetProperty) (DeviceIntPtr dev,
- Atom property,
- XIPropertyValuePtr prop,
- BOOL checkonly),
- int (*GetProperty) (DeviceIntPtr dev,
- Atom property),
- int (*DeleteProperty) (DeviceIntPtr dev,
- Atom property))
- {
- XIPropertyHandlerPtr new_handler;
- new_handler = calloc(1, sizeof(XIPropertyHandler));
- if (!new_handler)
- return 0;
- new_handler->id = XIPropHandlerID++;
- new_handler->SetProperty = SetProperty;
- new_handler->GetProperty = GetProperty;
- new_handler->DeleteProperty = DeleteProperty;
- new_handler->next = dev->properties.handlers;
- dev->properties.handlers = new_handler;
- return new_handler->id;
- }
- void
- XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
- {
- XIPropertyHandlerPtr curr, prev = NULL;
- curr = dev->properties.handlers;
- while (curr && curr->id != id) {
- prev = curr;
- curr = curr->next;
- }
- if (!curr)
- return;
- if (!prev) /* first one */
- dev->properties.handlers = curr->next;
- else
- prev->next = curr->next;
- free(curr);
- }
- static XIPropertyPtr
- XICreateDeviceProperty(Atom property)
- {
- XIPropertyPtr prop;
- prop = (XIPropertyPtr) malloc(sizeof(XIPropertyRec));
- if (!prop)
- return NULL;
- prop->next = NULL;
- prop->propertyName = property;
- prop->value.type = None;
- prop->value.format = 0;
- prop->value.size = 0;
- prop->value.data = NULL;
- prop->deletable = TRUE;
- return prop;
- }
- static XIPropertyPtr
- XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
- {
- XIPropertyPtr prop;
- for (prop = dev->properties.properties; prop; prop = prop->next)
- if (prop->propertyName == property)
- return prop;
- return NULL;
- }
- static void
- XIDestroyDeviceProperty(XIPropertyPtr prop)
- {
- free(prop->value.data);
- free(prop);
- }
- /* This function destroys all of the device's property-related stuff,
- * including removing all device handlers.
- * DO NOT CALL FROM THE DRIVER.
- */
- void
- XIDeleteAllDeviceProperties(DeviceIntPtr device)
- {
- XIPropertyPtr prop, next;
- XIPropertyHandlerPtr curr_handler, next_handler;
- for (prop = device->properties.properties; prop; prop = next) {
- next = prop->next;
- send_property_event(device, prop->propertyName, XIPropertyDeleted);
- XIDestroyDeviceProperty(prop);
- }
- device->properties.properties = NULL;
- /* Now free all handlers */
- curr_handler = device->properties.handlers;
- while (curr_handler) {
- next_handler = curr_handler->next;
- free(curr_handler);
- curr_handler = next_handler;
- }
- device->properties.handlers = NULL;
- }
- int
- XIDeleteDeviceProperty(DeviceIntPtr device, Atom property, Bool fromClient)
- {
- XIPropertyPtr prop, *prev;
- int rc = Success;
- for (prev = &device->properties.properties; (prop = *prev);
- prev = &(prop->next))
- if (prop->propertyName == property)
- break;
- if (!prop)
- return Success;
- if (fromClient && !prop->deletable)
- return BadAccess;
- /* Ask handlers if we may delete the property */
- if (device->properties.handlers) {
- XIPropertyHandlerPtr handler = device->properties.handlers;
- while (handler) {
- if (handler->DeleteProperty)
- rc = handler->DeleteProperty(device, prop->propertyName);
- if (rc != Success)
- return rc;
- handler = handler->next;
- }
- }
- if (prop) {
- *prev = prop->next;
- send_property_event(device, prop->propertyName, XIPropertyDeleted);
- XIDestroyDeviceProperty(prop);
- }
- return Success;
- }
- int
- XIChangeDeviceProperty(DeviceIntPtr dev, Atom property, Atom type,
- int format, int mode, unsigned long len,
- const void *value, Bool sendevent)
- {
- XIPropertyPtr prop;
- int size_in_bytes;
- int total_size;
- unsigned long total_len;
- XIPropertyValuePtr prop_value;
- XIPropertyValueRec new_value;
- Bool add = FALSE;
- int rc;
- size_in_bytes = format >> 3;
- /* first see if property already exists */
- prop = XIFetchDeviceProperty(dev, property);
- if (!prop) { /* just add to list */
- prop = XICreateDeviceProperty(property);
- if (!prop)
- return BadAlloc;
- add = TRUE;
- mode = PropModeReplace;
- }
- prop_value = &prop->value;
- /* To append or prepend to a property the request format and type
- must match those of the already defined property. The
- existing format and type are irrelevant when using the mode
- "PropModeReplace" since they will be written over. */
- if ((format != prop_value->format) && (mode != PropModeReplace))
- return BadMatch;
- if ((prop_value->type != type) && (mode != PropModeReplace))
- return BadMatch;
- new_value = *prop_value;
- if (mode == PropModeReplace)
- total_len = len;
- else
- total_len = prop_value->size + len;
- if (mode == PropModeReplace || len > 0) {
- void *new_data = NULL, *old_data = NULL;
- total_size = total_len * size_in_bytes;
- new_value.data = (void *) malloc(total_size);
- if (!new_value.data && total_size) {
- if (add)
- XIDestroyDeviceProperty(prop);
- return BadAlloc;
- }
- new_value.size = len;
- new_value.type = type;
- new_value.format = format;
- switch (mode) {
- case PropModeReplace:
- new_data = new_value.data;
- old_data = NULL;
- break;
- case PropModeAppend:
- new_data = (void *) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
- old_data = new_value.data;
- break;
- case PropModePrepend:
- new_data = new_value.data;
- old_data = (void *) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
- break;
- }
- if (new_data)
- memcpy((char *) new_data, value, len * size_in_bytes);
- if (old_data)
- memcpy((char *) old_data, (char *) prop_value->data,
- prop_value->size * size_in_bytes);
- if (dev->properties.handlers) {
- XIPropertyHandlerPtr handler;
- BOOL checkonly = TRUE;
- /* run through all handlers with checkonly TRUE, then again with
- * checkonly FALSE. Handlers MUST return error codes on the
- * checkonly run, errors on the second run are ignored */
- do {
- handler = dev->properties.handlers;
- while (handler) {
- if (handler->SetProperty) {
- rc = handler->SetProperty(dev, prop->propertyName,
- &new_value, checkonly);
- if (checkonly && rc != Success) {
- free(new_value.data);
- if (add)
- XIDestroyDeviceProperty(prop);
- return rc;
- }
- }
- handler = handler->next;
- }
- checkonly = !checkonly;
- } while (!checkonly);
- }
- free(prop_value->data);
- *prop_value = new_value;
- }
- else if (len == 0) {
- /* do nothing */
- }
- if (add) {
- prop->next = dev->properties.properties;
- dev->properties.properties = prop;
- }
- if (sendevent)
- send_property_event(dev, prop->propertyName,
- (add) ? XIPropertyCreated : XIPropertyModified);
- return Success;
- }
- int
- XIGetDeviceProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
- {
- XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
- int rc;
- if (!prop) {
- *value = NULL;
- return BadAtom;
- }
- /* If we can, try to update the property value first */
- if (dev->properties.handlers) {
- XIPropertyHandlerPtr handler = dev->properties.handlers;
- while (handler) {
- if (handler->GetProperty) {
- rc = handler->GetProperty(dev, prop->propertyName);
- if (rc != Success) {
- *value = NULL;
- return rc;
- }
- }
- handler = handler->next;
- }
- }
- *value = &prop->value;
- return Success;
- }
- int
- XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
- {
- XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
- if (!prop)
- return BadAtom;
- prop->deletable = deletable;
- return Success;
- }
- int
- ProcXListDeviceProperties(ClientPtr client)
- {
- Atom *atoms;
- xListDevicePropertiesReply rep;
- int natoms;
- DeviceIntPtr dev;
- int rc = Success;
- REQUEST(xListDevicePropertiesReq);
- REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
- if (rc != Success)
- return rc;
- rc = list_atoms(dev, &natoms, &atoms);
- if (rc != Success)
- return rc;
- rep = (xListDevicePropertiesReply) {
- .repType = X_Reply,
- .RepType = X_ListDeviceProperties,
- .sequenceNumber = client->sequence,
- .length = natoms,
- .nAtoms = natoms
- };
- WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
- if (natoms) {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
- free(atoms);
- }
- return rc;
- }
- int
- ProcXChangeDeviceProperty(ClientPtr client)
- {
- REQUEST(xChangeDevicePropertyReq);
- DeviceIntPtr dev;
- unsigned long len;
- int totalSize;
- int rc;
- REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
- rc = check_change_property(client, stuff->property, stuff->type,
- stuff->format, stuff->mode, stuff->nUnits);
- len = stuff->nUnits;
- if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
- return BadLength;
- totalSize = len * (stuff->format / 8);
- REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
- rc = change_property(client, dev, stuff->property, stuff->type,
- stuff->format, stuff->mode, len, (void *) &stuff[1]);
- return rc;
- }
- int
- ProcXDeleteDeviceProperty(ClientPtr client)
- {
- REQUEST(xDeleteDevicePropertyReq);
- DeviceIntPtr dev;
- int rc;
- REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
- if (!ValidAtom(stuff->property)) {
- client->errorValue = stuff->property;
- return BadAtom;
- }
- rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
- return rc;
- }
- int
- ProcXGetDeviceProperty(ClientPtr client)
- {
- REQUEST(xGetDevicePropertyReq);
- DeviceIntPtr dev;
- int length;
- int rc, format, nitems, bytes_after;
- char *data;
- Atom type;
- xGetDevicePropertyReply reply;
- REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
- if (stuff->delete)
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client,
- stuff->delete ? DixSetPropAccess : DixGetPropAccess);
- if (rc != Success)
- return rc;
- rc = get_property(client, dev, stuff->property, stuff->type,
- stuff->delete, stuff->longOffset, stuff->longLength,
- &bytes_after, &type, &format, &nitems, &length, &data);
- if (rc != Success)
- return rc;
- reply = (xGetDevicePropertyReply) {
- .repType = X_Reply,
- .RepType = X_GetDeviceProperty,
- .sequenceNumber = client->sequence,
- .length = bytes_to_int32(length),
- .propertyType = type,
- .bytesAfter = bytes_after,
- .nItems = nitems,
- .format = format,
- .deviceid = dev->id
- };
- if (stuff->delete && (reply.bytesAfter == 0))
- send_property_event(dev, stuff->property, XIPropertyDeleted);
- WriteReplyToClient(client, sizeof(xGenericReply), &reply);
- if (length) {
- switch (reply.format) {
- case 32:
- client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
- break;
- case 16:
- client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
- break;
- default:
- client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
- break;
- }
- WriteSwappedDataToClient(client, length, data);
- }
- /* delete the Property */
- if (stuff->delete && (reply.bytesAfter == 0)) {
- XIPropertyPtr prop, *prev;
- for (prev = &dev->properties.properties; (prop = *prev);
- prev = &prop->next) {
- if (prop->propertyName == stuff->property) {
- *prev = prop->next;
- XIDestroyDeviceProperty(prop);
- break;
- }
- }
- }
- return Success;
- }
- int
- SProcXListDeviceProperties(ClientPtr client)
- {
- REQUEST(xListDevicePropertiesReq);
- REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
- swaps(&stuff->length);
- return (ProcXListDeviceProperties(client));
- }
- int
- SProcXChangeDeviceProperty(ClientPtr client)
- {
- REQUEST(xChangeDevicePropertyReq);
- REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
- swaps(&stuff->length);
- swapl(&stuff->property);
- swapl(&stuff->type);
- swapl(&stuff->nUnits);
- return (ProcXChangeDeviceProperty(client));
- }
- int
- SProcXDeleteDeviceProperty(ClientPtr client)
- {
- REQUEST(xDeleteDevicePropertyReq);
- REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
- swaps(&stuff->length);
- swapl(&stuff->property);
- return (ProcXDeleteDeviceProperty(client));
- }
- int
- SProcXGetDeviceProperty(ClientPtr client)
- {
- REQUEST(xGetDevicePropertyReq);
- REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
- swaps(&stuff->length);
- swapl(&stuff->property);
- swapl(&stuff->type);
- swapl(&stuff->longOffset);
- swapl(&stuff->longLength);
- return (ProcXGetDeviceProperty(client));
- }
- /* Reply swapping */
- void
- SRepXListDeviceProperties(ClientPtr client, int size,
- xListDevicePropertiesReply * rep)
- {
- swaps(&rep->sequenceNumber);
- swapl(&rep->length);
- swaps(&rep->nAtoms);
- /* properties will be swapped later, see ProcXListDeviceProperties */
- WriteToClient(client, size, rep);
- }
- void
- SRepXGetDeviceProperty(ClientPtr client, int size,
- xGetDevicePropertyReply * rep)
- {
- swaps(&rep->sequenceNumber);
- swapl(&rep->length);
- swapl(&rep->propertyType);
- swapl(&rep->bytesAfter);
- swapl(&rep->nItems);
- /* data will be swapped, see ProcXGetDeviceProperty */
- WriteToClient(client, size, rep);
- }
- /* XI2 Request/reply handling */
- int
- ProcXIListProperties(ClientPtr client)
- {
- Atom *atoms;
- xXIListPropertiesReply rep;
- int natoms;
- DeviceIntPtr dev;
- int rc = Success;
- REQUEST(xXIListPropertiesReq);
- REQUEST_SIZE_MATCH(xXIListPropertiesReq);
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixListPropAccess);
- if (rc != Success)
- return rc;
- rc = list_atoms(dev, &natoms, &atoms);
- if (rc != Success)
- return rc;
- rep = (xXIListPropertiesReply) {
- .repType = X_Reply,
- .RepType = X_XIListProperties,
- .sequenceNumber = client->sequence,
- .length = natoms,
- .num_properties = natoms
- };
- WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
- if (natoms) {
- client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
- WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
- free(atoms);
- }
- return rc;
- }
- int
- ProcXIChangeProperty(ClientPtr client)
- {
- int rc;
- DeviceIntPtr dev;
- int totalSize;
- unsigned long len;
- REQUEST(xXIChangePropertyReq);
- REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
- rc = check_change_property(client, stuff->property, stuff->type,
- stuff->format, stuff->mode, stuff->num_items);
- len = stuff->num_items;
- if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
- return BadLength;
- totalSize = len * (stuff->format / 8);
- REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
- rc = change_property(client, dev, stuff->property, stuff->type,
- stuff->format, stuff->mode, len, (void *) &stuff[1]);
- return rc;
- }
- int
- ProcXIDeleteProperty(ClientPtr client)
- {
- DeviceIntPtr dev;
- int rc;
- REQUEST(xXIDeletePropertyReq);
- REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
- if (!ValidAtom(stuff->property)) {
- client->errorValue = stuff->property;
- return BadAtom;
- }
- rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
- return rc;
- }
- int
- ProcXIGetProperty(ClientPtr client)
- {
- REQUEST(xXIGetPropertyReq);
- DeviceIntPtr dev;
- xXIGetPropertyReply reply;
- int length;
- int rc, format, nitems, bytes_after;
- char *data;
- Atom type;
- REQUEST_SIZE_MATCH(xXIGetPropertyReq);
- if (stuff->delete)
- UpdateCurrentTime();
- rc = dixLookupDevice(&dev, stuff->deviceid, client,
- stuff->delete ? DixSetPropAccess : DixGetPropAccess);
- if (rc != Success)
- return rc;
- rc = get_property(client, dev, stuff->property, stuff->type,
- stuff->delete, stuff->offset, stuff->len,
- &bytes_after, &type, &format, &nitems, &length, &data);
- if (rc != Success)
- return rc;
- reply = (xXIGetPropertyReply) {
- .repType = X_Reply,
- .RepType = X_XIGetProperty,
- .sequenceNumber = client->sequence,
- .length = bytes_to_int32(length),
- .type = type,
- .bytes_after = bytes_after,
- .num_items = nitems,
- .format = format
- };
- if (length && stuff->delete && (reply.bytes_after == 0))
- send_property_event(dev, stuff->property, XIPropertyDeleted);
- WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
- if (length) {
- switch (reply.format) {
- case 32:
- client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
- break;
- case 16:
- client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
- break;
- default:
- client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
- break;
- }
- WriteSwappedDataToClient(client, length, data);
- }
- /* delete the Property */
- if (stuff->delete && (reply.bytes_after == 0)) {
- XIPropertyPtr prop, *prev;
- for (prev = &dev->properties.properties; (prop = *prev);
- prev = &prop->next) {
- if (prop->propertyName == stuff->property) {
- *prev = prop->next;
- XIDestroyDeviceProperty(prop);
- break;
- }
- }
- }
- return Success;
- }
- int
- SProcXIListProperties(ClientPtr client)
- {
- REQUEST(xXIListPropertiesReq);
- REQUEST_SIZE_MATCH(xXIListPropertiesReq);
- swaps(&stuff->length);
- swaps(&stuff->deviceid);
- return (ProcXIListProperties(client));
- }
- int
- SProcXIChangeProperty(ClientPtr client)
- {
- REQUEST(xXIChangePropertyReq);
- REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
- swaps(&stuff->length);
- swaps(&stuff->deviceid);
- swapl(&stuff->property);
- swapl(&stuff->type);
- swapl(&stuff->num_items);
- return (ProcXIChangeProperty(client));
- }
- int
- SProcXIDeleteProperty(ClientPtr client)
- {
- REQUEST(xXIDeletePropertyReq);
- REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
- swaps(&stuff->length);
- swaps(&stuff->deviceid);
- swapl(&stuff->property);
- return (ProcXIDeleteProperty(client));
- }
- int
- SProcXIGetProperty(ClientPtr client)
- {
- REQUEST(xXIGetPropertyReq);
- REQUEST_SIZE_MATCH(xXIGetPropertyReq);
- swaps(&stuff->length);
- swaps(&stuff->deviceid);
- swapl(&stuff->property);
- swapl(&stuff->type);
- swapl(&stuff->offset);
- swapl(&stuff->len);
- return (ProcXIGetProperty(client));
- }
- void
- SRepXIListProperties(ClientPtr client, int size, xXIListPropertiesReply * rep)
- {
- swaps(&rep->sequenceNumber);
- swapl(&rep->length);
- swaps(&rep->num_properties);
- /* properties will be swapped later, see ProcXIListProperties */
- WriteToClient(client, size, rep);
- }
- void
- SRepXIGetProperty(ClientPtr client, int size, xXIGetPropertyReply * rep)
- {
- swaps(&rep->sequenceNumber);
- swapl(&rep->length);
- swapl(&rep->type);
- swapl(&rep->bytes_after);
- swapl(&rep->num_items);
- /* data will be swapped, see ProcXIGetProperty */
- WriteToClient(client, size, rep);
- }
|