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 <wettstein...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel