diff --git a/Xi/exevents.c b/Xi/exevents.c index 884fe724d..a72fb8498 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -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); } diff --git a/dix/devices.c b/dix/devices.c index c94e93518..6266b63f5 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -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); diff --git a/dix/getevents.c b/dix/getevents.c index 40cf4cab5..fa3c7817b 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -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()); diff --git a/include/events.h b/include/events.h index cc5092ee4..d44188b67 100644 --- a/include/events.h +++ b/include/events.h @@ -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; diff --git a/include/input.h b/include/input.h index 194dbebc5..437b392ff 100644 --- a/include/input.h +++ b/include/input.h @@ -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, diff --git a/mi/mi.h b/mi/mi.h index 182cea593..4431239cf 100644 --- a/mi/mi.h +++ b/mi/mi.h @@ -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 */ ); /** diff --git a/mi/mieq.c b/mi/mieq.c index d094e1313..7ba755c29 100644 --- a/mi/mieq.c +++ b/mi/mieq.c @@ -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. */