Merge b1332490bc
into b735a051ce
This commit is contained in:
commit
8d31b0e849
10 changed files with 241 additions and 1 deletions
|
@ -59,6 +59,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)
|
||||
|
|
|
@ -22,3 +22,4 @@
|
|||
#include <behaviors/mouse_key_press.dtsi>
|
||||
#include <behaviors/soft_off.dtsi>
|
||||
#include <behaviors/studio_unlock.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
|
|
@ -15,6 +15,7 @@
|
|||
typedef uint32_t zmk_keymap_layers_state_t;
|
||||
|
||||
uint8_t zmk_keymap_layer_default(void);
|
||||
int zmk_keymap_layer_set_default(uint8_t layer);
|
||||
zmk_keymap_layers_state_t zmk_keymap_layer_state(void);
|
||||
bool zmk_keymap_layer_active(uint8_t layer);
|
||||
uint8_t zmk_keymap_highest_layer_active(void);
|
||||
|
|
158
app/src/behaviors/behavior_default_layer.c
Normal file
158
app/src/behaviors/behavior_default_layer.c
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* 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);
|
||||
|
||||
#if DT_HAS_COMPAT_STATUS_OKAY(DT_DRV_COMPAT)
|
||||
|
||||
struct default_layer_settings_t {
|
||||
bool using_global_setting;
|
||||
uint8_t global_default;
|
||||
uint8_t endpoint_defaults[ZMK_ENDPOINT_COUNT];
|
||||
};
|
||||
|
||||
static struct default_layer_settings_t default_layers = {0};
|
||||
|
||||
static struct k_work_delayable df_layers_save_work;
|
||||
|
||||
static void zmk_default_layers_save_state_work(struct k_work *_work) {
|
||||
settings_save_one("default_layer/settings", &default_layers, sizeof(default_layers));
|
||||
}
|
||||
|
||||
static int apply_default_layer_config(struct zmk_endpoint_instance endpoint) {
|
||||
uint8_t index = zmk_endpoint_instance_to_index(endpoint);
|
||||
uint8_t layer = default_layers.endpoint_defaults[index];
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
k_work_init_delayable(&df_layers_save_work, zmk_default_layers_save_state_work);
|
||||
|
||||
settings_load_subtree("default_layer");
|
||||
|
||||
return apply_default_layer_config(zmk_endpoints_selected());
|
||||
}
|
||||
SYS_INIT(default_layer_init, APPLICATION, CONFIG_APPLICATION_INIT_PRIORITY);
|
||||
|
||||
static int save_default_layer_setting(uint8_t layer, struct zmk_endpoint_instance endpoint) {
|
||||
if (layer >= ZMK_KEYMAP_LAYERS_LEN) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uint8_t index = zmk_endpoint_instance_to_index(endpoint);
|
||||
default_layers.endpoint_defaults[index] = layer;
|
||||
|
||||
char endpoint_str[ZMK_ENDPOINT_STR_LEN];
|
||||
zmk_endpoint_instance_to_str(endpoint, endpoint_str, sizeof(endpoint_str));
|
||||
LOG_INF("Updated default layer (%d) for %s.", layer, endpoint_str);
|
||||
|
||||
int ret = k_work_reschedule(&df_layers_save_work, K_MSEC(CONFIG_ZMK_SETTINGS_SAVE_DEBOUNCE));
|
||||
return MIN(0, ret);
|
||||
}
|
||||
|
||||
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);
|
|
@ -108,6 +108,29 @@ static inline int set_layer_state(uint8_t layer, bool state) {
|
|||
|
||||
uint8_t zmk_keymap_layer_default(void) { return _zmk_keymap_layer_default; }
|
||||
|
||||
int zmk_keymap_layer_set_default(uint8_t layer) {
|
||||
int ret = 0;
|
||||
uint8_t prev_default = _zmk_keymap_layer_default;
|
||||
|
||||
ret = set_layer_state(layer, true);
|
||||
if (ret < 0) {
|
||||
LOG_WRN("Failed to activate the new default layer; aborting changes.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
_zmk_keymap_layer_default = layer;
|
||||
ret = set_layer_state(prev_default, false);
|
||||
if (ret < 0) {
|
||||
LOG_WRN("Unable to deactivate the current default layer; reverting changes.");
|
||||
_zmk_keymap_layer_default = prev_default;
|
||||
set_layer_state(layer, false);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LOG_DBG("Default layer changed to: %d", layer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
zmk_keymap_layers_state_t zmk_keymap_layer_state(void) { return _zmk_keymap_layer_state; }
|
||||
|
||||
bool zmk_keymap_layer_active_with_state(uint8_t layer, zmk_keymap_layers_state_t state_to_test) {
|
||||
|
|
|
@ -37,6 +37,7 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
|
|||
| `&to` | [To Layer](layers.md#to-layer) | Enables a layer and disables all other layers except the default layer |
|
||||
| `&tog` | [Toggle Layer](layers.md#toggle-layer) | Enables a layer until the layer is manually disabled |
|
||||
| `&sl` | [Sticky Layer](sticky-layer.md) | Activates a layer until another key is pressed, then deactivates it |
|
||||
| `&df` | [Default Layer](layers.md#default-layer) | Change the default layer. Persisted across power reset. |
|
||||
|
||||
## Mouse Emulation Behaviors
|
||||
|
||||
|
|
|
@ -120,3 +120,36 @@ Example:
|
|||
|
||||
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
|
||||
|
||||
?> What is the default layer?
|
||||
|
||||
It is the first one you define on your keymap (unless changed using this behavior). It is _special_ in two aspects:
|
||||
|
||||
- It can't be disabled by other behaviors.
|
||||
- It is the only one active when the board starts running.
|
||||
|
||||
This 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 setting 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
|
||||
```
|
||||
|
|
|
@ -13,7 +13,7 @@ Applies to: `compatible = "zmk,keymap"`
|
|||
|
||||
Definition file: [zmk/app/dts/bindings/zmk,keymap.yaml](https://github.com/zmkfirmware/zmk/blob/main/app/dts/bindings/zmk%2Ckeymap.yaml)
|
||||
|
||||
The `zmk,keymap` node itself has no properties. It should have one child node per layer of the keymap, starting with the default layer (layer 0).
|
||||
The `zmk,keymap` node itself has no properties. It should have one child node per layer of the keymap, the first one being the default layer (until changed with [`&df`](layers.md#default-layer)).
|
||||
|
||||
Each child node can have the following properties:
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue