367 lines
10 KiB
Lua
367 lines
10 KiB
Lua
-- Vicious module initialization
|
|
-- Copyright (C) 2009 Lucas de Vries <lucas@glacicle.com>
|
|
-- Copyright (C) 2009-2013 Adrian C. (anrxc) <anrxc@sysphere.org>
|
|
-- Copyright (C) 2011-2017 Joerg Thalheim <joerg@thalheim.io>
|
|
-- Copyright (C) 2012 Arvydas Sidorenko <asido4@gmail.com>
|
|
-- Copyright (C) 2013 Dodo <dodo.the.last@gmail.com>
|
|
-- Copyright (C) 2014 blastmaster <blastmaster@tuxcode.org>
|
|
-- Copyright (C) 2015,2019 Daniel Hahler <github@thequod.de>
|
|
-- Copyright (C) 2017 James Reed <supplantr@users.noreply.github.com>
|
|
-- Copyright (C) 2017 getzze <getzze@gmail.com>
|
|
-- Copyright (C) 2017 mutlusun <mutlusun@github.com>
|
|
-- Copyright (C) 2018 Beniamin Kalinowski <beniamin.kalinowski@gmail.com>
|
|
-- Copyright (C) 2018,2020 Nguyễn Gia Phong <mcsinyx@disroot.org>
|
|
-- Copyright (C) 2022 Constantin Piber <cp.piber@gmail.com>
|
|
--
|
|
-- This file is part of Vicious.
|
|
--
|
|
-- Vicious is free software: you can redistribute it and/or modify
|
|
-- it under the terms of the GNU General Public License as
|
|
-- published by the Free Software Foundation, either version 2 of the
|
|
-- License, or (at your option) any later version.
|
|
--
|
|
-- Vicious is distributed in the hope that it will be useful,
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
-- GNU General Public License for more details.
|
|
--
|
|
-- You should have received a copy of the GNU General Public License
|
|
-- along with Vicious. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
-- {{{ Setup environment
|
|
local type = type
|
|
local pairs = pairs
|
|
local tonumber = tonumber
|
|
local timer = type(timer) == "table" and timer or require("gears.timer")
|
|
local os = { time = os.time }
|
|
local table = {
|
|
insert = table.insert,
|
|
remove = table.remove
|
|
}
|
|
local helpers = require("vicious.helpers")
|
|
local dstatus, debug = pcall(require, "gears.debug")
|
|
local stderr = io.stderr
|
|
local warn
|
|
if dstatus then
|
|
warn = debug.print_warning
|
|
else
|
|
warn = function (msg) stderr:write("Warning (vicious): ", msg, "\n") end
|
|
end
|
|
|
|
-- Vicious: widgets for the awesome window manager
|
|
local vicious = {}
|
|
vicious.widgets = require("vicious.widgets")
|
|
--vicious.contrib = require("vicious.contrib")
|
|
|
|
-- Initialize tables
|
|
local timers = {}
|
|
local registered = {}
|
|
local widget_cache = {}
|
|
-- }}}
|
|
|
|
|
|
-- {{{ Local functions
|
|
-- {{{ Update a widget
|
|
local function update(widget, reg, disablecache)
|
|
-- Check if there are any equal widgets
|
|
if reg == nil then
|
|
for w, i in pairs(registered) do
|
|
if w == widget then
|
|
for _, r in pairs(i) do
|
|
update(w, r, disablecache)
|
|
end
|
|
end
|
|
end
|
|
|
|
return
|
|
end
|
|
|
|
local update_time = os.time()
|
|
|
|
local function format_data(data)
|
|
local ret
|
|
if type(data) == "table" then
|
|
local escaped_data = {}
|
|
for k, v in pairs(data) do
|
|
if type(v) == "string" then
|
|
escaped_data[k] = helpers.escape(v)
|
|
else
|
|
escaped_data[k] = v
|
|
end
|
|
end
|
|
|
|
if type(reg.format) == "string" then
|
|
ret = helpers.format(reg.format, escaped_data)
|
|
elseif type(reg.format) == "function" then
|
|
ret = reg.format(widget, escaped_data)
|
|
end
|
|
end
|
|
return ret or data
|
|
end
|
|
|
|
local function topercent(e) return tonumber(e) and tonumber(e) / 100 end
|
|
|
|
local function update_value(data)
|
|
local fmtd_data = format_data(data)
|
|
if widget.add_value ~= nil then
|
|
if widget.get_stack ~= nil and widget:get_stack() then
|
|
for idx, _ in ipairs(widget:get_stack_colors()) do
|
|
if fmtd_data[idx] then
|
|
widget:add_value(topercent(fmtd_data[idx]), idx)
|
|
end
|
|
end
|
|
else
|
|
widget:add_value(topercent(fmtd_data))
|
|
end
|
|
elseif widget.set_value ~= nil then
|
|
widget:set_value(topercent(fmtd_data))
|
|
elseif widget.set_markup ~= nil then
|
|
widget:set_markup(fmtd_data)
|
|
else
|
|
widget.text = fmtd_data
|
|
end
|
|
end
|
|
|
|
local function update_cache(data, t, cache)
|
|
-- Update cache
|
|
if t and cache then
|
|
cache.time, cache.data = t, data
|
|
end
|
|
end
|
|
|
|
-- Check for cached output newer than the last update
|
|
local c = widget_cache[reg.wtype]
|
|
if c and update_time < c.time + reg.timeout and not disablecache then
|
|
update_value(c.data)
|
|
elseif reg.wtype then
|
|
if type(reg.wtype) == "table" and reg.wtype.async then
|
|
if not reg.lock then
|
|
reg.lock = true
|
|
return reg.wtype.async(reg.format,
|
|
reg.warg,
|
|
function(data)
|
|
update_cache(data, update_time, c)
|
|
local status, res = pcall(update_value, data)
|
|
if not status then warn(res) end
|
|
reg.lock=false
|
|
end)
|
|
end
|
|
else
|
|
local data = reg.wtype(reg.format, reg.warg)
|
|
update_cache(data, update_time, c)
|
|
update_value(data)
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Register from reg object
|
|
local function regregister(reg)
|
|
if not reg.running then
|
|
if registered[reg.widget] == nil then
|
|
registered[reg.widget] = {}
|
|
table.insert(registered[reg.widget], reg)
|
|
else
|
|
local already = false
|
|
|
|
for w, i in pairs(registered) do
|
|
if w == reg.widget then
|
|
for _, v in pairs(i) do
|
|
if v == reg then
|
|
already = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if already then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if not already then
|
|
table.insert(registered[reg.widget], reg)
|
|
end
|
|
end
|
|
|
|
-- Start the timer
|
|
if reg.timeout > 0 then
|
|
local tm = timers[reg.timeout] and timers[reg.timeout].timer
|
|
tm = tm or timer({ timeout = reg.timeout })
|
|
if tm.connect_signal then
|
|
tm:connect_signal("timeout", reg.update)
|
|
else
|
|
tm:add_signal("timeout", reg.update)
|
|
end
|
|
if not timers[reg.timeout] then
|
|
timers[reg.timeout] = { timer = tm, refs = 1 }
|
|
else
|
|
timers[reg.timeout].refs = timers[reg.timeout].refs + 1
|
|
end
|
|
if not tm.started then
|
|
tm:start()
|
|
end
|
|
-- Initial update
|
|
reg.update()
|
|
end
|
|
reg.running = true
|
|
end
|
|
end
|
|
-- }}}
|
|
-- }}}
|
|
|
|
|
|
-- {{{ Global functions
|
|
-- {{{ Register a widget
|
|
function vicious.register(widget, wtype, format, timeout, warg)
|
|
local reg = {
|
|
-- Set properties
|
|
wtype = wtype,
|
|
lock = false,
|
|
format = format,
|
|
timeout = timeout or 2,
|
|
warg = warg,
|
|
widget = widget,
|
|
}
|
|
reg.timer = timeout -- For backward compatibility.
|
|
|
|
-- Set functions
|
|
function reg.update()
|
|
update(widget, reg)
|
|
end
|
|
|
|
-- Register a reg object
|
|
regregister(reg)
|
|
|
|
-- Return a reg object for reuse
|
|
return reg
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Unregister a widget
|
|
function vicious.unregister(widget, keep, reg)
|
|
if reg == nil then
|
|
for w, i in pairs(registered) do
|
|
if w == widget then
|
|
for _, v in pairs(i) do
|
|
reg = vicious.unregister(w, keep, v)
|
|
end
|
|
end
|
|
end
|
|
|
|
return reg
|
|
end
|
|
|
|
if not keep then
|
|
for w, i in pairs(registered) do
|
|
if w == widget then
|
|
for k, v in pairs(i) do
|
|
if v == reg then
|
|
table.remove(registered[w], k)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if not reg.running then
|
|
return reg
|
|
end
|
|
|
|
-- Disconnect from timer
|
|
local tm = timers[reg.timeout]
|
|
if tm.timer.disconnect_signal then
|
|
tm.timer:disconnect_signal("timeout", reg.update)
|
|
else
|
|
tm.timer:remove_signal("timeout", reg.update)
|
|
end
|
|
reg.running = false
|
|
-- Stop the timer
|
|
tm.refs = tm.refs - 1
|
|
if tm.refs == 0 and tm.timer.started then
|
|
tm.timer:stop()
|
|
end
|
|
|
|
return reg
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Enable caching of a widget type
|
|
function vicious.cache(wtype)
|
|
if wtype ~= nil then
|
|
if widget_cache[wtype] == nil then
|
|
widget_cache[wtype] = { data = nil, time = 0 }
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Force update of widgets
|
|
function vicious.force(wtable)
|
|
if type(wtable) == "table" then
|
|
for _, w in pairs(wtable) do
|
|
update(w, nil, true)
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Suspend all widgets
|
|
function vicious.suspend()
|
|
for w, i in pairs(registered) do
|
|
for _, v in pairs(i) do
|
|
vicious.unregister(w, true, v)
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Activate a widget
|
|
function vicious.activate(widget)
|
|
for w, i in pairs(registered) do
|
|
if widget == nil or w == widget then
|
|
for _, v in pairs(i) do
|
|
regregister(v)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Get formatted data from a synchronous widget type
|
|
function vicious.call(wtype, format, warg)
|
|
if wtype.async ~= nil then return nil end
|
|
|
|
local data = wtype(format, warg)
|
|
if type(format) == "string" then
|
|
return helpers.format(format, data)
|
|
elseif type(format) == "function" then
|
|
return format(wtype, data)
|
|
end
|
|
end
|
|
-- }}}
|
|
|
|
-- {{{ Get formatted data from an asynchronous widget type
|
|
function vicious.call_async(wtype, format, warg, callback)
|
|
if wtype.async == nil then
|
|
callback()
|
|
return
|
|
end
|
|
|
|
wtype.async(
|
|
format, warg,
|
|
function (data)
|
|
if type(format) == "string" then
|
|
callback(helpers.format(format, data))
|
|
elseif type(format) == "function" then
|
|
callback(format(wtype, data))
|
|
else
|
|
callback()
|
|
end
|
|
end)
|
|
end
|
|
-- }}}
|
|
|
|
return vicious
|
|
-- }}}
|