feat!: add W Engine plugin (#81)
* feat!: add W Engine plugin * feat!: add en translation * fix: rm useless line * feat!: add preview window in a pannel * fix: rm no dependencies tools * feat!: update thumbnail with new image * feat: add screen choose with selector and add id check for warn string command folder * docs: add dependencies on toml and read me * fix: rm pkill and use kill * feat!: add multiple path check, default output, select where set wallpaper * feat!: rm debug notif * docs: add new action documentation * feat!: add new service for good restart (pkill all instance linux-wallpaper and rm all tmp file created by w engine) * feat!: add check if pid is a linux-wallpaper instance * docs: add depedencie and new entries * feat!: support personnal path with json load * docs: add docs for custom path * feat!: use new api function for show all wallpaper * fix: rm useless notify
This commit is contained in:
@@ -0,0 +1,263 @@
|
||||
--!nonstrict
|
||||
-- W-Engine panel — picks a Wallpaper Engine workshop item and applies it via
|
||||
-- linux-wallpaperengine.
|
||||
|
||||
-- Local variable
|
||||
|
||||
wallpaperPath = {"~/.steam/steam/steamapps/workshop/content/431960/",
|
||||
"~/.local/share/Steam/steamapps/workshop/content/431960/",
|
||||
"~/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/workshop/content/431960/",
|
||||
"~/snap/steam/common/.local/share/Steam/steamapps/workshop/content/431960/",
|
||||
"~/snap/steam/common/.local/share/steam/steamapps/workshop/content/431960/"}
|
||||
wallpaperPathSelected = nil
|
||||
|
||||
local pickSlots = {}
|
||||
local columns = 4
|
||||
local previewWidth = 180
|
||||
local previewHeight = 100
|
||||
|
||||
local outputFinalList = {}
|
||||
local outputSelectedName = nil
|
||||
local lastOutputUse = nil
|
||||
|
||||
local pidList: { killSystem } = {}
|
||||
|
||||
-- load personnal path
|
||||
|
||||
local dir = noctalia.pluginDataDir()
|
||||
local path = dir .. "/data.json"
|
||||
local raw = noctalia.readFile(path)
|
||||
if raw then
|
||||
local data = noctalia.json.decode(raw)
|
||||
if data and data.personnalPath then
|
||||
for _, p in ipairs(data.personnalPath) do
|
||||
table.insert(wallpaperPath, p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--
|
||||
type Wallpaper = {
|
||||
nb: string,
|
||||
name: string,
|
||||
preview: string,
|
||||
}
|
||||
|
||||
type killSystem = {
|
||||
pid: number,
|
||||
output: string,
|
||||
}
|
||||
|
||||
function tr(key, subst)
|
||||
if subst then
|
||||
return noctalia.tr(key, subst)
|
||||
end
|
||||
return noctalia.tr(key)
|
||||
end
|
||||
|
||||
function takeWallpaper()
|
||||
local wallpaper: { Wallpaper } = {}
|
||||
|
||||
for count = 1, #wallpaperPath, 1 do
|
||||
if noctalia.listDir(wallpaperPath[count]) then
|
||||
wallpaperPathSelected = wallpaperPath[count]
|
||||
end
|
||||
end
|
||||
|
||||
local entries, err = noctalia.listDir(wallpaperPathSelected)
|
||||
if not entries then
|
||||
warn(err or "impossible de lister")
|
||||
noctalia.notify(tr("panel.title"), tr("panel.list_failed"))
|
||||
return wallpaper
|
||||
end
|
||||
for _, entryName in entries do
|
||||
|
||||
if not tonumber(entryName) then -- test if is a id
|
||||
continue
|
||||
end
|
||||
|
||||
local content, readErr = noctalia.readFile(wallpaperPathSelected .. entryName .. "/project.json")
|
||||
if content then
|
||||
local value = noctalia.json.decode(content)
|
||||
local name = value.title or entryName
|
||||
local preview = value.preview or "no preview"
|
||||
table.insert(wallpaper, {
|
||||
nb = entryName,
|
||||
name = name,
|
||||
preview = preview,
|
||||
})
|
||||
else
|
||||
noctalia.notify(tr("panel.title"), tr("panel.missing_project_json", { name = entryName }))
|
||||
end
|
||||
end
|
||||
return wallpaper
|
||||
end
|
||||
|
||||
function trim(s) -- personnal trim
|
||||
return (s:gsub("^%s+", ""):gsub("%s+$", ""))
|
||||
end
|
||||
|
||||
function isValidPid(screen, pid)
|
||||
local path = "/tmp/w-engine-" .. screen .. ".pid"
|
||||
if noctalia.fileExists(path) then
|
||||
local fileTmp = noctalia.readFile(path)
|
||||
if not fileTmp then
|
||||
return false
|
||||
end
|
||||
local file = trim(fileTmp)
|
||||
if file == pid then
|
||||
|
||||
local check = "/proc/" .. pid .. "/cmdline"
|
||||
local checkContentTmp = noctalia.readFile(check)
|
||||
if not checkContentTmp then
|
||||
return false
|
||||
end
|
||||
local checkContent = trim(checkContentTmp)
|
||||
local match = "^linux%-wallpaperengine"
|
||||
if checkContent:match(match) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function getStoredPid(screen)
|
||||
for _, entry in ipairs(pidList) do
|
||||
if entry.output == screen then
|
||||
if isValidPid(screen, entry.pid) then
|
||||
return entry.pid
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function setStoredPid(screen, pid)
|
||||
for _, entry in ipairs(pidList) do
|
||||
if entry.output == screen then
|
||||
entry.pid = pid
|
||||
return
|
||||
end
|
||||
end
|
||||
table.insert(pidList, { pid = pid, output = screen })
|
||||
end
|
||||
|
||||
|
||||
function launchWallpaper(screen, id, pidFile)
|
||||
local cmd = "setsid linux-wallpaperengine --screen-root " .. screen .. " " .. id
|
||||
.. " > /dev/null 2>&1 & echo $! > " .. pidFile
|
||||
|
||||
noctalia.runAsync(cmd, function(result)
|
||||
local pidContent = noctalia.readFile(pidFile)
|
||||
if pidContent then
|
||||
local pid = trim(pidContent)
|
||||
setStoredPid(screen, pid)
|
||||
end
|
||||
end, 5000)
|
||||
end
|
||||
|
||||
function loadWallpaper(id)
|
||||
lastOutputUse = outputSelectedName or takeOutput()
|
||||
local pidFile = "/tmp/w-engine-" .. lastOutputUse .. ".pid"
|
||||
local oldPid = getStoredPid(lastOutputUse) -- here
|
||||
if oldPid then
|
||||
noctalia.runAsync("kill " .. oldPid, function() -- here
|
||||
launchWallpaper(lastOutputUse, id, pidFile)
|
||||
end, 3000)
|
||||
else
|
||||
launchWallpaper(lastOutputUse, id, pidFile)
|
||||
end
|
||||
end
|
||||
|
||||
function onPickAt(slot)
|
||||
local id = pickSlots[slot]
|
||||
if id ~= nil then
|
||||
loadWallpaper(id)
|
||||
noctalia.notify(tr("panel.title"), tr("panel.apply", { id = id }))
|
||||
end
|
||||
end
|
||||
|
||||
local function render()
|
||||
pickSlots = {}
|
||||
local tiles = {}
|
||||
local list = takeWallpaper()
|
||||
for count = 1, #list, 1 do
|
||||
local data = list[count]
|
||||
local slotIndex = count - 1
|
||||
pickSlots[slotIndex] = data.nb
|
||||
table.insert(tiles, ui.column({ gap = 4, key = data.nb, align = "center" }, {
|
||||
ui.image({
|
||||
path = wallpaperPathSelected .. data.nb .. "/" .. data.preview,
|
||||
width = previewWidth,
|
||||
height = previewHeight,
|
||||
fit = "cover",
|
||||
radius = 8,
|
||||
onClick = function()
|
||||
loadWallpaper(pickSlots[slotIndex])
|
||||
noctalia.notify(tr("panel.title"), tr("panel.apply", { id = pickSlots[slotIndex] }))
|
||||
end,
|
||||
}),
|
||||
ui.label({
|
||||
text = data.name,
|
||||
fontSize = 11,
|
||||
maxLines = 1,
|
||||
maxWidth = 120,
|
||||
textAlign = "center",
|
||||
}),
|
||||
}))
|
||||
end
|
||||
local rows = {}
|
||||
local row = {}
|
||||
for i, tile in ipairs(tiles) do
|
||||
table.insert(row, tile)
|
||||
if #row == columns or i == #tiles then
|
||||
table.insert(rows, ui.row({ gap = 12, align = "start" }, row))
|
||||
row = {}
|
||||
end
|
||||
end
|
||||
panel.render(ui.column({ flexGrow = 1, gap = 16 }, {
|
||||
ui.row({ align = "center", justify = "space_between", gap = 8 }, {
|
||||
ui.label({ text = tr("panel.title"), align = "center", fontSize = 16, fontWeight = "bold", color = "on_surface", flexGrow = 1 }),
|
||||
ui.select({ options = getOutput(), onChange = "outputSelected" }),
|
||||
ui.button({ glyph = "close", onClick = "onCloseClicked" }),
|
||||
}),
|
||||
ui.scroll({ gap = 12, align = "stretch", flexGrow = 1 }, rows),
|
||||
}))
|
||||
end
|
||||
|
||||
function takeOutput()
|
||||
local output = noctalia.outputs()
|
||||
for _, outputF in ipairs(output) do
|
||||
return outputF.name
|
||||
end
|
||||
end
|
||||
|
||||
function outputSelected(index, label)
|
||||
if type(label) == "string" and label ~= "" then
|
||||
outputSelectedName = label
|
||||
noctalia.notify("Output change :", outputSelectedName)
|
||||
end
|
||||
end
|
||||
|
||||
function getOutput()
|
||||
outputFinalList = {}
|
||||
local outputsList = noctalia.outputs()
|
||||
if not outputsList then
|
||||
return
|
||||
end
|
||||
for _, output in ipairs(outputsList) do
|
||||
noctalia.log(output.name)
|
||||
table.insert(outputFinalList, output.name)
|
||||
end
|
||||
return outputFinalList
|
||||
end
|
||||
|
||||
function onOpen(_context)
|
||||
outputSelectedName = takeOutput()
|
||||
render()
|
||||
end
|
||||
|
||||
function onCloseClicked()
|
||||
panel.close()
|
||||
end
|
||||
Reference in New Issue
Block a user