← KD100

Add auto-show/auto-hide feature for OSD

ccec19272dc161567ff91efb69c0e9c061466e9a · Claude · Feb 7, 2026 04:50

When osd_auto_show is enabled (default: true) and osd_start_visible
is false, the OSD will automatically appear when keys are pressed
and hide after the display_duration_ms timeout.

Changes:
- Added osd_auto_show config option
- Added last_action_time_ms tracking in osd state
- osd_record_action now shows OSD when hidden (if auto_show enabled)
- osd_update now auto-hides after display_duration_ms of inactivity
- Updated device.c to always call osd_update for auto-hide timer

https://claude.ai/code/session_01H5sr8TkRyt6U1vdkVZRRvy

+40 −7 · 6 files changed

  • default.cfg +2 −0
  • src/config.c +9 −0
  • src/config.h +1 −0
  • src/device.c +3 −2
  • src/osd.c +23 −5
  • src/osd.h +2 −0
diff --git a/default.cfg b/default.cfg
index cfaf940..f94e5c2 100644
--- a/default.cfg
+++ b/default.cfg
@@ -62,6 +62,7 @@
 //      OSD Settings:
 //        osd_enabled:          true/false - Enable/disable OSD feature
 //        osd_start_visible:    true/false - Show OSD when driver starts
+//        osd_auto_show:        true/false - Auto-show OSD when keys are pressed (then auto-hide)
 //        osd_position:         x,y - Initial position on screen
 //        osd_opacity:          0.0-1.0 - Background opacity (0.67 = 33% transparent)
 //        osd_display_duration: milliseconds - How long actions stay visible
@@ -72,6 +73,7 @@
 //
 osd_enabled: true
 osd_start_visible: false
+osd_auto_show: true
 osd_position: 50,50
 osd_opacity: 0.67
 osd_display_duration: 3000
diff --git a/src/config.c b/src/config.c
index 8587bfb..1f8ec6c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -90,6 +90,7 @@ config_t* config_create(void) {
     // Initialize OSD settings
     config->osd.enabled = 0;
     config->osd.start_visible = 0;
+    config->osd.auto_show = 1;  // Auto-show on key press by default
     config->osd.pos_x = 50;
     config->osd.pos_y = 50;
     config->osd.opacity = 0.67f;  // 33% transparent = 67% opaque
@@ -294,6 +295,14 @@ int config_load(config_t* config, const char* filename, int debug) {
             continue;
         }
 
+        if (strncasecmp(line, "osd_auto_show:", 14) == 0) {
+            char* value = line + 14;
+            while (*value == ' ') value++;
+            config->osd.auto_show = (strncasecmp(value, "true", 4) == 0 || strcmp(value, "1") == 0);
+            if (debug) printf("Config: osd_auto_show = %s\n", config->osd.auto_show ? "true" : "false");
+            continue;
+        }
+
         if (strncasecmp(line, "osd_position:", 13) == 0) {
             char* value = line + 13;
             while (*value == ' ') value++;
diff --git a/src/config.h b/src/config.h
index 4c4af8e..528d28f 100644
--- a/src/config.h
+++ b/src/config.h
@@ -19,6 +19,7 @@ typedef struct {
 typedef struct {
     int enabled;              // Is OSD enabled
     int start_visible;        // Show OSD on startup
+    int auto_show;            // Auto-show OSD when keys are pressed
     int pos_x;                // Initial X position
     int pos_y;                // Initial Y position
     float opacity;            // Background opacity (0.0-1.0, default 0.67 = 33% transparent)
diff --git a/src/device.c b/src/device.c
index 6412eaf..a176a17 100644
--- a/src/device.c
+++ b/src/device.c
@@ -61,6 +61,7 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in
             osd->expanded_width = config->osd.expanded_width;
             osd->expanded_height = config->osd.expanded_height;
             osd->font_size = config->osd.font_size;
+            osd->auto_show = config->osd.auto_show;
 
             // Initialize X11 display
             if (osd_init_display(osd) == 0) {
@@ -355,8 +356,8 @@ void device_run(libusb_context* ctx, config_t* config, int debug, int accept, in
                     unsigned char data[40];
                     int keycode = 0;
 
-                    // Update OSD (process X11 events)
-                    if (osd && osd->mode != OSD_MODE_HIDDEN) {
+                    // Update OSD (process X11 events and auto-hide timer)
+                    if (osd) {
                         osd_update(osd);
                     }
 
diff --git a/src/osd.c b/src/osd.c
index 1e5d89a..298524b 100644
--- a/src/osd.c
+++ b/src/osd.c
@@ -85,6 +85,8 @@ osd_state_t* osd_create(config_t* config) {
     osd->opacity = 0.67f;  // 33% transparent = 67% opaque
     osd->display_duration_ms = 3000;  // Show actions for 3 seconds
     osd->font_size = 13;  // Default font size
+    osd->auto_show = 1;  // Auto-show on key press by default
+    osd->last_action_time_ms = 0;
     osd->recent_count = 0;
     osd->recent_head = 0;
     osd->config = config;
@@ -317,12 +319,16 @@ void osd_record_action(osd_state_t* osd, int button_index, const char* action) {
     if (osd->recent_actions[slot].action) free(osd->recent_actions[slot].action);
 
     // Store new action
+    long now = osd_get_time_ms();
     osd->recent_actions[slot].key_name = strdup(BUTTON_NAMES[button_index]);
     osd->recent_actions[slot].action = action ? strdup(action) : strdup("(unknown)");
-    osd->recent_actions[slot].timestamp_ms = osd_get_time_ms();
+    osd->recent_actions[slot].timestamp_ms = now;
+    osd->last_action_time_ms = now;
 
-    // Trigger redraw if visible
-    if (osd->mode != OSD_MODE_HIDDEN) {
+    // Auto-show OSD if hidden and auto_show is enabled
+    if (osd->mode == OSD_MODE_HIDDEN && osd->auto_show && osd->display != NULL) {
+        osd_set_mode(osd, OSD_MODE_MINIMAL);
+    } else if (osd->mode != OSD_MODE_HIDDEN) {
         osd_redraw(osd);
     }
 }
@@ -520,10 +526,23 @@ void osd_redraw(osd_state_t* osd) {
 
 // Process X11 events
 void osd_update(osd_state_t* osd) {
-    if (osd == NULL || osd->display == NULL || osd->mode == OSD_MODE_HIDDEN) return;
+    if (osd == NULL || osd->display == NULL) return;
 
     Display* dpy = (Display*)osd->display;
     Window win = (Window)osd->window;
+    long now = osd_get_time_ms();
+
+    // Auto-hide check: if auto_show is enabled, OSD is visible, and enough time passed
+    if (osd->auto_show && osd->mode != OSD_MODE_HIDDEN && osd->last_action_time_ms > 0) {
+        long time_since_action = now - osd->last_action_time_ms;
+        if (time_since_action > osd->display_duration_ms) {
+            osd_hide(osd);
+            return;
+        }
+    }
+
+    // Only process X11 events if visible
+    if (osd->mode == OSD_MODE_HIDDEN) return;
 
     while (XPending(dpy)) {
         XEvent event;
@@ -580,7 +599,6 @@ void osd_update(osd_state_t* osd) {
 
     // Check if we need to clear old actions and redraw
     static long last_cleanup = 0;
-    long now = osd_get_time_ms();
     if (now - last_cleanup > 500) {  // Check every 500ms
         last_cleanup = now;
 
diff --git a/src/osd.h b/src/osd.h
index c4ee3af..3431502 100644
--- a/src/osd.h
+++ b/src/osd.h
@@ -32,6 +32,8 @@ typedef struct {
     float opacity;                // Background opacity (0.0-1.0)
     int display_duration_ms;      // How long to show key actions
     int font_size;                // Font size in pixels (default 13)
+    int auto_show;                // Auto-show OSD on key press
+    long last_action_time_ms;     // Time of last action (for auto-hide)
 
     // Recent actions buffer (circular)
     recent_action_t recent_actions[10];