aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/devices.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2009-07-25 19:39:46 +0000
committermarha <marha@users.sourceforge.net>2009-07-25 19:39:46 +0000
commit4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05 (patch)
treec1e02b9d3509aa97703aa4b540d4cd22ec4600ed /xorg-server/dix/devices.c
parentdc3c299dd0995549e2a6973ca0f25b254afd38a5 (diff)
downloadvcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.tar.gz
vcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.tar.bz2
vcxsrv-4a3dbb926ae3f5410198d7cc4f4ebe4f62eebf05.zip
Added xorg-server-1.6.2.tar.gz
Diffstat (limited to 'xorg-server/dix/devices.c')
-rw-r--r--xorg-server/dix/devices.c1255
1 files changed, 899 insertions, 356 deletions
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index 5a726afe8..3b8d544da 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -27,13 +27,13 @@ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
+both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
+software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
@@ -57,11 +57,13 @@ SOFTWARE.
#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xproto.h>
+#include <X11/Xatom.h>
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
+#include "ptrveloc.h"
#include "site.h"
#ifndef XKB_IN_SERVER
#define XKB_IN_SERVER
@@ -71,21 +73,109 @@ SOFTWARE.
#endif
#include "privates.h"
#include "xace.h"
+#include "mi.h"
#include "dispatch.h"
#include "swaprep.h"
#include "dixevents.h"
+#include "mipointer.h"
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include "exglobals.h"
#include "exevents.h"
+#include "listdev.h" /* for CopySwapXXXClass */
+#include "xiproperty.h"
+#include "enterleave.h" /* for EnterWindow() */
+#include "xserver-properties.h"
/** @file
* This file handles input device-related stuff.
*/
-DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
+static int CoreDevicePrivateKeyIndex;
+DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKeyIndex;
+/* Used to sture classes currently not in use by an MD */
+static int UnusedClassesPrivateKeyIndex;
+DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKeyIndex;
+
+
+/**
+ * DIX property handler.
+ */
+static int
+DeviceSetProperty(DeviceIntPtr dev, Atom property, XIPropertyValuePtr prop,
+ BOOL checkonly)
+{
+ if (property == XIGetKnownProperty(XI_PROP_ENABLED))
+ {
+ if (prop->format != 8 || prop->type != XA_INTEGER || prop->size != 1)
+ return BadValue;
+
+ /* Don't allow disabling of VCP/VCK */
+ if ((dev == inputInfo.pointer || dev == inputInfo.keyboard) &&
+ !(*(CARD8*)prop->data))
+ return BadAccess;
+
+ if (!checkonly)
+ {
+ if ((*((CARD8*)prop->data)) && !dev->enabled)
+ EnableDevice(dev);
+ else if (!(*((CARD8*)prop->data)) && dev->enabled)
+ DisableDevice(dev);
+ }
+ }
+
+ return Success;
+}
+
+/* Pair the keyboard to the pointer device. Keyboard events will follow the
+ * pointer sprite. Only applicable for master devices.
+ * If the client is set, the request to pair comes from some client. In this
+ * case, we need to check for access. If the client is NULL, it's from an
+ * internal automatic pairing, we must always permit this.
+ */
+static int
+PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd)
+{
+ if (!ptr)
+ return BadDevice;
+
+ /* Don't allow pairing for slave devices */
+ if (!ptr->isMaster || !kbd->isMaster)
+ return BadDevice;
+
+ if (ptr->spriteInfo->paired)
+ return BadDevice;
+
+ if (kbd->spriteInfo->spriteOwner)
+ {
+ xfree(kbd->spriteInfo->sprite);
+ kbd->spriteInfo->sprite = NULL;
+ kbd->spriteInfo->spriteOwner = FALSE;
+ }
+
+ kbd->spriteInfo->sprite = ptr->spriteInfo->sprite;
+ kbd->spriteInfo->paired = ptr;
+ ptr->spriteInfo->paired = kbd;
+ return Success;
+}
+
+
+/**
+ * Find and return the next unpaired MD pointer device.
+ */
+static DeviceIntPtr
+NextFreePointerDevice(void)
+{
+ DeviceIntPtr dev;
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ if (dev->isMaster &&
+ dev->spriteInfo->spriteOwner &&
+ !dev->spriteInfo->paired)
+ return dev;
+ return NULL;
+}
/**
* Create a new input device and init it to sane values. The device is added
@@ -95,69 +185,48 @@ DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
* @return The newly created device.
*/
DeviceIntPtr
-AddInputDevice(DeviceProc deviceProc, Bool autoStart)
+AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
{
DeviceIntPtr dev, *prev; /* not a typo */
DeviceIntPtr devtmp;
int devid;
- char devind[MAX_DEVICES];
+ char devind[MAXDEVICES];
+ BOOL enabled;
/* Find next available id */
- memset(devind, 0, sizeof(char)*MAX_DEVICES);
+ memset(devind, 0, sizeof(char)*MAXDEVICES);
for (devtmp = inputInfo.devices; devtmp; devtmp = devtmp->next)
devind[devtmp->id]++;
for (devtmp = inputInfo.off_devices; devtmp; devtmp = devtmp->next)
devind[devtmp->id]++;
- for (devid = 0; devid < MAX_DEVICES && devind[devid]; devid++)
+ for (devid = 0; devid < MAXDEVICES && devind[devid]; devid++)
;
- if (devid >= MAX_DEVICES)
+ if (devid >= MAXDEVICES)
return (DeviceIntPtr)NULL;
- dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1);
+ dev = xcalloc(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 1);
if (!dev)
return (DeviceIntPtr)NULL;
- dev->name = (char *)NULL;
- dev->type = 0;
dev->id = devid;
- dev->public.on = FALSE;
dev->public.processInputProc = (ProcessInputProc)NoopDDA;
dev->public.realInputProc = (ProcessInputProc)NoopDDA;
dev->public.enqueueInputProc = EnqueueEvent;
dev->deviceProc = deviceProc;
dev->startup = autoStart;
- dev->sync.frozen = FALSE;
- dev->sync.other = NullGrab;
- dev->sync.state = NOT_GRABBED;
- dev->sync.event = (xEvent *) NULL;
- dev->sync.evcount = 0;
- dev->grab = NullGrab;
- dev->grabTime = currentTime;
- dev->fromPassiveGrab = FALSE;
- dev->key = (KeyClassPtr)NULL;
- dev->valuator = (ValuatorClassPtr)NULL;
- dev->button = (ButtonClassPtr)NULL;
- dev->focus = (FocusClassPtr)NULL;
- dev->proximity = (ProximityClassPtr)NULL;
- dev->absolute = (AbsoluteClassPtr)NULL;
- dev->kbdfeed = (KbdFeedbackPtr)NULL;
- dev->ptrfeed = (PtrFeedbackPtr)NULL;
- dev->intfeed = (IntegerFeedbackPtr)NULL;
- dev->stringfeed = (StringFeedbackPtr)NULL;
- dev->bell = (BellFeedbackPtr)NULL;
- dev->leds = (LedFeedbackPtr)NULL;
-#ifdef XKB
- dev->xkb_interest = NULL;
-#endif
- dev->config_info = NULL;
- dev->devPrivates = NULL;
- dev->unwrapProc = NULL;
+
+ /* device grab defaults */
+ dev->deviceGrab.grabTime = currentTime;
+ dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+ dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+
dev->coreEvents = TRUE;
- dev->inited = FALSE;
- dev->enabled = FALSE;
+
+ /* sprite defaults */
+ dev->spriteInfo = (SpriteInfoPtr)&dev[1];
/* security creation/labeling check
*/
- if (XaceHook(XACE_DEVICE_ACCESS, serverClient, dev, DixCreateAccess)) {
+ if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixCreateAccess)) {
xfree(dev);
return NULL;
}
@@ -169,14 +238,24 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart)
*prev = dev;
dev->next = NULL;
+ enabled = FALSE;
+ XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
+ XA_INTEGER, 8, PropModeReplace, 1, &enabled,
+ FALSE);
+ XISetDevicePropertyDeletable(dev, XIGetKnownProperty(XI_PROP_ENABLED), FALSE);
+ XIRegisterPropertyHandler(dev, DeviceSetProperty, NULL, NULL);
+
return dev;
}
/**
+ * Enable the device through the driver, add the device to the device list.
* Switch device ON through the driver and push it onto the global device
- * list. All clients are notified about the device being enabled.
+ * list. Initialize the DIX sprite or pair the device. All clients are
+ * notified about the device being enabled.
*
- * A device will send events once enabled.
+ * A master pointer device needs to be enabled before a master keyboard
+ * device.
*
* @param The device to be enabled.
* @return TRUE on success or FALSE otherwise.
@@ -187,15 +266,62 @@ EnableDevice(DeviceIntPtr dev)
DeviceIntPtr *prev;
int ret;
DeviceIntRec dummyDev;
+ DeviceIntPtr other;
devicePresenceNotify ev;
+ int namelen = 0; /* dummy */
+ int evsize = sizeof(xEvent);
+ int listlen;
+ EventListPtr evlist;
+ BOOL enabled;
for (prev = &inputInfo.off_devices;
*prev && (*prev != dev);
prev = &(*prev)->next)
;
+
+ if (!dev->spriteInfo->sprite)
+ {
+ if (dev->isMaster)
+ {
+ /* Sprites appear on first root window, so we can hardcode it */
+ if (dev->spriteInfo->spriteOwner)
+ {
+ InitializeSprite(dev, WindowTable[0]);
+ /* mode doesn't matter */
+ EnterWindow(dev, WindowTable[0], NotifyAncestor);
+ }
+ else if ((other = NextFreePointerDevice()) == NULL)
+ {
+ ErrorF("[dix] cannot find pointer to pair with. "
+ "This is a bug.\n");
+ return FALSE;
+ } else
+ PairDevices(NULL, other, dev);
+ } else
+ {
+ other = (IsPointerDevice(dev)) ? inputInfo.pointer :
+ inputInfo.keyboard;
+ AttachDevice(NULL, dev, other);
+ }
+ }
+
+ /* Before actually enabling the device, we need to make sure the event
+ * list's events have enough memory for a ClassesChangedEvent from the
+ * device
+ */
+
+ SizeDeviceInfo(dev, &namelen, &evsize);
+
+ listlen = GetEventList(&evlist);
+ OsBlockSignals();
+ SetMinimumEventSize(evlist, listlen, evsize);
+ mieqResizeEvents(evsize);
+ OsReleaseSignals();
+
+
if ((*prev != dev) || !dev->inited ||
((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) {
- ErrorF("couldn't enable device %d\n", dev->id);
+ ErrorF("[dix] couldn't enable device %d\n", dev->id);
return FALSE;
}
dev->enabled = TRUE;
@@ -206,11 +332,16 @@ EnableDevice(DeviceIntPtr dev)
*prev = dev;
dev->next = NULL;
+ enabled = TRUE;
+ XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
+ XA_INTEGER, 8, PropModeReplace, 1, &enabled,
+ TRUE);
+
ev.type = DevicePresenceNotify;
ev.time = currentTime.milliseconds;
ev.devchange = DeviceEnabled;
ev.deviceid = dev->id;
- dummyDev.id = 0;
+ dummyDev.id = MAXDEVICES;
SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
(xEvent *) &ev, 1);
@@ -222,14 +353,18 @@ EnableDevice(DeviceIntPtr dev)
* list. A device will not send events while disabled. All clients are
* notified about the device being disabled.
*
+ * Master keyboard devices have to be disabled before master pointer devices
+ * otherwise things turn bad.
+ *
* @return TRUE on success or FALSE otherwise.
*/
Bool
DisableDevice(DeviceIntPtr dev)
{
- DeviceIntPtr *prev;
+ DeviceIntPtr *prev, other;
DeviceIntRec dummyDev;
devicePresenceNotify ev;
+ BOOL enabled;
for (prev = &inputInfo.devices;
*prev && (*prev != dev);
@@ -237,17 +372,54 @@ DisableDevice(DeviceIntPtr dev)
;
if (*prev != dev)
return FALSE;
+
+ /* float attached devices */
+ if (dev->isMaster)
+ {
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if (other->u.master == dev)
+ AttachDevice(NULL, other, NULL);
+ }
+ }
+ else
+ {
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if (other->isMaster && other->u.lastSlave == dev)
+ other->u.lastSlave = NULL;
+ }
+ }
+
+ if (dev->isMaster && dev->spriteInfo->sprite)
+ {
+ for (other = inputInfo.devices; other; other = other->next)
+ {
+ if (other->spriteInfo->paired == dev)
+ {
+ ErrorF("[dix] cannot disable device, still paired. "
+ "This is a bug. \n");
+ return FALSE;
+ }
+ }
+ }
+
(void)(*dev->deviceProc)(dev, DEVICE_OFF);
dev->enabled = FALSE;
*prev = dev->next;
dev->next = inputInfo.off_devices;
inputInfo.off_devices = dev;
+ enabled = FALSE;
+ XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_ENABLED),
+ XA_INTEGER, 8, PropModeReplace, 1, &enabled,
+ TRUE);
+
ev.type = DevicePresenceNotify;
ev.time = currentTime.milliseconds;
ev.devchange = DeviceDisabled;
ev.deviceid = dev->id;
- dummyDev.id = 0;
+ dummyDev.id = MAXDEVICES;
SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
(xEvent *) &ev, 1);
@@ -257,7 +429,8 @@ DisableDevice(DeviceIntPtr dev)
/**
* Initialise a new device through the driver and tell all clients about the
* new device.
- *
+ *
+ * Must be called before EnableDevice.
* The device will NOT send events until it is enabled!
*
* @return Success or an error code on failure.
@@ -268,18 +441,27 @@ ActivateDevice(DeviceIntPtr dev)
int ret = Success;
devicePresenceNotify ev;
DeviceIntRec dummyDev;
+ ScreenPtr pScreen = screenInfo.screens[0];
if (!dev || !dev->deviceProc)
return BadImplementation;
ret = (*dev->deviceProc) (dev, DEVICE_INIT);
dev->inited = (ret == Success);
-
+ if (!dev->inited)
+ return ret;
+
+ /* Initialize memory for sprites. */
+ if (dev->isMaster && dev->spriteInfo->spriteOwner)
+ pScreen->DeviceCursorInitialize(dev, pScreen);
+
ev.type = DevicePresenceNotify;
ev.time = currentTime.milliseconds;
ev.devchange = DeviceAdded;
ev.deviceid = dev->id;
- dummyDev.id = 0;
+
+ memset(&dummyDev, 0, sizeof(DeviceIntRec));
+ dummyDev.id = MAXDEVICES;
SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
(xEvent *) &ev, 1);
@@ -305,7 +487,7 @@ CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl)
}
/**
- * Device control function for the Virtual Core Keyboard.
+ * Device control function for the Virtual Core Keyboard.
*/
static int
CoreKeyboardProc(DeviceIntPtr pDev, int what)
@@ -315,9 +497,16 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
#ifdef XKB
XkbComponentNamesRec names;
#endif
+ ClassesPtr classes;
switch (what) {
case DEVICE_INIT:
+ if (!(classes = xcalloc(1, sizeof(ClassesRec))))
+ {
+ ErrorF("[dix] Could not allocate device classes.\n");
+ return BadAlloc;
+ }
+
keySyms.minKeyCode = 8;
keySyms.maxKeyCode = 255;
keySyms.mapWidth = 4;
@@ -326,21 +515,21 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
keySyms.minKeyCode + 1) *
keySyms.mapWidth);
if (!keySyms.map) {
- ErrorF("Couldn't allocate core keymap\n");
+ ErrorF("[dix] Couldn't allocate core keymap\n");
+ xfree(classes);
return BadAlloc;
}
- modMap = (CARD8 *)xalloc(MAP_LENGTH);
+ modMap = xcalloc(1, MAP_LENGTH);
if (!modMap) {
- ErrorF("Couldn't allocate core modifier map\n");
+ ErrorF("[dix] Couldn't allocate core modifier map\n");
+ xfree(classes);
return BadAlloc;
}
- bzero((char *)modMap, MAP_LENGTH);
#ifdef XKB
if (!noXkbExtension) {
bzero(&names, sizeof(names));
- XkbSetRulesDflts("base", "pc105", "us", NULL, NULL);
XkbInitKeyboardDeviceStruct(pDev, &names, &keySyms, modMap,
CoreKeyboardBell, CoreKeyboardCtl);
}
@@ -354,11 +543,9 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
xfree(keySyms.map);
xfree(modMap);
-
break;
case DEVICE_CLOSE:
- dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
break;
default:
@@ -369,28 +556,34 @@ 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 (!(classes = xcalloc(1, sizeof(ClassesRec))))
+ return BadAlloc;
+
for (i = 1; i <= 32; i++)
map[i] = i;
InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
- GetMotionHistory, (PtrCtrlProcPtr)NoopDDA,
+ (PtrCtrlProcPtr)NoopDDA,
GetMotionHistorySize(), 2);
pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
- pDev->valuator->lastx = pDev->valuator->axisVal[0];
+ pDev->last.valuators[0] = pDev->valuator->axisVal[0];
pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
- pDev->valuator->lasty = pDev->valuator->axisVal[1];
+ pDev->last.valuators[1] = pDev->valuator->axisVal[1];
break;
case DEVICE_CLOSE:
- dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
break;
default:
@@ -402,68 +595,41 @@ CorePointerProc(DeviceIntPtr pDev, int what)
/**
* Initialise the two core devices, VCP and VCK (see events.c).
- * The devices are activated but not enabled.
+ * Both devices are not tied to physical devices, but guarantee that there is
+ * always a keyboard and a pointer present and keep the protocol semantics.
+ *
* Note that the server MUST have two core devices at all times, even if there
* is no physical device connected.
*/
void
InitCoreDevices(void)
{
- DeviceIntPtr dev;
+ if (AllocMasterDevice(serverClient, "Virtual core",
+ &inputInfo.pointer,
+ &inputInfo.keyboard) != Success)
+ FatalError("Failed to allocate core devices");
+
+ ActivateDevice(inputInfo.pointer);
+ ActivateDevice(inputInfo.keyboard);
+ EnableDevice(inputInfo.pointer);
+ EnableDevice(inputInfo.keyboard);
- if (!inputInfo.keyboard) {
- dev = AddInputDevice(CoreKeyboardProc, TRUE);
- if (!dev)
- FatalError("Failed to allocate core keyboard");
- dev->name = strdup("Virtual core keyboard");
-#ifdef XKB
- dev->public.processInputProc = CoreProcessKeyboardEvent;
- dev->public.realInputProc = CoreProcessKeyboardEvent;
- if (!noXkbExtension)
- XkbSetExtension(dev, ProcessKeyboardEvent);
-#else
- dev->public.processInputProc = ProcessKeyboardEvent;
- dev->public.realInputProc = ProcessKeyboardEvent;
-#endif
- dev->ActivateGrab = ActivateKeyboardGrab;
- dev->DeactivateGrab = DeactivateKeyboardGrab;
- dev->coreEvents = FALSE;
- (void)ActivateDevice(dev);
- inputInfo.keyboard = dev;
- }
-
- if (!inputInfo.pointer) {
- dev = AddInputDevice(CorePointerProc, TRUE);
- if (!dev)
- FatalError("Failed to allocate core pointer");
- dev->name = strdup("Virtual core pointer");
-#ifdef XKB
- dev->public.processInputProc = CoreProcessPointerEvent;
- dev->public.realInputProc = CoreProcessPointerEvent;
- if (!noXkbExtension)
- XkbSetExtension(dev, ProcessPointerEvent);
-#else
- dev->public.processInputProc = ProcessPointerEvent;
- dev->public.realInputProc = ProcessPointerEvent;
-#endif
- dev->ActivateGrab = ActivatePointerGrab;
- dev->DeactivateGrab = DeactivatePointerGrab;
- dev->coreEvents = FALSE;
- (void)ActivateDevice(dev);
- inputInfo.pointer = dev;
- }
}
/**
* Activate all switched-off devices and then enable all those devices.
- *
+ *
* Will return an error if no core keyboard or core pointer is present.
* In theory this should never happen if you call InitCoreDevices() first.
- *
+ *
+ * InitAndStartDevices needs to be called AFTER the windows are initialized.
+ * Devices will start sending events after InitAndStartDevices() has
+ * completed.
+ *
* @return Success or error code on failure.
*/
int
-InitAndStartDevices(void)
+InitAndStartDevices()
{
DeviceIntPtr dev, next;
@@ -472,6 +638,8 @@ InitAndStartDevices(void)
if (!dev->inited)
ActivateDevice(dev);
}
+
+ /* enable real devices */
for (dev = inputInfo.off_devices; dev; dev = next)
{
DebugF("(dix) enabling device %d\n", dev->id);
@@ -479,27 +647,183 @@ InitAndStartDevices(void)
if (dev->inited && dev->startup)
(void)EnableDevice(dev);
}
- for (dev = inputInfo.devices;
- dev && (dev != inputInfo.keyboard);
- dev = dev->next)
- ;
- if (!dev || (dev != inputInfo.keyboard)) {
- ErrorF("No core keyboard\n");
- return BadImplementation;
+
+ return Success;
+}
+
+/**
+ * Free the given device class and reset the pointer to NULL.
+ */
+static void
+FreeDeviceClass(int type, pointer *class)
+{
+ if (!(*class))
+ return;
+
+ switch(type)
+ {
+ case KeyClass:
+ {
+ KeyClassPtr* k = (KeyClassPtr*)class;
+#ifdef XKB
+ if ((*k)->xkbInfo)
+ {
+ XkbFreeInfo((*k)->xkbInfo);
+ (*k)->xkbInfo = NULL;
+ }
+#endif
+ xfree((*k)->curKeySyms.map);
+ xfree((*k)->modifierKeyMap);
+ xfree((*k));
+ break;
+ }
+ case ButtonClass:
+ {
+ ButtonClassPtr *b = (ButtonClassPtr*)class;
+#ifdef XKB
+ if ((*b)->xkb_acts)
+ xfree((*b)->xkb_acts);
+#endif
+ xfree((*b));
+ break;
+ }
+ case ValuatorClass:
+ {
+ ValuatorClassPtr *v = (ValuatorClassPtr*)class;
+
+ /* Counterpart to 'biggest hack ever' in init. */
+ if ((*v)->motion)
+ xfree((*v)->motion);
+ xfree((*v));
+ break;
+ }
+ case FocusClass:
+ {
+ FocusClassPtr *f = (FocusClassPtr*)class;
+ xfree((*f)->trace);
+ xfree((*f));
+ break;
+ }
+ case ProximityClass:
+ {
+ ProximityClassPtr *p = (ProximityClassPtr*)class;
+ xfree((*p));
+ break;
+ }
}
- for (dev = inputInfo.devices;
- dev && (dev != inputInfo.pointer);
- dev = dev->next)
- ;
- if (!dev || (dev != inputInfo.pointer)) {
- ErrorF("No core pointer\n");
- return BadImplementation;
+ *class = NULL;
+}
+
+static void
+FreeFeedbackClass(int type, pointer *class)
+{
+ if (!(*class))
+ return;
+
+ switch(type)
+ {
+ case KbdFeedbackClass:
+ {
+ KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class;
+ KbdFeedbackPtr k, knext;
+ for (k = (*kbdfeed); k; k = knext) {
+ knext = k->next;
+#ifdef XKB
+ if (k->xkb_sli)
+ XkbFreeSrvLedInfo(k->xkb_sli);
+#endif
+ xfree(k);
+ }
+ break;
+ }
+ case PtrFeedbackClass:
+ {
+ PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class;
+ PtrFeedbackPtr p, pnext;
+
+ for (p = (*ptrfeed); p; p = pnext) {
+ pnext = p->next;
+ xfree(p);
+ }
+ break;
+ }
+ case IntegerFeedbackClass:
+ {
+ IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class;
+ IntegerFeedbackPtr i, inext;
+
+ for (i = (*intfeed); i; i = inext) {
+ inext = i->next;
+ xfree(i);
+ }
+ break;
+ }
+ case StringFeedbackClass:
+ {
+ StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class;
+ StringFeedbackPtr s, snext;
+
+ for (s = (*stringfeed); s; s = snext) {
+ snext = s->next;
+ xfree(s->ctrl.symbols_supported);
+ xfree(s->ctrl.symbols_displayed);
+ xfree(s);
+ }
+ break;
+ }
+ case BellFeedbackClass:
+ {
+ BellFeedbackPtr *bell = (BellFeedbackPtr*)class;
+ BellFeedbackPtr b, bnext;
+
+ for (b = (*bell); b; b = bnext) {
+ bnext = b->next;
+ xfree(b);
+ }
+ break;
+ }
+ case LedFeedbackClass:
+ {
+ LedFeedbackPtr *leds = (LedFeedbackPtr*)class;
+ LedFeedbackPtr l, lnext;
+
+ for (l = (*leds); l; l = lnext) {
+ lnext = l->next;
+#ifdef XKB
+ if (l->xkb_sli)
+ XkbFreeSrvLedInfo(l->xkb_sli);
+#endif
+ xfree(l);
+ }
+ break;
+ }
}
- return Success;
+ *class = NULL;
+}
+
+static void
+FreeAllDeviceClasses(ClassesPtr classes)
+{
+ if (!classes)
+ return;
+
+ FreeDeviceClass(KeyClass, (pointer)&classes->key);
+ FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator);
+ FreeDeviceClass(ButtonClass, (pointer)&classes->button);
+ FreeDeviceClass(FocusClass, (pointer)&classes->focus);
+ FreeDeviceClass(ProximityClass, (pointer)&classes->proximity);
+
+ FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed);
+ FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed);
+ FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed);
+ FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed);
+ FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell);
+ FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds);
+
}
/**
- * Close down a device and free all resources.
+ * Close down a device and free all resources.
* Once closed down, the driver will probably not expect you that you'll ever
* enable it again and free associated structs. If you want the device to just
* be disabled, DisableDevice().
@@ -508,106 +832,65 @@ InitAndStartDevices(void)
static void
CloseDevice(DeviceIntPtr dev)
{
- KbdFeedbackPtr k, knext;
- PtrFeedbackPtr p, pnext;
- IntegerFeedbackPtr i, inext;
- StringFeedbackPtr s, snext;
- BellFeedbackPtr b, bnext;
- LedFeedbackPtr l, lnext;
+ ScreenPtr screen = screenInfo.screens[0];
+ ClassesPtr classes;
+ int j;
+
+ if (!dev)
+ return;
+
+ XIDeleteAllDeviceProperties(dev);
if (dev->inited)
(void)(*dev->deviceProc)(dev, DEVICE_CLOSE);
- xfree(dev->name);
+ /* free sprite memory */
+ if (dev->isMaster && dev->spriteInfo->sprite)
+ screen->DeviceCursorCleanup(dev, screen);
- if (dev->key) {
-#ifdef XKB
- if (dev->key->xkbInfo)
- XkbFreeInfo(dev->key->xkbInfo);
-#endif
- dev->key->xkbInfo = NULL;
- xfree(dev->key->curKeySyms.map);
- xfree(dev->key->modifierKeyMap);
- xfree(dev->key);
- dev->key = NULL;
- }
+ /* free acceleration info */
+ if(dev->valuator && dev->valuator->accelScheme.AccelCleanupProc)
+ dev->valuator->accelScheme.AccelCleanupProc(dev);
- if (dev->valuator) {
- /* Counterpart to 'biggest hack ever' in init. */
- if (dev->valuator->motion &&
- dev->valuator->GetMotionProc == GetMotionHistory)
- xfree(dev->valuator->motion);
- xfree(dev->valuator);
- }
+ xfree(dev->name);
- if (dev->button) {
-#ifdef XKB
- if (dev->button->xkb_acts)
- xfree(dev->button->xkb_acts);
-#endif
- xfree(dev->button);
- }
+ classes = (ClassesPtr)&dev->key;
+ FreeAllDeviceClasses(classes);
- if (dev->focus) {
- xfree(dev->focus->trace);
- xfree(dev->focus);
+ if (dev->isMaster)
+ {
+ classes = dixLookupPrivate(&dev->devPrivates, UnusedClassesPrivateKey);
+ FreeAllDeviceClasses(classes);
}
- if (dev->proximity)
- xfree(dev->proximity);
- for (k = dev->kbdfeed; k; k = knext) {
- knext = k->next;
#ifdef XKB
- if (k->xkb_sli)
- XkbFreeSrvLedInfo(k->xkb_sli);
+ while (dev->xkb_interest)
+ XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
#endif
- xfree(k);
- }
- for (p = dev->ptrfeed; p; p = pnext) {
- pnext = p->next;
- xfree(p);
- }
-
- for (i = dev->intfeed; i; i = inext) {
- inext = i->next;
- xfree(i);
+ if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
+ xfree(dev->spriteInfo->sprite->spriteTrace);
+ xfree(dev->spriteInfo->sprite);
}
- for (s = dev->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) {
- bnext = b->next;
- xfree(b);
- }
-
- for (l = dev->leds; l; l = lnext) {
- lnext = l->next;
-#ifdef XKB
- if (l->xkb_sli)
- XkbFreeSrvLedInfo(l->xkb_sli);
-#endif
- xfree(l);
+ /* a client may have the device set as client pointer */
+ for (j = 0; j < currentMaxClients; j++)
+ {
+ if (clients[j] && clients[j]->clientPtr == dev)
+ {
+ clients[j]->clientPtr = NULL;
+ clients[j]->clientPtr = PickPointer(clients[j]);
+ }
}
-#ifdef XKB
- while (dev->xkb_interest)
- XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource);
-#endif
-
- xfree(dev->sync.event);
+ xfree(dev->deviceGrab.sync.event);
dixFreePrivates(dev->devPrivates);
xfree(dev);
}
/**
- * Shut down all devices, free all resources, etc.
+ * Shut down all devices, free all resources, etc.
* Only useful if you're shutting down the server!
*/
void
@@ -615,6 +898,17 @@ CloseDownDevices(void)
{
DeviceIntPtr dev, next;
+ /* Float all SDs before closing them. Note that at this point resources
+ * (e.g. cursors) have been freed already, so we can't just call
+ * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master
+ * to NULL and pretend nothing happened.
+ */
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ {
+ if (!dev->isMaster && dev->u.master)
+ dev->u.master = NULL;
+ }
+
for (dev = inputInfo.devices; dev; dev = next)
{
next = dev->next;
@@ -625,17 +919,40 @@ CloseDownDevices(void)
next = dev->next;
DeleteInputDeviceRequest(dev);
}
+
inputInfo.devices = NULL;
inputInfo.off_devices = NULL;
inputInfo.keyboard = NULL;
inputInfo.pointer = NULL;
+#ifdef XKB
+ XkbDeleteRulesDflts();
+#endif
+}
+
+/**
+ * Remove the cursor sprite for all devices. This needs to be done before any
+ * resources are freed or any device is deleted.
+ */
+void
+UndisplayDevices()
+{
+ DeviceIntPtr dev;
+ ScreenPtr screen = screenInfo.screens[0];
+
+ for (dev = inputInfo.devices; dev; dev = dev->next)
+ screen->DisplayCursor(dev, screen, NullCursor);
}
/**
* Remove a device from the device list, closes it and thus frees all
- * resources.
+ * resources.
* Removes both enabled and disabled devices and notifies all devices about
* the removal of the device.
+ *
+ * No PresenceNotify is sent for device that the client never saw. This can
+ * happen if a malloc fails during the addition of master devices. If
+ * dev->init is FALSE it means the client never received a DeviceAdded event,
+ * so let's not send a DeviceRemoved event either.
*/
int
RemoveDevice(DeviceIntPtr dev)
@@ -644,13 +961,19 @@ RemoveDevice(DeviceIntPtr dev)
int ret = BadMatch;
devicePresenceNotify ev;
DeviceIntRec dummyDev;
+ ScreenPtr screen = screenInfo.screens[0];
int deviceid;
+ int initialized;
DebugF("(dix) removing device %d\n", dev->id);
if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer)
return BadImplementation;
+ initialized = dev->inited;
+ if (DevHasCursor(dev))
+ screen->DisplayCursor(dev, screen, NullCursor);
+
deviceid = dev->id;
DisableDevice(dev);
@@ -658,13 +981,13 @@ RemoveDevice(DeviceIntPtr dev)
for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) {
next = tmp->next;
if (tmp == dev) {
- CloseDevice(tmp);
if (prev==NULL)
inputInfo.devices = next;
else
prev->next = next;
+ CloseDevice(tmp);
ret = Success;
}
}
@@ -683,14 +1006,14 @@ RemoveDevice(DeviceIntPtr dev)
ret = Success;
}
}
-
- if (ret == Success) {
+
+ if (ret == Success && initialized) {
inputInfo.numDevices--;
ev.type = DevicePresenceNotify;
ev.time = currentTime.milliseconds;
ev.devchange = DeviceRemoved;
ev.deviceid = deviceid;
- dummyDev.id = 0;
+ dummyDev.id = MAXDEVICES;
SendEventToAllWindows(&dummyDev, DevicePresenceNotifyMask,
(xEvent *) &ev, 1);
}
@@ -701,6 +1024,8 @@ RemoveDevice(DeviceIntPtr dev)
int
NumMotionEvents(void)
{
+ /* only called to fill data in initial connection reply.
+ * VCP is ok here, it is the only fixed device we have. */
return inputInfo.pointer->valuator->numMotionEvents;
}
@@ -776,10 +1101,9 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
KeySym *map;
int bytes = sizeof(KeySym) * src->mapWidth *
(dst->maxKeyCode - dst->minKeyCode + 1);
- map = (KeySym *)xalloc(bytes);
+ map = (KeySym *)xcalloc(1, bytes);
if (!map)
return FALSE;
- bzero((char *)map, bytes);
if (dst->map)
{
for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++)
@@ -790,6 +1114,16 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src)
}
dst->mapWidth = src->mapWidth;
dst->map = map;
+ } else if (!dst->map)
+ {
+ KeySym *map;
+ int bytes = sizeof(KeySym) * src->mapWidth *
+ (dst->maxKeyCode - dst->minKeyCode + 1);
+ map = (KeySym *)xcalloc(1, bytes);
+ if (!map)
+ return FALSE;
+ dst->map = map;
+ dst->mapWidth = src->mapWidth;
}
memmove((char *)&dst->map[rowDif * dst->mapWidth],
(char *)src->map,
@@ -819,10 +1153,9 @@ InitModMap(KeyClassPtr keyc)
}
}
}
- keyc->modifierKeyMap = (KeyCode *)xalloc(8*keyc->maxKeysPerModifier);
+ keyc->modifierKeyMap = xcalloc(8, keyc->maxKeysPerModifier);
if (!keyc->modifierKeyMap && keyc->maxKeysPerModifier)
return (FALSE);
- bzero((char *)keyc->modifierKeyMap, 8*(int)keyc->maxKeysPerModifier);
for (i = 0; i < 8; i++)
keysPerModifier[i] = 0;
for (i = 8; i < MAP_LENGTH; i++)
@@ -843,27 +1176,15 @@ InitModMap(KeyClassPtr keyc)
_X_EXPORT Bool
InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers[])
{
- int i;
KeyClassPtr keyc;
-
- keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec));
+
+ keyc = xcalloc(1, sizeof(KeyClassRec));
if (!keyc)
return FALSE;
- keyc->curKeySyms.map = (KeySym *)NULL;
- keyc->curKeySyms.mapWidth = 0;
keyc->curKeySyms.minKeyCode = pKeySyms->minKeyCode;
keyc->curKeySyms.maxKeyCode = pKeySyms->maxKeyCode;
- keyc->modifierKeyMap = (KeyCode *)NULL;
- keyc->state = 0;
- keyc->prev_state = 0;
if (pModifiers)
memmove((char *)keyc->modifierMap, (char *)pModifiers, MAP_LENGTH);
- else
- bzero((char *)keyc->modifierMap, MAP_LENGTH);
- bzero((char *)keyc->down, DOWN_LENGTH);
- bzero((char *)keyc->postdown, DOWN_LENGTH);
- for (i = 0; i < 8; i++)
- keyc->modifierKeyCount[i] = 0;
if (!SetKeySymsMap(&keyc->curKeySyms, pKeySyms) || !InitModMap(keyc))
{
xfree(keyc->curKeySyms.map);
@@ -880,32 +1201,24 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers
}
_X_EXPORT Bool
-InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
+InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons,
CARD8 *map)
{
ButtonClassPtr butc;
int i;
- butc = (ButtonClassPtr)xalloc(sizeof(ButtonClassRec));
+ butc = xcalloc(1, sizeof(ButtonClassRec));
if (!butc)
return FALSE;
butc->numButtons = numButtons;
for (i = 1; i <= numButtons; i++)
butc->map[i] = map[i];
- butc->buttonsDown = 0;
- butc->state = 0;
- butc->motionMask = 0;
- bzero((char *)butc->down, DOWN_LENGTH);
-#ifdef XKB
- butc->xkb_acts= NULL;
-#endif
dev->button = butc;
return TRUE;
}
_X_EXPORT Bool
-InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
- ValuatorMotionProcPtr motionProc,
+InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
int numMotionEvents, int mode)
{
int i;
@@ -914,7 +1227,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
if (!dev)
return FALSE;
- valc = (ValuatorClassPtr)xalloc(sizeof(ValuatorClassRec) +
+ valc = (ValuatorClassPtr)xcalloc(1, sizeof(ValuatorClassRec) +
numAxes * sizeof(AxisInfo) +
numAxes * sizeof(unsigned int));
if (!valc)
@@ -923,7 +1236,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
valc->motion = NULL;
valc->first_motion = 0;
valc->last_motion = 0;
- valc->GetMotionProc = motionProc;
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
@@ -931,20 +1243,82 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes,
valc->mode = mode;
valc->axes = (AxisInfoPtr)(valc + 1);
valc->axisVal = (int *)(valc->axes + numAxes);
- valc->lastx = 0;
- valc->lasty = 0;
- valc->dxremaind = 0;
- valc->dyremaind = 0;
dev->valuator = valc;
- /* biggest hack ever. */
- if (motionProc == GetMotionHistory)
- AllocateMotionHistory(dev);
+ AllocateMotionHistory(dev);
for (i=0; i<numAxes; i++) {
- InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0);
+ InitValuatorAxisStruct(dev, i, NO_AXIS_LIMITS, NO_AXIS_LIMITS,
+ 0, 0, 0);
valc->axisVal[i]=0;
}
+
+ dev->last.numValuators = numAxes;
+ if(dev->isMaster) /* master devs do not accelerate */
+ InitPointerAccelerationScheme(dev, PtrAccelNoOp);
+ else
+ InitPointerAccelerationScheme(dev, PtrAccelDefault);
+ return TRUE;
+}
+
+/* global list of acceleration schemes */
+ValuatorAccelerationRec pointerAccelerationScheme[] = {
+ {PtrAccelNoOp, NULL, NULL, NULL},
+ {PtrAccelPredictable, acceleratePointerPredictable, NULL, AccelerationDefaultCleanup},
+ {PtrAccelLightweight, acceleratePointerLightweight, NULL, NULL},
+ {-1, NULL, NULL, NULL} /* terminator */
+};
+
+/**
+ * install an acceleration scheme. returns TRUE on success, and should not
+ * change anything if unsuccessful.
+ */
+_X_EXPORT Bool
+InitPointerAccelerationScheme(DeviceIntPtr dev,
+ int scheme)
+{
+ int x, i = -1;
+ void* data = NULL;
+ ValuatorClassPtr val;
+
+ val = dev->valuator;
+
+ if(!val)
+ return FALSE;
+
+ if(dev->isMaster && (scheme != PtrAccelNoOp))
+ scheme = PtrAccelNoOp; /* no accel for master devices */
+
+ for(x = 0; pointerAccelerationScheme[x].number >= 0; x++) {
+ if(pointerAccelerationScheme[x].number == scheme){
+ i = x;
+ break;
+ }
+ }
+
+ if(-1 == i)
+ return FALSE;
+
+
+ /* init scheme-specific data */
+ switch(scheme){
+ case PtrAccelPredictable:
+ {
+ DeviceVelocityPtr s;
+ s = (DeviceVelocityPtr)xalloc(sizeof(DeviceVelocityRec));
+ if(!s)
+ return FALSE;
+ InitVelocityData(s);
+ data = s;
+ break;
+ }
+ default:
+ break;
+ }
+
+ val->accelScheme = pointerAccelerationScheme[i];
+ val->accelScheme.accelData = data;
+
return TRUE;
}
@@ -958,10 +1332,10 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
return FALSE;
/* we don't do anything sensible with these, but should */
- abs->min_x = -1;
- abs->min_y = -1;
- abs->max_x = -1;
- abs->max_y = -1;
+ abs->min_x = NO_AXIS_LIMITS;
+ abs->min_y = NO_AXIS_LIMITS;
+ abs->max_x = NO_AXIS_LIMITS;
+ abs->max_y = NO_AXIS_LIMITS;
abs->flip_x = 0;
abs->flip_y = 0;
abs->rotation = 0;
@@ -969,8 +1343,8 @@ InitAbsoluteClassDeviceStruct(DeviceIntPtr dev)
abs->offset_x = 0;
abs->offset_y = 0;
- abs->width = -1;
- abs->height = -1;
+ abs->width = NO_AXIS_LIMITS;
+ abs->height = NO_AXIS_LIMITS;
abs->following = 0;
abs->screen = 0;
@@ -998,7 +1372,7 @@ InitFocusClassDeviceStruct(DeviceIntPtr dev)
}
_X_EXPORT Bool
-InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc,
+InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc,
KbdCtrlProcPtr controlProc)
{
KbdFeedbackPtr feedc;
@@ -1062,7 +1436,7 @@ static IntegerCtrl defaultIntegerControl = {
_X_EXPORT Bool
InitStringFeedbackClassDeviceStruct (
- DeviceIntPtr dev, StringCtrlProcPtr controlProc,
+ DeviceIntPtr dev, StringCtrlProcPtr controlProc,
int max_symbols, int num_symbols_supported, KeySym *symbols)
{
int i;
@@ -1075,9 +1449,9 @@ InitStringFeedbackClassDeviceStruct (
feedc->ctrl.num_symbols_supported = num_symbols_supported;
feedc->ctrl.num_symbols_displayed = 0;
feedc->ctrl.max_symbols = max_symbols;
- feedc->ctrl.symbols_supported = (KeySym *)
+ feedc->ctrl.symbols_supported = (KeySym *)
xalloc (sizeof (KeySym) * num_symbols_supported);
- feedc->ctrl.symbols_displayed = (KeySym *)
+ feedc->ctrl.symbols_displayed = (KeySym *)
xalloc (sizeof (KeySym) * max_symbols);
if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed)
{
@@ -1101,7 +1475,7 @@ InitStringFeedbackClassDeviceStruct (
}
_X_EXPORT Bool
-InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
+InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc,
BellCtrlProcPtr controlProc)
{
BellFeedbackPtr feedc;
@@ -1160,23 +1534,22 @@ InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr contr
}
_X_EXPORT Bool
-InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
- ValuatorMotionProcPtr motionProc,
+InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons,
PtrCtrlProcPtr controlProc, int numMotionEvents,
int numAxes)
{
DeviceIntPtr dev = (DeviceIntPtr)device;
return(InitButtonClassDeviceStruct(dev, numButtons, map) &&
- InitValuatorClassDeviceStruct(dev, numAxes, motionProc,
+ InitValuatorClassDeviceStruct(dev, numAxes,
numMotionEvents, 0) &&
InitPtrFeedbackClassDeviceStruct(dev, controlProc));
}
_X_EXPORT Bool
-InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms,
- CARD8 pModifiers[], BellProcPtr bellProc,
- KbdCtrlProcPtr controlProc)
+InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms,
+ CARD8 pModifiers[], BellProcPtr bellProc,
+ KbdCtrlProcPtr controlProc)
{
DeviceIntPtr dev = (DeviceIntPtr)device;
@@ -1186,8 +1559,8 @@ InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms,
}
_X_EXPORT void
-SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count,
- ClientPtr client)
+SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode,
+ unsigned count, ClientPtr client)
{
int i;
xEvent event;
@@ -1201,9 +1574,9 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count,
}
#ifdef XKB
if (!noXkbExtension &&
- ((request == MappingKeyboard) || (request == MappingModifier)))
- XkbApplyMappingChange(inputInfo.keyboard, request, firstKeyCode, count,
- client);
+ ((request == MappingKeyboard) || (request == MappingModifier))) {
+ XkbApplyMappingChange(pDev,request,firstKeyCode,count, client);
+ }
#endif
/* 0 is the server client */
@@ -1225,13 +1598,15 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count,
}
/*
- * n-squared algorithm. n < 255 and don't want to copy the whole thing and
- * sort it to do the checking. How often is it called? Just being lazy?
+ * Check if the given buffer contains elements between low (inclusive) and
+ * high (inclusive) only.
+ *
+ * @return TRUE if the device map is invalid, FALSE otherwise.
*/
Bool
BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
{
- int i, j;
+ int i;
for (i = 0; i < length; i++)
if (buff[i]) /* only check non-zero elements */
@@ -1241,12 +1616,6 @@ BadDeviceMap(BYTE *buff, int length, unsigned low, unsigned high, XID *errval)
*errval = buff[i];
return TRUE;
}
- for (j = i + 1; j < length; j++)
- if (buff[i] == buff[j])
- {
- *errval = buff[i];
- return TRUE;
- }
}
return FALSE;
}
@@ -1281,10 +1650,11 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap,
int numKeyPerModifier, xSetModifierMappingReply *rep)
{
DeviceIntPtr pDev = NULL;
+ DeviceIntPtr cp = PickKeyboard(client); /* ClientPointer keyboard */
int rc, i = 0, inputMapLen = numKeyPerModifier * 8;
for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
- if ((pDev->coreEvents || pDev == inputInfo.keyboard) && pDev->key) {
+ if (pDev == cp || (!pDev->isMaster && (pDev->u.master == cp) && pDev->key)) {
for (i = 0; i < inputMapLen; i++) {
/* Check that all the new modifiers fall within the advertised
* keycode range, and are okay with the DDX. */
@@ -1350,7 +1720,7 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap,
return Success;
}
-int
+int
ProcSetModifierMapping(ClientPtr client)
{
xSetModifierMappingReply rep;
@@ -1372,7 +1742,6 @@ ProcSetModifierMapping(ClientPtr client)
if (rc != Success)
return rc;
- SendMappingNotify(MappingModifier, 0, 0, client);
for (dev = inputInfo.devices; dev; dev = dev->next)
if (dev->key && dev->coreEvents)
SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev);
@@ -1384,12 +1753,12 @@ int
ProcGetModifierMapping(ClientPtr client)
{
xGetModifierMappingReply rep;
- KeyClassPtr keyc = inputInfo.keyboard->key;
+ DeviceIntPtr dev = PickKeyboard(client);
+ KeyClassPtr keyc = dev->key;
int rc;
REQUEST_SIZE_MATCH(xReq);
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
- DixGetAttrAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -1413,12 +1782,12 @@ ProcChangeKeyboardMapping(ClientPtr client)
REQUEST(xChangeKeyboardMappingReq);
unsigned len;
KeySymsRec keysyms;
- KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
+ KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms;
DeviceIntPtr pDev = NULL;
int rc;
REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq);
- len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);
+ len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2);
if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode))
return BadLength;
@@ -1451,8 +1820,6 @@ ProcChangeKeyboardMapping(ClientPtr client)
if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms))
return BadAlloc;
- SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes,
- client);
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
if (pDev->key && pDev->coreEvents)
SendDeviceMappingNotify(client, MappingKeyboard,
@@ -1466,36 +1833,23 @@ static int
DoSetPointerMapping(ClientPtr client, DeviceIntPtr device, BYTE *map, int n)
{
int rc, i = 0;
- DeviceIntPtr dev = NULL;
if (!device || !device->button)
return BadDevice;
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
- rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixManageAccess);
- if (rc != Success)
- return rc;
- }
- }
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixManageAccess);
+ if (rc != Success)
+ return rc;
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
- for (i = 0; i < n; i++) {
- if ((device->button->map[i + 1] != map[i]) &&
- BitIsOn(device->button->down, i + 1)) {
- return MappingBusy;
- }
- }
+ for (i = 0; i < n; i++) {
+ if ((device->button->map[i + 1] != map[i]) &&
+ BitIsOn(device->button->down, i + 1)) {
+ return MappingBusy;
}
}
- for (dev = inputInfo.devices; dev; dev = dev->next) {
- if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) {
- for (i = 0; i < n; i++)
- dev->button->map[i + 1] = map[i];
- }
- }
+ for (i = 0; i < n; i++)
+ device->button->map[i + 1] = map[i];
return Success;
}
@@ -1505,6 +1859,8 @@ ProcSetPointerMapping(ClientPtr client)
{
BYTE *map;
int ret;
+ int i, j;
+ DeviceIntPtr ptr = PickPointer(client);
xSetPointerMappingReply rep;
REQUEST(xSetPointerMappingReq);
REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq);
@@ -1516,25 +1872,41 @@ ProcSetPointerMapping(ClientPtr client)
rep.sequenceNumber = client->sequence;
rep.success = MappingSuccess;
map = (BYTE *)&stuff[1];
-
+
/* So we're bounded here by the number of core buttons. This check
* probably wants disabling through XFixes. */
- if (stuff->nElts != inputInfo.pointer->button->numButtons) {
+ /* MPX: With ClientPointer, we can return the right number of buttons.
+ * Let's just hope nobody changed ClientPointer between GetPointerMapping
+ * and SetPointerMapping
+ */
+ if (stuff->nElts != ptr->button->numButtons) {
client->errorValue = stuff->nElts;
return BadValue;
}
if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue))
return BadValue;
- ret = DoSetPointerMapping(client, inputInfo.pointer, map, stuff->nElts);
+ /* core protocol specs don't allow for duplicate mappings. */
+ for (i = 0; i < stuff->nElts; i++)
+ {
+ for (j = i + 1; j < stuff->nElts; j++)
+ {
+ if (map[i] && map[i] == map[j])
+ {
+ client->errorValue = map[i];
+ return BadValue;
+ }
+ }
+ }
+
+ ret = DoSetPointerMapping(client, ptr, map, stuff->nElts);
if (ret != Success) {
rep.success = ret;
WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
return Success;
}
- /* FIXME: Send mapping notifies for all the extended devices as well. */
- SendMappingNotify(MappingPointer, 0, 0, client);
+ SendMappingNotify(ptr, MappingPointer, 0, 0, client);
WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep);
return Success;
}
@@ -1543,13 +1915,13 @@ int
ProcGetKeyboardMapping(ClientPtr client)
{
xGetKeyboardMappingReply rep;
- KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms;
+ DeviceIntPtr kbd = PickKeyboard(client);
+ KeySymsPtr curKeySyms = &kbd->key->curKeySyms;
int rc;
REQUEST(xGetKeyboardMappingReq);
REQUEST_SIZE_MATCH(xGetKeyboardMappingReq);
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
- DixGetAttrAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -1584,12 +1956,14 @@ int
ProcGetPointerMapping(ClientPtr client)
{
xGetPointerMappingReply rep;
- ButtonClassPtr butc = inputInfo.pointer->button;
+ /* Apps may get different values each time they call GetPointerMapping as
+ * the ClientPointer could change. */
+ DeviceIntPtr ptr = PickPointer(client);
+ ButtonClassPtr butc = ptr->button;
int rc;
REQUEST_SIZE_MATCH(xReq);
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer,
- DixGetAttrAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -1599,7 +1973,7 @@ ProcGetPointerMapping(ClientPtr client)
rep.length = ((unsigned)rep.nElts + (4-1))/4;
WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep);
(void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]);
- return Success;
+ return Success;
}
void
@@ -1639,7 +2013,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
index2 = (BITS32) lowbit (vmask);
vmask &= ~index2;
switch (index2) {
- case KBKeyClickPercent:
+ case KBKeyClickPercent:
t = (INT8)*vlist;
vlist++;
if (t == -1) {
@@ -1728,8 +2102,8 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
case KBKey:
key = (KeyCode)*vlist;
vlist++;
- if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode ||
- (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) {
+ if ((KeyCode)key < keybd->key->curKeySyms.minKeyCode ||
+ (KeyCode)key > keybd->key->curKeySyms.maxKeyCode) {
client->errorValue = key;
return BadValue;
}
@@ -1789,7 +2163,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist,
return Success;
#undef DO_ALL
-}
+}
int
ProcChangeKeyboardControl (ClientPtr client)
@@ -1833,12 +2207,12 @@ int
ProcGetKeyboardControl (ClientPtr client)
{
int rc, i;
- KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl;
+ DeviceIntPtr kbd = PickKeyboard(client);
+ KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl;
xGetKeyboardControlReply rep;
REQUEST_SIZE_MATCH(xReq);
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
- DixGetAttrAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -1855,21 +2229,26 @@ ProcGetKeyboardControl (ClientPtr client)
rep.map[i] = ctrl->autoRepeats[i];
WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep);
return Success;
-}
+}
int
ProcBell(ClientPtr client)
{
- DeviceIntPtr keybd = inputInfo.keyboard;
+ DeviceIntPtr keybd = PickKeyboard(client);
int base = keybd->kbdfeed->ctrl.bell;
int newpercent;
int rc;
REQUEST(xBellReq);
REQUEST_SIZE_MATCH(xBellReq);
+ /* Seems like no keyboard actually has the BellProc set. Returning
+ * BadDevice (previous code) will make apps crash badly. The man pages
+ * doesn't say anything about a BadDevice being returned either.
+ * So just quietly do nothing and pretend everything has worked.
+ */
if (!keybd->kbdfeed->BellProc)
- return BadDevice;
-
+ return Success;
+
if (stuff->percent < -100 || stuff->percent > 100) {
client->errorValue = stuff->percent;
return BadValue;
@@ -1879,7 +2258,7 @@ ProcBell(ClientPtr client)
if (stuff->percent < 0)
newpercent = base + newpercent;
else
- newpercent = base - newpercent + stuff->percent;
+ newpercent = base - newpercent + stuff->percent;
for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
if ((keybd->coreEvents || keybd == inputInfo.keyboard) &&
@@ -1900,20 +2279,20 @@ ProcBell(ClientPtr client)
}
return Success;
-}
+}
int
ProcChangePointerControl(ClientPtr client)
{
- DeviceIntPtr mouse = inputInfo.pointer;
+ DeviceIntPtr mouse = PickPointer(client);
PtrCtrl ctrl; /* might get BadValue part way through */
int rc;
REQUEST(xChangePointerControlReq);
REQUEST_SIZE_MATCH(xChangePointerControlReq);
-
+
if (!mouse->ptrfeed->CtrlProc)
return BadDevice;
-
+
ctrl = mouse->ptrfeed->ctrl;
if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) {
client->errorValue = stuff->doAccel;
@@ -1969,7 +2348,7 @@ ProcChangePointerControl(ClientPtr client)
}
for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
- if ((mouse->coreEvents || mouse == inputInfo.pointer) &&
+ if ((mouse->coreEvents || mouse == PickPointer(client)) &&
mouse->ptrfeed && mouse->ptrfeed->CtrlProc) {
mouse->ptrfeed->ctrl = ctrl;
(*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl);
@@ -1977,18 +2356,18 @@ ProcChangePointerControl(ClientPtr client)
}
return Success;
-}
+}
int
ProcGetPointerControl(ClientPtr client)
{
- PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl;
+ DeviceIntPtr ptr = PickPointer(client);
+ PtrCtrl *ctrl = &ptr->ptrfeed->ctrl;
xGetPointerControlReply rep;
int rc;
REQUEST_SIZE_MATCH(xReq);
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer,
- DixGetAttrAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess);
if (rc != Success)
return rc;
@@ -2005,7 +2384,7 @@ ProcGetPointerControl(ClientPtr client)
void
MaybeStopHint(DeviceIntPtr dev, ClientPtr client)
{
- GrabPtr grab = dev->grab;
+ GrabPtr grab = dev->deviceGrab.grab;
if ((grab && SameClient(grab, client) &&
((grab->eventMask & PointerMotionHintMask) ||
@@ -2026,7 +2405,7 @@ ProcGetMotionEvents(ClientPtr client)
xGetMotionEventsReply rep;
int i, count, xmin, xmax, ymin, ymax, rc;
unsigned long nEvents;
- DeviceIntPtr mouse = inputInfo.pointer;
+ DeviceIntPtr mouse = PickPointer(client);
TimeStamp start, stop;
REQUEST(xGetMotionEventsReq);
REQUEST_SIZE_MATCH(xGetMotionEventsReq);
@@ -2051,14 +2430,9 @@ ProcGetMotionEvents(ClientPtr client)
{
if (CompareTimeStamps(stop, currentTime) == LATER)
stop = currentTime;
- coords = (xTimecoord *)xalloc(mouse->valuator->numMotionEvents
- * sizeof(xTimecoord));
- if (!coords)
- return BadAlloc;
- count = (*mouse->valuator->GetMotionProc) (mouse, coords,
- start.milliseconds,
- stop.milliseconds,
- pWin->drawable.pScreen);
+ count = GetMotionHistory(mouse, &coords, start.milliseconds,
+ stop.milliseconds, pWin->drawable.pScreen,
+ TRUE);
xmin = pWin->drawable.x - wBorderWidth (pWin);
xmax = pWin->drawable.x + (int)pWin->drawable.width +
wBorderWidth (pWin);
@@ -2094,15 +2468,15 @@ ProcQueryKeymap(ClientPtr client)
{
xQueryKeymapReply rep;
int rc, i;
- CARD8 *down = inputInfo.keyboard->key->down;
+ DeviceIntPtr keybd = PickKeyboard(client);
+ CARD8 *down = keybd->key->down;
REQUEST_SIZE_MATCH(xReq);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 2;
- rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard,
- DixReadAccess);
+ rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
if (rc != Success)
return rc;
@@ -2110,5 +2484,174 @@ ProcQueryKeymap(ClientPtr client)
rep.map[i] = down[i];
WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep);
+
+ return Success;
+}
+
+/**
+ * Attach device 'dev' to device 'master'.
+ * Client is set to the client that issued the request, or NULL if it comes
+ * from some internal automatic pairing.
+ *
+ * Master may be NULL to set the device floating.
+ *
+ * We don't allow multi-layer hierarchies right now. You can't attach a slave
+ * to another slave.
+ */
+int
+AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
+{
+ ScreenPtr screen;
+ DeviceIntPtr oldmaster;
+ if (!dev || dev->isMaster)
+ return BadDevice;
+
+ if (master && !master->isMaster) /* can't attach to slaves */
+ return BadDevice;
+
+ /* set from floating to floating? */
+ if (!dev->u.master && !master)
+ return Success;
+
+ /* free the existing sprite. */
+ if (!dev->u.master && dev->spriteInfo->paired == dev)
+ {
+ screen = miPointerGetScreen(dev);
+ screen->DeviceCursorCleanup(dev, screen);
+ xfree(dev->spriteInfo->sprite);
+ }
+
+ oldmaster = dev->u.master;
+ dev->u.master = master;
+
+ /* If device is set to floating, we need to create a sprite for it,
+ * otherwise things go bad. However, we don't want to render the cursor,
+ * so we reset spriteOwner.
+ * Sprite has to be forced to NULL first, otherwise InitializeSprite won't
+ * alloc new memory but overwrite the previous one.
+ */
+ if (!master)
+ {
+ WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0];
+ /* we need to init a fake sprite */
+ screen = currentRoot->drawable.pScreen;
+ screen->DeviceCursorInitialize(dev, screen);
+ dev->spriteInfo->sprite = NULL;
+ InitializeSprite(dev, currentRoot);
+ dev->spriteInfo->spriteOwner = FALSE;
+ dev->spriteInfo->paired = dev;
+
+ } else
+ {
+ dev->spriteInfo->sprite = master->spriteInfo->sprite;
+ dev->spriteInfo->paired = master;
+ dev->spriteInfo->spriteOwner = FALSE;
+ }
+
+ /* If we were connected to master device before, this MD may need to
+ * change back to it's original classes.
+ */
+ if (oldmaster)
+ {
+ DeviceIntPtr it;
+ for (it = inputInfo.devices; it; it = it->next)
+ if (!it->isMaster && it->u.master == oldmaster)
+ break;
+ }
+
+ return Success;
+}
+
+/**
+ * Return the device paired with the given device or NULL.
+ * Returns the device paired with the parent master if the given device is a
+ * slave device.
+ */
+_X_EXPORT DeviceIntPtr
+GetPairedDevice(DeviceIntPtr dev)
+{
+ if (!dev->isMaster && dev->u.master)
+ dev = dev->u.master;
+
+ return dev->spriteInfo->paired;
+}
+
+
+/**
+ * Create a new master device (== one pointer, one keyboard device).
+ * Only allocates the devices, you will need to call ActivateDevice() and
+ * EnableDevice() manually.
+ */
+int
+AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd)
+{
+ DeviceIntPtr pointer;
+ DeviceIntPtr keyboard;
+ ClassesPtr classes;
+ *ptr = *keybd = NULL;
+
+ pointer = AddInputDevice(client, CorePointerProc, TRUE);
+ if (!pointer)
+ return BadAlloc;
+
+ pointer->name = xcalloc(strlen(name) + strlen(" pointer") + 1, sizeof(char));
+ strcpy(pointer->name, name);
+ strcat(pointer->name, " pointer");
+
+#ifdef XKB
+ pointer->public.processInputProc = ProcessOtherEvent;
+ pointer->public.realInputProc = ProcessOtherEvent;
+ if (!noXkbExtension)
+ XkbSetExtension(pointer, ProcessPointerEvent);
+#else
+ pointer->public.processInputProc = ProcessPointerEvent;
+ pointer->public.realInputProc = ProcessPointerEvent;
+#endif
+ pointer->deviceGrab.ActivateGrab = ActivatePointerGrab;
+ pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab;
+ pointer->coreEvents = TRUE;
+ pointer->spriteInfo->spriteOwner = TRUE;
+
+ pointer->u.lastSlave = NULL;
+ pointer->isMaster = TRUE;
+
+ keyboard = AddInputDevice(client, CoreKeyboardProc, TRUE);
+ if (!keyboard)
+ {
+ RemoveDevice(pointer);
+ return BadAlloc;
+ }
+
+ keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char));
+ strcpy(keyboard->name, name);
+ strcat(keyboard->name, " keyboard");
+
+#ifdef XKB
+ keyboard->public.processInputProc = ProcessOtherEvent;
+ keyboard->public.realInputProc = ProcessOtherEvent;
+ if (!noXkbExtension)
+ XkbSetExtension(keyboard, ProcessKeyboardEvent);
+#else
+ keyboard->public.processInputProc = ProcessKeyboardEvent;
+ keyboard->public.realInputProc = ProcessKeyboardEvent;
+#endif
+ keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab;
+ keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab;
+ keyboard->coreEvents = TRUE;
+ keyboard->spriteInfo->spriteOwner = FALSE;
+
+ keyboard->u.lastSlave = NULL;
+ keyboard->isMaster = TRUE;
+
+
+ /* The ClassesRec stores the device classes currently not used. */
+ classes = xcalloc(1, sizeof(ClassesRec));
+ dixSetPrivate(&pointer->devPrivates, UnusedClassesPrivateKey, classes);
+ classes = xcalloc(1, sizeof(ClassesRec));
+ dixSetPrivate(&keyboard->devPrivates, UnusedClassesPrivateKey, classes);
+
+ *ptr = pointer;
+ *keybd = keyboard;
+
return Success;
}