Add leader key descriptions and bump to v1.7.1
Implement leader_description_N config fields that provide per-button labels shown in the OSD when the leader key is active. Eligible buttons swap their description to the leader variant (purple-tinted) in the expanded keyboard layout. Input validation enforced (max 64 chars, printable ASCII). https://claude.ai/code/session_019MPUMMqDBcEYr7qFBLzJd6
+129 −16 · 9 files changed
-
Makefile+1 −1 -
README.md+31 −3 -
default.cfg+32 −2 -
src/config.c+35 −0 -
src/config.h+2 −1 -
src/device.c+5 −2 -
src/main.c+4 −4 -
src/osd.c+16 −2 -
src/osd.h+3 −1
@@ -7,7 +7,7 @@ DIR = $(shell pwd) HOME = "/home/"$(shell logname) TARGET = KD100 DEBUG_TARGET = KD100-debug -VERSION = 1.7.0 +VERSION = 1.7.1 # Source files SRC_DIR = src @@ -6,11 +6,12 @@ Originally forked from [mckset/KD100](https://github.com/mckset/KD100), now inde A simple driver for the Huion KD100 mini Keydial written in C to give the device some usability while waiting for Huion to fix their Linux drivers. Each button can be configured to either act as a key/multiple keys or to execute a program/command. -**Version 1.7.0** enhances the OSD with active button highlighting, wheel function descriptions, wheel set indicators, leader key visual feedback, and action aggregation for wheel events. +**Version 1.7.1** adds leader key descriptions — per-button labels that swap in when the leader key is active, shown in the expanded OSD keyboard layout. Also includes all v1.7.0 enhancements: active button highlighting, wheel function descriptions, wheel set indicators, leader key visual feedback, and action aggregation. > **NOTICE:** When updating from **v1.31** or below, make sure you updated your config file to follow the new format shown in the default config file. ## Features +- **Leader Key Descriptions (v1.7.1)**: Per-button descriptions that swap in when leader is active - **Wheel Function Descriptions (v1.7.0)**: Human-readable names for wheel functions shown in OSD - **Active Button Highlighting (v1.7.0)**: Pressed buttons flash green in expanded keyboard layout - **Leader Key Visual Feedback (v1.7.0)**: Orange highlight for active leader, purple tint for eligible keys @@ -33,7 +34,7 @@ A simple driver for the Huion KD100 mini Keydial written in C to give the device - **Clean Compilation**: Zero warnings with strict compiler flags - **Better Code Organization**: Easy to extend and maintain -## Architecture (v1.7.0) +## Architecture (v1.7.1) The codebase is organized into focused modules: @@ -149,6 +150,21 @@ function: p leader_eligible: false # Cannot be modified by leader ``` +### Leader Key Descriptions (v1.7.1) +Each button can have a separate description shown when the leader key is active. This lets you display the modified action in the OSD expanded view. + +```bash +# Format: leader_description_<button_number>: <description> +# Maximum 64 characters, printable ASCII only +# Only define for leader-eligible buttons + +leader_description_0: Shift+Brush +leader_description_2: Shift+Transform +leader_description_3: Shift+Lasso +``` + +When the leader key is active, eligible buttons in the OSD keyboard layout swap their label to the leader description (shown with a purple tint). Non-eligible buttons keep their normal description. + ### Configuration Example ```bash # Leader configuration @@ -167,6 +183,10 @@ Button 18 # Wheel toggle button type: 1 function: swap leader_eligible: false # Typically not eligible + +# Leader descriptions (shown in OSD when leader is active) +leader_description_0: Shift+Brush +leader_description_2: Shift+Transform ``` ## On-Screen Display (OSD) @@ -486,7 +506,15 @@ If you encounter permission errors or device conflicts: ## Version History -### v1.7.0 (Current) - Enhanced OSD Feedback & Wheel Descriptions +### v1.7.1 (Current) - Leader Key Descriptions +- **Leader Key Descriptions**: New `leader_description_N` config fields for per-button labels when leader is active + - Descriptions swap in on eligible buttons in the expanded OSD keyboard layout + - Purple-tinted buttons show the leader description instead of the normal one + - Input validation: max 64 chars, printable ASCII only +- **Configuration**: `leader_description_<button_number>: <description>` in config file +- **Version Bump**: Updated version strings across all modules + +### v1.7.0 - Enhanced OSD Feedback & Wheel Descriptions - **Wheel Function Descriptions**: New `wheel_description_N` config fields for human-readable names - Shown in OSD set indicator, function pair display, and action messages - Replaces inline comments after wheel function lines in config @@ -1,4 +1,4 @@ -// KD100 config file - Version 1.7.0 +// KD100 config file - Version 1.7.1 // // Assumptions: // - (B)utton defines a new button and the following number specifies which button it is. @@ -141,7 +141,37 @@ description_16: SHIFT description_17: Redo description_18: Wheel Fn -// +// +// ========================================== +// LEADER KEY DESCRIPTIONS +// ========================================== +// +// Descriptions shown in the OSD when the leader key is active. +// When leader is on, eligible buttons show these descriptions +// instead of their normal ones. +// +// Format: leader_description_<button_number>: <description> +// Maximum 64 characters, printable ASCII only. +// Only define for leader-eligible buttons (not button 1 or 18). +// +leader_description_0: Shift+Brush +leader_description_2: Shift+Transform +leader_description_3: Shift+Lasso +leader_description_4: Shift+New Layer +leader_description_5: Shift+Duplicate +leader_description_6: Shift+Merge +leader_description_7: Shift+Eraser +leader_description_8: Shift+Deselect +leader_description_9: Shift+Delete +leader_description_10: Shift+Undo +leader_description_11: Shift+Inv Sel +leader_description_12: Shift+Pan +leader_description_13: Shift+Zoom +leader_description_14: Shift+Rotate +leader_description_15: Shift+Mirror +leader_description_17: Shift+Redo + +// // Leader configuration // Options: // Leader Button: Specify which key should take role as modifier for the keys. @@ -148,6 +148,7 @@ config_t* config_create(void) { // Initialize key descriptions for (int i = 0; i < 19; i++) { config->key_descriptions[i] = NULL; + config->leader_descriptions[i] = NULL; } return config; @@ -194,6 +195,9 @@ void config_destroy(config_t* config) { if (config->key_descriptions[i] != NULL) { free(config->key_descriptions[i]); } + if (config->leader_descriptions[i] != NULL) { + free(config->leader_descriptions[i]); + } } free(config); @@ -453,6 +457,25 @@ int config_load(config_t* config, const char* filename, int debug) { continue; } + // Parse leader key descriptions (leader_description_0, leader_description_1, etc.) + if (strncasecmp(line, "leader_description_", 19) == 0) { + char* num_str = line + 19; + char* colon = strchr(num_str, ':'); + if (colon) { + *colon = '\0'; + int btn = atoi(num_str); + if (btn >= 0 && btn <= 18) { + char* value = colon + 1; + while (*value == ' ') value++; + if (config->leader_descriptions[btn]) free(config->leader_descriptions[btn]); + config->leader_descriptions[btn] = sanitize_description(value); + if (debug) printf("Config: leader_description_%d = %s\n", btn, + config->leader_descriptions[btn] ? config->leader_descriptions[btn] : "(empty)"); + } + } + continue; + } + // Parse wheel descriptions (wheel_description_0, wheel_description_1, etc.) if (strncasecmp(line, "wheel_description_", 18) == 0) { char* num_str = line + 18; @@ -695,5 +718,17 @@ void config_print(const config_t* config, int debug) { } } + // Print leader key descriptions if any are set + int has_leader_descriptions = 0; + for (int i = 0; i < 19; i++) { + if (config->leader_descriptions[i]) { + if (!has_leader_descriptions) { + printf("\n=== Leader Key Descriptions ===\n"); + has_leader_descriptions = 1; + } + printf("Button %d (leader): %s\n", i, config->leader_descriptions[i]); + } + } + printf("\n"); } @@ -55,7 +55,8 @@ typedef struct { wheel_mode_t wheel_mode; // Wheel toggle mode (sequential or sets) osd_config_t osd; // OSD settings profile_config_t profile; // Profile settings - char* key_descriptions[19]; // Per-button descriptions (for default profile) + char* key_descriptions[19]; // Per-button descriptions (for default profile) + char* leader_descriptions[19]; // Per-button descriptions when leader is active } config_t; // Configuration functions @@ -40,7 +40,7 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in if (debug > 0) { if (debug > 2) debug = 2; - printf("Version 1.7.0 - Enhanced OSD Feedback & Wheel Descriptions\n"); + printf("Version 1.7.1 - Leader Key Descriptions\n"); printf("Debug level: %d\n", debug); } @@ -70,6 +70,9 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in if (config->key_descriptions[i]) { osd_set_key_description(osd, i, config->key_descriptions[i]); } + if (config->leader_descriptions[i]) { + osd_set_leader_description(osd, i, config->leader_descriptions[i]); + } } // Load wheel descriptions from config @@ -355,7 +358,7 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in } printf("Driver is running!\n"); - printf("Enhanced Leader Key System v1.7.0\n"); + printf("Enhanced Leader Key System v1.7.1\n"); printf("Mode: %s | Timeout: %d ms\n", leader_mode_to_string(config->leader.mode), config->leader.timeout_ms); printf("Wheel Mode: %s", config->wheel_mode == WHEEL_MODE_SEQUENTIAL ? "sequential" : "sets"); @@ -1,5 +1,5 @@ /* - V1.7.0 - Enhanced OSD Feedback & Wheel Descriptions + V1.7.1 - Leader Key Descriptions https://github.com/mckset/KD100.git KD100 Linux driver for X11 desktops Features: @@ -169,7 +169,7 @@ int main(int args, char *in[]) { printf("\t-d [-d]\t\tEnable debug outputs (use twice to view data sent by the device)\n"); printf("\t-dry \t\tDisplay data sent by the device without sending events\n"); printf("\t-h\t\tDisplays this message\n"); - printf("\nNew in v1.7.0 - ENHANCED OSD FEEDBACK:\n"); + printf("\nNew in v1.7.1 - LEADER KEY DESCRIPTIONS:\n"); printf("\t• Wheel function descriptions (wheel_description_N: name)\n"); printf("\t• Active button highlighting in expanded keyboard layout\n"); printf("\t• Leader key visual feedback (orange/purple indicators)\n"); @@ -249,8 +249,8 @@ int main(int args, char *in[]) { } } - printf("\nKD100 Driver v1.7.0 - Enhanced OSD Feedback & Wheel Descriptions\n"); - printf("Features: OSD overlay | Profile switching | Wheel descriptions | Button highlighting\n\n"); + printf("\nKD100 Driver v1.7.1 - Leader Key Descriptions\n"); + printf("Features: OSD overlay | Profile switching | Wheel descriptions | Leader descriptions | Button highlighting\n\n"); // Run device handler device_run(ctx, config, debug, accept, dry); @@ -97,6 +97,7 @@ osd_state_t* osd_create(config_t* config) { // Initialize key descriptions to NULL for (int i = 0; i < 19; i++) { osd->key_descriptions[i] = NULL; + osd->leader_descriptions[i] = NULL; } // Initialize active button state @@ -136,6 +137,7 @@ void osd_destroy(osd_state_t* osd) { // Free key descriptions for (int i = 0; i < 19; i++) { if (osd->key_descriptions[i]) free(osd->key_descriptions[i]); + if (osd->leader_descriptions[i]) free(osd->leader_descriptions[i]); } // Free wheel descriptions @@ -439,9 +441,11 @@ static void draw_button_key(Display* dpy, Window win, GC gc, osd_state_t* osd, snprintf(num, sizeof(num), "%d", btn); XDrawString(dpy, win, gc, x + text_offset_x, y + text_offset_y1, num, strlen(num)); - // Draw description or function + // Draw description or function (swap to leader description when leader is active) const char* desc = NULL; - if (osd->key_descriptions[btn]) { + if (is_leader_modified && osd->leader_descriptions[btn]) { + desc = osd->leader_descriptions[btn]; + } else if (osd->key_descriptions[btn]) { desc = osd->key_descriptions[btn]; } else if (osd->config && btn < osd->config->totalButtons && osd->config->events[btn].function) { @@ -907,6 +911,16 @@ void osd_set_key_description(osd_state_t* osd, int button_index, const char* des osd->key_descriptions[button_index] = description ? strdup(description) : NULL; } +// Set leader key description +void osd_set_leader_description(osd_state_t* osd, int button_index, const char* description) { + if (osd == NULL || button_index < 0 || button_index > 18) return; + + if (osd->leader_descriptions[button_index]) { + free(osd->leader_descriptions[button_index]); + } + osd->leader_descriptions[button_index] = description ? strdup(description) : NULL; +} + // Get key description const char* osd_get_key_description(osd_state_t* osd, int button_index) { if (osd == NULL || button_index < 0 || button_index > 18) return NULL; @@ -73,7 +73,8 @@ typedef struct { config_t* config; // Key descriptions for the current profile - char* key_descriptions[19]; // Descriptions for buttons 0-18 + char* key_descriptions[19]; // Descriptions for buttons 0-18 + char* leader_descriptions[19]; // Descriptions when leader is active // Active button highlighting int active_button; // Currently pressed button (-1 = none) @@ -110,6 +111,7 @@ void osd_move(osd_state_t* osd, int dx, int dy); // Key description functions void osd_set_key_description(osd_state_t* osd, int button_index, const char* description); +void osd_set_leader_description(osd_state_t* osd, int button_index, const char* description); const char* osd_get_key_description(osd_state_t* osd, int button_index); void osd_clear_descriptions(osd_state_t* osd);