New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add stripModMask to customize cleanMask/extraModifiers #374
base: master
Are you sure you want to change the base?
Conversation
(Unfortunately MIN_VERSION_xmonad has only 3 parameters and adding a cabal flag seems too heavyweight.) Relates: xmonad/xmonad#374 Relates: xmonad/xmonad#172 Relates: xmonad#290
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pinging @kurogetsusai and @ibbem for testing
src/XMonad/Operations.hs
Outdated
smm <- join $ asks $ stripModMask . config | ||
return $ map (foldl' (.|.) 0) (subsequences (bits smm)) | ||
where | ||
bits 0 = [] | ||
bits n = let b = countTrailingZeros n in bit b : bits (n `clearBit` b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Understandable" refers to the implementation or the user interface? I wanted to abstract away the implementation detail that we need to grab all bit combinations and just expose a mask that's directly used in cleanMask
and processed into combinations in here.
You could argue, however, that abstracting the implementation detail is harmful in here, because people who want to not strip numlock will need to manually grab some keys with and without numlock, so abstracting it away will make it harder for them to get the right mental models. Hm, not sure what to do. :-/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue that the fact that key masks are or'd together is an implementation detail in itself, which is not necessarily known to the user (many people don't know what the funnly looking .|.
is doing in their configs :). Intuitively, I would expect an option along the lines of "filter out these modifiers" to take a list of key masks instead of a single one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, that makes sense: 67304e9
Co-authored-by: Tony Zorman <soliditsallgood@mailbox.org>
-- but only when Num Lock is off (or on). Another use case is adding | ||
-- 'mod5Mask' to the list of stripped/irrelevant modifiers. | ||
defaultStripModMask :: X [KeyMask] | ||
defaultStripModMask = gets numberlockMask <&> \numLockMask -> [lockMask, numLockMask] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is gets ((:[lockMask]) . numberlockMask)
better? I don't know. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think one is more obscure than the other, so feel free to pick the one you like best :)
-- but only when Num Lock is off (or on). Another use case is adding | ||
-- 'mod5Mask' to the list of stripped/irrelevant modifiers. | ||
defaultStripModMask :: X [KeyMask] | ||
defaultStripModMask = gets numberlockMask <&> \numLockMask -> [lockMask, numLockMask] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think one is more obscure than the other, so feel free to pick the one you like best :)
I currently try to test this change, but while updating my configuration I'm stuck with trying to figure out how to bind a key while numlock is active. The problem is, that the numlock mask is determined during the startup of xmonad, so it is not available at configuration time. (I also tried to run the numlock extraction code before the configuration code, but for that I would have to open a X connection.) import XMonad
import XMonad.Util.CustomKeys
main :: IO ()
main =
xmonad
def
{ stripModMask = lockMask,
keys =
customKeys (const []) $
\XConfig {modMask = modMask} ->
[ ((modMask, xK_y), xmessage "without numlock"),
((modMask .|. undefined {- how do I obtain the numlock mask? -}, xK_y), xmessage "with numlock")
]
} Is it possible to use a static numlock mask? When does the numlock mask actually change (I saw that it is updated when a When I use different mappings for the caps lock state it works as expected with this configuration: import XMonad
import XMonad.Util.CustomKeys
main :: IO ()
main =
xmonad
def
{ stripModMask = gets numberlockMask,
keys =
customKeys (const []) $
\XConfig {modMask = modMask} ->
[ ((modMask, xK_y), xmessage "without caps lock"),
((modMask .|. lockMask, xK_y), xmessage "with caps lock")
]
} So the actual logic of this change seems to work. For the interface it would probably be a good idea to offer a function (maybe in xmonad-contrib) to ignore a modifier for all other mappings. I'm not exactly sure about the interface for such a function, some quick ideas include: keysWithoutIgnoringModifiers1 :: KeyMask -> [((KeyMask, KeySym), X ())] -> XConfig l -> XConfig l This would automatically remove the modifiers from the stripModMask, duplicate the key mappings from the given config, with and without the modifier, and add the given key mapping unmodified. keysWithoutIgnoringModifiers2 :: KeyMask -> (XConfig Layout -> [((KeyMask, KeySym), X ())]) -> XConfig l -> XConfig l Variation on the above that use a function like the one used for ignoreModifiers :: KeyMask -> [((KeyMask, KeySym), X ())] -> [((KeyMask, KeySym), X ())] This would only duplicate the key mappings with and without the modifier. Note that it is unnecessary to adapt this one to use a function like Usage of these would look like: import XMonad
import XMonad.Util.CustomKeys
main :: IO ()
main =
xmonad
$ keysWithoutIgnoringModifiers2 lockMask (\XConfig {modMask = modMask} ->
[ ((modMask, xK_y), xmessage "without caps lock"),
((modMask .|. lockMask, xK_y), xmessage "with caps lock")
])
$ def
{ keys =
customKeys (const []) $
\XConfig {modMask = modMask} ->
[ {- some custom keys -} ]
} or import XMonad
import XMonad.Util.CustomKeys
main :: IO ()
main =
xmonad
def
{ stripModMask = gets numberlockMask,
keys =
customKeys (const []) $
\XConfig {modMask = modMask, workspaces = workspaces} ->
ignoreModifiers lockMask
[ {- some other key bindings -} ]
++
[ ((modMask, xK_y), xmessage "without caps lock"),
((modMask .|. lockMask, xK_y), xmessage "with caps lock")
]
} I think I prefer |
Description
Added
stripModMask
to allow customizing which modifiers are irrelevant for key bindings. Useful for binding numpad keys only when Num Lock is off, or to make Mod5 irrelevant in addition to the default Num/Caps Lock.Fixes: #172
Relates: xmonad/xmonad-contrib#290
Checklist
I've read CONTRIBUTING.md
I've confirmed these changes don't belong in xmonad-contrib instead
I've considered how to best test these changes (property, unit, manually, ...) and concluded: I'm hoping that someone who requested this in Key bindings ignore numlock state #172 will test it manually :-)
I updated the
CHANGES.md
file