Added some extra project management utilities

This commit is contained in:
Yessiest 2022-12-11 02:28:22 +04:00
parent 379b838751
commit 0d3131a8f9
24 changed files with 423 additions and 107 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
/links
/libs/pam
/libs/pam.so
/doc

4
.ldoc.lua Normal file
View File

@ -0,0 +1,4 @@
file = {"libs","modules","widgets"}
format = "markdown"
title = "Reno Desktop documentation"
description = "Reno Desktop is an AwesomeWM config that harnesses the power of AwesomeWM to bring the essential functionality of a desktop environment."

31
.luarc.json Normal file
View File

@ -0,0 +1,31 @@
{
"diagnostics": {
"enable": true,
"globals": [
"awesome",
"button",
"dbus",
"client",
"mouse",
"screen",
"root"
]
},
"runtime": {
"version": "Lua 5.3",
"path": [
"/usr/share/awesome/lib/?/?.lua"
],
"pathStrict": true
},
"workspace": {
"library": [
"runtime/lua",
"/usr/share/awesome/lib"
],
"checkThirdParty": false,
"maxPreload": 2000,
"preloadFileSize": 1000
},
"telemetry.enable": true
}

49
Rakefile Normal file
View File

@ -0,0 +1,49 @@
task default: [:install]
ConfigPath = (ENV["XDG_DATA_HOME"] or ENV["HOME"]+'/.config')
desc "Copy files to .config"
file "copy-config" => ["rc.lua"] do
sh "mkdir -p #{ConfigPath}/awesome"
["libs","modules","themes","widgets","rc.lua","desktop.conf"].each { |x|
cp_r "./#{x}" "#{ConfigPath}/awesome"
}
end
desc "Compile and install luapam"
file "build-luapam" => "#{ConfigPath}/libs/pam.so" do
sh "sh ./extra/install_luapam.sh"
end
desc "Install config"
task install: ["copy-config","build-luapam"]
desc "Build documentation"
task :doc do
sh "ldoc ./.ldoc.lua"
end
desc "Install extras"
task "install-extra" do
if Process.euid != 0
raise Exception, "You need to be root to install extras"
end
cp "./extra/udev/backlight.rules" "/etc/udev/rules.d"
mkdir "#{ConfigPath}/autostart"
begin
cp "/usr/share/applications/picom.desktop" "#{ConfigPath}/autostart/"
rescue
puts "picom not installed - ignoring"
else
cp "./extra/picom.conf" "#{ConfigPath}"
end
puts "Done! Reload awesome to complete installation"
end
desc "Uninstall from .config"
task :clean do
rm_rf "#{ConfigPath}/awesome"
end
desc "Wipe configuration and reinstall from scratch"
task reinstall: [:clean,:install]

View File

@ -17,6 +17,7 @@ modkey+Control+Down = ":root.screen_previous"
modkey+Tab = ":root.client_swap"
modkey+Return = ":root.spawn_terminal"
modkey+Shift+Return = ":root.spawn_browser"
modkey+Shift+y = ":root.toggle_titlebars"
# Client keys only work if a focused client exists
modkey+Shift+c = ":client.kill"
@ -40,6 +41,7 @@ XF86MonBrightnessDown = ":battery.brightness_down"
XF86AudioPlay = ":mpc.play"
XF86AudioPrev = ":mpc.prev"
XF86AudioNext = ":mpc.next"
# Custom keys
Print = "flameshot gui"
Shift+Print = "flameshot launcher"

View File

@ -1,6 +1,5 @@
backend = "xrender";
vsync = true;
# Shadow
shadow = true; # Enabled client-side shadows on windows.
shadow-radius = 12; # The blur radius for shadows. (default 12)
@ -31,7 +30,8 @@ shadow-exclude = [
# This list includes all the affected apps I found in my testing. The "! name~=''" part excludes shadows on any "Unknown" windows, this prevents a visual glitch with the XFWM alt tab switcher.
# Fading
fading = true# Fade windows during opacity changes.
fading = true;
# Fade windows during opacity changes.
fade-delta = 4; # The time between steps in a fade in milliseconds. (default 10).
fade-in-step = 0.03; # Opacity change between steps while fading in. (default 0.028).
fade-out-step = 0.03; # Opacity change between steps while fading out. (default 0.03).

View File

@ -19,7 +19,6 @@ local awmtk = {}
awmtk.create_delta = function(name,instance_delta,class_delta,parent_delta)
-- to save memory, we create proxies for lower layers called "deltas"
-- this function creates that proxy layer using metatables
-- fun story - i used instance_delta instead of {} at first.
-- the results were horrifying and confusing.
return setmetatable({},{
@ -86,8 +85,8 @@ end
awmtk.wrap_hooks = function(w,callbacks)
-- attach hooks to function
local mcall = getmetatable(w).__call
return awmtk.mask_object_call(w,function(...)
local mcall = (getmetatable(w) and getmetatable(w).__call) or w
local call_wrapper = function(...)
if callbacks and callbacks.on_create_pre then
callbacks.on_create_pre(...)
end
@ -96,8 +95,12 @@ awmtk.wrap_hooks = function(w,callbacks)
callbacks.on_create(widget,...)
end
if callbacks and callbacks.on_ready then
callbacks._on_ready_called = false
local func = function()
if not callbacks._on_ready_called then
callbacks.on_ready(widget)
callbacks._on_ready_called = true
end
end
widget:connect_signal("widget::layout_changed",func)
widget:connect_signal("widget::layout_changed",function()
@ -105,7 +108,9 @@ awmtk.wrap_hooks = function(w,callbacks)
end)
end
return widget
end)
end
return (getmetatable(w) and awmtk.mask_object_call(w,call_wrapper)) or
call_wrapper
end
awmtk.merge = gears.table.join
@ -245,7 +250,7 @@ awmtk.proto_templates = {
shape = style.button.shape,
shape_border_color = style.button.shape_border_color,
shape_border_width = style.button.shape_border_width,
widget = wibox.container.background
widget = awmtk.wrap_hooks(wibox.container.background,options)
},options or {})
end
end,
@ -255,7 +260,7 @@ awmtk.proto_templates = {
return function(options)
return awmtk.merge({
font = style.textbox.font,
widget = wibox.widget.textbox,
widget = awmtk.wrap_hooks(wibox.widget.textbox,options)
},options or {})
end
end,
@ -264,7 +269,7 @@ awmtk.proto_templates = {
-- wow, i guess?
return function(options)
return awmtk.merge({
widget = wibox.widget.separator,
widget = awmtk.wrap_hooks(wibox.widget.separator,options),
orientation = "horizontal",
thickness = style.separator.thickness,
color = style.separator.color,
@ -277,7 +282,7 @@ awmtk.proto_templates = {
-- i'm running out of comments
return function(options)
return awmtk.merge({
widget = wibox.widget.separator,
widget = awmtk.wrap_hooks(wibox.widget.separator,options),
orientation = "vertical",
thickness = style.separator.thickness,
color = style.separator.color,
@ -332,7 +337,10 @@ awmtk.proto_templates = {
layout = wibox.layout.flex.vertical
},
spacing = style.article.spacing,
layout = wibox.layout.fixed.horizontal,
layout = awmtk.wrap_hooks(
wibox.layout.fixed.horizontal,
options
)
}, options or {})
end
end,
@ -350,7 +358,10 @@ awmtk.proto_templates = {
style.center.width,
widget = wibox.container.constraint
},
widget = wibox.container.place,
widget = awmtk.wrap_hooks(
wibox.container.place,
options
),
valign = "center",
halign = "center"
},options or {})
@ -365,7 +376,7 @@ awmtk.proto_templates = {
widget = {
widget,
margins = style.popup.margins,
layout = wibox.container.margin
layout = awmtk.wrap_hooks(wibox.container.margin,options)
},
bgimage = style.popup.bgimage_normal,
shape = style.popup.shape,
@ -393,7 +404,7 @@ awmtk.proto_templates = {
return awmtk.merge({
layout,
margins = margins,
layout = wibox.container.margin,
layout = awmtk.wrap_hooks(wibox.container.margin,options),
left = style.titlebar.left,
right = style.titlebar.right,
bottom = style.titlebar.bottom,
@ -415,7 +426,7 @@ awmtk.proto_templates = {
return awmtk.merge({
layout,
margins = margins,
layout = wibox.container.margin,
layout = awmtk.wrap_hooks(wibox.container.margin,options),
left = style.wibar.left,
right = style.wibar.right,
bottom = style.wibar.bottom,
@ -442,7 +453,7 @@ awmtk.proto_templates = {
bar_border_color = style.slider.bar_border_color,
forced_width = style.slider.width,
forced_height = style.slider.height,
widget = wibox.widget.slider
widget = awmtk.wrap_hooks(wibox.widget.slider,args)
},args or {})
end
end,
@ -450,13 +461,16 @@ awmtk.proto_templates = {
checkbox = function(style)
return function(args)
return awmtk.merge({
color = style.checkbox.bg_focus,
padding = 2,
color = style.checkbox.color or style.checkbox.bg_normal,
paddings = style.checkbox.paddings,
shape = style.checkbox.shape,
border_width = style.checkbox.shape_border_width,
bg = style.checkbox.shape_border_color,
widget = wibox.widget.checkbox
},args or {})
border_width = style.checkbox.border_width,
border_color = style.checkbox.border_color or style.checkbox.bg_normal,
bg = style.checkbox.bg or style.checkbox.bg_focus,
check_color = style.checkbox.check_color or style.checkbox.bg_normal,
check_shape = style.checkbox.check_shape,
widget = awmtk.wrap_hooks(wibox.widget.checkbox,args)
},args)
end
end
}

View File

@ -14,6 +14,7 @@ global.modkey = global.modkey or "Mod4"
ask.set_keymap(config.keys)
local custom_keys = ask.custom_binds()
local k = ask.k
local titlebar_states = {}
local keys = gears.table.join(
k(':root.client_next',
@ -54,6 +55,11 @@ local keys = gears.table.join(
awful.spawn(global.browser)
end,
{description = "open browser", group = "launcher"}),
k(":root.toggle_titlebars",
function (c)
awesome.emit_signal("titlebar::toggle")
end ,
{description = "(un)hide all titlebars", group = "client"}),
table.unpack(custom_keys))
root.keys(keys)
@ -109,14 +115,9 @@ local clientkeys = gears.table.join(
{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
c:emit_signal("titlebar::toggle")
end ,
{description = "(un)hide titlebars", group = "client"}))
awful.rules.rules[1].properties.keys = clientkeys
local clientbuttons = gears.table.join(

View File

@ -116,15 +116,47 @@ table.insert(awful.rules.rules,
}
)
client.connect_signal("manage", function(c)
local shape = beautiful.window_shape or function(cr, width, height)
local window_shape_hide = function(cr, width, height)
return gears.shape.partially_rounded_rect(cr,width,height,
false,false,false,false,0)
end
local window_shape = beautiful.window_shape or function(cr, width, height)
return gears.shape.partially_rounded_rect(cr,width,height,
true,true,false,false,beautiful.window_rounding)
end
c.shape = shape
end
client.connect_signal("manage", function(c)
c.shape = window_shape
end)
client.connect_signal("request::titlebars",function(c)
local titlebars_on = true
awesome.connect_signal("titlebar::toggle",function()
titlebars_on = not titlebars_on
for _,c in ipairs(client.get()) do
if titlebars_on then
for _, pos in ipairs({"top","bottom","left","right"}) do
awful.titlebar.show(c,pos)
end
c.shape = window_shape
c:emit_signal("titlebar::perform_action",function(titlebar)
titlebar.widget.visible = true
end)
else
for _, pos in ipairs({"top","bottom","left","right"}) do
awful.titlebar.hide(c,pos)
end
c.shape = window_shape_hide
c:emit_signal("titlebar::perform_action",function(titlebar)
titlebar.widget.visible = false
end)
end
end
end)
-- Second manage call to create hidden titlebars
client.connect_signal("manage",function(c)
-- Drag and resize buttons
local buttons = gears.table.join(
awful.button({}, 1, function()
c:emit_signal("request::activate","titlebar",{raise=true})
@ -135,8 +167,10 @@ client.connect_signal("request::titlebars",function(c)
awful.mouse.client.resize(c)
end)
)
-- Building the titlebars
for k,v in pairs({"titlebar_top","titlebar_bottom","titlebar_left","titlebar_right"}) do
local contents = { widget = wibox.container.background }
-- Build content of the titlebar
local contents = { widget = wibox.widget.textbox, text = "" }
if titlebar_config[v] then
contents = builder(titlebar_config[v],{
client = c,
@ -145,6 +179,7 @@ client.connect_signal("request::titlebars",function(c)
buttons = buttons
})
end
-- Create the base
local titlebar = awful.titlebar(c,{
size = style[v].size or 0,
position = v:gsub("titlebar_",""),
@ -156,8 +191,14 @@ client.connect_signal("request::titlebars",function(c)
fg_focus = style[v].fg_focus,
font = style[v].font
})
c[v] = titlebar:setup(t.titlebar(contents))
-- Compile and build titlebar
titlebar:setup(t.titlebar({
contents,
widget = wibox.container.background
}))
-- Since new clients will be placed without titlebars, we need to apply placement rules again
awful.rules.rules[1].properties.placement(c)
-- Callbacks for focus/unfocus of titlebars
if style[v].onfocus then
c:connect_signal("focus",function()
style[v].onfocus(titlebar)
@ -168,12 +209,32 @@ client.connect_signal("request::titlebars",function(c)
style[v].onunfocus(titlebar)
end)
end
c:connect_signal("titlebar::hide",function(c)
c[v].visible = false
-- Activate focus callback if our client is focused
if (c == client.focus) and (style[v].onfocus) then
style[v].onfocus(titlebar)
end
-- Add a titlebar toggle signal
c:connect_signal("titlebar::toggle",function(c)
titlebar.widget.visible = not titlebar.widget.visible
if titlebar.widget.visible then
awful.titlebar.show(c,v:gsub("titlebar_",""))
c.shape = window_shape
else
awful.titlebar.hide(c,v:gsub("titlebar_",""))
c.shape = window_shape_hide
end
end)
c:connect_signal("titlebar::unhide",function(c)
c[v].visible = true
c:connect_signal("titlebar::perform_action",function(c,f)
f(titlebar)
end)
-- Add rules for hiding titlebars on creation
if (not titlebars_on) or
(c.titlebars_enabled == false) or
(c.requests_no_titlebar == true) then
titlebar.widget.visible = false
c.shape = window_shape_hide
awful.titlebar.hide(c,v:gsub("titlebar_",""))
end
end
end)
end --}}}

View File

@ -374,6 +374,7 @@ theme.widgets = {
end,
},
titlebar = {
hidden_size = 2,
bgimage_normal = theme.bgimage_outset,
--margins = 5,
left = 4,

View File

@ -1,2 +1,3 @@
A compositor (like compton) is ***required*** for this theme to work as intended.
This is in part due to the fact that it makes the top bar look less bland, and in part due to the fact that your titlebar corners will look weird otherwise.
This is in part due to the fact that it makes the top bar look less bland, and in part due to the fact that your titlebar corners will look weird otherwise (the corners won't be properly cut).
You may, of course, dismiss using a compositor, but don't tell me about not exactly round corners being a "bug" in this theme afterwards - it's the best you can get with Awesome.

View File

@ -0,0 +1,32 @@
{
"list": [
{
"list": [
{"widget": "widgets.base.popuptitle",
"options":{
"title":"Reno Unity"
}
},
{"widget": "widgets.rootcontrols"},
{"widget": "widgets.xdgmenu",
"options": {
"exclude_category": [
"Other"
]
}
}
],
"vertical": true
},
{
"list":[
{"widget": "widgets.base.tagswitcher",
"screen":true
},
{"widget": "widgets.rootbuttons"}
],
"vertical":true
}
],
"vertical":false
}

View File

@ -7,6 +7,7 @@
],
"right": [
{ "widget":"widgets.volume" },
{ "widget": "widgets.notifications",
"screen": true
},

BIN
themes/unity/icons/reno.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 819 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -12,8 +12,6 @@ local theme_assets = require("beautiful.theme_assets")
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi
local gears = require("gears")
local gfs = require("gears.filesystem")
local themes_path = root_path.."/themes/"
local theme = {}
@ -214,6 +212,12 @@ theme["mpc-next-symbolic"] = themes_path.."unity/icons/mpc-next-symbolic.png"
theme["action-poweroff-symbolic"] = themes_path.."unity/icons/action-poweroff-symbolic.png"
theme["action-lock-screen-symbolic"] = themes_path.."unity/icons/action-lock-screen-symbolic.png"
theme["action-suspend-symbolic"] = themes_path.."unity/icons/action-suspend-symbolic.png"
theme["volume-high-symbolic"] = themes_path.."unity/icons/volume-high-symbolic.png"
theme["volume-medium-symbolic"] = themes_path.."unity/icons/volume-medium-symbolic.png"
theme["volume-low-symbolic"] = themes_path.."unity/icons/volume-low-symbolic.png"
theme["volume-muted-symbolic"] = themes_path.."unity/icons/volume-muted-symbolic.png"
theme.wallpaper = themes_path.."unity/background.png"
theme.wallpapers_icon = themes_path.."unity/icons/wallpapers.png"
-- Default icon for clients
@ -244,7 +248,11 @@ for k,v in pairs({
"action-lock-screen-symbolic",
"action-suspend-symbolic",
"wallpapers_icon",
"icon_default"}) do
"icon_default",
"volume-high-symbolic",
"volume-medium-symbolic",
"volume-low-symbolic",
"volume-muted-symbolic"}) do
if theme[v] and gears.filesystem.file_readable(theme[v]) then
theme[v] = gears.color.recolor_image(theme[v],theme.fg_normal)
end
@ -281,6 +289,7 @@ theme.widgets = {
end,
},
titlebar = {
hidden_size = 2,
root_shape = function(cr,width,height)
return gears.shape.partially_rounded_rect(cr,width,height,
true,true,false,false,6) end,
@ -316,9 +325,12 @@ theme.widgets = {
bar_border_width = 2
},
checkbox = {
width = 15,
height = 15,
shape = gears.shape.circle,
shape_border_width = 3,
shaoe_border_color = theme.bg_focus
border_width = 3,
border_color = theme.bg_normal,
paddings = {2,2,2,2}
},
},
-- }}}
@ -541,15 +553,16 @@ theme.widgets = {
local root = titlebar:get_children_by_id("titlebar_root")[1]
root:set_bg(theme.titlebar_bg_focus)
root:set_shape(function(cr,width,height)
return gears.shape.partially_rounded_rect(cr,width,height,
return gears.shape.partially_rounded_rect(
cr,width,height,
true,true,false,false,6) end)
end,
onunfocus = function(titlebar)
local root = titlebar:get_children_by_id("titlebar_root")[1]
root:set_bg(theme.titlebar_bg_normal)
root:set_shape(function(cr,width,height)
return gears.shape.partially_rounded_rect(cr,width,height,
return gears.shape.partially_rounded_rect(
cr,width,height,
true,true,false,false,6) end)
end,
bg_focus = "#00000000",

View File

@ -19,7 +19,7 @@ local function get_virtual_icon(data)
local count = 0
local cumulative = 0
local name = "battery-"
for k,v in pairs(data) do
for _,v in pairs(data) do
if type(v) == "number" then
cumulative = cumulative + v
count = count + 1
@ -77,7 +77,7 @@ return function(args)
-- make it possible to press the button and make it toggle the popup
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)
battery_widget:connect_signal("button::press",function(_,_,_,button)
if button == 1 then
popup.visible = (not popup.visible)
if popup.visible then
@ -154,7 +154,7 @@ return function(args)
timeout = args.power_polling or 2,
autostart = true,
callback = function()
for k,v in pairs(power_devices) do
for _,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]
@ -184,7 +184,7 @@ return function(args)
-- {{{ Backlight
local backlight_devices = syscontrol.backlight.enumerate()
local default_backlight_device
for k,v in pairs(backlight_devices) do
for _,v in pairs(backlight_devices) do
local data = syscontrol.backlight.read_attribs(v)
if data then
widget_map[data.name] = wibox.widget(t.container({
@ -193,12 +193,18 @@ return function(args)
icon = beautiful["backlight-symbolic"],
title = "Backlight",
}),
(data.writable and t.checkbox({
checked = true,
(data.writable and t.center(
t.checkbox({
checked = false,
id = "checkbox",
forced_height = style.article.icon_size,
forced_width = style.article.icon_size
})),
}),
{
width = style.checkbox.width,
height = style.checkbox.height
})
),
layout = wibox.layout.fixed.horizontal,
spacing = style.base.spacing
},
@ -234,7 +240,7 @@ return function(args)
if default_backlight_device then
local check2 = widget_map[default_backlight_device.name]
:get_children_by_id("checkbox")[1]
check2.checked = false
check2.checked = true
end
default_backlight_device = data
end)
@ -247,7 +253,7 @@ return function(args)
timeout = args.backlight_polling or 2,
autostart = true,
callback = function()
for k,v in pairs(backlight_devices) do
for _,v in pairs(backlight_devices) do
local data,err = syscontrol.backlight.read_attribs(v)
if data then
local w = widget_map[data.name]

View File

@ -8,8 +8,6 @@
-- Additional client controls, hidden for cleaner UI in the submenu.
local awmtk2 = require("awmtk2")
local wibox = require("wibox")
local gears = require("gears")
local awful = require("awful")
local beautiful = require("beautiful")
return function(args)

View File

@ -13,7 +13,6 @@ 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
@ -45,6 +44,7 @@ return function(args)
local widget = wibox.widget(t.container({
t.center({
id = "client_volume_icon",
resize = true,
widget = wibox.widget.imagebox
}),
t.textbox({
@ -62,11 +62,7 @@ return function(args)
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)
local touched = false
-- Attach to focus change
client.connect_signal("update_volume",function(c)
awful.spawn.easy_async("pactl list sink-inputs",function(stdout)
@ -109,22 +105,21 @@ return function(args)
-- Async lock to prevent callback interference
local volume_lock = false
-- Function to set client volume
local function volume(volume)
local function volume(value)
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
for _,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).."%")
print(sink_id, value)
awful.spawn("pactl set-sink-input-volume "..tostring(sink_id).." "..tostring(value).."%")
end
end
end
@ -132,7 +127,7 @@ return function(args)
end)
end
-- Attach change to slider
slider:connect_signal("widget::redraw_needed",function(widget)
slider:connect_signal("widget::redraw_needed",function()
if touched then
volume(slider.value)
update_timer:again()

106
widgets/volume.lua Normal file
View File

@ -0,0 +1,106 @@
-- 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 pactl_found = test_pactl
if _VERSION:match("5.1") then
pactl_found = (test_pactl == 0)
end
local test_amixer = os.execute("amixer --version")
local amixer_found = test_amixer
if _VERSION:match("5.1") then
amixer_found = (test_amixer == 0)
end
if (not (amixer_found or pactl_found)) then
return
end
local try_launch = [[which pavucontrol && pavucontrol || which pulsemixer && ]]..global.terminal..[[ -e pulsemixer || which alsamixer && ]]..global.terminal..[[ -e alsamixer ]]
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("volume",
awmtk2.generic.oneline_widget, args.style)
local templates = awmtk2.create_template_lib("volume",awmtk2.templates,args.templates)
local t = awmtk2.build_templates(templates,style)
local widget = wibox.widget({
t.button({
image = get_icon(0),
id = "volume_icon",
resize = true,
widget = wibox.widget.imagebox
}),
t.container({
t.slider({
minimum = 0,
maximum = 100,
id = "volume",
value = -1
}),
layout = wibox.layout.fixed.horizontal
},{
visible = false,
id = "slidercontainer"
}),
layout = wibox.layout.fixed.horizontal
})
local icon = widget:get_children_by_id("volume_icon")[1]
local slider = widget:get_children_by_id("volume")[1]
local container = widget:get_children_by_id("slidercontainer")[1]
-- Alsa master handle
args.device = args.device or "default"
gears.timer {
autostart = true,
timeout = 0.5,
call_now = true,
callback = function()
awful.spawn.easy_async_with_shell("amixer -D "..args.device.." sget Master",function(stdout)
local volume_percent = stdout:match("%[(%d+)%%%]")
volume_percent = tonumber(volume_percent)
if not volume_percent then
return
end
slider.value = volume_percent
icon.image = get_icon(volume_percent)
end)
end
}
slider:connect_signal("widget::redraw_needed",function()
awful.spawn("amixer -D "..args.device.." sset Master "..slider.value.."%")
icon.image = get_icon(slider.value)
end)
icon:connect_signal("button::press",function(self,lx,ly,button)
if button == 1 then
container.visible = not container.visible
end
if button == 2 then
awful.spawn.with_shell(args.mixer or try_launch)
end
end)
return widget
end