feat: restore keyboard backlight on focus loss
This commit is contained in:
@@ -5,18 +5,20 @@
|
|||||||
* Listens to pause/playback/core-idle so lights only stay off when media is actively playing.
|
* 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.
|
* 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.
|
* 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:
|
Requirements:
|
||||||
* Linux + mpv 0.36+ with the bundled Lua 5.2 runtime.
|
* 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.
|
* `brightnessctl` accessible in PATH or via `brightnessctl_path`, with permission to control the target LED class device.
|
||||||
|
|
||||||
Configuration:
|
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 = {
|
local config = {
|
||||||
timeout_ms = 3000,
|
timeout_ms = 3000,
|
||||||
restore_on_pause = true,
|
restore_on_pause = true,
|
||||||
|
restore_on_unfocus = true,
|
||||||
minimum_brightness = 0,
|
minimum_brightness = 0,
|
||||||
led_path = "",
|
led_path = "",
|
||||||
debounce_ms = 250,
|
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.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.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_pause = coerce_boolean(config.restore_on_pause, true)
|
||||||
|
config.restore_on_unfocus = coerce_boolean(config.restore_on_unfocus, true)
|
||||||
|
|
||||||
local function seconds(ms)
|
local function seconds(ms)
|
||||||
return (tonumber(ms) or 0) / 1000
|
return (tonumber(ms) or 0) / 1000
|
||||||
@@ -68,6 +71,7 @@ local state = {
|
|||||||
device_detection_attempted = false,
|
device_detection_attempted = false,
|
||||||
first_frame_seen = false,
|
first_frame_seen = false,
|
||||||
pending_timer = false,
|
pending_timer = false,
|
||||||
|
window_focused = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function detect_keyboard_device()
|
local function detect_keyboard_device()
|
||||||
@@ -388,6 +392,30 @@ local function handle_idle_event(tag)
|
|||||||
restore_backlight(tag or "idle")
|
restore_backlight(tag or "idle")
|
||||||
end
|
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)
|
local function on_pause(_, value)
|
||||||
if value == nil then
|
if value == nil then
|
||||||
return
|
return
|
||||||
@@ -425,9 +453,17 @@ local function on_filename(_, value)
|
|||||||
end
|
end
|
||||||
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("pause", "bool", on_pause)
|
||||||
mp.observe_property("playback-time", "native", on_playback_time)
|
mp.observe_property("playback-time", "native", on_playback_time)
|
||||||
mp.observe_property("filename", "string", on_filename)
|
mp.observe_property("filename", "string", on_filename)
|
||||||
|
mp.observe_property("focused", "bool", on_focus)
|
||||||
|
|
||||||
mp.register_event("end-file", function()
|
mp.register_event("end-file", function()
|
||||||
handle_idle_event("end-file")
|
handle_idle_event("end-file")
|
||||||
|
|||||||
Reference in New Issue
Block a user