Skip to content

Instantly share code, notes, and snippets.

@optozorax
Created August 31, 2019 16:05
Show Gist options
  • Save optozorax/770d188b7a4ca22b2118092aa82782c7 to your computer and use it in GitHub Desktop.
Save optozorax/770d188b7a4ca22b2118092aa82782c7 to your computer and use it in GitHub Desktop.
Каждая клавиша - функция. Идея паттерна для программируемых клавиатур
/** Идея для программируемых клавиатур, когда каждая клавиша - функция.
В чатике много шутили, типо: давайте сделаем каждую клавишу - процессом)))000)), а давайте http-сервером)))00)). Так вот, эта идея является серьезной реализацией этих шуток, причём это даже может быть удобно.
*/
typedef std::function<void()> Key;
//----------------------------------------------------------------------------
// Стандартные клавиши
Key KC_NULL = [](){};
Key KC_0 = [](){
register_code(48);
unregister_code(48);
};
Key KC_1 = //...
//...
//----------------------------------------------------------------------------
// Модификаторы
Key SHIFT = [](const Key& K) -> Key {
return [&K](){
register_code(/* shift */);
K();
unregister_code(/* shift */);
};
};
Key CTRL = // ...
// ...
//----------------------------------------------------------------------------
// Макросы
Key LANG = [](){
CTRL(ALT(KC_NULL))();
};
Key THREE_DOT = [](){
KC_DOT();
KC_DOT();
KC_DOT();
};
Key KLAVOGONKI_NEXT = [](){
KC_TAB();
KC_TAB();
CTRL(KC_RIGHT)();
};
// ...
//----------------------------------------------------------------------------
// Русские клавиши (даже если сейчас английский язык!)
int currentLayer;
Key PRESS_RUSSIAN = [&currentLayer](Key K){
return [](){
if (currentLayer != RUSSIAN) {
layer_on(RUSSIAN);
LANG();
K();
LANG();
layer_off(RUSSIAN);
} else {
K();
}
};
};
Key RU_A = PRESS_RUSSIAN(KC_F)
Key RU_V = [](){
PRESS_RUSSIAN(KC_D)(); // или можно так
};
// ...
//----------------------------------------------------------------------------
const std::vector<std::vector<Key>> keymap = {
{KC_A, KC_B, LANG, RU_A, PRESS_RUSSIAN(SHIFT(KC_3)), RU_B}
};
//----------------------------------------------------------------------------
// Как нажать клавишу, зная её позицию? Так:
keymap[x][y]();
//----------------------------------------------------------------------------
/** Плюсы и минусы:
+ То, как себя поведёт клавиша, определяется в месте её объявления.
+ Можно выражать куда более сложные вещи, чем те, что в QMK, которые используют выставление бита, например, как: PRESS_RUSSIAN.
- Требует много памяти и выполняется дольше, однозначно на микроконтроллере в 32кб не хватит места.
*/
@optozorax
Copy link
Author

Я забыл также, что у каждую клавишу можно не только нажать, но ещё и зажать, а от этого логика всего этого значительно меняется. Каждая клавиша теперь должна стать двумя лямбдами: DOWN, UP.
А вообще можно ввести ещё промежуточное состояние, когда клавиша нажата достаточно долго, и начинает отправляться автоповтор: HOLDED.
Задавать три лямбды для одной клавиши можно через какой-нибудь конструктор, типо:

typedef std::function<void()> Fun;
struct Key {
	Key(Fun down, Fun holded, Fun up) : down(down), holded(holded), up(up) {}

	Fun down, holded, up;
};

Key KC_0([](){
	register_code(48);
}, [](){
	// Ничего не делаем, потому что операционка сама обрабатывает повтор
}, [](){
	urregister_code(48);
});

Key ALT_TAB([](){
	register_code(ALT);
	register_code(TAB);
	unregister_code(TAB);
}, [](){
	// А тут уже нужны повторения, если эта клавиша зажата
	register_code(TAB);
	unregister_code(TAB);
}, [](){
	unregister_code(ALT);;
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment