big update
This commit is contained in:
parent
736ada7652
commit
7d60e5625f
|
@ -23,6 +23,11 @@ The installation process is not much different from the previous iteration, exce
|
|||
3. Install AwesomeWM (version 4.3 as of right now)
|
||||
4. (Optional) Read additional installation steps in `extra/README.md`
|
||||
|
||||
## Keybindings and user guide
|
||||
- press win+s
|
||||
- read extra/README.md
|
||||
- enjoy
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [x] Port widgets from original config to AWMTK2
|
||||
|
|
11
desktop.conf
11
desktop.conf
|
@ -26,11 +26,20 @@ modkey+b = ":client.below"
|
|||
modkey+f = ":client.fullscreen"
|
||||
modkey+n = ":client.minimize"
|
||||
modkey+m = ":client.maximize"
|
||||
modkey+p = ":client.pin"
|
||||
modkey+y = ":client.toggle_titlebars"
|
||||
|
||||
# Widget keys
|
||||
modkey+r = ":dismal.run"
|
||||
modkey+s = ":help.show"
|
||||
|
||||
Control+XF86AudioRaiseVolume = ":client.volume_up"
|
||||
Control+XF86AudioLowerVolume = ":client.volume_down"
|
||||
Control+XF86AudioMute = ":client.volume_mute"
|
||||
XF86MonBrightnessUp = ":battery.brightness_up"
|
||||
XF86MonBrightnessDown = ":battery.brightness_down"
|
||||
XF86AudioPlay = ":mpc.play"
|
||||
XF86AudioPrev = ":mpc.prev"
|
||||
XF86AudioNext = ":mpc.next"
|
||||
# Custom keys
|
||||
Print = "flameshot gui"
|
||||
Shift+Print = "flameshot launcher"
|
||||
|
|
|
@ -12,6 +12,12 @@ local asckey = {
|
|||
}
|
||||
local awful = require("awful")
|
||||
|
||||
asckey.set_keymap = function(keymap)
|
||||
for k,v in pairs(keymap) do
|
||||
asckey.keymap[v] = k
|
||||
end
|
||||
end
|
||||
|
||||
asckey.get_keycomb = function(name)
|
||||
local modifiers = {}
|
||||
name = name:gsub("[^%s%+]+%+",function(v)
|
||||
|
|
|
@ -162,6 +162,9 @@ awmtk.proto_style.center = awmtk.create_delta("center", {
|
|||
awmtk.proto_style.slider = awmtk.create_delta("slider", {
|
||||
margins = 1
|
||||
}, awmtk.proto_style,awmtk.proto_style.base)
|
||||
|
||||
awmtk.proto_style.checkbox = awmtk.create_delta("checkbox", {
|
||||
}, awmtk.proto_style,awmtk.proto_style.base)
|
||||
-- }}}
|
||||
|
||||
-- {{{ Generic templates
|
||||
|
@ -407,6 +410,19 @@ awmtk.proto_templates = {
|
|||
widget = wibox.widget.slider
|
||||
},args or {})
|
||||
end
|
||||
end,
|
||||
|
||||
checkbox = function(style)
|
||||
return function(args)
|
||||
return awmtk.merge({
|
||||
color = style.checkbox.bg_focus,
|
||||
padding = 2,
|
||||
shape = style.checkbox.shape,
|
||||
border_width = style.checkbox.shape_border_width,
|
||||
bg = style.checkbox.shape_border_color,
|
||||
widget = wibox.widget.checkbox
|
||||
},args or {})
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
local parsers = require("parsers")
|
||||
function rprint(t,ident)
|
||||
ident = ident or 0
|
||||
for k,v in pairs(t) do
|
||||
print((" "):rep(ident)..k,v)
|
||||
if type(v) == "table" then
|
||||
rprint(v,ident+4)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Conf parser
|
||||
local data = [[
|
||||
# Global variables
|
||||
|
@ -45,3 +54,163 @@ for k,v in pairs(parsers.conf(data)) do
|
|||
print(kk,vv)
|
||||
end
|
||||
end
|
||||
|
||||
-- yaml-like (pactl) parser
|
||||
data = [[
|
||||
Sink Input #75
|
||||
Driver: PipeWire
|
||||
Owner Module: n/a
|
||||
Client: 58
|
||||
Sink: 46
|
||||
Sample Specification: float32le 2ch 44100Hz
|
||||
Channel Map: front-left,front-right
|
||||
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
|
||||
Corked: no
|
||||
Mute: no
|
||||
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
|
||||
balance 0.00
|
||||
Buffer Latency: 0 usec
|
||||
Sink Latency: 0 usec
|
||||
Resample method: PipeWire
|
||||
Properties:
|
||||
client.api = "pipewire-pulse"
|
||||
pulse.server.type = "unix"
|
||||
application.name = "LibreWolf"
|
||||
application.process.id = "1756"
|
||||
application.process.user = "yessiest"
|
||||
application.process.host = "architect"
|
||||
application.process.binary = "librewolf"
|
||||
application.language = "C.UTF-8"
|
||||
window.x11.display = ":0"
|
||||
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
|
||||
application.process.session_id = "1"
|
||||
media.name = "AudioStream"
|
||||
node.rate = "1/44100"
|
||||
node.latency = "3307/44100"
|
||||
stream.is-live = "true"
|
||||
node.name = "LibreWolf"
|
||||
node.autoconnect = "true"
|
||||
node.want-driver = "true"
|
||||
media.class = "Stream/Output/Audio"
|
||||
adapt.follower.spa-node = ""
|
||||
object.register = "false"
|
||||
factory.id = "6"
|
||||
clock.quantum-limit = "8192"
|
||||
factory.mode = "split"
|
||||
audio.adapt.follower = ""
|
||||
library.name = "audioconvert/libspa-audioconvert"
|
||||
client.id = "56"
|
||||
object.id = "57"
|
||||
object.serial = "75"
|
||||
pulse.attr.maxlength = "4194304"
|
||||
pulse.attr.tlength = "44104"
|
||||
pulse.attr.prebuf = "35296"
|
||||
pulse.attr.minreq = "8816"
|
||||
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
|
||||
]]
|
||||
rprint(parsers.yaml_pseudo(data))
|
||||
-- Fast incomplete yaml parser
|
||||
data = [[
|
||||
Sink Input #73
|
||||
Driver: PipeWire
|
||||
Owner Module: n/a
|
||||
Client: 58
|
||||
Sink: 46
|
||||
Sample Specification: float32le 2ch 44100Hz
|
||||
Channel Map: front-left,front-right
|
||||
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
|
||||
Corked: no
|
||||
Mute: no
|
||||
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
|
||||
balance 0.00
|
||||
Buffer Latency: 0 usec
|
||||
Sink Latency: 0 usec
|
||||
Resample method: PipeWire
|
||||
Properties:
|
||||
client.api = "pipewire-pulse"
|
||||
pulse.server.type = "unix"
|
||||
application.name = "LibreWolf"
|
||||
application.process.id = "1756"
|
||||
application.process.user = "yessiest"
|
||||
application.process.host = "architect"
|
||||
application.process.binary = "librewolf"
|
||||
application.language = "C.UTF-8"
|
||||
window.x11.display = ":0"
|
||||
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
|
||||
application.process.session_id = "1"
|
||||
media.name = "AudioStream"
|
||||
node.rate = "1/44100"
|
||||
node.latency = "3307/44100"
|
||||
stream.is-live = "true"
|
||||
node.name = "LibreWolf"
|
||||
node.autoconnect = "true"
|
||||
node.want-driver = "true"
|
||||
media.class = "Stream/Output/Audio"
|
||||
adapt.follower.spa-node = ""
|
||||
object.register = "false"
|
||||
factory.id = "6"
|
||||
clock.quantum-limit = "8192"
|
||||
factory.mode = "split"
|
||||
audio.adapt.follower = ""
|
||||
library.name = "audioconvert/libspa-audioconvert"
|
||||
client.id = "56"
|
||||
object.id = "57"
|
||||
object.serial = "75"
|
||||
pulse.attr.maxlength = "4194304"
|
||||
pulse.attr.tlength = "44104"
|
||||
pulse.attr.prebuf = "35296"
|
||||
pulse.attr.minreq = "8816"
|
||||
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
|
||||
|
||||
Sink Input #75
|
||||
Driver: PipeWire
|
||||
Owner Module: n/a
|
||||
Client: 58
|
||||
Sink: 46
|
||||
Sample Specification: float32le 2ch 44100Hz
|
||||
Channel Map: front-left,front-right
|
||||
Format: pcm, format.sample_format = "\"float32le\"" format.rate = "44100" format.channels = "2" format.channel_map = "\"front-left,front-right\""
|
||||
Corked: no
|
||||
Mute: no
|
||||
Volume: front-left: 38326 / 58% / -13.98 dB, front-right: 38326 / 58% / -13.98 dB
|
||||
balance 0.00
|
||||
Buffer Latency: 0 usec
|
||||
Sink Latency: 0 usec
|
||||
Resample method: PipeWire
|
||||
Properties:
|
||||
client.api = "pipewire-pulse"
|
||||
pulse.server.type = "unix"
|
||||
application.name = "LibreWolf"
|
||||
application.process.id = "1756"
|
||||
application.process.user = "yessiest"
|
||||
application.process.host = "architect"
|
||||
application.process.binary = "librewolf"
|
||||
application.language = "C.UTF-8"
|
||||
window.x11.display = ":0"
|
||||
application.process.machine_id = "a8099c2d12fe88c3df940ed562adbe8c"
|
||||
application.process.session_id = "1"
|
||||
media.name = "AudioStream"
|
||||
node.rate = "1/44100"
|
||||
node.latency = "3307/44100"
|
||||
stream.is-live = "true"
|
||||
node.name = "LibreWolf"
|
||||
node.autoconnect = "true"
|
||||
node.want-driver = "true"
|
||||
media.class = "Stream/Output/Audio"
|
||||
adapt.follower.spa-node = ""
|
||||
object.register = "false"
|
||||
factory.id = "6"
|
||||
clock.quantum-limit = "8192"
|
||||
factory.mode = "split"
|
||||
audio.adapt.follower = ""
|
||||
library.name = "audioconvert/libspa-audioconvert"
|
||||
client.id = "56"
|
||||
object.id = "57"
|
||||
object.serial = "75"
|
||||
pulse.attr.maxlength = "4194304"
|
||||
pulse.attr.tlength = "44104"
|
||||
pulse.attr.prebuf = "35296"
|
||||
pulse.attr.minreq = "8816"
|
||||
module-stream-restore.id = "sink-input-by-application-name:LibreWolf"
|
||||
]]
|
||||
rprint(parsers.fast_split_yaml(data))
|
||||
|
|
|
@ -34,7 +34,60 @@ local function split_strings(text)
|
|||
return split
|
||||
end
|
||||
|
||||
parsers.fast_split_yaml = function(cfgtext)
|
||||
-- Fast yaml splitter - incomplete parsing, only first layer is parsed
|
||||
-- Used within timers to find objects while decreasing CPU usage
|
||||
local items = {}
|
||||
local replacements = 1
|
||||
cfgtext = cfgtext:gsub("^%s*","")
|
||||
while replacements > 0 do
|
||||
cfgtext,replacements = cfgtext:gsub("^(.-\n)(%S+)",function(struct,n)
|
||||
table.insert(items,struct)
|
||||
return ""..n
|
||||
end)
|
||||
end
|
||||
table.insert(items,cfgtext)
|
||||
return items
|
||||
end
|
||||
parsers.yaml_pseudo = function(cfgtext)
|
||||
-- Somewhat yaml-like structure used by pactl
|
||||
local struct = {}
|
||||
local lines = {}
|
||||
cfgtext:gsub("(%s*)([^\n]*)",function(spacing,line)
|
||||
table.insert(lines,
|
||||
{
|
||||
spacing:len(),
|
||||
-- key
|
||||
line:match("^([^:=]-)%s*[:=]") or line,
|
||||
-- value
|
||||
line:match(":%s*(.-)%s*$") or
|
||||
line:match("=%s*(.-)%s*$")
|
||||
}
|
||||
)
|
||||
end)
|
||||
local history = {struct}
|
||||
local spacing_width = 0
|
||||
for k,v in pairs(lines) do
|
||||
if v[1] > spacing_width then
|
||||
history[#history][lines[k-1][2]] = {
|
||||
[lines[k-1][2]] = lines[k-1][3]
|
||||
}
|
||||
history[#history+1] = history[#history][lines[k-1][2]]
|
||||
elseif v[1] < spacing_width then
|
||||
history[#history] = nil
|
||||
end
|
||||
if v[3] and v[3]:match("^%s*\".*\"%s*$") then
|
||||
history[#history][v[2]] = v[3]:match("^%s*\"(.*)\"%s*$")
|
||||
else
|
||||
history[#history][v[2]] = v[3]
|
||||
end
|
||||
spacing_width = v[1]
|
||||
end
|
||||
return struct
|
||||
end
|
||||
|
||||
parsers.conf = function(cfgtext)
|
||||
-- Conf style parser (not exactly TOML)
|
||||
cfgtext = cfgtext:gsub("#[^\n]*","")
|
||||
local split_by_strings,err = split_strings(cfgtext)
|
||||
if not split_by_strings then
|
||||
|
|
|
@ -10,7 +10,8 @@
|
|||
local syscontrol = {
|
||||
power_supply = {},
|
||||
backlight = {},
|
||||
hwmon = {}
|
||||
hwmon = {},
|
||||
pulse = {}
|
||||
}
|
||||
syscontrol.backlight.enumerate = function()
|
||||
local lshandler = io.popen("ls -1 /sys/class/backlight","r")
|
||||
|
|
|
@ -11,7 +11,7 @@ local gears = require("gears")
|
|||
local ask = require("asckey")
|
||||
global.modkey = global.modkey or "Mod4"
|
||||
|
||||
ask.keymap = keybindings
|
||||
ask.set_keymap(config.keys)
|
||||
local custom_keys = ask.custom_binds()
|
||||
local k = ask.k
|
||||
|
||||
|
@ -101,7 +101,22 @@ local clientkeys = gears.table.join(
|
|||
c.maximized = not c.maximized
|
||||
c:raise()
|
||||
end ,
|
||||
{description = "(un)maximize", group = "client"}))
|
||||
{description = "(un)maximize", group = "client"}),
|
||||
k(":client.pin",
|
||||
function (c)
|
||||
c.sticky = not c.sticky
|
||||
end ,
|
||||
{description = "(un)pin", group = "client"}),
|
||||
k(":client.toggle_titlebars",
|
||||
function (c)
|
||||
if (not c.titlebar_top.visible) then
|
||||
c:emit_signal("titlebar::unhide")
|
||||
else
|
||||
c:emit_signal("titlebar::hide")
|
||||
end
|
||||
end ,
|
||||
{description = "(un)hide titlebars", group = "client"}))
|
||||
|
||||
awful.rules.rules[1].properties.keys = clientkeys
|
||||
|
||||
local clientbuttons = gears.table.join(
|
||||
|
|
|
@ -156,7 +156,7 @@ client.connect_signal("request::titlebars",function(c)
|
|||
fg_focus = style[v].fg_focus,
|
||||
font = style[v].font
|
||||
})
|
||||
titlebar:setup(t.titlebar(contents))
|
||||
c[v] = titlebar:setup(t.titlebar(contents))
|
||||
awful.rules.rules[1].properties.placement(c)
|
||||
if style[v].onfocus then
|
||||
c:connect_signal("focus",function()
|
||||
|
@ -168,6 +168,12 @@ client.connect_signal("request::titlebars",function(c)
|
|||
style[v].onunfocus(titlebar)
|
||||
end)
|
||||
end
|
||||
c:connect_signal("titlebar::hide",function(c)
|
||||
c[v].visible = false
|
||||
end)
|
||||
c:connect_signal("titlebar::unhide",function(c)
|
||||
c[v].visible = true
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end --}}}
|
||||
|
|
|
@ -12,16 +12,8 @@ local conf_file = io.open(root_path.."/desktop.conf","r")
|
|||
if not conf_file then
|
||||
error("desktop.conf is missing or not readable")
|
||||
end
|
||||
local config = conf(conf_file:read("*a"))
|
||||
config = conf(conf_file:read("*a"))
|
||||
conf_file:close()
|
||||
global = config.global
|
||||
global.terminal = envsub(global.terminal)
|
||||
global.browser = envsub(global.browser)
|
||||
local function invert(t)
|
||||
local new_t = {}
|
||||
for k,v in pairs(t) do
|
||||
new_t[v] = k
|
||||
end
|
||||
return new_t
|
||||
end
|
||||
keybindings = invert(config.keys)
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
-- 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/>.
|
||||
-- Powerman X - second generation of the power management daemon
|
||||
local sysctl = require("syscontrol")
|
||||
local naughty = require("naughty")
|
||||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
local batteries = sysctl.power_supply.enumerate()
|
||||
local state_tracking = {}
|
||||
-- Configuration variables
|
||||
local cfg = config.powerman or {}
|
||||
local quality_min = cfg.battery_quality_min or 33
|
||||
local capacity_min = cfg.battery_capacity_min or 15
|
||||
-- Main loop
|
||||
local update_loop = gears.timer({
|
||||
timeout = 2,
|
||||
autostart = true,
|
||||
callback = function()
|
||||
for k,v in pairs(batteries) do
|
||||
local data,err = sysctl.power_supply.read_attribs(v)
|
||||
state_tracking[v] = state_tracking[v] or {}
|
||||
if data.type == "Battery" then
|
||||
if (tonumber(data.quality) < quality_min) and
|
||||
(not state_tracking[v].quality_notification) then
|
||||
naughty.notify({
|
||||
title = "Critical battery condition",
|
||||
text = "Battery "..data.name.." has reached critically low condition, seek a suitable replacement"
|
||||
})
|
||||
state_tracking[v].quality_notification = true
|
||||
end
|
||||
if (tonumber(data.capacity) <= capacity_min) and
|
||||
(not data.charging) and
|
||||
(not state_tracking[v].capacity_notification) then
|
||||
naughty.notify({
|
||||
title = "Battery capacity low",
|
||||
text = "Battery "..data.name.." capacity is at "..tostring(data.capacity).."%"
|
||||
})
|
||||
state_tracking[v].capacity_notification = true
|
||||
end
|
||||
if (tonumber(data.capacity) > capacity_min) then
|
||||
state_tracking[v].capacity_notification = false
|
||||
end
|
||||
if (data.capacity == "100") and
|
||||
(data.charging) and
|
||||
(not state_tracking[v].charged_notification) then
|
||||
naughty.notify({
|
||||
title = "Battery is completely charged",
|
||||
text = "Disconnect the charger from the power grid to avoid passive electricity usage."
|
||||
})
|
||||
end
|
||||
if (not data.charging) then
|
||||
state_tracking[v].charged_notification = false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
|
1
rc.lua
1
rc.lua
|
@ -16,6 +16,7 @@ package.cpath = package.cpath
|
|||
-- Modules list
|
||||
require("modules.collect_garbage")
|
||||
require("modules.global")
|
||||
require("modules.powermanX")
|
||||
require("modules.errorlog")
|
||||
require("modules.base")
|
||||
require("modules.binds")
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{
|
||||
"list": [
|
||||
{"widget": "widgets.clientvolume"},
|
||||
{"widget": "widgets.clientcontrols"},
|
||||
{"widget": "widgets.clientbuttons"}
|
||||
],
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
-- Reno98 - a retro replica of a very recognizable theme
|
||||
-- Reno Unity - Unity theme for Reno desktop
|
||||
--[[
|
||||
Reno98 - A theme for Reno desktop
|
||||
Reno Unity - A theme for Reno desktop
|
||||
|
||||
Written in 2022 by Yessiest (yessiest@memeware.net)
|
||||
|
||||
|
@ -306,11 +306,20 @@ theme.widgets = {
|
|||
end,
|
||||
height = 20,
|
||||
width = 140,
|
||||
bg_focus = theme.bg_normal,
|
||||
bg_normal = theme.bg_focus,
|
||||
handle_width = 8,
|
||||
handle_border_color = theme.bg_focus,
|
||||
handle_border_color = theme.bg_normal,
|
||||
handle_border_width = 2,
|
||||
bar_height = 6
|
||||
}
|
||||
bar_height = 6,
|
||||
bar_border_color = theme.bg_focus,
|
||||
bar_border_width = 2
|
||||
},
|
||||
checkbox = {
|
||||
shape = gears.shape.circle,
|
||||
shape_border_width = 3,
|
||||
shaoe_border_color = theme.bg_focus
|
||||
},
|
||||
},
|
||||
-- }}}
|
||||
-- {{{ Menus
|
||||
|
|
|
@ -12,6 +12,7 @@ local gears = require("gears")
|
|||
local wibox = require("wibox")
|
||||
local awmtk2 = require("awmtk2")
|
||||
local syscontrol = require("syscontrol")
|
||||
local ask = require("asckey")
|
||||
|
||||
local function get_virtual_icon(data)
|
||||
-- Get an icon from a cumulative total of battery percentages and current charging state
|
||||
|
@ -182,14 +183,25 @@ return function(args)
|
|||
-- }}}
|
||||
-- {{{ Backlight
|
||||
local backlight_devices = syscontrol.backlight.enumerate()
|
||||
local default_backlight_device
|
||||
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",
|
||||
}),
|
||||
(data.writable and t.checkbox({
|
||||
checked = true,
|
||||
id = "checkbox",
|
||||
forced_height = style.article.icon_size,
|
||||
forced_width = style.article.icon_size
|
||||
})),
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
spacing = style.base.spacing
|
||||
},
|
||||
t.textbox({
|
||||
markup = "Brightness: "..tostring(data.brightness),
|
||||
id = "brightness_id"
|
||||
|
@ -201,7 +213,7 @@ return function(args)
|
|||
(data.writable and t.slider({
|
||||
minimum = data.max_brightness*0.05,
|
||||
maximum = data.max_brightness,
|
||||
value = data.brightness,
|
||||
value = tonumber(data.brightness),
|
||||
id = "slider"
|
||||
})),
|
||||
layout = wibox.layout.fixed.vertical
|
||||
|
@ -210,11 +222,22 @@ return function(args)
|
|||
bgimage = style.container.bgimage_highlight
|
||||
}))
|
||||
if data.writable then
|
||||
local slider = widget_map[data.name]:get_children_by_id("slider")[1]
|
||||
local w = widget_map[data.name]
|
||||
local slider = w: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)
|
||||
slider.value = tonumber(data.brightness)
|
||||
local checkbox = w:get_children_by_id("checkbox")[1]
|
||||
checkbox:connect_signal("button::press",function()
|
||||
if default_backlight_device then
|
||||
local check2 = widget_map[default_backlight_device.name]
|
||||
:get_children_by_id("checkbox")[1]
|
||||
check2.checked = false
|
||||
end
|
||||
default_backlight_device = data
|
||||
end)
|
||||
end
|
||||
layout:add(widget_map[data.name])
|
||||
end
|
||||
|
@ -236,6 +259,34 @@ return function(args)
|
|||
end
|
||||
end
|
||||
})
|
||||
-- Keybindings
|
||||
root.keys(gears.table.join(
|
||||
root.keys(),
|
||||
ask.k(":battery.brightness_up",function()
|
||||
if default_backlight_device then
|
||||
local data = default_backlight_device
|
||||
local s = widget_map[data.name]:get_children_by_id("slider")[1]
|
||||
local value = s.value+(data.max_brightness*0.05)
|
||||
if value > data.max_brightness then
|
||||
value = data.max_brightness
|
||||
end
|
||||
syscontrol.backlight.set_brightness(data,math.floor(value))
|
||||
s.value = math.floor(value)
|
||||
end
|
||||
end,{description="increase brightness", group = "widgets"}),
|
||||
ask.k(":battery.brightness_down",function()
|
||||
if default_backlight_device then
|
||||
local data = default_backlight_device
|
||||
local s = widget_map[data.name]:get_children_by_id("slider")[1]
|
||||
local value = s.value-(data.max_brightness*0.05)
|
||||
if value < data.max_brightness*0.05 then
|
||||
value = data.max_brightness*0.05
|
||||
end
|
||||
syscontrol.backlight.set_brightness(data,math.floor(value))
|
||||
s.value = math.floor(value)
|
||||
end
|
||||
end,{description="decrease brightness", group = "widgets"})
|
||||
))
|
||||
-- }}}
|
||||
-- We don't need this widget if we don't have anything to show
|
||||
local function count(t)
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
-- 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/>.
|
||||
-- Pulseaudio per-client volume setting
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local awmtk2 = require("awmtk2")
|
||||
local fastyaml = require("parsers").fast_split_yaml
|
||||
local beautiful = require("beautiful")
|
||||
local ask = require("asckey")
|
||||
local pactl_data = {}
|
||||
|
||||
local test_pactl = os.execute("pactl --version")
|
||||
local result = test_pactl
|
||||
if _VERSION:match("5.1") then
|
||||
result = (test_pactl == 0)
|
||||
end
|
||||
if not result then
|
||||
return
|
||||
end
|
||||
|
||||
local function get_icon(percent)
|
||||
if percent >= 66 then
|
||||
return beautiful["volume-high-symbolic"]
|
||||
elseif percent >= 33 then
|
||||
return beautiful["volume-medium-symbolic"]
|
||||
elseif percent > 0 then
|
||||
return beautiful["volume-low-symbolic"]
|
||||
else
|
||||
return beautiful["volume-muted-symbolic"]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
return function(args)
|
||||
local style = awmtk2.create_style("client_volume",
|
||||
awmtk2.generic.oneline_widget, args.style)
|
||||
local templates = awmtk2.create_template_lib("client_volume",awmtk2.templates,args.templates)
|
||||
local t = awmtk2.build_templates(templates,style)
|
||||
local widget = wibox.widget(t.container({
|
||||
t.center({
|
||||
id = "client_volume_icon",
|
||||
widget = wibox.widget.imagebox
|
||||
}),
|
||||
t.textbox({
|
||||
id = "error"
|
||||
}),
|
||||
t.slider({
|
||||
minimum = 0,
|
||||
maximum = 100,
|
||||
id = "client_volume",
|
||||
value = -1
|
||||
}),
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
}))
|
||||
local errorbox = widget:get_children_by_id("error")[1]
|
||||
local icon = widget:get_children_by_id("client_volume_icon")[1]
|
||||
local slider = widget:get_children_by_id("client_volume")[1]
|
||||
-- Local tracking value to prevent zero volume on start
|
||||
local slider_touched = false
|
||||
-- Get initial pactl data
|
||||
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
||||
local pactl_data = fastyaml(stdout)
|
||||
end)
|
||||
-- Attach to focus change
|
||||
client.connect_signal("update_volume",function(c)
|
||||
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
||||
local pactl_data = fastyaml(stdout)
|
||||
local cl
|
||||
for k,v in pairs(pactl_data) do
|
||||
if not c then return end
|
||||
if v:match("application.process.id = \""..tostring(c.pid).."\"") then
|
||||
cl = v
|
||||
end
|
||||
end
|
||||
if not cl then
|
||||
slider.visible = false
|
||||
errorbox.visible = true
|
||||
errorbox:set_markup("No sound/Not available")
|
||||
icon:set_image(beautiful["volume-muted-symbolic"])
|
||||
return
|
||||
end
|
||||
local volume = tonumber(cl:match("Volume:[^\n]-(%d*)%%"))
|
||||
slider.visible = true
|
||||
errorbox.visible = false
|
||||
icon:set_image(get_icon(volume))
|
||||
slider.value = volume
|
||||
touched = true
|
||||
end)
|
||||
end)
|
||||
client.connect_signal("focus",function(c)
|
||||
touched = false
|
||||
c:emit_signal("update_volume")
|
||||
end)
|
||||
local update_timer = gears.timer({
|
||||
timeout = 0.5,
|
||||
autostart = true,
|
||||
callback = function()
|
||||
if client.focus then
|
||||
client.focus:emit_signal("update_volume")
|
||||
end
|
||||
end
|
||||
})
|
||||
-- Async lock to prevent callback interference
|
||||
local volume_lock = false
|
||||
-- Function to set client volume
|
||||
local function volume(volume)
|
||||
if volume_lock then return end
|
||||
volume_lock = true
|
||||
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
|
||||
local pactl_data = fastyaml(stdout)
|
||||
local cl = {}
|
||||
if not (client.focus and client.focus.pid) then
|
||||
volume_lock = false
|
||||
return
|
||||
end
|
||||
for k,v in pairs(pactl_data) do
|
||||
if v:match("application.process.id = \""..tostring(client.focus.pid).."\"") then
|
||||
local sink_id = v:match("^%s*Sink Input #(%d+)")
|
||||
if sink_id then
|
||||
print(sink_id, volume)
|
||||
awful.spawn("pactl set-sink-input-volume "..tostring(sink_id).." "..tostring(volume).."%")
|
||||
end
|
||||
end
|
||||
end
|
||||
volume_lock = false
|
||||
end)
|
||||
end
|
||||
-- Attach change to slider
|
||||
slider:connect_signal("widget::redraw_needed",function(widget)
|
||||
if touched then
|
||||
volume(slider.value)
|
||||
update_timer:again()
|
||||
end
|
||||
end)
|
||||
root.keys(gears.table.join(
|
||||
root.keys(),
|
||||
ask.k(":client.volume_up", function()
|
||||
volume("+5")
|
||||
end,{description = "increase client volume", group = "client"}),
|
||||
ask.k(":client.volume_down", function()
|
||||
volume("-5")
|
||||
end,{description = "decrease client volume", group = "client"}),
|
||||
ask.k(":client.volume_mute", function()
|
||||
volume(0)
|
||||
end,{description = "mute client", group = "client"})
|
||||
))
|
||||
return widget
|
||||
end
|
|
@ -12,6 +12,7 @@ local wibox = require("wibox")
|
|||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
local beautiful = require("beautiful")
|
||||
local ask = require("asckey")
|
||||
|
||||
return function(args)
|
||||
local style = awmtk2.create_style("soundclown",
|
||||
|
@ -72,15 +73,16 @@ return function(args)
|
|||
local bprev = widget:get_children_by_id("prev")[1]
|
||||
bprev:connect_signal("button::press",style.button.onpress)
|
||||
bprev:connect_signal("button::release",style.button.onrelease)
|
||||
bprev:connect_signal("button::press",function()
|
||||
local function prev()
|
||||
awful.spawn("mpc cdprev")
|
||||
end)
|
||||
end
|
||||
bprev:connect_signal("button::press",prev)
|
||||
local pause_state = true
|
||||
local icon = widget:get_children_by_id("statusicon")[1]
|
||||
local bplay = widget:get_children_by_id("play")[1]
|
||||
bplay:connect_signal("button::press",style.button.onpress)
|
||||
bplay:connect_signal("button::release",style.button.onrelease)
|
||||
bplay:connect_signal("button::press",function()
|
||||
local function play()
|
||||
pause_state = (not pause_state)
|
||||
if pause_state == false then
|
||||
icon.image = beautiful["mpc-pause-symbolic"]
|
||||
|
@ -89,13 +91,16 @@ return function(args)
|
|||
icon.image = beautiful["mpc-play-symbolic"]
|
||||
awful.spawn("mpc play")
|
||||
end
|
||||
end)
|
||||
end
|
||||
bplay:connect_signal("button::press",play)
|
||||
local bnext = widget:get_children_by_id("next")[1]
|
||||
bnext:connect_signal("button::press",style.button.onpress)
|
||||
bnext:connect_signal("button::release",style.button.onrelease)
|
||||
bnext:connect_signal("button::press",function()
|
||||
local function nextb()
|
||||
awful.spawn("mpc next")
|
||||
end)
|
||||
end
|
||||
bnext:connect_signal("button::press",nextb)
|
||||
local update_ready = true
|
||||
local function update_mpd_status()
|
||||
awful.spawn.easy_async("mpc",function(out)
|
||||
local status = ""
|
||||
|
@ -104,6 +109,7 @@ return function(args)
|
|||
state = true
|
||||
icon.image = beautiful["mpc-play-symbolic"]
|
||||
display:set_markup(status)
|
||||
update_ready = true
|
||||
return
|
||||
else
|
||||
status = status.."[PAUSED] "
|
||||
|
@ -113,6 +119,7 @@ return function(args)
|
|||
out:match("[^\n]*").." "..
|
||||
out:match("%d*:%d*/%d*:%d*%s*%(%d*%%%)")
|
||||
display:set_markup(status)
|
||||
update_ready = true
|
||||
end)
|
||||
end
|
||||
update_mpd_status()
|
||||
|
@ -120,8 +127,19 @@ return function(args)
|
|||
timeout = args.polling_delay or 1,
|
||||
autostart = true,
|
||||
callback = function()
|
||||
if not update_ready then return end
|
||||
update_ready = false
|
||||
update_mpd_status()
|
||||
end
|
||||
}
|
||||
root.keys(gears.table.join(
|
||||
root.keys(),
|
||||
ask.k(":mpc.prev",prev,
|
||||
{description = "switch to previous MPD track",group="widgets"}),
|
||||
ask.k(":mpc.play",play,
|
||||
{description = "play/pause MPD",group="widgets"}),
|
||||
ask.k(":mpc.next",nextb,
|
||||
{description = "switch to next MPD track",group="widgets"})
|
||||
))
|
||||
return widget
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue