[PATCH xserver] XKB: Redirect actions defunct with Gtk3 (XInput?)

wettstein509 at solnet.ch wettstein509 at solnet.ch
Sat Feb 25 11:48:17 PST 2012


When redirect actions are used with Gtk3, Gtk3 complained about
events not holding a GdkDevice.  This was caused by device IDs
not being set for redirect actions.

More seriously, Gtk3 did not receive state changes redirect
actions might specify.  This was because event_set_state in
dix/inpututils.c accesses the prev_state field, but the changes
for the redirect action were only put into the state field.

Signed-off-by: Andreas Wettstein <wettstein509 at solnet.ch>
---
 xkb/xkbActions.c |   28 +++++++++++++++++++++++-----
 1 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index da0bdea..891179b 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -795,7 +795,7 @@ _XkbFilterRedirectKey(	XkbSrvInfoPtr	xkbi,
 {
 DeviceEvent	ev;
 int		x,y;
-XkbStateRec	old;
+XkbStateRec	old, old_prev;
 unsigned	mods,mask;
 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
 ProcessInputProc backupproc;
@@ -803,6 +803,7 @@ ProcessInputProc backupproc;
     /* never actually used uninitialised, but gcc isn't smart enough
      * to work that out. */
     memset(&old, 0, sizeof(old));
+    memset(&old_prev, 0, sizeof(old_prev));
     memset(&ev, 0, sizeof(ev));
 
     if ((filter->keycode!=0)&&(filter->keycode!=keycode))
@@ -814,6 +815,11 @@ ProcessInputProc backupproc;
     ev.time = GetTimeInMillis();
     ev.root_x = x;
     ev.root_y = y;
+    /* redirect actions do not work across devices, therefore the following is
+     * correct: */
+    ev.deviceid = xkbi->device->id;
+    /* filter->priv must be set up by the caller for the initial press. */
+    ev.sourceid = filter->priv;
 
     if (filter->keycode==0) {		/* initial press */
 	if ((pAction->redirect.new_key<xkbi->desc->min_key_code)||
@@ -823,7 +829,6 @@ ProcessInputProc backupproc;
 	filter->keycode = keycode;
 	filter->active = 1;
 	filter->filterOthers = 0;
-	filter->priv = 0;
 	filter->filter = _XkbFilterRedirectKey;
 	filter->upAction = *pAction;
 
@@ -839,6 +844,7 @@ ProcessInputProc backupproc;
 
 	if ( mask || mods ) {
 	    old= xkbi->state;
+	    old_prev= xkbi->prev_state;
 	    xkbi->state.base_mods&= ~mask;
 	    xkbi->state.base_mods|= (mods&mask);
 	    xkbi->state.latched_mods&= ~mask;
@@ -846,15 +852,18 @@ ProcessInputProc backupproc;
 	    xkbi->state.locked_mods&= ~mask;
 	    xkbi->state.locked_mods|= (mods&mask);
 	    XkbComputeDerivedState(xkbi);
+	    xkbi->prev_state= xkbi->state;
 	}
 
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
 	xkbi->device->public.processInputProc((InternalEvent*)&ev, xkbi->device);
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
 				     backupproc,xkbUnwrapProc);
-	
-	if ( mask || mods )
+
+	if ( mask || mods ) {
 	    xkbi->state= old;
+	    xkbi->prev_state= old_prev;
+	}
     }
     else if (filter->keycode==keycode) {
 
@@ -870,6 +879,7 @@ ProcessInputProc backupproc;
 
 	if ( mask || mods ) {
 	    old= xkbi->state;
+	    old_prev= xkbi->prev_state;
 	    xkbi->state.base_mods&= ~mask;
 	    xkbi->state.base_mods|= (mods&mask);
 	    xkbi->state.latched_mods&= ~mask;
@@ -877,6 +887,7 @@ ProcessInputProc backupproc;
 	    xkbi->state.locked_mods&= ~mask;
 	    xkbi->state.locked_mods|= (mods&mask);
 	    XkbComputeDerivedState(xkbi);
+	    xkbi->prev_state= xkbi->state;
 	}
 
 	UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc);
@@ -884,8 +895,10 @@ ProcessInputProc backupproc;
 	COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr,
 				     backupproc,xkbUnwrapProc);
 
-	if ( mask || mods )
+	if ( mask || mods ) {
 	    xkbi->state= old;
+	    xkbi->prev_state= old_prev;
+	}
 
 	filter->keycode= 0;
 	filter->active= 0;
@@ -1155,6 +1168,11 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
 		    break;
 		case XkbSA_RedirectKey:
 		    filter = _XkbNextFreeFilter(xkbi);
+		    /* redirect actions must create a new DeviceEvent.  The
+		     * source device id for this event cannot be obtained from
+		     * xkbi, so we pass it here explicitly. The field deviceid
+		     * equals to xkbi->device->id. */
+		    filter->priv = event->sourceid;
 		    sendEvent= _XkbFilterRedirectKey(xkbi,filter,key,&act);
 		    break;
 		case XkbSA_DeviceBtn:
-- 
1.7.6



More information about the xorg-devel mailing list