summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMihail Konev <k.mvc@ya.ru>2017-01-04 07:08:51 +0500
committerPeter Hutterer <peter.hutterer@who-t.net>2017-01-04 13:23:31 +1000
commit9d32b71c93cf6187e9320c99ae857e34a51b7102 (patch)
tree004ab764b8afe1b9b3849d0ef1892518e02f5f01
parent29a4f3db60fdeaef7bca3aa2746bb43a1850fddd (diff)
xkb: Match key releases with an overlaid press
Testcase: In ~/.xbindkeysrc: "xterm &" XF86LaunchA In ~/ov.xkb: xkb_keymap { xkb_keycodes { include "evdev" }; xkb_types { include "complete" }; xkb_compat { include "complete" interpret Overlay1_Enable+AnyOfOrNone(all) { action= SetControls(controls=Overlay1); }; }; xkb_symbols { include "pc+inet(evdev)+us" key <INS> { [ Overlay1_Enable ] }; key <AE01> { overlay1 = <AE02> }; // Insert+1 => 2 key <TLDE> { overlay1 = <I128> }; // Insert+~ => XF86LaunchA }; xkb_geometry { include "pc(pc104)" }; }; Apply this layout: 'xkbcomp ~/ov.xkb $DISPLAY'. Run "xbindkeys -n -v" In the exact order: - press Insert - press Tilde - release Insert - wait - release Tilde Keyboard input in the new terminal window(s) would be locked until another Insert+Tilde . Reported-by: Mariusz Mazur <mariusz.g.mazur@gmail.com> Signed-off-by: Mihail Konev <k.mvc@ya.ru> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r--include/xkbsrv.h2
-rw-r--r--xkb/xkbInit.c9
-rw-r--r--xkb/xkbPrKeyEv.c29
3 files changed, 32 insertions, 8 deletions
diff --git a/include/xkbsrv.h b/include/xkbsrv.h
index 6e4ad44d4..2870f3987 100644
--- a/include/xkbsrv.h
+++ b/include/xkbsrv.h
@@ -195,6 +195,8 @@ typedef struct _XkbSrvInfo {
XkbFilterPtr filters;
XkbSrvCheckRepeatPtr checkRepeat;
+
+ char overlay_perkey_state[256/8]; /* bitfield */
} XkbSrvInfoRec, *XkbSrvInfoPtr;
#define XkbSLI_IsDefault (1L<<0)
diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c
index 9c772f549..46016aba5 100644
--- a/xkb/xkbInit.c
+++ b/xkb/xkbInit.c
@@ -505,6 +505,13 @@ XkbInitControls(DeviceIntPtr pXDev, XkbSrvInfoPtr xkbi)
return Success;
}
+static Status
+XkbInitOverlayState(XkbSrvInfoPtr xkbi)
+{
+ memset(xkbi->overlay_perkey_state, 0, sizeof(xkbi->overlay_perkey_state));
+ return Success;
+}
+
static Bool
InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
const char *keymap, int keymap_length,
@@ -608,6 +615,8 @@ InitKeyboardDeviceStructInternal(DeviceIntPtr dev, XkbRMLVOSet * rmlvo,
XkbInitIndicatorMap(xkbi);
+ XkbInitOverlayState(xkbi);
+
XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &changes,
&check, &cause);
diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c
index f7a6b4b14..d2c7e33f4 100644
--- a/xkb/xkbPrKeyEv.c
+++ b/xkb/xkbPrKeyEv.c
@@ -121,20 +121,33 @@ XkbProcessKeyboardEvent(DeviceEvent *event, DeviceIntPtr keybd)
case XkbKB_Overlay2:
{
unsigned which;
+ unsigned overlay_active_now;
+ unsigned is_keyrelease = (event->type == ET_KeyRelease) ? 1 : 0;
+ /* Remembers whether the key was pressed while overlay was down,
+ * for when overlay is already released, but the key is not. */
+ unsigned key_was_overlaid = 0;
if (behavior.type == XkbKB_Overlay1)
which = XkbOverlay1Mask;
else
which = XkbOverlay2Mask;
- if ((xkbi->desc->ctrls->enabled_ctrls & which) == 0)
- break;
- if ((behavior.data >= xkbi->desc->min_key_code) &&
- (behavior.data <= xkbi->desc->max_key_code)) {
+ overlay_active_now = (xkbi->desc->ctrls->enabled_ctrls & which) ? 1 : 0;
+
+ if ((unsigned char)key == key) {
+ key_was_overlaid = BitIsOn(xkbi->overlay_perkey_state, key);
+ if (!is_keyrelease) {
+ if (overlay_active_now)
+ SetBit(xkbi->overlay_perkey_state, key);
+ } else {
+ if (key_was_overlaid)
+ ClearBit(xkbi->overlay_perkey_state, key);
+ }
+ }
+
+ if ((overlay_active_now || key_was_overlaid) &&
+ (behavior.data >= xkbi->desc->min_key_code) &&
+ (behavior.data <= xkbi->desc->max_key_code)) {
event->detail.key = behavior.data;
- /* 9/11/94 (ef) -- XXX! need to match release with */
- /* press even if the state of the */
- /* corresponding overlay control */
- /* changes while the key is down */
}
}
break;