X.A.{Grid,Tree}Select: Fix keybindings in secondary kbd layouts

We didn't clean XKB group bits out of the KeyPress events' state so key
bindings only worked in the primary keyboard layout (first XKB group).
To fix this, this adds a `cleanKeyMask` function to X.Prelude which is
analogous to `cleanMask` but aimed at cleaning regular KeyPress states
(as opposed to just KeyPresses from passive key grabs), and this is then
used instead of `cleanMask`.

Related: https://github.com/xmonad/xmonad-contrib/issues/290
Related: https://github.com/xmonad/xmonad-contrib/pull/590
This commit is contained in:
Tomas Janousek 2022-02-09 23:53:16 +00:00
parent 2e3254a908
commit adced0a8c8
3 changed files with 18 additions and 2 deletions

View File

@ -409,7 +409,7 @@ makeXEventhandler keyhandler = fix $ \me -> join $ liftX $ withDisplay $ \d -> l
then do then do
(ks,s) <- lookupString $ asKeyEvent e (ks,s) <- lookupString $ asKeyEvent e
return $ do return $ do
mask <- liftX $ cleanMask (ev_state ev) mask <- liftX $ cleanKeyMask <*> pure (ev_state ev)
keyhandler (fromMaybe xK_VoidSymbol ks, s, mask) keyhandler (fromMaybe xK_VoidSymbol ks, s, mask)
else else
return $ stdHandle ev me return $ stdHandle ev me

View File

@ -535,7 +535,7 @@ navigate = gets tss_display >>= \d -> join . liftIO . allocaXEvent $ \e -> do
if | ev_event_type ev == keyPress -> do if | ev_event_type ev == keyPress -> do
(ks, _) <- lookupString $ asKeyEvent e (ks, _) <- lookupString $ asKeyEvent e
return $ do return $ do
mask <- liftX $ cleanMask (ev_state ev) mask <- liftX $ cleanKeyMask <*> pure (ev_state ev)
f <- asks ts_navigate f <- asks ts_navigate
fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f fromMaybe navigate $ M.lookup (mask, fromMaybe xK_VoidSymbol ks) f
| ev_event_type ev == buttonPress -> do | ev_event_type ev == buttonPress -> do

View File

@ -24,6 +24,7 @@ module XMonad.Prelude (
safeGetWindowAttributes, safeGetWindowAttributes,
keyToString, keyToString,
keymaskToString, keymaskToString,
cleanKeyMask,
) where ) where
import Foreign (alloca, peek) import Foreign (alloca, peek)
@ -116,3 +117,18 @@ keymaskToString numLockMask msk =
-- pair, into a string. -- pair, into a string.
keyToString :: (KeyMask, KeySym) -> [Char] keyToString :: (KeyMask, KeySym) -> [Char]
keyToString = uncurry (++) . bimap (keymaskToString 0) keysymToString keyToString = uncurry (++) . bimap (keymaskToString 0) keysymToString
-- | Strip numlock, capslock, mouse buttons and XKB group from a 'KeyMask',
-- leaving only modifier keys like Shift, Control, Super, Hyper in the mask
-- (hence the \"Key\" in \"cleanKeyMask\").
--
-- Core's 'cleanMask' only strips the first two because key events from
-- passive grabs (key bindings) are stripped of mouse buttons and XKB group by
-- the X server already for compatibility reasons. For more info, see:
-- <https://www.x.org/releases/X11R7.7/doc/kbproto/xkbproto.html#Delivering_a_Key_or_Button_Event_to_a_Client>
cleanKeyMask :: X (KeyMask -> KeyMask)
cleanKeyMask = cleanKeyMask' <$> gets numberlockMask
cleanKeyMask' :: KeyMask -> KeyMask -> KeyMask
cleanKeyMask' numLockMask mask =
mask .&. complement (numLockMask .|. lockMask) .&. (button1Mask - 1)