Before: send_leader_combination() was resetting leader state for all modes After: Only resets for one_shot mode, preserves state for toggle and sticky Added proper separation between leader_active (temporary) and toggle_state (persistent) Shows toggle state separately from leader active state Clearer mode indication in debug output Button 18 was getting the last parsed leader_eligible value
+69 −55 · 2 files changed
-
KD100.c+32 −18 -
default.cfg+37 −37
@@ -139,6 +139,10 @@ void setup_crash_handler(void) { } #endif +// Device identifiers +const int vid = 0x256c; +const int pid = 0x006d; + int keycodes[] = {1, 2, 4, 8, 16, 32, 64, 128, 129, 130, 132, 136, 144, 160, 192, 256, 257, 258, 260, 641, 642}; char* file = "default.cfg"; int enable_uclogic = 0; @@ -193,9 +197,6 @@ void trim_trailing_spaces(char* str); leader_mode_t parse_leader_mode(const char* mode_str); const char* leader_mode_to_string(leader_mode_t mode); -const int vid = 0x256c; -const int pid = 0x006d; - // Get current time in milliseconds long get_time_ms() { struct timeval tv; @@ -269,13 +270,13 @@ int is_modifier_key(const char* key) { return 0; } -// Reset leader state +// Reset leader state (but preserve toggle state for toggle mode) void reset_leader_state(leader_state* state) { state->leader_active = 0; state->last_button = -1; state->leader_press_time.tv_sec = 0; state->leader_press_time.tv_usec = 0; - state->toggle_state = 0; // Also reset toggle state + // Don't reset toggle_state here - it's managed separately } // Send leader combination @@ -293,10 +294,15 @@ void send_leader_combination(leader_state* state, char* combination, int debug) snprintf(cmd, sizeof(cmd), "xdotool key %s", combination); system(cmd); - // Reset leader state after sending (except for sticky mode) - if (state->mode != LEADER_MODE_STICKY) { + // Reset leader state after sending (except for sticky and toggle modes) + if (state->mode == LEADER_MODE_ONE_SHOT) { reset_leader_state(state); + state->toggle_state = 0; // Also reset toggle for one_shot + } else if (state->mode == LEADER_MODE_STICKY) { + // Update timer for sticky mode + gettimeofday(&state->leader_press_time, NULL); } + // For toggle mode, don't reset anything - stay active } // Process leader key combinations @@ -305,7 +311,7 @@ void process_leader_combination(leader_state* state, event* events, int button_i return; } - // Check if this is the wheel button (button 18) - should not be modified + // Check if this is the wheel button (button 18) - handle specially if (button_index == 18) { // Wheel button - handle normally without leader if (events[button_index].function != NULL && @@ -313,7 +319,10 @@ void process_leader_combination(leader_state* state, event* events, int button_i // Handle swap function // (This would need wheel state tracking - implemented elsewhere) } - reset_leader_state(state); + // Don't reset leader state for wheel button in toggle mode + if (state->mode != LEADER_MODE_TOGGLE) { + reset_leader_state(state); + } return; } @@ -342,6 +351,7 @@ void process_leader_combination(leader_state* state, event* events, int button_i // Disable toggle mode state->toggle_state = 0; state->leader_active = 0; + reset_leader_state(state); if (debug == 1) { printf("Leader toggle mode DISABLED by button %d\n", button_index); @@ -369,8 +379,13 @@ void process_leader_combination(leader_state* state, event* events, int button_i return; } - // Check if we're in leader mode - if (state->leader_active) { + // Check if we're in leader mode (either active or toggle mode is on) + int in_leader_mode = state->leader_active; + if (state->mode == LEADER_MODE_TOGGLE) { + in_leader_mode = state->toggle_state; + } + + if (in_leader_mode) { // Check eligibility first if (events[button_index].leader_eligible == 0) { // Button is not eligible for leader modifications @@ -379,7 +394,7 @@ void process_leader_combination(leader_state* state, event* events, int button_i } // For sticky mode, we might want to keep leader active - if (state->mode != LEADER_MODE_STICKY) { + if (state->mode != LEADER_MODE_STICKY && state->mode != LEADER_MODE_TOGGLE) { reset_leader_state(state); } @@ -391,12 +406,14 @@ void process_leader_combination(leader_state* state, event* events, int button_i gettimeofday(&now, NULL); long elapsed = time_diff_ms(state->leader_press_time, now); + // Check timeout (skip for toggle mode) if (elapsed > state->timeout_ms && state->mode != LEADER_MODE_TOGGLE) { // Leader timeout - reset (except for toggle mode) if (debug == 1) { printf("Leader timeout (%ld ms > %d ms)\n", elapsed, state->timeout_ms); } reset_leader_state(state); + state->toggle_state = 0; // Fall through to normal button handling } else { // We have a leader combination! @@ -418,11 +435,6 @@ void process_leader_combination(leader_state* state, event* events, int button_i gettimeofday(&state->leader_press_time, NULL); } - // For one-shot mode, reset after sending - if (state->mode == LEADER_MODE_ONE_SHOT) { - reset_leader_state(state); - } - return; // Don't also handle as normal button } } @@ -1252,7 +1264,9 @@ void GetDevice(libusb_context *ctx, int debug, int accept, int dry){ } printf("]\n"); - if (leader.leader_active) { + if (leader.toggle_state) { + printf("Leader toggle: ON (mode: %s)\n", leader_mode_to_string(leader.mode)); + } else if (leader.leader_active) { struct timeval now; gettimeofday(&now, NULL); long elapsed = time_diff_ms(leader.leader_press_time, now); @@ -47,52 +47,52 @@ // // -// Leader configuration -// Options: -// Leader Button: Specify which key should take role as modifier for the keys. -// Leader Functions: Specify which key press will be used. -// Leader Timeout: Ammount of time that leader remains active in miliseconds. -// Leader Mode: One of the three modes that the leader will act. -// -// One shot: The leader keypress will act one time in the configured time window. -// Example: Press Button 16 (leader) -> Press Button 0 (b) -> Result: shift+b -> Leader resets -// -// Sticky: Leader stays active until timeout -// Example: Press Button 16 (leader) -> Press Button 0 (b) -> Result: shift+b -// Press Button 1 (p) -> Result: shift+p -// Press Button 2 (t) -> Result: shift+t -// Timeout after 1000ms -> Leader resets -// -// Toggle: Leader toggles on/off -// Example: Press Button 16 (leader) -> Leader enabled -// Press Button 0 (b) -> Result: shift+b -// Press Button 1 (p) -> Result: shift+p -// Press Button 16 (leader) -> Leader disabled -// Press Button 0 (b) -> Result: b (normal) -// Default: one_shot -// +// Leader configuration +// Options: +// Leader Button: Specify which key should take role as modifier for the keys. +// Leader Functions: Specify which key press will be used. +// Leader Timeout: Ammount of time that leader remains active in miliseconds. +// Leader Mode: One of the three modes that the leader will act. +// +// one_shot: The leader keypress will act one time in the configured time window. +// Example: Press Button 16 (leader) -> Press Button 0 (b) -> Result: shift+b -> Leader resets +// +// sticky: Leader stays active until timeout +// Example: Press Button 16 (leader) -> Press Button 0 (b) -> Result: shift+b +// Press Button 1 (p) -> Result: shift+p +// Press Button 2 (t) -> Result: shift+t +// Timeout after 1000ms -> Leader resets +// +// toggle: Leader toggles on/off +// Example: Press Button 16 (leader) -> Leader enabled +// Press Button 0 (b) -> Result: shift+b +// Press Button 1 (p) -> Result: shift+p +// Press Button 16 (leader) -> Leader disabled +// Press Button 0 (b) -> Result: b (normal) +// Default: one_shot +// leader_button: 16 leader_function: shift leader_timeout: 1000 -leader_mode: one_shot +leader_mode: toggle // -// hid_uclogic compatibility configuration -// enabe_uclogic: [true|false] - OpenTabletDriver requires hid_uclogic to be unloaded from kernel. -// Default: false -// enable_uclogic: false -// +// hid_uclogic compatibility configuration +// enabe_uclogic: [true|false] - OpenTabletDriver requires hid_uclogic to be unloaded from kernel. +// Default: false +// enable_uclogic: false +// -// -// Brush Tool -// +// +// Brush Tool +// Button 0 type: 0 function: b // -// Optional: leader_eligible: [true|false] -// Declare button as eligble to be used or not alongside with the leader key -// Default: all buttons (with the exception of Button 18, the wheel toggle button, are eligible. +// Optional: leader_eligible: [true|false] +// Declare button as eligble to be used or not alongside with the leader key +// Default: all buttons (with the exception of Button 18, the wheel toggle button, are eligible. // leader_eligible: true // @@ -101,7 +101,7 @@ leader_eligible: true Button 1 type: 0 function: p -leader_eligible: true +leader_eligible: false // // Transform Tool //