feat(mouse): Added auto-layer-toggle
Input Listener: Added logging Auto Layer Toggle: Added initial version Auto Layer Toggle: Changed how config is retrieved Auto Layer Toggle: Adjust logging
This commit is contained in:
parent
01221695e5
commit
a81da31d6a
2 changed files with 156 additions and 10 deletions
|
@ -19,3 +19,18 @@ properties:
|
||||||
scale-divisor:
|
scale-divisor:
|
||||||
type: int
|
type: int
|
||||||
default: 1
|
default: 1
|
||||||
|
layer-toggle:
|
||||||
|
type: int
|
||||||
|
default: -1
|
||||||
|
required: false
|
||||||
|
description: The layer that should be toggled when the mouse is moved.
|
||||||
|
layer-toggle-delay-ms:
|
||||||
|
type: int
|
||||||
|
default: 250
|
||||||
|
required: false
|
||||||
|
description: How many miliseconds of mouse activity are required before the layer is toggled on.
|
||||||
|
layer-toggle-timeout-ms:
|
||||||
|
type: int
|
||||||
|
default: 250
|
||||||
|
required: false
|
||||||
|
description: How many miliseconds of mouse inactivity are required before the layer is toggled off again.
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include <zmk/mouse.h>
|
#include <zmk/mouse.h>
|
||||||
#include <zmk/endpoints.h>
|
#include <zmk/endpoints.h>
|
||||||
#include <zmk/hid.h>
|
#include <zmk/hid.h>
|
||||||
|
#include <zmk/keymap.h>
|
||||||
|
|
||||||
|
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||||
|
|
||||||
enum input_listener_xy_data_mode {
|
enum input_listener_xy_data_mode {
|
||||||
INPUT_LISTENER_XY_DATA_MODE_NONE,
|
INPUT_LISTENER_XY_DATA_MODE_NONE,
|
||||||
|
@ -27,22 +30,35 @@ struct input_listener_xy_data {
|
||||||
int16_t y;
|
int16_t y;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct input_listener_data {
|
|
||||||
struct input_listener_xy_data data;
|
|
||||||
struct input_listener_xy_data wheel_data;
|
|
||||||
|
|
||||||
uint8_t button_set;
|
|
||||||
uint8_t button_clear;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct input_listener_config {
|
struct input_listener_config {
|
||||||
bool xy_swap;
|
bool xy_swap;
|
||||||
bool x_invert;
|
bool x_invert;
|
||||||
bool y_invert;
|
bool y_invert;
|
||||||
uint16_t scale_multiplier;
|
uint16_t scale_multiplier;
|
||||||
uint16_t scale_divisor;
|
uint16_t scale_divisor;
|
||||||
|
int layer_toggle;
|
||||||
|
int layer_toggle_delay_ms;
|
||||||
|
int layer_toggle_timeout_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct input_listener_data {
|
||||||
|
const struct device *dev;
|
||||||
|
|
||||||
|
struct input_listener_xy_data data;
|
||||||
|
struct input_listener_xy_data wheel_data;
|
||||||
|
|
||||||
|
uint8_t button_set;
|
||||||
|
uint8_t button_clear;
|
||||||
|
|
||||||
|
bool layer_toggle_layer_enabled;
|
||||||
|
int64_t layer_toggle_last_mouse_package_time;
|
||||||
|
struct k_work_delayable layer_toggle_activation_delay;
|
||||||
|
struct k_work_delayable layer_toggle_deactivation_delay;
|
||||||
|
};
|
||||||
|
|
||||||
|
void zmk_input_listener_layer_toggle_input_rel_received(const struct input_listener_config *config,
|
||||||
|
struct input_listener_data *data);
|
||||||
|
|
||||||
static void handle_rel_code(struct input_listener_data *data, struct input_event *evt) {
|
static void handle_rel_code(struct input_listener_data *data, struct input_event *evt) {
|
||||||
switch (evt->code) {
|
switch (evt->code) {
|
||||||
case INPUT_REL_X:
|
case INPUT_REL_X:
|
||||||
|
@ -66,6 +82,31 @@ static void handle_rel_code(struct input_listener_data *data, struct input_event
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *get_input_code_name(struct input_event *evt) {
|
||||||
|
switch (evt->code) {
|
||||||
|
case INPUT_REL_X:
|
||||||
|
return "INPUT_REL_X";
|
||||||
|
case INPUT_REL_Y:
|
||||||
|
return "INPUT_REL_Y";
|
||||||
|
case INPUT_REL_WHEEL:
|
||||||
|
return "INPUT_REL_WHEEL";
|
||||||
|
case INPUT_REL_HWHEEL:
|
||||||
|
return "INPUT_REL_HWHEEL";
|
||||||
|
case INPUT_BTN_0:
|
||||||
|
return "INPUT_BTN_0";
|
||||||
|
case INPUT_BTN_1:
|
||||||
|
return "INPUT_BTN_1";
|
||||||
|
case INPUT_BTN_2:
|
||||||
|
return "INPUT_BTN_2";
|
||||||
|
case INPUT_BTN_3:
|
||||||
|
return "INPUT_BTN_3";
|
||||||
|
case INPUT_BTN_4:
|
||||||
|
return "INPUT_BTN_4";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_key_code(struct input_listener_data *data, struct input_event *evt) {
|
static void handle_key_code(struct input_listener_data *data, struct input_event *evt) {
|
||||||
int8_t btn;
|
int8_t btn;
|
||||||
|
|
||||||
|
@ -126,6 +167,10 @@ static void input_handler(const struct input_listener_config *config,
|
||||||
// First, filter to update the event data as needed.
|
// First, filter to update the event data as needed.
|
||||||
filter_with_input_config(config, evt);
|
filter_with_input_config(config, evt);
|
||||||
|
|
||||||
|
LOG_DBG("Got input_handler event: %s with value 0x%x", get_input_code_name(evt), evt->value);
|
||||||
|
|
||||||
|
zmk_input_listener_layer_toggle_input_rel_received(config, data);
|
||||||
|
|
||||||
switch (evt->type) {
|
switch (evt->type) {
|
||||||
case INPUT_EV_REL:
|
case INPUT_EV_REL:
|
||||||
handle_rel_code(data, evt);
|
handle_rel_code(data, evt);
|
||||||
|
@ -171,6 +216,72 @@ static void input_handler(const struct input_listener_config *config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void zmk_input_listener_layer_toggle_input_rel_received(const struct input_listener_config *config,
|
||||||
|
struct input_listener_data *data) {
|
||||||
|
if (config->layer_toggle == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->layer_toggle_last_mouse_package_time = k_uptime_get();
|
||||||
|
|
||||||
|
if (data->layer_toggle_layer_enabled == false) {
|
||||||
|
k_work_schedule(&data->layer_toggle_activation_delay,
|
||||||
|
K_MSEC(config->layer_toggle_delay_ms));
|
||||||
|
} else {
|
||||||
|
// Deactivate the layer if no further movement within
|
||||||
|
// layer_toggle_timeout_ms
|
||||||
|
k_work_reschedule(&data->layer_toggle_deactivation_delay,
|
||||||
|
K_MSEC(config->layer_toggle_timeout_ms));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zmk_input_listener_layer_toggle_activate_layer(struct k_work *item) {
|
||||||
|
struct k_work_delayable *d_work = k_work_delayable_from_work(item);
|
||||||
|
|
||||||
|
struct input_listener_data *data =
|
||||||
|
CONTAINER_OF(d_work, struct input_listener_data, layer_toggle_activation_delay);
|
||||||
|
const struct input_listener_config *config = data->dev->config;
|
||||||
|
|
||||||
|
int64_t current_time = k_uptime_get();
|
||||||
|
int64_t last_mv_within_ms = current_time - data->layer_toggle_last_mouse_package_time;
|
||||||
|
|
||||||
|
if (last_mv_within_ms <= config->layer_toggle_timeout_ms * 0.1) {
|
||||||
|
LOG_INF("Activating layer %d due to mouse activity...", config->layer_toggle);
|
||||||
|
|
||||||
|
zmk_keymap_layer_activate(config->layer_toggle, false);
|
||||||
|
data->layer_toggle_layer_enabled = true;
|
||||||
|
} else {
|
||||||
|
LOG_INF("Not activating mouse layer %d, because last mouse activity was %lldms ago",
|
||||||
|
config->layer_toggle, last_mv_within_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void zmk_input_listener_layer_toggle_deactivate_layer(struct k_work *item) {
|
||||||
|
struct k_work_delayable *d_work = k_work_delayable_from_work(item);
|
||||||
|
|
||||||
|
struct input_listener_data *data =
|
||||||
|
CONTAINER_OF(d_work, struct input_listener_data, layer_toggle_deactivation_delay);
|
||||||
|
const struct input_listener_config *config = data->dev->config;
|
||||||
|
|
||||||
|
LOG_INF("Deactivating layer %d due to mouse activity...", config->layer_toggle);
|
||||||
|
|
||||||
|
if (zmk_keymap_layer_active(config->layer_toggle)) {
|
||||||
|
zmk_keymap_layer_deactivate(config->layer_toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
data->layer_toggle_layer_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int zmk_input_listener_layer_toggle_init(const struct input_listener_config *config,
|
||||||
|
struct input_listener_data *data) {
|
||||||
|
k_work_init_delayable(&data->layer_toggle_activation_delay,
|
||||||
|
zmk_input_listener_layer_toggle_activate_layer);
|
||||||
|
k_work_init_delayable(&data->layer_toggle_deactivation_delay,
|
||||||
|
zmk_input_listener_layer_toggle_deactivate_layer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#define IL_INST(n) \
|
#define IL_INST(n) \
|
||||||
static const struct input_listener_config config_##n = { \
|
static const struct input_listener_config config_##n = { \
|
||||||
.xy_swap = DT_INST_PROP(n, xy_swap), \
|
.xy_swap = DT_INST_PROP(n, xy_swap), \
|
||||||
|
@ -178,11 +289,31 @@ static void input_handler(const struct input_listener_config *config,
|
||||||
.y_invert = DT_INST_PROP(n, y_invert), \
|
.y_invert = DT_INST_PROP(n, y_invert), \
|
||||||
.scale_multiplier = DT_INST_PROP(n, scale_multiplier), \
|
.scale_multiplier = DT_INST_PROP(n, scale_multiplier), \
|
||||||
.scale_divisor = DT_INST_PROP(n, scale_divisor), \
|
.scale_divisor = DT_INST_PROP(n, scale_divisor), \
|
||||||
|
.layer_toggle = DT_INST_PROP(n, layer_toggle), \
|
||||||
|
.layer_toggle_delay_ms = DT_INST_PROP(n, layer_toggle_delay_ms), \
|
||||||
|
.layer_toggle_timeout_ms = DT_INST_PROP(n, layer_toggle_timeout_ms), \
|
||||||
|
}; \
|
||||||
|
static struct input_listener_data data_##n = { \
|
||||||
|
.dev = DEVICE_DT_INST_GET(n), \
|
||||||
|
.layer_toggle_layer_enabled = false, \
|
||||||
|
.layer_toggle_last_mouse_package_time = 0, \
|
||||||
}; \
|
}; \
|
||||||
static struct input_listener_data data_##n = {}; \
|
|
||||||
void input_handler_##n(struct input_event *evt) { \
|
void input_handler_##n(struct input_event *evt) { \
|
||||||
input_handler(&config_##n, &data_##n, evt); \
|
input_handler(&config_##n, &data_##n, evt); \
|
||||||
} \
|
} \
|
||||||
INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_INST_PHANDLE(n, device)), input_handler_##n);
|
INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_INST_PHANDLE(n, device)), input_handler_##n); \
|
||||||
|
\
|
||||||
|
static int zmk_input_listener_init_##n(const struct device *dev) { \
|
||||||
|
\
|
||||||
|
struct input_listener_data *data = dev->data; \
|
||||||
|
const struct input_listener_config *config = dev->config; \
|
||||||
|
\
|
||||||
|
zmk_input_listener_layer_toggle_init(config, data); \
|
||||||
|
\
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(n, &zmk_input_listener_init_##n, NULL, &data_##n, &config_##n, \
|
||||||
|
POST_KERNEL, CONFIG_APPLICATION_INIT_PRIORITY, NULL);
|
||||||
|
|
||||||
DT_INST_FOREACH_STATUS_OKAY(IL_INST)
|
DT_INST_FOREACH_STATUS_OKAY(IL_INST)
|
||||||
|
|
Loading…
Add table
Reference in a new issue