ports/178170: [patch] xdb misbehaviour on keyboard layouts switch
Eugene Grosbein
eugen at grosbein.net
Fri Apr 26 05:10:01 UTC 2013
>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 at 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:
More information about the freebsd-ports-bugs
mailing list