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"
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;

View File

@ -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
*/

View File

@ -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 */

View File

@ -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 {