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_to_layer.c)
|
||||||
target_sources(app PRIVATE src/behaviors/behavior_transparent.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_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 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_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)
|
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/macros.dtsi>
|
||||||
#include <behaviors/mouse_key_press.dtsi>
|
#include <behaviors/mouse_key_press.dtsi>
|
||||||
#include <behaviors/soft_off.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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("default_layer_changed: %d", layer);
|
LOG_DBG("Default layer changed to: %d", layer);
|
||||||
return 0;
|
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.
|
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).
|
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