forked from kofal.net/zmk
fix: Optimize layout changes by doing runtime mapping
* To avoid tons of migration, extra flash writes, etc, we keep the keymaps and settings using a key position index that's tied to the stock layout, and at runtime mapping key positions as needed.
This commit is contained in:
committed by
Pete Johanson
parent
a6d09f8c00
commit
ea1a09bf99
@@ -18,6 +18,7 @@
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/matrix.h>
|
||||
#include <zmk/physical_layouts.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/position_state_changed.h>
|
||||
@@ -213,6 +214,35 @@ static void zmk_physical_layouts_kscan_process_msgq(struct k_work *item) {
|
||||
}
|
||||
}
|
||||
|
||||
static const struct zmk_physical_layout *get_default_layout(void) {
|
||||
const struct zmk_physical_layout *initial;
|
||||
|
||||
#if USE_PHY_LAYOUTS && DT_HAS_CHOSEN(zmk_physical_layout)
|
||||
initial = &_CONCAT(_zmk_physical_layout_, DT_CHOSEN(zmk_physical_layout));
|
||||
#else
|
||||
initial = layouts[0];
|
||||
#endif
|
||||
|
||||
return initial;
|
||||
}
|
||||
|
||||
static int get_index_of_layout(const struct zmk_physical_layout *layout) {
|
||||
for (int i = 0; i < ARRAY_SIZE(layouts); i++) {
|
||||
if (layouts[i] == layout) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static uint32_t selected_to_stock_map[ZMK_KEYMAP_LEN];
|
||||
|
||||
int zmk_physical_layouts_get_selected_to_stock_position_map(uint32_t const **map) {
|
||||
*map = selected_to_stock_map;
|
||||
return ZMK_KEYMAP_LEN;
|
||||
}
|
||||
|
||||
int zmk_physical_layouts_select_layout(const struct zmk_physical_layout *dest_layout) {
|
||||
if (!dest_layout) {
|
||||
return -ENODEV;
|
||||
@@ -233,6 +263,15 @@ int zmk_physical_layouts_select_layout(const struct zmk_physical_layout *dest_la
|
||||
}
|
||||
}
|
||||
|
||||
int new_idx = get_index_of_layout(dest_layout);
|
||||
int stock_idx = get_index_of_layout(get_default_layout());
|
||||
int ret = zmk_physical_layouts_get_position_map(stock_idx, new_idx, ZMK_KEYMAP_LEN,
|
||||
selected_to_stock_map);
|
||||
if (ret < 0) {
|
||||
LOG_ERR("Failed to refresh the selected to stock mapping (%d)", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
active = dest_layout;
|
||||
|
||||
if (active->kscan) {
|
||||
@@ -284,15 +323,7 @@ static int8_t saved_selected_index = -1;
|
||||
#endif
|
||||
|
||||
int zmk_physical_layouts_select_initial(void) {
|
||||
const struct zmk_physical_layout *initial;
|
||||
|
||||
#if USE_PHY_LAYOUTS && DT_HAS_CHOSEN(zmk_physical_layout)
|
||||
initial = &_CONCAT(_zmk_physical_layout_, DT_CHOSEN(zmk_physical_layout));
|
||||
#else
|
||||
initial = layouts[0];
|
||||
#endif
|
||||
|
||||
int ret = zmk_physical_layouts_select_layout(initial);
|
||||
int ret = zmk_physical_layouts_select_layout(get_default_layout());
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -326,6 +357,14 @@ int zmk_physical_layouts_get_position_map(uint8_t source, uint8_t dest, size_t m
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (source == dest) {
|
||||
for (int i = 0; i < map_size; i++) {
|
||||
map[i] = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct zmk_physical_layout *src_layout = layouts[source];
|
||||
const struct zmk_physical_layout *dest_layout = layouts[dest];
|
||||
int max_kp = dest_layout->keys_len;
|
||||
@@ -435,6 +474,11 @@ static int zmk_physical_layouts_init(void) {
|
||||
}
|
||||
#endif // IS_ENABLED(CONFIG_PM_DEVICE)
|
||||
|
||||
// Initialize a sane mapping
|
||||
for (int i = 0; i < ZMK_KEYMAP_LEN; i++) {
|
||||
selected_to_stock_map[i] = i;
|
||||
}
|
||||
|
||||
return zmk_physical_layouts_select_initial();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user