Описание моей раскладки для клавиатуры Dactyl Manuform 4x5
Особенности раскладки
-
Симметричная раскладка для возможности работать одной рукой (левой если в правой мышь, или правой, если в левой телефон).
-
Два режима работы: ЙЦУКЕН для работы преимущественно двумя руками, и РИСАТЕНО (аккордовая раскладка) для возможности набирать текст одной рукой. Пока рисатено не освоена в полной мере, этот режим я использую для тренировки, а также в ситуациях, когда надо много работать мышью и вводить мало текста.
-
Не используются тап-холды. Почему-то для меня тап-холды являются источником дополнительных ошибок, и как следствие - дополнительный стресс и ненормативная лексика. Это совсем не то, для чего мне нужна эргономичная клавиатура.
-
Все символы (кроме букв) находятся на одних и тех же клавишах как в русской так и в английской раскладке. Это реализовано через Альт-коды. Работает только под Windows и не требует установки какого-либо софта в ОС.
-
Не все клавиши присутствуют на клавиатуре. Не все хоткеи можно нажать. К примеру нет таких вредных клавиш как CapsLock, Insert и даже Alt. Тем не менее есть возможность использовать комбинацию клавиш Alt+Tab. Я добавил в раскладку только те возможности, которыми сам пользуюсь. Поэтому эта раскладка не является готовым решением, ее можно использовать как источник идей и не более того.
-
Раскладка сделана на QMK, в клавиатуре используется микроконтроллер Atmega32u4
Возможные проблемы
-
Некоторые приложения могут в определенных ситуациях напрямую работать со скан-кодами и не понимать те трюки, которые тут используются. Придется искать пути обхода проблемы.
-
Существует проблема при работе с удаленным компьютером по RDP. Когда клавиатура на одно нажатие клавиши отправляет зажатие модификатора, ввод символа и отпускание модификатора, модификатор может не прийти на удаленный компьютер. В связке QMK+Atmega32u4 эта проблема возникает редко, при активной работе можно наблюдать 2-3 случая за день, а можно и совсем не столкнуться. Но в других конфигурациях этот баг может стать серьезной проблемой.
Переключение режимов
Зеленый аккорд включает ЙЦУКЕН, синий аккорд РИСАТЕНО.
http://www.keyboard-layout-editor.com/#/gists/c2a368b82d47b45e139749ba492dcef3
Аккорды выбраны таким образом, чтобы исключить случайное нажатие. Повторное нажатие аккорда ничего не делает, поэтому мы можем не выяснять, в каком режиме находится клавиатура, а просто нажать нужный аккорд, и быть уверенными, что теперь клавиатура в нужном режиме.
Примеры кода
В файле rules.mk
COMBO_ENABLE = yes
В файле config.h
#define COMBO_TERM 120
На период обучения поставил тайминг аккордов побольше.
В файле keymap.c
enum combo_events {
CB_QZ
, CB_W_LPR
, PNC_N_UND
, PNC_A_LPR
//
, COMBO_LENGTH
};
uint16_t COMBO_LEN = COMBO_LENGTH; // remove the COMBO_COUNT define and use this instead!
const uint16_t PROGMEM combo_QZ[] = {KC_Q, KC_Z, COMBO_END};
const uint16_t PROGMEM combo_W_LPR[] = {KC_W, KC_GRV, COMBO_END};
const uint16_t PROGMEM pnc_N_UND[] = {PNC_N, PNC_UNDSCR, COMBO_END};
const uint16_t PROGMEM pnc_A_LPR[] = {PNC_A, PNC_LBRKTL, COMBO_END};
combo_t key_combos[] = {
[CB_QZ] = COMBO_ACTION(combo_QZ)
, [CB_W_LPR] = COMBO_ACTION(combo_W_LPR)
, [PNC_N_UND] = COMBO_ACTION(pnc_N_UND)
, [PNC_A_LPR] = COMBO_ACTION(pnc_A_LPR)
};
void process_combo_event(uint16_t combo_index, bool pressed) {
if (pressed) {
case CB_QZ:
// DEF
break;
case CB_W_LPR:
// PNCATEHO
layer_clear();
layer_on(_PNC);
break;
case PNC_N_UND:
// DEF
layer_clear();
layer_on(_DEF);
break;
case PNC_A_LPR:
// PNCATEHO
break;
}
}
}
Тамб кластер
http://www.keyboard-layout-editor.com/#/gists/b51caa94916d0108c9a1aa6b57c84e63
-
nav - слой навигации
-
shft = Shift
-
num - цифровой слой
-
spc - пробел
-
bkspc = Backspace
-
esc = Escape
-
nav+shft - стрелки с шифтом, выделение текста
-
spc+shft - Enter
-
spc+num - Ctrl
-
esc+bkspc - Ctrl+Backspace, удаление целого слова
Нижние кнопки (esc и bkspc) не очень удобно нажимать. Все зависит от размера руки. В моем случае эти клавиши пригодны для единичных нажатий, но не годятся для того чтобы их удерживать и нажимать той же рукой что-то еще.
На четырех нижних кнопках есть еще место для двух аккордов (spc+esc, num+bkspc), на которые можно повесить какие-нибудь хоткеи.
Знаки препинания
В разряд знаков препинания я постарался включить символы, которые часто используются в наборе текста, в противоположность спецсимволам. Получился такой список .,;:"'!?()<>[]{}. Символы '<>[]{} в этом списке скорее лишние, они попали сюда за компанию со скобками и кавычкой. С другой сторны не хватает дефиса, но дефис оказался среди спецсимволов в одной компании с "плюсом" и "равно".
В двуруком и одноруком режимах знаки препинания сделаны по разному.
В режиме ЙЦУКЕН знаки препинания вводятся в тамб кластере, при этом одна рука зажимает слоефикатор NUM, а другая вводит символ.
http://www.keyboard-layout-editor.com/#/gists/9007726697f131c0142263a946d7da19
-
двоеточие вводится тап-денсом: надо нажать точку два раза подряд. Если нажать точку третий раз то получится троеточие.
-
точка с запятой вводится аккордом (точка + запятая)
http://www.keyboard-layout-editor.com/#/gists/acf023ded36bcd85b32d4881da12eb66
-
Вопросительный знак вводится тап-денсом
-
Одиночная кавычка вводится аккордом
В режиме РИСАТЕНО знаки препинания вводятся на основном слое фингерами.
http://www.keyboard-layout-editor.com/#/gists/a9226bd793dbbdcd19448fba3559fe79
-
Тап-денс и аккорды работают точно так же
-
Угловые и фигурные скобки вводятся с шифтом
-
Скобки на половинках зекально не отражаются левая скобка всегда слева, правая справа
Примеры кода
Этот пример демонстрирует использование альт-кодов и переопределение поведения клавиши с шифтом:
enum custom_keycodes { // эти кейкоды расмещаем в слои лэйаут вместо стандартых
M_UNDSCR = SAFE_RANGE // начало диапазона кастом-кодов
, PNC_LPRNTHL // наш пример: левая скобка на левой половине слоя РИСАТЕНО
};
// для двузначных альт-кодов
void tap_alt_code2(uint16_t mods, uint8_t n1, uint8_t n2) {
unregister_mods(mods);
register_mods(MOD_BIT(KC_LEFT_ALT));
if (n1 == 0) {
tap_code(KC_KP_0);
} else {
tap_code(KC_KP_1 + n1 - 1);
}
if (n2 == 0) {
tap_code(KC_KP_0);
} else {
tap_code(KC_KP_1 + n2 - 1);
}
unregister_mods(MOD_BIT(KC_LEFT_ALT));
register_mods(mods);
}
// для трехзначных альт-кодов
void tap_alt_code3(uint16_t mods, uint8_t n1, uint8_t n2, uint8_t n3) {
unregister_mods(mods);
register_mods(MOD_BIT(KC_LEFT_ALT));
if (n1 == 0) {
tap_code(KC_KP_0);
} else {
tap_code(KC_KP_1 + n1 - 1);
}
if (n2 == 0) {
tap_code(KC_KP_0);
} else {
tap_code(KC_KP_1 + n2 - 1);
}
if (n3 == 0) {
tap_code(KC_KP_0);
} else {
tap_code(KC_KP_1 + n3 - 1);
}
unregister_mods(MOD_BIT(KC_LEFT_ALT));
register_mods(mods);
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint16_t mods = get_mods();
if (record->event.pressed) {
switch (keycode) {
case PNC_LPRNTHL:
case PNC_LPRNTHR:
if (mods & MOD_MASK_SHIFT) {
// <
tap_alt_code2(mods, 6, 0);
} else {
// (
tap_code16(S(KC_9));
}
break;
return true;
}
Тап-денс у меня реализован велосипедным методом, по причинам, которые уже не актуальны. Поэтому примеров кода нет. Возможно в будущем перепишу раскладку и выложу пример реализации тап-денса, но в документации QMK есть примеры.
При вводе запятой в двуруком режиме возникла проблема. Быстрое нажатие NUM + Space отрабатывается как аккорд, на который у меня повешен Ctrl. При том что аккорд я всегда ввожу на одной половинке, а для ввода запятой задействуются клавиши с разных половин. Для решения этой проблемы я назначил на клавиши NUM и Space кастомные кей-коды, разные для правой и левой половин. Пришлось прописывать обработку включения/выключения слоя, ввода пробела, что в итоге вылилось в довольно сложный код. Тем не менее я его выложу, чтобы продемонстрировать программное включение-выключение слоев и программное нажатие-отжатие клавиши.
// если нажаты оба NUM и один из них отпускаем, как определить, надо ли выключать слой?
// запомним какой из них слой включил
bool is_lnum = false;
bool is_rnum = false;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint16_t mods = get_mods();
if (record->event.pressed) {
switch (keycode) {
case M_LNUM: // нажали левый NUM
if (IS_LAYER_ON(_NUM)) {
// слой уже включен правым NUM, выведем точку
tap_alt_code2(mods, 4, 6);
} else { // слой еще не включен, надо включить
layer_on(_NUM);
is_lnum = true;
}
break;
case M_RNUM:
if (IS_LAYER_ON(_NUM)) {
// слой уже включен левым NUM, выведем кавычку
tap_alt_code2(mods, 3, 4);
} else { // слой еще не включен, надо включить
layer_on(_NUM);
is_rnum = true;
}
break;
case M_LSPC: // нажали левый пробел
if (IS_LAYER_ON(_NUM) && is_rnum) {
// слой включен правым NUM, выведем запятую
tap_alt_code2(mods, 4, 4);
} else {
// выполним нажатие пробела без отжатия, чтобы можно было напечатать много пробелов, удерживая клавишу
register_code(KC_SPC);
}
break;
case M_RSPC: // нажали правый пробел
if (IS_LAYER_ON(_NUM) && is_lnum) {
// слой включен левым NUM, выведем восклицательный знак
tap_code16(S(KC_1));
} else {
register_code(KC_SPC);
}
break;
}
} else {
switch (keycode) {
case M_LNUM: // отжали левый нум
if (IS_LAYER_ON(_NUM) && is_lnum) {
// слой включен левым нумом, выключим слой
layer_off(_NUM);
is_lnum = false;
}
}
break;
case M_RNUM: // отжали правый нум
if (IS_LAYER_ON(_NUM) && is_rnum) {
// слой включен правым нумом, выключим слой
layer_off(_NUM);
is_rnum = false;
}
break;
case M_LSPC: // отжали пробел
if (IS_LAYER_OFF(_NUM)) {
// слой выключен, значит это не запятая и не восклицательный знак
// отжимаем пробел
unregister_code(KC_SPC);
}
break;
case M_RSPC:
if (IS_LAYER_OFF(_NUM)) {
unregister_code(KC_SPC);
}
break;
}
}
return true;
}
Слой навигации
Слой навигации доступен для работы одной рукой.
http://www.keyboard-layout-editor.com/#/gists/79ce66b0f58dccba811fd6a52ef47102
-
Стрелка влево и стрелка вверх двигают курсор к началу текста. Поэтому стрелка вверх расположена слева, а стрелка вниз - вправо.
-
Клавиша Home двигает курсор дальше, чем стрелка. Поэтому стрелки внутри, а Home/End - снаружи.
-
Стрелки с контролом перемещают курсор по словам.
-
На синих клавишах размещены хоткеи IDE для навигации по коду: перейти к определению, вернуться назад, поиск парных скобок.
-
Альт-таб работает полностью нативно. Когда первый раз нажимается клавиша "Альт-таб", клавиатура посылает в систему зажатие альта и однократное нажатие таба. На экране появляются миниатюры приложений. При последующих нажатиях кнопки посылаются только нажатия таба - на экране происходит выбор приложения. После отпускания кнопки NAV, в систему посылается отжатие альта, выбор приложения завершается.
-
В слое есть аккорды для переключения языка и вызова контекстного меню. Стрелки отображаются с одной половинки на другую не зеркально. Чтобы аккорды нажимались на двух половинках одинаково, для них выбраны симметрично расположенные клавиши.
Примеры кода
Этот пример иллюстрирует работу Alt-Tab. Ctrl-Tab делается аналогично.
bool is_atab_active = false;
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
uint16_t mods = get_mods();
// alt tab cleanup
if (is_atab_active && keycode != M_ATAB) {
// отжали слоефикатор или нажали другую клавишу в слое
unregister_mods(MOD_BIT(KC_LALT)); // отжимаем альт
is_atab_active = false;
}
if (record->event.pressed) {
switch (keycode) {
case M_ATAB:
if (!is_atab_active) { // первое нажатие - зажимаем альт
register_mods(MOD_BIT(KC_LALT));
is_atab_active = true;
}
tap_code(KC_TAB); // нажали и отпустили таб
break;
}
return true;
}
Цифровой слой
Цифровой слой доступен для работы одной рукой.
http://www.keyboard-layout-editor.com/#/gists/1d4b7a9f529fc47c7d2f6e25f81378dc
-
За основу взят цифровой слой РИСАТЕНО. Цифры старше 6 и 0 вводятся аккордами.
-
Верхняя клавиша второго ряда указа не задействована, потому что до нее сложно тянуться, если тамб удерживает NUM
-
Некоторые символы вводятся тап-денсом, некоторые аккордом
Для ввода дробных чисел и дат удобно иметь в цифровом слое точку и запятую. Для этого в слой добавлены аккорды:
http://www.keyboard-layout-editor.com/#/gists/62182e2b8c3b1b845886283e2b11fa0f
Слой Ctrl
Модификатор Ctrl зажимается аккордом в тамб-кластере. Он работает как обычный модификатор, например, влияет на поведение нажатий левой кнопки мыши. Но также меняет работу почти всех клавиш, т.е. по сути включает слой. У меня это реализовано не через слой, переопределено поведение каждой клавиши в двух слоях. Но, наверное, через слой это было бы проще сделать.
Все функции слоя Ctrl доступны для работы одной рукой.
http://www.keyboard-layout-editor.com/#/gists/17234cd347f88b73d924f6cc8424e7eb
Shft2 - это слой в слое. Продолжая удерживать тамбом аккорд, зажимаем средним пальцем Shft2, и получаем возможность выполнить еще несколько действий:
http://www.keyboard-layout-editor.com/#/gists/ecfb0b1eaf30bed1066bbd7c00792774
Ссылки
http://www.keyboard-layout-editor.com/#/gists/cd7791577b534d8fd26ed35210f549e5
http://www.keyboard-layout-editor.com/#/gists/803320870a706259504871c9ab27acdb
http://www.keyboard-layout-editor.com/#/gists/d84f5e80f60aa40f7e377dad88784ca2