diff options
-rw-r--r-- | dix/getevents.c | 10 | ||||
-rw-r--r-- | include/input.h | 6 | ||||
-rw-r--r-- | xkb/xkbActions.c | 90 |
3 files changed, 68 insertions, 38 deletions
diff --git a/dix/getevents.c b/dix/getevents.c index a9b6e82c3..20bcf7e8a 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -652,8 +652,8 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, * events if a DCCE was generated. * @return The updated @events pointer. */ -static EventListPtr -updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) +EventListPtr +UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events) { DeviceIntPtr master; @@ -929,7 +929,7 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, num_events = 1; - events = updateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &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)) { @@ -1091,7 +1091,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, (type == MotionNotify && num_valuators <= 0)) return 0; - events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); + events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); raw = (RawDeviceEvent*)events->event; events++; @@ -1206,7 +1206,7 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, (num_valuators + first_valuator) > pDev->valuator->numAxes) return 0; - events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); + events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); event = (DeviceEvent *) events->event; init_event(pDev, event, GetTimeInMillis()); diff --git a/include/input.h b/include/input.h index 55b1537f6..ffb1c33fa 100644 --- a/include/input.h +++ b/include/input.h @@ -439,6 +439,12 @@ extern void CreateClassesChangedEvent(EventListPtr event, DeviceIntPtr master, DeviceIntPtr slave, int type); +extern EventListPtr UpdateFromMaster( + EventListPtr events, + DeviceIntPtr pDev, + int type, + int *num_events); + extern _X_EXPORT int GetPointerEvents( EventListPtr events, DeviceIntPtr pDev, diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index eea3d4adf..c36dba0b5 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -1332,35 +1332,53 @@ xkbStateNotify sn; return; } +/* + * The event is injected into the event processing, not the EQ. Thus, + * ensure that we restore the master after the event sequence to the + * original set of classes. Otherwise, the master remains on the XTEST + * classes and drops events that don't fit into the XTEST layout (e.g. + * events with more than 2 valuators). + * + * FIXME: EQ injection in the processing stage is not designed for, so this + * is a rather awkward hack. The event list returned by GetPointerEvents() + * and friends is always prefixed with a DCE if the last _posted_ device was + * different. For normal events, this sequence then resets the master during + * the processing stage. Since we inject the PointerKey events in the + * processing stage though, we need to manually reset to restore the + * previous order, because the events already in the EQ must be sent for the + * right device. + * So we post-fix the event list we get from GPE with a DCE back to the + * previous slave device. + * + * First one on drinking island wins! + */ static void -XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) +InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int num_valuators, int *valuators) { + ScreenPtr pScreen; EventListPtr events; int nevents, i; - DeviceIntPtr ptr; - ScreenPtr pScreen; + DeviceIntPtr ptr, mpointer, lastSlave; Bool saveWait; - int gpe_flags = 0; - if (IsMaster(dev)) - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); - else if (!dev->u.master) + if (IsMaster(dev)) { + mpointer = GetMaster(dev, MASTER_POINTER); + lastSlave = mpointer->u.lastSlave; + ptr = GetXTestDevice(mpointer); + } else if (!dev->u.master) ptr = dev; else return; - if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) - gpe_flags = POINTER_ABSOLUTE; - else - gpe_flags = POINTER_RELATIVE; - events = InitEventList(GetMaximumEventsNum()); + events = InitEventList(GetMaximumEventsNum() + 1); OsBlockSignals(); pScreen = miPointerGetScreen(ptr); saveWait = miPointerSetWaitForUpdate(pScreen, FALSE); - nevents = GetPointerEvents(events, ptr, - MotionNotify, 0, - gpe_flags, 0, 2, (int[]){x, y}); + nevents = GetPointerEvents(events, ptr, type, button, flags, 0, + num_valuators, valuators); + if (IsMaster(dev) && (lastSlave && lastSlave != ptr)) + UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents); miPointerSetWaitForUpdate(pScreen, saveWait); OsReleaseSignals(); @@ -1368,13 +1386,29 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); FreeEventList(events, GetMaximumEventsNum()); + +} + +static void +XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) +{ + int gpe_flags = 0; + + /* ignore attached SDs */ + if (!IsMaster(dev) && GetMaster(dev, MASTER_POINTER) != NULL) + return; + + if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) + gpe_flags = POINTER_ABSOLUTE; + else + gpe_flags = POINTER_RELATIVE; + + InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, 2, (int[]){x, y}); } void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) { - EventListPtr events; - int nevents, i; DeviceIntPtr ptr; /* If dev is a slave device, and the SD is attached, do nothing. If we'd @@ -1385,24 +1419,14 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) * if dev is a floating slave, post through the device itself. */ - if (IsMaster(dev)) - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); - else if (!dev->u.master) + if (IsMaster(dev)) { + DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER); + ptr = GetXTestDevice(mpointer); + } else if (!dev->u.master) ptr = dev; else return; - events = InitEventList(GetMaximumEventsNum()); - OsBlockSignals(); - nevents = GetPointerEvents(events, ptr, - press ? ButtonPress : ButtonRelease, button, - 0 /* flags */, 0 /* first */, - 0 /* num_val */, NULL); - OsReleaseSignals(); - - - for (i = 0; i < nevents; i++) - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); - - FreeEventList(events, GetMaximumEventsNum()); + InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease, + button, 0, 0, NULL); } |