thinkpad-led (#329)

* thinkpad-led

* Update en.json

* Update README with widget information

* PR fixes

* fix PR
This commit is contained in:
Zeti_1223
2026-08-11 10:42:13 -04:00
committed by GitHub
parent 30f6bf0d66
commit 1cdbaba5e7
5 changed files with 143 additions and 0 deletions
+27
View File
@@ -0,0 +1,27 @@
# ThinkPad Logo LED
A simple Noctalia bar widget to toggle the ThinkPad lid logo LED on and off.
## Plugin
| Property | Value |
| --- | --- |
| **ID** | `zeti1223/thinkpad-led` |
| **Widget** | `led` |
| **Version** | `1.1.0` |
| **Author** | zeti1223 |
| **License** | MIT |
## Usage
Add the `led` widget to your Noctalia bar layout. Clicking the widget toggles the ThinkPad logo LED state.
* **Left Click**: Toggle LED (ON / OFF).
## Requirements
* `sh`
## Notes
* **Hardware & Permissions**: This plugin writes directly to `/sys/class/leds/tpacpi::lid_logo_dot/brightness`. Ensure your user account has write permissions to this path (for example, via a `udev` rule), otherwise command execution will fail.
+14
View File
@@ -0,0 +1,14 @@
id = "zeti1223/thinkpad-led"
name = "ThinkPad Logo LED"
version = "1.1.0"
plugin_api = 3
author = "zeti1223"
license = "MIT"
dependencies = ["sh"]
tags = ["bar", "hardware"]
icon = "bulb"
description = "Turn the ThinkPad lid logo LED on or off."
[[widget]]
id = "led"
entry = "widget.luau"
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

+1
View File
@@ -0,0 +1 @@
{}
+101
View File
@@ -0,0 +1,101 @@
--!nonstrict
-- ThinkPad lid logo LED — bar widget
-- A red dot in the bar that directly controls the /sys/class/leds/tpacpi::lid_logo_dot LED.
-- Left click : toggle on / off
local LED_PATH = "/sys/class/leds/tpacpi::lid_logo_dot/brightness"
-- Tri-state: true = on, false = off, nil = unknown (path missing, unreadable, etc).
local ledOn = nil
local pending = false -- true while a toggle write is in flight
local writeFailed = false -- true if the last write attempt did not succeed
-- Reads the LED brightness straight from sysfs instead of trusting any cached
-- guess. Returns nil when the file can't be read (missing device, no
-- permissions, etc), which the UI renders as an "unavailable" state.
local function readLedState()
local contents = noctalia.readFile(LED_PATH)
if not contents then
return nil
end
local value = tonumber((contents:gsub("%s+", "")))
if not value then
return nil
end
return value > 0
end
local function statusColor()
if ledOn then
return "error"
else
return "outline"
end
end
local function render()
barWidget.render(ui.box({
width = 10,
height = 10,
radius = 5,
fill = statusColor(),
border = "outline",
borderWidth = 1,
}))
if ledOn == nil then
barWidget.setTooltip("ThinkPad LED: unavailable (check permissions on " .. LED_PATH .. ")")
elseif pending then
barWidget.setTooltip("ThinkPad LED: updating…")
elseif writeFailed then
barWidget.setTooltip("ThinkPad LED: last toggle failed (permission denied?)")
elseif ledOn then
barWidget.setTooltip("ThinkPad LED: ON (Left click: turn off)")
else
barWidget.setTooltip("ThinkPad LED: OFF (Left click: turn on)")
end
end
function update()
if not pending then
ledOn = readLedState()
end
render()
end
function onClick()
if pending then
return
end
-- Toggle off the actual hardware state, not a guessed one.
local current = readLedState()
if current == nil then
ledOn = nil
render()
return
end
local target = not current
local val = target and "255" or "0"
pending = true
writeFailed = false
render()
local started = noctalia.runAsync(`sh -c "echo {val} > {LED_PATH}"`, function(result)
pending = false
writeFailed = result.exitCode ~= 0
-- Trust the hardware over the write result: read the brightness back
-- rather than assuming the echo did what we asked.
ledOn = readLedState()
render()
end)
if not started then
pending = false
writeFailed = true
ledOn = readLedState()
render()
end
end