From 38bba0c1b75b84e8bbdfa7975cf701a9414a3afd Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 20 Feb 2009 16:07:33 +1000 Subject: [PATCH] Xi: Change ChangeMasterDeviceClasses to new XI2 events. Split ChangeMasterDeviceClasses into an extra XISendDeviceChangedEvent that assembles the XI2 wire event for the DeviceChanged event. Re-use this when detaching the last SD. Not quite perfect yet, we still copy the device classes from the slave now rather than from the data we had when the event occured. But it's a start. (We can now unexport SizeDeviceInfo and CopySwapDevices, not needed anymore) Signed-off-by: Peter Hutterer --- Xi/exevents.c | 106 ++++++++++++++++++++++++++++++------------- Xi/extinit.c | 109 ++++++++++++++++++++++++++++++++++++--------- Xi/listdev.c | 33 +++++++------- Xi/listdev.h | 11 ----- Xi/querydev.c | 6 +-- Xi/querydev.h | 3 ++ dix/devices.c | 22 ++------- dix/eventconvert.c | 42 +++++++++-------- include/exevents.h | 4 ++ 9 files changed, 217 insertions(+), 119 deletions(-) diff --git a/Xi/exevents.c b/Xi/exevents.c index 885148734..fe11694b9 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -56,12 +56,13 @@ SOFTWARE. #include #endif +#include "inputstr.h" #include #include #include #include +#include #include -#include "inputstr.h" #include "windowstr.h" #include "miscstruct.h" #include "region.h" @@ -73,6 +74,7 @@ SOFTWARE. #include "scrnintstr.h" #include "listdev.h" /* for CopySwapXXXClass */ #include "xace.h" +#include "querydev.h" /* For List*Info */ #include #include "xkbsrv.h" @@ -654,15 +656,78 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) * @param device The slave device * @param dcce Pointer to the event struct. */ +void +XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce) +{ + xXIDeviceChangedEvent *dcce; + int len = sizeof(xXIDeviceChangedEvent); + int nkeys; + char *ptr; + + if (dce->buttons.num_buttons) + { + len += sizeof(xXIButtonInfo); + len += dce->buttons.num_buttons * sizeof(Atom); /* button names */ + } + if (dce->num_valuators) + len += sizeof(xXIValuatorInfo) * dce->num_valuators; + + nkeys = (dce->keys.max_keycode > 0) ? + dce->keys.max_keycode - dce->keys.min_keycode + 1 : 0; + if (nkeys > 0) + { + len += sizeof(xXIKeyInfo); + len += sizeof(CARD32) * nkeys; /* keycodes */ + } + + dcce = xalloc(len); + if (!dcce) + { + ErrorF("[Xi] BadAlloc in SendDeviceChangedEvent.\n"); + return; + } + + dcce->type = GenericEvent; + dcce->extension = IReqCode; + dcce->evtype = XI_DeviceChanged; + dcce->time = GetTimeInMillis(); + dcce->deviceid = master->id; + dcce->sourceid = device->id; + dcce->reason = SlaveSwitch; + dcce->num_classes = 0; + dcce->length = (len - sizeof(xEvent))/4; + + ptr = (char*)&dcce[1]; + if (dce->buttons.num_buttons) + { + dcce->num_classes++; + ptr += ListButtonInfo(device, (xXIButtonInfo*)ptr); + } + + if (nkeys) + { + dcce->num_classes++; + ptr += ListKeyInfo(device, (xXIKeyInfo*)ptr); + } + + if (dce->num_valuators) + { + int i; + + dcce->num_classes += dce->num_valuators; + for (i = 0; i < dce->num_valuators; i++) + ptr += ListValuatorInfo(device, (xXIValuatorInfo*)ptr, i); + } + + /* we don't actually swap if there's a NullClient, swapping is done + * later when event is delivered. */ + SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1); +} + static void -ChangeMasterDeviceClasses(DeviceIntPtr device, - DeviceChangedEvent *dce) +ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce) { DeviceIntPtr master = device->u.master; - deviceClassesChangedEvent *dcce; - char* classbuff; - int len = sizeof(xEvent); - int namelen = 0; /* dummy */ if (device->isMaster) return; @@ -670,34 +735,11 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, if (!master) /* if device was set floating between SIGIO and now */ return; - SizeDeviceInfo(device, &namelen, &len); - dcce = xalloc(len); - if (!dcce) - { - ErrorF("[Xi] BadAlloc in ChangeMasterDeviceClasses\n"); - return; - } - - dcce->type = GenericEvent; - dcce->extension = IReqCode; - dcce->evtype = XI_DeviceClassesChangedNotify; - dcce->time = GetTimeInMillis(); - dcce->new_slave = device->id; - dcce->deviceid = master->id; - dcce->num_classes = 0; - - dcce->length = (len - sizeof(xEvent))/4; - master->public.devicePrivate = device->public.devicePrivate; + /* FIXME: the classes may have changed since we generated the event. */ DeepCopyDeviceClasses(device, master); - - classbuff = (char*)&dcce[1]; - /* we don't actually swap if there's a NullClient, swapping is done - * later when event is delivered. */ - CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff); - SendEventToAllWindows(master, XI_DeviceClassesChangedMask, - (xEvent*)dcce, 1); + XISendDeviceChangedEvent(device, master, dce); } /** diff --git a/Xi/extinit.c b/Xi/extinit.c index 8452186a5..5e87451f5 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -627,49 +627,111 @@ SDeviceLeaveNotifyEvent (xXILeaveEvent *from, xXILeaveEvent *to) } static void -SDeviceClassesChangedEvent(deviceClassesChangedEvent* from, - deviceClassesChangedEvent* to) +SDeviceChangedEvent(xXIDeviceChangedEvent* from, xXIDeviceChangedEvent* to) { char n; int i, j; - xAnyClassPtr any; + xXIAnyInfo *any; *to = *from; memcpy(&to[1], &from[1], from->length * 4); swaps(&to->sequenceNumber, n); swapl(&to->length, n); + swaps(&to->evtype, n); + swaps(&to->deviceid, n); swapl(&to->time, n); - + swaps(&to->num_classes, n); + swaps(&to->sourceid, n); + /* now swap the actual classes */ - any = (xAnyClassPtr)&to[1]; + any = (xXIAnyInfo*)&to[1]; for (i = 0; i < to->num_classes; i++) { - switch(any->class) + swaps(&any->type, n); + swaps(&any->length, n); + switch(any->type) { case KeyClass: - swaps(&((xKeyInfoPtr)any)->num_keys, n); + { + xXIKeyInfo *ki = (xXIKeyInfo*)any; + uint32_t *key = (uint32_t*)&ki[1]; + for (j = 0; j < ki->num_keycodes; j++, key++) + swapl(key, n); + swaps(&ki->num_keycodes, n); + } break; case ButtonClass: - swaps(&((xButtonInfoPtr)any)->num_buttons, n); + { + xXIButtonInfo *bi = (xXIButtonInfo*)any; + for (j = 0; j < bi->num_buttons; j++) + swapl(&bi[1 + j], n); + swaps(&bi->num_buttons, n); + } break; case ValuatorClass: { - xValuatorInfoPtr v = (xValuatorInfoPtr)any; - xAxisInfoPtr a = (xAxisInfoPtr)&v[1]; - - swapl(&v->motion_buffer_size, n); - for (j = 0; j < v->num_axes; j++) - { - swapl(&a->min_value, n); - swapl(&a->max_value, n); - swapl(&a->resolution, n); - a++; - } + xXIValuatorInfo* ai = (xXIValuatorInfo*)any; + swapl(&ai->name, n); + swapl(&ai->min.integral, n); + swapl(&ai->min.frac, n); + swapl(&ai->max.integral, n); + swapl(&ai->max.frac, n); + swapl(&ai->resolution, n); + swaps(&ai->number, n); } break; } - any = (xAnyClassPtr)((char*)any + any->length); + any = (xXIAnyInfo*)((char*)any + any->length * 4); + } +} + +static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to) +{ + int i; + char n; + char *ptr; + char *vmask; + + *to = *from; + memcpy(&to[1], &from[1], from->length * 4); + + swaps(&to->sequenceNumber, n); + swapl(&to->length, n); + swaps(&to->evtype, n); + swaps(&to->deviceid, n); + swapl(&to->time, n); + swapl(&to->root, n); + swapl(&to->event, n); + swapl(&to->child, n); + swapl(&to->root_x.integral, n); + swapl(&to->root_x.frac, n); + swapl(&to->root_y.integral, n); + swapl(&to->root_y.frac, n); + swapl(&to->event_x.integral, n); + swapl(&to->event_x.frac, n); + swapl(&to->event_y.integral, n); + swapl(&to->event_y.frac, n); + swaps(&to->buttons_len, n); + swaps(&to->valuators_len, n); + swaps(&to->sourceid, n); + swapl(&to->mods.base_mods, n); + swapl(&to->mods.latched_mods, n); + swapl(&to->mods.locked_mods, n); + + ptr = (char*)(&to[1]); + ptr += from->buttons_len; + vmask = ptr; /* valuator mask */ + ptr += from->valuators_len; + for (i = 0; i < from->valuators_len * 32; i++) + { + if (BitIsOn(vmask, i)) + { + swapl(((uint32_t*)ptr), n); + ptr += 4; + swapl(((uint32_t*)ptr), n); + ptr += 4; + } } } @@ -683,6 +745,13 @@ XI2EventSwap(xGenericEvent *from, xGenericEvent *to) case XI_Leave: SDeviceLeaveNotifyEvent((xXILeaveEvent*)from, (xXILeaveEvent*)to); break; + case XI_DeviceChanged: + SDeviceChangedEvent((xXIDeviceChangedEvent*)from, + (xXIDeviceChangedEvent*)to); + break; + default: + SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to); + break; } } diff --git a/Xi/listdev.c b/Xi/listdev.c index 925d0ecbf..e7d0a9d68 100644 --- a/Xi/listdev.c +++ b/Xi/listdev.c @@ -93,7 +93,7 @@ SProcXListInputDevices(ClientPtr client) * */ -void +static void SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size) { int chunks; @@ -273,22 +273,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) return (i); } -/*********************************************************************** - * - * This procedure lists information to be returned for an input device. - * - */ - static void -ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev, - char **devbuf, char **classbuf, char **namebuf) -{ - CopyDeviceName(namebuf, d->name); - CopySwapDevice(client, d, 0, devbuf); - CopySwapClasses(client, d, &dev->num_classes, classbuf); -} - -void CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes, char** classbuf) { @@ -306,6 +291,22 @@ CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes, } } +/*********************************************************************** + * + * This procedure lists information to be returned for an input device. + * + */ + +static void +ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev, + char **devbuf, char **classbuf, char **namebuf) +{ + CopyDeviceName(namebuf, d->name); + CopySwapDevice(client, d, 0, devbuf); + CopySwapClasses(client, d, &dev->num_classes, classbuf); +} + + /*********************************************************************** * * This procedure lists the input devices available to the server. diff --git a/Xi/listdev.h b/Xi/listdev.h index 39ea2d635..b0d2dd5e2 100644 --- a/Xi/listdev.h +++ b/Xi/listdev.h @@ -43,15 +43,4 @@ void SRepXListInputDevices(ClientPtr /* client */ , xListInputDevicesReply * /* rep */ ); -void -CopySwapClasses(ClientPtr /* client */, - DeviceIntPtr /* dev */, - CARD8* /* num_classes */, - char** /* classbuf */); - -void -SizeDeviceInfo(DeviceIntPtr /* dev */, - int* /* namesize */, - int* /* size */); - #endif /* LISTDEV_H */ diff --git a/Xi/querydev.c b/Xi/querydev.c index 0d90fa926..c7ee0e162 100644 --- a/Xi/querydev.c +++ b/Xi/querydev.c @@ -219,7 +219,7 @@ SizeDeviceClasses(DeviceIntPtr dev) * Write button information into info. * @return Number of bytes written into info. */ -static int +int ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info) { info->type = ButtonClass; @@ -250,7 +250,7 @@ SwapButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info) * Write key information into info. * @return Number of bytes written into info. */ -static int +int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info) { int i; @@ -288,7 +288,7 @@ SwapKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info) * * @return The number of bytes written into info. */ -static int +int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber) { ValuatorClassPtr v = dev->valuator; diff --git a/Xi/querydev.h b/Xi/querydev.h index 92ab2bd77..34e87bdde 100644 --- a/Xi/querydev.h +++ b/Xi/querydev.h @@ -39,4 +39,7 @@ void SRepXIQueryDevice(ClientPtr client, int size, xXIQueryDeviceReply *rep); int SizeDeviceClasses(DeviceIntPtr dev); int ListDeviceClasses(DeviceIntPtr dev, char* any, uint16_t* nclasses); int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment); +int ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info); +int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info); +int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber); #endif /* QUERYDEV_H */ diff --git a/dix/devices.c b/dix/devices.c index ca0da070a..0795d30ea 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -2217,28 +2217,14 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) if (!it) /* no dev is paired with old master */ { - /* XXX: reset to defaults */ EventListPtr event = NULL; - char* classbuf; - int namelen = 0; /* dummy */ - int len = sizeof(xEvent); - deviceClassesChangedEvent *dcce; + /* XXX: reset master back to defaults */ event = InitEventList(1); - SizeDeviceInfo(oldmaster, &namelen, &len); - SetMinimumEventSize(event, 1, len); - - /* Send event to clients */ + SetMinimumEventSize(event, 1, sizeof(DeviceChangedEvent)); CreateClassesChangedEvent(event, oldmaster, oldmaster); - dcce = (deviceClassesChangedEvent*)event->event; - dcce->deviceid = oldmaster->id; - dcce->num_classes = 0; - dcce->length = (len - sizeof(xEvent))/4; - classbuf = (char*)&event->event[1]; - CopySwapClasses(NullClient, oldmaster, - &dcce->num_classes, &classbuf); - SendEventToAllWindows(oldmaster, XI_DeviceClassesChangedMask, - event->event, 1); + XISendDeviceChangedEvent(oldmaster, oldmaster, + (DeviceChangedEvent*)event->event); FreeEventList(event, 1); } } diff --git a/dix/eventconvert.c b/dix/eventconvert.c index c3328d63f..553d95330 100644 --- a/dix/eventconvert.c +++ b/dix/eventconvert.c @@ -45,13 +45,12 @@ #include "events.h" #include "exglobals.h" #include "eventconvert.h" -#include "listdev.h" +#include "querydev.h" static int countValuators(DeviceEvent *ev, int *first); static int getValuatorEvents(DeviceEvent *ev, deviceValuator *xv); static int eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count); -static int eventToClassesChanged(DeviceChangedEvent *ev, xEvent **dcce, - int *count); +static int eventToClassesChanged(DeviceChangedEvent *ev, xEvent **dcce); static int eventToDeviceEvent(DeviceEvent *ev, xEvent **xi); /** * Convert the given event to the respective core event. @@ -127,8 +126,9 @@ EventToXI(InternalEvent *ev, xEvent **xi, int *count) case ET_ProximityOut: return eventToKeyButtonPointer((DeviceEvent*)ev, xi, count); case ET_DeviceChanged: - return eventToClassesChanged((DeviceChangedEvent*)ev, xi, count); - break; + *count = 0; + *xi = NULL; + return Success; } ErrorF("[dix] EventToXI: Not implemented for %d \n", ev->u.any.type); @@ -162,6 +162,9 @@ EventToXI2(InternalEvent *ev, xEvent **xi) case ET_ProximityOut: *xi = NULL; return Success; + case ET_DeviceChanged: + return eventToClassesChanged((DeviceChangedEvent*)ev, xi); + } ErrorF("[dix] EventToXI2: Not implemented for %d \n", ev->u.any.type); @@ -290,14 +293,12 @@ getValuatorEvents(DeviceEvent *ev, deviceValuator *xv) } static int -eventToClassesChanged(DeviceChangedEvent *ev, xEvent **xi, int *count) +eventToClassesChanged(DeviceChangedEvent *ev, xEvent **xi) { int len = sizeof(xEvent); - int namelen = 0; /* dummy */ DeviceIntPtr slave; int rc; - deviceClassesChangedEvent *dcce; - + xXIDeviceChangedEvent *dce; rc = dixLookupDevice(&slave, ev->new_slaveid, serverClient, DixReadAccess); @@ -305,21 +306,25 @@ eventToClassesChanged(DeviceChangedEvent *ev, xEvent **xi, int *count) if (rc != Success) return rc; - SizeDeviceInfo(slave, &namelen, &len); + len += SizeDeviceClasses(slave); *xi = xcalloc(1, len); if (!(*xi)) return BadAlloc; - dcce = (deviceClassesChangedEvent*)(*xi); - dcce->type = GenericEvent; - dcce->extension = IReqCode; - dcce->evtype = XI_DeviceClassesChangedNotify; - dcce->time = GetTimeInMillis(); - dcce->new_slave = slave->id; - dcce->length = (len - sizeof(xEvent))/4; + dce = (xXIDeviceChangedEvent*)(*xi); + dce->type = GenericEvent; + dce->extension = IReqCode; + dce->evtype = XI_DeviceChanged; + dce->time = GetTimeInMillis(); + dce->sourceid = slave->id; + dce->reason = SlaveSwitch; + dce->length = (len - sizeof(xEvent))/4; + + /* FIXME: this should come from the event, not from the device. See + * CreateClassesChangedEvent */ + ListDeviceClasses(slave, (char*)&dce[1], &dce->num_classes); - *count = 1; return Success; } @@ -350,7 +355,6 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi) char *ptr; int32_t *axisval; - /* FIXME: this should just send the buttons we have, not MAX_BUTTONs. Same * with MAX_VALUATORS below */ /* btlen is in 4 byte units */ diff --git a/include/exevents.h b/include/exevents.h index d09ad3c5b..4ee7084ef 100644 --- a/include/exevents.h +++ b/include/exevents.h @@ -250,4 +250,8 @@ extern _X_EXPORT int XIPropToFloat( * would it merely be irrelevant and confusing? */ extern _X_EXPORT int XIShouldNotify(ClientPtr client, DeviceIntPtr dev); +extern void +XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, + DeviceChangedEvent *dce); + #endif /* EXEVENTS_H */