XMonad: Есть ли способ привязать одновременно срабатывающий кейкорд?

Есть ли способ сделать одновременные нажатия клавиш в привязке клавиш, например. для клавиш w, e, f, при нажатии которых с интервалом в 0,05 секунды друг от друга запускалась команда?

Чтобы быть более конкретным:

  1. Если w, e, f нажаты в пределах 0,05 секунды друг от друга, то при нажатии последней XMonad должен вызвать указанную команду . XMonad тоже должен был перехватить три ключа, чтобы они не шли лишним в сфокусированное окно.

  2. В противном случае (если хотя бы одна из них не будет нажата в течение 0,05 секунды) XMonad должен отправить клавиши в выделенное окно, как обычно.

Моя цель в этом состоит в том, чтобы использовать w, e, f для "Escape" в vim-подобный "Normal Mode", XMonad. Actions.Submap (подкарта).


Обновите методом failed, если кто-то увидит, как это исправить:

Я попытался реализовать это с помощью подкарт, так что, например, если вы нажмете w, вы попадете в chord_mode_w, если вы нажмете e оттуда, вы попадете в chord_mode_we, и если вы нажмете f оттуда, вы в конце концов окажетесь, например, в normal_mode. Реализация была очень запутанной: я включил в свои основные сочетания клавиш что-то вроде:

("w", spawn "xdotool key <chord_mode_w_keybinding> ; sleep 0.05 ; xdotool key <abort_keybinding>")
(chord_mode_w_keybinding, chord_mode_w)

для обнаружения w (остальное будет аналогичным), а также (неполных) подкарт, таких как:

 chord_mode_w = submap . mkKeymap c $
              [
                      ("e",  chord_mode_we )
                    , ("f",  chord_mode_wf )
                    , (abort_keybinding, pasteString "w")

                    -- in order for the submap to not eat all other letters,
                    -- would need to include all mappings like:
                    , ("a", pasteString "wa")
                    , ("b", pasteString "wb")
                    ...
              ]

 chord_mode_we = submap . mkKeymap c $
               [
                      ("f",  normal_mode )
                    , (abort_keybinding, pasteString "we")


                    -- in order for the submap to not eat all other letters,
                    -- would need to include all mappings like:
                    , ("a", pasteString "wea")
                    , ("b", pasteString "web")
                    ...
               ]

 chord_mode_wf = submap . mkKeymap c $
               [
                      ("e",  normal_mode )
                    , (abort_keybinding, pasteString "wf")

                    -- in order for the submap to not eat all other letters,
                    -- would need to include all mappings like:
                    , ("a", pasteString "wfa")
                    , ("b", pasteString "wfb")
                    ...
               ]

Полная реализация, очевидно, была бы очень грязной, но теоретически должна была отправить меня в normal_mode, если бы я нажимал "wef" в пределах 0,05 секунды друг от друга, прерывая и вводя символы в противном случае. Однако возникли две проблемы:

  1. pasteString (а также другие функции вставки в XMonad.Util.Paste) слишком медленны для обычного набора текста

  2. Я бы оказался в normal_mode лишь в небольшой части времени, даже если бы я установил задержку прерывания намного выше. Не уверен в причине этого.

(Причина, по которой я использовал pasteString при прерывании вместо порождения другого xdotool, заключалась в том, что вывод xdotool повторно запускал один из chord_mode_w_keybinding, chord_mode_e_keybinding, chord_mode_f_keybinding обратно в основные сочетания клавиш, отправляя меня обратно к режимам аккордов на неопределенный срок.)


person spacingissue    schedule 02.01.2015    source источник
comment
Не хочу показаться высокомерным, но, кажется, я не понимаю вашего вопроса. Пример есть в Submap документации. Вы хотите иметь такую ​​задержку (0,05 с), или что конкретно пример вам не дает?   -  person deshtop    schedule 02.01.2015
comment
Я внес правку, которая, надеюсь, прояснит вопрос. Активация подкарты была только тем примером, для которого я хотел ее использовать; вопрос на самом деле в том, как можно было бы сделать привязки клавиш к аккордам.   -  person spacingissue    schedule 03.01.2015


Ответы (1)


https://hackage.haskell.org/package/xmonad-contrib-0.13/docs/XMonad-Actions-Submap.html

Submap действительно делает почти то, что вы хотите (оно дает вам большую часть пути)... и я предлагаю вам немного изменить то, что вы пытаетесь сделать, и то Submaps отлично справляются с этим.

Вы можете настроить Submap для захвата ключевого события w и начать ожидание e, которое затем ожидает f. Я даже попробовал это и подтвердил, что это работает:

, ((0, xK_w), submap . M.fromList $
    [ ((0, xK_e),    submap . M.fromList $
      [ ((0, xK_f),  spawn "notify-send \"wef combo detected!\"" ) ])
    ])

Тем не менее, вышеизложенное почти наверняка не то, что вы на самом деле хотели бы сделать ... поскольку теперь невозможно отправить нажатие клавиши w в окно (мне пришлось отключить эту конфигурацию перед вводом этого ответа, что потребовало отправки нескольких нажатий клавиши w события в активное окно)

Поведение, которое я только что увидел, играя с этим, таково: если я нажимаю w, xmonad перехватывает это событие (не отправляет его в активное окно) и теперь находится в состоянии, когда он ожидает либо e, либо чего-то еще... если я нажимаю что-то еще, xmonad больше не находится в этом состоянии, но он не «воспроизводит» эти пойманные события. Поэтому, если я нажму w, а затем какую-нибудь другую клавишу, отличную от e, результатом будет только то, что xmonad вернется из состояния прослушивания ключей в подкарте. Он никогда не пропускает w к активному окну... что мне показалось неудобным.

Ваши варианты, как я это вижу: 1) согласиться на начальную привязку клавиш с модификатором, поэтому ваша многоклавишная команда будет Mod4-w e f 2) найти способ взломать логику задержки, которую вы описали, в действие на подкарте

Я начал использовать такой конфиг, где я вложил концептуально похожие действия, которые нечасто нужны, в дерево вложенных подкарт, аналогично тому, что я вставил выше. Однако корень этого дерева всегда имеет модификатор, поэтому он не крадет нажатия клавиш, которые я хочу перенаправить в активное окно. Я использую Mod3-semicolon в качестве корня этого дерева, а затем есть много немодифицированных нажатий клавиш, которые являются просто буквами (это мнемоники для действий).

Мне это кажется лучшим решением, чем ждать несколько сотен миллисекунд, а затем пересылать события, если они не совпадают. Я чувствую, что это раздражает, так как это задерживает любое событие нажатия клавиши w...

YMMV, надеюсь, это кому-то поможет

person Blake Miller    schedule 15.08.2015
comment
Это действительно полезно! Однако у меня возникает проблема при определении нескольких комбинаций, начинающихся с одного и того же ключа: работает только последняя указанная комбинация, все остальные игнорируются - в чем может быть проблема? - person user905686; 31.08.2017
comment
То, что вы описываете, у меня работает. Могу ли я предложить вам задать новый вопрос и опубликовать код, который вы используете? Я думаю, что пока первый ключ привязан к подкарте (как в моем примере), он должен работать. Если вы прокомментируете здесь ссылку на свой вопрос, я постараюсь помочь. - person Blake Miller; 12.09.2017
comment
Спасибо, я разместил новый вопрос. - person user905686; 14.09.2017
comment
Обратите внимание, что есть submapDefaultWithKey, который можно использовать для ручного воспроизведения ключевых событий, когда на подкарте не было совпадений. Тем не менее, это все равно оставит проблему, заключающуюся в том, что вы не можете ввести wef. - person marzipankaiser; 20.03.2020