feat: &df
behavior and docs
This commit is contained in:
parent
3f12a14bdf
commit
4c6818a86e
7 changed files with 227 additions and 1 deletions
|
@ -55,6 +55,7 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|||
target_sources(app PRIVATE src/behaviors/behavior_to_layer.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_transparent.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_none.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_default_layer.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE app PRIVATE src/behaviors/behavior_sensor_rotate.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_VAR app PRIVATE src/behaviors/behavior_sensor_rotate_var.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON app PRIVATE src/behaviors/behavior_sensor_rotate_common.c)
|
||||
|
|
|
@ -21,3 +21,4 @@
|
|||
#include <behaviors/macros.dtsi>
|
||||
#include <behaviors/mouse_key_press.dtsi>
|
||||
#include <behaviors/soft_off.dtsi>
|
||||
#include <behaviors/default_layer.dtsi>
|
||||
|
|
14
app/dts/behaviors/default_layer.dtsi
Normal file
14
app/dts/behaviors/default_layer.dtsi
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ df: default_layer {
|
||||
compatible = "zmk,behavior-default-layer";
|
||||
#binding-cells = <1>;
|
||||
};
|
||||
};
|
||||
};
|
|
@ -0,0 +1,8 @@
|
|||
# Copyright (c) 2024 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
description: Behavior to change default layer for current endpoint
|
||||
|
||||
compatible: "zmk,behavior-default-layer"
|
||||
|
||||
include: one_param.yaml
|
176
app/src/behaviors/behavior_default_layer.c
Normal file
176
app/src/behaviors/behavior_default_layer.c
Normal file
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_default_layer
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/settings/settings.h>
|
||||
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/keymap.h>
|
||||
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/endpoint_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct default_layer_settings_t {
|
||||
uint8_t usb[ZMK_ENDPOINT_USB_COUNT];
|
||||
uint8_t ble[ZMK_ENDPOINT_BLE_COUNT];
|
||||
};
|
||||
|
||||
static struct default_layer_settings_t default_layers = {0};
|
||||
|
||||
static int apply_default_layer_config(struct zmk_endpoint_instance endpoint) {
|
||||
uint8_t layer = 0;
|
||||
|
||||
switch (endpoint.transport) {
|
||||
case ZMK_TRANSPORT_USB:
|
||||
__ASSERT(ZMK_ENDPOINT_USB_COUNT == 1, "Unreachable");
|
||||
layer = default_layers.usb[0];
|
||||
break;
|
||||
|
||||
case ZMK_TRANSPORT_BLE:
|
||||
__ASSERT(endpoint.ble.profile_index < ZMK_ENDPOINT_BLE_COUNT, "Unreachable");
|
||||
layer = default_layers.ble[endpoint.ble.profile_index];
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = zmk_keymap_layer_set_default(layer);
|
||||
if (ret < 0) {
|
||||
LOG_WRN("Could not apply default layer from settings. Perhaps something in the code/keymap "
|
||||
"changed since configuration was saved.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_INF("Activated default layer (%d) for the current endpoint.", layer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int default_layer_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) {
|
||||
const char *next;
|
||||
int rc;
|
||||
|
||||
if (settings_name_steq(name, "settings", &next) && !next) {
|
||||
if (len != sizeof(default_layers)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = read_cb(cb_arg, &default_layers, sizeof(default_layers));
|
||||
if (rc >= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
struct settings_handler default_layer_conf = {
|
||||
.name = "default_layer",
|
||||
.h_set = default_layer_set,
|
||||
};
|
||||
|
||||
static int default_layer_init(void) {
|
||||
settings_subsys_init();
|
||||
|
||||
int ret = settings_register(&default_layer_conf);
|
||||
if (ret) {
|
||||
LOG_ERR("Could not register default layer settings (%d).", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
settings_load_subtree("default_layer");
|
||||
|
||||
return apply_default_layer_config(zmk_endpoints_selected());
|
||||
}
|
||||
SYS_INIT(default_layer_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
static int save_default_layer_setting(uint8_t layer, struct zmk_endpoint_instance endpoint) {
|
||||
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (endpoint.transport) {
|
||||
case ZMK_TRANSPORT_USB:
|
||||
__ASSERT(ZMK_ENDPOINT_USB_COUNT == 1, "Unreachable");
|
||||
default_layers.usb[0] = layer;
|
||||
break;
|
||||
|
||||
case ZMK_TRANSPORT_BLE:
|
||||
__ASSERT(endpoint.ble.profile_index < ZMK_ENDPOINT_BLE_COUNT, "Unreachable");
|
||||
default_layers.ble[endpoint.ble.profile_index] = layer;
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = settings_save_one("default_layer/settings", &default_layers, sizeof(default_layers));
|
||||
if (ret < 0) {
|
||||
LOG_WRN("Could not update the settings.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (endpoint.transport == ZMK_TRANSPORT_USB) {
|
||||
LOG_INF("Updated default layer (%d) for USB endpoint.", layer);
|
||||
} else {
|
||||
LOG_INF("Updated default layer (%d) for BLE endpoint %d.", layer,
|
||||
endpoint.ble.profile_index);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int behavior_default_layer_init(const struct device *dev) { return 0; }
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
int ret = 0;
|
||||
struct zmk_endpoint_instance endpoint = zmk_endpoints_selected();
|
||||
|
||||
ret = save_default_layer_setting(binding->param1, endpoint);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = apply_default_layer_config(endpoint);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
return ZMK_BEHAVIOR_OPAQUE;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_default_layer_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed,
|
||||
.binding_released = on_keymap_binding_released,
|
||||
};
|
||||
|
||||
BEHAVIOR_DT_INST_DEFINE(0, behavior_default_layer_init, NULL, NULL, NULL, POST_KERNEL,
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &behavior_default_layer_driver_api);
|
||||
|
||||
#endif
|
||||
|
||||
static int endpoint_changed_cb(const zmk_event_t *eh) {
|
||||
struct zmk_endpoint_changed *evt = as_zmk_endpoint_changed(eh);
|
||||
|
||||
if (evt != NULL) {
|
||||
apply_default_layer_config(evt->endpoint);
|
||||
}
|
||||
|
||||
return ZMK_EV_EVENT_BUBBLE;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(endpoint, endpoint_changed_cb);
|
||||
ZMK_SUBSCRIPTION(endpoint, zmk_endpoint_changed);
|
|
@ -127,7 +127,7 @@ int zmk_keymap_layer_set_default(uint8_t layer) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
LOG_DBG("default_layer_changed: %d", layer);
|
||||
LOG_DBG("Default layer changed to: %d", layer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -153,3 +153,29 @@ It is possible to use "toggle layer" to have keys that raise and lower the layer
|
|||
|
||||
The "conditional layers" feature enables a particular layer when all layers in a specified set are active.
|
||||
For more information, see [conditional layers](../features/conditional-layers.md).
|
||||
|
||||
## Default Layer
|
||||
|
||||
The default layer behavior allows configuring a different default layer, for example to test DVORAK while keeping QWERTY on another layer, or moving a couple keycodes around for Windows/Mac usage.
|
||||
|
||||
This is stored on a per-endpoint basis, so you can configure USB to use QWERTY, and the first BLE endpoint to use DVORAK.
|
||||
|
||||
The stored settings are read and applied when the keyboard boots (receives powers) and also when the selected endpoint changes.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
- Reference: `&df`
|
||||
- Parameter: The layer number to set as default for current endpoint, e.g. `1`
|
||||
|
||||
Example:
|
||||
|
||||
```dts
|
||||
&df DVORAK
|
||||
```
|
||||
|
||||
For a keymap with:
|
||||
|
||||
```dts
|
||||
#define QWERTY 0
|
||||
#define DVORAK 1
|
||||
```
|
||||
|
|
Loading…
Add table
Reference in a new issue