summaryrefslogtreecommitdiff
path: root/brightness-widget/brightness.lua
blob: 3a77a44433db943543f42301ccd1ce2650e0360a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
-------------------------------------------------
-- Brightness Widget for Awesome Window Manager
-- Shows the brightness level of the laptop display
-- More details could be found here:
-- https://github.com/streetturtle/awesome-wm-widgets/tree/master/brightness-widget

-- @author Pavel Makhov
-- @copyright 2021 Pavel Makhov
-------------------------------------------------

local awful = require("awful")
local wibox = require("wibox")
local watch = require("awful.widget.watch")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local beautiful = require("beautiful")

local ICON_DIR = os.getenv("HOME") .. '/.config/awesome/awesome-wm-widgets/brightness-widget/'
local get_brightness_cmd
local set_brightness_cmd
local inc_brightness_cmd
local dec_brightness_cmd

local brightness_widget = {}

local function show_warning(message)
    naughty.notify{
        preset = naughty.config.presets.critical,
        title = 'Brightness Widget',
        text = message}
end

local function worker(user_args)

    local args = user_args or {}

    local type = args.type or 'arc' -- arc or icon_and_text
    local path_to_icon = args.path_to_icon or ICON_DIR .. 'brightness.svg'
    local font = args.font or beautiful.font
    local timeout = args.timeout or 100

    local program = args.program or 'light'
    local step = args.step or 5
    local base = args.base or 20
    local current_level = 0 -- current brightness value
    local tooltip = args.tooltip or false
    local percentage = args.percentage or false
    if program == 'light' then
        get_brightness_cmd = 'light -G'
        set_brightness_cmd = 'light -S %d' -- <level>
        inc_brightness_cmd = 'light -A ' .. step
        dec_brightness_cmd = 'light -U ' .. step
    elseif program == 'xbacklight' then
        get_brightness_cmd = 'xbacklight -get'
        set_brightness_cmd = 'xbacklight -set %d' -- <level>
        inc_brightness_cmd = 'xbacklight -inc ' .. step
        dec_brightness_cmd = 'xbacklight -dec ' .. step
    elseif program == 'brightnessctl' then
        get_brightness_cmd = 'bash -c "brightnessctl -m | cut -d, -f4 | tr -d %"'
        set_brightness_cmd = 'brightnessctl set %d%%' -- <level>
        inc_brightness_cmd = 'brightnessctl set +' .. step .. '%'
        dec_brightness_cmd = 'brightnessctl set ' .. step .. '-%'
    else
        show_warning(program .. " command is not supported by the widget")
        return
    end

    if type == 'icon_and_text' then
        brightness_widget.widget = wibox.widget {
            {
                {
                    image = path_to_icon,
                    resize = false,
                    widget = wibox.widget.imagebox,
                },
                valign = 'center',
                layout = wibox.container.place
            },
            {
                id = 'txt',
                font = font,
                widget = wibox.widget.textbox
            },
            spacing = 4,
            layout = wibox.layout.fixed.horizontal,
            set_value = function(self, level)
                local display_level = level
                if percentage then
                    display_level = display_level .. '%'
                end
                self:get_children_by_id('txt')[1]:set_text(display_level)
            end
        }
    elseif type == 'arc' then
        brightness_widget.widget = wibox.widget {
            {
                {
                    image = path_to_icon,
                    resize = true,
                    widget = wibox.widget.imagebox,
                },
                valign = 'center',
                layout = wibox.container.place
            },
            max_value = 100,
            thickness = 2,
            start_angle = 4.71238898, -- 2pi*3/4
            forced_height = 18,
            forced_width = 18,
            paddings = 2,
            widget = wibox.container.arcchart,
            set_value = function(self, level)
                self:set_value(level)
            end
        }
    else
        show_warning(type .. " type is not supported by the widget")
        return

    end

    local update_widget = function(widget, stdout, _, _, _)
        local brightness_level = tonumber(string.format("%.0f", stdout))
        current_level = brightness_level
        widget:set_value(brightness_level)
    end

    function brightness_widget:set(value)
        current_level = value
        spawn.easy_async(string.format(set_brightness_cmd, value), function()
            spawn.easy_async(get_brightness_cmd, function(out)
                update_widget(brightness_widget.widget, out)
            end)
        end)
    end
    local old_level = 0
    function brightness_widget:toggle()
        if old_level < 0.1 then
            -- avoid toggling between '0' and 'almost 0'
            old_level = 1
        end
        if current_level < 0.1 then
            -- restore previous level
            current_level = old_level
        else
            -- save current brightness for later
            old_level = current_level
            current_level = 0
        end
        brightness_widget:set(current_level)
    end
    function brightness_widget:inc()
        spawn.easy_async(inc_brightness_cmd, function()
            spawn.easy_async(get_brightness_cmd, function(out)
                update_widget(brightness_widget.widget, out)
            end)
        end)
    end
    function brightness_widget:dec()
        spawn.easy_async(dec_brightness_cmd, function()
            spawn.easy_async(get_brightness_cmd, function(out)
                update_widget(brightness_widget.widget, out)
            end)
        end)
    end

    brightness_widget.widget:buttons(
            awful.util.table.join(
                    awful.button({}, 1, function() brightness_widget:set(base) end),
                    awful.button({}, 3, function() brightness_widget:toggle() end),
                    awful.button({}, 4, function() brightness_widget:inc() end),
                    awful.button({}, 5, function() brightness_widget:dec() end)
            )
    )

    watch(get_brightness_cmd, timeout, update_widget, brightness_widget.widget)

    if tooltip then
        awful.tooltip {
            objects        = { brightness_widget.widget },
            timer_function = function()
                return current_level .. " %"
            end,
        }
    end

    return brightness_widget.widget
end

return setmetatable(brightness_widget, { __call = function(_, ...)
    return worker(...)
end })