Is there any good way to do that without having to list all of the currently undefined combos?
Você deve entender que não é simplesmente "bloquear qualquer combinação desconhecida". Você provavelmente não quer bloquear coisas como Controle - R que permite reverter o histórico do seu shell, ou Controlar - P que abre o diálogo de impressão na sua suíte de escritório favorita.
Com isso dito, a maneira mais limpa de atingir seu objetivo é redefinir como os atalhos de teclado são procurados no XMonad para que qualquer "não encontrado" se transforme em "bloquear a tela". Infelizmente, o XMonad não oferece essas facilidades ao usuário; você terá que hackear o próprio XMonad.
A próxima melhor coisa que você pode fazer é gerar um mapa de todos os combos de chave válidos, removê-los daqueles que você já definiu e vincular todos os restantes ao comando "bloquear a tela". Felizmente, tudo isso pode ser automatizado.
Suponho que você tenha seu comando de bloqueio de tela definido assim:
lockScreen = spawn "i3lock"
As combinações de chaves consistem em uma máscara e uma chave, todas listadas em Graphics.X11.Types
.
Primeiro, vamos definir uma lista de possíveis máscaras:
masks = [controlMask, mod1Mask]
Aqui eu assumi que você só quer bloquear combos começando com Control e Alt . Existem 8 máscaras, e elas podem ser combinadas, então essa linha pode ser muito mais complicada. No entanto, quanto mais máscaras definirmos aqui, mais cuidadosos devemos ter ao gerar ligações - não queremos bloquear acidentalmente algo importante!
Ok, a próxima parada é a lista de chaves. Eles também estão listados em Graphics.X11.Types
e começam com xK_
. Eles têm o tipo KeySym
, mas o que eles realmente são é Word64
. No entanto, aconselho a não enlouquecer e evitar escrever algo como [0 .. maxBound :: KeySym]
- isso resultará em um mapa enorme que consumirá muita memória.
Então, basta procurar o número de chaves que você deseja cobrir e agrupá-las em pequenas definições. Aqui, por exemplo, eu cubro as chaves mais comuns:
keys :: [KeySym]
keys = [xK_Home .. xK_Num_Lock] ++ -- Cursor control & motion
[xK_KP_Space .. xK_R15] ++ -- Keypad and Function keys
[xK_space .. xK_asciitilde] -- ASCII and such
Agora estamos prontos para definir uma lista de atalhos de teclado:
fallbackKeys = [((mask, key), lockScreen)
| mask <- masks
, key <- keys ]
Isso gerará uma definição de keybind para todas as combinações possíveis de máscaras e chaves fornecidas.
Agora temos que aplicar essas definições à sua configuração.
XMonad.Util.EZConfig
tem um % co_de muito útil % combinator que, dada uma configuração e uma lista de definições de ligação de chaves, adicionará o último ao primeiro, sobrescrevendo definições existentes se houver algum conflito. O que queremos é exatamente o oposto: queremos aplicar additionalKeys
de tal forma que eles preencham apenas lugares indefinidos, deixando keybinds já definidas como elas são. Para conseguir isso, vamos definir outra função:
import qualified Data.Map as M
backupKeys :: XConfig a -> [((ButtonMask, KeySym), X ())] -> XConfig a
backupKeys conf keyList =
conf { keys = \cnf -> M.union (keys conf cnf) (M.fromList keyList) }
Este é um copiar-colar direto de fallbackKeys
, mas os argumentos para additionalKeys
são trocados, resultando no comportamento que queremos. (Veja a documentação Data.Map.union
para entender como isso funciona.)
E agora podemos finalmente usar tudo isso. Algum lugar no seu union
você tem uma linha como esta:
main = xmonad $ def {…} 'additionalKeys' myKeys
Altere da seguinte forma:
main = xmonad $ def {…} 'additionalKeys' myKeys 'backupKeys' fallbackKeys
Recompile e reinicie o XMonad e aproveite suas novas configurações!