diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-11-09 23:10:24 +1030 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2007-11-09 23:10:24 +1030 |
commit | 7a81bafc9bc7048560b17483e6addf58469a05d0 (patch) | |
tree | c6babb6619ccd1cb977edfe0fbb73cc3b891b524 | |
parent | c0a05805783ee3d38fbcc0fb45f4aa3c511785f0 (diff) |
Xi, dix: Add ability to change MD classes + send event when doing so.
Each time a different slave device sends through a master, an
DeviceClassesChangedEvent is enqueued. When this event is processed, all
classes of the matching master device are changed, and the event is sent to
the clients.
Next time the master is queried, it thus shows the evclasses of the last slave
device. The original classes are stored in the devPrivates.
TODO: if all slave devices are removed, the master's original classes need to
be restored.
-rw-r--r-- | Xi/exevents.c | 57 | ||||
-rw-r--r-- | Xi/extinit.c | 51 | ||||
-rw-r--r-- | Xi/listdev.c | 15 | ||||
-rw-r--r-- | Xi/listdev.h | 14 | ||||
-rw-r--r-- | dix/devices.c | 122 | ||||
-rw-r--r-- | dix/getevents.c | 93 | ||||
-rw-r--r-- | mi/mieq.c | 7 |
7 files changed, 293 insertions, 66 deletions
diff --git a/Xi/exevents.c b/Xi/exevents.c index 4c57fd017..617aef7b4 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -73,6 +73,7 @@ SOFTWARE. #include "dixevents.h" /* DeliverFocusedEvent */ #include "dixgrabs.h" /* CreateGrab() */ #include "scrnintstr.h" +#include "listdev.h" /* for CopySwapXXXClass */ #ifdef XKB #include "xkbsrv.h" @@ -127,6 +128,62 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) xEvent core; int coretype = 0; + /* This event is always the first we get, before the actual events with + * the data. However, the way how the DDX is set up, "device" will + * actually be the slave device that caused the event. + */ + if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify)) + { + deviceClassesChangedEvent* dcce = (deviceClassesChangedEvent*)xE; + DeviceIntPtr master = device->u.master; + char* classbuff; + + if (device->isMaster) + return; + + if (!master) /* if device was set floating between SIGIO and now */ + return; + + dcce->deviceid = master->id; + dcce->num_classes = 0; + + master->key = device->key; + master->valuator = device->valuator; + master->button = device->button; + master->focus = device->focus; + master->proximity = device->proximity; + master->absolute = device->absolute; + master->kbdfeed = device->kbdfeed; + master->ptrfeed = device->ptrfeed; + master->intfeed = device->intfeed; + master->stringfeed = device->stringfeed; + master->bell = device->bell; + master->leds = device->leds; + + /* event is already correct size, see comment in GetPointerEvents */ + classbuff = (char*)&xE[1]; + if (master->key) + { + /* we don't actually swap here, swapping is done later */ + CopySwapKeyClass(NullClient, master->key, &classbuff); + dcce->num_classes++; + } + if (master->button) + { + CopySwapButtonClass(NullClient, master->button, &classbuff); + dcce->num_classes++; + } + if (master->valuator) + { + CopySwapValuatorClass(NullClient, master->valuator, &classbuff); + dcce->num_classes++; + } + + SendEventToAllWindows(master, XI_DeviceClassesChangedMask, + xE, 1); + return; + } + coretype = XItoCoreType(xE->u.u.type); if (device->isMaster && device->coreEvents && coretype) sendCore = TRUE; diff --git a/Xi/extinit.c b/Xi/extinit.c index 0ecb421f0..017b6935a 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -703,6 +703,53 @@ SRawDeviceEvent(rawDeviceEvent* from, rawDeviceEvent *to) swapl(valptr, n); } +static void +SDeviceClassesChangedEvent(deviceClassesChangedEvent* from, + deviceClassesChangedEvent* to) +{ + char n; + int i, j; + xAnyClassPtr any; + + *to = *from; + memcpy(&to[1], &from[1], from->length * 4); + + swaps(&to->sequenceNumber, n); + swapl(&to->length, n); + swapl(&to->time, n); + + /* now swap the actual classes */ + any = (xAnyClassPtr)&to[1]; + for (i = 0; i < to->num_classes; i++) + { + switch(any->class) + { + case KeyClass: + swaps(&((xKeyInfoPtr)any)->num_keys, n); + break; + case ButtonClass: + swaps(&((xButtonInfoPtr)any)->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++; + } + } + break; + } + any = (xAnyClassPtr)((char*)any + any->length); + } +} + /************************************************************************** * * Allow the specified event to have its propagation suppressed. @@ -1153,6 +1200,10 @@ XIGEEventSwap(xGenericEvent* from, xGenericEvent* to) case XI_RawDeviceEvent: SRawDeviceEvent((rawDeviceEvent*)from, (rawDeviceEvent*)to); break; + case XI_DeviceClassesChangedNotify: + SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from, + (deviceClassesChangedEvent*)to); + break; } } diff --git a/Xi/listdev.c b/Xi/listdev.c index 8753b292c..962998efe 100644 --- a/Xi/listdev.c +++ b/Xi/listdev.c @@ -68,7 +68,6 @@ SOFTWARE. #include "listdev.h" -#define VPC 20 /* Max # valuators per chunk */ /*********************************************************************** * @@ -143,7 +142,7 @@ CopyDeviceName(char **namebuf, char *name) * */ -static void +void CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf) { char n; @@ -153,7 +152,7 @@ CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf) b2->class = ButtonClass; b2->length = sizeof(xButtonInfo); b2->num_buttons = b->numButtons; - if (client->swapped) { + if (client && client->swapped) { swaps(&b2->num_buttons, n); /* macro - braces are required */ } *buf += sizeof(xButtonInfo); @@ -202,7 +201,7 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, * */ -static void +void CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) { char n; @@ -214,7 +213,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) k2->min_keycode = k->curKeySyms.minKeyCode; k2->max_keycode = k->curKeySyms.maxKeyCode; k2->num_keys = k2->max_keycode - k2->min_keycode + 1; - if (client->swapped) { + if (client && client->swapped) { swaps(&k2->num_keys, n); } *buf += sizeof(xKeyInfo); @@ -232,7 +231,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) * */ -static int +int CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) { int i, j, axes, t_axes; @@ -252,7 +251,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) v2->num_axes = t_axes; v2->mode = v->mode & DeviceMode; v2->motion_buffer_size = v->numMotionEvents; - if (client->swapped) { + if (client && client->swapped) { swapl(&v2->motion_buffer_size, n); } *buf += sizeof(xValuatorInfo); @@ -262,7 +261,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) a2->min_value = a->min_value; a2->max_value = a->max_value; a2->resolution = a->resolution; - if (client->swapped) { + if (client && client->swapped) { swapl(&a2->min_value, n); swapl(&a2->max_value, n); swapl(&a2->resolution, n); diff --git a/Xi/listdev.h b/Xi/listdev.h index db376decf..afdcd6992 100644 --- a/Xi/listdev.h +++ b/Xi/listdev.h @@ -30,6 +30,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef LISTDEV_H #define LISTDEV_H 1 +#define VPC 20 /* Max # valuators per chunk */ + int SProcXListInputDevices(ClientPtr /* client */ ); @@ -41,4 +43,16 @@ void SRepXListInputDevices(ClientPtr /* client */ , xListInputDevicesReply * /* rep */ ); +void +CopySwapKeyClass(ClientPtr /* client */, + KeyClassPtr /* k */, + char** /* buf */); +void +CopySwapButtonClass(ClientPtr /* client */, + ButtonClassPtr /* b */, + char** /* buf */); +int +CopySwapValuatorClass(ClientPtr /* client */, + ValuatorClassPtr /* v */, + char** /* buf */); #endif /* LISTDEV_H */ diff --git a/dix/devices.c b/dix/devices.c index c9831ea92..b42337820 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -84,8 +84,25 @@ SOFTWARE. * This file handles input device-related stuff. */ +typedef struct { + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + AbsoluteClassPtr absolute; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; +} ClassesRec, *ClassesPtr; + + int CoreDevicePrivatesIndex = 0; static int CoreDevicePrivatesGeneration = -1; +int MasterDevClassesPrivIdx = -1; /* The client that is allowed to change pointer-keyboard pairings. */ static ClientPtr pairingClient = NULL; @@ -385,9 +402,16 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) #ifdef XKB XkbComponentNamesRec names; #endif + ClassesPtr classes; switch (what) { case DEVICE_INIT: + if (MasterDevClassesPrivIdx == -1) + MasterDevClassesPrivIdx = AllocateDevicePrivateIndex(); + + if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) || + !(classes = xcalloc(1, sizeof(ClassesRec)))) + keySyms.minKeyCode = 8; keySyms.maxKeyCode = 255; keySyms.mapWidth = 4; @@ -425,6 +449,19 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) xfree(keySyms.map); xfree(modMap); + classes->key = pDev->key; + classes->valuator = pDev->valuator; + classes->button = pDev->button; + classes->focus = pDev->focus; + classes->proximity = pDev->proximity; + classes->absolute = pDev->absolute; + classes->kbdfeed = pDev->kbdfeed; + classes->ptrfeed = pDev->ptrfeed; + classes->intfeed = pDev->intfeed; + classes->stringfeed = pDev->stringfeed; + classes->bell = pDev->bell; + classes->leds = pDev->leds; + pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes; break; case DEVICE_CLOSE: @@ -439,15 +476,27 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) /** * Device control function for the Virtual Core Pointer. + * + * Aside from initialisation, it backs up the original device classes into the + * devicePrivates. This only needs to be done for master devices. */ static int CorePointerProc(DeviceIntPtr pDev, int what) { BYTE map[33]; int i = 0; + ClassesPtr classes; + switch (what) { case DEVICE_INIT: + if (MasterDevClassesPrivIdx == -1) + MasterDevClassesPrivIdx = AllocateDevicePrivateIndex(); + + if (!AllocateDevicePrivate(pDev, MasterDevClassesPrivIdx) || + !(classes = xcalloc(1, sizeof(ClassesRec)))) + return BadAlloc; + for (i = 1; i <= 32; i++) map[i] = i; InitPointerDeviceStruct((DevicePtr)pDev, map, 32, @@ -457,6 +506,21 @@ CorePointerProc(DeviceIntPtr pDev, int what) pDev->valuator->lastx = pDev->valuator->axisVal[0]; pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; pDev->valuator->lasty = pDev->valuator->axisVal[1]; + + classes->key = pDev->key; + classes->valuator = pDev->valuator; + classes->button = pDev->button; + classes->focus = pDev->focus; + classes->proximity = pDev->proximity; + classes->absolute = pDev->absolute; + classes->kbdfeed = pDev->kbdfeed; + classes->ptrfeed = pDev->ptrfeed; + classes->intfeed = pDev->intfeed; + classes->stringfeed = pDev->stringfeed; + classes->bell = pDev->bell; + classes->leds = pDev->leds; + + pDev->devPrivates[MasterDevClassesPrivIdx].ptr = classes; break; case DEVICE_CLOSE: @@ -574,6 +638,7 @@ CloseDevice(DeviceIntPtr dev) BellFeedbackPtr b, bnext; LedFeedbackPtr l, lnext; ScreenPtr screen = screenInfo.screens[0]; + ClassesPtr classes; int j; if (!dev) @@ -588,41 +653,46 @@ CloseDevice(DeviceIntPtr dev) xfree(dev->name); - if (dev->key) { + if (dev->isMaster) + classes = (ClassesPtr)dev->devPrivates[MasterDevClassesPrivIdx].ptr; + else + classes = (ClassesPtr)&dev->key; + + if (classes->key) { #ifdef XKB - if (dev->key->xkbInfo) - XkbFreeInfo(dev->key->xkbInfo); + if (classes->key->xkbInfo) + XkbFreeInfo(classes->key->xkbInfo); #endif - xfree(dev->key->curKeySyms.map); - xfree(dev->key->modifierKeyMap); - xfree(dev->key); + xfree(classes->key->curKeySyms.map); + xfree(classes->key->modifierKeyMap); + xfree(classes->key); } - if (dev->valuator) { + if (classes->valuator) { /* Counterpart to 'biggest hack ever' in init. */ - if (dev->valuator->motion && - dev->valuator->GetMotionProc == GetMotionHistory) - xfree(dev->valuator->motion); - xfree(dev->valuator); + if (classes->valuator->motion && + classes->valuator->GetMotionProc == GetMotionHistory) + xfree(classes->valuator->motion); + xfree(classes->valuator); } - if (dev->button) { + if (classes->button) { #ifdef XKB - if (dev->button->xkb_acts) - xfree(dev->button->xkb_acts); + if (classes->button->xkb_acts) + xfree(classes->button->xkb_acts); #endif - xfree(dev->button); + xfree(classes->button); } - if (dev->focus) { - xfree(dev->focus->trace); - xfree(dev->focus); + if (classes->focus) { + xfree(classes->focus->trace); + xfree(classes->focus); } - if (dev->proximity) - xfree(dev->proximity); + if (classes->proximity) + xfree(classes->proximity); - for (k = dev->kbdfeed; k; k = knext) { + for (k = classes->kbdfeed; k; k = knext) { knext = k->next; #ifdef XKB if (k->xkb_sli) @@ -631,29 +701,29 @@ CloseDevice(DeviceIntPtr dev) xfree(k); } - for (p = dev->ptrfeed; p; p = pnext) { + for (p = classes->ptrfeed; p; p = pnext) { pnext = p->next; xfree(p); } - for (i = dev->intfeed; i; i = inext) { + for (i = classes->intfeed; i; i = inext) { inext = i->next; xfree(i); } - for (s = dev->stringfeed; s; s = snext) { + for (s = classes->stringfeed; s; s = snext) { snext = s->next; xfree(s->ctrl.symbols_supported); xfree(s->ctrl.symbols_displayed); xfree(s); } - for (b = dev->bell; b; b = bnext) { + for (b = classes->bell; b; b = bnext) { bnext = b->next; xfree(b); } - for (l = dev->leds; l; l = lnext) { + for (l = classes->leds; l; l = lnext) { lnext = l->next; #ifdef XKB if (l->xkb_sli) diff --git a/dix/getevents.c b/dix/getevents.c index a23eabea2..425b60234 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -67,6 +67,7 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #include "exevents.h" #include "exglobals.h" #include "extnsionst.h" +#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ /* Maximum number of valuators, divided by six, rounded up, to get number * of events. */ @@ -110,6 +111,52 @@ key_autorepeats(DeviceIntPtr pDev, int key_code) (1 << (key_code & 7))); } +static void +CreateClassesChangedEvent(EventList* event, + DeviceIntPtr master, + DeviceIntPtr slave) +{ + deviceClassesChangedEvent *dcce; + int len = sizeof(xEvent); + CARD32 ms = GetTimeInMillis(); + + /* XXX: ok, this is a bit weird. We need to alloc enough size for the + * event so it can be filled in in POE lateron. Reason being that if + * we realloc the event in POE we can get SIGABRT when we try to free + * or realloc the original pointer. + * We can only do it here as we don't have the EventList in the event + * processing any more. + * + * Code is basically same as in Xi/listdev.c + */ + if (slave->key) + len += sizeof(xKeyInfo); + if (slave->button) + len += sizeof(xButtonInfo); + if (slave->valuator) + { + int chunks = ((int)slave->valuator->numAxes + 19) / VPC; + len += (chunks * sizeof(xValuatorInfo) + + slave->valuator->numAxes * sizeof(xAxisInfo)); + } + if (event->evlen < len) + { + event->event = realloc(event->event, len); + if (!event->event) + FatalError("[dix] Cannot allocate memory for " + "DeviceClassesChangedEvent.\n"); + event->evlen = len; + } + + dcce = (deviceClassesChangedEvent*)event->event; + dcce->type = GenericEvent; + dcce->extension = IReqCode; + dcce->evtype = XI_DeviceClassesChangedNotify; + dcce->time = ms; + dcce->new_slave = slave->id; + dcce->length = (len - sizeof(xEvent))/4; +} + /** * Allocate the motion history buffer. */ @@ -415,6 +462,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, KeySym *map = pDev->key->curKeySyms.map; KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth]; deviceKeyButtonPointer *kbp = NULL; + DeviceIntPtr master; if (!events) return 0; @@ -432,6 +480,18 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, if (key_code < 8 || key_code > 255) return 0; + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + CreateClassesChangedEvent(events, master, pDev); + + pDev->valuator->lastx = master->valuator->lastx; + pDev->valuator->lasty = master->valuator->lasty; + master->u.lastSlave = pDev; + numEvents++; + events++; + } + if (num_valuators) { if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) num_valuators = MAX_VALUATOR_EVENTS; @@ -606,37 +666,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, master = pDev->u.master; if (master && master->u.lastSlave != pDev) { -#if 0 - /* XXX: we should enqueue the state changed event here */ - devStateEvent *state; - num_events++; - state = events->event; - - state->type = GenericEvent; - state->extension = IReqCode; - state->evtype = XI_DeviceStateChangedNotify; - state->deviceid = master->deviceid; - state->new_slave = pDev->id; - state->time = ms; - events++; - -#endif + CreateClassesChangedEvent(events, master, pDev); - /* now we need to update our device to the master's device - welcome - * to hell. - * We need to match each device's capabilities to the previous - * capabilities as used by the master. Valuator[N] of master has to - * be written into valuator[N] of pDev. For all relative valuators. - * Otherwise we get jumpy valuators. - * - * However, this if iffy, if pDev->num_valuators != - * master->num_valuators. What do we do with the others? - * - * XXX: just do lastx/y for now. - */ pDev->valuator->lastx = master->valuator->lastx; pDev->valuator->lasty = master->valuator->lasty; master->u.lastSlave = pDev; + + num_events++; + events++; } /* Do we need to send a DeviceValuator event? */ @@ -652,8 +689,6 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes) return 0; - - /* fill up the raw event, after checking that it is large enough to * accommodate all valuators. */ @@ -243,12 +243,13 @@ ChangeDeviceID(DeviceIntPtr dev, xEvent* event) else if (type == GenericEvent) { /* FIXME: need to put something into XGE to make this saner */ - xGenericEvent* generic = (xGenericEvent*)event; - if (generic->extension == IReqCode - && generic->evtype == XI_RawDeviceEvent) + if (GEIsType(event, IReqCode, XI_RawDeviceEvent)) { rawDeviceEvent* raw = (rawDeviceEvent*)event; raw->deviceid = dev->id; + } else if (GEIsType(event, IReqCode, XI_DeviceClassesChangedNotify)) + { + // do nothing or drink a beer. your choice. } else ErrorF("[mi] Unknown generic event, cannot change id.\n"); } else |