В этой статье я бы хотел поговорить об изменении клавиш на клавиатуре. Сперва это была короткая заметка, но со временем текст вырос во что-то большее. Оказалось, есть что сказать по теме.

Вообще, я не стремлюсь менять клавиши и затачивать программы под себя. Разработчики предлагают удобные схемы, и в целом удобно, когда вы работаете на стандартных настройках. Всё же, годы за клавиатурой подталкивают к некоторым изменениям.

Главный довод в пользу изменения клавиш — физиология. У людей разная форма кистей и длина пальцев. Невозможно выпустить клавиатуру, которая подошла бы всем людям. Именно физиология и чуткое внимание к ощущениям подсказывают, что менять что-то нужно, иначе — боль в суставах.

Одно время я увлекался эргономичными клавиатурами, но быстро разочаровался в них. За огромные деньги мы получим поделие Франкенштейна: огромных размеров, тяжелое, неудобное. Такая клавиатура полностью меняет рабочее пространство, заставляет кое-что купить в довесок. Её не возьмешь в командировку или на дачу, словом — нет.

Типичные пациенты:

На последней картинке – Microsoft Sculpt. Я пользовался ей полгода, но страшно заболела левая рука.

Сам я предпочитаю внешнюю клавиатуру Эпла: маленькая, лёгкая, без проводов. Заряда хватает на месяц. Бросил в рюкзак и неси в любое место. Метал, а не пластик. Тип кнопок на ней не тот, что в последних прошках, но всё равно удобно.

Конечно, кому-то нужны кастомные эргономичные эти клавиатуры, но я решил проблему простым способом — переназначением клавиш.

Простой способ поменять клавиши на Маке — открыть настройки клавиатуры. На первой вкладке внизу кнопка “Modifier Keys…”. Откроется диаложек, где можно указать, что на что заменить. Работает без перезагрузки в разрезе устройства. Однако этот способ подойдёт только неискушенным пользователям.

Первая проблема в том, что что среди доступных клавишей нет шифта. Это довольно странно: капс, контрол, альт и прочие доступны, а шифт — нет. Видимо, положение шифта кажется настолько “нормальным”, что разработчики решили: а что его менять? И не добавили в список. Что ж, трогать исходный шифт я и не собирался. Но назначить другой кнопке функцию шифта тоже нельзя, что очень печально.

Вторая проблема — диалог не различает правые и левые кнопки. Даже быстрый взгляд на клавиатуру доказывает, что она не симметрична, и поэтому у людей могут быть предпочтения из-за физиологии. У меня именно тот случай — правый и левый Command ведут себя по-разному (причину объясню ниже). Из-за обеих причин стандартный диалог мне не подошёл.

Под Мак написана программа Karabiner Elements (в прошлом — просто Karabiner). Это убер-комбайн, с помощью которого можно переназначить что угодно, в том числе задать хитрые комбинации и комбо. Например, медленное нажатие, быстрое, связку конкретных клавиш и прочее. Я долго им пользовался, и вот что меня смущало.

Во-первых, Karabiner явно испытывает трудности с операционной системой. Пару лет назад программа радикально обновилась как раз из-за изменений в Маке (то ли в Каталине, то ли другой версии, неважно). Во-вторых, я частенько ловил баги с клавиатурой, которые смутно указывали на Karabiner, и это стало напрягать.

Например, после выхода из сна клавиатура порой не работала — как внешняя, так встроенная в ноут. Или внизу экрана всплывало уведомление, что Karabiner не заработает, пока не нажмёшь такую-то кнопку. Эти баги трудно описать, потому что обычно на них нет времени, плюс поведение то одно, то другое. Но чем-то задним чувствуешь: так быть не должно.

Я стал искать замену Karabiner, и нашёл на удивление быстро. Нужно было только погуглить.

Встроенная утилита hidutil предлагает доступ к устройствам ввода. Это CLI-обертка над фреймворком HIDDriverKit. Аббревиатура HID означает Human Interface Device. Судя по документации, она доступна с версии ОС 10.15+, но я не проверял.

Hidutil читает и записывает свойства устройств. Нас интересует свойство UserKeyMapping — переназначение клавиш. Посмотреть текущее состояние можно так:

hidutil property --get "UserKeyMapping"

Скорей всего, вы увидите (null) или пустоту, потому что ещё ничего не переназначили.

Чтобы задать правила, укажите ключ --set. За ним следует JSON примерно такой структуры:

{"UserKeyMapping":
  [
    {
      "HIDKeyboardModifierMappingSrc": ...,
      "HIDKeyboardModifierMappingDst": ...
    }
  ]
}

Это массив объектов с полями HIDKeyboardModifierMappingSrc и HIDKeyboardModifierMappingDst, с чего на что менять. Значения — полные коды клавиш. Полный код строится по правилу:

0x700000000 OR <code>

, где <code> — краткий код клавиши. Таблица кодов находится на официальной странице Apple. Название “Keyboard Left/Right GUI” означает Command.

Таким образом, если мы хотим поменять левый Command на Alt, тело --set будет следующим:

{
  "UserKeyMapping": [
    {
      "HIDKeyboardModifierMappingSrc":0x7000000E7,
      "HIDKeyboardModifierMappingDst":0x7000000E6
    }
  ]
}

В ответ утилита покажет новое соответствие клавиш. Его же можно запросить с помощью --get UserKeyMapping:

UserKeyMapping:(
    {
        HIDKeyboardModifierMappingDst = 30064771300;
        HIDKeyboardModifierMappingSrc = 30064771302;
    }
)

Способ работает без перезагрузки, не требует сторонних программ. Судя по всему, он заработает на новом чипе M1, в то время как у Karabiner проблемы с новым Маком. Это лишний раз говорит в пользу hidutils. Не хотелось бы покупать новый Мак и воевать с клавишами, которые внезапно отвалились.

Тот JSON, что вы состряпали, логично поместить куда-нибудь на GitHub или хотя бы в gist, чтобы не набирать с нуля. Вот ссылка на мой файл. Для красоты можно оформить JSON в несколько строк и как-то облагородить, но это в будущем.

Теперь объясню, какие кнопки я меняю на своей машине и какой в этом смысл. Предупреждаю, что это исключительно личный фактор, который ни к чему вас не обязывает. Ни в коем случае не топлю за то, чтобы все делали так же.

Комбинаций на самом деле немного, всего лишь три. Первая — замена Caps на Shift (0x700000039 → 0x7000000E1). Дело вот в чём: если я положу левую руку на WASD, то мизинец находится аккурат над Caps. А чтобы нажать шифт, его нужно спустить вниз. Поскольку шифт нужен примерно в тысячу раз чаще, чем капс, выбор очевиден — нужно повесить шифт на ту кнопку, что находится под мизинцем, чтобы не заставлять его перемещаться.

Да, мы лишаемся капса, но ничуть не сожалею об этом. Любой редактор умеет менять регистр по требованию. Кроме того, такая функция есть даже в главном меню Мака. Про замену капса на шифт я даже писал отдельную заметку.

Вторая комбинация — сменить правый Command на Alt (0x7000000E7 → 0x7000000E6). Должно быть, вы знаете, что я пользуюсь Емаксом. В нём две основные клавиши: Command и Meta, которые кратко обозначаются C и M. Их семантика примерно та же, что и у обычных Command и Alt. Это основная команда для буквенной клавиши (C-p, C-n) и модификация (M-p, M-n).

Обе C и M используются постоянно. Иногда я проделываю долгие комбо с зажатым Command, и большой палец сильно устает. Если добавить сюда Meta, который приходится на Alt, начинается боль в физическом смысле, потому что приходится подгибать палец. Открою интимный факт: два раза в год я делаю массаж спины и шеи, и в какой-то момент пришлось добавить левую кисть — вот до чего дошло.

Идея в том, чтобы максимально разгрузить левую руку. Для этого оставим ей на откуп только левый Command, а Meta повесим на правый Command. Это победа со всех сторон. Во-первых, теперь на C и M давят только большие, самые сильные пальцы. Во-вторых, их не нужно никуда подгибать: кнопки прямо под пальцами.

Третья и последняя замена — повесить на правый Alt функцию Control (0x7000000E6 → 0x7000000E4). Объяснение этому следующее. Мне часто приходится копировать текст из терминала, поэтому в iTerm2 у меня работают обычные комбинации Command-C/V. Возникает вопрос, как послать сигнал Ctrl-C, чтобы завершить процесс. Если вы посмотрите на клавиатуру, то станет ясно — нужно тянуться левым мизинцем к Control, что полный ужас для сустава: кисть поворачивается влево градусов на тридцать.

Мизинец — не лучший палец для комбинаций клавиш, ему можно доверить только одну буквенную. Более лучший способ — поручить Control большому пальцу правой руки. Поскольку правый Command уже занят под Alt из-за Емакса, повесим Control на соседнюю кнопку — правый Alt. Теперь достаточно сместить правый большой палец вправо. Впрочем, это случается редко, потому что на Маке почти все функции Control выполняет Command.

Вот такая у меня раскладка и как я к ней пришёл.

Я пишу этот пост несколько дней и заметил: с удалением Karabiner Elements исчезли подвисания после выхода ноута из сна. Считаю это важными поводом отказаться от программы.

С другой стороны, у hidutils тоже недостаток. Её эффект не сохраняется после перезагрузки машины. Чтобы это исправить, добавьте ваш скрипт в автозагрузку. Это можно сделать несколькими способами:

  1. Открыть “Users & Groups” и выбрать своего пользователя. Во вкладке “Login Items” добавить путь к шелл-скрипту.

  2. Положить в папку ~/Library/LaunchAgents файл user.ivan.remap.plist примерно такого содержания:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
   <key>Label</key>
   <string>user.ivan.remap</string>
   <key>ProgramArguments</key>
   <array><string>/path/to/remapping/script.sh</string></array>
   <key>RunAtLoad</key>
   <true/>
</dict>
</plist>

Беглое знакомство с hidutils подсказывает, что утилита (и стоящий за ней фреймворк) могут довольно многое. Было бы здорово прописать опции не только клавиатуры, но и тачпада, мыши и так далее, чтобы не париться при смене ноута. Например, однажды я час искал нужную галочку для тачпада, а она оказалась в “Accessibility”.

Но графического интерфейса у hidutils нет. Вот если бы кто-то написал веб-страничку с конструктором опций на JavaScript. Указываешь, что изменить, а на выходе получаешь шелл-скрипт.

Поделитесь, какие клавиши изменяете вы и что для этого используете — добавлю ссылки в статью.

UPD