Xi: pack the property stuff into a struct, make handlers a linked list.

We may need more than one handler to deal with a property (e.g. one in the
driver, one in the DIX), so get the handlers into a linked list and call them
one-by-one. This is of course slightly less entertaining than the hilarious
WRAP/UNWRAP game we play in other parts of the server.

XIRegisterPropertyHandler/XIUnregisterPropertyHandler are the interface
drivers/the DIX should use to attach themselves to the device.

XIDeleteAllDeviceProperties destroys everything, including the handlers.
This commit is contained in:
Peter Hutterer 2008-07-10 11:03:31 +09:30
parent 2039c6ea43
commit e4054e5cb3
4 changed files with 154 additions and 54 deletions

View File

@ -39,33 +39,57 @@
#include "xiproperty.h" #include "xiproperty.h"
void static long XIPropHandlerID = 1;
XIDeleteAllDeviceProperties (DeviceIntPtr device)
/* 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; XIPropertyHandlerPtr new_handler;
devicePropertyNotifyEvent event;
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; prev = curr;
curr = curr->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);
} }
if (!curr)
return;
if (!prev) /* first one */
dev->properties.handlers = curr->next;
else
prev->next = curr->next;
xfree(curr);
} }
static void static void
@ -112,13 +136,53 @@ XIDestroyDeviceProperty (XIPropertyPtr prop)
xfree(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 int
XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient) XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
{ {
XIPropertyPtr prop, *prev; XIPropertyPtr prop, *prev;
devicePropertyNotifyEvent event; 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) if (prop->propertyName == property)
break; break;
@ -234,13 +298,20 @@ XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
we're in a single thread after all we're in a single thread after all
*/ */
if (pending && prop->is_pending) if (pending && prop->is_pending)
dev->pendingProperties = TRUE; dev->properties.pendingProperties = TRUE;
if (pending && dev->SetProperty && if (pending && dev->properties.handlers)
!dev->SetProperty(dev, prop->propertyName, &new_value))
{ {
if (new_value.data) XIPropertyHandlerPtr handler = dev->properties.handlers;
xfree (new_value.data); while(handler)
return (BadValue); {
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) if (prop_value->data)
xfree (prop_value->data); xfree (prop_value->data);
@ -254,8 +325,8 @@ XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
if (add) if (add)
{ {
prop->next = dev->properties; prop->next = dev->properties.properties;
dev->properties = prop; dev->properties.properties = prop;
} }
@ -280,7 +351,7 @@ XIQueryDeviceProperty (DeviceIntPtr dev, Atom property)
{ {
XIPropertyPtr prop; XIPropertyPtr prop;
for (prop = dev->properties; prop; prop = prop->next) for (prop = dev->properties.properties; prop; prop = prop->next)
if (prop->propertyName == property) if (prop->propertyName == property)
return prop; return prop;
return NULL; return NULL;
@ -297,8 +368,15 @@ XIGetDeviceProperty (DeviceIntPtr dev, Atom property, Bool pending)
return &prop->pending; return &prop->pending;
else { else {
/* If we can, try to update the property value first */ /* If we can, try to update the property value first */
if (dev->GetProperty) if (dev->properties.handlers)
dev->GetProperty(dev, prop->propertyName); {
XIPropertyHandlerPtr handler = dev->properties.handlers;
while(handler)
{
handler->GetProperty(dev, prop->propertyName);
handler = handler->next;
}
}
return &prop->current; return &prop->current;
} }
} }
@ -353,8 +431,8 @@ XIConfigureDeviceProperty (DeviceIntPtr dev, Atom property,
prop->valid_values = new_values; prop->valid_values = new_values;
if (add) { if (add) {
prop->next = dev->properties; prop->next = dev->properties.properties;
dev->properties = prop; dev->properties.properties = prop;
} }
return Success; return Success;
@ -377,7 +455,7 @@ ProcXListDeviceProperties (ClientPtr client)
if (rc != Success) if (rc != Success)
return rc; return rc;
for (prop = dev->properties; prop; prop = prop->next) for (prop = dev->properties.properties; prop; prop = prop->next)
numProps++; numProps++;
if (numProps) if (numProps)
if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom)))) if(!(pAtoms = (Atom *)xalloc(numProps * sizeof(Atom))))
@ -395,7 +473,7 @@ ProcXListDeviceProperties (ClientPtr client)
swapl (&rep.length, n); swapl (&rep.length, n);
} }
temppAtoms = pAtoms; temppAtoms = pAtoms;
for (prop = dev->properties; prop; prop = prop->next) for (prop = dev->properties.properties; prop; prop = prop->next)
*temppAtoms++ = prop->propertyName; *temppAtoms++ = prop->propertyName;
WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep); WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
@ -589,7 +667,7 @@ ProcXGetDeviceProperty (ClientPtr client)
return(BadAtom); 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) if (prop->propertyName == stuff->property)
break; break;

View File

@ -175,10 +175,9 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
dev->last.numValuators = 0; dev->last.numValuators = 0;
/* device properties */ /* device properties */
dev->properties = NULL; dev->properties.properties = NULL;
dev->SetProperty = NULL; dev->properties.pendingProperties = FALSE;
dev->GetProperty = NULL; dev->properties.handlers = NULL;
dev->pendingProperties = FALSE;
/* security creation/labeling check /* security creation/labeling check
*/ */

View File

@ -239,4 +239,18 @@ extern int XIConfigureDeviceProperty(
INT32* /* values */ 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 */ #endif /* EXEVENTS_H */

View File

@ -358,14 +358,22 @@ typedef struct _XIProperty
pending; pending;
} XIPropertyRec; } XIPropertyRec;
typedef XIPropertyRec *XIPropertyPtr; typedef XIPropertyRec *XIPropertyPtr;
typedef XIPropertyValueRec *XIPropertyValuePtr; typedef XIPropertyValueRec *XIPropertyValuePtr;
typedef Bool (*XISetDevicePropertyProcPtr) (DeviceIntPtr dev,
Atom property, typedef struct _XIPropertyHandler
XIPropertyValuePtr prop); {
typedef Bool (*XIGetDevicePropertyProcPtr) (DeviceIntPtr dev, struct _XIPropertyHandler* next;
Atom property); long id;
Bool (*SetProperty) (DeviceIntPtr dev,
Atom property,
XIPropertyValuePtr prop);
Bool (*GetProperty) (DeviceIntPtr dev,
Atom property);
} XIPropertyHandler, *XIPropertyHandlerPtr;
/* states for devices */ /* states for devices */
@ -465,11 +473,12 @@ typedef struct _DeviceIntRec {
int numValuators; int numValuators;
} last; } last;
/* Input device property handling */ /* Input device property handling. */
XIPropertyPtr properties; struct {
Bool pendingProperties; XIPropertyPtr properties;
XISetDevicePropertyProcPtr SetProperty; Bool pendingProperties;
XIGetDevicePropertyProcPtr GetProperty; XIPropertyHandlerPtr handlers; /* NULL-terminated */
} properties;
} DeviceIntRec; } DeviceIntRec;
typedef struct { typedef struct {