2022-08-31 12:20:58 +00:00
-- This file is part of Reno desktop.
--
-- Reno desktop 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 3 of the License, or (at your option) any later version.
--
-- Reno desktop 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 Reno desktop. If not, see <https://www.gnu.org/licenses/>.
-- Generic battery widget with support for multiple power sources, backlights and backlight control
2022-08-30 07:00:35 +00:00
local awful = require ( " awful " )
local beautiful = require ( " beautiful " )
local gears = require ( " gears " )
local wibox = require ( " wibox " )
local awmtk2 = require ( " awmtk2 " )
local syscontrol = require ( " syscontrol " )
local function get_virtual_icon ( data )
2022-08-31 12:20:58 +00:00
-- Get an icon from a cumulative total of battery percentages and current charging state
2022-08-30 07:00:35 +00:00
local count = 0
local cumulative = 0
local name = " battery- "
for k , v in pairs ( data ) do
if type ( v ) == " number " then
cumulative = cumulative + v
count = count + 1
end
end
local percentage = math.floor ( ( cumulative / ( count * 100 ) ) * 100 )
if percentage < 15 then
name = name .. " caution- "
elseif percentage < 30 then
name = name .. " low- "
elseif percentage < 60 then
name = name .. " good- "
else
name = name .. " full- "
end
if data [ " charge " ] then
name = name .. " charging- "
end
return beautiful [ name .. " symbolic " ] , percentage
end
return function ( args )
local style = awmtk2.create_style ( " battery " , awmtk2.default , args.style )
local templates = awmtk2.create_template_lib ( " battery " , awmtk2.templates , args.templates )
local t = awmtk2.build_templates ( templates , style )
-- set up popup layout
local layout = wibox.widget ( {
layout = wibox.layout . fixed.vertical ,
spacing = style.base . spacing
} )
-- create popup
local popup = awful.popup ( t.popup ( layout ) )
-- create battery widget
local battery_widget = wibox.widget ( t.button ( {
{
image = beautiful [ " battery-missing-symbolic " ] ,
resize = true ,
widget = wibox.widget . imagebox ,
id = " virtual_id "
} ,
( args.percentage and {
markup = " 0% " ,
id = " percentage_id " ,
widget = wibox.widget . textbox
} ) ,
layout = wibox.layout . fixed.horizontal ,
spacing = style.base . spacing
} ) )
2022-08-31 12:20:58 +00:00
-- make it possible to press the button and make it toggle the popup
2022-08-30 07:00:35 +00:00
battery_widget : connect_signal ( " button::press " , style.button . onpress )
battery_widget : connect_signal ( " button::release " , style.button . onrelease )
battery_widget : connect_signal ( " button::press " , function ( self , x , y , button )
if button == 1 then
popup.visible = ( not popup.visible )
if popup.visible then
popup : move_next_to ( mouse.current_widget_geometry )
end
end
end )
2022-08-31 12:20:58 +00:00
-- map widgets to their names to make it easier to update separate components
2022-08-30 07:00:35 +00:00
local widget_map = { }
2022-08-31 12:20:58 +00:00
-- also map current charge state of every device to get the icon for the tray
2022-08-30 07:00:35 +00:00
local percentage_map = { }
-- {{{ Power supply devices
local power_devices = syscontrol.power_supply . enumerate ( )
for _ , device in pairs ( power_devices ) do
local data = syscontrol.power_supply . read_attribs ( device )
if data.type == " Battery " then
widget_map [ data.name ] = wibox.widget ( t.container ( {
t.article ( {
icon = get_virtual_icon ( {
data.capacity ,
charge = data.charging
} ) ,
icon_id = " battery_icon " ,
title = " Battery ( " .. data.model .. " ) " ,
} ) ,
t.textbox ( {
markup = ( " Capacity: %d%% " ) : format ( data.capacity ) ,
id = " capacity_id "
} ) ,
t.textbox ( {
markup = ( " Quality: %.4f%% " ) : format ( data.quality ) ,
id = " quality_id " ,
} ) ,
layout = wibox.layout . fixed.vertical
} ) )
layout : add ( widget_map [ data.name ] )
percentage_map [ data.name ] = data.capacity
elseif data.type == " Mains " then
widget_map [ data.name ] = wibox.widget ( t.container ( {
t.article ( {
icon = beautiful [ " ac-adapter-symbolic " ] ,
title = " Power supply " ,
} ) ,
t.textbox ( {
markup = " Powered: " .. tostring ( data.online ) ,
id = " online_id " ,
} ) ,
layout = wibox.layout . fixed.vertical
} ) )
layout : add ( widget_map [ data.name ] )
percentage_map [ " charge " ] = data.online
end
end
2022-08-31 12:20:58 +00:00
-- "Virtual" here means a battery that displays the state of a cumulative total of all attached batteries (as if there are any devices that even have more than 1 battery)
2022-08-30 07:00:35 +00:00
local function update_virtual_battery ( )
local icon = battery_widget : get_children_by_id ( " virtual_id " ) [ 1 ]
local percentage = battery_widget : get_children_by_id ( " percentage_id " ) [ 1 ]
local capacity
icon.image , capacity = get_virtual_icon ( percentage_map )
if percentage then
percentage : set_markup ( tostring ( capacity ) .. " % " )
end
end
update_virtual_battery ( )
-- Update loop
2022-08-31 12:57:26 +00:00
local power_update = gears.timer ( {
2022-08-30 07:00:35 +00:00
timeout = args.power_polling or 2 ,
autostart = true ,
callback = function ( )
for k , v in pairs ( power_devices ) do
local data , err = syscontrol.power_supply . read_attribs ( v )
if data and data.type == " Mains " then
local w = widget_map [ data.name ]
local online = w : get_children_by_id ( " online_id " ) [ 1 ]
online : set_markup ( " Powered: " .. tostring ( data.online ) )
percentage_map [ " charge " ] = data.online
elseif data and data.type == " Battery " then
local w = widget_map [ data.name ]
local icon = w : get_children_by_id ( " battery_icon " ) [ 1 ]
local capacity = w : get_children_by_id ( " capacity_id " ) [ 1 ]
local quality = w : get_children_by_id ( " quality_id " ) [ 1 ]
icon.image = get_virtual_icon ( {
data.capacity ,
charge = data.charging
} )
capacity : set_markup ( ( " Capacity: %d%% " ) : format ( data.capacity ) )
quality : set_markup ( ( " Quality: %.4f%% " ) : format ( data.quality ) )
percentage_map [ data.name ] = data.capacity
else
print ( err )
end
update_virtual_battery ( )
end
end
} )
-- }}}
-- {{{ Backlight
local backlight_devices = syscontrol.backlight . enumerate ( )
for k , v in pairs ( backlight_devices ) do
local data = syscontrol.backlight . read_attribs ( v )
if data then
widget_map [ data.name ] = wibox.widget ( t.container ( {
t.article ( {
icon = beautiful [ " backlight-symbolic " ] ,
title = " Backlight " ,
} ) ,
t.textbox ( {
markup = " Brightness: " .. tostring ( data.brightness ) ,
id = " brightness_id "
} ) ,
t.textbox ( {
markup = " Max brightness: " .. tostring ( data.max_brightness ) ,
id = " max_brightness "
} ) ,
( data.writable and t.slider ( {
minimum = data.max_brightness * 0.05 ,
maximum = data.max_brightness ,
value = data.brightness ,
id = " slider "
} ) ) ,
layout = wibox.layout . fixed.vertical
} ) )
if data.writable then
local slider = widget_map [ data.name ] : get_children_by_id ( " slider " ) [ 1 ]
slider : connect_signal ( " widget::redraw_needed " , function ( self )
local value = self.value
syscontrol.backlight . set_brightness ( data , math.floor ( value ) )
end )
end
layout : add ( widget_map [ data.name ] )
end
end
-- Update loop
2022-08-31 12:57:26 +00:00
local backlight_update = gears.timer ( {
2022-08-30 07:00:35 +00:00
timeout = args.backlight_polling or 2 ,
autostart = true ,
callback = function ( )
for k , v in pairs ( backlight_devices ) do
local data , err = syscontrol.backlight . read_attribs ( v )
if data then
local w = widget_map [ data.name ]
local online = w : get_children_by_id ( " brightness_id " ) [ 1 ]
online : set_markup ( " Brightness: " .. tostring ( data.brightness ) )
else
print ( err )
end
end
end
} )
-- }}}
2022-08-31 12:57:26 +00:00
-- We don't need this widget if we don't have anything to show
2022-08-31 12:59:57 +00:00
local function count ( t )
local count = 0
for k , v in pairs ( t ) do
count = count + 1
end
return count
end
if count ( widget_map ) == 0 then
2022-08-31 12:57:26 +00:00
backlight_update : stop ( )
power_update : stop ( )
return
end
2022-08-30 07:00:35 +00:00
return battery_widget
end