Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[core][new feature]Pointing device modes #21426

Open
wants to merge 20 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions builddefs/common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
VPATH += $(QUANTUM_DIR)/pointing_device
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_auto_mouse.c
SRC += $(QUANTUM_DIR)/pointing_device/pointing_device_modes.c
SRC += $(QUANTUM_DIR)/process_keycode/process_pointing_modes.c
ifneq ($(strip $(POINTING_DEVICE_DRIVER)), custom)
SRC += drivers/sensors/$(strip $(POINTING_DEVICE_DRIVER)).c
OPT_DEFS += -DPOINTING_DEVICE_DRIVER_$(strip $(shell echo $(POINTING_DEVICE_DRIVER) | tr '[:lower:]' '[:upper:]'))
Expand Down
3 changes: 1 addition & 2 deletions data/constants/keycodes/keycodes_0.0.1.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
"0x52C0/0x001F": {
"define": "QK_LAYER_TAP_TOGGLE"
},
// 0x52E0/0x001F - UNUSED
// 0x5300/0x02FF - UNUSED
// 0x5346/0x02B9 - UNUSED
"0x5600/0x00FF": {
"define": "QK_SWAP_HANDS"
},
Expand Down
1 change: 1 addition & 0 deletions data/constants/keycodes/keycodes_0.0.7.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

31 changes: 31 additions & 0 deletions data/constants/keycodes/keycodes_0.0.7_pointing_modes.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"ranges": {
"0x5302/0x001F": {
"define": "QK_POINTING_MODES_MO"
},
"0x5322/0x001F": {
"define": "QK_POINTING_MODES_TG"
},
"0x5342/0x0001": {
"define": "QK_POINTING_MODES_UTIL"
}
},
"keycodes": {
"0x5342": {
"group": "pointing_modes_util",
"key": "QK_PM_CYCLE_DEVICES",
"label": "Cycle pointing mode device",
"aliases": [
"PM_CYDEV"
]
},
"0x5343":{
"group": "pointing_modes_util",
"key": "QK_PM_CYCLE_PRECISION",
"label": "Cycle through precision values for active device",
"aliases": [
"PM_CYCPRE"
]
}
}
}
843 changes: 834 additions & 9 deletions docs/features/pointing_device.md

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion quantum/keyboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ typedef struct {
uint8_t row;
} keypos_t;

typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4, DIP_SWITCH_ON_EVENT = 5, DIP_SWITCH_OFF_EVENT = 6 } keyevent_type_t;
typedef enum keyevent_type_t { TICK_EVENT = 0, KEY_EVENT = 1, ENCODER_CW_EVENT = 2, ENCODER_CCW_EVENT = 3, COMBO_EVENT = 4, DIP_SWITCH_ON_EVENT = 5, DIP_SWITCH_OFF_EVENT = 6, POINTING_MODES_EVENT = 7} keyevent_type_t;

/* key event */
typedef struct {
Expand All @@ -50,6 +50,7 @@ typedef struct {
#define KEYLOC_ENCODER_CCW 252
#define KEYLOC_DIP_SWITCH_ON 251
#define KEYLOC_DIP_SWITCH_OFF 250
#define KEYLOC_POINTING_MODES 249

static inline bool IS_NOEVENT(const keyevent_t event) {
return event.type == TICK_EVENT;
Expand All @@ -69,6 +70,9 @@ static inline bool IS_ENCODEREVENT(const keyevent_t event) {
static inline bool IS_DIPSWITCHEVENT(const keyevent_t event) {
return event.type == DIP_SWITCH_ON_EVENT || event.type == DIP_SWITCH_OFF_EVENT;
}
static inline bool IS_POINTINGEVENT(const keyevent_t event) {
return event.type == POINTING_MODES_EVENT;
}

/* Common keypos_t object factory */
#define MAKE_KEYPOS(row_num, col_num) ((keypos_t){.row = (row_num), .col = (col_num)})
Expand Down Expand Up @@ -103,6 +107,15 @@ static inline bool IS_DIPSWITCHEVENT(const keyevent_t event) {
# define MAKE_DIPSWITCH_OFF_EVENT(switch_id, press) MAKE_EVENT(KEYLOC_DIP_SWITCH_OFF, (switch_id), (press), DIP_SWITCH_OFF_EVENT)
#endif // DIP_SWITCH_MAP_ENABLE

#ifdef POINTING_DEVICE_MODES_ENABLE
/* Pointing mode events */
# ifdef POINTING_MODES_8WAY_MAP_ENABLE
# define MAKE_POINTING_MODES_EVENT(map_id, dir, press) MAKE_EVENT(KEYLOC_POINTING_MODES, (uint8_t)(((map_id) << 3) | (dir)), (press), POINTING_MODES_EVENT)
# else
# define MAKE_POINTING_MODES_EVENT(map_id, dir, press) MAKE_EVENT(KEYLOC_POINTING_MODES, (uint8_t)(((map_id) << 2) | (dir)), (press), POINTING_MODES_EVENT)
# endif // POINTING_MODES_8WAY_MAP_ENABLE
#endif // POINTING_DEVICE_MODES_ENABLE

/* it runs once at early stage of startup before keyboard_init. */
void keyboard_setup(void);
/* it runs once after initializing host side protocol, debug and MCU peripherals. */
Expand Down
15 changes: 15 additions & 0 deletions quantum/keycodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ enum qk_keycode_ranges {
QK_LAYER_TAP_TOGGLE_MAX = 0x52DF,
QK_PERSISTENT_DEF_LAYER = 0x52E0,
QK_PERSISTENT_DEF_LAYER_MAX = 0x52FF,
QK_POINTING_MODES_MO = 0x5302,
QK_POINTING_MODES_MO_MAX = 0x5321,
QK_POINTING_MODES_TG = 0x5322,
QK_POINTING_MODES_TG_MAX = 0x5341,
QK_POINTING_MODES_UTIL = 0x5342,
QK_POINTING_MODES_UTIL_MAX = 0x5343,
QK_SWAP_HANDS = 0x5600,
QK_SWAP_HANDS_MAX = 0x56FF,
QK_TAP_DANCE = 0x5700,
Expand Down Expand Up @@ -314,6 +320,8 @@ enum qk_keycode_defines {
KC_RIGHT_SHIFT = 0x00E5,
KC_RIGHT_ALT = 0x00E6,
KC_RIGHT_GUI = 0x00E7,
QK_PM_CYCLE_DEVICES = 0x5342,
QK_PM_CYCLE_PRECISION = 0x5343,
QK_SWAP_HANDS_TOGGLE = 0x56F0,
QK_SWAP_HANDS_TAP_TOGGLE = 0x56F1,
QK_SWAP_HANDS_MOMENTARY_ON = 0x56F2,
Expand Down Expand Up @@ -977,6 +985,8 @@ enum qk_keycode_defines {
KC_RGUI = KC_RIGHT_GUI,
KC_RCMD = KC_RIGHT_GUI,
KC_RWIN = KC_RIGHT_GUI,
PM_CYDEV = QK_PM_CYCLE_DEVICES,
PM_CYCPRE = QK_PM_CYCLE_PRECISION,
SH_TOGG = QK_SWAP_HANDS_TOGGLE,
SH_TT = QK_SWAP_HANDS_TAP_TOGGLE,
SH_MON = QK_SWAP_HANDS_MOMENTARY_ON,
Expand Down Expand Up @@ -1465,6 +1475,9 @@ enum qk_keycode_defines {
#define IS_QK_ONE_SHOT_MOD(code) ((code) >= QK_ONE_SHOT_MOD && (code) <= QK_ONE_SHOT_MOD_MAX)
#define IS_QK_LAYER_TAP_TOGGLE(code) ((code) >= QK_LAYER_TAP_TOGGLE && (code) <= QK_LAYER_TAP_TOGGLE_MAX)
#define IS_QK_PERSISTENT_DEF_LAYER(code) ((code) >= QK_PERSISTENT_DEF_LAYER && (code) <= QK_PERSISTENT_DEF_LAYER_MAX)
#define IS_QK_POINTING_MODES_MO(code) ((code) >= QK_POINTING_MODES_MO && (code) <= QK_POINTING_MODES_MO_MAX)
#define IS_QK_POINTING_MODES_TG(code) ((code) >= QK_POINTING_MODES_TG && (code) <= QK_POINTING_MODES_TG_MAX)
#define IS_QK_POINTING_MODES_UTIL(code) ((code) >= QK_POINTING_MODES_UTIL && (code) <= QK_POINTING_MODES_UTIL_MAX)
#define IS_QK_SWAP_HANDS(code) ((code) >= QK_SWAP_HANDS && (code) <= QK_SWAP_HANDS_MAX)
#define IS_QK_TAP_DANCE(code) ((code) >= QK_TAP_DANCE && (code) <= QK_TAP_DANCE_MAX)
#define IS_QK_MAGIC(code) ((code) >= QK_MAGIC && (code) <= QK_MAGIC_MAX)
Expand All @@ -1491,6 +1504,7 @@ enum qk_keycode_defines {
#define IS_CONSUMER_KEYCODE(code) ((code) >= KC_AUDIO_MUTE && (code) <= KC_LAUNCHPAD)
#define IS_MOUSE_KEYCODE(code) ((code) >= QK_MOUSE_CURSOR_UP && (code) <= QK_MOUSE_ACCELERATION_2)
#define IS_MODIFIER_KEYCODE(code) ((code) >= KC_LEFT_CTRL && (code) <= KC_RIGHT_GUI)
#define IS_POINTING_MODES_UTIL_KEYCODE(code) ((code) >= QK_PM_CYCLE_DEVICES && (code) <= QK_PM_CYCLE_PRECISION)
#define IS_SWAP_HANDS_KEYCODE(code) ((code) >= QK_SWAP_HANDS_TOGGLE && (code) <= QK_SWAP_HANDS_ONE_SHOT)
#define IS_MAGIC_KEYCODE(code) ((code) >= QK_MAGIC_SWAP_CONTROL_CAPS_LOCK && (code) <= QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK)
#define IS_MIDI_KEYCODE(code) ((code) >= QK_MIDI_ON && (code) <= QK_MIDI_PITCH_BEND_UP)
Expand All @@ -1517,6 +1531,7 @@ enum qk_keycode_defines {
#define CONSUMER_KEYCODE_RANGE KC_AUDIO_MUTE ... KC_LAUNCHPAD
#define MOUSE_KEYCODE_RANGE QK_MOUSE_CURSOR_UP ... QK_MOUSE_ACCELERATION_2
#define MODIFIER_KEYCODE_RANGE KC_LEFT_CTRL ... KC_RIGHT_GUI
#define POINTING_MODES_UTIL_KEYCODE_RANGE QK_PM_CYCLE_DEVICES ... QK_PM_CYCLE_PRECISION
#define SWAP_HANDS_KEYCODE_RANGE QK_SWAP_HANDS_TOGGLE ... QK_SWAP_HANDS_ONE_SHOT
#define MAGIC_KEYCODE_RANGE QK_MAGIC_SWAP_CONTROL_CAPS_LOCK ... QK_MAGIC_TOGGLE_ESCAPE_CAPS_LOCK
#define MIDI_KEYCODE_RANGE QK_MIDI_ON ... QK_MIDI_PITCH_BEND_UP
Expand Down
13 changes: 13 additions & 0 deletions quantum/keymap_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key
return keycode_at_encodermap_location(layer, key.col, false);
}
#endif // ENCODER_MAP_ENABLE

#ifdef DIP_SWITCH_MAP_ENABLE
else if (key.row == KEYLOC_DIP_SWITCH_ON && key.col < NUM_DIP_SWITCHES) {
return keycode_at_dip_switch_map_location(key.col, true);
Expand All @@ -216,5 +217,17 @@ __attribute__((weak)) uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key
}
#endif // DIP_SWITCH_MAP_ENABLE

#ifdef POINTING_DEVICE_MODES_ENABLE
# ifdef POINTING_MODES_8WAY_MAP_ENABLE
else if (key.row == KEYLOC_POINTING_MODES && key.col < ((pointing_modes_map_count() << 3) | 0x07)) {
return keycode_at_pointing_modes_map_location(key.col);
}
# else
else if (key.row == KEYLOC_POINTING_MODES && key.col < ((pointing_modes_map_count() << 2) | 0x03)) {
return keycode_at_pointing_modes_map_location(key.col);
}
# endif
#endif // POINTING_DEVICE_MODES_ENABLE

return KC_NO;
}
60 changes: 60 additions & 0 deletions quantum/keymap_introspection.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,3 +171,63 @@ __attribute__((weak)) const key_override_t* key_override_get(uint16_t key_overri
}

#endif // defined(KEY_OVERRIDE_ENABLE)

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pointing mode mapping

#ifdef POINTING_DEVICE_MODES_ENABLE

# define POINTING_MODES_MAP_COUNT_RAW (uint8_t)(sizeof(pointing_modes_maps) / ((POINTING_MODES_NUM_DIRECTIONS) * sizeof(uint16_t)))

uint8_t pointing_modes_map_count_raw(void) {
return POINTING_MODES_MAP_COUNT_RAW;
}

__attribute__((weak)) uint8_t pointing_modes_map_count(void) {
return pointing_modes_map_count_raw();
}

/*
* @brief Retrieve keycode from pointing mode map
*
* Returns keycode from pointing mode map based on 8 bit index location
* breakdown of location:
* mode id | direction
* XXXX XX | XX
*
* NOTE: silently fails and returns KC_NO if mode map out of range
*
* @param[in] map_loc uint8_t
*
* @return uint16_t keycode at pointing mode map location
*/
uint16_t keycode_at_pointing_modes_map_location_raw(uint8_t map_loc) {
# ifdef POINTING_MODES_8WAY_MAP_ENABLE
uint8_t map_id = map_loc >> 3;
uint8_t dir = map_loc & 0x07;
# else
uint8_t map_id = map_loc >> 2;
uint8_t dir = map_loc & 0x03;
# endif // POINTING_MODES_8WAY_MAP_ENABLE

if (map_id < pointing_modes_map_count()) {
return pgm_read_word(&pointing_modes_maps[map_id][dir]);
}
return KC_NO;
}

/*
* @brief Weakly defined function for retreiving keycode from pointing mode map
*
* Defaults to passing map_loc to raw function, would allow interception of
* keycode retrieval process for pointing mode maps
*
* @param[in] map_loc uint8_t
*
* @return uint16_t keycode at pointing mode map location
*/
__attribute__((weak)) uint16_t keycode_at_pointing_modes_map_location(uint8_t map_loc) {
return keycode_at_pointing_modes_map_location_raw(map_loc);
}

#endif // POINTING_DEVICE_MODES_ENABLE
16 changes: 16 additions & 0 deletions quantum/keymap_introspection.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,19 @@ const key_override_t* key_override_get_raw(uint16_t key_override_idx);
const key_override_t* key_override_get(uint16_t key_override_idx);

#endif // defined(KEY_OVERRIDE_ENABLE)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Pointing Mode Mapping

#if defined(POINTING_DEVICE_MODES_ENABLE)

// Get the number of pointing mode maps, stored in firmware
uint8_t pointing_modes_map_count_raw(void);
// Get the number of pointing mode maps, potentially stored dynamically
uint8_t pointing_modes_map_count(void);

// Get the keycode for the pointing mode map location, stored in firmware
uint16_t keycode_at_pointing_modes_map_location_raw(uint8_t map_loc);
// Get the keycode for the encoder mapping location, potentially stored dynamically
uint16_t keycode_at_pointing_modes_map_location(uint8_t map_loc);

#endif // defined(POINTING_DEVICE_MODES_ENABLE)
47 changes: 45 additions & 2 deletions quantum/pointing_device/pointing_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ __attribute__((weak)) bool pointing_device_send(void) {
uint8_t buttons = local_mouse_report.buttons;
memset(&local_mouse_report, 0, sizeof(local_mouse_report));
local_mouse_report.buttons = buttons;

memcpy(&old_report, &local_mouse_report, sizeof(local_mouse_report));

return should_send_report || buttons;
Expand Down Expand Up @@ -303,14 +304,18 @@ __attribute__((weak)) bool pointing_device_task(void) {
local_mouse_report = pointing_device_adjust_by_defines_right(local_mouse_report);
shared_mouse_report = pointing_device_adjust_by_defines(shared_mouse_report);
}
local_mouse_report = is_keyboard_left() ? pointing_device_task_combined_kb(local_mouse_report, shared_mouse_report) : pointing_device_task_combined_kb(shared_mouse_report, local_mouse_report);
local_mouse_report = is_keyboard_left() ? pointing_device_task_combined(local_mouse_report, shared_mouse_report) : pointing_device_task_combined(shared_mouse_report, local_mouse_report);
#else
local_mouse_report = pointing_device_adjust_by_defines(local_mouse_report);
local_mouse_report = pointing_device_task_kb(local_mouse_report);
#endif
// automatic mouse layer function
#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
pointing_device_task_auto_mouse(local_mouse_report);
#endif
// pointing device modes handling for single pointing device
#if defined(POINTING_DEVICE_MODES_ENABLE) && !(defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED))
local_mouse_report = pointing_modes_device_task(local_mouse_report);
#endif
// combine with mouse report to ensure that the combined is sent correctly
#ifdef MOUSEKEY_ENABLE
Expand Down Expand Up @@ -486,6 +491,44 @@ report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_repo
return mouse_report;
}

/**
* @brief Handle core combined pointing device tasks
*
* Takes 2 report_mouse_t structs allowing individual modification of either side and then returns pointing_device_task_combined_kb.
*
* NOTE: Only available when using both SPLIT_POINTING_ENABLE and POINTING_DEVICE_COMBINED
*
* @param[in] left_report report_mouse_t
* @param[in] right_report report_mouse_t
* @return pointing_device_task_combined_kb(left_report, right_report) by default
*/
report_mouse_t pointing_device_task_combined(report_mouse_t left_report, report_mouse_t right_report) {
# ifdef POINTING_DEVICE_MODE_ENABLE
# if POINTING_MODES_SINGLE_CONTROL
// only one side controlled at any one time
switch (pointing_modes_get_active_device()) {
case PM_RIGHT_DEVICE:
right_report = pointing_modes_device_task(right_report);
break;
default:
left_report = pointing_modes_device_task(left_report);
}
# else
// both sides controlled independently
// save current device id
uint8_t active_device = pointing_modes_get_active_device();
pointing_modes_set_active_device(PM_RIGHT_DEVICE);
right_report = pointing_modes_device_task(right_report);

pointing_modes_set_active_device(PM_LEFT_DEVICE);
left_report = pointing_modes_device_task(left_report);
// set device id back
pointing_modes_set_active_device(active_device);
# endif
# endif
return pointing_device_task_combined_kb(left_report, right_report);
}

/**
* @brief Weak function allowing for keyboard level mouse report modification
*
Expand Down Expand Up @@ -515,7 +558,7 @@ __attribute__((weak)) report_mouse_t pointing_device_task_combined_kb(report_mou
__attribute__((weak)) report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report) {
return pointing_device_combine_reports(left_report, right_report);
}
#endif
#endif // defined(SPLIT_POINTING_ENABLE) && defined(POINTING_DEVICE_COMBINED)

__attribute__((weak)) void pointing_device_keycode_handler(uint16_t keycode, bool pressed) {
if IS_MOUSEKEY_BUTTON (keycode) {
Expand Down
4 changes: 4 additions & 0 deletions quantum/pointing_device/pointing_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ typedef struct {
#ifdef POINTING_DEVICE_AUTO_MOUSE_ENABLE
# include "pointing_device_auto_mouse.h"
#endif
#ifdef POINTING_DEVICE_MODES_ENABLE
# include "pointing_device_modes.h"
#endif

#if defined(POINTING_DEVICE_DRIVER_adns5050)
# include "drivers/sensors/adns5050.h"
Expand Down Expand Up @@ -139,6 +142,7 @@ uint16_t pointing_device_get_shared_cpi(void);
# if defined(POINTING_DEVICE_COMBINED)
void pointing_device_set_cpi_on_side(bool left, uint16_t cpi);
report_mouse_t pointing_device_combine_reports(report_mouse_t left_report, report_mouse_t right_report);
report_mouse_t pointing_device_task_combined(report_mouse_t left_report, report_mouse_t right_report);
report_mouse_t pointing_device_task_combined_kb(report_mouse_t left_report, report_mouse_t right_report);
report_mouse_t pointing_device_task_combined_user(report_mouse_t left_report, report_mouse_t right_report);
report_mouse_t pointing_device_adjust_by_defines_right(report_mouse_t mouse_report);
Expand Down
9 changes: 7 additions & 2 deletions quantum/pointing_device/pointing_device_auto_mouse.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Copyright 2021 Christopher Courtney, aka Drashna Jael're (@drashna) <[email protected]>
* Copyright 2022 Alabastard
* Copyright 2022 Alabastard (@Alabastard-64)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -430,7 +430,12 @@ bool process_auto_mouse(uint16_t keycode, keyrecord_t* record) {
*/
static bool is_mouse_record(uint16_t keycode, keyrecord_t* record) {
// allow for keyboard to hook in and override if need be
if (is_mouse_record_kb(keycode, record) || IS_MOUSEKEY(keycode)) return true;
if (is_mouse_record_kb(keycode, record) || IS_MOUSEKEY(keycode) ||
# ifdef POINTING_DEVICE_MODES_ENABLE
IS_QK_POINTING_MODES_MO(keycode) || IS_QK_POINTING_MODES_TG(keycode) ||
# endif
false)
return true;
return false;
}

Expand Down
Loading