Compare commits
No commits in common. "feat/pointers-move-scroll" and "main" have entirely different histories.
feat/point
...
main
49 changed files with 106 additions and 1181 deletions
|
@ -36,6 +36,7 @@ target_sources_ifdef(CONFIG_ZMK_GPIO_KEY_WAKEUP_TRIGGER app PRIVATE src/gpio_key
|
|||
target_sources(app PRIVATE src/events/activity_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/position_state_changed.c)
|
||||
target_sources(app PRIVATE src/events/sensor_event.c)
|
||||
target_sources(app PRIVATE src/events/mouse_button_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_WPM app PRIVATE src/events/wpm_state_changed.c)
|
||||
target_sources_ifdef(CONFIG_USB_DEVICE_STACK app PRIVATE src/events/usb_conn_state_changed.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_reset.c)
|
||||
|
@ -43,7 +44,7 @@ target_sources_ifdef(CONFIG_ZMK_EXT_POWER app PRIVATE src/behaviors/behavior_ext
|
|||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SOFT_OFF app PRIVATE src/behaviors/behavior_soft_off.c)
|
||||
if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
||||
target_sources(app PRIVATE src/hid.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse/input_listener.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_MOUSE app PRIVATE src/mouse.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_key_press.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_KEY_TOGGLE app PRIVATE src/behaviors/behavior_key_toggle.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_HOLD_TAP app PRIVATE src/behaviors/behavior_hold_tap.c)
|
||||
|
@ -63,7 +64,6 @@ if ((NOT CONFIG_ZMK_SPLIT) OR CONFIG_ZMK_SPLIT_ROLE_CENTRAL)
|
|||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON app PRIVATE src/behaviors/behavior_sensor_rotate_common.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_MOUSE_KEY_PRESS app PRIVATE src/behaviors/behavior_mouse_key_press.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_STUDIO_UNLOCK app PRIVATE src/behaviors/behavior_studio_unlock.c)
|
||||
target_sources_ifdef(CONFIG_ZMK_BEHAVIOR_INPUT_TWO_AXIS app PRIVATE src/behaviors/behavior_input_two_axis.c)
|
||||
target_sources(app PRIVATE src/combo.c)
|
||||
target_sources(app PRIVATE src/behaviors/behavior_tap_dance.c)
|
||||
target_sources(app PRIVATE src/behavior_queue.c)
|
||||
|
|
|
@ -395,7 +395,13 @@ endif
|
|||
#Display/LED Options
|
||||
endmenu
|
||||
|
||||
rsource "src/mouse/Kconfig"
|
||||
menu "Mouse Options"
|
||||
|
||||
config ZMK_MOUSE
|
||||
bool "Enable ZMK mouse emulation"
|
||||
|
||||
#Mouse Options
|
||||
endmenu
|
||||
|
||||
menu "Power Management"
|
||||
|
||||
|
|
|
@ -71,7 +71,8 @@ config ZMK_BEHAVIOR_KEY_TOGGLE
|
|||
config ZMK_BEHAVIOR_MOUSE_KEY_PRESS
|
||||
bool
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED && ZMK_MOUSE
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_MOUSE_KEY_PRESS_ENABLED
|
||||
imply ZMK_MOUSE
|
||||
|
||||
config ZMK_BEHAVIOR_STICKY_KEY
|
||||
bool
|
||||
|
@ -93,11 +94,6 @@ config ZMK_BEHAVIOR_SOFT_OFF
|
|||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_SOFT_OFF_ENABLED && ZMK_PM_SOFT_OFF
|
||||
|
||||
config ZMK_BEHAVIOR_INPUT_TWO_AXIS
|
||||
bool
|
||||
default y
|
||||
depends on DT_HAS_ZMK_BEHAVIOR_INPUT_TWO_AXIS_ENABLED && ZMK_MOUSE
|
||||
|
||||
config ZMK_BEHAVIOR_SENSOR_ROTATE_COMMON
|
||||
bool
|
||||
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <behaviors/key_press.dtsi>
|
||||
#include <behaviors/key_toggle.dtsi>
|
||||
#include <behaviors/transparent.dtsi>
|
||||
|
@ -25,9 +19,6 @@
|
|||
#include <behaviors/key_repeat.dtsi>
|
||||
#include <behaviors/backlight.dtsi>
|
||||
#include <behaviors/macros.dtsi>
|
||||
#include <behaviors/mouse_key_press.dtsi>
|
||||
#include <behaviors/soft_off.dtsi>
|
||||
#include <behaviors/studio_unlock.dtsi>
|
||||
#include <behaviors/mouse_move.dtsi>
|
||||
#include <behaviors/mouse_scroll.dtsi>
|
||||
#include <behaviors/macros.dtsi>
|
||||
#include <behaviors/mouse_keys.dtsi>
|
||||
|
|
|
@ -16,9 +16,4 @@
|
|||
#binding-cells = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
mkp_input_listener: mkp_input_listener {
|
||||
compatible = "zmk,input-listener";
|
||||
device = <&mkp>;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "mouse_key_press.dtsi"
|
||||
#include "mouse_move.dtsi"
|
||||
#include "mouse_scroll.dtsi"
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ mmv: mouse_move {
|
||||
compatible = "zmk,behavior-input-two-axis";
|
||||
#binding-cells = <1>;
|
||||
x-input-code = <INPUT_REL_X>;
|
||||
y-input-code = <INPUT_REL_Y>;
|
||||
time-to-max-speed-ms = <300>;
|
||||
acceleration-exponent = <1>;
|
||||
};
|
||||
};
|
||||
|
||||
mmv_input_listener: mmv_input_listener {
|
||||
compatible = "zmk,input-listener";
|
||||
device = <&mmv>;
|
||||
};
|
||||
};
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
/*
|
||||
* Copyright (c) 2024 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
behaviors {
|
||||
/omit-if-no-ref/ msc: mouse_scroll {
|
||||
compatible = "zmk,behavior-input-two-axis";
|
||||
#binding-cells = <1>;
|
||||
x-input-code = <INPUT_REL_HWHEEL>;
|
||||
y-input-code = <INPUT_REL_WHEEL>;
|
||||
time-to-max-speed-ms = <300>;
|
||||
acceleration-exponent = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
msc_input_listener: msc_input_listener {
|
||||
compatible = "zmk,input-listener";
|
||||
device = <&msc>;
|
||||
};
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
description: Two axis input behavior
|
||||
|
||||
compatible: "zmk,behavior-input-two-axis"
|
||||
|
||||
include: one_param.yaml
|
||||
|
||||
properties:
|
||||
x-input-code:
|
||||
type: int
|
||||
required: true
|
||||
y-input-code:
|
||||
type: int
|
||||
required: true
|
||||
trigger-period-ms:
|
||||
type: int
|
||||
default: 16
|
||||
description: The time (in ms) between generated inputs when an input has non-zero speed.
|
||||
delay-ms:
|
||||
type: int
|
||||
time-to-max-speed-ms:
|
||||
type: int
|
||||
required: true
|
||||
acceleration-exponent:
|
||||
type: int
|
||||
default: 1
|
|
@ -1,21 +0,0 @@
|
|||
description: |
|
||||
Listener to subscribe to input events and send HID updates after processing
|
||||
|
||||
compatible: "zmk,input-listener"
|
||||
|
||||
properties:
|
||||
device:
|
||||
type: phandle
|
||||
required: true
|
||||
xy-swap:
|
||||
type: boolean
|
||||
x-invert:
|
||||
type: boolean
|
||||
y-invert:
|
||||
type: boolean
|
||||
scale-multiplier:
|
||||
type: int
|
||||
default: 1
|
||||
scale-divisor:
|
||||
type: int
|
||||
default: 1
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023 The ZMK Contributors
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
@ -22,29 +22,3 @@
|
|||
|
||||
#define MB4 BIT(3)
|
||||
#define MB5 BIT(4)
|
||||
|
||||
#ifndef ZMK_MOUSE_DEFAULT_MOVE_VAL
|
||||
#define ZMK_MOUSE_DEFAULT_MOVE_VAL 600
|
||||
#endif
|
||||
|
||||
#ifndef ZMK_MOUSE_DEFAULT_SCRL_VAL
|
||||
#define ZMK_MOUSE_DEFAULT_SCRL_VAL 10
|
||||
#endif
|
||||
|
||||
/* Mouse move behavior */
|
||||
#define MOVE_Y(vert) ((vert)&0xFFFF)
|
||||
#define MOVE_Y_DECODE(encoded) (int16_t)((encoded)&0x0000FFFF)
|
||||
#define MOVE_X(hor) (((hor)&0xFFFF) << 16)
|
||||
#define MOVE_X_DECODE(encoded) (int16_t)(((encoded)&0xFFFF0000) >> 16)
|
||||
|
||||
#define MOVE(hor, vert) (MOVE_X(hor) + MOVE_Y(vert))
|
||||
|
||||
#define MOVE_UP MOVE_Y(-ZMK_MOUSE_DEFAULT_MOVE_VAL)
|
||||
#define MOVE_DOWN MOVE_Y(ZMK_MOUSE_DEFAULT_MOVE_VAL)
|
||||
#define MOVE_LEFT MOVE_X(-ZMK_MOUSE_DEFAULT_MOVE_VAL)
|
||||
#define MOVE_RIGHT MOVE_X(ZMK_MOUSE_DEFAULT_MOVE_VAL)
|
||||
|
||||
#define SCRL_UP MOVE_Y(ZMK_MOUSE_DEFAULT_SCRL_VAL)
|
||||
#define SCRL_DOWN MOVE_Y(-ZMK_MOUSE_DEFAULT_SCRL_VAL)
|
||||
#define SCRL_LEFT MOVE_X(-ZMK_MOUSE_DEFAULT_SCRL_VAL)
|
||||
#define SCRL_RIGHT MOVE_X(ZMK_MOUSE_DEFAULT_SCRL_VAL)
|
||||
|
|
|
@ -77,10 +77,6 @@
|
|||
#define ZMK_HID_REPORT_ID_CONSUMER 0x02
|
||||
#define ZMK_HID_REPORT_ID_MOUSE 0x03
|
||||
|
||||
#define HID_USAGE16(a, b) HID_ITEM(HID_ITEM_TAG_USAGE, HID_ITEM_TYPE_LOCAL, 2), a, b
|
||||
|
||||
#define HID_USAGE16_SINGLE(a) HID_USAGE16((a & 0xFF), ((a >> 8) & 0xFF))
|
||||
|
||||
static const uint8_t zmk_hid_report_desc[] = {
|
||||
HID_USAGE_PAGE(HID_USAGE_GEN_DESKTOP),
|
||||
HID_USAGE(HID_USAGE_GD_KEYBOARD),
|
||||
|
@ -189,17 +185,10 @@ static const uint8_t zmk_hid_report_desc[] = {
|
|||
HID_USAGE(HID_USAGE_GD_X),
|
||||
HID_USAGE(HID_USAGE_GD_Y),
|
||||
HID_USAGE(HID_USAGE_GD_WHEEL),
|
||||
HID_LOGICAL_MIN16(0xFF, -0x7F),
|
||||
HID_LOGICAL_MAX16(0xFF, 0x7F),
|
||||
HID_REPORT_SIZE(0x10),
|
||||
HID_REPORT_COUNT(0x03),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL),
|
||||
HID_USAGE_PAGE(HID_USAGE_CONSUMER),
|
||||
HID_USAGE16_SINGLE(HID_USAGE_CONSUMER_AC_PAN),
|
||||
HID_LOGICAL_MIN16(0xFF, -0x7F),
|
||||
HID_LOGICAL_MAX16(0xFF, 0x7F),
|
||||
HID_LOGICAL_MIN8(-0x7F),
|
||||
HID_LOGICAL_MAX8(0x7F),
|
||||
HID_REPORT_SIZE(0x08),
|
||||
HID_REPORT_COUNT(0x01),
|
||||
HID_REPORT_COUNT(0x03),
|
||||
HID_INPUT(ZMK_HID_MAIN_VAL_DATA | ZMK_HID_MAIN_VAL_VAR | ZMK_HID_MAIN_VAL_REL),
|
||||
HID_END_COLLECTION,
|
||||
HID_END_COLLECTION,
|
||||
|
@ -269,10 +258,9 @@ struct zmk_hid_consumer_report {
|
|||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
struct zmk_hid_mouse_report_body {
|
||||
zmk_mouse_button_flags_t buttons;
|
||||
int16_t d_x;
|
||||
int16_t d_y;
|
||||
int16_t d_scroll_y;
|
||||
int16_t d_scroll_x;
|
||||
int8_t d_x;
|
||||
int8_t d_y;
|
||||
int8_t d_wheel;
|
||||
} __packed;
|
||||
|
||||
struct zmk_hid_mouse_report {
|
||||
|
@ -313,10 +301,6 @@ int zmk_hid_mouse_button_press(zmk_mouse_button_t button);
|
|||
int zmk_hid_mouse_button_release(zmk_mouse_button_t button);
|
||||
int zmk_hid_mouse_buttons_press(zmk_mouse_button_flags_t buttons);
|
||||
int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons);
|
||||
void zmk_hid_mouse_movement_set(int16_t x, int16_t y);
|
||||
void zmk_hid_mouse_scroll_set(int8_t x, int8_t y);
|
||||
void zmk_hid_mouse_movement_update(int16_t x, int16_t y);
|
||||
void zmk_hid_mouse_scroll_update(int8_t x, int8_t y);
|
||||
void zmk_hid_mouse_clear(void);
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2023 The ZMK Contributors
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
|
|
@ -1,265 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_behavior_input_two_axis
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/input/input.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/util.h> // CLAMP
|
||||
|
||||
#include <zmk/behavior.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
struct vector2d {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
struct movement_state_1d {
|
||||
float remainder;
|
||||
int16_t speed;
|
||||
uint64_t start_time;
|
||||
};
|
||||
|
||||
struct movement_state_2d {
|
||||
struct movement_state_1d x;
|
||||
struct movement_state_1d y;
|
||||
};
|
||||
|
||||
struct behavior_input_two_axis_data {
|
||||
struct k_work_delayable tick_work;
|
||||
const struct device *dev;
|
||||
|
||||
struct movement_state_2d state;
|
||||
};
|
||||
|
||||
struct behavior_input_two_axis_config {
|
||||
int16_t x_code;
|
||||
int16_t y_code;
|
||||
uint16_t delay_ms;
|
||||
uint16_t time_to_max_speed_ms;
|
||||
uint8_t trigger_period_ms;
|
||||
// acceleration exponent 0: uniform speed
|
||||
// acceleration exponent 1: uniform acceleration
|
||||
// acceleration exponent 2: uniform jerk
|
||||
uint8_t acceleration_exponent;
|
||||
};
|
||||
|
||||
#if CONFIG_MINIMAL_LIBC
|
||||
static float powf(float base, float exponent) {
|
||||
// poor man's power implementation rounds the exponent down to the nearest integer.
|
||||
float power = 1.0f;
|
||||
for (; exponent >= 1.0f; exponent--) {
|
||||
power = power * base;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
#else
|
||||
#include <math.h>
|
||||
#endif
|
||||
|
||||
static int64_t ms_since_start(int64_t start, int64_t now, int64_t delay) {
|
||||
if (start == 0) {
|
||||
return 0;
|
||||
}
|
||||
int64_t move_duration = now - (start + delay);
|
||||
// start can be in the future if there's a delay
|
||||
if (move_duration < 0) {
|
||||
move_duration = 0;
|
||||
}
|
||||
return move_duration;
|
||||
}
|
||||
|
||||
static float speed(const struct behavior_input_two_axis_config *config, float max_speed,
|
||||
int64_t duration_ms) {
|
||||
// Calculate the speed based on MouseKeysAccel
|
||||
// See https://en.wikipedia.org/wiki/Mouse_keys
|
||||
if (duration_ms == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (duration_ms > config->time_to_max_speed_ms || config->time_to_max_speed_ms == 0 ||
|
||||
config->acceleration_exponent == 0) {
|
||||
return max_speed;
|
||||
}
|
||||
float time_fraction = (float)duration_ms / config->time_to_max_speed_ms;
|
||||
return max_speed * powf(time_fraction, config->acceleration_exponent);
|
||||
}
|
||||
|
||||
static void track_remainder(float *move, float *remainder) {
|
||||
float new_move = *move + *remainder;
|
||||
*remainder = new_move - (int)new_move;
|
||||
*move = (int)new_move;
|
||||
}
|
||||
|
||||
static float update_movement_1d(const struct behavior_input_two_axis_config *config,
|
||||
struct movement_state_1d *state, int64_t now) {
|
||||
float move = 0;
|
||||
if (state->speed == 0) {
|
||||
state->remainder = 0;
|
||||
return move;
|
||||
}
|
||||
|
||||
int64_t move_duration = ms_since_start(state->start_time, now, config->delay_ms);
|
||||
move = (move_duration > 0)
|
||||
? (speed(config, state->speed, move_duration) * config->trigger_period_ms / 1000)
|
||||
: 0;
|
||||
|
||||
track_remainder(&(move), &(state->remainder));
|
||||
|
||||
return move;
|
||||
}
|
||||
static struct vector2d update_movement_2d(const struct behavior_input_two_axis_config *config,
|
||||
struct movement_state_2d *state, int64_t now) {
|
||||
struct vector2d move = {0};
|
||||
|
||||
move = (struct vector2d){
|
||||
.x = update_movement_1d(config, &state->x, now),
|
||||
.y = update_movement_1d(config, &state->y, now),
|
||||
};
|
||||
|
||||
return move;
|
||||
}
|
||||
|
||||
static bool is_non_zero_1d_movement(int16_t speed) { return speed != 0; }
|
||||
|
||||
static bool is_non_zero_2d_movement(struct movement_state_2d *state) {
|
||||
return is_non_zero_1d_movement(state->x.speed) || is_non_zero_1d_movement(state->y.speed);
|
||||
}
|
||||
|
||||
static bool should_be_working(struct behavior_input_two_axis_data *data) {
|
||||
return is_non_zero_2d_movement(&data->state);
|
||||
}
|
||||
|
||||
static void tick_work_cb(struct k_work *work) {
|
||||
struct k_work_delayable *d_work = k_work_delayable_from_work(work);
|
||||
struct behavior_input_two_axis_data *data =
|
||||
CONTAINER_OF(d_work, struct behavior_input_two_axis_data, tick_work);
|
||||
const struct device *dev = data->dev;
|
||||
const struct behavior_input_two_axis_config *cfg = dev->config;
|
||||
|
||||
uint64_t timestamp = k_uptime_get();
|
||||
|
||||
LOG_INF("x start: %llu, y start: %llu, current timestamp: %llu", data->state.x.start_time,
|
||||
data->state.y.start_time, timestamp);
|
||||
|
||||
struct vector2d move = update_movement_2d(cfg, &data->state, timestamp);
|
||||
|
||||
int ret = 0;
|
||||
bool have_x = is_non_zero_1d_movement(move.x);
|
||||
bool have_y = is_non_zero_1d_movement(move.y);
|
||||
if (have_x) {
|
||||
ret = input_report_rel(dev, cfg->x_code, (int16_t)CLAMP(move.x, INT16_MIN, INT16_MAX),
|
||||
!have_y, K_NO_WAIT);
|
||||
}
|
||||
if (have_y) {
|
||||
ret = input_report_rel(dev, cfg->y_code, (int16_t)CLAMP(move.y, INT16_MIN, INT16_MAX), true,
|
||||
K_NO_WAIT);
|
||||
}
|
||||
|
||||
if (should_be_working(data)) {
|
||||
k_work_schedule(&data->tick_work, K_MSEC(cfg->trigger_period_ms));
|
||||
}
|
||||
}
|
||||
|
||||
static void set_start_times_for_activity_1d(struct movement_state_1d *state) {
|
||||
if (state->speed != 0 && state->start_time == 0) {
|
||||
state->start_time = k_uptime_get();
|
||||
} else if (state->speed == 0) {
|
||||
state->start_time = 0;
|
||||
}
|
||||
}
|
||||
static void set_start_times_for_activity(struct movement_state_2d *state) {
|
||||
set_start_times_for_activity_1d(&state->x);
|
||||
set_start_times_for_activity_1d(&state->y);
|
||||
}
|
||||
|
||||
static void update_work_scheduling(const struct device *dev) {
|
||||
struct behavior_input_two_axis_data *data = dev->data;
|
||||
const struct behavior_input_two_axis_config *cfg = dev->config;
|
||||
|
||||
set_start_times_for_activity(&data->state);
|
||||
|
||||
if (should_be_working(data)) {
|
||||
k_work_schedule(&data->tick_work, K_MSEC(cfg->trigger_period_ms));
|
||||
} else {
|
||||
k_work_cancel_delayable(&data->tick_work);
|
||||
}
|
||||
}
|
||||
|
||||
int behavior_input_two_axis_adjust_speed(const struct device *dev, int16_t dx, int16_t dy) {
|
||||
struct behavior_input_two_axis_data *data = dev->data;
|
||||
|
||||
LOG_DBG("Adjusting: %d %d", dx, dy);
|
||||
data->state.x.speed += dx;
|
||||
data->state.y.speed += dy;
|
||||
|
||||
LOG_DBG("After: %d %d", data->state.x.speed, data->state.y.speed);
|
||||
|
||||
update_work_scheduling(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int behavior_input_two_axis_init(const struct device *dev) {
|
||||
struct behavior_input_two_axis_data *data = dev->data;
|
||||
|
||||
data->dev = dev;
|
||||
k_work_init_delayable(&data->tick_work, tick_work_cb);
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
|
||||
const struct device *behavior_dev = zmk_behavior_get_binding(binding->behavior_dev);
|
||||
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
|
||||
int16_t x = MOVE_X_DECODE(binding->param1);
|
||||
int16_t y = MOVE_Y_DECODE(binding->param1);
|
||||
|
||||
behavior_input_two_axis_adjust_speed(behavior_dev, x, y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
const struct device *behavior_dev = zmk_behavior_get_binding(binding->behavior_dev);
|
||||
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
|
||||
int16_t x = MOVE_X_DECODE(binding->param1);
|
||||
int16_t y = MOVE_Y_DECODE(binding->param1);
|
||||
|
||||
behavior_input_two_axis_adjust_speed(behavior_dev, -x, -y);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_input_two_axis_driver_api = {
|
||||
.binding_pressed = on_keymap_binding_pressed, .binding_released = on_keymap_binding_released};
|
||||
|
||||
#define ITA_INST(n) \
|
||||
static struct behavior_input_two_axis_data behavior_input_two_axis_data_##n = {}; \
|
||||
static struct behavior_input_two_axis_config behavior_input_two_axis_config_##n = { \
|
||||
.x_code = DT_INST_PROP(n, x_input_code), \
|
||||
.y_code = DT_INST_PROP(n, y_input_code), \
|
||||
.trigger_period_ms = DT_INST_PROP(n, trigger_period_ms), \
|
||||
.delay_ms = DT_INST_PROP_OR(n, delay_ms, 0), \
|
||||
.time_to_max_speed_ms = DT_INST_PROP(n, time_to_max_speed_ms), \
|
||||
.acceleration_exponent = DT_INST_PROP_OR(n, acceleration_exponent, 1), \
|
||||
}; \
|
||||
BEHAVIOR_DT_INST_DEFINE( \
|
||||
n, behavior_input_two_axis_init, NULL, &behavior_input_two_axis_data_##n, \
|
||||
&behavior_input_two_axis_config_##n, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \
|
||||
&behavior_input_two_axis_driver_api);
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(ITA_INST)
|
|
@ -11,9 +11,8 @@
|
|||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <zmk/behavior.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zephyr/input/input.h>
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
#include <zmk/event_manager.h>
|
||||
#include <zmk/events/mouse_button_state_changed.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
|
@ -21,31 +20,19 @@ LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
static int behavior_mouse_key_press_init(const struct device *dev) { return 0; };
|
||||
|
||||
static void process_key_state(const struct device *dev, int32_t val, bool pressed) {
|
||||
for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
|
||||
if (val & BIT(i)) {
|
||||
WRITE_BIT(val, i, 0);
|
||||
input_report_key(dev, INPUT_BTN_0 + i, pressed ? 1 : 0, val == 0, K_FOREVER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int on_keymap_binding_pressed(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
|
||||
process_key_state(zmk_behavior_get_binding(binding->behavior_dev), binding->param1, true);
|
||||
|
||||
return 0;
|
||||
return raise_zmk_mouse_button_state_changed_from_encoded(binding->param1, true,
|
||||
event.timestamp);
|
||||
}
|
||||
|
||||
static int on_keymap_binding_released(struct zmk_behavior_binding *binding,
|
||||
struct zmk_behavior_binding_event event) {
|
||||
LOG_DBG("position %d keycode 0x%02X", event.position, binding->param1);
|
||||
|
||||
process_key_state(zmk_behavior_get_binding(binding->behavior_dev), binding->param1, false);
|
||||
|
||||
return 0;
|
||||
return raise_zmk_mouse_button_state_changed_from_encoded(binding->param1, false,
|
||||
event.timestamp);
|
||||
}
|
||||
|
||||
static const struct behavior_driver_api behavior_mouse_key_press_driver_api = {
|
||||
|
|
|
@ -27,9 +27,8 @@ static uint8_t keys_held = 0;
|
|||
|
||||
#if IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static struct zmk_hid_mouse_report mouse_report = {
|
||||
.report_id = ZMK_HID_REPORT_ID_MOUSE,
|
||||
.body = {.buttons = 0, .d_x = 0, .d_y = 0, .d_scroll_y = 0}};
|
||||
static struct zmk_hid_mouse_report mouse_report = {.report_id = ZMK_HID_REPORT_ID_MOUSE,
|
||||
.body = {.buttons = 0}};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
|
@ -432,37 +431,7 @@ int zmk_hid_mouse_buttons_release(zmk_mouse_button_flags_t buttons) {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void zmk_hid_mouse_movement_set(int16_t x, int16_t y) {
|
||||
mouse_report.body.d_x = x;
|
||||
mouse_report.body.d_y = y;
|
||||
LOG_DBG("Mouse movement set to %d/%d", mouse_report.body.d_x, mouse_report.body.d_y);
|
||||
}
|
||||
|
||||
void zmk_hid_mouse_movement_update(int16_t x, int16_t y) {
|
||||
mouse_report.body.d_x += x;
|
||||
mouse_report.body.d_y += y;
|
||||
LOG_DBG("Mouse movement updated to %d/%d", mouse_report.body.d_x, mouse_report.body.d_y);
|
||||
}
|
||||
|
||||
void zmk_hid_mouse_scroll_set(int8_t x, int8_t y) {
|
||||
mouse_report.body.d_scroll_x = x;
|
||||
mouse_report.body.d_scroll_y = y;
|
||||
LOG_DBG("Mouse scroll set to %d/%d", mouse_report.body.d_scroll_x,
|
||||
mouse_report.body.d_scroll_y);
|
||||
}
|
||||
|
||||
void zmk_hid_mouse_scroll_update(int8_t x, int8_t y) {
|
||||
mouse_report.body.d_scroll_x += x;
|
||||
mouse_report.body.d_scroll_y += y;
|
||||
LOG_DBG("Mouse scroll updated to X: %d/%d", mouse_report.body.d_scroll_x,
|
||||
mouse_report.body.d_scroll_y);
|
||||
}
|
||||
|
||||
void zmk_hid_mouse_clear(void) {
|
||||
LOG_DBG("Mouse report cleared");
|
||||
memset(&mouse_report.body, 0, sizeof(mouse_report.body));
|
||||
}
|
||||
void zmk_hid_mouse_clear(void) { memset(&mouse_report.body, 0, sizeof(mouse_report.body)); }
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
|
|
|
@ -380,6 +380,7 @@ int zmk_hog_send_mouse_report(struct zmk_hid_mouse_report_body *report) {
|
|||
|
||||
return 0;
|
||||
};
|
||||
|
||||
#endif // IS_ENABLED(CONFIG_ZMK_MOUSE)
|
||||
|
||||
static int zmk_hog_init(void) {
|
||||
|
|
|
@ -14,10 +14,6 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
|
|||
|
||||
#include <zmk/display.h>
|
||||
|
||||
#ifdef CONFIG_ZMK_MOUSE
|
||||
#include <zmk/mouse.h>
|
||||
#endif /* CONFIG_ZMK_MOUSE */
|
||||
|
||||
int main(void) {
|
||||
LOG_INF("Welcome to ZMK!\n");
|
||||
|
||||
|
|
43
app/src/mouse.c
Normal file
43
app/src/mouse.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2021 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <drivers/behavior.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zmk/events/mouse_button_state_changed.h>
|
||||
#include <zmk/hid.h>
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/mouse.h>
|
||||
|
||||
static void listener_mouse_button_pressed(const struct zmk_mouse_button_state_changed *ev) {
|
||||
LOG_DBG("buttons: 0x%02X", ev->buttons);
|
||||
zmk_hid_mouse_buttons_press(ev->buttons);
|
||||
zmk_endpoints_send_mouse_report();
|
||||
}
|
||||
|
||||
static void listener_mouse_button_released(const struct zmk_mouse_button_state_changed *ev) {
|
||||
LOG_DBG("buttons: 0x%02X", ev->buttons);
|
||||
zmk_hid_mouse_buttons_release(ev->buttons);
|
||||
zmk_endpoints_send_mouse_report();
|
||||
}
|
||||
|
||||
int mouse_listener(const zmk_event_t *eh) {
|
||||
const struct zmk_mouse_button_state_changed *mbt_ev = as_zmk_mouse_button_state_changed(eh);
|
||||
if (mbt_ev) {
|
||||
if (mbt_ev->state) {
|
||||
listener_mouse_button_pressed(mbt_ev);
|
||||
} else {
|
||||
listener_mouse_button_released(mbt_ev);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
ZMK_LISTENER(mouse_listener, mouse_listener);
|
||||
ZMK_SUBSCRIPTION(mouse_listener, zmk_mouse_button_state_changed);
|
|
@ -1,8 +0,0 @@
|
|||
# Copyright (c) 2023 The ZMK Contributors
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
config ZMK_MOUSE
|
||||
bool "Mouse Emulation"
|
||||
select INPUT
|
||||
select INPUT_THREAD_PRIORITY_OVERRIDE
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2020 The ZMK Contributors
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#define DT_DRV_COMPAT zmk_input_listener
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/input/input.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
|
||||
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
#include <zmk/endpoints.h>
|
||||
#include <zmk/mouse.h>
|
||||
#include <zmk/hid.h>
|
||||
|
||||
#define ONE_IF_DEV_OK(n) \
|
||||
COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_PHANDLE(n, device), okay), (1 +), (0 +))
|
||||
|
||||
#define VALID_LISTENER_COUNT (DT_INST_FOREACH_STATUS_OKAY(ONE_IF_DEV_OK) 0)
|
||||
|
||||
#if VALID_LISTENER_COUNT > 0
|
||||
|
||||
enum input_listener_xy_data_mode {
|
||||
INPUT_LISTENER_XY_DATA_MODE_NONE,
|
||||
INPUT_LISTENER_XY_DATA_MODE_REL,
|
||||
INPUT_LISTENER_XY_DATA_MODE_ABS,
|
||||
};
|
||||
|
||||
struct input_listener_xy_data {
|
||||
enum input_listener_xy_data_mode mode;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
};
|
||||
|
||||
struct input_listener_data {
|
||||
union {
|
||||
struct {
|
||||
struct input_listener_xy_data data;
|
||||
struct input_listener_xy_data wheel_data;
|
||||
|
||||
uint8_t button_set;
|
||||
uint8_t button_clear;
|
||||
} mouse;
|
||||
};
|
||||
};
|
||||
|
||||
struct input_listener_config {
|
||||
bool xy_swap;
|
||||
bool x_invert;
|
||||
bool y_invert;
|
||||
uint16_t scale_multiplier;
|
||||
uint16_t scale_divisor;
|
||||
};
|
||||
|
||||
static void handle_rel_code(struct input_listener_data *data, struct input_event *evt) {
|
||||
switch (evt->code) {
|
||||
case INPUT_REL_X:
|
||||
data->mouse.data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
|
||||
data->mouse.data.x += evt->value;
|
||||
break;
|
||||
case INPUT_REL_Y:
|
||||
data->mouse.data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
|
||||
data->mouse.data.y += evt->value;
|
||||
break;
|
||||
case INPUT_REL_WHEEL:
|
||||
data->mouse.wheel_data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
|
||||
data->mouse.wheel_data.y += evt->value;
|
||||
break;
|
||||
case INPUT_REL_HWHEEL:
|
||||
data->mouse.wheel_data.mode = INPUT_LISTENER_XY_DATA_MODE_REL;
|
||||
data->mouse.wheel_data.x += evt->value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_abs_code(const struct input_listener_config *config,
|
||||
struct input_listener_data *data, struct input_event *evt) {}
|
||||
|
||||
static void handle_key_code(const struct input_listener_config *config,
|
||||
struct input_listener_data *data, struct input_event *evt) {
|
||||
int8_t btn;
|
||||
|
||||
switch (evt->code) {
|
||||
case INPUT_BTN_0:
|
||||
case INPUT_BTN_1:
|
||||
case INPUT_BTN_2:
|
||||
case INPUT_BTN_3:
|
||||
case INPUT_BTN_4:
|
||||
btn = evt->code - INPUT_BTN_0;
|
||||
if (evt->value > 0) {
|
||||
WRITE_BIT(data->mouse.button_set, btn, 1);
|
||||
} else {
|
||||
WRITE_BIT(data->mouse.button_clear, btn, 1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void swap_xy(struct input_event *evt) {
|
||||
switch (evt->code) {
|
||||
case INPUT_REL_X:
|
||||
evt->code = INPUT_REL_Y;
|
||||
break;
|
||||
case INPUT_REL_Y:
|
||||
evt->code = INPUT_REL_X;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool is_x_data(const struct input_event *evt) {
|
||||
return evt->type == INPUT_EV_REL && evt->code == INPUT_REL_X;
|
||||
}
|
||||
|
||||
static inline bool is_y_data(const struct input_event *evt) {
|
||||
return evt->type == INPUT_EV_REL && evt->code == INPUT_REL_Y;
|
||||
}
|
||||
|
||||
static void filter_with_input_config(const struct input_listener_config *cfg,
|
||||
struct input_event *evt) {
|
||||
if (!evt->dev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cfg->xy_swap) {
|
||||
swap_xy(evt);
|
||||
}
|
||||
|
||||
if ((cfg->x_invert && is_x_data(evt)) || (cfg->y_invert && is_y_data(evt))) {
|
||||
evt->value = -(evt->value);
|
||||
}
|
||||
|
||||
evt->value = (int16_t)((evt->value * cfg->scale_multiplier) / cfg->scale_divisor);
|
||||
}
|
||||
|
||||
static void clear_xy_data(struct input_listener_xy_data *data) {
|
||||
data->x = data->y = 0;
|
||||
data->mode = INPUT_LISTENER_XY_DATA_MODE_NONE;
|
||||
}
|
||||
|
||||
static void input_handler(const struct input_listener_config *config,
|
||||
struct input_listener_data *data, struct input_event *evt) {
|
||||
// First, filter to update the event data as needed.
|
||||
filter_with_input_config(config, evt);
|
||||
|
||||
switch (evt->type) {
|
||||
case INPUT_EV_REL:
|
||||
handle_rel_code(data, evt);
|
||||
break;
|
||||
case INPUT_EV_ABS:
|
||||
handle_abs_code(config, data, evt);
|
||||
break;
|
||||
case INPUT_EV_KEY:
|
||||
handle_key_code(config, data, evt);
|
||||
break;
|
||||
}
|
||||
|
||||
if (evt->sync) {
|
||||
if (data->mouse.wheel_data.mode == INPUT_LISTENER_XY_DATA_MODE_REL) {
|
||||
zmk_hid_mouse_scroll_set(data->mouse.wheel_data.x, data->mouse.wheel_data.y);
|
||||
}
|
||||
|
||||
if (data->mouse.data.mode == INPUT_LISTENER_XY_DATA_MODE_REL) {
|
||||
zmk_hid_mouse_movement_set(data->mouse.data.x, data->mouse.data.y);
|
||||
}
|
||||
|
||||
if (data->mouse.button_set != 0) {
|
||||
for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
|
||||
if ((data->mouse.button_set & BIT(i)) != 0) {
|
||||
zmk_hid_mouse_button_press(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data->mouse.button_clear != 0) {
|
||||
for (int i = 0; i < ZMK_HID_MOUSE_NUM_BUTTONS; i++) {
|
||||
if ((data->mouse.button_clear & BIT(i)) != 0) {
|
||||
zmk_hid_mouse_button_release(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
zmk_endpoints_send_mouse_report();
|
||||
zmk_hid_mouse_scroll_set(0, 0);
|
||||
zmk_hid_mouse_movement_set(0, 0);
|
||||
|
||||
clear_xy_data(&data->mouse.data);
|
||||
clear_xy_data(&data->mouse.wheel_data);
|
||||
|
||||
data->mouse.button_set = data->mouse.button_clear = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // VALID_LISTENER_COUNT > 0
|
||||
|
||||
#define IL_INST(n) \
|
||||
COND_CODE_1( \
|
||||
DT_NODE_HAS_STATUS(DT_INST_PHANDLE(n, device), okay), \
|
||||
(static const struct input_listener_config config_##n = \
|
||||
{ \
|
||||
.xy_swap = DT_INST_PROP(n, xy_swap), \
|
||||
.x_invert = DT_INST_PROP(n, x_invert), \
|
||||
.y_invert = DT_INST_PROP(n, y_invert), \
|
||||
.scale_multiplier = DT_INST_PROP(n, scale_multiplier), \
|
||||
.scale_divisor = DT_INST_PROP(n, scale_divisor), \
|
||||
}; \
|
||||
static struct input_listener_data data_##n = {}; \
|
||||
void input_handler_##n(struct input_event *evt) { \
|
||||
input_handler(&config_##n, &data_##n, evt); \
|
||||
} INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_INST_PHANDLE(n, device)), input_handler_##n);), \
|
||||
())
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(IL_INST)
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,18 +0,0 @@
|
|||
movement_set: Mouse movement set to -1/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -5/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -5/-5
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/-5
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,33 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
&mmv_input_listener {
|
||||
scale-multiplier = <5>;
|
||||
scale-divisor = <3>;
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_LEFT &mmv MOVE_UP
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,18 +0,0 @@
|
|||
movement_set: Mouse movement set to 1/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 2/2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 2/2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 3/2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 3/3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,33 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
&mmv_input_listener {
|
||||
x-invert;
|
||||
y-invert;
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_LEFT &mmv MOVE_UP
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,18 +0,0 @@
|
|||
movement_set: Mouse movement set to 0/-1
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,32 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
&mmv_input_listener {
|
||||
xy-swap;
|
||||
};
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_LEFT &mmv MOVE_UP
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,18 +0,0 @@
|
|||
movement_set: Mouse movement set to -1/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,29 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <behaviors/mouse_move.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_LEFT &mmv MOVE_UP
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,24 +0,0 @@
|
|||
movement_set: Mouse movement set to -1/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -2/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to -3/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 1/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 2/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 2/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 3/0
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,29 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <behaviors/mouse_move.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_LEFT &mmv MOVE_RIGHT
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -1 +0,0 @@
|
|||
s/.*hid_mouse_//p
|
|
@ -1,24 +0,0 @@
|
|||
movement_set: Mouse movement set to 0/-1
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/-2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/-3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/1
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/2
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
||||
movement_set: Mouse movement set to 0/3
|
||||
scroll_set: Mouse scroll set to 0/0
|
||||
movement_set: Mouse movement set to 0/0
|
|
@ -1,6 +0,0 @@
|
|||
CONFIG_GPIO=n
|
||||
CONFIG_ZMK_BLE=n
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_ZMK_LOG_LEVEL_DBG=y
|
||||
CONFIG_ZMK_MOUSE=y
|
|
@ -1,29 +0,0 @@
|
|||
#include <behaviors.dtsi>
|
||||
#include <behaviors/mouse_move.dtsi>
|
||||
#include <dt-bindings/zmk/keys.h>
|
||||
#include <dt-bindings/zmk/kscan_mock.h>
|
||||
#include <dt-bindings/zmk/mouse.h>
|
||||
|
||||
/ {
|
||||
keymap {
|
||||
compatible = "zmk,keymap";
|
||||
label ="Default keymap";
|
||||
|
||||
default_layer {
|
||||
bindings = <
|
||||
&mmv MOVE_UP &mmv MOVE_DOWN
|
||||
&none &none
|
||||
>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
&kscan {
|
||||
events = <
|
||||
ZMK_MOCK_PRESS(0,0,100)
|
||||
ZMK_MOCK_RELEASE(0,0,10)
|
||||
ZMK_MOCK_PRESS(0,1,100)
|
||||
ZMK_MOCK_RELEASE(0,1,10)
|
||||
>;
|
||||
};
|
|
@ -14,34 +14,34 @@ ZMK is currently missing some features found in other popular firmware. This tab
|
|||
| Legend: | ✅ Supported | 🚧 Under Development | 💡 Planned |
|
||||
| :------ | :----------- | :------------------- | :--------- |
|
||||
|
||||
| **Feature** | ZMK | BlueMicro | QMK |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------------- | :-: | :-------: | :-: |
|
||||
| Low Latency BLE Support | ✅ | ✅ | |
|
||||
| Multi-Device BLE Support | ✅ | | |
|
||||
| [USB Connectivity](behaviors/outputs.md) | ✅ | ✅ | ✅ |
|
||||
| User Configuration Repositories | ✅ | | |
|
||||
| Split Keyboard Support | ✅ | ✅ | ✅ |
|
||||
| [Keymaps and Layers](behaviors/layers.md) | ✅ | ✅ | ✅ |
|
||||
| [Hold-Tap](behaviors/hold-tap.mdx) (which includes [Mod-Tap](behaviors/mod-tap.md) and [Layer-Tap](behaviors/layers.md#layer-tap)) | ✅ | ✅ | ✅ |
|
||||
| [Tap-Dance](behaviors/tap-dance.mdx) | ✅ | ✅[^2] | ✅ |
|
||||
| [Keyboard Codes](codes/index.mdx#keyboard) | ✅ | ✅ | ✅ |
|
||||
| [Media](codes/index.mdx#media-controls) & [Consumer](codes/index.mdx#consumer-controls) Codes | ✅ | ✅ | ✅ |
|
||||
| [Encoders](features/encoders.md) | ✅ | ✅ | ✅ |
|
||||
| [Display Support](features/displays.md)[^1] | 🚧 | 🚧 | ✅ |
|
||||
| [RGB Underglow](features/underglow.md) | ✅ | ✅ | ✅ |
|
||||
| [Backlight](features/backlight.mdx) | ✅ | ✅ | ✅ |
|
||||
| One Shot Keys | ✅ | ✅ | ✅ |
|
||||
| [Combo Keys](features/combos.md) | ✅ | | ✅ |
|
||||
| [Macros](behaviors/macros.md) | ✅ | ✅ | ✅ |
|
||||
| Mouse Keys | ✅ | ✅ | ✅ |
|
||||
| Low Active Power Usage | ✅ | | |
|
||||
| Low Power Sleep States | ✅ | ✅ | |
|
||||
| [Low Power Mode (VCC Shutoff)](behaviors/power.md) | ✅ | ✅ | |
|
||||
| Battery Reporting | ✅ | ✅ | |
|
||||
| Shell over BLE | 💡 | | |
|
||||
| Realtime Keymap Updating | 💡 | | ✅ |
|
||||
| AVR/8 Bit | | | ✅ |
|
||||
| [Wide Range of ARM Chips Supported](https://docs.zephyrproject.org/3.5.0/boards/index.html) | ✅ | | |
|
||||
| **Feature** | ZMK | BlueMicro | QMK |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | :-: | :-------: | :-: |
|
||||
| Low Latency BLE Support | ✅ | ✅ | |
|
||||
| Multi-Device BLE Support | ✅ | | |
|
||||
| [USB Connectivity](keymaps/behaviors/outputs.md) | ✅ | ✅ | ✅ |
|
||||
| User Configuration Repositories | ✅ | | |
|
||||
| Split Keyboard Support | ✅ | ✅ | ✅ |
|
||||
| [Keymaps and Layers](keymaps/behaviors/layers.md) | ✅ | ✅ | ✅ |
|
||||
| [Hold-Tap](keymaps/behaviors/hold-tap.mdx) (which includes [Mod-Tap](keymaps/behaviors/mod-tap.md) and [Layer-Tap](keymaps/behaviors/layers.md#layer-tap)) | ✅ | ✅ | ✅ |
|
||||
| [Tap-Dance](keymaps/behaviors/tap-dance.mdx) | ✅ | ✅[^2] | ✅ |
|
||||
| [Keyboard Keycodes](keymaps/list-of-keycodes.mdx#keyboard) | ✅ | ✅ | ✅ |
|
||||
| [Media](keymaps/list-of-keycodes.mdx#media-controls) & [Consumer](keymaps/list-of-keycodes.mdx#consumer-controls) Codes | ✅ | ✅ | ✅ |
|
||||
| [Encoders](features/encoders.md) | ✅ | ✅ | ✅ |
|
||||
| [Display Support](features/displays.md)[^1] | 🚧 | 🚧 | ✅ |
|
||||
| [RGB Underglow](features/underglow.md) | ✅ | ✅ | ✅ |
|
||||
| [Backlight](features/backlight.mdx) | ✅ | ✅ | ✅ |
|
||||
| One Shot Keys | ✅ | ✅ | ✅ |
|
||||
| [Combo Keys](keymaps/combos.md) | ✅ | | ✅ |
|
||||
| [Macros](keymaps/behaviors/macros.md) | ✅ | ✅ | ✅ |
|
||||
| Mouse Keys | 🚧 | ✅ | ✅ |
|
||||
| Low Active Power Usage | ✅ | | |
|
||||
| Low Power Sleep States | ✅ | ✅ | |
|
||||
| [Low Power Mode (VCC Shutoff)](keymaps/behaviors/power.md) | ✅ | ✅ | |
|
||||
| Battery Reporting | ✅ | ✅ | |
|
||||
| Shell over BLE | 💡 | | |
|
||||
| Realtime Keymap Updating | 💡 | | ✅ |
|
||||
| AVR/8 Bit | | | ✅ |
|
||||
| [Wide Range of ARM Chips Supported](https://docs.zephyrproject.org/3.5.0/boards/index.html) | ✅ | | |
|
||||
|
||||
[^2]: Tap-Dances are limited to single and double-tap on BlueMicro
|
||||
[^1]: OLEDs are currently proof of concept in ZMK.
|
||||
|
|
|
@ -43,8 +43,6 @@ Below is a summary of pre-defined behavior bindings and user-definable behaviors
|
|||
| Binding | Behavior | Description |
|
||||
| ------- | ----------------------------------------------------------- | ------------------------------- |
|
||||
| `&mkp` | [Mouse Button Press](mouse-emulation.md#mouse-button-press) | Emulates pressing mouse buttons |
|
||||
| `&mmv` | [Mouse Button Press](mouse-emulation.md#mouse-move) | Emulates mouse movement |
|
||||
| `&msc` | [Mouse Button Press](mouse-emulation.md#mouse-scroll) | Emulates mouse scrolling |
|
||||
|
||||
## Reset Behaviors
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ sidebar_label: Mouse Emulation
|
|||
|
||||
## Summary
|
||||
|
||||
Mouse emulation behaviors send mouse events, including mouse button presses, cursor movement and scrolling.
|
||||
Mouse emulation behaviors send mouse events. Currently, only mouse button presses are supported, but movement
|
||||
and scroll action support is planned for the future.
|
||||
|
||||
:::warning[Refreshing the HID descriptor]
|
||||
|
||||
|
@ -16,12 +17,14 @@ The mouse functionality will not work over BLE until that is done.
|
|||
|
||||
## Configuration Option
|
||||
|
||||
To use any of the behaviors documented here, the ZMK mouse feature must be enabled explicitly via a config option:
|
||||
This feature can be enabled or disabled explicitly via a config option:
|
||||
|
||||
```
|
||||
CONFIG_ZMK_MOUSE=y
|
||||
```
|
||||
|
||||
If you use the mouse key press behavior in your keymap, the feature will automatically be enabled for you.
|
||||
|
||||
## Mouse Button Defines
|
||||
|
||||
To make it easier to encode the HID mouse button numeric values, include
|
||||
|
@ -66,67 +69,3 @@ This example will send press of the fourth mouse button when the binding is trig
|
|||
```
|
||||
&mkp MB4
|
||||
```
|
||||
|
||||
## Mouse Move
|
||||
|
||||
This behavior sends mouse X/Y movement events to the connected host.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
- Reference: `&mmv`
|
||||
- Parameter: A `uint32` with 16-bits each used for vertical and horizontal velocity.
|
||||
|
||||
The following defines can be passed for the parameter:
|
||||
|
||||
| Define | Action |
|
||||
| :----------- | :--------- |
|
||||
| `MOVE_UP` | Move up |
|
||||
| `MOVE_DOWN` | Move down |
|
||||
| `MOVE_LEFT` | Move left |
|
||||
| `MOVE_RIGHT` | Move right |
|
||||
|
||||
### Examples
|
||||
|
||||
The following will send a scroll down event to the host when pressed/held:
|
||||
|
||||
```
|
||||
&mmv MOVE_DOWN
|
||||
```
|
||||
|
||||
The following will send a scroll left event to the host when pressed/held:
|
||||
|
||||
```
|
||||
&mmv MOVE_LEFT
|
||||
```
|
||||
|
||||
## Mouse Scroll
|
||||
|
||||
This behavior sends vertical and horizontal scroll events to the connected host.
|
||||
|
||||
### Behavior Binding
|
||||
|
||||
- Reference: `&msc`
|
||||
- Parameter: A `uint32` with 16-bits each used for vertical and horizontal velocity.
|
||||
|
||||
The following defines can be passed for the parameter:
|
||||
|
||||
| Define | Action |
|
||||
| :----------- | :--------- |
|
||||
| `MOVE_UP` | Move up |
|
||||
| `MOVE_DOWN` | Move down |
|
||||
| `MOVE_LEFT` | Move left |
|
||||
| `MOVE_RIGHT` | Move right |
|
||||
|
||||
### Examples
|
||||
|
||||
The following will send a scroll down event to the host when pressed/held:
|
||||
|
||||
```
|
||||
&msc MOVE_DOWN
|
||||
```
|
||||
|
||||
The following will send a scroll left event to the host when pressed/held:
|
||||
|
||||
```
|
||||
&msc MOVE_LEFT
|
||||
```
|
||||
|
|
Loading…
Add table
Reference in a new issue