Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
|
e4ed68daf0 | |
|
c7d942050c | |
|
25c44f100a | |
|
3fdad6db65 | |
|
f9e933bebf | |
|
1b7cc116dc | |
|
fc811359ae | |
|
08c4d52480 |
23
README.md
23
README.md
|
@ -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
|
||||||
|
|
128
desktop.conf
128
desktop.conf
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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.."]")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -9,14 +9,10 @@ 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)
|
}
|
||||||
gears.timer.delayed_call(function()
|
|
||||||
c.minimized = true
|
|
||||||
end)
|
|
||||||
end}
|
|
||||||
},
|
},
|
||||||
{ rule = { fullscreen = true },
|
{ rule = { fullscreen = true },
|
||||||
properties = {
|
properties = {
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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
2
rc.lua
|
@ -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")
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -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 = {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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]
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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},
|
||||||
|
|
|
@ -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 awmtk2 = require("awmtk2")
|
local awmtk2 = require("awmtk2")
|
||||||
|
|
Loading…
Reference in New Issue