Date: Fri, 26 Apr 2013 12:03:04 +0700 (NOVT) From: Eugene Grosbein <eugen@grosbein.net> To: FreeBSD-gnats-submit@freebsd.org Subject: ports/178170: [patch] xdb misbehaviour on keyboard layouts switch Message-ID: <201304260503.r3Q534wR068482@eg.sd.rdtc.ru> Resent-Message-ID: <201304260510.r3Q5A1ip092730@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 178170 >Category: ports >Synopsis: [patch] xdb misbehaviour on keyboard layouts switch >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Apr 26 05:10:00 UTC 2013 >Closed-Date: >Last-Modified: >Originator: Eugene Grosbein >Release: FreeBSD 8.4-BETA1 amd64 >Organization: RDTC JSC >Environment: System: FreeBSD eg.sd.rdtc.ru 8.4-BETA1 FreeBSD 8.4-BETA1 #1: Tue Apr 16 17:55:46 NOVT 2013 root@eg.sd.rdtc.ru:/usr/local/obj/usr/local/src/sys/EG amd64 >Description: The problem described here is exactly identical to https://bugs.freedesktop.org/show_bug.cgi?id=865 In short, xkb switches keyboard layouts on press of switching key combination. This breaks application hotkeys like Ctrl-Shift-A when your layout switching key combo is Ctrl-Shift. xkb should switch layouts on key release, not press, like Windows GUI does. >How-To-Repeat: The section in xorg.conf: Section "InputDevice" Identifier "Keyboard0" Driver "kbd" Option "XkbRules" "xorg" Option "XkbModel" "pc105" Option "XkbLayout" "us,ru" Option "XkbVariant" "winkeys" Option "XkbOptions" "grp:ctrl_shift_toggle" EndSection For example, you cannot use Ctrl-Shift-A in Firefox with such config. >Fix: The patch taken from mentioned freedesktop.org bug solves the problem by changing xkb behaviour to switch layouts on key release. https://bugs.freedesktop.org/attachment.cgi?id=33142 The patch should be added to ports tree as ports/x11-servers/xorg-server/files/patch-xkbActions.c --- xkb/xkbActions.c +++ xkb/xkbActions.c @@ -325,24 +325,83 @@ _XkbFilterLatchState( XkbSrvInfoPtr xkbi, return 1; } +static int xkbSwitchGroupOnRelease(void) +{ + /* TODO: user configuring */ + return TRUE; +} + +static void xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction* pAction) +{ + XkbGroupAction ga = pAction->group; + if (ga.flags&XkbSA_GroupAbsolute) + xkbi->state.locked_group= XkbSAGroup(&ga); + else xkbi->state.locked_group+= XkbSAGroup(&ga); +} + +static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi); + static int -_XkbFilterLockState( XkbSrvInfoPtr xkbi, +_XkbFilterLockGroup( XkbSrvInfoPtr xkbi, XkbFilterPtr filter, unsigned keycode, XkbAction * pAction) { - if (pAction&&(pAction->type==XkbSA_LockGroup)) { - if (pAction->group.flags&XkbSA_GroupAbsolute) - xkbi->state.locked_group= XkbSAGroup(&pAction->group); - else xkbi->state.locked_group+= XkbSAGroup(&pAction->group); - return 1; + int sendEvent = 1; + + if (!xkbSwitchGroupOnRelease()) { + xkbUpdateLockedGroup(xkbi, pAction); + return sendEvent; + } + + /* Delay switch till button release */ + if (filter->keycode==0) { /* initial press */ + filter->keycode = keycode; + filter->active = 1; + filter->filterOthers = 0; /* for what? */ + filter->filter = _XkbFilterLockGroup; + + /* filter->priv = 0; */ + filter->upAction = *pAction; + + /* Ok, now we need to simulate the action which would go if this action didn't block it. + XkbSA_SetMods is the one: it is to set modifier' flag up. */ + { + XkbStateRec fake_state = xkbi->state; + XkbAction act; + + fake_state.mods = 0; + act = XkbGetKeyAction(xkbi, &fake_state, keycode); + + /* KLUDGE: XkbSA_SetMods only? */ + if (act.type == XkbSA_SetMods) { + XkbFilterPtr filter = _XkbNextFreeFilter(xkbi); + sendEvent = _XkbFilterSetState(xkbi,filter,keycode,&act); + } + } } + else { + /* do nothing if some button else is pressed */ + if (!pAction) + xkbUpdateLockedGroup(xkbi, &filter->upAction); + filter->active = 0; + } + + return sendEvent; +} + +static int +_XkbFilterLockMods( XkbSrvInfoPtr xkbi, + XkbFilterPtr filter, + unsigned keycode, + XkbAction * pAction) +{ if (filter->keycode==0) { /* initial press */ filter->keycode = keycode; filter->active = 1; filter->filterOthers = 0; filter->priv = 0; - filter->filter = _XkbFilterLockState; + filter->filter = _XkbFilterLockMods; filter->upAction = *pAction; xkbi->state.locked_mods^= pAction->mods.mask; xkbi->setMods = pAction->mods.mask; @@ -1104,9 +1163,12 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act); break; case XkbSA_LockMods: + filter = _XkbNextFreeFilter(xkbi); + sendEvent=_XkbFilterLockMods(xkbi,filter,key,&act); + break; case XkbSA_LockGroup: filter = _XkbNextFreeFilter(xkbi); - sendEvent=_XkbFilterLockState(xkbi,filter,key,&act); + sendEvent=_XkbFilterLockGroup(xkbi,filter,key,&act); break; case XkbSA_ISOLock: filter = _XkbNextFreeFilter(xkbi); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201304260503.r3Q534wR068482>