refactor(behaviors): capture behavior event in sticky keys

This commit is contained in:
Okke Formsma 2020-12-19 21:33:33 +01:00
parent 92990a2c11
commit 3a2407a87b

View file

@ -18,7 +18,7 @@
#include <zmk/events/keycode_state_changed.h> #include <zmk/events/keycode_state_changed.h>
#include <zmk/events/modifiers_state_changed.h> #include <zmk/events/modifiers_state_changed.h>
#include <zmk/hid.h> #include <zmk/hid.h>
#include <zmk/event-manager.h> #include <zmk/event_manager.h>
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL); LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
@ -34,9 +34,7 @@ struct behavior_sticky_key_config {
}; };
struct active_sticky_key { struct active_sticky_key {
uint32_t position; const struct behavior_state_changed *event;
uint32_t param1;
uint32_t param2;
const struct behavior_sticky_key_config *config; const struct behavior_sticky_key_config *config;
// timer data. // timer data.
bool timer_started; bool timer_started;
@ -50,22 +48,18 @@ struct active_sticky_key {
struct active_sticky_key active_sticky_keys[ZMK_BHV_STICKY_KEY_MAX_HELD] = {}; struct active_sticky_key active_sticky_keys[ZMK_BHV_STICKY_KEY_MAX_HELD] = {};
static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t param1, static struct active_sticky_key *store_sticky_key(const struct behavior_state_changed *event,
uint32_t param2,
const struct behavior_sticky_key_config *config) { const struct behavior_sticky_key_config *config) {
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
struct active_sticky_key *const sticky_key = &active_sticky_keys[i]; struct active_sticky_key *const sticky_key = &active_sticky_keys[i];
if (sticky_key->position != ZMK_BHV_STICKY_KEY_POSITION_FREE || if (sticky_key->event != NULL || sticky_key->timer_cancelled) {
sticky_key->timer_cancelled) {
continue; continue;
} }
sticky_key->position = position; sticky_key->event = event;
sticky_key->param1 = param1;
sticky_key->param2 = param2;
sticky_key->config = config; sticky_key->config = config;
sticky_key->release_at = 0;
sticky_key->timer_cancelled = false; sticky_key->timer_cancelled = false;
sticky_key->timer_started = false; sticky_key->timer_started = false;
sticky_key->release_at = 0;
sticky_key->modified_key_usage_page = 0; sticky_key->modified_key_usage_page = 0;
sticky_key->modified_key_keycode = 0; sticky_key->modified_key_keycode = 0;
return sticky_key; return sticky_key;
@ -73,13 +67,11 @@ static struct active_sticky_key *store_sticky_key(uint32_t position, uint32_t pa
return NULL; return NULL;
} }
static void clear_sticky_key(struct active_sticky_key *sticky_key) {
sticky_key->position = ZMK_BHV_STICKY_KEY_POSITION_FREE;
}
static struct active_sticky_key *find_sticky_key(uint32_t position) { static struct active_sticky_key *find_sticky_key(uint32_t position) {
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
if (active_sticky_keys[i].position == position && !active_sticky_keys[i].timer_cancelled) { if (active_sticky_keys[i].event != NULL &&
active_sticky_keys[i].event->position == position &&
!active_sticky_keys[i].timer_cancelled) {
return &active_sticky_keys[i]; return &active_sticky_keys[i];
} }
} }
@ -88,21 +80,20 @@ static struct active_sticky_key *find_sticky_key(uint32_t position) {
static inline int press_sticky_key_behavior(struct active_sticky_key *sticky_key, static inline int press_sticky_key_behavior(struct active_sticky_key *sticky_key,
int64_t timestamp) { int64_t timestamp) {
// todo: use correct layer
int layer = 0;
return ZMK_EVENT_RAISE(create_behavior_state_changed( return ZMK_EVENT_RAISE(create_behavior_state_changed(
sticky_key->config->behavior.behavior_dev, sticky_key->param1, sticky_key->param2, true, sticky_key->config->behavior.behavior_dev, sticky_key->event->param1,
layer, sticky_key->position, timestamp)); sticky_key->event->param2, true, sticky_key->event->layer, sticky_key->event->position,
timestamp));
} }
static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_key, static inline int release_sticky_key_behavior(struct active_sticky_key *sticky_key,
int64_t timestamp) { int64_t timestamp) {
clear_sticky_key(sticky_key); const struct behavior_state_changed *event = sticky_key->event;
// todo: use correct layer sticky_key->event = NULL;
int layer = 0; return ZMK_EVENT_RAISE(create_behavior_state_changed(sticky_key->config->behavior.behavior_dev,
return ZMK_EVENT_RAISE(create_behavior_state_changed( event->param1, event->param2, false,
sticky_key->config->behavior.behavior_dev, sticky_key->param1, sticky_key->param2, false, event->layer, event->position, timestamp));
layer, sticky_key->position, timestamp)); k_free((void *)event);
} }
static int stop_timer(struct active_sticky_key *sticky_key) { static int stop_timer(struct active_sticky_key *sticky_key) {
@ -123,7 +114,7 @@ static int on_sticky_key_binding_pressed(const struct behavior_state_changed *ev
stop_timer(sticky_key); stop_timer(sticky_key);
release_sticky_key_behavior(sticky_key, event->timestamp); release_sticky_key_behavior(sticky_key, event->timestamp);
} }
sticky_key = store_sticky_key(event->position, event->param1, event->param2, cfg); sticky_key = store_sticky_key(event, cfg);
if (sticky_key == NULL) { if (sticky_key == NULL) {
LOG_ERR("unable to store sticky key, did you press more than %d sticky_key?", LOG_ERR("unable to store sticky key, did you press more than %d sticky_key?",
ZMK_BHV_STICKY_KEY_MAX_HELD); ZMK_BHV_STICKY_KEY_MAX_HELD);
@ -132,7 +123,7 @@ static int on_sticky_key_binding_pressed(const struct behavior_state_changed *ev
press_sticky_key_behavior(sticky_key, event->timestamp); press_sticky_key_behavior(sticky_key, event->timestamp);
LOG_DBG("%d new sticky_key", event->position); LOG_DBG("%d new sticky_key", event->position);
return ZMK_BEHAVIOR_OPAQUE; return ZMK_BEHAVIOR_CAPTURED;
} }
static int on_sticky_key_binding_released(const struct behavior_state_changed *event) { static int on_sticky_key_binding_released(const struct behavior_state_changed *event) {
@ -170,14 +161,14 @@ static int sticky_key_keycode_state_changed_listener(const struct zmk_event_head
struct keycode_state_changed *ev = cast_keycode_state_changed(eh); struct keycode_state_changed *ev = cast_keycode_state_changed(eh);
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
struct active_sticky_key *sticky_key = &active_sticky_keys[i]; struct active_sticky_key *sticky_key = &active_sticky_keys[i];
if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) { if (sticky_key->event == NULL) {
continue; continue;
} }
if (strcmp(sticky_key->config->behavior.behavior_dev, "KEY_PRESS") == 0 && if (strcmp(sticky_key->config->behavior.behavior_dev, "KEY_PRESS") == 0 &&
HID_USAGE_ID(sticky_key->param1) == ev->keycode && HID_USAGE_ID(sticky_key->event->param1) == ev->keycode &&
(HID_USAGE_PAGE(sticky_key->param1) & 0xFF) == ev->usage_page && (HID_USAGE_PAGE(sticky_key->event->param1) & 0xFF) == ev->usage_page &&
SELECT_MODS(sticky_key->param1) == ev->implicit_modifiers) { SELECT_MODS(sticky_key->event->param1) == ev->implicit_modifiers) {
// don't catch key down events generated by the sticky key behavior itself // don't catch key down events generated by the sticky key behavior itself
continue; continue;
} }
@ -219,7 +210,7 @@ ZMK_SUBSCRIPTION(behavior_sticky_key, keycode_state_changed);
void behavior_sticky_key_timer_handler(struct k_work *item) { void behavior_sticky_key_timer_handler(struct k_work *item) {
struct active_sticky_key *sticky_key = struct active_sticky_key *sticky_key =
CONTAINER_OF(item, struct active_sticky_key, release_timer); CONTAINER_OF(item, struct active_sticky_key, release_timer);
if (sticky_key->position == ZMK_BHV_STICKY_KEY_POSITION_FREE) { if (sticky_key->event == NULL) {
return; return;
} }
if (sticky_key->timer_cancelled) { if (sticky_key->timer_cancelled) {
@ -235,7 +226,7 @@ static int behavior_sticky_key_init(const struct device *dev) {
for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) { for (int i = 0; i < ZMK_BHV_STICKY_KEY_MAX_HELD; i++) {
k_delayed_work_init(&active_sticky_keys[i].release_timer, k_delayed_work_init(&active_sticky_keys[i].release_timer,
behavior_sticky_key_timer_handler); behavior_sticky_key_timer_handler);
active_sticky_keys[i].position = ZMK_BHV_STICKY_KEY_POSITION_FREE; active_sticky_keys[i].event = NULL;
} }
} }
init_first_run = false; init_first_run = false;