Browse Source

Migrate swap_hands to quantum

pull/13925/head
zvecr 2 years ago
parent
commit
4029395a1b
11 changed files with 204 additions and 257 deletions
  1. +2
    -143
      quantum/action.c
  2. +0
    -17
      quantum/action.h
  3. +0
    -30
      quantum/action_code.h
  4. +0
    -54
      quantum/action_util.c
  5. +0
    -8
      quantum/action_util.h
  6. +0
    -5
      quantum/keymap_common.c
  7. +155
    -0
      quantum/process_keycode/process_swap_hands.c
  8. +28
    -0
      quantum/process_keycode/process_swap_hands.h
  9. +6
    -0
      quantum/quantum.c
  10. +4
    -0
      quantum/quantum.h
  11. +9
    -0
      quantum/quantum_keycodes.h

+ 2
- 143
quantum/action.c View File

@ -79,12 +79,6 @@ void action_exec(keyevent_t event) {
clear_weak_mods();
}
#ifdef SWAP_HANDS_ENABLE
if (!IS_NOEVENT(event)) {
process_hand_swap(&event);
}
#endif
keyrecord_t record = {.event = event};
#ifndef NO_ACTION_ONESHOT
@ -96,11 +90,6 @@ void action_exec(keyevent_t event) {
if (has_oneshot_mods_timed_out()) {
clear_oneshot_mods();
}
# ifdef SWAP_HANDS_ENABLE
if (has_oneshot_swaphands_timed_out()) {
clear_oneshot_swaphands();
}
# endif
# endif
}
#endif
@ -121,31 +110,6 @@ void action_exec(keyevent_t event) {
#endif
}
#ifdef SWAP_HANDS_ENABLE
bool swap_hands = false;
bool swap_held = false;
/** \brief Process Hand Swap
*
* FIXME: Needs documentation.
*/
void process_hand_swap(keyevent_t *event) {
static swap_state_row_t swap_state[MATRIX_ROWS];
keypos_t pos = event->key;
swap_state_row_t col_bit = (swap_state_row_t)1 << pos.col;
bool do_swap = event->pressed ? swap_hands : swap_state[pos.row] & (col_bit);
if (do_swap) {
event->key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row);
event->key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col);
swap_state[pos.row] |= col_bit;
} else {
swap_state[pos.row] &= ~(col_bit);
}
}
#endif
#if !defined(NO_ACTION_LAYER) && !defined(STRICT_LAYER_RELEASE)
bool disable_action_cache = false;
@ -171,18 +135,8 @@ void process_record_tap_hint(keyrecord_t *record) {
action_t action = layer_switch_get_action(record->event.key);
switch (action.kind.id) {
# ifdef SWAP_HANDS_ENABLE
case ACT_SWAP_HANDS:
switch (action.swap.code) {
case OP_SH_ONESHOT:
break;
case OP_SH_TAP_TOGGLE:
default:
swap_hands = !swap_hands;
swap_held = true;
}
default:
break;
# endif
}
}
#endif
@ -259,11 +213,7 @@ void process_action(keyrecord_t *record, action_t action) {
#ifndef NO_ACTION_ONESHOT
bool do_release_oneshot = false;
// notice we only clear the one shot layer if the pressed key is not a modifier.
if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code))
# ifdef SWAP_HANDS_ENABLE
&& !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)
# endif
&& !keymap_config.oneshot_disable) {
if (is_oneshot_layer_active() && event.pressed && (action.kind.id == ACT_USAGE || !IS_MOD(action.key.code)) && !keymap_config.oneshot_disable) {
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
do_release_oneshot = !is_oneshot_layer_active();
}
@ -631,79 +581,6 @@ void process_action(keyrecord_t *record, action_t action) {
action_macro_play(action_get_macro(record, action.func.id, action.func.opt));
break;
#endif
#ifdef SWAP_HANDS_ENABLE
case ACT_SWAP_HANDS:
switch (action.swap.code) {
case OP_SH_TOGGLE:
if (event.pressed) {
swap_hands = !swap_hands;
}
break;
case OP_SH_ON_OFF:
swap_hands = event.pressed;
break;
case OP_SH_OFF_ON:
swap_hands = !event.pressed;
break;
case OP_SH_ON:
if (!event.pressed) {
swap_hands = true;
}
break;
case OP_SH_OFF:
if (!event.pressed) {
swap_hands = false;
}
break;
# ifndef NO_ACTION_ONESHOT
case OP_SH_ONESHOT:
if (event.pressed) {
set_oneshot_swaphands();
} else {
release_oneshot_swaphands();
}
break;
# endif
# ifndef NO_ACTION_TAPPING
case OP_SH_TAP_TOGGLE:
/* tap toggle */
if (event.pressed) {
if (swap_held) {
swap_held = false;
} else {
swap_hands = !swap_hands;
}
} else {
if (tap_count < TAPPING_TOGGLE) {
swap_hands = !swap_hands;
}
}
break;
default:
/* tap key */
if (tap_count > 0) {
if (swap_held) {
swap_hands = !swap_hands; // undo hold set up in _tap_hint
swap_held = false;
}
if (event.pressed) {
register_code(action.swap.code);
} else {
wait_ms(TAP_CODE_DELAY);
unregister_code(action.swap.code);
*record = (keyrecord_t){}; // hack: reset tap mode
}
} else {
if (swap_held && !event.pressed) {
swap_hands = !swap_hands; // undo hold set up in _tap_hint
swap_held = false;
}
}
# endif
}
#endif
#ifndef NO_ACTION_FUNCTION
case ACT_FUNCTION:
action_function(record, action.func.id, action.func.opt);
@ -756,14 +633,6 @@ void process_action(keyrecord_t *record, action_t action) {
# endif
#endif
#ifdef SWAP_HANDS_ENABLE
# ifndef NO_ACTION_ONESHOT
if (event.pressed && !(action.kind.id == ACT_SWAP_HANDS && action.swap.code == OP_SH_ONESHOT)) {
use_oneshot_swaphands();
}
# endif
#endif
#ifndef NO_ACTION_ONESHOT
/* Because we switch layers after a oneshot event, we need to release the
* key before we leave the layer or no key up event will be generated.
@ -1084,13 +953,6 @@ bool is_tap_action(action_t action) {
return true;
}
return false;
case ACT_SWAP_HANDS:
switch (action.swap.code) {
case KC_NO ... KC_RIGHT_GUI:
case OP_SH_TAP_TOGGLE:
return true;
}
return false;
case ACT_MACRO:
case ACT_FUNCTION:
if (action.func.opt & FUNC_TAP) {
@ -1159,9 +1021,6 @@ void debug_action(action_t action) {
case ACT_FUNCTION:
dprint("ACT_FUNCTION");
break;
case ACT_SWAP_HANDS:
dprint("ACT_SWAP_HANDS");
break;
default:
dprint("UNKNOWN");
break;


+ 0
- 17
quantum/action.h View File

@ -86,23 +86,6 @@ bool process_record_quantum(keyrecord_t *record);
extern bool disable_action_cache;
#endif
/* Code for handling one-handed key modifiers. */
#ifdef SWAP_HANDS_ENABLE
extern bool swap_hands;
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
# if (MATRIX_COLS <= 8)
typedef uint8_t swap_state_row_t;
# elif (MATRIX_COLS <= 16)
typedef uint16_t swap_state_row_t;
# elif (MATRIX_COLS <= 32)
typedef uint32_t swap_state_row_t;
# else
# error "MATRIX_COLS: invalid value"
# endif
void process_hand_swap(keyevent_t *record);
#endif
void process_record_nocache(keyrecord_t *record);
void process_record(keyrecord_t *record);
void process_record_handler(keyrecord_t *record);


+ 0
- 30
quantum/action_code.h View File

@ -48,9 +48,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
* ACT_MOUSEKEY(0101): TODO: Merge these two actions to conserve space?
* 0101|xxxx| keycode Mouse key
*
* ACT_SWAP_HANDS(0110):
* 0110|xxxx| keycode Swap hands (keycode on tap, or options)
*
* 0111|xxxx xxxx xxxx (reserved)
*
* Layer Actions(10xx)
@ -104,8 +101,6 @@ enum action_kind_id {
/* Other Keys */
ACT_USAGE = 0b0100,
ACT_MOUSEKEY = 0b0101,
/* One-hand Support */
ACT_SWAP_HANDS = 0b0110,
/* Layer Actions */
ACT_LAYER = 0b1000,
ACT_LAYER_MODS = 0b1001,
@ -169,11 +164,6 @@ typedef union {
uint8_t opt : 4;
uint8_t kind : 4;
} func;
struct action_swap {
uint8_t code : 8;
uint8_t opt : 4;
uint8_t kind : 4;
} swap;
} action_t;
/* action utility */
@ -286,23 +276,3 @@ enum function_opts {
#define ACTION_FUNCTION(id) ACTION(ACT_FUNCTION, (id))
#define ACTION_FUNCTION_TAP(id) ACTION(ACT_FUNCTION, FUNC_TAP << 8 | (id))
#define ACTION_FUNCTION_OPT(id, opt) ACTION(ACT_FUNCTION, (opt) << 8 | (id))
/* OneHand Support */
enum swap_hands_param_tap_op {
OP_SH_TOGGLE = 0xF0,
OP_SH_TAP_TOGGLE,
OP_SH_ON_OFF,
OP_SH_OFF_ON,
OP_SH_OFF,
OP_SH_ON,
OP_SH_ONESHOT,
};
#define ACTION_SWAP_HANDS() ACTION_SWAP_HANDS_ON_OFF()
#define ACTION_SWAP_HANDS_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TOGGLE)
#define ACTION_SWAP_HANDS_TAP_TOGGLE() ACTION(ACT_SWAP_HANDS, OP_SH_TAP_TOGGLE)
#define ACTION_SWAP_HANDS_ONESHOT() ACTION(ACT_SWAP_HANDS, OP_SH_ONESHOT)
#define ACTION_SWAP_HANDS_TAP_KEY(key) ACTION(ACT_SWAP_HANDS, key)
#define ACTION_SWAP_HANDS_ON_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_ON_OFF)
#define ACTION_SWAP_HANDS_OFF_ON() ACTION(ACT_SWAP_HANDS, OP_SH_OFF_ON)
#define ACTION_SWAP_HANDS_ON() ACTION(ACT_SWAP_HANDS, OP_SH_ON)
#define ACTION_SWAP_HANDS_OFF() ACTION(ACT_SWAP_HANDS, OP_SH_OFF)

+ 0
- 54
quantum/action_util.c View File

@ -77,63 +77,9 @@ static int8_t oneshot_layer_data = 0;
inline uint8_t get_oneshot_layer(void) { return oneshot_layer_data >> 3; }
inline uint8_t get_oneshot_layer_state(void) { return oneshot_layer_data & 0b111; }
# ifdef SWAP_HANDS_ENABLE
enum {
SHO_OFF,
SHO_ACTIVE, // Swap hands button was pressed, and we didn't send any swapped keys yet
SHO_PRESSED, // Swap hands button is currently pressed
SHO_USED, // Swap hands button is still pressed, and we already sent swapped keys
} swap_hands_oneshot = SHO_OFF;
# endif
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
static uint16_t oneshot_layer_time = 0;
inline bool has_oneshot_layer_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_layer_time) >= ONESHOT_TIMEOUT && !(get_oneshot_layer_state() & ONESHOT_TOGGLED); }
# ifdef SWAP_HANDS_ENABLE
static uint16_t oneshot_swaphands_time = 0;
inline bool has_oneshot_swaphands_timed_out() { return TIMER_DIFF_16(timer_read(), oneshot_swaphands_time) >= ONESHOT_TIMEOUT && (swap_hands_oneshot == SHO_ACTIVE); }
# endif
# endif
# ifdef SWAP_HANDS_ENABLE
void set_oneshot_swaphands(void) {
swap_hands_oneshot = SHO_PRESSED;
swap_hands = true;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_swaphands_time = timer_read();
if (oneshot_layer_time != 0) {
oneshot_layer_time = oneshot_swaphands_time;
}
# endif
}
void release_oneshot_swaphands(void) {
if (swap_hands_oneshot == SHO_PRESSED) {
swap_hands_oneshot = SHO_ACTIVE;
}
if (swap_hands_oneshot == SHO_USED) {
clear_oneshot_swaphands();
}
}
void use_oneshot_swaphands(void) {
if (swap_hands_oneshot == SHO_PRESSED) {
swap_hands_oneshot = SHO_USED;
}
if (swap_hands_oneshot == SHO_ACTIVE) {
clear_oneshot_swaphands();
}
}
void clear_oneshot_swaphands(void) {
swap_hands_oneshot = SHO_OFF;
swap_hands = false;
# if (defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0))
oneshot_swaphands_time = 0;
# endif
}
# endif
/** \brief Set oneshot layer


+ 0
- 8
quantum/action_util.h View File

@ -76,7 +76,6 @@ void reset_oneshot_layer(void);
bool is_oneshot_layer_active(void);
uint8_t get_oneshot_layer_state(void);
bool has_oneshot_layer_timed_out(void);
bool has_oneshot_swaphands_timed_out(void);
void oneshot_locked_mods_changed_user(uint8_t mods);
void oneshot_locked_mods_changed_kb(uint8_t mods);
@ -93,13 +92,6 @@ bool is_oneshot_enabled(void);
/* inspect */
uint8_t has_anymod(void);
#ifdef SWAP_HANDS_ENABLE
void set_oneshot_swaphands(void);
void release_oneshot_swaphands(void);
void use_oneshot_swaphands(void);
void clear_oneshot_swaphands(void);
#endif
#ifdef __cplusplus
}
#endif

+ 0
- 5
quantum/keymap_common.c View File

@ -152,11 +152,6 @@ action_t action_for_keycode(uint16_t keycode) {
action.code = ACTION_MODS_TAP_KEY(mod, keycode & 0xFF);
break;
#endif
#ifdef SWAP_HANDS_ENABLE
case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
action.code = ACTION(ACT_SWAP_HANDS, keycode & 0xff);
break;
#endif
default:
action.code = ACTION_NO;


+ 155
- 0
quantum/process_keycode/process_swap_hands.c View File

@ -0,0 +1,155 @@
/* Copyright 2021 QMK
*
* 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
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "process_swap_hands.h"
#include "quantum_keycodes.h"
#include "action_tapping.h"
#include "matrix.h"
extern const keypos_t PROGMEM hand_swap_config[MATRIX_ROWS][MATRIX_COLS];
static matrix_row_t swap_state[MATRIX_ROWS];
static bool swap_hands_enabled = false;
static bool oneshot_enabled = false;
static uint16_t oneshot_expiry = 0;
#if defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)
static inline bool has_oneshot_swaphands_timed_out(void) {
return (oneshot_expiry && timer_expired(timer_read(), oneshot_expiry));
}
#endif
static inline void swap_hands_task(void) {
#if defined(ONESHOT_TIMEOUT) && (ONESHOT_TIMEOUT > 0)
if (has_oneshot_swaphands_timed_out()) {
clear_oneshot_swaphands();
}
#endif
}
void clear_oneshot_swaphands(void) {
oneshot_expiry = 0;
swap_hands_enabled = false;
oneshot_enabled = false;
}
void preprocess_swap_hands(keyrecord_t *record) {
// TODO: implement a "real" swap_hands_task called from matrix_scan_quantum?
swap_hands_task();
keypos_t pos = record->event.key;
matrix_row_t col_bit = MATRIX_ROW_SHIFTER << pos.col;
bool do_swap = record->event.pressed ? swap_hands_enabled : swap_state[pos.row] & (col_bit);
if (do_swap) {
record->event.key.row = pgm_read_byte(&hand_swap_config[pos.row][pos.col].row);
record->event.key.col = pgm_read_byte(&hand_swap_config[pos.row][pos.col].col);
swap_state[pos.row] |= col_bit;
} else {
swap_state[pos.row] &= ~(col_bit);
}
}
bool process_swap_hands(uint16_t keycode, keyrecord_t *record) {
static uint16_t last_keycode = 0;
bool pressed = record->event.pressed;
uint16_t previous_keycode = last_keycode;
last_keycode = keycode;
bool interupted = (previous_keycode != keycode);
switch (keycode) {
case SH_TG:
if (pressed) {
swap_hands_enabled = !swap_hands_enabled;
}
break;
case SH_MON:
swap_hands_enabled = pressed;
break;
case SH_MOFF:
swap_hands_enabled = !pressed;
break;
case SH_ON:
if (!pressed) {
swap_hands_enabled = true;
}
break;
case SH_OFF:
if (!pressed) {
swap_hands_enabled = false;
}
break;
case SH_TT: {
static uint8_t start_state = 0xFF;
if (pressed && (start_state == 0xFF)) {
start_state = swap_hands_enabled;
}
static int tap_count = 0;
if (interupted) {
tap_count = 0;
start_state = 0xFF;
} else {
tap_count++;
if (tap_count >= TAPPING_TOGGLE) {
swap_hands_enabled = !start_state;
start_state = 0xFF;
tap_count = 0;
}
}
swap_hands_enabled = !swap_hands_enabled;
break;
}
case SH_OS:
if (pressed) {
swap_hands_enabled = true;
} else if (!interupted) {
oneshot_enabled = true;
#ifdef ONESHOT_TIMEOUT
oneshot_expiry = timer_read() + ONESHOT_TIMEOUT;
#endif
} else {
swap_hands_enabled = false;
}
break;
case SH_T(0x00)... SH_T(0xEF):
swap_hands_enabled = pressed;
static uint16_t tap_expiry = 0;
if (pressed) {
tap_expiry = timer_read() + TAPPING_TERM;
} else if (!timer_expired(timer_read(), tap_expiry)) {
tap_code(keycode & 0xFF);
}
break;
default:
if (oneshot_enabled && !pressed) {
clear_oneshot_swaphands();
}
return true;
}
return false;
}
bool is_swap_hands_enabled(void) { return swap_hands_enabled; }
void swap_hands_enable(void) { swap_hands_enabled = true; }
void swap_hands_disable(void) { swap_hands_enabled = false; }
void swap_hands_toggle(void) { swap_hands_enabled = !swap_hands_enabled; }

+ 28
- 0
quantum/process_keycode/process_swap_hands.h View File

@ -0,0 +1,28 @@
/* Copyright 2021 QMK
*
* 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
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdbool.h>
#include "action.h"
void preprocess_swap_hands(keyrecord_t *record);
bool process_swap_hands(uint16_t keycode, keyrecord_t *record);
bool is_swap_hands_enabled(void);
void swap_hands_enable(void);
void swap_hands_disable(void);
void swap_hands_toggle(void);

+ 6
- 0
quantum/quantum.c View File

@ -194,6 +194,9 @@ void post_process_record_quantum(keyrecord_t *record) {
then processes internal quantum keycodes, and then processes
ACTIONs. */
bool process_record_quantum(keyrecord_t *record) {
#ifdef SWAP_HANDS_ENABLE
preprocess_swap_hands(record);
#endif
uint16_t keycode = get_record_keycode(record, true);
// This is how you use actions here
@ -235,6 +238,9 @@ bool process_record_quantum(keyrecord_t *record) {
#ifdef HAPTIC_ENABLE
process_haptic(keycode, record) &&
#endif
#ifdef SWAP_HANDS_ENABLE
process_swap_hands(keycode, record) &&
#endif
#if defined(VIA_ENABLE)
process_record_via(keycode, record) &&
#endif


+ 4
- 0
quantum/quantum.h View File

@ -155,6 +155,10 @@ extern layer_state_t layer_state;
# include "process_grave_esc.h"
#endif
#ifdef SWAP_HANDS_ENABLE
# include "process_swap_hands.h"
#endif
#if defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
# include "process_rgb.h"
#endif


+ 9
- 0
quantum/quantum_keycodes.h View File

@ -850,6 +850,15 @@ enum quantum_keycodes {
#define UC_M_WC UNICODE_MODE_WINC
// Swap Hands
enum swap_hands_param_tap_op {
OP_SH_TOGGLE = 0xF0,
OP_SH_TAP_TOGGLE,
OP_SH_ON_OFF,
OP_SH_OFF_ON,
OP_SH_OFF,
OP_SH_ON,
OP_SH_ONESHOT,
};
#define SH_T(kc) (QK_SWAP_HANDS | (kc))
#define SH_TG (QK_SWAP_HANDS | OP_SH_TOGGLE)
#define SH_TT (QK_SWAP_HANDS | OP_SH_TAP_TOGGLE)


Loading…
Cancel
Save