diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c index 832a4582d..59bfe0f33 100644 --- a/Xi/xiproperty.c +++ b/Xi/xiproperty.c @@ -39,33 +39,57 @@ #include "xiproperty.h" -void -XIDeleteAllDeviceProperties (DeviceIntPtr device) +static long XIPropHandlerID = 1; + +/* 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, + Bool (*SetProperty) (DeviceIntPtr dev, + Atom property, + XIPropertyValuePtr prop), + Bool (*GetProperty) (DeviceIntPtr dev, + Atom property)) { - XIPropertyPtr prop, next; - devicePropertyNotifyEvent event; + XIPropertyHandlerPtr new_handler; - for (prop = device->properties; prop; prop = next) + new_handler = xcalloc(1, sizeof(XIPropertyHandler)); + if (!new_handler) + return 0; + + new_handler->id = XIPropHandlerID++; + new_handler->SetProperty = SetProperty; + new_handler->GetProperty = GetProperty; + 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) { - next = prop->next; - - event.type = GenericEvent; - event.extension = IReqCode; - event.evtype = XI_DevicePropertyNotify; - event.length = 0; - event.deviceid = device->id; - event.state = PropertyDelete; - event.atom = prop->propertyName; - event.time = currentTime.milliseconds; - SendEventToAllWindows(device, XI_DevicePropertyNotifyMask, - (xEvent*)&event, 1); - - if (prop->current.data) - xfree(prop->current.data); - if (prop->pending.data) - xfree(prop->pending.data); - xfree(prop); + prev = curr; + curr = curr->next; } + + if (!curr) + return; + + if (!prev) /* first one */ + dev->properties.handlers = curr->next; + else + prev->next = curr->next; + + xfree(curr); } static void @@ -112,13 +136,53 @@ XIDestroyDeviceProperty (XIPropertyPtr prop) xfree(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; + devicePropertyNotifyEvent event; + + for (prop = device->properties.properties; prop; prop = next) + { + next = prop->next; + + event.type = GenericEvent; + event.extension = IReqCode; + event.evtype = XI_DevicePropertyNotify; + event.length = 0; + event.deviceid = device->id; + event.state = PropertyDelete; + event.atom = prop->propertyName; + event.time = currentTime.milliseconds; + SendEventToAllWindows(device, XI_DevicePropertyNotifyMask, + (xEvent*)&event, 1); + + XIDestroyDeviceProperty(prop); + } + + /* Now free all handlers */ + curr_handler = device->properties.handlers; + while(curr_handler) + { + next_handler = curr_handler->next; + xfree(curr_handler); + curr_handler = next_handler; + } +} + + int XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient) { XIPropertyPtr prop, *prev; devicePropertyNotifyEvent event; - for (prev = &device->properties; (prop = *prev); prev = &(prop->next)) + for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next)) if (prop->propertyName == property) break; @@ -234,13 +298,20 @@ XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type, we're in a single thread after all */ if (pending && prop->is_pending) - dev->pendingProperties = TRUE; - if (pending && dev->SetProperty && - !dev->SetProperty(dev, prop->propertyName, &new_value)) + dev->properties.pendingProperties = TRUE; + if (pending && dev->properties.handlers) { - if (new_value.data) - xfree (new_value.data); - return (BadValue); + XIPropertyHandlerPtr handler = dev->properties.handlers; + while(handler) + { + if (!handler->SetProperty(dev, prop->propertyName, &new_value)) + { + if (new_value.data) + xfree (new_value.data); + return (BadValue); + } + handler = handler->next; + } } if (prop_value->data) xfree (prop_value->data); @@ -254,8 +325,8 @@ XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type, if (add) { - prop->next = dev->properties; - dev->properties = prop; + prop->next = dev->properties.properties; + dev->properties.properties = prop; } @@ -280,7 +351,7 @@ XIQueryDeviceProperty (DeviceIntPtr dev, Atom property) { XIPropertyPtr prop; - for (prop = dev->properties; prop; prop = prop->next) + for (prop = dev->properties.properties; prop; prop = prop->next) if (prop->propertyName == property) return prop; return NULL; @@ -297,8 +368,15 @@ XIGetDeviceProperty (DeviceIntPtr dev, Atom property, Bool pending) return &prop->pending; else { /* If we can, try to update the property value first */ - if (dev->GetProperty) - dev->GetProperty(dev, prop->propertyName); + if (dev->properties.handlers) + { + XIPropertyHandlerPtr handler = dev->properties.handlers; + while(handler) + { + handler->GetProperty(dev, prop->propertyName); + handler = handler->next; + } + } return &prop->current; } } @@ -353,8 +431,8 @@ XIConfigureDeviceProperty (DeviceIntPtr dev, Atom property, prop->valid_values = new_values; if (add) { - prop->next = dev->properties; - dev->properties = prop; + prop->next = dev->properties.properties; + dev->properties.properties = prop; } return Success; @@ -377,7 +455,7 @@ ProcXListDeviceProperties (ClientPtr client) if (rc != Success) return rc; - for (prop = dev->properties; prop; prop = prop->next) + for (prop = dev->properties.properties; prop; prop = prop->next) numProps++; if (numProps) if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) @@ -395,7 +473,7 @@ ProcXListDeviceProperties (ClientPtr client) swapl (&rep.length, n); } temppAtoms = pAtoms; - for (prop = dev->properties; prop; prop = prop->next) + for (prop = dev->properties.properties; prop; prop = prop->next) *temppAtoms++ = prop->propertyName; WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); @@ -589,7 +667,7 @@ ProcXGetDeviceProperty (ClientPtr client) return(BadAtom); } - for (prev = &dev->properties; (prop = *prev); prev = &prop->next) + for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next) if (prop->propertyName == stuff->property) break; diff --git a/dix/devices.c b/dix/devices.c index df53613c3..615142185 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -175,10 +175,9 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) dev->last.numValuators = 0; /* device properties */ - dev->properties = NULL; - dev->SetProperty = NULL; - dev->GetProperty = NULL; - dev->pendingProperties = FALSE; + dev->properties.properties = NULL; + dev->properties.pendingProperties = FALSE; + dev->properties.handlers = NULL; /* security creation/labeling check */ diff --git a/include/exevents.h b/include/exevents.h index 48dfccf02..b77a363e6 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -239,4 +239,18 @@ extern int XIConfigureDeviceProperty( INT32* /* values */ ); +extern long XIRegisterPropertyHandler( + DeviceIntPtr dev, + Bool (*SetProperty) (DeviceIntPtr dev, + Atom property, + XIPropertyValuePtr prop), + Bool (*GetProperty) (DeviceIntPtr dev, + Atom property) +); + +extern void XIUnRegisterPropertyHandler( + DeviceIntPtr dev, + long id +); + #endif /* EXEVENTS_H */ diff --git a/include/inputstr.h b/include/inputstr.h index 280774e99..f3211a972 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -358,14 +358,22 @@ typedef struct _XIProperty pending; } XIPropertyRec; + + typedef XIPropertyRec *XIPropertyPtr; typedef XIPropertyValueRec *XIPropertyValuePtr; -typedef Bool (*XISetDevicePropertyProcPtr) (DeviceIntPtr dev, - Atom property, - XIPropertyValuePtr prop); -typedef Bool (*XIGetDevicePropertyProcPtr) (DeviceIntPtr dev, - Atom property); + +typedef struct _XIPropertyHandler +{ + struct _XIPropertyHandler* next; + long id; + Bool (*SetProperty) (DeviceIntPtr dev, + Atom property, + XIPropertyValuePtr prop); + Bool (*GetProperty) (DeviceIntPtr dev, + Atom property); +} XIPropertyHandler, *XIPropertyHandlerPtr; /* states for devices */ @@ -465,11 +473,12 @@ typedef struct _DeviceIntRec { int numValuators; } last; - /* Input device property handling */ - XIPropertyPtr properties; - Bool pendingProperties; - XISetDevicePropertyProcPtr SetProperty; - XIGetDevicePropertyProcPtr GetProperty; + /* Input device property handling. */ + struct { + XIPropertyPtr properties; + Bool pendingProperties; + XIPropertyHandlerPtr handlers; /* NULL-terminated */ + } properties; } DeviceIntRec; typedef struct {