Compare commits

...

11 Commits
1.1 ... master

27 changed files with 777 additions and 341 deletions

View File

@ -1,6 +1,6 @@
# Reno desktop - awesomewm || ( openbox && xfce ) # Reno desktop - awesomewm || ( openbox && xfce )
Reno is an evolution of my previous configuration, https://512mb.org/git/Yessiest/awesome. This time, this bad boy can fit 90% more configuration options, through the use of AWMTK2 (or RenoTK, never really decided on the name). Reno is an evolution of my previous configuration, https://512mb.org/git/Yessiest/awesome. This time, this bad boy can fit 90% more configuration options, through the use of AWMTK2 (or RenoTK, haven't really decided on the name).
Through advancements in the ~~science~~ dark magic art of lua metatablery, AWMTK2 makes it possible to create complex and visually rich themes, while mainting relatively low memory footprint. Through advancements in the ~~science~~ dark magic art of lua metatablery, AWMTK2 makes it possible to create complex and visually rich themes, while mainting relatively low memory footprint.
@ -11,23 +11,36 @@ Thanks to the ethically questionable decision of employing JSON to Widget Layout
#### Current default theme, Reno98 #### Current default theme, Reno98
![Totally not windows 98 trust me it's legally distinct](https://adastra7.net/git/Yessiest/reno/raw/branch/master/extra/screenshots/reno98.png) ![Totally not windows 98 trust me it's legally distinct](https://adastra7.net/git/Yessiest/reno/raw/branch/master/extra/screenshots/reno98.png)
#### An iteration on the look of Ubuntu with Ambiance theme - Works best with [Chicago95](https://github.com/grassmunk/Chicago95) for GTK and [QTStep (QTStepWMakerDefault in particular)](https://github.com/andbgr/QTStep) on [Kvantum](https://github.com/tsujan/Kvantum).
![Totally not ubuntu guys this how can't you see that](https://adastra7.net/git/Yessiest/reno/raw/branch/master/extra/screenshots/unity.png) - For Wine apps, use `winecfg`, go to Desktop Integration and set "(No Theme)" under "Theme". A matching QTStep theme is "QTStepBeige", but it doesn't quite match Chicago95, so you may want to configure the window colors using the Item editor, or by installing a custom theme.
#### Unity: a theme that mimics the look of Ubuntu with Ambiance theme
![Totally not ubuntu guys how can't you see that](https://adastra7.net/git/Yessiest/reno/raw/branch/master/extra/screenshots/unity.png)
- Works best with official [Ubuntu Themes](https://launchpad.net/ubuntu-themes) ([AUR package](https://aur.archlinux.org/packages/ubuntu-themes)) for GTK and [Kvantum's](https://github.com/tsujan/Kvantum) default themes KvAmbiance or KvAmbience.
- For Wine apps, [Ubuntu Light for Windows XP](http://freddi67.deviantart.com/art/Ubuntu-Light-for-Windows-XP-177514325) theme exists on DeviantArt, which you can install using `winecfg`.
## Installation ## Installation
The installation process is not much different from the previous iteration, except this time the window manager does not crash if you don't install luapam. Instead, the lock widget will simply refuse to operate. Reno internally requires [ImageMagick](https://imagemagick.org/) to generate thumbnails for images. Please consider installing ImageMagick for things to function correctly.
1. `git clone` the repository to your .config folder 1. `git clone` the repository to your .config folder
2. Rename `reno` folder to `awesome` 2. Rename `reno` folder to `awesome`
3. Install AwesomeWM (version 4.3 as of right now) 3. Install AwesomeWM (version 4.3 as of right now)
4. (Optional) Read additional installation steps in `extra/README.md` 4. Change your shell, terminal emulator, browser, keybindings and other settings in `desktop.conf`
5. (Optional) Read additional installation steps in `extra/README.md`
6. Reload your awesomewm if you have already loaded it.
## Keybindings and user guide ## Keybindings and user guide
- press win+s - press win+s
- read extra/README.md - read extra/README.md
- enjoy - enjoy
## Feedback
Your feedback would be highly appreciated. However, please understand that I may not be able to answer all of your issues in a timely manner.
## Roadmap ## Roadmap
- [x] Port widgets from original config to AWMTK2 - [x] Port widgets from original config to AWMTK2

View File

@ -1,87 +1,90 @@
# Global variables # Global variables
[global] [global]
terminal = "st" # Your preferred terminal emulator
browser = "librewolf" terminal = "xterm"
# Your preferred browser (opens the first one available by default)
browser = "xdg-open about:blank"
# Your modkey (Mod4 = Super key (Win key))
modkey = "Mod4" modkey = "Mod4"
# Your theme (one of the themes available in ./themes/)
theme = "unity" theme = "unity"
shell = "zsh" # Your shell (currently doesn't do much, preferrably should remain the same)
shell = "bash"
# Keybindings # Keybindings
# Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>" # Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>"
# "modkey" as modifier will be substituted for modkey variable in [global] # "modkey" as modifier will be substituted for modkey variable in [global]
[keys] [keys]
modkey+Left = ":root.tag_next" "modkey+Left" = ":root.tag_next"
modkey+Right = ":root.tag_prev" "modkey+Right" = ":root.tag_prev"
modkey+j = ":root.client_next" "modkey+j" = ":root.client_next"
modkey+k = ":root.client_previous" "modkey+k" = ":root.client_previous"
modkey+Control+j = ":root.screen_next" "modkey+Control+j" = ":root.screen_next"
modkey+Control+k = ":root.screen_previous" "modkey+Control+k" = ":root.screen_previous"
modkey+Tab = ":root.client_swap" "modkey+Tab" = ":root.client_swap"
modkey+Return = ":root.spawn_terminal" "modkey+Return" = ":root.spawn_terminal"
modkey+Shift+Return = ":root.spawn_browser" "modkey+Shift+Return" = ":root.spawn_browser"
modkey+Shift+y = ":root.toggle_titlebars" "modkey+Shift+y" = ":root.toggle_titlebars"
# Client keys only work if a focused client exists # Client keys only work if a focused client exists
modkey+Control+o = ":client.move_to_screen" "modkey+Control+o" = ":client.move_to_screen"
modkey+Shift+c = ":client.kill" "modkey+Shift+c" = ":client.kill"
modkey+t = ":client.cycle_screen" "modkey+t" = ":client.cycle_screen"
modkey+o = ":client.ontop" "modkey+o" = ":client.ontop"
modkey+b = ":client.below" "modkey+b" = ":client.below"
modkey+f = ":client.fullscreen" "modkey+f" = ":client.fullscreen"
modkey+n = ":client.minimize" "modkey+n" = ":client.minimize"
modkey+m = ":client.maximize" "modkey+m" = ":client.maximize"
modkey+p = ":client.pin" "modkey+p" = ":client.pin"
modkey+y = ":client.toggle_titlebars" "modkey+y" = ":client.toggle_titlebars"
# Widget keys # Widget keys
modkey+r = ":dismal.run" "modkey+r" = ":dismal.run"
modkey+s = ":help.show" "modkey+s" = ":help.show"
modkey+q = ":client.menu" "modkey+q" = ":client.menu"
modkey+x = ":supermenu.open" "modkey+x" = ":supermenu.open"
Control+XF86AudioRaiseVolume = ":client.volume_up" "Control+XF86AudioRaiseVolume" = ":client.volume_up"
Control+XF86AudioLowerVolume = ":client.volume_down" "Control+XF86AudioLowerVolume" = ":client.volume_down"
Control+XF86AudioMute = ":client.volume_mute" "Control+XF86AudioMute" = ":client.volume_mute"
XF86AudioRaiseVolume = ":root.volume_up" "XF86AudioRaiseVolume" = ":root.volume_up"
XF86AudioLowerVolume = ":root.volume_down" "XF86AudioLowerVolume" = ":root.volume_down"
XF86AudioMute = ":root.volume_mute" "XF86AudioMute" = ":root.volume_mute"
XF86MonBrightnessUp = ":battery.brightness_up" "XF86MonBrightnessUp" = ":battery.brightness_up"
XF86MonBrightnessDown = ":battery.brightness_down" "XF86MonBrightnessDown" = ":battery.brightness_down"
XF86AudioPlay = ":mpc.play" "XF86AudioPlay" = ":mpc.play"
XF86AudioPrev = ":mpc.prev" "XF86AudioPrev" = ":mpc.prev"
XF86AudioNext = ":mpc.next" "XF86AudioNext" = ":mpc.next"
# Custom keys # Custom keys
Print = "flameshot gui" "Print" = "flameshot gui"
Shift+Print = "flameshot launcher" "Shift+Print" = "flameshot launcher"
# Macro recording/playback keys # Macro recording/playback keys
KP_Home = ":macro.play_1" KP_Divide = ":macro.play_1"
KP_Up = ":macro.play_2" KP_Multiply = ":macro.play_2"
KP_PageUp = ":macro.play_3" KP_Add = ":macro.record_1"
KP_Left = ":macro.record_1" KP_Subtract = ":macro.record_2"
KP_Begin = ":macro.record_2"
KP_Right = ":macro.record_3"
KP_Delete = ":macro.loop" KP_Delete = ":macro.loop"
# Tiling # Tiling
modkey+Shift+j = ":layout.swap_next_client" "modkey+Shift+j" = ":layout.swap_next_client"
modkey+Shift+k = ":layout.swap_prev_client" "modkey+Shift+k" = ":layout.swap_prev_client"
modkey+Control+Return = ":client.swap_to_master" "modkey+Control+Return" = ":client.swap_to_master"
modkey+l = ":layout.increase_master" "modkey+l" = ":layout.increase_master"
modkey+h = ":layout.decrease_master" "modkey+h" = ":layout.decrease_master"
modkey+Shift+l = ":layout.increase_master_count" "modkey+Shift+l" = ":layout.increase_master_count"
modkey+Shift+h = ":layout.decrease_master_count" "modkey+Shift+h" = ":layout.decrease_master_count"
modkey+Control+l = ":layout.increase_column_count" "modkey+Control+l" = ":layout.increase_column_count"
modkey+Control+h = ":layout.decrease_column_count" "modkey+Control+h" = ":layout.decrease_column_count"
modkey+[ = ":layout.next_layout" "modkey+[" = ":layout.next_layout"
modkey+] = ":layout.prev_layout" "modkey+]" = ":layout.prev_layout"
# Power manager module # Power manager module
[powerman] [powerman]
# Bad battery condition warning threshold # Bad battery condition warning threshold (in %)
battery_quality_min = 33 battery_quality_min = 33
# Low battery warning threshold # Low battery warning threshold (in %)
battery_capacity_min = 15 battery_capacity_min = 15
# Process to execute on low battery # Process to execute on low battery
on_low_battery = "" on_low_battery = ""
@ -99,3 +102,10 @@ exec = "picom"
[macros] [macros]
step = 10 step = 10
# Autostart system
[autostart]
# Enable minimization of apps with "Hidden" in their .desktop file
minimize_enable = true
# How long to target apps that should be minimized
minimize_timeout = 120

View File

@ -11,11 +11,11 @@
- install mpc - install mpc
- quick links - quick links
- create `links` directory in the config directory - create `links` directory in the config directory
- add .desktop files with of apps you want to show on the quick launcher - add .desktop files of apps you want to have on the quick launcher
- anti-aliased window corners (unity theme only) - anti-aliased window corners (unity theme only)
- install picom - install picom
- drop the picom.conf file into your .config folder - drop the picom.conf file into your .config folder
- enable picom to run on wm boot (read autostart) - enable picom to run on wm boot (read autostart)
- autostart - autostart
- create "autostart" directory in .config folder - create "autostart" directory in .config folder
- drop .desktop files (files in /usr/share/applications) of apps you want torun on wm boot - drop .desktop files (files in /usr/share/applications) of apps you want to run on wm boot

View File

@ -1,10 +1,10 @@
-- this file is part of reno desktop. -- 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 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. -- 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/>. -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
-- renotk (formerly awmtk2) - template/granular styling library for reno -- renotk (formerly awmtk2) - template/granular styling library for reno
local wibox = require("wibox") local wibox = require("wibox")
local gears = require("gears") local gears = require("gears")
@ -143,7 +143,7 @@ awmtk.proto_style = {
-- } -- }
-- { callbacks -- { callbacks
-- a tiny bit more complex thing to account for more extensibility -- a tiny bit more complex thing to account for more extensibility
-- the stub functions do nothing - you should implement functionality inside theme -- the stub functions do nothing - you should implement functionality inside the theme
onpress = function() end, onpress = function() end,
onrelease = function() end, onrelease = function() end,
-- } -- }
@ -463,7 +463,7 @@ awmtk.proto_templates = {
end, end,
wibar = function(style) wibar = function(style)
-- just you regular old wibar, but as a style template. -- just your regular old wibar, but as a style template.
return function(layout,options) return function(layout,options)
local margins = style.wibar.margins local margins = style.wibar.margins
if (style.wibar.left or if (style.wibar.left or

View File

@ -1,3 +1,11 @@
-- 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/>.
-- Since it would seem that get_widget_by_id is still an open issue (https://github.com/awesomeWM/awesome/issues/2945, https://github.com/awesomeWM/awesome/issues/2181), this abomination is the nuclear solution to finding **ALL** widgets that don't get indexed because they are separated by an already instantiated widget. If you use this, please, use it carefully. Don't call it more than you really need, cache the results if you have to. -- Since it would seem that get_widget_by_id is still an open issue (https://github.com/awesomeWM/awesome/issues/2945, https://github.com/awesomeWM/awesome/issues/2181), this abomination is the nuclear solution to finding **ALL** widgets that don't get indexed because they are separated by an already instantiated widget. If you use this, please, use it carefully. Don't call it more than you really need, cache the results if you have to.
-- Hypothetically, if there occurs such a thing as widget cycle, this will get stuck. Also it's very expensive. -- Hypothetically, if there occurs such a thing as widget cycle, this will get stuck. Also it's very expensive.
return function(widget, id) return function(widget, id)

View File

@ -1,3 +1,10 @@
-- 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/>.
-- If possible, try to blur the image and return its path via callback. Relies on ImageMagick -- If possible, try to blur the image and return its path via callback. Relies on ImageMagick
local awful = require("awful") local awful = require("awful")
return function(image_path,callback) return function(image_path,callback)

View File

@ -30,23 +30,22 @@ shell = "zsh"
# Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>" # Format: <modifier>(+<modifier>+...)+<key> = "<command or :internal.function>"
# "modkey" as modifier will be substituted for modkey variable in [global] # "modkey" as modifier will be substituted for modkey variable in [global]
[keys] [keys]
modkey+Up = ":root.client_next" "modkey+Up" = ":root.client_next"
modkey+Down = ":root.client_previous" "modkey+Down" = ":root.client_previous"
modkey+Control+Up = ":root.screen_next" "modkey+Control+Up" = ":root.screen_next"
modkey+Control+Down = ":root.screen_previous" "modkey+Control+Down" = ":root.screen_previous"
modkey+Tab = ":root.client_swap" "modkey+Tab" = ":root.client_swap"
modkey+Return = ":root.spawn_terminal" "modkey+Return" = ":root.spawn_terminal"
modkey+Shift+Return = ":root.spawn_browser" "modkey+Shift+Return" = ":root.spawn_browser"
# Client keys only work if a focused client exists # Client keys only work if a focused client exists
modkey+Shift+c = ":client.kill" "modkey+Shift+c" = ":client.kill"
modkey+t = ":client.cycle_screen" "modkey+t" = ":client.cycle_screen"
modkey+o = ":client.ontop" "modkey+o" = ":client.ontop"
modkey+b = ":client.below" "modkey+b" = ":client.below"
modkey+f = ":client.fullscreen" "modkey+f" = ":client.fullscreen"
modkey+n = ":client.minimize" "modkey+n" = ":client.minimize"
modkey+m = ":client.maximize" "modkey+m" = ":client.maximize"
]] ]]
for k,v in pairs(parsers.conf(data)) do for k,v in pairs(parsers.conf(data)) do
print("Block: ["..k.."]") print("Block: ["..k.."]")

View File

@ -10,7 +10,7 @@
local parsers = {} local parsers = {}
local function split_strings(text) local function split_strings(text)
-- probably the cleanest function to split by strings i've written -- probably the cleanest function to split by strings i've written to date
local split = {} local split = {}
while text:find("\"") do while text:find("\"") do
local strstart = text:find("\"") local strstart = text:find("\"")
@ -86,48 +86,74 @@ parsers.yaml_pseudo = function(cfgtext)
return struct return struct
end end
local function quotestrip(txt)
if (txt:sub(1,1):match("['\"]"))
and (txt:sub(-1,-1) == txt:sub(1,1)) then
return txt:sub(2,-2)
else
return txt
end
end
parsers.conf = function(cfgtext) parsers.conf = function(cfgtext)
-- Conf style parser (not exactly TOML) -- Conf style parser (not exactly TOML)
cfgtext = cfgtext:gsub("#[^\n]*","") cfgtext = cfgtext:gsub("#[^\n]*","")
local split_by_strings,err = split_strings(cfgtext) local split_by_strings,err = split_strings(cfgtext)
if not split_by_strings then if not split_by_strings then error(err) end
error(err) local full_split = {{}}
local current_line = full_split[1]
-- tokenizer
for _,v in pairs(split_by_strings) do
v = v:match("^[ \t]*(.*)[ \t]*$")
if (not (v == "")) then
if not v:match("^\".*\"$") then
v:gsub("[^ \t]+",function(text)
while text:match("\n") do
local before,after = text:match("([^\n]*)\n(.*)")
if before ~= "" then
table.insert(current_line,before)
end
if #current_line > 0 then
table.insert(full_split,{})
current_line = full_split[#full_split]
end
text = after
end
if text ~= "" then
table.insert(current_line,text)
end
end)
else
table.insert(current_line,v)
end
end
end end
table.remove(full_split,#full_split)
local struct = {global = {}} local struct = {global = {}}
local block = "global" local block = "global"
local last_string_key = nil -- parser
local err for _,line in pairs(full_split) do
for k,v in pairs(split_by_strings) do if line[1] and line[1]:match("^%[[^%]]+%]$") then -- block
if not v:match("^\".*\"$") then block = line[1]:match("^%[([^%]]+)%]$")
v:gsub("[^\n]*",function(line) struct[block] = {}
-- Nothing elseif #line == 3 then -- assignment
if line:match("^%s*$") then if (line[3]:sub(1,1):match("['\"]")) -- string
return and (line[3]:sub(-1,-1) == line[3]:sub(1,1)) then
end struct[block][quotestrip(line[1])] = quotestrip(line[3])
-- Namespace block elseif line[3]:match("^%d+$") then -- number
if line:match("^%s*%[[^%]]-%]%s*$") then struct[block][quotestrip(line[1])] = tonumber(line[3])
block = line:match("%[([^%]]-)%]") elseif (line[3] == "true") or (line[3] == "false") then -- boolean
struct[block] = {} struct[block][quotestrip(line[1])] = (line[3] == "true")
return else
end error("Invalid assignment expression: "..line[3])
-- String/Multiline string assignment end
if line:match("^%s*[^=]-%s*=%s*$") then else -- invalid
last_string_key = line:match("^%s*([^=]-)%s*=%s*$") local textline = ""
return for _,v in pairs(line) do
end textline = textline..v.." "
-- Number/boolean assignment end
local key,value = line:match("^%s*([^=]-)%s*=%s*(.-)%s*$") error("Invalid config expression: "..textline:sub(1,-2))
-- number
if value:match("^[%d%.]*$") then
value = tonumber(value)
-- bool
elseif (value:lower() == "yes") or (value:lower() == "no") then
value = (value:lower() == "yes")
end
struct[block][key] = value
end)
else
struct[block][last_string_key] = v:sub(2,-2)
end end
end end
return struct return struct

137
libs/xdg_data.lua Normal file
View File

@ -0,0 +1,137 @@
-- 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/>.
-- Asynchronous XDG data aggregator (library)
local menu_utils = require("menubar.utils")
local awful = require("awful")
local gears = require("gears")
local json = require("dkjson")
local lib = {}
function lib.init_xdg_struct()
-- Global xdg data struct
local xdg = {
directory_integrity = {},
directory_listings = {},
apps = {},
categories = {
Other = {
icon = "applications-other",
apps = {}
},
Wine = {
icon = "wine",
apps = {}
}
}
}
return xdg
end
function lib.load_xdg_cache()
-- Load cached applications
local cache_file = io.open(gears.filesystem.get_xdg_cache_home()..".reno_xdg_cache.json","r")
local cache
if cache_file then
cache = json.decode(cache_file:read("*a"))
cache_file:close()
end
return cache
end
function lib.add_categories(xdg, categories)
-- Add missing category entries as defined by awesome
for _,v in pairs(categories) do
xdg.categories[v.app_type] = {
name = v.name,
icon = v.icon_name,
apps = {}
}
end
end
function lib.async_process_dirs(xdg, dirs, cache, on_dir_done)
-- Asynchronous scanning process
for _,v in pairs(dirs) do
xdg.directory_listings[v] = {}
awful.spawn.with_line_callback("find "..tostring(v).." -maxdepth 1 -name *.desktop",{
stdout = function(line)
-- Assume the cache is valid for a listed file
if cache and cache.directory_listings[v][line] then
xdg.directory_listings[v][line] = true
xdg.apps[line] = cache.apps[line]
xdg.categories[cache.apps[line].category].apps[line] = cache.apps[line]
return
end
local data = menu_utils.parse_desktop_file(line)
if data.NoDisplay then
return
end
local appdata = {
name = data.Name,
category = "Other",
exec = data.Exec,
icon = (data.Icon and menu_utils.lookup_icon(data.Icon)),
description = data.Comment
}
-- Match first available cateogry for sorting
for _,vv in pairs(data.Categories or {"Other"}) do
if xdg.categories[vv] then
appdata.category = vv
break
end
-- Oh how do I love those Wine applications and their categories
if vv:match("^Wine") then
appdata.category = "Wine"
break
end
end
-- Open terminal apps in the terminal (duh)
if data.Terminal then
appdata.exec = global.terminal.." -e "..appdata.exec
end
-- Just for you, Wine - special case because you're being a shit
if (appdata.exec and appdata.exec:find("%W?wine ")) then
appdata.category = "Wine"
end
xdg.apps[line] = appdata
xdg.categories[appdata.category].apps[line] = appdata
-- Add the file to the listing of cached ones
xdg.directory_listings[v][line] = true
end,
output_done = function(...) on_dir_done(v,...) end
})
end
end
function lib.generate_meta_patch(xdg)
local patch = {apps = {}}
for k,v in pairs(xdg.apps) do
patch.apps[k] = {}
for kk,vv in pairs(v) do
patch.apps[k][kk] = vv
end
patch.apps[k].name = nil
patch.apps[k].category = nil
patch.apps[k].exec = nil
patch.apps[k].icon = nil
patch.apps[k].description = nil
end
return patch
end
function lib.apply_meta_patch(xdg,patch)
for k,v in pairs(patch.apps) do
if xdg.apps[k] then
for kk,vv in pairs(v) do
xdg.apps[k][kk] = vv
end
end
end
end
return lib

View File

@ -5,11 +5,82 @@
-- 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. -- 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/>. -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
-- XFCE style autostart system -- XFCE style autostart system with a system to automatically kill children just to fuck over Steam. (now with SMЯT targeting software package!)
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local gfs = gears.filesystem local gfs = gears.filesystem
local menu_utils = require("menubar.utils") local menu_utils = require("menubar.utils")
local hide_ids = {}
local related_ids = {}
local settings = config.autostart
local stop_checking = false
-- I know this is linux specific, blame Steam for creating a triple-forking launcher with no startup id.
-- I love the fact that valve is supportive of linux and thinks it's the future of gaming and all that
-- but you could've just done the due diligence and, yk, maybe research how things work with XDG?
-- P.S. if you know how to make this function work in similar vein on BSD, feel free to contribute
local function is_child_of(pid,related)
related = related or pid
local ppidfile = io.open("/proc/"..tostring(pid).."/status","rb")
if not ppidfile then return false end
local ppid = ppidfile:read("*a"):match("PPid:%s*(%d+)")
ppidfile:close()
if (not ppid) or (ppid == "1") then return false end
if hide_ids[tonumber(ppid)] then
related_ids[related] = tonumber(ppid)
return true
else
return is_child_of(ppid,related)
end
end
-- Play whack-a-mole with the clients that match ids to hide
-- NO MORE MR NICE GUY, until the user EXPLICITLY activates the client,
-- it's being hidden.
local callback = function(c)
if not settings.minimize_enable then return end
if stop_checking then return end
gears.timer.delayed_call(function()
local kill_later = false
if c.pid and hide_ids[c.pid] then
kill_later = true
end
if c.startup_id and hide_ids[c.startup_id] then
kill_later = true
end
if c.pid and is_child_of(c.pid) then
kill_later = true
end
if kill_later then
c.minimized = true
end
end)
end
client.connect_signal("focus",callback)
client.connect_signal("manage",callback)
-- if the client has been mouse pressed we no longer hide it or any of its siblings - user needs the client to be active.
client.connect_signal("request::activate",function(c,reason)
if (reason ~= "mouse_click") and (reason ~= "tasklist") then
return
end
if c.pid then
hide_ids[c.pid] = nil
if related_ids[c.pid] then
hide_ids[related_ids[c.pid]] = nil
end
end
if c.startup_id then
hide_ids[c.startup_id] = nil
end
end)
-- this ain't happy hour - stop hitting everything in sight.
gears.timer {
timeout = settings.minimize_timeout or 30,
autostart = true,
single_shot = true,
callback = function()
stop_checking = true
hide_ids = {}
end
}
local stdir = os.getenv("XDG_RUNTIME_DIR").."/.awesome_startup/" local stdir = os.getenv("XDG_RUNTIME_DIR").."/.awesome_startup/"
gfs.make_directories(stdir) gfs.make_directories(stdir)
awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -name *.desktop",{ awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -name *.desktop",{
@ -17,8 +88,16 @@ awful.spawn.with_line_callback("find "..gfs.get_xdg_config_home().."autostart/ -
local data = menu_utils.parse_desktop_file(line) local data = menu_utils.parse_desktop_file(line)
if (data.RunHook == "0") or (data.RunHook == nil) then if (data.RunHook == "0") or (data.RunHook == nil) then
if not gfs.file_readable(stdir..line:match("[^/]*$")) then if not gfs.file_readable(stdir..line:match("[^/]*$")) then
io.open(stdir..line:match("[^/]*$"),"w"):close() local npid,nsnid = awful.spawn(data.Exec:gsub("%%%w",""))
awful.spawn(data.Exec:gsub("%%%w","")) io.open(stdir..line:match("[^/]*$"),"w"):write(npid):close()
if data.Hidden then
if npid then
hide_ids[npid] = true
end
if nsnid then
hide_ids[nsnid] = true
end
end
end end
end end
end end

View File

@ -1,3 +1,10 @@
-- 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/>.
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local ask = require("asckey") local ask = require("asckey")

View File

@ -5,7 +5,7 @@
-- 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. -- 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/>. -- 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 -- Powerman X - second generation of the power management module
local awful = require("awful") local awful = require("awful")
local sysctl = require("syscontrol") local sysctl = require("syscontrol")
local naughty = require("naughty") local naughty = require("naughty")

View File

@ -9,13 +9,26 @@ awful.rules.rules = gears.table.join(awful.rules.rules, {
}}, }},
properties = {inhibit_compositor = true}, properties = {inhibit_compositor = true},
}, },
{ rule_any = { class = { { rule = { name = "notificationtoasts.*" },
"thunderbird" properties = {
}}, focusable = false
properties = {callback = function(c) }
},
{ rule = { fullscreen = true },
properties = {
titlebars_enabled = false,
floating = true,
border_width = 0,
border_color = 0,
size_hints_honor = false,
placement=awful.placement.no_offscreen
},
callback = function(c)
gears.timer.delayed_call(function() gears.timer.delayed_call(function()
c.minimized = true if c.valid then
c:geometry(c.screen.geometry)
end
end) end)
end} end
} }
}) })

View File

@ -1,3 +1,10 @@
-- 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/>.
local awful = require("awful") local awful = require("awful")
awful.layout.layouts = { awful.layout.layouts = {

View File

@ -6,13 +6,11 @@
-- --
-- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>. -- You should have received a copy of the GNU General Public License along with Reno desktop. If not, see <https://www.gnu.org/licenses/>.
-- Asynchronous XDG data aggregator -- Asynchronous XDG data aggregator
local start_human = os.time()
local start_computer = os.clock()
local menu_utils = require("menubar.utils") local menu_utils = require("menubar.utils")
local menu_gen = require("menubar.menu_gen") local menu_gen = require("menubar.menu_gen")
local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local json = require("dkjson") local json = require("dkjson")
local lib = require("xdg_data")
menu_utils.wm_name = "" menu_utils.wm_name = ""
-- Directories to scan for .desktop files -- Directories to scan for .desktop files
@ -27,95 +25,18 @@ end)
-- Global xdg data struct -- Global xdg data struct
_G.xdg = { _G.xdg = lib.init_xdg_struct()
directory_integrity = {},
directory_listings = {},
apps = {},
categories = {
Other = {
icon = "applications-other",
apps = {}
},
Wine = {
icon = "wine",
apps = {}
}
}
}
-- Load cached applications -- Load cached applications
local cache_file = io.open(gears.filesystem.get_xdg_cache_home()..".reno_xdg_cache.json","r") local cache = lib.load_xdg_cache()
local cache
if cache_file then
cache = json.decode(cache_file:read("*a"))
cache_file:close()
end
-- Add missing category entries as defined by awesome -- Add missing category entries as defined by awesome
for _,v in pairs(menu_gen.all_categories) do lib.add_categories(xdg,menu_gen.all_categories)
xdg.categories[v.app_type] = {
name = v.name,
icon = v.icon_name,
apps = {}
}
end
-- Asynchronous scanning process -- Asynchronous scanning process
for _,v in pairs(desktop_dirs) do lib.async_process_dirs(xdg,desktop_dirs,cache,function(v)
xdg.directory_listings[v] = {} -- Count completed directory
awful.spawn.with_line_callback("find "..tostring(v).." -maxdepth 1 -name *.desktop",{ desktop_dirs_complete = desktop_dirs_complete + 1
stdout = function(line) -- Call a global signal
-- Assume the cache is valid for a listed file awesome.emit_signal("xdg::dir_finished",v)
if cache and cache.directory_listings[v][line] then end)
xdg.directory_listings[v][line] = true
xdg.apps[line] = cache.apps[line]
xdg.categories[cache.apps[line].category].apps[line] = cache.apps[line]
return
end
local data = menu_utils.parse_desktop_file(line)
if data.NoDisplay then
return
end
local appdata = {
name = data.Name,
category = "Other",
exec = data.Exec,
icon = (data.Icon and menu_utils.lookup_icon(data.Icon)),
description = data.Comment
}
-- Match first available cateogry for sorting
for _,vv in pairs(data.Categories or {"Other"}) do
if xdg.categories[vv] then
appdata.category = vv
break
end
-- Oh how do I love those Wine applications and their categories
if vv:match("^Wine") then
appdata.category = "Wine"
break
end
end
-- Open terminal apps in the terminal (duh)
if data.Terminal then
appdata.exec = global.terminal.." -e "..appdata.exec
end
-- Just for you, Wine - special case because you're being a shit
if (appdata.exec and appdata.exec:find("%W?wine ")) then
appdata.category = "Wine"
end
xdg.apps[line] = appdata
xdg.categories[appdata.category].apps[line] = appdata
-- Add the file to the listing of cached ones
xdg.directory_listings[v][line] = true
end,
output_done = function()
-- Save directory listing hash
desktop_dirs_complete = desktop_dirs_complete + 1
-- Call a global signal
awesome.emit_signal("xdg::dir_finished",v)
end
})
end
local count = function(t) local count = function(t)
local n = 0 local n = 0

2
rc.lua
View File

@ -18,11 +18,11 @@ require("modules.collect_garbage")
require("modules.global") require("modules.global")
require("modules.powermanX") require("modules.powermanX")
require("modules.base") require("modules.base")
require("modules.autostart")
require("modules.rules_stub") require("modules.rules_stub")
require("modules.compositor") require("modules.compositor")
require("modules.binds") require("modules.binds")
require("modules.xdg_data") require("modules.xdg_data")
require("modules.autostart")
require("modules.static_tags") require("modules.static_tags")
require("modules.tiling") require("modules.tiling")
require("modules.desktop") require("modules.desktop")

View File

@ -494,7 +494,7 @@ theme.widgets = {
}, },
-- awesomewm: yo pass me that pango markup -- awesomewm: yo pass me that pango markup
-- pango: you better not make unintuitive cryptic shit -- pango: you better not make unintuitive cryptic shit
-- awesomewm: *attach foreground setting to drawable container* -- awesomewm: *attaches foreground text color setting to container*
fg_normal = "#FAFAFA" fg_normal = "#FAFAFA"
} }
}, },

View File

@ -636,9 +636,6 @@ theme.widgets = {
return gears.shape.rounded_rect(cr,width,height,0) return gears.shape.rounded_rect(cr,width,height,0)
end, end,
margins = 0, margins = 0,
-- WARNING: Change this to true only if you're wiliing to take
-- the visual performance impact from cairo re-rendering the
-- canvas a lot!
transparent = true transparent = true
}, },
icon = { icon = {

View File

@ -1,2 +1,9 @@
-- 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/>.
local awful = require("awful") local awful = require("awful")
return function(args) return awful.widget.layoutbox(args.screen) end return function(args) return awful.widget.layoutbox(args.screen) end

View File

@ -21,7 +21,7 @@ return function(args)
if args.vertical then if args.vertical then
widget:get_children_by_id("systray")[1]:set_horizontal(false) widget:get_children_by_id("systray")[1]:set_horizontal(false)
end end
-- Part of a private API -- Stolen from the API. Apparently this function is entirely undocumented.
if awesome.systray() == 0 then if awesome.systray() == 0 then
widget.visible = false widget.visible = false
end end

View File

@ -15,6 +15,53 @@ local beautiful = require("beautiful")
local ask = require("asckey") local ask = require("asckey")
local test_pactl = os.execute("pactl --version") local test_pactl = os.execute("pactl --version")
G_ClientSinksByPID = G_ClientSinksByPID or {}
G_ClientSinksByName = G_ClientSinksByName or {}
G_SinkVolumeLevels = G_SinkVolumeLevels or {}
G_SinkMediaTypes = G_SinkMediaTypes or {}
local update_client_volumes = function()
awful.spawn.easy_async("pactl -n \"awesome\" list sink-inputs",function(stdout)
local pactl_data = fastyaml(stdout)
local indexed_sinks = {}
local sinks_by_pid = {}
local sinks_by_name = {}
local sink_volume_levels = {}
local sink_media_types = {}
for _,v in pairs(pactl_data) do
local sink_id = tonumber(v:match("Sink Input #(%d+)"))
if sink_id then
if v:match("application.process.id = \"(%d+)\"") then
local pid = tonumber(v:match("application.process.id = \"(%d+)\""))
sinks_by_pid[pid] = sinks_by_pid[pid] or {}
table.insert(sinks_by_pid[pid], sink_id)
indexed_sinks[sink_id] = true
end
if v:match("application.name = \"([^\n]+)\"") then
local name = v:match("application.name = \"([^\n]+)\"")
sinks_by_name[name] = sinks_by_name[name] or {}
if not indexed_sinks[sink_id] then
indexed_sinks[sink_id] = true
table.insert(sinks_by_name[name], sink_id)
end
end
if indexed_sinks[sink_id] then
sink_volume_levels[sink_id] = tonumber(v:match("Volume: .-(%d+)%%"))
sink_media_types[sink_id] = v:match("media.name = \"([^\"]+)\"") or
v:match("media.class = \"([^\"]+)\"")
end
end
end
G_ClientSinksByName = sinks_by_name
G_ClientSinksByPID = sinks_by_pid
G_SinkVolumeLevels = sink_volume_levels
G_SinkMediaTypes = sink_media_types
end)
end
G_ClientSinksUpdateTimer = G_ClientSinksUpdateTimer or gears.timer({
timeout = 0.5,
autostart = true,
callback = update_client_volumes
})
local result = test_pactl local result = test_pactl
if _VERSION:match("5.1") then if _VERSION:match("5.1") then
result = (test_pactl == 0) result = (test_pactl == 0)
@ -38,117 +85,180 @@ end
return function(args) return function(args)
local style = awmtk2.create_style("client_volume", local style = awmtk2.create_style("client_volume",
awmtk2.generic.oneline_widget, args.style,args.vertical) awmtk2.generic.oneline_widget, args.style)
local templates = awmtk2.create_template_lib("client_volume",awmtk2.templates,args.templates) local templates = awmtk2.create_template_lib("client_volume",awmtk2.templates,args.templates)
local t = awmtk2.build_templates(templates,style,args.vertical) local t = awmtk2.build_templates(templates,style)
local widget = wibox.widget(t.container({ local widget = wibox.widget(t.container({
t.icon({ {
t.icon({
image = get_icon(0);
resize = true
}),
t.textbox({
markup = "No sound/Not available"
}),
visible = true,
id = "error",
spacing = style.base.spacing,
layout = wibox.layout.fixed.horizontal
},
{
id = "client_volume_container",
spacing = style.base.spacing,
layout = wibox.layout.fixed.vertical
},
spacing = style.base.spacing,
layout = wibox.layout.fixed.vertical
}))
local client_volume_container = widget:get_children_by_id("client_volume_container")[1]
local errorbox = widget:get_children_by_id("error")[1]
local id_by_slider_container = {}
local active_sliders = {}
-- Asynchronous promise for a "create_slider" function
local create_slider = function(sink_input_id) end
local remove_slider = function(sink_input_id)
local index_to_remove = nil
for k,v in pairs(client_volume_container.children) do
if id_by_slider_container[v] == sink_input_id then
index_to_remove = k
end
end
if index_to_remove then
active_sliders[sink_input_id] = nil
client_volume_container:remove(index_to_remove)
end
end
-- Callback to update all slider values
local function update_active_sliders()
local checked_sliders = {}
if client.focus and client.focus.name then
for _,v in pairs(G_ClientSinksByName[client.focus.name] or {}) do
checked_sliders[v] = true
if not active_sliders[v] then
create_slider(v)
end
end
end
if client.focus and client.focus.pid then
for _,v in pairs(G_ClientSinksByPID[client.focus.pid] or {}) do
checked_sliders[v] = true
if not active_sliders[v] then
create_slider(v)
end
end
end
for k,_ in pairs(active_sliders) do
if not checked_sliders[k] then
remove_slider(k)
end
end
for sink_input_id,slider in pairs(active_sliders) do
slider.value = G_SinkVolumeLevels[sink_input_id] or -1
end
end
-- Update sliders every 0.5 seconds
local update_sliders = gears.timer({
timeout = 0.5,
autostart = true,
callback = update_active_sliders
})
-- Function to set client volume
local function volume(filter,value)
update_sliders:again()
if type(filter) == "number" then
awful.spawn("pactl set-sink-input-volume "..tostring(filter).." "..tostring(value).."%")
elseif filter then
if filter.name then
for _,v in pairs(G_ClientSinksByName[filter.name] or {}) do
awful.spawn("pactl set-sink-input-volume "..tostring(v).." "..tostring(value).."%")
end
end
if filter.pid then
for _,v in pairs(G_ClientSinksByPID[filter.pid] or {}) do
awful.spawn("pactl set-sink-input-volume "..tostring(v).." "..tostring(value).."%")
end
end
end
end
create_slider = function(sink_input_id)
local slider_icon_container = wibox.widget(t.icon({
id = "client_volume_icon", id = "client_volume_icon",
resize = true, resize = true,
}), }))
(args.vertical and { local slider_icon = slider_icon_container:get_children_by_id("client_volume_icon")[1]
t.textbox({ local slider_container = wibox.widget(t.slider({
id = "error"
}),
widget = wibox.container.rotate,
direction = "east"
}) or t.textbox({
id = "error"
}),
t.slider({
minimum = 0, minimum = 0,
maximum = 100, maximum = 100,
id = "client_volume", id = "client_volume",
value = -1 value = -1,
}), }))
layout = (args.vertical and wibox.layout.fixed.vertical) or local slider = slider_container:get_children_by_id("client_volume")[1]
wibox.layout.fixed.horizontal local slider_touching = false
})) slider:connect_signal("widget::redraw_needed",function()
local errorbox = widget:get_children_by_id("error")[1] if slider_touching then
local icon = widget:get_children_by_id("client_volume_icon")[1] volume(sink_input_id,slider.value)
local slider = widget:get_children_by_id("client_volume")[1]
-- Local tracking value to prevent zero volume on start
local touched = false
-- 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 _,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 end
if not cl then slider_icon.image = get_icon(slider.value)
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)
end) active_sliders[sink_input_id] = slider
client.connect_signal("focus",function(c) slider:connect_signal("mouse::enter", function()
touched = false slider_touching = true
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(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)
if not (client.focus and client.focus.pid) then
volume_lock = false
return
end
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, value)
awful.spawn("pactl set-sink-input-volume "..tostring(sink_id).." "..tostring(value).."%")
end
end
end
volume_lock = false
end) end)
slider:connect_signal("mouse::leave", function()
slider_touching = false
end)
local new_widget = wibox.widget({
t.textbox({
markup = G_SinkMediaTypes[sink_input_id],
ellipsize = "end",
forced_width = style.slider.width,
forced_height = style.slider.height*(2/3)
}),
{
slider_icon_container,
slider_container,
layout = wibox.layout.fixed.horizontal
},
spacing = style.base.spacing,
layout = wibox.layout.fixed.vertical,
id = tostring(sink_input_id)
})
client_volume_container:add(new_widget)
id_by_slider_container[new_widget] = sink_input_id
end end
-- Attach change to slider local function update_slider_list(c)
slider:connect_signal("widget::redraw_needed",function() active_sliders = {}
if touched then client_volume_container:reset()
volume(slider.value) update_sliders:again()
update_timer:again() local count = false
if c.name then
for _,v in pairs(G_ClientSinksByName[c.name] or {}) do
create_slider(v)
count = true
end
end end
end) if c.pid then
for _,v in pairs(G_ClientSinksByPID[c.pid] or {}) do
create_slider(v)
count = true
end
end
update_active_sliders()
errorbox.visible = not count
end
-- Attach to focus change
client.connect_signal("focus",update_slider_list)
-- Update
root.keys(gears.table.join( root.keys(gears.table.join(
root.keys(), root.keys(),
ask.k(":client.volume_up", function() ask.k(":client.volume_up", function()
volume("+5") volume(client.focus,"+5")
end,{description = "increase client volume", group = "client"}), end,{description = "increase client volume", group = "client"}),
ask.k(":client.volume_down", function() ask.k(":client.volume_down", function()
volume("-5") volume(client.focus,"-5")
end,{description = "decrease client volume", group = "client"}), end,{description = "decrease client volume", group = "client"}),
ask.k(":client.volume_mute", function() ask.k(":client.volume_mute", function()
volume(0) volume(client.focus,0)
end,{description = "mute client", group = "client"}) end,{description = "mute client", group = "client"})
)) ))
return widget return widget

View File

@ -15,7 +15,7 @@ local syscontrol = require("syscontrol")
local ask = require("asckey") local ask = require("asckey")
local function get_virtual_icon(data) local function get_virtual_icon(data)
-- Get an icon from a cumulative total of battery percentages and current charging state -- Get an icon from average of total battery percentage and current charging state
local count = 0 local count = 0
local cumulative = 0 local cumulative = 0
local name = "battery-" local name = "battery-"
@ -142,7 +142,7 @@ return function(args)
percentage_map["charge"] = data.online percentage_map["charge"] = data.online
end end
end end
-- "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) -- "Virtual" here means an abstract icon that represents the average state of all batteries.
local function update_virtual_battery() local function update_virtual_battery()
local icon = battery_widget:get_children_by_id("virtual_id")[1] local icon = battery_widget:get_children_by_id("virtual_id")[1]
local percentage = battery_widget:get_children_by_id("percentage_id")[1] local percentage = battery_widget:get_children_by_id("percentage_id")[1]

View File

@ -60,13 +60,17 @@ return function(args)
return return
end end
local textbox = self:get_children_by_id("text_role")[1] or {} local textbox = self:get_children_by_id("text_role")[1] or {}
-- Apparently the original system for changing bgimage is -- Apparently the original system for changing
-- the bgimage of a tasklist is
-- 1) broken -- 1) broken
-- 2) uses deprecated functions (nice code practices awesomewm) -- 2) uses deprecated functions (nice code practices awesomewm)
-- Solution: write my own. I blame material design for all this. -- Solution: write my own. I blame material design for all this.
-- (P.S: Not to bullshit you, check it yourself - replicatable -- (P.S: Not to bullshit you, check it yourself:
-- by adding theme.tasklist_bg_image_normal or -- you can replicate this by adding
-- theme.tasklist_bg_image_focus in current beautiful theme.) -- ``theme.tasklist_bg_image_normal``
-- or
-- ``theme.tasklist_bg_image_focus``
-- in the default awesomewm config.)
local onfocus = function() local onfocus = function()
self.bgimage = style.button.bgimage_focus self.bgimage = style.button.bgimage_focus
self.bg = style.button.bg_focus self.bg = style.button.bg_focus
@ -105,13 +109,14 @@ return function(args)
c:connect_signal("unfocus",onunfocus) c:connect_signal("unfocus",onunfocus)
c:connect_signal("property::urgent",onurgent) c:connect_signal("property::urgent",onurgent)
c:connect_signal("property::minimized",onminimize) c:connect_signal("property::minimized",onminimize)
if client.focus == c then if client.focus == c then
onfocus() onfocus()
else else
onunfocus() onunfocus()
end end
end, end,
-- Uncomment this only, and **ONLY** if you actually need it. -- Uncomment this only, and **ONLY** if you actually need it.
-- (P.S: you don't need it.)
--id = "background_role" --id = "background_role"
}) })
return awful.widget.tasklist { return awful.widget.tasklist {

View File

@ -20,14 +20,14 @@ return function(args)
awmtk2.generic.status_widget,args.style,args.vertical) awmtk2.generic.status_widget,args.style,args.vertical)
local templates = awmtk2.create_template_lib("lock_clock",awmtk2.templates,args.templates) local templates = awmtk2.create_template_lib("lock_clock",awmtk2.templates,args.templates)
local t = awmtk2.build_templates(templates,style,args.vertical) local t = awmtk2.build_templates(templates,style,args.vertical)
-- Don't mind me just stealing default library code -- Don't mind me just stealing standard library code
local format = args.format or "%a %b %d, %H:%M" local format = args.format or "%a %b %d, %H:%M"
local refresh = args.refresh or 60 local refresh = args.refresh or 60
local tzid = args.tzid local tzid = args.tzid
local timezone = (tzid and TimeZone.new(tzid)) or TimeZone.new_local() local timezone = (tzid and TimeZone.new(tzid)) or TimeZone.new_local()
-- Seriously, was it so hard to add a font parameter for textclock? -- Seriously, was it so hard to add a font parameter for textclock?
-- Do you actually expect of nobody to change the font to something like -- Do you actually expect nobody to change the font to something like
-- idk, 7-segment display? Goddamnit awesome. I trusted you. -- idk, 7-segment display? Goddamnit awesome. I trusted you.
local widget = wibox.widget(t.container(t.textbox({ local widget = wibox.widget(t.container(t.textbox({
id = "clocktext" id = "clocktext"

View File

@ -77,7 +77,7 @@ return function(args)
end end
end end
end) end)
-- If any of the menus emits cascade::kill, close the menu -- If any of the menus emit cascade::kill, close the menu
for _,v in pairs(menus) do for _,v in pairs(menus) do
v:connect_signal("cascade::kill",function() v:connect_signal("cascade::kill",function()
root_menu.visible = false root_menu.visible = false

View File

@ -8,11 +8,62 @@
-- Simple global context menu controls -- Simple global context menu controls
local beautiful = require("beautiful") local beautiful = require("beautiful")
local menugen = require("context_menu") local menugen = require("context_menu")
local xdglib = require("xdg_data")
local menu_gen = require("menubar.menu_gen")
local gears = require("gears")
local json = require("dkjson")
local function regenerate_xdg()
local desktop_dirs = {os.getenv("HOME").."/Desktop"}
local desktop_dirs_complete = 0
local _ = ((table.concat(gears.filesystem.get_xdg_data_dirs(),":") or
"/usr/share:/usr/local/share")..":"..os.getenv("HOME").."/.local/share")
:gsub("[^:]*",function(path)
if gears.filesystem.dir_readable(path.."/applications") then
table.insert(desktop_dirs,path.."/applications")
end
end)
local function count(t)
local c = 0
for _,_ in pairs(t) do
c = c +1
end
return c
end
require("naughty").notify({title="Regenerating XDG cache..."})
-- Generate a patch containing metadata
local meta = xdglib.generate_meta_patch(_G.xdg)
-- Initialize structure
_G.xdg = xdglib.init_xdg_struct()
-- Add missing category entries
xdglib.add_categories(xdg,menu_gen.all_categories)
-- Asynchronous process scanning
xdglib.async_process_dirs(xdg,desktop_dirs,nil,function()
desktop_dirs_complete = desktop_dirs_complete + 1
if desktop_dirs_complete == #desktop_dirs then
for k,v in pairs(xdg.categories) do
if count(v.apps) == 0 then
xdg.categories[k] = nil
end
end
xdglib.apply_meta_patch(xdg,meta)
require("naughty").notify({
text="Done! Restart WM to reload menus."
})
io.open(gears.filesystem.get_xdg_cache_home()..
".reno_xdg_cache.json","w"
):write(json.encode(xdg)):close()
end
end)
end
return function(args) return function(args)
local widget = menugen({ local widget = menugen({
items = { items = {
{"Awesome", { {"Awesome", {
{"reload cache",regenerate_xdg},
{"open config dir", "xdg-open "..root_path}, {"open config dir", "xdg-open "..root_path},
{"open docs", "xdg-open https://awesomewm.org/doc/api/"}, {"open docs", "xdg-open https://awesomewm.org/doc/api/"},
{"restart", function() awesome.restart() end}, {"restart", function() awesome.restart() end},

View File

@ -1,8 +1,17 @@
-- 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/>.
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local awmtk2 = require("awmtk2") local awmtk2 = require("awmtk2")
local wibox = require("wibox") local wibox = require("wibox")
local beautiful = require("beautiful") local beautiful = require("beautiful")
local pager_gen = require("pager")
local asckey_context = require("asckey").context
local icon = beautiful["applications-tab-symbolic"] local icon = beautiful["applications-tab-symbolic"]
@ -161,6 +170,37 @@ return function(args)
sorting_method = "recent" sorting_method = "recent"
end) end)
local appgrid = widget:get_children_by_id("appgrid")[1] local appgrid = widget:get_children_by_id("appgrid")[1]
local pager = pager_gen(appgrid,{},args.rows*args.columns)
local pager_context = asckey_context(gears.table.join(
awful.key({},"Next",function()
pager:next()
end),
awful.key({},"Prior",function()
pager:prev()
end),
awful.key({},"Return",function()
searchbox:emit_signal("button::press")
end),
awful.key({}," ",function()
searchbox:emit_signal("button::press")
end)
))
supermenu:connect_signal("property::visible",function()
if (not pager_context.active) and (supermenu.visible) then
pager_context:activate()
end
if (pager_context.active) and (not supermenu.visible) then
pager_context:deactivate()
end
end)
local root = widget:get_children_by_id("root_ratio")[1]
root:connect_signal("button::press",function(_,_,_,button)
if button == 4 then
pager:prev()
elseif button == 5 then
pager:next()
end
end)
local icon_cache = gears.cache(function(icon,title,exec) local icon_cache = gears.cache(function(icon,title,exec)
local appicon = wibox.widget({ local appicon = wibox.widget({
t.icon({ t.icon({
@ -177,7 +217,7 @@ return function(args)
appicon:connect_signal("button::press",function(_,_,_,button) appicon:connect_signal("button::press",function(_,_,_,button)
if button == 1 then if button == 1 then
supermenu.visible = false supermenu.visible = false
awful.spawn(exec) awful.spawn(exec:gsub("%%%w",""))
end end
end) end)
return appicon return appicon
@ -190,19 +230,22 @@ return function(args)
end end
end) end)
searchbox:connect_signal("button::press",function() searchbox:connect_signal("button::press",function()
if prompt_open then return end
prompt_open = true prompt_open = true
awful.prompt.run { awful.prompt.run {
textbox = searchtext, textbox = searchtext,
exe_callback = function(command) exe_callback = function(command)
local results = xdg_search(command, args.rows*args.columns, sorting_method) local results = xdg_search(command, math.huge, sorting_method)
appgrid:reset() pager.list = {}
pager.index = 0
for _,v in pairs(results) do for _,v in pairs(results) do
appgrid:add(icon_cache:get( table.insert(pager.list,icon_cache:get(
v[2].icon or beautiful.icon_default, v[2].icon or beautiful.icon_default,
v[2].name, v[2].name,
v[2].exec v[2].exec
)) ))
end end
pager:update()
end, end,
done_callback = function() done_callback = function()
prompt_open = false prompt_open = false
@ -211,14 +254,10 @@ return function(args)
} }
end) end)
awesome.connect_signal("xdg::all_finished",function() awesome.connect_signal("xdg::all_finished",function()
local count = 0
for _,v in pairs(xdg.apps) do for _,v in pairs(xdg.apps) do
count = count + 1 table.insert(pager.list,icon_cache:get(v.icon or beautiful.icon_default,v.name,v.exec))
appgrid:add(icon_cache:get(v.icon or beautiful.icon_default,v.name,v.exec))
if count >= args.columns*args.rows then
break
end
end end
pager:update()
end) end)
return widget,icon return widget,icon
end end