diff --git a/Xext/xtest.c b/Xext/xtest.c index ab882311a..d21eedcde 100644 --- a/Xext/xtest.c +++ b/Xext/xtest.c @@ -54,6 +54,7 @@ extern int DeviceValuator; extern int DeviceMotionNotify; +extern DevPrivateKey XTstDevicePrivateKey; #ifdef PANORAMIX #include "panoramiX.h" @@ -160,6 +161,7 @@ ProcXTestFakeInput(ClientPtr client) int i; int base = 0; int flags = 0; + DeviceIntPtr xtstdevice; nev = (stuff->length << 2) - sizeof(xReq); if ((nev % sizeof(xEvent)) || !nev) @@ -268,6 +270,8 @@ ProcXTestFakeInput(ClientPtr client) } else { + DeviceIntPtr it; + if (nev != 1) return BadLength; switch (type) @@ -294,8 +298,14 @@ ProcXTestFakeInput(ClientPtr client) return BadValue; } - if (dev->u.lastSlave) - dev = dev->u.lastSlave; + /* When faking core events through XTest, we always fake through the + * virtual test device. + */ + for(it = inputInfo.devices; it ; it = it->next ) + if( !it->isMaster && it->u.master == dev && + dixLookupPrivate(&it->devPrivates, XTstDevicePrivateKey )) + break; + dev= it; } /* If the event has a time set, wait for it to pass */ @@ -403,6 +413,7 @@ ProcXTestFakeInput(ClientPtr client) for (i = 0; i < nevents; i++) mieqProcessDeviceEvent(dev, (events+i)->event, NULL); + miPointerUpdateSprite(dev); return client->noClientException; } diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c index 5c8b36906..6c70bd9aa 100644 --- a/Xi/chdevhier.c +++ b/Xi/chdevhier.c @@ -52,6 +52,8 @@ #include "chdevhier.h" +extern DevPrivateKey XTstDevicePrivateKey; + /*********************************************************************** * @@ -74,7 +76,7 @@ int SProcXChangeDeviceHierarchy(ClientPtr client) int ProcXChangeDeviceHierarchy(ClientPtr client) { - DeviceIntPtr ptr, keybd; + DeviceIntPtr ptr, keybd, xtstptr, xtstkeybd; DeviceIntRec dummyDev; xAnyHierarchyChangeInfo *any; int required_len = sizeof(xChangeDeviceHierarchyReq); @@ -118,14 +120,33 @@ ProcXChangeDeviceHierarchy(ClientPtr client) if (!c->sendCore) ptr->coreEvents = keybd->coreEvents = FALSE; + /* Allocate virtual slave devices for xtest events */ + rc = AllocXtstDevice(client, name, &xtstptr, &xtstkeybd); + if (rc != Success) + { + + xfree(name); + goto unwind; + } + ActivateDevice(ptr); ActivateDevice(keybd); + ActivateDevice(xtstptr); + ActivateDevice(xtstkeybd); if (c->enable) { EnableDevice(ptr); EnableDevice(keybd); + EnableDevice(xtstptr); + EnableDevice(xtstkeybd); } + + /* Attach the XTest virtual devices to the newly + created master device */ + AttachDevice(NULL, xtstptr, ptr); + AttachDevice(NULL, xtstkeybd, keybd); + xfree(name); nchanges++; } @@ -133,6 +154,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) case CH_RemoveMasterDevice: { xRemoveMasterInfo* r = (xRemoveMasterInfo*)any; + DeviceIntPtr xtstdevice; if (r->returnMode != AttachToMaster && r->returnMode != Floating) @@ -158,7 +180,17 @@ ProcXChangeDeviceHierarchy(ClientPtr client) goto unwind; } - /* disable keyboards first */ + for(xtstdevice = inputInfo.devices; xtstdevice ; xtstdevice = xtstdevice->next ) + if( !xtstdevice->isMaster && xtstdevice->u.master == ptr && + dixLookupPrivate(&xtstdevice->devPrivates, XTstDevicePrivateKey )) + break; + + rc = dixLookupDevice(&xtstptr, xtstdevice->id, client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + + /* find keyboards to destroy */ if (IsPointerDevice(ptr)) { rc = dixLookupDevice(&keybd, @@ -167,6 +199,7 @@ ProcXChangeDeviceHierarchy(ClientPtr client) DixDestroyAccess); if (rc != Success) goto unwind; + } else { @@ -177,8 +210,47 @@ ProcXChangeDeviceHierarchy(ClientPtr client) DixDestroyAccess); if (rc != Success) goto unwind; + } + /* handle xtst pointer / keyboard slave devices */ + if ( IsPointerDevice(xtstptr)) + { + /* Search the matching keyboard */ + for(xtstdevice = inputInfo.devices; xtstdevice ; xtstdevice = xtstdevice->next ) + if( !xtstdevice->isMaster && + xtstdevice->u.master == keybd && + IsKeyboardDevice(xtstdevice) && + dixLookupPrivate(&xtstdevice->devPrivates, XTstDevicePrivateKey )) + break; + + rc = dixLookupDevice(&xtstkeybd, + xtstdevice->id, + client, + DixDestroyAccess); + + if (rc != Success) + goto unwind; + } + else + { + xtstkeybd = xtstptr; + /* Search the matching pointer */ + for(xtstdevice = inputInfo.devices; xtstdevice ; xtstdevice = xtstdevice->next ) + if( !xtstdevice->isMaster && + xtstdevice->u.master == ptr && + IsPointerDevice(xtstdevice) && + dixLookupPrivate(&xtstdevice->devPrivates, XTstDevicePrivateKey ) + ) + break; + rc = dixLookupDevice(&xtstptr, + xtstdevice->id, + client, + DixDestroyAccess); + + if (rc != Success) + goto unwind; + } /* Disabling sends the devices floating, reattach them if * desired. */ @@ -228,9 +300,18 @@ ProcXChangeDeviceHierarchy(ClientPtr client) /* can't disable until we removed pairing */ keybd->spriteInfo->paired = NULL; ptr->spriteInfo->paired = NULL; + xtstptr->spriteInfo->paired = NULL; + xtstkeybd->spriteInfo->paired = NULL; + + /* disable the remove the devices, xtst devices must be done first + else the sprites they rely on will be destroyed */ + DisableDevice(xtstptr); + DisableDevice(xtstkeybd); DisableDevice(keybd); DisableDevice(ptr); + RemoveDevice(xtstptr); + RemoveDevice(xtstkeybd); RemoveDevice(keybd); RemoveDevice(ptr); nchanges++; @@ -238,6 +319,8 @@ ProcXChangeDeviceHierarchy(ClientPtr client) break; case CH_ChangeAttachment: { + DeviceIntPtr *xtstdevice; + xChangeAttachmentInfo* c = (xChangeAttachmentInfo*)any; rc = dixLookupDevice(&ptr, c->deviceid, client, @@ -252,6 +335,17 @@ ProcXChangeDeviceHierarchy(ClientPtr client) goto unwind; } + xtstdevice = dixLookupPrivate( &ptr->devPrivates, + XTstDevicePrivateKey ); + + /* Don't allow changes to Xtst Devices, these are fixed */ + if( xtstdevice ) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + if (c->changeMode == Floating) AttachDevice(client, ptr, NULL); else diff --git a/dix/devices.c b/dix/devices.c index bbddf3bc1..afe340b2f 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -88,9 +88,24 @@ SOFTWARE. static int CoreDevicePrivateKeyIndex; DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKeyIndex; -/* Used to sture classes currently not in use by an MD */ +/* Used to store classes currently not in use by an MD */ static int UnusedClassesPrivateKeyIndex; DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKeyIndex; +/* Used to store if a device is an XTest Virtual device */ +static int XTstDevicePrivateKeyIndex; +DevPrivateKey XTstDevicePrivateKey = &XTstDevicePrivateKeyIndex; + +/** + * vxtstpointer + * is the virtual pointer for XTest. It is the first slave + * device of the VCP. + * vxtstkeyboard + * is the virtual keyboard for XTest. It is the first slave + * device of the VCK + * + * Neither of these devices can be deleted. + */ +DeviceIntPtr vxtstpointer, vxtstkeyboard; /** @@ -556,6 +571,25 @@ InitCoreDevices(void) if (!EnableDevice(inputInfo.pointer) || !EnableDevice(inputInfo.keyboard)) FatalError("Failed to enable core devices."); + + /* + Allocate an virtual slave device for xtest events, this + is a slave device to inputInfo master devices + */ + if(AllocXtstDevice(serverClient, "Virtual core", + &vxtstpointer, + &vxtstkeyboard) != Success) + FatalError("Failed to allocate XTst devices"); + + if (ActivateDevice(vxtstpointer) != Success || + ActivateDevice(vxtstkeyboard) != Success) + FatalError("Failed to activate xtst core devices."); + if (!EnableDevice(vxtstpointer) || + !EnableDevice(vxtstkeyboard)) + FatalError("Failed to enable xtst core devices."); + + AttachDevice(NULL, vxtstpointer, inputInfo.pointer); + AttachDevice(NULL, vxtstkeyboard, inputInfo.keyboard); } /** @@ -2339,3 +2373,31 @@ AllocDevicePair (ClientPtr client, char* name, return Success; } + +/** + * Allocate a device pair that is initialised as a slave + * device with properties that identify the devices as belonging + * to XTest subsystem. + * This only creates the pair, Activate/Enable Device + * still need to be called. + */ +int AllocXtstDevice (ClientPtr client, char* name, + DeviceIntPtr* ptr, DeviceIntPtr* keybd) +{ + int retval; + int len = strlen(name); + char *xtstname = xcalloc(len + 6, 1 ); + + strncpy( xtstname, name, len); + strncat( xtstname, " Xtst", 5 ); + + retval = AllocDevicePair( client, xtstname, ptr, keybd, FALSE); + if ( retval == Success ){ + dixSetPrivate(&((*ptr)->devPrivates), XTstDevicePrivateKey, (void *)True ); + dixSetPrivate(&((*keybd)->devPrivates), XTstDevicePrivateKey,(void *)True); + } + + xfree( xtstname ); + + return retval; +} diff --git a/include/input.h b/include/input.h index b3bb5d1a5..56c3d2981 100644 --- a/include/input.h +++ b/include/input.h @@ -481,6 +481,10 @@ extern int generate_modkeymap(ClientPtr client, DeviceIntPtr dev, KeyCode **modkeymap, int *max_keys_per_mod); extern int change_modmap(ClientPtr client, DeviceIntPtr dev, KeyCode *map, int max_keys_per_mod); +extern int AllocXtstDevice(ClientPtr client, + char* name, + DeviceIntPtr* ptr, + DeviceIntPtr* keybd); /* Implemented by the DDX. */ extern _X_EXPORT int NewInputDeviceRequest(