input: introduce partial class copying depending on the event.

Copying all classes into the master device has drawbacks for hybrid devices
(devices that are both mice and keyboards). If such a device posts an event,
it's key classes are moved into the VCP. The key event itself is unaffected
by keyboard grabs and the like.

Partial class copying copies depending on the event and copies the classes
into the right master device (i.e. the VCK for key events, the VCP for
pointer events).

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2009-05-20 10:55:03 +10:00
parent bc63c8a457
commit ebe45e1a72
7 changed files with 210 additions and 156 deletions

View File

@ -216,83 +216,6 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
if (from->kbdfeed)
{
KbdFeedbackPtr *k, it;
if (!to->kbdfeed)
{
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->kbdfeed = classes->kbdfeed;
if (!to->kbdfeed)
InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
}
k = &to->kbdfeed;
for(it = from->kbdfeed; it; it = it->next)
{
if (!(*k))
{
*k = xcalloc(1, sizeof(KbdFeedbackClassRec));
if (!*k)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*k)->BellProc = it->BellProc;
(*k)->CtrlProc = it->CtrlProc;
(*k)->ctrl = it->ctrl;
if ((*k)->xkb_sli)
XkbFreeSrvLedInfo((*k)->xkb_sli);
(*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
k = &(*k)->next;
}
} else if (to->kbdfeed && !from->kbdfeed)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->kbdfeed = to->kbdfeed;
to->kbdfeed = NULL;
}
if (from->ptrfeed)
{
PtrFeedbackPtr *p, it;
if (!to->ptrfeed)
{
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->ptrfeed = classes->ptrfeed;
}
p = &to->ptrfeed;
for (it = from->ptrfeed; it; it = it->next)
{
if (!(*p))
{
*p = xcalloc(1, sizeof(PtrFeedbackClassRec));
if (!*p)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*p)->CtrlProc = it->CtrlProc;
(*p)->ctrl = it->ctrl;
p = &(*p)->next;
}
} else if (to->ptrfeed && !from->ptrfeed)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->ptrfeed = to->ptrfeed;
to->ptrfeed = NULL;
}
if (from->intfeed)
{
@ -443,31 +366,63 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
}
}
/**
* Copies the CONTENT of the classes of device from into the classes in device
* to. From and to are identical after finishing.
*
* If to does not have classes from currenly has, the classes are stored in
* to's devPrivates system. Later, we recover it again from there if needed.
* Saves a few memory allocations.
*/
void
DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
static void
DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
/* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
* kbdfeed to be set up properly, so let's do the feedback classes first.
*/
DeepCopyFeedbackClasses(from, to);
if (from->kbdfeed)
{
KbdFeedbackPtr *k, it;
if (!to->kbdfeed)
{
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->kbdfeed = classes->kbdfeed;
if (!to->kbdfeed)
InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
}
k = &to->kbdfeed;
for(it = from->kbdfeed; it; it = it->next)
{
if (!(*k))
{
*k = xcalloc(1, sizeof(KbdFeedbackClassRec));
if (!*k)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*k)->BellProc = it->BellProc;
(*k)->CtrlProc = it->CtrlProc;
(*k)->ctrl = it->ctrl;
if ((*k)->xkb_sli)
XkbFreeSrvLedInfo((*k)->xkb_sli);
(*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
k = &(*k)->next;
}
} else if (to->kbdfeed && !from->kbdfeed)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->kbdfeed = to->kbdfeed;
to->kbdfeed = NULL;
}
if (from->key)
{
if (!to->key)
{
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
UnusedClassesPrivateKey);
to->key = classes->key;
if (!to->key)
InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
@ -484,6 +439,89 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
to->key = NULL;
}
/* We can't just copy over the focus class. When an app sets the focus,
* it'll do so on the master device. Copying the SDs focus means losing
* the focus.
* So we only copy the focus class if the device didn't have one,
* otherwise we leave it as it is.
*/
if (from->focus)
{
if (!to->focus)
{
WindowPtr *oldTrace;
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->focus = classes->focus;
if (!to->focus)
{
to->focus = xcalloc(1, sizeof(FocusClassRec));
if (!to->focus)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->focus = NULL;
oldTrace = to->focus->trace;
memcpy(to->focus, from->focus, sizeof(FocusClassRec));
to->focus->trace = xrealloc(oldTrace,
to->focus->traceSize * sizeof(WindowPtr));
if (!to->focus->trace && to->focus->traceSize)
FatalError("[Xi] no memory for trace.\n");
memcpy(to->focus->trace, from->focus->trace,
from->focus->traceSize * sizeof(WindowPtr));
}
} else if (to->focus)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->focus = to->focus;
to->focus = NULL;
}
}
static void
DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
/* Feedback classes must be copied first */
if (from->ptrfeed)
{
PtrFeedbackPtr *p, it;
if (!to->ptrfeed)
{
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->ptrfeed = classes->ptrfeed;
}
p = &to->ptrfeed;
for (it = from->ptrfeed; it; it = it->next)
{
if (!(*p))
{
*p = xcalloc(1, sizeof(PtrFeedbackClassRec));
if (!*p)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*p)->CtrlProc = it->CtrlProc;
(*p)->ctrl = it->ctrl;
p = &(*p)->next;
}
} else if (to->ptrfeed && !from->ptrfeed)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->ptrfeed = to->ptrfeed;
to->ptrfeed = NULL;
}
if (from->valuator)
{
ValuatorClassPtr v;
@ -552,47 +590,6 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
to->button = NULL;
}
/* We can't just copy over the focus class. When an app sets the focus,
* it'll do so on the master device. Copying the SDs focus means losing
* the focus.
* So we only copy the focus class if the device didn't have one,
* otherwise we leave it as it is.
*/
if (from->focus)
{
if (!to->focus)
{
WindowPtr *oldTrace;
classes = dixLookupPrivate(&to->devPrivates,
UnusedClassesPrivateKey);
to->focus = classes->focus;
if (!to->focus)
{
to->focus = xcalloc(1, sizeof(FocusClassRec));
if (!to->focus)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->focus = NULL;
oldTrace = to->focus->trace;
memcpy(to->focus, from->focus, sizeof(FocusClassRec));
to->focus->trace = xrealloc(oldTrace,
to->focus->traceSize * sizeof(WindowPtr));
if (!to->focus->trace && to->focus->traceSize)
FatalError("[Xi] no memory for trace.\n");
memcpy(to->focus->trace, from->focus->trace,
from->focus->traceSize * sizeof(WindowPtr));
}
} else if (to->focus)
{
ClassesPtr classes;
classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey);
classes->focus = to->focus;
to->focus = NULL;
}
if (from->proximity)
{
if (!to->proximity)
@ -642,6 +639,27 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
}
}
/**
* Copies the CONTENT of the classes of device from into the classes in device
* to. From and to are identical after finishing.
*
* If to does not have classes from currenly has, the classes are stored in
* to's devPrivates system. Later, we recover it again from there if needed.
* Saves a few memory allocations.
*/
void
DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
{
/* generic feedback classes, not tied to pointer and/or keyboard */
DeepCopyFeedbackClasses(from, to);
if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
DeepCopyKeyboardClasses(from, to);
if ((dce->flags & DEVCHANGE_POINTER_EVENT))
DeepCopyPointerClasses(from, to);
}
/**
* Change MD to look like SD by copying all classes over. An event is sent to
* all interested clients.
@ -727,10 +745,14 @@ ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
if (!master) /* if device was set floating between SIGIO and now */
return;
master = GetMaster(device,
(dce->flags & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD);
master->public.devicePrivate = device->public.devicePrivate;
/* FIXME: the classes may have changed since we generated the event. */
DeepCopyDeviceClasses(device, master);
DeepCopyDeviceClasses(device, master, dce);
XISendDeviceChangedEvent(device, master, dce);
}

View File

@ -2320,7 +2320,8 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
/* XXX: reset master back to defaults */
event = InitEventList(1);
SetMinimumEventSize(event, 1, sizeof(DeviceChangedEvent));
CreateClassesChangedEvent(event, oldmaster, oldmaster);
CreateClassesChangedEvent(event, oldmaster, oldmaster,
DEVCHANGE_POINTER_EVENT | DEVCHANGE_KEYBOARD_EVENT);
XISendDeviceChangedEvent(oldmaster, oldmaster,
(DeviceChangedEvent*)event->event);
FreeEventList(event, 1);

View File

@ -187,7 +187,8 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator,
void
CreateClassesChangedEvent(EventList* event,
DeviceIntPtr master,
DeviceIntPtr slave)
DeviceIntPtr slave,
int type)
{
int i;
DeviceChangedEvent *dce;
@ -200,6 +201,7 @@ CreateClassesChangedEvent(EventList* event,
dce->length = sizeof(DeviceChangedEvent);
dce->type = ET_DeviceChanged;
dce->time = ms;
dce->flags = type;
if (master->last.slave)
{
dce->flags |= DEVCHANGE_HAS_OLD_SLAVE;
@ -605,12 +607,13 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
*
* @param events Pointer to a pre-allocated event list.
* @param dev The slave device that generated an event.
* @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
* @param num_events The current number of events, returns the number of
* events if a DCCE was generated.
* @return The updated @events pointer.
*/
static EventListPtr
updateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events)
updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
{
DeviceIntPtr master;
@ -618,7 +621,7 @@ updateFromMaster(EventListPtr events, DeviceIntPtr dev, int *num_events)
if (master && master->last.slave != dev)
{
CreateClassesChangedEvent(events, master, dev);
CreateClassesChangedEvent(events, master, dev, type);
updateSlaveDeviceCoords(master, dev);
master->last.slave = dev;
master->last.numValuators = dev->last.numValuators;
@ -852,7 +855,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
num_events = 1;
events = updateFromMaster(events, pDev, &num_events);
events = updateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
/* Handle core repeating, via press/release/press/release. */
if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
@ -1021,7 +1024,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
(type == MotionNotify && num_valuators <= 0))
return 0;
events = updateFromMaster(events, pDev, &num_events);
events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
raw = (RawDeviceEvent*)events->event;
events++;
@ -1134,7 +1137,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
(num_valuators + first_valuator) > pDev->valuator->numAxes)
return 0;
events = updateFromMaster(events, pDev, &num_events);
events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
event = (DeviceEvent *) events->event;
init_event(pDev, event, GetTimeInMillis());

View File

@ -115,6 +115,10 @@ typedef struct
/* Flags used in DeviceChangedEvent to signal if new/old slave is present. */
#define DEVCHANGE_HAS_OLD_SLAVE 0x1
#define DEVCHANGE_HAS_NEW_SLAVE 0x2
/* Flags used in DeviceChangedEvent to signal whether the event was a
* pointer event or a keyboard event */
#define DEVCHANGE_POINTER_EVENT 0x4
#define DEVCHANGE_KEYBOARD_EVENT 0x8
/**
* Sent whenever a device's capabilities have changed.
@ -126,7 +130,8 @@ typedef struct
int length; /**< Length in bytes */
Time time; /**< Time in ms */
int deviceid; /**< Device whose capabilities have changed */
int flags; /**< Mask of ::HAS_OLD_SLAVE or ::HAS_NEW_SLAVE */
int flags; /**< Mask of ::HAS_OLD_SLAVE, ::HAS_NEW_SLAVE,
::POINTER_EVENT, ::KEYBOARD_EVENT */
/** If flags & HAS_OLD_SLAVE is set, old_slaveid specifies SD previously
* attached to this device. */
int old_slaveid;

View File

@ -412,7 +412,8 @@ extern _X_EXPORT void FreeEventList(EventListPtr list, int num_events);
extern void CreateClassesChangedEvent(EventListPtr event,
DeviceIntPtr master,
DeviceIntPtr slave);
DeviceIntPtr slave,
int type);
extern int GetPointerEvents(
EventListPtr events,
DeviceIntPtr pDev,
@ -480,7 +481,8 @@ extern int AllocDevicePair(ClientPtr client,
DeviceIntPtr* keybd,
Bool master);
extern void DeepCopyDeviceClasses(DeviceIntPtr from,
DeviceIntPtr to);
DeviceIntPtr to,
DeviceChangedEvent *dce);
/* Helper functions. */
extern int generate_modkeymap(ClientPtr client, DeviceIntPtr dev,

View File

@ -221,11 +221,10 @@ extern _X_EXPORT void mieqProcessInputEvents(
void
);
extern void CopyGetMasterEvent(
DeviceIntPtr /* mdev */,
extern DeviceIntPtr CopyGetMasterEvent(
DeviceIntPtr /* sdev */,
InternalEvent* /* original */,
EventListPtr /* master */
EventListPtr /* mlist */
);
/**

View File

@ -307,28 +307,53 @@ FixUpEventForMaster(DeviceIntPtr mdev, DeviceIntPtr sdev,
/**
* Copy the given event into master.
* @param mdev The master device
* @param sdev The slave device the original event comes from
* @param original The event as it came from the EQ
* @param master The event after being copied
* @return The master device or NULL if the device is a floating slave.
*/
void
CopyGetMasterEvent(DeviceIntPtr mdev, DeviceIntPtr sdev,
InternalEvent* original, EventListPtr master)
DeviceIntPtr
CopyGetMasterEvent(DeviceIntPtr sdev,
InternalEvent* original, EventListPtr mlist)
{
DeviceIntPtr mdev;
int len = original->any.length;
InternalEvent *mevent;
CHECKEVENT(original);
if (master->evlen < len)
SetMinimumEventSize(master, 1, len);
if (!sdev->u.master)
return NULL;
mevent = (InternalEvent*)master->event;
switch(original->any.type)
{
case ET_KeyPress:
case ET_KeyRelease:
mdev = GetMaster(sdev, MASTER_KEYBOARD);
break;
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_Motion:
case ET_ProximityIn:
case ET_ProximityOut:
mdev = GetMaster(sdev, MASTER_POINTER);
break;
default:
mdev = sdev->u.master;
break;
}
if (mlist->evlen < len)
SetMinimumEventSize(mlist, 1, len);
mevent = (InternalEvent*)mlist->event;
memcpy(mevent, original, len);
ChangeDeviceID(mdev, mevent);
FixUpEventForMaster(mdev, sdev, original, mevent);
return mdev;
}
@ -359,10 +384,7 @@ mieqProcessDeviceEvent(DeviceIntPtr dev,
NewCurrentScreen (dev, DequeueScreen(dev), x, y);
}
else {
master = (!IsMaster(dev) && dev->u.master) ? dev->u.master : NULL;
if (master)
CopyGetMasterEvent(master, dev, event, masterEvents);
master = CopyGetMasterEvent(dev, event, masterEvents);
/* If someone's registered a custom event handler, let them
* steal it. */