diff --git a/scripts/kb-blackout.lua b/scripts/kb-blackout.lua index 624c0d2..f1a46a4 100644 --- a/scripts/kb-blackout.lua +++ b/scripts/kb-blackout.lua @@ -5,18 +5,20 @@ * Listens to pause/playback/core-idle so lights only stay off when media is actively playing. * Captures the session's starting brightness, dims via `brightnessctl`, and restores exactly that value when playback stops. * Debounces rapid state flips, auto-discovers an LED device (`brightnessctl --list`), and surfaces warnings when Linux, device, or permission prerequisites fail. + * Optionally restores the keyboard backlight whenever mpv loses window focus so other apps retain your preferred lighting. Requirements: * Linux + mpv 0.36+ with the bundled Lua 5.2 runtime. * `brightnessctl` accessible in PATH or via `brightnessctl_path`, with permission to control the target LED class device. Configuration: - Edit the `config` table below to tune timeouts, restore behavior, minimum brightness, LED device detection, and the `brightnessctl` binary path. + Edit the `config` table below to tune timeouts, restore behavior, minimum brightness, LED device detection, focus handling, and the `brightnessctl` binary path. ]] local config = { timeout_ms = 3000, restore_on_pause = true, + restore_on_unfocus = true, minimum_brightness = 0, led_path = "", debounce_ms = 250, @@ -50,6 +52,7 @@ config.timeout_ms = tonumber(config.timeout_ms) or 3000 config.minimum_brightness = math.max(0, math.floor(tonumber(config.minimum_brightness) or 0)) config.debounce_ms = math.max(0, tonumber(config.debounce_ms) or 250) config.restore_on_pause = coerce_boolean(config.restore_on_pause, true) +config.restore_on_unfocus = coerce_boolean(config.restore_on_unfocus, true) local function seconds(ms) return (tonumber(ms) or 0) / 1000 @@ -68,6 +71,7 @@ local state = { device_detection_attempted = false, first_frame_seen = false, pending_timer = false, + window_focused = true, } local function detect_keyboard_device() @@ -388,6 +392,30 @@ local function handle_idle_event(tag) restore_backlight(tag or "idle") end +local function handle_focus_event(source, focused) + local is_focused = not not focused + if state.window_focused == is_focused then + return + end + state.window_focused = is_focused + + if not is_focused then + emit_intent("focus_lost") + cancel_timer() + if config.restore_on_unfocus then + restore_backlight(source or "focus-lost") + else + msg.verbose("Focus lost; restore_on_unfocus disabled; keeping lights off.") + end + return + end + + emit_intent("focus_gained") + if state.playback_active and not mp.get_property_native("pause") then + handle_play_event(source or "focus-gained") + end +end + local function on_pause(_, value) if value == nil then return @@ -425,9 +453,17 @@ local function on_filename(_, value) end end +local function on_focus(_, value) + if value == nil then + return + end + handle_focus_event("focus", value) +end + mp.observe_property("pause", "bool", on_pause) mp.observe_property("playback-time", "native", on_playback_time) mp.observe_property("filename", "string", on_filename) +mp.observe_property("focused", "bool", on_focus) mp.register_event("end-file", function() handle_idle_event("end-file")