summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dix/getevents.c10
-rw-r--r--include/input.h6
-rw-r--r--xkb/xkbActions.c90
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);
}