diff --git a/awesome/.config/awesome/alias-config.lua b/awesome/.config/awesome/alias-config.lua
new file mode 100644
index 0000000..4f9e8ce
--- /dev/null
+++ b/awesome/.config/awesome/alias-config.lua
@@ -0,0 +1,32 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Application aliases for tasklist widget --
+-----------------------------------------------------------------------------------------------------------------------
+
+local appnames = {}
+
+appnames["Exaile" ] = "EXAILE"
+appnames["Pragha" ] = "PRAG"
+appnames["Smplayer" ] = "SMPL"
+appnames["Firefox" ] = "FIFOX"
+appnames["Gnome-terminal" ] = "GTERM"
+appnames["Gnome-system-monitor"] = "SYSMN"
+appnames["Gthumb" ] = "THUMB"
+appnames["Gimp-2.8" ] = "GIMP"
+appnames["Gimp-2.10" ] = "GIMP"
+appnames["Goldendict" ] = "GDIC"
+appnames["Easytag" ] = "ETAG"
+appnames["Mcomix" ] = "COMIX"
+appnames["Claws-mail" ] = "CMAIL"
+appnames["Evolution" ] = "EVOM"
+appnames["URxvt" ] = "RXVT"
+appnames["VirtualBox" ] = "VBOX"
+appnames["Keepassx" ] = "KPASS"
+appnames["keepassxc" ] = "KPASS"
+appnames["Evince" ] = "EVINCE"
+appnames["Thunderbird" ] = "TBIRD"
+appnames["jetbrains-pycharm-ce"] = "PYCRM"
+appnames["jetbrains-clion" ] = "CLION"
+appnames["Qemu-system-x86_64" ] = "QEMU"
+
+return appnames
+
diff --git a/awesome/.config/awesome/edges-config.lua b/awesome/.config/awesome/edges-config.lua
new file mode 100644
index 0000000..373b632
--- /dev/null
+++ b/awesome/.config/awesome/edges-config.lua
@@ -0,0 +1,76 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Active screen edges config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local awful = require("awful")
+local redflat = require("redflat")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local edges = {}
+
+local switcher = redflat.float.appswitcher
+local currenttags = redflat.widget.tasklist.filter.currenttags
+local allscreen = redflat.widget.tasklist.filter.allscreen
+
+-- Active screen edges
+-----------------------------------------------------------------------------------------------------------------------
+function edges:init(args)
+
+ args = args or {}
+ local ew = args.width or 1 -- edge width
+ local workarea = args.workarea or screen[mouse.screen].workarea
+
+ -- edge geometry
+ local egeometry = {
+ top = { width = workarea.width - 2 * ew, height = ew , x = ew, y = 0 },
+ right = { width = ew, height = workarea.height, x = workarea.width - ew, y = 0 },
+ left = { width = ew, height = workarea.height, x = 0, y = 0 }
+ }
+
+ -- Top
+ --------------------------------------------------------------------------------
+ local top = redflat.util.desktop.edge("horizontal")
+ top.wibox:geometry(egeometry["top"])
+
+ top.layout:buttons(awful.util.table.join(
+ awful.button({}, 1,
+ function()
+ if client.focus then client.focus.maximized = not client.focus.maximized end
+ end
+ )
+ ))
+
+ -- Right
+ --------------------------------------------------------------------------------
+ local right = redflat.util.desktop.edge("vertical")
+ right.wibox:geometry(egeometry["right"])
+
+ right.layout:buttons(awful.util.table.join(
+ awful.button({}, 5, function() awful.tag.viewnext(mouse.screen) end),
+ awful.button({}, 4, function() awful.tag.viewprev(mouse.screen) end)
+ ))
+
+ -- Left
+ --------------------------------------------------------------------------------
+ local left = redflat.util.desktop.edge("vertical", { ew, workarea.height - ew })
+ left.wibox:geometry(egeometry["left"])
+
+ left.area[1]:buttons(awful.util.table.join(
+ awful.button({}, 4, function() switcher:show({ filter = allscreen }) end),
+ awful.button({}, 5, function() switcher:show({ filter = allscreen, reverse = true }) end)
+ ))
+
+ left.area[2]:buttons(awful.util.table.join(
+ awful.button({}, 9, function() if client.focus then client.focus.minimized = true end end),
+ awful.button({}, 4, function() switcher:show({ filter = currenttags }) end),
+ awful.button({}, 5, function() switcher:show({ filter = currenttags, reverse = true }) end)
+ ))
+
+ left.wibox:connect_signal("mouse::leave", function() redflat.float.appswitcher:hide() end)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return edges
diff --git a/awesome/.config/awesome/env-config.lua b/awesome/.config/awesome/env-config.lua
new file mode 100644
index 0000000..8903d66
--- /dev/null
+++ b/awesome/.config/awesome/env-config.lua
@@ -0,0 +1,100 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Environment config --
+-----------------------------------------------------------------------------------------------------------------------
+
+local awful = require("awful")
+local gears = require("gears")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local naughty = require("naughty")
+
+local redflat = require("redflat")
+
+local unpack = unpack or table.unpack
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local env = {}
+
+-- Build hotkeys depended on config parameters
+-----------------------------------------------------------------------------------------------------------------------
+function env:init(args)
+
+ -- init vars
+ args = args or {}
+
+ -- environment vars
+ self.terminal = args.terminal or "termite"
+ self.editor = os.getenv("EDITOR") or "vim"
+ self.editor_cmd = self.terminal .. " -e " .. self.editor
+
+ self.mod = args.mod or "Mod4"
+ self.fm = args.fm or "nemo"
+ self.mail = args.mail or "thunderbird"
+ self.player = args.player or "mpd"
+ self.updates = args.updates or "bash -c 'pacman -Qu | grep -v ignored | wc -l'"
+ self.home = os.getenv("HOME")
+ self.themedir = awful.util.get_configuration_dir() .. "themes/default"
+
+ -- boolean defaults is pain
+ self.sloppy_focus = args.sloppy_focus or false
+ self.color_border_focus = args.color_border_focus or false
+ self.set_slave = args.set_slave == nil and true or false
+ self.set_center = args.set_center or false
+ self.desktop_autohide = args.desktop_autohide or false
+
+ -- theme setup
+ beautiful.init(env.themedir .. "/theme.lua")
+ beautiful.useless_gap = 5
+ -- naughty config
+ naughty.config.padding = beautiful.useless_gap and 2 * beautiful.useless_gap or 0
+
+ if beautiful.naughty then
+ naughty.config.presets.normal = redflat.util.table.merge(beautiful.naughty.base, beautiful.naughty.normal)
+ naughty.config.presets.critical = redflat.util.table.merge(beautiful.naughty.base, beautiful.naughty.critical)
+ naughty.config.presets.low = redflat.util.table.merge(beautiful.naughty.base, beautiful.naughty.low)
+ end
+end
+
+
+-- Common functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Wallpaper setup
+--------------------------------------------------------------------------------
+env.wallpaper = function(s)
+ if beautiful.wallpaper then
+ if not env.desktop_autohide and awful.util.file_readable(beautiful.wallpaper) then
+ gears.wallpaper.maximized(beautiful.wallpaper, s, true)
+ else
+ gears.wallpaper.set(beautiful.color and beautiful.color.bg)
+ end
+ end
+end
+
+-- Tag tooltip text generation
+--------------------------------------------------------------------------------
+env.tagtip = function(t)
+ local layname = awful.layout.getname(awful.tag.getproperty(t, "layout"))
+ if redflat.util.table.check(beautiful, "widget.layoutbox.name_alias") then
+ layname = beautiful.widget.layoutbox.name_alias[layname] or layname
+ end
+ return string.format("%s (%d apps) [%s]", t.name, #(t:clients()), layname)
+end
+
+-- Panel widgets wrapper
+--------------------------------------------------------------------------------
+env.wrapper = function(widget, name, buttons)
+ local margin = redflat.util.table.check(beautiful, "widget.wrapper")
+ and beautiful.widget.wrapper[name] or { 0, 0, 0, 0 }
+ if buttons then
+ widget:buttons(buttons)
+ end
+
+ return wibox.container.margin(widget, unpack(margin))
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return env
diff --git a/awesome/.config/awesome/ercheck-config.lua b/awesome/.config/awesome/ercheck-config.lua
new file mode 100644
index 0000000..e7e9c54
--- /dev/null
+++ b/awesome/.config/awesome/ercheck-config.lua
@@ -0,0 +1,27 @@
+local naughty = require("naughty")
+
+if awesome.startup_errors then
+ naughty.notify({
+ preset = naughty.config.presets.critical,
+ title = "Oops, there were errors during startup!",
+ text = awesome.startup_error
+ })
+end
+
+do
+ local in_error = false
+ awesome.connect_signal(
+ "debug::error",
+ function (err)
+ if in_error then return end
+ in_error = true
+
+ naughty.notify({
+ preset = naughty.config.presets.critical,
+ title = "Oops, an error happened!",
+ text = err
+ })
+ in_error = false
+ end
+ )
+end
diff --git a/awesome/.config/awesome/hotkeys_popup/termite.lua b/awesome/.config/awesome/hotkeys_popup/termite.lua
index 57b431e..d6a0a9e 100644
--- a/awesome/.config/awesome/hotkeys_popup/termite.lua
+++ b/awesome/.config/awesome/hotkeys_popup/termite.lua
@@ -5,7 +5,7 @@
-- @copyright 2017 ikselven
-- @module awful.hotkeys_popup.keys.termite
---------------------------------------------------------------------------
-
+require("awful.hotkeys_popup.keys")
local hotkeys_popup = require("awful.hotkeys_popup.widget")
local termite_rule = { class = "Termite" }
diff --git a/awesome/.config/awesome/key.old b/awesome/.config/awesome/key.old
new file mode 100644
index 0000000..83879d0
--- /dev/null
+++ b/awesome/.config/awesome/key.old
@@ -0,0 +1,230 @@
+-- {{{ Key bindings
+globalkeys = gears.table.join(
+ awful.key({ env.mod }, "b", function ()
+ mouse.screen.mywibox.visible = not mouse.screen.mywibox.visible
+ end,{description="togle wibox",group="awesome"}),
+ awful.key({ env.mod, }, "s", hotkeys_popup.show_help,
+ {description="show help", group="awesome"}),
+ awful.key({ env.mod, }, "e", revelation,
+ {description="revelation shortcut",group="awesome"}),
+ awful.key({ env.mod, }, "Left", awful.tag.viewprev,
+ {description = "view previous", group = "tag"}),
+ awful.key({ env.mod, }, "Right", awful.tag.viewnext,
+ {description = "view next", group = "tag"}),
+ awful.key({ env.mod, }, "Escape", awful.tag.history.restore,
+ {description = "go back", group = "tag"}),
+ awful.key({ "Shift" }, "Alt_L", function() mykeyboardlayout.next_layout(); end),
+ awful.key({ env.mod, }, "j",
+ function ()
+ awful.client.focus.byidx( 1)
+ end,
+ {description = "focus next by index", group = "client"}
+ ),
+ awful.key({ env.mod, }, "k",
+ function ()
+ awful.client.focus.byidx(-1)
+ end,
+ {description = "focus previous by index", group = "client"}
+ ),
+ awful.key({env.mod,"Shift"},"o" , function() xrandr.xrandr() end,
+ {description = "xrandr shortcut", group = "awesome"}),
+ awful.key({ env.mod, }, "w", function () mainmenu.mainmenu:show() end,
+ {description = "show main menu", group = "awesome"}),
+
+ -- Layout manipulation
+ awful.key({ env.mod, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
+ {description = "swap with next client by index", group = "client"}),
+ awful.key({ env.mod, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
+ {description = "swap with previous client by index", group = "client"}),
+ awful.key({ env.mod, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
+ {description = "focus the next screen", group = "screen"}),
+ awful.key({ env.mod, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
+ {description = "focus the previous screen", group = "screen"}),
+ awful.key({ env.mod, }, "u", awful.client.urgent.jumpto,
+ {description = "jump to urgent client", group = "client"}),
+ awful.key({ env.mod, }, "Tab",
+ function ()
+ awful.client.focus.history.previous()
+ if client.focus then
+ client.focus:raise()
+ end
+ end,
+ {description = "go back", group = "client"}),
+
+ -- Standard program
+ -- Dropdown application
+ awful.key({ env.mod, }, "Return", function () awful.spawn(terminal) end,
+ {description = "open a terminal", group = "launcher"}),
+ awful.key({ env.mod, "Control" }, "r", awesome.restart,
+ {description = "reload awesome", group = "awesome"}),
+ awful.key({ env.mod, "Shift" }, "q", awesome.quit,
+ {description = "quit awesome", group = "awesome"}),
+
+ awful.key({ env.mod, }, "l", function () awful.tag.incmwfact( 0.05) end,
+ {description = "increase master width factor", group = "layout"}),
+ awful.key({ env.mod, }, "h", function () awful.tag.incmwfact(-0.05) end,
+ {description = "decrease master width factor", group = "layout"}),
+ awful.key({ env.mod, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
+ {description = "increase the number of master clients", group = "layout"}),
+ awful.key({ env.mod, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
+ {description = "decrease the number of master clients", group = "layout"}),
+ awful.key({ env.mod, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
+ {description = "increase the number of columns", group = "layout"}),
+ awful.key({ env.mod, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
+ {description = "decrease the number of columns", group = "layout"}),
+ awful.key({ env.mod, }, "space", function () awful.layout.inc( 1) end,
+ {description = "select next", group = "layout"}),
+ awful.key({ env.mod, "Shift" }, "space", function () awful.layout.inc(-1) end,
+ {description = "select previous", group = "layout"}),
+
+ awful.key({ env.mod, "Control" }, "n",
+ function ()
+ local c = awful.client.restore()
+ -- Focus restored client
+ if c then
+ client.focus = c
+ c:raise()
+ end
+ end,
+ {description = "restore minimized", group = "client"}),
+
+ -- Prompt
+ awful.key({ env.mod }, "r", function () awful.screen.focused().mypromptbox:run() end,
+ {description = "run prompt", group = "launcher"}),
+
+ awful.key({ env.mod }, "x",
+ function ()
+ awful.prompt.run {
+ prompt = "Run Lua code: ",
+ textbox = awful.screen.focused().mypromptbox.widget,
+ exe_callback = awful.util.eval,
+ history_path = awful.util.get_cache_dir() .. "/history_eval"
+ }
+ end,
+ {description = "lua execute prompt", group = "awesome"}),
+ -- Menubar
+ awful.key({ env.mod }, "p", function() menubar.show() end,
+ {description = "show the menubar", group = "launcher"}),
+ awful.key({ },"XF86AudioRaiseVolume", function() awful.spawn("pamixer -i 5") end),
+ awful.key({ }, "XF86AudioLowerVolume", function () awful.spawn("pamixer -d 5") end),
+ --multimedia keys
+ awful.key({ }, "XF86MonBrightnessUp", function () awful.spawn("light -A 10") end),
+ awful.key({ }, "XF86MonBrightnessDown", function () awful.spawn("light -U 10") end),
+ awful.key({ }, "XF86AudioMute", function () awful.spawn("pamixer -t") end),
+ awful.key({ }, "XF86AudioPlay", function () awful.spawn("mpc toggle") end),
+ awful.key({ }, "XF86AudioStop", function () awful.spawn("mpc stop") end),
+ awful.key({ }, "XF86AudioNext", function () awful.spawn("mpc next") end),
+ awful.key({ }, "XF86AudioPrev", function () awful.spawn("mpc prev") end),
+ --application hotkeys (logitech keyboard g710+)
+ awful.key({ }, "XF86LaunchA", function () awful.spawn(terminal) end,
+ {description = "open a terminal", group = "launcher"}),
+ awful.key({ }, "XF86Launch9", function () awful.spawn("keepassxc") end,
+ {description = "open keepass", group = "launcher"}),
+
+ awful.key({ }, "XF86Launch8", function () awful.spawn("firefox") end,
+ {description = "open a Firefox", group = "launcher"}),
+
+ awful.key({ }, "XF86Launch7", function () awful.spawn("code") end,
+ {description = "open VScode", group = "launcher"})
+)
+
+clientkeys = gears.table.join(
+ awful.key({ env.mod, }, "f",
+ function (c)
+ c.fullscreen = not c.fullscreen
+ c:raise()
+ end,
+ {description = "toggle fullscreen", group = "client"}),
+ awful.key({ env.mod, "Shift" }, "c", function (c) c:kill() end,
+ {description = "close", group = "client"}),
+ awful.key({ env.mod, "Control" }, "space", awful.client.floating.toggle ,
+ {description = "toggle floating", group = "client"}),
+ awful.key({ env.mod, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
+ {description = "move to master", group = "client"}),
+ awful.key({ env.mod, }, "o", function (c) c:move_to_screen() end,
+ {description = "move to screen", group = "client"}),
+ awful.key({ env.mod, }, "t", function (c) c.ontop = not c.ontop end,
+ {description = "toggle keep on top", group = "client"}),
+ awful.key({ env.mod, }, "n",
+ function (c)
+ -- The client currently has the input focus, so it cannot be
+ -- minimized, since minimized clients can't have the focus.
+ c.minimized = true
+ end ,
+ {description = "minimize", group = "client"}),
+ awful.key({ env.mod, }, "m",
+ function (c)
+ c.maximized = not c.maximized
+ c:raise()
+ end ,
+ {description = "(un)maximize", group = "client"}),
+ awful.key({ env.mod, "Control" }, "m",
+ function (c)
+ c.maximized_vertical = not c.maximized_vertical
+ c:raise()
+ end ,
+ {description = "(un)maximize vertically", group = "client"}),
+ awful.key({ env.mod, "Shift" }, "m",
+ function (c)
+ c.maximized_horizontal = not c.maximized_horizontal
+ c:raise()
+ end ,
+ {description = "(un)maximize horizontally", group = "client"})
+)
+
+-- Bind all key numbers to tags.
+-- Be careful: we use keycodes to make it work on any keyboard layout.
+-- This should map on the top row of your keyboard, usually 1 to 9.
+for i = 1, 9 do
+ globalkeys = gears.table.join(globalkeys,
+ -- View tag only.
+ awful.key({ env.mod }, "#" .. i + 9,
+ function ()
+ local screen = awful.screen.focused()
+ local tag = screen.tags[i]
+ if tag then
+ tag:view_only()
+ end
+ end,
+ {description = "view tag #"..i, group = "tag"}),
+ -- Toggle tag display.
+ awful.key({ env.mod, "Control" }, "#" .. i + 9,
+ function ()
+ local screen = awful.screen.focused()
+ local tag = screen.tags[i]
+ if tag then
+ awful.tag.viewtoggle(tag)
+ end
+ end,
+ {description = "toggle tag #" .. i, group = "tag"}),
+ -- Move client to tag.
+ awful.key({ env.mod, "Shift" }, "#" .. i + 9,
+ function ()
+ if client.focus then
+ local tag = client.focus.screen.tags[i]
+ if tag then
+ client.focus:move_to_tag(tag)
+ end
+ end
+ end,
+ {description = "move focused client to tag #"..i, group = "tag"}),
+ -- Toggle tag on focused client.
+ awful.key({ env.mod, "Control", "Shift" }, "#" .. i + 9,
+ function ()
+ if client.focus then
+ local tag = client.focus.screen.tags[i]
+ if tag then
+ client.focus:toggle_tag(tag)
+ end
+ end
+ end,
+ {description = "toggle focused client on tag #" .. i, group = "tag"})
+ )
+end
+
+clientbuttons = gears.table.join(
+ awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
+ awful.button({ env.mod }, 1, awful.mouse.client.move),
+ awful.button({ env.mod }, 3, awful.mouse.client.resize))
+
+ root.keys(globalkeys)
\ No newline at end of file
diff --git a/awesome/.config/awesome/keys-config.lua b/awesome/.config/awesome/keys-config.lua
new file mode 100644
index 0000000..2bc1696
--- /dev/null
+++ b/awesome/.config/awesome/keys-config.lua
@@ -0,0 +1,838 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Hotkeys and mouse buttons config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local table = table
+local awful = require("awful")
+local redflat = require("redflat")
+--import xrandr library
+local xrandr = require("xrandr")
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local hotkeys = { mouse = {}, raw = {}, keys = {}, fake = {} }
+
+-- key aliases
+local apprunner = redflat.float.apprunner
+local appswitcher = redflat.float.appswitcher
+local current = redflat.widget.tasklist.filter.currenttags
+local allscr = redflat.widget.tasklist.filter.allscreen
+local laybox = redflat.widget.layoutbox
+local redtip = redflat.float.hotkeys
+local laycom = redflat.layout.common
+local grid = redflat.layout.grid
+local map = redflat.layout.map
+local redtitle = redflat.titlebar
+local qlaunch = redflat.float.qlaunch
+
+-- Key support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- change window focus by history
+local function focus_to_previous()
+ awful.client.focus.history.previous()
+ if client.focus then client.focus:raise() end
+end
+
+-- change window focus by direction
+local focus_switch_byd = function(dir)
+ return function()
+ awful.client.focus.bydirection(dir)
+ if client.focus then client.focus:raise() end
+ end
+end
+
+-- minimize and restore windows
+local function minimize_all()
+ for _, c in ipairs(client.get()) do
+ if current(c, mouse.screen) then c.minimized = true end
+ end
+end
+
+local function minimize_all_except_focused()
+ for _, c in ipairs(client.get()) do
+ if current(c, mouse.screen) and c ~= client.focus then c.minimized = true end
+ end
+end
+
+local function restore_all()
+ for _, c in ipairs(client.get()) do
+ if current(c, mouse.screen) and c.minimized then c.minimized = false end
+ end
+end
+
+local function restore_client()
+ local c = awful.client.restore()
+ if c then client.focus = c; c:raise() end
+end
+
+-- close window
+local function kill_all()
+ for _, c in ipairs(client.get()) do
+ if current(c, mouse.screen) and not c.sticky then c:kill() end
+ end
+end
+
+-- new clients placement
+local function toggle_placement(env)
+ env.set_slave = not env.set_slave
+ redflat.float.notify:show({ text = (env.set_slave and "Slave" or "Master") .. " placement" })
+end
+
+-- numeric keys function builders
+local function tag_numkey(i, mod, action)
+ return awful.key(
+ mod, "#" .. i + 9,
+ function ()
+ local screen = awful.screen.focused()
+ local tag = screen.tags[i]
+ if tag then action(tag) end
+ end
+ )
+end
+
+local function client_numkey(i, mod, action)
+ return awful.key(
+ mod, "#" .. i + 9,
+ function ()
+ if client.focus then
+ local tag = client.focus.screen.tags[i]
+ if tag then action(tag) end
+ end
+ end
+ )
+end
+
+-- brightness functions
+local brightness = function(args)
+ redflat.float.brightness:change_with_xbacklight(args) -- use xbacklight
+end
+
+-- right bottom corner position
+local rb_corner = function()
+ return { x = screen[mouse.screen].workarea.x + screen[mouse.screen].workarea.width,
+ y = screen[mouse.screen].workarea.y + screen[mouse.screen].workarea.height }
+end
+
+-- Build hotkeys depended on config parameters
+-----------------------------------------------------------------------------------------------------------------------
+function hotkeys:init(args)
+
+ -- Init vars
+ args = args or {}
+ local env = args.env
+ local volume = args.volume
+ local mainmenu = args.menu
+ local appkeys = args.appkeys or {}
+
+ self.mouse.root = (awful.util.table.join(
+ awful.button({ }, 1, function () mainmenu:hide() end),
+ awful.button({ }, 3, function () mainmenu:toggle() end),
+ awful.button({ }, 4, awful.tag.viewnext),
+ awful.button({ }, 5, awful.tag.viewprev)
+ ))
+
+ -- volume functions
+ local volume_raise = function() volume:change_volume({ show_notify = true }) end
+ local volume_lower = function() volume:change_volume({ show_notify = true, down = true }) end
+ local volume_mute = function() volume:mute() end
+
+ -- Init widgets
+ redflat.float.qlaunch:init()
+
+ -- Application hotkeys helper
+ --------------------------------------------------------------------------------
+ local apphelper = function(keys)
+ if not client.focus then return end
+
+ local app = client.focus.class:lower()
+ for name, sheet in pairs(keys) do
+ if name == app then
+ redtip:set_pack(
+ client.focus.class, sheet.pack, sheet.style.column, sheet.style.geometry,
+ function() redtip:remove_pack() end
+ )
+ redtip:show()
+ return
+ end
+ end
+
+ redflat.float.notify:show({ text = "No tips for " .. client.focus.class })
+ end
+
+ -- Keys for widgets
+ --------------------------------------------------------------------------------
+
+ -- Apprunner widget
+ ------------------------------------------------------------
+ local apprunner_keys_move = {
+ {
+ { env.mod }, "k", function() apprunner:down() end,
+ { description = "Select next item", group = "Navigation" }
+ },
+ {
+ { env.mod }, "i", function() apprunner:up() end,
+ { description = "Select previous item", group = "Navigation" }
+ },
+ }
+
+ -- apprunner:set_keys(awful.util.table.join(apprunner.keys.move, apprunner_keys_move), "move")
+ apprunner:set_keys(apprunner_keys_move, "move")
+
+ -- Menu widget
+ ------------------------------------------------------------
+ local menu_keys_move = {
+ {
+ { env.mod }, "k", redflat.menu.action.down,
+ { description = "Select next item", group = "Navigation" }
+ },
+ {
+ { env.mod }, "i", redflat.menu.action.up,
+ { description = "Select previous item", group = "Navigation" }
+ },
+ {
+ { env.mod }, "j", redflat.menu.action.back,
+ { description = "Go back", group = "Navigation" }
+ },
+ {
+ { env.mod }, "l", redflat.menu.action.enter,
+ { description = "Open submenu", group = "Navigation" }
+ },
+ }
+
+ -- redflat.menu:set_keys(awful.util.table.join(redflat.menu.keys.move, menu_keys_move), "move")
+ redflat.menu:set_keys(menu_keys_move, "move")
+
+ -- Appswitcher widget
+ ------------------------------------------------------------
+ local appswitcher_keys = {
+
+ {
+ { env.mod }, "a", function() appswitcher:switch() end,
+ { description = "Select next app", group = "Navigation" }
+ },
+ {
+ { env.mod, "Shift" }, "a", function() appswitcher:switch() end,
+ {} -- hidden key
+ },
+ {
+ { env.mod }, "q", function() appswitcher:switch({ reverse = true }) end,
+ { description = "Select previous app", group = "Navigation" }
+ },
+ {
+ { env.mod, "Shift" }, "q", function() appswitcher:switch({ reverse = true }) end,
+ {} -- hidden key
+ },
+ {
+ {}, "Super_L", function() appswitcher:hide() end,
+ { description = "Activate and exit", group = "Action" }
+ },
+ {
+ { env.mod }, "Super_L", function() appswitcher:hide() end,
+ {} -- hidden key
+ },
+ {
+ { env.mod, "Shift" }, "Super_L", function() appswitcher:hide() end,
+ {} -- hidden key
+ },
+ {
+ {}, "Return", function() appswitcher:hide() end,
+ { description = "Activate and exit", group = "Action" }
+ },
+ {
+ {}, "Escape", function() appswitcher:hide(true) end,
+ { description = "Exit", group = "Action" }
+ },
+ {
+ { env.mod }, "Escape", function() appswitcher:hide(true) end,
+ {} -- hidden key
+ },
+ {
+ { env.mod }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+ }
+
+ appswitcher:set_keys(appswitcher_keys)
+
+
+
+ -- Layouts
+ --------------------------------------------------------------------------------
+
+ -- shared layout keys
+ local layout_tile = {
+ {
+ { env.mod }, "l", function () awful.tag.incmwfact( 0.05) end,
+ { description = "Increase master width factor", group = "Layout" }
+ },
+ {
+ { env.mod }, "j", function () awful.tag.incmwfact(-0.05) end,
+ { description = "Decrease master width factor", group = "Layout" }
+ },
+ {
+ { env.mod }, "i", function () awful.client.incwfact( 0.05) end,
+ { description = "Increase window factor of a client", group = "Layout" }
+ },
+ {
+ { env.mod }, "k", function () awful.client.incwfact(-0.05) end,
+ { description = "Decrease window factor of a client", group = "Layout" }
+ },
+ {
+ { env.mod, }, "+", function () awful.tag.incnmaster( 1, nil, true) end,
+ { description = "Increase the number of master clients", group = "Layout" }
+ },
+ {
+ { env.mod, }, "=", function () awful.tag.incnmaster( 1, nil, true) end,
+ { description = "Increase the number of master clients", group = "Layout" }
+ },
+ {
+ { env.mod }, "-", function () awful.tag.incnmaster(-1, nil, true) end,
+ { description = "Decrease the number of master clients", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "+", function () awful.tag.incncol( 1, nil, true) end,
+ { description = "Increase the number of columns", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "=", function () awful.tag.incncol( 1, nil, true) end,
+ { description = "Increase the number of columns", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "-", function () awful.tag.incncol(-1, nil, true) end,
+ { description = "Decrease the number of columns", group = "Layout" }
+ },
+ }
+
+ laycom:set_keys(layout_tile, "tile")
+
+ -- grid layout keys
+ local layout_grid_move = {
+ {
+ { env.mod }, "KP_Up", function() grid.move_to("up") end,
+ { description = "Move window up", group = "Movement" }
+ },
+ {
+ { env.mod }, "KP_Down", function() grid.move_to("down") end,
+ { description = "Move window down", group = "Movement" }
+ },
+ {
+ { env.mod }, "KP_Left", function() grid.move_to("left") end,
+ { description = "Move window left", group = "Movement" }
+ },
+ {
+ { env.mod }, "KP_right", function() grid.move_to("right") end,
+ { description = "Move window right", group = "Movement" }
+ },
+ {
+ { env.mod, "Control" }, "KP_Up", function() grid.move_to("up", true) end,
+ { description = "Move window up by bound", group = "Movement" }
+ },
+ {
+ { env.mod, "Control" }, "KP_Down", function() grid.move_to("down", true) end,
+ { description = "Move window down by bound", group = "Movement" }
+ },
+ {
+ { env.mod, "Control" }, "KP_Left", function() grid.move_to("left", true) end,
+ { description = "Move window left by bound", group = "Movement" }
+ },
+ {
+ { env.mod, "Control" }, "KP_Right", function() grid.move_to("right", true) end,
+ { description = "Move window right by bound", group = "Movement" }
+ },
+ }
+
+ local layout_grid_resize = {
+ {
+ { env.mod }, "i", function() grid.resize_to("up") end,
+ { description = "Inrease window size to the up", group = "Resize" }
+ },
+ {
+ { env.mod }, "k", function() grid.resize_to("down") end,
+ { description = "Inrease window size to the down", group = "Resize" }
+ },
+ {
+ { env.mod }, "j", function() grid.resize_to("left") end,
+ { description = "Inrease window size to the left", group = "Resize" }
+ },
+ {
+ { env.mod }, "l", function() grid.resize_to("right") end,
+ { description = "Inrease window size to the right", group = "Resize" }
+ },
+ {
+ { env.mod, "Shift" }, "i", function() grid.resize_to("up", nil, true) end,
+ { description = "Decrease window size from the up", group = "Resize" }
+ },
+ {
+ { env.mod, "Shift" }, "k", function() grid.resize_to("down", nil, true) end,
+ { description = "Decrease window size from the down", group = "Resize" }
+ },
+ {
+ { env.mod, "Shift" }, "j", function() grid.resize_to("left", nil, true) end,
+ { description = "Decrease window size from the left", group = "Resize" }
+ },
+ {
+ { env.mod, "Shift" }, "l", function() grid.resize_to("right", nil, true) end,
+ { description = "Decrease window size from the right", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "i", function() grid.resize_to("up", true) end,
+ { description = "Increase window size to the up by bound", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "k", function() grid.resize_to("down", true) end,
+ { description = "Increase window size to the down by bound", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "j", function() grid.resize_to("left", true) end,
+ { description = "Increase window size to the left by bound", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "l", function() grid.resize_to("right", true) end,
+ { description = "Increase window size to the right by bound", group = "Resize" }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "i", function() grid.resize_to("up", true, true) end,
+ { description = "Decrease window size from the up by bound ", group = "Resize" }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "k", function() grid.resize_to("down", true, true) end,
+ { description = "Decrease window size from the down by bound ", group = "Resize" }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "j", function() grid.resize_to("left", true, true) end,
+ { description = "Decrease window size from the left by bound ", group = "Resize" }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "l", function() grid.resize_to("right", true, true) end,
+ { description = "Decrease window size from the right by bound ", group = "Resize" }
+ },
+ }
+
+ redflat.layout.grid:set_keys(layout_grid_move, "move")
+ redflat.layout.grid:set_keys(layout_grid_resize, "resize")
+
+ -- user map layout keys
+ local layout_map_layout = {
+ {
+ { env.mod }, "s", function() map.swap_group() end,
+ { description = "Change placement direction for group", group = "Layout" }
+ },
+ {
+ { env.mod }, "v", function() map.new_group(true) end,
+ { description = "Create new vertical group", group = "Layout" }
+ },
+ {
+ { env.mod }, "h", function() map.new_group(false) end,
+ { description = "Create new horizontal group", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "v", function() map.insert_group(true) end,
+ { description = "Insert new vertical group before active", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "h", function() map.insert_group(false) end,
+ { description = "Insert new horizontal group before active", group = "Layout" }
+ },
+ {
+ { env.mod }, "d", function() map.delete_group() end,
+ { description = "Destroy group", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "d", function() map.clean_groups() end,
+ { description = "Destroy all empty groups", group = "Layout" }
+ },
+ {
+ { env.mod }, "f", function() map.set_active() end,
+ { description = "Set active group", group = "Layout" }
+ },
+ {
+ { env.mod }, "g", function() map.move_to_active() end,
+ { description = "Move focused client to active group", group = "Layout" }
+ },
+ {
+ { env.mod, "Control" }, "f", function() map.hilight_active() end,
+ { description = "Hilight active group", group = "Layout" }
+ },
+ {
+ { env.mod }, "a", function() map.switch_active(1) end,
+ { description = "Activate next group", group = "Layout" }
+ },
+ {
+ { env.mod }, "q", function() map.switch_active(-1) end,
+ { description = "Activate previous group", group = "Layout" }
+ },
+ {
+ { env.mod }, "]", function() map.move_group(1) end,
+ { description = "Move active group to the top", group = "Layout" }
+ },
+ {
+ { env.mod }, "[", function() map.move_group(-1) end,
+ { description = "Move active group to the bottom", group = "Layout" }
+ },
+ {
+ { env.mod }, "r", function() map.reset_tree() end,
+ { description = "Reset layout structure", group = "Layout" }
+ },
+ }
+
+ local layout_map_resize = {
+ {
+ { env.mod }, "j", function() map.incfactor(nil, 0.1, false) end,
+ { description = "Increase window horizontal size factor", group = "Resize" }
+ },
+ {
+ { env.mod }, "l", function() map.incfactor(nil, -0.1, false) end,
+ { description = "Decrease window horizontal size factor", group = "Resize" }
+ },
+ {
+ { env.mod }, "i", function() map.incfactor(nil, 0.1, true) end,
+ { description = "Increase window vertical size factor", group = "Resize" }
+ },
+ {
+ { env.mod }, "k", function() map.incfactor(nil, -0.1, true) end,
+ { description = "Decrease window vertical size factor", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "j", function() map.incfactor(nil, 0.1, false, true) end,
+ { description = "Increase group horizontal size factor", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "l", function() map.incfactor(nil, -0.1, false, true) end,
+ { description = "Decrease group horizontal size factor", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "i", function() map.incfactor(nil, 0.1, true, true) end,
+ { description = "Increase group vertical size factor", group = "Resize" }
+ },
+ {
+ { env.mod, "Control" }, "k", function() map.incfactor(nil, -0.1, true, true) end,
+ { description = "Decrease group vertical size factor", group = "Resize" }
+ },
+ }
+
+ redflat.layout.map:set_keys(layout_map_layout, "layout")
+ redflat.layout.map:set_keys(layout_map_resize, "resize")
+
+
+ -- Global keys
+ --------------------------------------------------------------------------------
+ self.raw.root = {
+ {
+ { env.mod }, "b", function () mouse.screen.mywibox.visible = not mouse.screen.mywibox.visible end,{description="togle wibox",group="awesome"}
+ },
+ {
+ { env.mod }, "F1", function() redtip:show() end,
+ { description = "[Hold] Show awesome hotkeys helper", group = "Main" }
+ },
+ {
+ { env.mod, "Control" }, "F1", function() apphelper(appkeys) end,
+ { description = "[Hold] Show hotkeys helper for application", group = "Main" }
+ },
+
+ {
+ { env.mod }, "F2", function () redflat.service.navigator:run() end,
+ { description = "[Hold] Tiling window control mode", group = "Window control" }
+ },
+ {
+ { env.mod }, "h", function() redflat.float.control:show() end,
+ { description = "[Hold] Floating window control mode", group = "Window control" }
+ },
+
+ {
+ { env.mod }, "Return", function() awful.spawn(env.terminal) end,
+ { description = "Open a terminal", group = "Actions" }
+ },
+ {
+ { env.mod, "Mod1" }, "space", function() awful.spawn("clipflap --show") end,
+ { description = "Clipboard manager", group = "Actions" }
+ },
+ {
+ { env.mod, "Control" }, "r", awesome.restart,
+ { description = "Reload WM", group = "Actions" }
+ },
+
+ {
+ { env.mod }, "l", focus_switch_byd("right"),
+ { description = "Go to right client", group = "Client focus" }
+ },
+ {
+ { env.mod }, "j", focus_switch_byd("left"),
+ { description = "Go to left client", group = "Client focus" }
+ },
+ {
+ { env.mod }, "i", focus_switch_byd("up"),
+ { description = "Go to upper client", group = "Client focus" }
+ },
+ {
+ { env.mod }, "k", focus_switch_byd("down"),
+ { description = "Go to lower client", group = "Client focus" }
+ },
+ {
+ { env.mod }, "u", awful.client.urgent.jumpto,
+ { description = "Go to urgent client", group = "Client focus" }
+ },
+ {
+ { env.mod }, "Tab", focus_to_previous,
+ { description = "Go to previos client", group = "Client focus" }
+ },
+ {
+ { env.mod, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
+ {description = "focus the next screen", group = "screen"}},
+ {
+ { env.mod, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
+ {description = "focus the previous screen", group = "screen"}},
+
+ {
+ { env.mod }, "w", function() mainmenu:show() end,
+ { description = "Show main menu", group = "Widgets" }
+ },
+ {
+ { env.mod }, "r", function() apprunner:show() end,
+ { description = "Application launcher", group = "Widgets" }
+ },
+ {
+ { env.mod }, "p", function() redflat.float.prompt:run() end,
+ { description = "Show the prompt box", group = "Widgets" }
+ },
+ {
+ { env.mod }, "x", function() redflat.float.top:show("cpu") end,
+ { description = "Show the top process list", group = "Widgets" }
+ },
+ {
+ { env.mod, "Control" }, "m", function() redflat.widget.mail:update(true) end,
+ { description = "Check new mail", group = "Widgets" }
+ },
+ {
+ { env.mod, "Control" }, "i", function() redflat.widget.minitray:toggle() end,
+ { description = "Show minitray", group = "Widgets" }
+ },
+ {
+ { env.mod, "Control" }, "u", function() redflat.widget.updates:update(true) end,
+ { description = "Check available updates", group = "Widgets" }
+ },
+ {
+ { env.mod }, "g", function() qlaunch:show() end,
+ { description = "Application quick launcher", group = "Widgets" }
+ },
+
+ {
+ { env.mod }, "y", function() laybox:toggle_menu(mouse.screen.selected_tag) end,
+ { description = "Show layout menu", group = "Layouts" }
+ },
+ {
+ { env.mod}, "Up", function() awful.layout.inc(1) end,
+ { description = "Select next layout", group = "Layouts" }
+ },
+ {
+ { env.mod }, "Down", function() awful.layout.inc(-1) end,
+ { description = "Select previous layout", group = "Layouts" }
+ },
+
+ {
+ {}, "XF86MonBrightnessUp", function() brightness({ step = 2 }) end,
+ { description = "Increase brightness", group = "Brightness control" }
+ },
+ {
+ {}, "XF86MonBrightnessDown", function() brightness({ step = 2, down = true }) end,
+ { description = "Reduce brightness", group = "Brightness control" }
+ },
+
+ {
+ {}, "XF86AudioRaiseVolume", volume_raise,
+ { description = "Increase volume", group = "Volume control" }
+ },
+ {
+ {}, "XF86AudioLowerVolume", volume_lower,
+ { description = "Reduce volume", group = "Volume control" }
+ },
+ {
+ {}, "XF86AudioMute", volume_mute,
+ { description = "Mute audio", group = "Volume control" }
+ },
+
+ {
+ { env.mod }, "a", nil, function() appswitcher:show({ filter = current }) end,
+ { description = "Switch to next with current tag", group = "Application switcher" }
+ },
+ {
+ { env.mod }, "q", nil, function() appswitcher:show({ filter = current, reverse = true }) end,
+ { description = "Switch to previous with current tag", group = "Application switcher" }
+ },
+ {
+ { env.mod, "Shift" }, "a", nil, function() appswitcher:show({ filter = allscr }) end,
+ { description = "Switch to next through all tags", group = "Application switcher" }
+ },
+ {
+ { env.mod, "Shift" }, "q", nil, function() appswitcher:show({ filter = allscr, reverse = true }) end,
+ { description = "Switch to previous through all tags", group = "Application switcher" }
+ },
+
+ {
+ { env.mod }, "Escape", awful.tag.history.restore,
+ { description = "Go previos tag", group = "Tag navigation" }
+ },
+ {
+ { env.mod }, "Right", awful.tag.viewnext,
+ { description = "View next tag", group = "Tag navigation" }
+ },
+ {
+ { env.mod }, "Left", awful.tag.viewprev,
+ { description = "View previous tag", group = "Tag navigation" }
+ },
+
+ {
+ { env.mod }, "t", function() redtitle.toggle(client.focus) end,
+ { description = "Show/hide titlebar for focused client", group = "Titlebar" }
+ },
+ --{
+ -- { env.mod, "Control" }, "t", function() redtitle.switch(client.focus) end,
+ -- { description = "Switch titlebar view for focused client", group = "Titlebar" }
+ --},
+ {
+ { env.mod, "Shift" }, "t", function() redtitle.toggle_all() end,
+ { description = "Show/hide titlebar for all clients", group = "Titlebar" }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "t", function() redtitle.global_switch() end,
+ { description = "Switch titlebar view for all clients", group = "Titlebar" }
+ },
+
+ {
+ { env.mod }, "e", function() redflat.float.player:show(rb_corner()) end,
+ { description = "Show/hide widget", group = "Audio player" }
+ },
+ {
+ {}, "XF86AudioPlay", function() redflat.float.player:action("PlayPause") end,
+ { description = "Play/Pause track", group = "Audio player" }
+ },
+ {
+ {}, "XF86AudioNext", function() redflat.float.player:action("Next") end,
+ { description = "Next track", group = "Audio player" }
+ },
+ {
+ {}, "XF86AudioPrev", function() redflat.float.player:action("Previous") end,
+ { description = "Previous track", group = "Audio player" }
+ },
+
+ {
+ { env.mod, "Control" }, "s", function() for s in screen do env.wallpaper(s) end end,
+ {} -- hidden key
+ },
+ --application hotkeys (logitech keyboard g710+)
+ {
+ { }, "XF86LaunchA", function () awful.spawn(terminal) end,
+ {description = "open a terminal", group = "launcher"}
+ },
+ {
+ { }, "XF86Launch9", function () awful.spawn("keepassxc") end,
+ {description = "open keepass", group = "launcher"}
+ },
+
+ {
+ { }, "XF86Launch8", function () awful.spawn("firefox") end,
+ {description = "open a Firefox", group = "launcher"}
+ },
+
+ {
+ { }, "XF86Launch7", function () awful.spawn("code") end,
+ {description = "open VScode", group = "launcher"}
+ },
+
+ {
+ {env.mod,"Shift"},"o" , function() xrandr.xrandr() end,
+ {description = "xrandr shortcut", group = "screen"}}
+ }
+ -- Client keys
+ --------------------------------------------------------------------------------
+ self.raw.client = {
+ {
+ { env.mod }, "f", function(c) c.fullscreen = not c.fullscreen; c:raise() end,
+ { description = "Toggle fullscreen", group = "Client keys" }
+ },
+ {
+ { env.mod }, "F4", function(c) c:kill() end,
+ { description = "Close", group = "Client keys" }
+ },
+ {
+ { env.mod, "Control" }, "f", awful.client.floating.toggle,
+ { description = "Toggle floating", group = "Client keys" }
+ },
+ {
+ { env.mod, "Control" }, "o", function(c) c.ontop = not c.ontop end,
+ { description = "Toggle keep on top", group = "Client keys" }
+ },
+ {
+ { env.mod }, "n", function(c) c.minimized = true end,
+ { description = "Minimize", group = "Client keys" }
+ },
+ {
+ { env.mod }, "m", function(c) c.maximized = not c.maximized; c:raise() end,
+ { description = "Maximize", group = "Client keys" }
+ },
+ {
+ { env.mod }, "o", function (c) c:move_to_screen() end,
+ {description = "move to screen", group = "client"}
+ },
+ }
+
+ self.keys.root = redflat.util.key.build(self.raw.root)
+ self.keys.client = redflat.util.key.build(self.raw.client)
+
+ -- Numkeys
+ --------------------------------------------------------------------------------
+
+ -- add real keys without description here
+ for i = 1, 9 do
+ self.keys.root = awful.util.table.join(
+ self.keys.root,
+ tag_numkey(i, { env.mod }, function(t) t:view_only() end),
+ tag_numkey(i, { env.mod, "Control" }, function(t) awful.tag.viewtoggle(t) end),
+ client_numkey(i, { env.mod, "Shift" }, function(t) client.focus:move_to_tag(t) end),
+ client_numkey(i, { env.mod, "Control", "Shift" }, function(t) client.focus:toggle_tag(t) end)
+ )
+ end
+
+ -- make fake keys with description special for key helper widget
+ local numkeys = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }
+
+ self.fake.numkeys = {
+ {
+ { env.mod }, "1..9", nil,
+ { description = "Switch to tag", group = "Numeric keys", keyset = numkeys }
+ },
+ {
+ { env.mod, "Control" }, "1..9", nil,
+ { description = "Toggle tag", group = "Numeric keys", keyset = numkeys }
+ },
+ {
+ { env.mod, "Shift" }, "1..9", nil,
+ { description = "Move focused client to tag", group = "Numeric keys", keyset = numkeys }
+ },
+ {
+ { env.mod, "Control", "Shift" }, "1..9", nil,
+ { description = "Toggle focused client on tag", group = "Numeric keys", keyset = numkeys }
+ },
+ }
+
+ -- Hotkeys helper setup
+ --------------------------------------------------------------------------------
+ redflat.float.hotkeys:set_pack("Main", awful.util.table.join(self.raw.root, self.raw.client, self.fake.numkeys), 2)
+
+ -- Mouse buttons
+ --------------------------------------------------------------------------------
+ self.mouse.client = awful.util.table.join(
+ awful.button({}, 1, function (c) client.focus = c; c:raise() end),
+ awful.button({}, 2, awful.mouse.client.move),
+ awful.button({ env.mod }, 3, awful.mouse.client.resize)
+ )
+
+ -- Set root hotkeys
+ --------------------------------------------------------------------------------
+ root.keys(self.keys.root)
+ root.buttons(self.mouse.root)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return hotkeys
diff --git a/awesome/.config/awesome/layout-config.lua b/awesome/.config/awesome/layout-config.lua
new file mode 100644
index 0000000..fd88f6f
--- /dev/null
+++ b/awesome/.config/awesome/layout-config.lua
@@ -0,0 +1,86 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Layouts config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local awful = require("awful")
+local redflat = require("redflat")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local layouts = {}
+
+
+-- Build table
+-----------------------------------------------------------------------------------------------------------------------
+function layouts:init()
+
+ -- layouts list
+ local layset = {
+ awful.layout.suit.floating,
+ redflat.layout.grid,
+ awful.layout.suit.tile,
+ awful.layout.suit.tile.left,
+ awful.layout.suit.tile.bottom,
+ awful.layout.suit.tile.top,
+ awful.layout.suit.fair,
+ redflat.layout.map,
+ awful.layout.suit.max,
+ --awful.layout.suit.max.fullscreen,
+ }
+
+ awful.layout.layouts = layset
+end
+
+-- some advanced layout settings
+redflat.layout.map.notification = false
+
+
+-- connect alternative moving handler to allow using custom handler per layout
+-- by now custom handler provided for 'redflat.layout.grid' only
+-- feel free to remove if you don't use this one
+client.disconnect_signal("request::geometry", awful.layout.move_handler)
+client.connect_signal("request::geometry", redflat.layout.common.mouse.move)
+
+
+-- connect additional signal for 'redflat.layout.map'
+-- this one removing client in smart way and correct tiling scheme
+-- feel free to remove if you want to restore plain queue behavior
+client.connect_signal("unmanage", redflat.layout.map.clean_client)
+
+client.connect_signal("property::minimized", function(c)
+ if c.minimized and redflat.layout.map.check_client(c) then redflat.layout.map.clean_client(c) end
+end)
+client.connect_signal("property::floating", function(c)
+ if c.floating and redflat.layout.map.check_client(c) then redflat.layout.map.clean_client(c) end
+end)
+
+client.connect_signal("untagged", function(c, t)
+ if redflat.layout.map.data[t] then redflat.layout.map.clean_client(c) end
+end)
+
+
+-- user map layout preset
+-- preset can be defined for individual tags, but this should be done after tag initialization
+
+-- redflat.layout.map.base_construct = function(wa)
+-- local tree = { set = {}, active = 1, autoaim = true }
+
+-- tree.set[1] = redflat.layout.map.construct_itempack({}, wa, false)
+-- tree.set[2] = redflat.layout.map.base_set_new_pack({}, wa, true, tree.set[1])
+-- tree.set[3] = redflat.layout.map.base_set_new_pack({}, wa, true, tree.set[1])
+-- tree.set[4] = redflat.layout.map.base_set_new_pack({}, wa, true, tree.set[1])
+
+-- function tree:aim()
+-- for i = 2, 4 do if #self.set[i].items == 0 then return i end end
+-- local active = #self.set[4].items >= #self.set[2].items and 2 or 4
+-- return active
+-- end
+
+-- return tree
+-- end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return layouts
diff --git a/awesome/.config/awesome/menu.lua b/awesome/.config/awesome/menu.lua
new file mode 100644
index 0000000..b313e42
--- /dev/null
+++ b/awesome/.config/awesome/menu.lua
@@ -0,0 +1,96 @@
+local beautiful = require("beautiful")
+local redflat = require("redflat")
+local awful = require("awful")
+local naughty = require("naughty")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local menu = {}
+
+-- Build function
+--------------------------------------------------------------------------------
+function menu:init(args)
+
+ -- vars
+ args = args or {}
+ local env = args.env or {} -- fix this?
+ local separator = args.separator or { widget = redflat.gauge.separator.horizontal() }
+ local theme = args.theme or { auto_hotkey = true }
+ local icon_style = args.icon_style or { custom_only = true, scalable_only = true }
+
+ -- theme vars
+ local default_icon = redflat.util.base.placeholder()
+ local icon = redflat.util.table.check(beautiful, "icon.awesome") and beautiful.icon.awesome or default_icon
+ local color = redflat.util.table.check(beautiful, "color.icon") and beautiful.color.icon or nil
+
+ -- icon finder
+ local function micon(name)
+ return redflat.service.dfparser.lookup_icon(name, icon_style)
+ end
+
+ -- extra commands
+ local ranger_comm = env.terminal .. " -e ranger"
+
+ -- Application submenu
+ ------------------------------------------------------------
+ local appmenu = redflat.service.dfparser.menu({ icons = icon_style, wm_name = "awesome" })
+
+ -- Awesome submenu
+ ------------------------------------------------------------
+ local awesomemenu = {
+ { "Restart", awesome.restart, micon("gnome-session-reboot") },
+ separator,
+ { "Awesome config", env.fm .. " ~/.config/awesome", micon("folder-bookmarks") },
+ }
+
+ -- Places submenu
+ ------------------------------------------------------------
+ local placesmenu = {
+ { "Documents", env.fm .. " Documents", micon("folder-documents") },
+ { "Downloads", env.fm .. " Downloads", micon("folder-download") },
+ { "Music", env.fm .. " Music", micon("folder-music") },
+ { "Pictures", env.fm .. " Pictures", micon("folder-pictures") },
+ { "Videos", env.fm .. " Videos", micon("folder-videos") },
+ separator,
+ { "Media", env.fm .. " /mnt/media", micon("folder-bookmarks") },
+ { "Storage", env.fm .. " /mnt/storage", micon("folder-bookmarks") },
+ }
+
+ -- Exit submenu
+ ------------------------------------------------------------
+ local exitmenu = {
+ { "Reboot", "reboot", micon("gnome-session-reboot") },
+ { "Shutdown", "shutdown now", micon("system-shutdown") },
+ separator,
+ { "Switch user", "dm-tool switch-to-greeter", micon("gnome-session-switch") },
+ { "Suspend", "systemctl suspend" , micon("gnome-session-suspend") },
+ { "Log out", awesome.quit, micon("exit") },
+ }
+
+ -- Main menu
+ ------------------------------------------------------------
+ self.mainmenu = redflat.menu({ theme = theme,
+ items = {
+ { "Awesome", awesomemenu, micon("awesome") },
+ { "Applications", appmenu, micon("distributor-logo") },
+ { "Places", placesmenu, micon("folder_home"), key = "c" },
+ separator,
+ { "Terminal", env.terminal, micon("terminal") },
+ { "Nemo", env.fm, micon("folder"), key = "n" },
+ { "Ranger", ranger_comm, micon("folder"), key = "r" },
+ { "Editor", "emacs", micon("emacs") },
+ separator,
+ { "Exit", exitmenu, micon("exit") },
+ }
+ })
+
+ -- Menu panel widget
+ ------------------------------------------------------------
+
+ self.widget = redflat.gauge.svgbox(icon, nil, color)
+ self.buttons = awful.util.table.join(
+ awful.button({ }, 1, function () self.mainmenu:toggle() end)
+ )
+end
+
+return menu
\ No newline at end of file
diff --git a/awesome/.config/awesome/rc.lua b/awesome/.config/awesome/rc.lua
index 97d5a45..b6c3823 100644
--- a/awesome/.config/awesome/rc.lua
+++ b/awesome/.config/awesome/rc.lua
@@ -1,6 +1,13 @@
-- Standard awesome library
local gears = require("gears")
local awful = require("awful")
+
+-- User modules
+------------------------------------------------------------
+local redflat = require("redflat")
+
+redflat.startup:activate()
+
require("awful.autofocus")
-- Widget and layout library
local wibox = require("wibox")
@@ -8,157 +15,170 @@ local wibox = require("wibox")
local lain = require("lain")
local markup = lain.util.markup
local beautiful = require("beautiful")
---import xrandr library
-local xrandr = require("xrandr")
+
-- Notification library
local naughty = require("naughty")
-local menubar = require("menubar")
---load revelation plugin
-local revelation=require("revelation")
+
--load hotkey_popup
local hotkeys_popup = require("awful.hotkeys_popup").widget
-- Enable hotkeys help widget for VIM and other apps
-- when client with a matching name is opened:
-require("awful.hotkeys_popup.keys")
+
require("hotkeys_popup.termite")
--- {{{ Error handling
--- Check if awesome encountered an error during startup and fell back to
--- another config (This code will only ever execute for the fallback config)
-if awesome.startup_errors then
- naughty.notify({ preset = naughty.config.presets.critical,
- title = "Oops, there were errors during startup!",
- text = awesome.startup_errors })
-end
+-- Error handling
+-----------------------------------------------------------------------------------------------------------------------
+require("ercheck-config") -- load file with error handling
--- Handle runtime errors after startup
-do
- local in_error = false
- awesome.connect_signal("debug::error", function (err)
- -- Make sure we don't go into an endless error loop
- if in_error then return end
- in_error = true
+env=require("env-config")
+env:init()
- naughty.notify({ preset = naughty.config.presets.critical,
- title = "Oops, an error happened!",
- text = tostring(err) })
- in_error = false
- end)
-end
--- }}}
-
--- {{{ Variable definitions
--- Themes define colours, icons, font and wallpapers.
-beautiful.init(awful.util.getdir("config") .. "/themes/default/theme.lua")
-beautiful.useless_gap = 5
-
--- revelation init
-revelation.init()
---
-- This is used later as the default terminal and editor to run.
+awful.util.terminal = env.terminal
-local terminal = "termite"
+local mainmenu=require("menu")
+mainmenu:init({ env = env })
-awful.util.terminal = terminal
+local layouts = require("layout-config") -- load file with tile layouts setup
+layouts:init()
-editor = os.getenv("EDITOR") or "vim"
-editor_cmd = terminal .. " -e " .. editor
--- Default modkey.
--- Usually, Mod4 is the key with a logo between Control and Alt.
--- If you do not like this or do not have such a key,
--- I suggest you to remap Mod4 to another key using xmodmap or other tools.
--- However, you can use another modifier like Mod1, but it may interact with others.
-modkey = "Mod4"
--- Table of layouts to cover with awful.layout.inc, order matters.
-awful.layout.layouts = {
- awful.layout.suit.floating,
- awful.layout.suit.tile,
- awful.layout.suit.tile.left,
- awful.layout.suit.tile.bottom,
- awful.layout.suit.tile.top,
- awful.layout.suit.fair,
- awful.layout.suit.fair.horizontal,
- --awful.layout.suit.spiral,
- --awful.layout.suit.spiral.dwindle,
- --awful.layout.suit.max,
- --awful.layout.suit.max.fullscreen,
- --awful.layout.suit.magnifier,
- awful.layout.suit.corner.nw,
- awful.layout.suit.corner.ne,
- -- awful.layout.suit.corner.sw,
- -- awful.layout.suit.corner.se,
-}
--- }}}
+--mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
+ -- menu = mainmenu })
--- {{{ Helper functions
-local function client_menu_toggle_fn()
- local instance = nil
+ local tasklist = {}
- return function ()
- if instance and instance.wibox.visible then
- instance:hide()
- instance = nil
- else
- instance = awful.menu.clients({ theme = { width = 250 } })
- end
- end
+-- load list of app name aliases from files and set it as part of tasklist theme
+tasklist.style = { appnames = require("alias-config")}
+
+tasklist.buttons = awful.util.table.join(
+ awful.button({}, 1, redflat.widget.tasklist.action.select),
+ awful.button({}, 2, redflat.widget.tasklist.action.close),
+ awful.button({}, 3, redflat.widget.tasklist.action.menu),
+ awful.button({}, 4, redflat.widget.tasklist.action.switch_next),
+ awful.button({}, 5, redflat.widget.tasklist.action.switch_prev)
+)
+
+-- Taglist widget
+--------------------------------------------------------------------------------
+local taglist = {}
+taglist.style = { widget = redflat.gauge.tag.orange.new, show_tip = true }
+taglist.buttons = awful.util.table.join(
+ awful.button({ }, 1, function(t) t:view_only() end),
+ awful.button({ env.mod }, 1, function(t) if client.focus then client.focus:move_to_tag(t) end end),
+ awful.button({ }, 2, awful.tag.viewtoggle),
+ awful.button({ }, 3, function(t) redflat.widget.layoutbox:toggle_menu(t) end),
+ awful.button({ env.mod }, 3, function(t) if client.focus then client.focus:toggle_tag(t) end end),
+ awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
+ awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
+)
+
+-- Textclock widget
+--------------------------------------------------------------------------------
+local textclock = {}
+textclock.widget = redflat.widget.textclock({ timeformat = "%H:%M", dateformat = "%b %d %a" })
+
+
+-- Layoutbox configure
+--------------------------------------------------------------------------------
+local layoutbox = {}
+
+layoutbox.buttons = awful.util.table.join(
+ awful.button({ }, 1, function () mainmenu.mainmenu:toggle() end),
+ awful.button({ }, 3, function () redflat.widget.layoutbox:toggle_menu(mouse.screen.selected_tag) end),
+ awful.button({ }, 4, function () awful.layout.inc( 1) end),
+ awful.button({ }, 5, function () awful.layout.inc(-1) end)
+)
+
+-- Tray widget
+--------------------------------------------------------------------------------
+local tray = {}
+tray.widget = redflat.widget.minitray()
+
+tray.buttons = awful.util.table.join(
+ awful.button({}, 1, function() redflat.widget.minitray:toggle() end)
+)
+
+local volume = {}
+volume.widget = redflat.widget.pulse(nil, { widget = redflat.gauge.audio.blue.new })
+
+-- activate player widget
+redflat.float.player:init({ name = env.player })
+
+volume.buttons = awful.util.table.join(
+ awful.button({}, 4, function() volume.widget:change_volume() end),
+ awful.button({}, 5, function() volume.widget:change_volume({ down = true }) end),
+ awful.button({}, 2, function() volume.widget:mute() end),
+ awful.button({}, 3, function() redflat.float.player:show() end),
+ awful.button({}, 1, function() redflat.float.player:action("PlayPause") end),
+ awful.button({}, 8, function() redflat.float.player:action("Previous") end),
+ awful.button({}, 9, function() redflat.float.player:action("Next") end)
+)
+
+-- Keyboard layout indicator
+--------------------------------------------------------------------------------
+local kbindicator = {}
+redflat.widget.keyboard:init({ "French", "English" })
+kbindicator.widget = redflat.widget.keyboard()
+
+kbindicator.buttons = awful.util.table.join(
+ awful.button({}, 1, function () redflat.widget.keyboard:toggle_menu() end),
+ awful.button({}, 4, function () redflat.widget.keyboard:toggle() end),
+ awful.button({}, 5, function () redflat.widget.keyboard:toggle(true) end)
+)
+
+
+local spr_right = redflat.gauge.separator.vertical()
+
+local sysmon = { widget = {}, buttons = {}, icon = {} }
+
+-- icons
+sysmon.icon.battery = redflat.util.table.check(beautiful, "wicon.battery")
+sysmon.icon.network = redflat.util.table.check(beautiful, "wicon.wireless")
+sysmon.icon.cpuram = redflat.util.table.check(beautiful, "wicon.monitor")
+
+
+-- CPU usage
+sysmon.widget.cpu = redflat.widget.sysmon(
+ { func = redflat.system.pformatted.cpu(80) },
+ { timeout = 2, monitor = { label = "CPU" } }
+)
+
+sysmon.buttons.cpu = awful.util.table.join(
+ awful.button({ }, 1, function() redflat.float.top:show("cpu") end)
+)
+
+-- RAM usage
+sysmon.widget.ram = redflat.widget.sysmon(
+ { func = redflat.system.pformatted.mem(80) },
+ { timeout = 10, monitor = { label = "RAM" } }
+)
+
+sysmon.buttons.ram = awful.util.table.join(
+ awful.button({ }, 1, function() redflat.float.top:show("mem") end)
+)
+-- battery
+local batstate=redflat.system.battery("BAT0")
+if batstate.value ~= nil then
+ sysmon.widget.battery = redflat.widget.sysmon(
+ { func = redflat.system.pformatted.bat(25), arg = "BAT0" },
+ { timeout = 60, widget = redflat.gauge.icon.single, monitor = { is_vertical = true, icon = sysmon.icon.battery } }
+ )
end
--- }}}
+-- network speed
--- {{{ Menu
--- Create a launcher widget and a main menu
-myawesomemenu = {
- { "hotkeys", function() return false, hotkeys_popup.show_help end},
- { "manual", terminal .. " -e man awesome" },
- { "edit config", editor_cmd .. " " .. awesome.conffile },
- { "restart", awesome.restart },
- { "quit", function() awesome.quit() end}
-}
-
-mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
- { "open terminal", terminal }
- }
- })
-
-mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
- menu = mymainmenu })
--- Menubar configuration
-menubar.utils.terminal = terminal -- Set the terminal for applications that require it
--- }}}
-
--- Keyboard map indicator and switcher
-mykeyboardlayout = awful.widget.keyboardlayout()
-
--- {{{ Wibar
--- Create a textclock widget
-mytextclock = wibox.widget.textclock()
-
-local spr_right = wibox.widget.imagebox(beautiful.spr_right)
-local cpuicon = wibox.widget.imagebox(beautiful.cpu_icon,true)
-local cpu = lain.widget.cpu({
- settings = function()
- widget:set_markup(markup.fontfg(beautiful.font,beautiful.fg_normal, cpu_now.usage .. "% "))
- end
-})
-local mymemicon =wibox.widget.imagebox(beautiful.ram_icon)
-local mymem = lain.widget.mem({
- settings = function()
- widget:set_markup(markup.fontfg(beautiful.font,beautiful.fg_normal, mem_now.perc .. "% "))
- end
-})
-
--- Net
-local netdownicon = wibox.widget.imagebox(beautiful.net_down)
-local netdowninfo = wibox.widget.textbox()
-local netupicon = wibox.widget.imagebox(beautiful.net_up)
-local netupinfo = lain.widget.net({
- settings = function()
-
- widget:set_markup(markup.fontfg(beautiful.font, "#e54c62", net_now.sent .. " "))
- netdowninfo:set_markup(markup.fontfg(beautiful.font, "#87af5f", net_now.received .. " "))
- end
-})
+-- use self-drawn rectange image as indicator icon
+local img = redflat.util.base.image(7, 40, { x = 1, y = 0, width = 5, height = 40 })
+local interfaces = "br0"
+local netstate=redflat.system.net_speed("br0",{})
+if netstate[3] == 0 then
+ interfaces = "wlp2s0"
+end
+sysmon.widget.network = redflat.widget.net(
+ { interface = interfaces, speed = { up = 6 * 1024^2, down = 6 * 1024^2 }, autoscale = false },
+ -- custom style
+ { timeout = 2, widget = redflat.gauge.icon.double, monitor = { step = 0.1, icon1 = img, icon2 = img, igap = 3 } }
+)
local mpdicon = wibox.widget.imagebox(beautiful.mpd_icon)
@@ -188,8 +208,7 @@ local mpd = lain.widget.mpd({
end
})
-local baticon = wibox.widget.imagebox(beautiful
-.widget_batt)
+local baticon = wibox.widget.imagebox(beautiful.widget_batt)
local bat = lain.widget.bat({
settings = function()
local perc = bat_now.perc ~= "N/A" and bat_now.perc .. "%" or bat_now.perc
@@ -204,468 +223,101 @@ local bat = lain.widget.bat({
end
})
--- Create a wibox for each screen and add it
-local taglist_buttons = gears.table.join(
- awful.button({ }, 1, function(t) t:view_only() end),
- awful.button({ modkey }, 1, function(t)
- if client.focus then
- client.focus:move_to_tag(t)
- end
- end),
- awful.button({ }, 3, awful.tag.viewtoggle),
- awful.button({ modkey }, 3, function(t)
- if client.focus then
- client.focus:toggle_tag(t)
- end
- end),
- awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
- awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
- )
-local function set_wallpaper(s)
- -- Wallpaper
- if beautiful.wallpaper then
- local wallpaper = beautiful.wallpaper
- -- If wallpaper is a function, call it with the screen
- if type(wallpaper) == "function" then
- wallpaper = wallpaper(s)
- end
- gears.wallpaper.maximized(wallpaper, s, true)
- end
-end
-
--- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
-screen.connect_signal("property::geometry", set_wallpaper)
-
awful.screen.connect_for_each_screen(function(s)
-- Wallpaper
- set_wallpaper(s)
+ env.wallpaper(s)
-- Each screen has its own tag taawful.util.terminable.
- awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[2])
+ awful.tag({ "1", "2", "3", "4","5" }, s, awful.layout.layouts[3])
-
- -- Create a promptbox for each screen
- s.mypromptbox = awful.widget.prompt()
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
-- We need one layoutbox per screen.
- s.mylayoutbox = awful.widget.layoutbox(s)
- s.mylayoutbox:buttons(gears.table.join(
- awful.button({ }, 1, function () awful.layout.inc( 1) end),
- awful.button({ }, 3, function () awful.layout.inc(-1) end),
- awful.button({ }, 4, function () awful.layout.inc( 1) end),
- awful.button({ }, 5, function () awful.layout.inc(-1) end)))
- -- Create a taglist widget
- s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.noempty, taglist_buttons)
+ -- layoutbox widget
+ layoutbox[s] = redflat.widget.layoutbox({ screen = s })
+ -- taglist widget
+ taglist[s] = redflat.widget.taglist({ screen = s, buttons = taglist.buttons, hint = env.tagtip }, taglist.style)
+
+ -- tasklist widget
+ tasklist[s] = redflat.widget.tasklist({ screen = s, buttons = tasklist.buttons }, tasklist.style)
+
-- Create the wibox
- s.mywibox = awful.wibar({ position = "top", screen = s })
+ s.mywibox = awful.wibar({ position = "top", screen = s, height = beautiful.panel_height or 36 })
-- Add widgets to the wibox
s.mywibox:setup {
layout = wibox.layout.align.horizontal,
{ -- Left widgets
layout = wibox.layout.fixed.horizontal,
- mylauncher,
- s.mytaglist,
- s.mypromptbox,
+ env.wrapper(layoutbox[s], "layoutbox", layoutbox.buttons),
+ spr_right,
+ env.wrapper(taglist[s], "taglist"),
+ spr_right,
+ env.wrapper(kbindicator.widget, "keyboard", kbindicator.buttons),
spr_right,
mpdicon,
mpd.widget
},
- nil -- Middle widget
- ,{ -- Right widgets
+ { -- middle widget
+ layout = wibox.layout.align.horizontal,
+ expand = "outside",
+
+ nil,
+ env.wrapper(tasklist[s], "tasklist"),
+ },
+ { -- Right widgets
layout = wibox.layout.fixed.horizontal,
- myredshift_stack,
spr_right,
- netdownicon,
- netdowninfo,
- netupicon,
- netupinfo.widget,
- cpuicon,
- cpu ,
- mymemicon,
- mymem,
+ env.wrapper(sysmon.widget.network, "network"),
+
+ spr_right,
+ env.wrapper(sysmon.widget.cpu, "cpu", sysmon.buttons.cpu),
+ spr_right,
+ env.wrapper(sysmon.widget.ram, "ram", sysmon.buttons.ram),
+ spr_right,
+ env.wrapper(sysmon.widget.battery, "battery"),
+ spr_right,
baticon,
bat,
- mykeyboardlayout,
- wibox.widget.systray(),
- mytextclock,
- s.mylayoutbox,
+ env.wrapper(volume.widget, "volume", volume.buttons),
+ spr_right,
+ env.wrapper(textclock.widget, "textclock"),
+ spr_right,
+ env.wrapper(tray.widget, "tray", tray.buttons),
},
}
end)
--- }}}
--- {{{ Mouse bindings
-root.buttons(gears.table.join(
- awful.button({ }, 3, function () mymainmenu:toggle() end),
- awful.button({ }, 4, awful.tag.viewnext),
- awful.button({ }, 5, awful.tag.viewprev)
-))
--- }}}
--- {{{ Key bindings
-globalkeys = gears.table.join(
- awful.key({ modkey }, "b", function ()
- mouse.screen.mywibox.visible = not mouse.screen.mywibox.visible
- end,{description="toble wibox",group="awesome"}),
- awful.key({ modkey, }, "s", hotkeys_popup.show_help,
- {description="show help", group="awesome"}),
- awful.key({ modkey, }, "e", revelation,
- {description="revelation shortcut",group="awesome"}),
- awful.key({ modkey, }, "Left", awful.tag.viewprev,
- {description = "view previous", group = "tag"}),
- awful.key({ modkey, }, "Right", awful.tag.viewnext,
- {description = "view next", group = "tag"}),
- awful.key({ modkey, }, "Escape", awful.tag.history.restore,
- {description = "go back", group = "tag"}),
- awful.key({ "Shift" }, "Alt_L", function() mykeyboardlayout.next_layout(); end),
- awful.key({ modkey, }, "j",
- function ()
- awful.client.focus.byidx( 1)
- end,
- {description = "focus next by index", group = "client"}
- ),
- awful.key({ modkey, }, "k",
- function ()
- awful.client.focus.byidx(-1)
- end,
- {description = "focus previous by index", group = "client"}
- ),
- awful.key({modkey,"Shift"},"o" , function() xrandr.xrandr() end,
- {description = "xrandr shortcut", group = "awesome"}),
- awful.key({ modkey, }, "w", function () mymainmenu:show() end,
- {description = "show main menu", group = "awesome"}),
-
- -- Layout manipulation
- awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
- {description = "swap with next client by index", group = "client"}),
- awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
- {description = "swap with previous client by index", group = "client"}),
- awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
- {description = "focus the next screen", group = "screen"}),
- awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
- {description = "focus the previous screen", group = "screen"}),
- awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
- {description = "jump to urgent client", group = "client"}),
- awful.key({ modkey, }, "Tab",
- function ()
- awful.client.focus.history.previous()
- if client.focus then
- client.focus:raise()
- end
- end,
- {description = "go back", group = "client"}),
-
- -- Standard program
- -- Dropdown application
- awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
- {description = "open a terminal", group = "launcher"}),
- awful.key({ modkey, "Control" }, "r", awesome.restart,
- {description = "reload awesome", group = "awesome"}),
- awful.key({ modkey, "Shift" }, "q", awesome.quit,
- {description = "quit awesome", group = "awesome"}),
-
- awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
- {description = "increase master width factor", group = "layout"}),
- awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
- {description = "decrease master width factor", group = "layout"}),
- awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
- {description = "increase the number of master clients", group = "layout"}),
- awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
- {description = "decrease the number of master clients", group = "layout"}),
- awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
- {description = "increase the number of columns", group = "layout"}),
- awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
- {description = "decrease the number of columns", group = "layout"}),
- awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
- {description = "select next", group = "layout"}),
- awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
- {description = "select previous", group = "layout"}),
-
- awful.key({ modkey, "Control" }, "n",
- function ()
- local c = awful.client.restore()
- -- Focus restored client
- if c then
- client.focus = c
- c:raise()
- end
- end,
- {description = "restore minimized", group = "client"}),
-
- -- Prompt
- awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
- {description = "run prompt", group = "launcher"}),
-
- awful.key({ modkey }, "x",
- function ()
- awful.prompt.run {
- prompt = "Run Lua code: ",
- textbox = awful.screen.focused().mypromptbox.widget,
- exe_callback = awful.util.eval,
- history_path = awful.util.get_cache_dir() .. "/history_eval"
- }
- end,
- {description = "lua execute prompt", group = "awesome"}),
- -- Menubar
- awful.key({ modkey }, "p", function() menubar.show() end,
- {description = "show the menubar", group = "launcher"}),
- awful.key({ },"XF86AudioRaiseVolume", function() awful.spawn("pamixer -i 5") end),
- awful.key({ }, "XF86AudioLowerVolume", function () awful.spawn("pamixer -d 5") end),
- --multimedia keys
- awful.key({ }, "XF86MonBrightnessUp", function () awful.spawn("light -A 10") end),
- awful.key({ }, "XF86MonBrightnessDown", function () awful.spawn("light -U 10") end),
- awful.key({ }, "XF86AudioMute", function () awful.spawn("pamixer -t") end),
- awful.key({ }, "XF86AudioPlay", function () awful.spawn("mpc toggle") end),
- awful.key({ }, "XF86AudioStop", function () awful.spawn("mpc stop") end),
- awful.key({ }, "XF86AudioNext", function () awful.spawn("mpc next") end),
- awful.key({ }, "XF86AudioPrev", function () awful.spawn("mpc prev") end),
- --application hotkeys (logitech keyboard g710+)
- awful.key({ }, "XF86LaunchA", function () awful.spawn(terminal) end,
- {description = "open a terminal", group = "launcher"}),
- awful.key({ }, "XF86Launch9", function () awful.spawn("keepassxc") end,
- {description = "open keepass", group = "launcher"}),
-
- awful.key({ }, "XF86Launch8", function () awful.spawn("firefox") end,
- {description = "open a Firefox", group = "launcher"}),
-
- awful.key({ }, "XF86Launch7", function () awful.spawn("code") end,
- {description = "open VScode", group = "launcher"})
-)
-
-clientkeys = gears.table.join(
- awful.key({ modkey, }, "f",
- function (c)
- c.fullscreen = not c.fullscreen
- c:raise()
- end,
- {description = "toggle fullscreen", group = "client"}),
- awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
- {description = "close", group = "client"}),
- awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
- {description = "toggle floating", group = "client"}),
- awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
- {description = "move to master", group = "client"}),
- awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
- {description = "move to screen", group = "client"}),
- awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
- {description = "toggle keep on top", group = "client"}),
- awful.key({ modkey, }, "n",
- function (c)
- -- The client currently has the input focus, so it cannot be
- -- minimized, since minimized clients can't have the focus.
- c.minimized = true
- end ,
- {description = "minimize", group = "client"}),
- awful.key({ modkey, }, "m",
- function (c)
- c.maximized = not c.maximized
- c:raise()
- end ,
- {description = "(un)maximize", group = "client"}),
- awful.key({ modkey, "Control" }, "m",
- function (c)
- c.maximized_vertical = not c.maximized_vertical
- c:raise()
- end ,
- {description = "(un)maximize vertically", group = "client"}),
- awful.key({ modkey, "Shift" }, "m",
- function (c)
- c.maximized_horizontal = not c.maximized_horizontal
- c:raise()
- end ,
- {description = "(un)maximize horizontally", group = "client"})
-)
-
--- Bind all key numbers to tags.
--- Be careful: we use keycodes to make it work on any keyboard layout.
--- This should map on the top row of your keyboard, usually 1 to 9.
-for i = 1, 9 do
- globalkeys = gears.table.join(globalkeys,
- -- View tag only.
- awful.key({ modkey }, "#" .. i + 9,
- function ()
- local screen = awful.screen.focused()
- local tag = screen.tags[i]
- if tag then
- tag:view_only()
- end
- end,
- {description = "view tag #"..i, group = "tag"}),
- -- Toggle tag display.
- awful.key({ modkey, "Control" }, "#" .. i + 9,
- function ()
- local screen = awful.screen.focused()
- local tag = screen.tags[i]
- if tag then
- awful.tag.viewtoggle(tag)
- end
- end,
- {description = "toggle tag #" .. i, group = "tag"}),
- -- Move client to tag.
- awful.key({ modkey, "Shift" }, "#" .. i + 9,
- function ()
- if client.focus then
- local tag = client.focus.screen.tags[i]
- if tag then
- client.focus:move_to_tag(tag)
- end
- end
- end,
- {description = "move focused client to tag #"..i, group = "tag"}),
- -- Toggle tag on focused client.
- awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
- function ()
- if client.focus then
- local tag = client.focus.screen.tags[i]
- if tag then
- client.focus:toggle_tag(tag)
- end
- end
- end,
- {description = "toggle focused client on tag #" .. i, group = "tag"})
- )
-end
-
-clientbuttons = gears.table.join(
- awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
- awful.button({ modkey }, 1, awful.mouse.client.move),
- awful.button({ modkey }, 3, awful.mouse.client.resize))
+-- Active screen edges
+-----------------------------------------------------------------------------------------------------------------------
+local edges = require("edges-config") -- load file with edges configuration
+edges:init()
-- Set keys
-root.keys(globalkeys)
--- }}}
+-- }}}
+local hotkeys = require("keys-config") -- load file with hotkeys configuration
+hotkeys:init({ env = env, menu = mainmenu.mainmenu,appkeys={}, volume = volume.widget })
-- {{{ Rules
-- Rules to apply to new clients (through the "manage" signal).
-awful.rules.rules = {
- -- All clients will match this rule.
- { rule = { },
- properties = { border_width = beautiful.border_width,
- border_color = beautiful.border_normal,
- focus = awful.client.focus.filter,
- raise = true,
- keys = clientkeys,
- buttons = clientbuttons,
- screen = awful.screen.preferred,
- placement = awful.placement.no_overlap+awful.placement.no_offscreen
- }
- },
+local rules = require("rules-config") -- load file with rules configuration
+rules:init({ hotkeys = hotkeys})
- -- Floating clients.
- { rule_any = {
- instance = {
- "DTA", -- Firefox addon DownThemAll.
- "copyq", -- Includes session name in class.
- },
- class = {
- "Arandr",
- "Gpick",
- "Kruler",
- "MessageWin", -- kalarm.
- "Sxiv",
- "Wpa_gui",
- "pinentry",
- "veromix",
- "xtightvncviewer",
- "keepassxc",
- },
-
- name = {
- "Calculatrice",
- "Event Tester", -- xev.
- },
- role = {
- "AlarmWindow", -- Thunderbird's calendar.
- "pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
- }
- }, properties = { floating = true,
- ontop=true
- }
- },
-
- -- Add titlebars to normal clients and dialogs
- { rule_any = {type = { "normal", "dialog" }
- }, properties = { titlebars_enabled = true }
- },
-
- -- Set Firefox to always map on the tag named "2" on screen 1.
- -- { rule = { class = "Firefox" },
- -- properties = { screen = 1, tag = "2" } },
-}
--- }}}
+-- Titlebar setup
+-----------------------------------------------------------------------------------------------------------------------
+local titlebar = require("titlebar-config") -- load file with titlebar configuration
+titlebar:init()
-- {{{ Signals
-- Signal function to execute when a new client appears.
-client.connect_signal("manage", function (c)
- -- Set the windows at the slave,
- -- i.e. put it at the end of others instead of setting it master.
- -- if not awesome.startup then awful.client.setslave(c) end
+-- Base signal set for awesome wm
+-----------------------------------------------------------------------------------------------------------------------
+local signals = require("signals-config") -- load file with signals configuration
+signals:init({ env = env })
- if awesome.startup and
- not c.size_hints.user_position
- and not c.size_hints.program_position then
- -- Prevent clients from being unreachable after screen count changes.
- awful.placement.no_offscreen(c)
- end
-end)
-
--- Add a titlebar if titlebars_enabled is set to true in the rules.
-client.connect_signal("request::titlebars", function(c)
- -- buttons for the titlebar
- local buttons = gears.table.join(
- awful.button({ }, 1, function()
- client.focus = c
- c:raise()
- awful.mouse.client.move(c)
- end),
- awful.button({ }, 3, function()
- client.focus = c
- c:raise()
- awful.mouse.client.resize(c)
- end)
- )
-
- awful.titlebar(c) : setup {
- { -- Left
- awful.titlebar.widget.iconwidget(c),
- buttons = buttons,
- layout = wibox.layout.fixed.horizontal
- },
- { -- Middle
- { -- Title
- align = "center",
- widget = awful.titlebar.widget.titlewidget(c)
- },
- buttons = buttons,
- layout = wibox.layout.flex.horizontal
- },
- { -- Right
- awful.titlebar.widget.floatingbutton (c),
- awful.titlebar.widget.maximizedbutton(c),
- awful.titlebar.widget.stickybutton (c),
- awful.titlebar.widget.ontopbutton (c),
- awful.titlebar.widget.closebutton (c),
- layout = wibox.layout.fixed.horizontal()
- },
- layout = wibox.layout.align.horizontal
- }
-end)
-
--- Enable sloppy focus, so that focus follows mouse.
-client.connect_signal("mouse::enter", function(c)
- if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
- and awful.client.focus.filter(c) then
- client.focus = c
- end
-end)
-
-client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
-client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
--- }}}
--
--include autorun file
awful.spawn.with_shell("~/.config/awesome/autorun.sh")
diff --git a/awesome/.config/awesome/redflat/.gitignore b/awesome/.config/awesome/redflat/.gitignore
new file mode 100644
index 0000000..e504a36
--- /dev/null
+++ b/awesome/.config/awesome/redflat/.gitignore
@@ -0,0 +1,2 @@
+# IDE settings
+.idea
\ No newline at end of file
diff --git a/awesome/.config/awesome/redflat/.luacheckrc b/awesome/.config/awesome/redflat/.luacheckrc
new file mode 100644
index 0000000..88eaa72
--- /dev/null
+++ b/awesome/.config/awesome/redflat/.luacheckrc
@@ -0,0 +1,39 @@
+-- Only allow symbols available in all Lua versions
+std = "min"
+
+-- Get rid of "unused argument self" - warnings
+self = false
+
+-- Do not check files outside of config
+exclude_files = {
+ ".luacheckrc", -- this file itself
+}
+
+-- Global objects defined by the C code
+read_globals = {
+ -- awesome API
+ "awesome",
+ "button",
+ "dbus",
+ "drawable",
+ "drawin",
+ "key",
+ "keygrabber",
+ "mousegrabber",
+ "root",
+ "selection",
+ "tag",
+ "window",
+
+ -- lua unpack
+ "table.unpack",
+ "unpack"
+}
+
+-- Not read-only globals.
+globals = {
+ -- awesome API
+ "screen",
+ "mouse",
+ "client",
+}
\ No newline at end of file
diff --git a/awesome/.config/awesome/redflat/desktop/calendar.lua b/awesome/.config/awesome/redflat/desktop/calendar.lua
new file mode 100644
index 0000000..639efc8
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/calendar.lua
@@ -0,0 +1,201 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Red Flat calendar desktop widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Multi monitoring widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local os = os
+local string = string
+local setmetatable = setmetatable
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local calendar = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ show_pointer = true,
+ label = { gap = 12, font = { font = "Sans", size = 18, face = 1, slant = 0 }, sep = "-" },
+ mark = { height = 20, width = 40, dx = 10, line = 4 },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040", bg = "#161616" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.calendar") or {})
+end
+
+local days_in_month = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function is_leap_year(year)
+ return year % 4 == 0 and (year % 100 ~= 0 or year % 400 == 0)
+end
+
+-- Drawing function
+-----------------------------------------------------------------------------------------------------------------------
+local function daymarks(style)
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ widg._data = {
+ gap = 1,
+ label_x = 0,
+ pointer = { show = false, index = 1, label = "01-01" },
+ days = 31,
+ marks = 31,
+ today = 1,
+ label = "01-01",
+ weekend = { 6, 0 }
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:update_data()
+ local date = os.date('*t')
+ local first_week_day = os.date('%w', os.time({ year = date.year, month = date.month, day = 1 }))
+
+ self._data.today = date.day
+ self._data.days = date.month == 2 and is_leap_year(date.year) and 29 or days_in_month[date.month]
+ self._data.weekend = { (7 - first_week_day) % 7, (8 - first_week_day) % 7 }
+ self._data.label = string.format("%.2d%s%.2d", date.day, style.label.sep, date.month)
+
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:update_pointer(show, index)
+ self._data.pointer.show = show
+ if index then self._data.pointer.index = index end
+
+ local date = os.date('*t')
+ self._data.pointer.label = string.format("%.2d%s%.2d", self._data.pointer.index, style.label.sep, date.month)
+
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ -- main draw
+ self._data.gap = (height - self._data.days * style.mark.height) / (self._data.days - 1)
+ self._data.label_x = width - style.mark.width - style.mark.dx - style.label.gap
+ cr:set_line_width(style.mark.line)
+
+ for i = 1, self._data.days do
+ -- calendar marks
+ local id = i % 7
+ local is_weekend = id == self._data.weekend[1] or id == self._data.weekend[2]
+
+ cr:set_source(color(is_weekend and style.color.main or style.color.gray))
+ cr:move_to(width, (style.mark.height + self._data.gap) * (i - 1))
+ cr:rel_line_to(0, style.mark.height)
+ cr:rel_line_to(-style.mark.width, 0)
+ cr:rel_line_to(-style.mark.dx, -style.mark.height / 2)
+ cr:rel_line_to(style.mark.dx, -style.mark.height / 2)
+ cr:close_path()
+ cr:fill()
+
+ -- data label
+ if i == self._data.today or (self._data.pointer.show and i == self._data.pointer.index) then
+ cr:set_source(color(i == self._data.today and style.color.main or style.color.gray))
+ local coord_y = ((style.mark.height + self._data.gap) * (i - 1)) + style.mark.height / 2
+ redutil.cairo.set_font(cr, style.label.font)
+
+ local ext = cr:text_extents(self._data.label)
+ cr:move_to(
+ self._data.label_x - (ext.width + 2 * ext.x_bearing), coord_y - (ext.height/2 + ext.y_bearing)
+ )
+ cr:show_text(i == self._data.today and self._data.label or self._data.pointer.label)
+ end
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+
+-- Create a new widget
+-----------------------------------------------------------------------------------------------------------------------
+function calendar.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ args = args or {}
+ style = redutil.table.merge(default_style(), style or {})
+ local timeout = args.timeout or 300
+
+ dwidget.style = style
+
+ -- Create calendar widget
+ --------------------------------------------------------------------------------
+ dwidget.calendar = daymarks(style)
+ dwidget.area = wibox.container.margin(dwidget.calendar)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = timeout })
+ t:connect_signal("timeout", function () dwidget.calendar:update_data() end)
+ t:start()
+ t:emit_signal("timeout")
+
+ -- Drawing date label under mouse
+ --------------------------------------------------------------------------------
+ function dwidget:activate_wibox(wbox)
+ if style.show_pointer then
+ wbox:connect_signal("mouse::move", function(_, x, y)
+ local show_poiter = false
+ local index
+
+ if x > self.calendar._data.label_x then
+ for i = 1, self.calendar._data.days do
+ local cy = y - (i - 1) * (self.calendar._data.gap + style.mark.height)
+ if cy > 0 and cy < style.mark.height then
+ show_poiter = true
+ index = i
+ break
+ end
+ end
+ end
+
+ if self.calendar._data.pointer.show ~= show_poiter then
+ self.calendar:update_pointer(show_poiter, index)
+ end
+ end)
+
+ wbox:connect_signal("mouse::leave", function()
+ if self.calendar._data.pointer.show then self.calendar:update_pointer(false) end
+ end)
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function calendar.mt:__call(...)
+ return calendar.new(...)
+end
+
+return setmetatable(calendar, calendar.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/bar/init.lua b/awesome/.config/awesome/redflat/desktop/common/bar/init.lua
new file mode 100644
index 0000000..e90fe55
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/bar/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.desktop.common.bar" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/desktop/common/bar/plain.lua b/awesome/.config/awesome/redflat/desktop/common/bar/plain.lua
new file mode 100644
index 0000000..03d0091
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/bar/plain.lua
@@ -0,0 +1,114 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat desktop progressbar widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Dashed horizontal progress bar
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local progressbar = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ maxm = 1,
+ width = nil,
+ height = nil,
+ chunk = { gap = 5, width = 5 },
+ autoscale = false,
+ color = { main = "#b1222b", gray = "#404040" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.common.bar.plain") or {})
+end
+
+-- Cairo drawing functions
+-----------------------------------------------------------------------------------------------------------------------
+
+local function draw_progressbar(cr, width, height, gap, first_point, last_point, fill_color)
+ cr:set_source(color(fill_color))
+ for i = first_point, last_point do
+ cr:rectangle((i - 1) * (width + gap), 0, width, height)
+ end
+ cr:fill()
+end
+
+-- Create a new progressbar widget
+-- @param style.chunk Table containing dash parameters
+-- @param style.color.main Main color
+-- @param style.width Widget width (optional)
+-- @param style.height Widget height (optional)
+-- @param style.autoscale Scaling received values, true by default
+-- @param style.maxm Scaling value if autoscale = false
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local maxm = style.maxm
+
+ --style aliases
+ local stg, stw = style.chunk.gap, style.chunk.width
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { value = 0, chunks = 1, gap = 1, cnum = 0 }
+
+ function widg:set_value(x)
+ if style.autoscale then
+ if x > maxm then maxm = x end
+ end
+
+ local cx = x / maxm
+ if cx > 1 then cx = 1 end
+
+ self._data.value = cx
+ local num = math.ceil(self._data.chunks * self._data.value)
+
+ if num ~= self._data.cnum then
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:fit(_, width, height)
+ local w = style.width and math.min(style.width, width) or width
+ local h = style.height and math.min(style.height, height) or height
+ return w, h
+ end
+
+ -- Draw function
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ -- progressbar
+ self._data.chunks = math.floor((width + stg) / (stw + stg))
+ self._data.gap = stg + (width - (self._data.chunks - 1) * (stw + stg) - stw) / (self._data.chunks - 1)
+ self._data.cnum = math.ceil(self._data.chunks * self._data.value)
+
+ draw_progressbar(cr, stw, height, self._data.gap, 1, self._data.cnum, style.color.main)
+ draw_progressbar(cr, stw, height, self._data.gap, self._data.cnum + 1, self._data.chunks, style.color.gray)
+ end
+ --------------------------------------------------------------------------------
+
+ return widg
+end
+
+-- Config metatable to call progressbar module as function
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.mt:__call(...)
+ return progressbar.new(...)
+end
+
+return setmetatable(progressbar, progressbar.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/bar/shaped.lua b/awesome/.config/awesome/redflat/desktop/common/bar/shaped.lua
new file mode 100644
index 0000000..672b5a0
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/bar/shaped.lua
@@ -0,0 +1,144 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat corners widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Vertical progress indicator with custom shape
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local tooltip = require("redflat.float.tooltip")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local progressbar = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ chunk = { num = 10, line = 5, height = 10 },
+ maxm = 1,
+ width = nil,
+ height = nil,
+ autoscale = false,
+ show = { tooltip = false },
+ tooltip = {},
+ shape = "corner",
+ color = { main = "#b1222b", gray = "#404040" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.common.bar.shaped") or {})
+end
+
+-- Cairo drawing functions
+-----------------------------------------------------------------------------------------------------------------------
+
+local function draw_corner(cr, width, height, gap, first_point, last_point, fill_color, style)
+ cr:set_source(color(fill_color))
+ for i = first_point, last_point do
+ cr:move_to(0, height - (i - 1) * (style.chunk.line + gap))
+ cr:rel_line_to(width / 2, - style.chunk.height)
+ cr:rel_line_to(width / 2, style.chunk.height)
+ cr:rel_line_to(- style.chunk.line, 0)
+ cr:rel_line_to(- width / 2 + style.chunk.line, - style.chunk.height + style.chunk.line)
+ cr:rel_line_to(- width / 2 + style.chunk.line, style.chunk.height - style.chunk.line)
+ cr:close_path()
+ end
+ cr:fill()
+end
+
+local function draw_line(cr, width, height, dy, first_point, last_point, fill_color, style)
+ cr:set_source(color(fill_color))
+ for i = first_point, last_point do
+ cr:rectangle(0, height - (i - 1) * dy, width, - style.chunk.line)
+ end
+ cr:fill()
+end
+
+-- Create a new progressbar widget
+-- @param style.chunk Table containing number and sizes for progress bar chunks
+-- @param style.color Main color
+-- @param style.width Widget width (optional)
+-- @param style.height Widget height (optional)
+-- @param style.autoscale Scaling received values, true by default
+-- @param style.maxm Scaling value if autoscale = false
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local maxm = style.maxm
+
+ --style aliases
+ local stn = style.chunk.num
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local shapewidg = wibox.widget.base.make_widget()
+ shapewidg._data = { value = 0, cnum = 0 }
+
+ -- tooltip
+ if style.show.tooltip then
+ shapewidg._tp = tooltip({ objects = { shapewidg } }, style.tooltip)
+ end
+
+ -- setup
+ function shapewidg:set_value(x)
+ if style.autoscale then
+ if x > maxm then maxm = x end
+ end
+
+ local cx = x / maxm
+ if cx > 1 then cx = 1 end
+
+ self._data.value = cx
+ local num = math.ceil(stn * self._data.value)
+
+ if num ~= self._data.cnum then
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function shapewidg:set_tip(txt)
+ if self._tp then self._tp:set_text(txt) end
+ end
+
+ function shapewidg:fit(_, width, height)
+ return style.width or width, style.height or height
+ end
+
+ -- Draw function
+ ------------------------------------------------------------
+ function shapewidg:draw(_, cr, width, height)
+ self._data.cnum = math.ceil(stn * self._data.value)
+
+ if style.shape == "plain" then
+ local line_gap = style.chunk.line + (height - style.chunk.line * stn)/(stn - 1)
+ draw_line(cr, width, height, line_gap, 1, self._data.cnum, style.color.main, style)
+ draw_line(cr, width, height, line_gap, self._data.cnum + 1, stn, style.color.gray, style)
+ elseif style.shape == "corner" then
+ local corner_gap = (height - (stn - 1) * style.chunk.line - style.chunk.height) / (stn - 1)
+ draw_corner(cr, width, height, corner_gap, 1, self._data.cnum, style.color.main, style)
+ draw_corner(cr, width, height, corner_gap, self._data.cnum + 1, stn, style.color.gray, style)
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return shapewidg
+end
+
+-- Config metatable to call progressbar module as function
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.mt:__call(...)
+ return progressbar.new(...)
+end
+
+return setmetatable(progressbar, progressbar.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/chart.lua b/awesome/.config/awesome/redflat/desktop/common/chart.lua
new file mode 100644
index 0000000..79bb1d8
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/chart.lua
@@ -0,0 +1,121 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat chart widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- History graph for desktop widgets
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local table = table
+local ipairs = ipairs
+local math = math
+local wibox = require("wibox")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local chart = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ maxm = 1,
+ color = "#404040",
+ width = nil,
+ height = nil,
+ zero_height = 4,
+ bar = { gap = 5, width = 5 },
+ autoscale = true
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.common.chart") or {})
+end
+
+-- Create a new chart widget
+-- @param style Table containing chart geometry and style
+-- See block of local vars below for more details
+-----------------------------------------------------------------------------------------------------------------------
+function chart.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local count = 0
+ local barnum
+ local current_maxm = style.maxm
+
+ -- updating values
+ local data = {
+ values = {}
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local chartwidg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function chartwidg:set_value(x)
+ if barnum then
+ count = count % barnum + 1
+ data.values[count] = x
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit function
+ ------------------------------------------------------------
+ function chartwidg:fit(_, width, height)
+ return style.width or width, style.height or height
+ end
+
+ -- Draw function
+ ------------------------------------------------------------
+ function chartwidg:draw(_, cr, width, height)
+
+ --scale
+ if style.autoscale then
+ current_maxm = style.maxm
+
+ for _, v in ipairs(data.values) do
+ if v > current_maxm then current_maxm = v end
+ end
+ end
+
+ -- chart
+ barnum = math.floor((width + style.bar.gap) / (style.bar.width + style.bar.gap))
+ while #data.values < barnum do
+ table.insert(data.values, 0)
+ end
+ local real_gap = style.bar.gap + (width - (barnum - 1) * (style.bar.width + style.bar.gap)
+ - style.bar.width) / (barnum - 1)
+
+ cr:set_source(color(style.color))
+ for i = 0, barnum - 1 do
+ local n = (count + i) % barnum + 1
+ local k = data.values[n] / current_maxm
+ if k > 1 then k = 1 end
+ local bar_height = - k * (height - style.zero_height)
+ cr:rectangle(i * (style.bar.width + real_gap), height, style.bar.width, - style.zero_height)
+ cr:rectangle(i * (style.bar.width + real_gap), height - style.zero_height, style.bar.width, bar_height)
+ end
+
+ cr:fill()
+ end
+
+ --------------------------------------------------------------------------------
+ return chartwidg
+end
+
+-- Config metatable to call chart module as function
+-----------------------------------------------------------------------------------------------------------------------
+function chart.mt:__call(...)
+ return chart.new(...)
+end
+
+return setmetatable(chart, chart.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/init.lua b/awesome/.config/awesome/redflat/desktop/common/init.lua
new file mode 100644
index 0000000..c982503
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.desktop.common" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/desktop/common/pack/init.lua b/awesome/.config/awesome/redflat/desktop/common/pack/init.lua
new file mode 100644
index 0000000..26e3e72
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/pack/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.desktop.common.pack" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/desktop/common/pack/lines.lua b/awesome/.config/awesome/redflat/desktop/common/pack/lines.lua
new file mode 100644
index 0000000..792ae81
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/pack/lines.lua
@@ -0,0 +1,137 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat barpack widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Group of indicators with progressbar, label and text in every line
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local dcommon = require("redflat.desktop.common")
+local tooltip = require("redflat.float.tooltip")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local barpack = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ label = {},
+ text = {},
+ show = { text = true, label = true, tooltip = false },
+ progressbar = {},
+ line = { height = 20 },
+ gap = { text = 20, label = 20 },
+ tooltip = {},
+ color = {}
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.common.pack.lines") or {})
+end
+
+
+-- Create a new barpack widget
+-----------------------------------------------------------------------------------------------------------------------
+function barpack.new(num, style)
+
+ local pack = {}
+ style = redutil.table.merge(default_style(), style or {})
+ local progressbar_style = redutil.table.merge(style.progressbar, { color = style.color })
+ local label_style = redutil.table.merge(style.label, { color = style.color.gray })
+ local text_style = redutil.table.merge(style.text, { color = style.color.gray })
+
+ -- Construct group of lines
+ --------------------------------------------------------------------------------
+ pack.layout = wibox.layout.align.vertical()
+ local flex_vertical = wibox.layout.flex.vertical()
+ local lines = {}
+
+ for i = 1, num do
+ lines[i] = {}
+
+ -- bar
+ local line_align = wibox.layout.align.horizontal()
+ line_align:set_forced_height(style.line.height)
+ lines[i].bar = dcommon.bar.plain(progressbar_style)
+ line_align:set_middle(lines[i].bar)
+
+ -- label
+ lines[i]._label_txt = ""
+ lines[i].label = dcommon.textbox("", label_style)
+ lines[i].label:set_width(0)
+ lines[i].label_margin = wibox.container.margin(lines[i].label)
+ line_align:set_left(lines[i].label_margin)
+
+ -- value text
+ lines[i].text = dcommon.textbox("", text_style)
+ lines[i].text:set_width(0)
+ lines[i].text_margin = wibox.container.margin(lines[i].text)
+ line_align:set_right(lines[i].text_margin)
+
+ -- tooltip
+ if style.show.tooltip then
+ lines[i].tooltip = tooltip({ objects = { line_align } }, style.tooltip)
+ end
+
+ if i == 1 then
+ pack.layout:set_top(line_align)
+ else
+ local line_space = wibox.layout.align.vertical()
+ line_space:set_bottom(line_align)
+ flex_vertical:add(line_space)
+ end
+ end
+ pack.layout:set_middle(flex_vertical)
+
+ -- Setup functions
+ --------------------------------------------------------------------------------
+
+ function pack:set_values(value, index)
+ lines[index].bar:set_value(value)
+ end
+
+ function pack:set_text(value, index)
+ if style.show.text then
+ lines[index].text:set_text(value)
+ lines[index].text:set_width(value and text_style.width or 0)
+ lines[index].text_margin:set_left(value and style.gap.text or 0)
+ end
+
+ if lines[index].tooltip then
+ lines[index].tooltip:set_text(string.format("%s %s", lines[index]._label_txt, value))
+ end
+ end
+
+ function pack:set_text_color(value, index)
+ lines[index].text:set_color(value)
+ end
+
+ function pack:set_label_color(value, index)
+ lines[index].label:set_color(value)
+ end
+
+ function pack:set_label(value, index)
+ lines[index]._label_txt = value
+ if style.show.label then
+ lines[index].label:set_text(value)
+ lines[index].label:set_width(value and label_style.width or 0)
+ lines[index].label_margin:set_right(value and style.gap.label or 0)
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return pack
+end
+
+-- Config metatable to call barpack module as function
+-----------------------------------------------------------------------------------------------------------------------
+function barpack.mt:__call(...)
+ return barpack.new(...)
+end
+
+return setmetatable(barpack, barpack.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/pack/upright.lua b/awesome/.config/awesome/redflat/desktop/common/pack/upright.lua
new file mode 100644
index 0000000..784b801
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/pack/upright.lua
@@ -0,0 +1,72 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat ber pack widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Group of upright indicators placed in horizontal layout
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+
+local wibox = require("wibox")
+--local beautiful = require("beautiful")
+
+local progressbar = require("redflat.desktop.common.bar.shaped")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local barpack = { mt = {} }
+
+-- Create a new barpack widget
+-- @param num Number of indicators
+-- @param style Style variables for redflat shaped progressbar widget
+-----------------------------------------------------------------------------------------------------------------------
+function barpack.new(num, style)
+
+ local pack = {}
+ style = style or {}
+
+ -- construct group of bar indicators
+ pack.layout = wibox.layout.align.horizontal()
+ local flex_horizontal = wibox.layout.flex.horizontal()
+ local crn = {}
+
+ for i = 1, num do
+ crn[i] = progressbar(style)
+ if i == 1 then
+ pack.layout:set_left(crn[i])
+ else
+ local bar_space = wibox.layout.align.horizontal()
+ bar_space:set_right(crn[i])
+ flex_horizontal:add(bar_space)
+ end
+ end
+ pack.layout:set_middle(flex_horizontal)
+
+ -- setup functions
+ function pack:set_values(values, n, tip)
+ if n then
+ if crn[n] then
+ crn[n]:set_value(values)
+ if tip then crn[n]:set_tip(tip) end
+ end
+ else
+ for i, v in ipairs(values) do
+ if crn[i] then
+ crn[i]:set_value(v)
+ if tip then crn[n]:set_tip(tip) end
+ end
+ end
+ end
+ end
+
+ return pack
+end
+
+-- Config metatable to call barpack module as function
+-----------------------------------------------------------------------------------------------------------------------
+function barpack.mt:__call(...)
+ return barpack.new(...)
+end
+
+return setmetatable(barpack, barpack.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/common/textbox.lua b/awesome/.config/awesome/redflat/desktop/common/textbox.lua
new file mode 100644
index 0000000..866dc64
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/common/textbox.lua
@@ -0,0 +1,158 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat textbox widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom textbox for desktop widgets
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local wibox = require("wibox")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local textbox = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = nil,
+ height = nil,
+ draw = "by_left",
+ separator = '%s',
+ color = "#404040",
+ font = { font = "Sans", size = 20, face = 0, slant = 0 }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.common.textbox") or {})
+end
+
+-- Text alignment functions
+-----------------------------------------------------------------------------------------------------------------------
+local align = {}
+
+function align.by_left(cr, _, _, text)
+ local ext = cr:text_extents(text)
+ --cr:move_to(0, height)
+ cr:move_to(0, ext.height)
+ cr:show_text(text)
+end
+
+function align.by_right(cr, width, _, text)
+ local ext = cr:text_extents(text)
+ --cr:move_to(width - (ext.width + ext.x_bearing), height)
+ cr:move_to(width - (ext.width + ext.x_bearing), ext.height)
+ cr:show_text(text)
+end
+
+function align.by_edges(cr, width, height, text, style)
+ local left_text, right_text = string.match(text, "(.+)" .. style.separator .. "(.+)")
+ if left_text and right_text then
+ align.by_left(cr, width, height, left_text)
+ align.by_right(cr, width, height, right_text)
+ else
+ align.by_right(cr, width, height, text)
+ end
+end
+
+function align.by_width(cr, width, _, text)
+ local ext = cr:text_extents(text)
+ local text_gap = (width - ext.width - ext.x_bearing)/(#text - 1)
+ local gap = 0
+
+ for i = 1, #text do
+ local c = string.sub(text, i, i)
+ --cr:move_to(gap, height)
+ cr:move_to(gap, ext.height)
+ cr:show_text(c)
+
+ local c_ext = cr:text_extents(c)
+ gap = gap + text_gap + c_ext.width + c_ext.x_bearing
+ -- !!! WORKAROUND for space character width only for font size = 24 font = "Play bold" !!!
+ --if c == " " then
+ -- gap = gap + 6
+ --end
+ end
+end
+
+-- Create a new textbox widget
+-- @param txt Text to display
+-- @param style.text Table containing font parameters
+-- @param style.color Font color
+-- @param style.draw Text align method
+-- @param style.width Widget width (optional)
+-- @param style.height Widget height (optional)
+-----------------------------------------------------------------------------------------------------------------------
+function textbox.new(txt, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+-- local textdraw = align[style.draw] or align.by_left
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local textwidg = wibox.widget.base.make_widget()
+ textwidg._data = {
+ text = txt or "",
+ width = style.width,
+ color = style.color
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function textwidg:set_text(text)
+ if self._data.text ~= text then
+ self._data.text = text
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function textwidg:set_color(value)
+ if self._data.color ~= value then
+ self._data.color = value
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function textwidg:set_width(width)
+ if self._data.width ~= width then
+ self._data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function textwidg:fit(_, width, height)
+ local w = self._data.width and math.min(self._data.width, width) or width
+ local h = style.height and math.min(style.height, height) or height
+ return w, h
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function textwidg:draw(_, cr, width, height)
+ cr:set_source(color(self._data.color))
+ redutil.cairo.set_font(cr, style.font)
+
+ align[style.draw](cr, width, height, self._data.text, style)
+ end
+
+ --------------------------------------------------------------------------------
+ return textwidg
+end
+
+-- Config metatable to call textbox module as function
+-----------------------------------------------------------------------------------------------------------------------
+function textbox.mt:__call(...)
+ return textbox.new(...)
+end
+
+return setmetatable(textbox, textbox.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/init.lua b/awesome/.config/awesome/redflat/desktop/init.lua
new file mode 100644
index 0000000..82f61a3
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.desktop" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/desktop/multiline.lua b/awesome/.config/awesome/redflat/desktop/multiline.lua
new file mode 100644
index 0000000..3a0627f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/multiline.lua
@@ -0,0 +1,136 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat dashpack desktop widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Multi monitoring widget
+-- Several lines with progressbar, label and text
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local string = string
+local unpack = unpack or table.unpack
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local lines = require("redflat.desktop.common.pack.lines")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local dashpack = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = { image = nil, margin = { 0, 0, 0, 0 } },
+ lines = {},
+ margin = { 0, 0, 0, 0 },
+ digits = 3,
+ dislabel = "OFF",
+ unit = { { "B", -1 }, { "KB", 1024 }, { "MB", 1024^2 }, { "GB", 1024^3 } },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.multiline") or {})
+end
+
+local default_args = { timeout = 60, sensors = {} }
+
+-- Create a new widget
+-----------------------------------------------------------------------------------------------------------------------
+function dashpack.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ args = redutil.table.merge(default_args, args or {})
+ style = redutil.table.merge(default_style(), style or {})
+ local alert_data = { counter = 0, state = false }
+
+ dwidget.style = style
+
+ -- initialize progressbar lines
+ local lines_style = redutil.table.merge(style.lines, { color = style.color })
+ local pack = lines(#args.sensors, lines_style)
+
+ -- add icon if needed
+ if style.icon.image then
+ dwidget.icon = svgbox(style.icon.image)
+ dwidget.icon:set_color(style.color.gray)
+
+ dwidget.area = wibox.layout.align.horizontal()
+ dwidget.area:set_middle(wibox.container.margin(pack.layout, unpack(style.margin)))
+ dwidget.area:set_left(wibox.container.margin(dwidget.icon, unpack(style.icon.margin)))
+ else
+ dwidget.area = wibox.container.margin(pack.layout, unpack(style.margin))
+ end
+
+ for i, sensor in ipairs(args.sensors) do
+ if sensor.name then pack:set_label(string.upper(sensor.name), i) end
+ end
+
+ -- Update info function
+ --------------------------------------------------------------------------------
+ local function set_raw_state(state, maxm, crit, i)
+ local alert = crit and state[1] > crit
+ local text_color = alert and style.color.main or style.color.gray
+
+ pack:set_values(state[1] / maxm, i)
+ pack:set_label_color(text_color, i)
+
+ if style.lines.show.text or style.lines.show.tooltip then
+ local txt = state.off and style.dislabel
+ or redutil.text.dformat(state[2] or state[1], style.unit, style.digits)
+ pack:set_text(txt, i)
+ pack:set_text_color(text_color, i)
+ end
+
+ if style.icon.image then
+ alert_data.counter = alert_data.counter + 1
+ alert_data.state = alert_data.state or alert
+ if alert_data.counter == #args.sensors then
+ dwidget.icon:set_color(alert_data.state and style.color.main or style.color.gray)
+ end
+ end
+ end
+
+ local function line_hadnler(maxm, crit, i)
+ return function(state) set_raw_state(state, maxm, crit, i) end
+ end
+
+ local function update()
+ alert_data = { counter = 0, state = false }
+ --if style.icon.image then dwidget.icon:set_color(style.color.gray) end
+ for i, sens in ipairs(args.sensors) do
+ local maxm, crit = sens.maxm, sens.crit
+ if sens.meter_function then
+ local state = sens.meter_function(sens.args)
+ set_raw_state(state, maxm, crit, i)
+ else
+ sens.async_function(line_hadnler(maxm, crit, i))
+ end
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = args.timeout })
+ t:connect_signal("timeout", update)
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function dashpack.mt:__call(...)
+ return dashpack.new(...)
+end
+
+return setmetatable(dashpack, dashpack.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/multimeter.lua b/awesome/.config/awesome/redflat/desktop/multimeter.lua
new file mode 100644
index 0000000..80de75f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/multimeter.lua
@@ -0,0 +1,167 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat multi monitoring deskotp widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Multi monitoring widget
+-- Pack of vertical indicators and two lines with labeled progressbar
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+--local awful = require("awful")
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+local unpack = unpack or table.unpack
+
+local dcommon = require("redflat.desktop.common")
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local multim = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ lines = {},
+ upbar = { width = 40 },
+ digits = 3,
+ height = { upright = 100, lines = 60 },
+ icon = { image = nil, margin = { 0, 20, 0, 0 }, full = false },
+ labels = {},
+ unit = { { "MB", - 1 }, { "GB", 1024 } },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.multimeter") or {})
+end
+
+local default_args = {
+ topbars = { num = 1, maxm = 1},
+ lines = { maxm = 1 },
+ meter = {},
+ timeout = 60,
+}
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function set_info(value, args, upright, lines, icon, last, style)
+ local upright_alert = value.alert
+
+ -- set progressbar values and color
+ for i, line in ipairs(args.lines) do
+ lines:set_values(value.lines[i][1] / line.maxm, i)
+ lines:set_text(redutil.text.dformat(value.lines[i][2], line.unit or style.unit, style.digits), i)
+
+ if line.crit then
+ local cc = value.lines[i][1] > line.crit and style.color.main or style.color.gray
+ lines:set_text_color(cc, i)
+ if style.labels[i] then lines:set_label_color(cc, i) end
+ end
+ end
+
+ -- set upright value
+ for i = 1, args.topbars.num do
+ local v = value.bars[i] and value.bars[i].value or 0
+ local tip = value.bars[i] and value.bars[i].text or nil
+ upright:set_values(v / args.topbars.maxm, i, tip)
+ if args.topbars.crit then upright_alert = upright_alert or v > args.topbars.crit end
+ end
+
+ -- colorize icon if needed
+ if style.icon.image and upright_alert ~= last.alert then
+ icon:set_color(upright_alert and style.color.main or style.color.gray)
+ last.alert = upright_alert
+ end
+end
+
+
+-- Create a new widget
+-----------------------------------------------------------------------------------------------------------------------
+function multim.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ local icon
+ local last = { alert = false }
+
+ args = redutil.table.merge(default_args, args or {})
+ --local geometry = redutil.table.merge(default_geometry, geometry or {})
+ style = redutil.table.merge(default_style(), style or {})
+
+ local lines_style = redutil.table.merge(style.lines, { progressbar = { color = style.color } })
+ local upbar_style = redutil.table.merge(style.upbar, { color = style.color })
+
+ dwidget.style = style
+
+ -- Construct layouts
+ --------------------------------------------------------------------------------
+ local lines = dcommon.pack.lines(#args.lines, lines_style)
+ local upright = dcommon.pack.upright(args.topbars.num, upbar_style)
+ lines.layout:set_forced_height(style.height.lines)
+
+ if style.icon.image then
+ icon = svgbox(style.icon.image)
+ icon:set_color(style.color.gray)
+ end
+
+ dwidget.area = wibox.widget({
+ {
+ icon and not style.icon.full and wibox.container.margin(icon, unpack(style.icon.margin)),
+ upright.layout,
+ nil,
+ forced_height = style.height.upright,
+ layout = wibox.layout.align.horizontal
+ },
+ nil,
+ lines.layout,
+ layout = wibox.layout.align.vertical
+ })
+
+ if icon and style.icon.full then
+ dwidget.area = wibox.widget({
+ wibox.container.margin(icon, unpack(style.icon.margin)),
+ dwidget.area,
+ nil,
+ layout = wibox.layout.align.horizontal
+ })
+ end
+
+ for i, label in ipairs(style.labels) do
+ lines:set_label(label, i)
+ end
+
+ -- Update info function
+ --------------------------------------------------------------------------------
+ local function raw_set(state)
+ set_info(state, args, upright, lines, icon, last, style)
+ end
+
+ local function update_plain()
+ local state = args.meter.func(args.meter.args)
+ set_info(state, args, upright, lines, icon, last, style)
+ end
+
+ local update = args.meter.async and function() args.meter.async(raw_set, args.meter.args) end or update_plain
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = args.timeout })
+ t:connect_signal("timeout", update)
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function multim.mt:__call(...)
+ return multim.new(...)
+end
+
+return setmetatable(multim, multim.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/singleline.lua b/awesome/.config/awesome/redflat/desktop/singleline.lua
new file mode 100644
index 0000000..7af6a34
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/singleline.lua
@@ -0,0 +1,138 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat simple line desktop widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Multi monitoring widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local string = string
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local textbox = require("redflat.desktop.common.textbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local sline = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ lbox = { draw = "by_left", width = 50 },
+ rbox = { draw = "by_right", width = 50 },
+ digits = 3,
+ icon = nil,
+ iwidth = 120,
+ unit = { { "B", -1 }, { "KB", 1024 }, { "MB", 1024^2 }, { "GB", 1024^3 } },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.singleline") or {})
+end
+
+local default_args = { timeout = 60, sensors = {} }
+
+-- Create a new widget
+-----------------------------------------------------------------------------------------------------------------------
+function sline.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ args = redutil.table.merge(default_args, args or {})
+ style = redutil.table.merge(default_style(), style or {})
+
+ dwidget.style = style
+
+ -- Initialize layouts
+ --------------------------------------------------------------------------------
+ dwidget.item = {}
+ dwidget.icon = {}
+ dwidget.area = wibox.layout.align.horizontal()
+
+ local mid = wibox.layout.flex.horizontal()
+
+ -- construct line
+ for i, _ in ipairs(args.sensors) do
+ dwidget.item[i] = textbox("", style.rbox)
+
+ if style.icon then dwidget.icon[i] = svgbox(style.icon) end
+
+ local boxlayout = wibox.widget({
+ textbox(string.upper(args.sensors[i].name or "mon"), style.lbox),
+ style.icon and {
+ nil, dwidget.icon[i], nil,
+ expand = "outside",
+ layout = wibox.layout.align.horizontal
+ },
+ dwidget.item[i],
+ forced_width = style.iwidth,
+ layout = wibox.layout.align.horizontal
+ })
+
+ if i == 1 then
+ dwidget.area:set_left(boxlayout)
+ else
+ local space = wibox.layout.align.horizontal()
+ space:set_right(boxlayout)
+ mid:add(space)
+ end
+ end
+
+ dwidget.area:set_middle(mid)
+
+ -- Update info function
+ --------------------------------------------------------------------------------
+ local function set_raw_state(state, crit, i)
+ local text_color = crit and state[1] > crit and style.color.main or style.color.gray
+ local txt = redutil.text.dformat(state[2] or state[1], style.unit, style.digits)
+
+ dwidget.item[i]:set_text(txt)
+ dwidget.item[i]:set_color(text_color)
+
+ if dwidget.icon[i] then
+ local icon_color = state.off and style.color.gray or style.color.main
+ dwidget.icon[i]:set_color(icon_color)
+ end
+ end
+
+ local function item_hadnler(crit, i)
+ return function(state) set_raw_state(state, crit, i) end
+ end
+
+ local function update()
+ for i, sens in ipairs(args.sensors) do
+ local crit = sens.crit
+ if sens.meter_function then
+ local state = sens.meter_function(sens.args)
+ set_raw_state(state, crit, i)
+ else
+ sens.async_function(item_hadnler(crit, i))
+ end
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = args.timeout })
+ t:connect_signal("timeout", update)
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function sline.mt:__call(...)
+ return sline.new(...)
+end
+
+return setmetatable(sline, sline.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/speedmeter/compact.lua b/awesome/.config/awesome/redflat/desktop/speedmeter/compact.lua
new file mode 100644
index 0000000..c31f2d0
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/speedmeter/compact.lua
@@ -0,0 +1,173 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat speed meter deskotp widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Network or disk i/o speed indicators
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+local unpack = unpack or table.unpack
+
+local system = require("redflat.system")
+local redutil = require("redflat.util")
+local dcommon = require("redflat.desktop.common")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local speedmeter = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = { margin = { 0, 0, 0, 0 }, },
+ label = { width = 100 },
+ margins = { label = { 0, 0, 0, 0 }, chart = { 0, 0, 2, 2 } },
+ progressbar = { chunk = { width = 10, gap = 5 }, height = 4 },
+ chart = {},
+ height = { chart = 50 },
+ digits = 2,
+ unit = { { "B", -1 }, { "KB", 1024 }, { "MB", 1024^2 }, { "GB", 1024^3 } },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.speedmeter.compact") or {})
+end
+
+local default_args = {
+ autoscale = true,
+ label = "NETWORK",
+ timeout = 5,
+ interface = "eth0",
+ meter_function = system.net_speed
+}
+
+local default_maxspeed = { up = 10 * 1024, down = 10 * 1024 }
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Construct chart with support elements
+--------------------------------------------------------------------------------
+local function value_chart(style, image, maxspeed)
+ local chart = dcommon.chart(redutil.table.merge(style.chart, { maxm = maxspeed }))
+ local progressbar = dcommon.bar.plain(redutil.table.merge(style.progressbar, { maxm = maxspeed }))
+
+ local text = dcommon.textbox("", style.label)
+ local icon = image and svgbox(image) or nil
+
+ local area = wibox.widget({
+ progressbar,
+ {
+ {
+ nil,
+ wibox.container.margin(text, unpack(style.margins.label)),
+ nil,
+ expand = "outside",
+ layout = wibox.layout.align.vertical
+ },
+ wibox.container.margin(chart, unpack(style.margins.chart)),
+ nil,
+ layout = wibox.layout.align.horizontal
+ },
+ progressbar,
+ forced_height = style.height.chart,
+ layout = wibox.layout.align.vertical
+ })
+
+ if image then
+ icon:set_color(style.color.gray)
+ area = wibox.widget({
+ wibox.container.margin(icon, unpack(style.icon.margin)),
+ area,
+ nil,
+ forced_height = style.height.chart,
+ layout = wibox.layout.align.horizontal
+ })
+ end
+
+ return { chart = chart, progressbar = progressbar, text = text, icon = icon, area = area }
+end
+
+
+-- Create a new speed meter widget
+-----------------------------------------------------------------------------------------------------------------------
+function speedmeter.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ local storage = {}
+ local last_state = { false, false }
+
+ args = redutil.table.merge(default_args, args or {})
+ style = redutil.table.merge(default_style(), style or {})
+ local maxspeed = redutil.table.merge(default_maxspeed, args.maxspeed or {})
+
+ style.chart = redutil.table.merge(style.chart, { autoscale = args.autoscale, color = style.color.gray })
+ style.progressbar = redutil.table.merge(style.progressbar, { autoscale = args.autoscale, color = style.color })
+ style.label = redutil.table.merge(style.label, { draw = "by_edges", color = style.color.gray })
+
+ dwidget.style = style
+
+ -- Construct indicators
+ --------------------------------------------------------------------------------
+ local widg = { {}, {} }
+ local placement = { "up", "down" }
+
+ for i = 1, 2 do
+ widg[i] = value_chart(style, style.icon[placement[i]], maxspeed[placement[i]])
+ end
+
+ dwidget.area = wibox.widget({
+ widg[1].area, nil, widg[2].area,
+ layout = wibox.layout.align.vertical
+ })
+
+ -- Update info
+ --------------------------------------------------------------------------------
+ local function update()
+ local state = args.meter_function(args.interface, storage)
+
+ for i = 1, 2 do
+ widg[i].chart:set_value(state[i])
+ widg[i].progressbar:set_value(state[i])
+ widg[i].text:set_text(redutil.text.dformat(state[i], style.unit, style.digits))
+
+ if widg[i].icon and args.crit then
+ local st = state[i] > args.crit[placement[i]]
+ if st ~= last_state[i] then
+ local newc = st and style.color.main or style.color.gray
+ widg[i].icon:set_color(newc)
+ widg[i].text:set_color(newc)
+ last_state[i] = st
+ end
+ end
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = args.timeout })
+ t:connect_signal("timeout", update)
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function speedmeter.mt:__call(...)
+ return speedmeter.new(...)
+end
+
+return setmetatable(speedmeter, speedmeter.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/speedmeter/init.lua b/awesome/.config/awesome/redflat/desktop/speedmeter/init.lua
new file mode 100644
index 0000000..6081eb2
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/speedmeter/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.desktop.speedmeter" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/desktop/speedmeter/normal.lua b/awesome/.config/awesome/redflat/desktop/speedmeter/normal.lua
new file mode 100644
index 0000000..3c5b178
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/speedmeter/normal.lua
@@ -0,0 +1,199 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat speed meter deskotp widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Network or disk i/o speed indicators
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local system = require("redflat.system")
+local redutil = require("redflat.util")
+local dcommon = require("redflat.desktop.common")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local speedmeter = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ images = {},
+ label = { height = 20, separator = "^" },
+ progressbar = { chunk = { width = 10, gap = 5 }, height = 4 },
+ chart = {},
+ barvalue_height = 32,
+ fullchart_height = 78,
+ digits = 2,
+ image_gap = 20,
+ unit = { { "B", -1 }, { "KB", 1024 }, { "MB", 1024^2 }, { "GB", 1024^3 } },
+ color = { main = "#b1222b", wibox = "#161616", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.speedmeter.normal") or {})
+end
+
+local default_args = {
+ autoscale = true,
+ label = "NETWORK",
+ timeout = 5,
+ interface = "eth0",
+ meter_function = system.net_speed
+}
+
+local default_maxspeed = { up = 10 * 1024, down = 10 * 1024 }
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function set_fullchart_info(objects, label, state, style)
+ for i, o in ipairs(objects) do
+ o.barvalue:set_value(state[i])
+ o.barvalue:set_text(
+ label .. style.label.separator .. redutil.text.dformat(state[i], style.unit, style.digits, " ")
+ )
+ o.chart:set_value(state[i])
+ end
+end
+
+local function colorize_icon(objects, last_state, values, crit, style)
+ for i, o in ipairs(objects) do
+ local st = values[i] > crit[i]
+ if st ~= last_state[i] then
+ o:set_color(st and style.color.main or style.color.gray)
+ last_state[i] = st
+ end
+ end
+end
+
+-- Construct complex indicator with progress bar and label on top of it
+--------------------------------------------------------------------------------
+local function barvalue(progressbar_style, label_style)
+ local widg = {}
+
+ -- construct layout with indicators
+ local progressbar = dcommon.bar.plain(progressbar_style)
+ local label = dcommon.textbox(nil, label_style)
+
+ widg.layout = wibox.widget({
+ label, nil, progressbar,
+ layout = wibox.layout.align.vertical,
+ })
+
+ -- setup functions
+ function widg:set_text(text) label:set_text(text) end
+ function widg:set_value(x) progressbar:set_value(x) end
+
+ return widg
+end
+
+-- Construct complex indicator with history chart, progress bar and label
+--------------------------------------------------------------------------------
+local function fullchart(label_style, progressbar_style, chart_style, barvalue_height, maxm)
+
+ local widg = {}
+ chart_style = redutil.table.merge(chart_style, { maxm = maxm })
+ progressbar_style = redutil.table.merge(progressbar_style, { maxm = maxm })
+
+ -- construct layout with indicators
+ widg.barvalue = barvalue(progressbar_style, label_style)
+ widg.chart = dcommon.chart(chart_style)
+ widg.barvalue.layout:set_forced_height(barvalue_height)
+
+ widg.layout = wibox.widget({
+ widg.barvalue.layout, nil, widg.chart,
+ layout = wibox.layout.align.vertical,
+ })
+
+ return widg
+end
+
+-- Construct speed info elements (fullchart and icon in one layout)
+--------------------------------------------------------------------------------
+local function speed_line(image, maxm, el_style, style)
+ local fc = fullchart(el_style.label, el_style.progressbar, el_style.chart, style.barvalue_height, maxm)
+ local align = wibox.layout.align.horizontal()
+ local icon
+
+ align:set_right(fc.layout)
+ align:set_forced_height(style.fullchart_height)
+
+ if image then
+ icon = svgbox(image)
+ icon:set_color(style.color.gray)
+ align:set_left(wibox.container.margin(icon, 0, style.image_gap))
+ end
+
+ return fc, align, icon
+end
+
+
+-- Create a new speed meter widget
+-----------------------------------------------------------------------------------------------------------------------
+function speedmeter.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local dwidget = {}
+ local storage = {}
+ local last = {}
+
+ args = redutil.table.merge(default_args, args or {})
+ style = redutil.table.merge(default_style(), style or {})
+ local maxspeed = redutil.table.merge(default_maxspeed, args.maxspeed or {})
+
+ local elements_style = {
+ label = redutil.table.merge(style.label, { draw = "by_edges", color = style.color.gray }),
+ progressbar = redutil.table.merge(style.progressbar, { autoscale = args.autoscale, color = style.color }),
+ chart = redutil.table.merge(style.chart, { autoscale = args.autoscale, color = style.color.gray })
+ }
+
+ dwidget.style = style
+
+ -- Construct indicators
+ --------------------------------------------------------------------------------
+ local up_widget, up_layout, up_icon = speed_line(style.images[1], maxspeed.up, elements_style, style)
+ local down_widget, down_layout, down_icon = speed_line(style.images[2], maxspeed.down, elements_style, style)
+
+ dwidget.area = wibox.widget({
+ up_layout, nil, down_layout,
+ layout = wibox.layout.align.vertical
+ })
+
+ -- Update info
+ --------------------------------------------------------------------------------
+ local function update()
+ local state = args.meter_function(args.interface, storage)
+
+ set_fullchart_info({ up_widget, down_widget }, args.label, state, style)
+
+ if style.images and args.crit then
+ colorize_icon({ up_icon, down_icon }, last, state, { args.crit.up, args.crit.down }, style)
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = args.timeout })
+ t:connect_signal("timeout", update)
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return dwidget
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function speedmeter.mt:__call(...)
+ return speedmeter.new(...)
+end
+
+return setmetatable(speedmeter, speedmeter.mt)
diff --git a/awesome/.config/awesome/redflat/desktop/textset.lua b/awesome/.config/awesome/redflat/desktop/textset.lua
new file mode 100644
index 0000000..41587b7
--- /dev/null
+++ b/awesome/.config/awesome/redflat/desktop/textset.lua
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat desktop text widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Text widget with text update function
+-----------------------------------------------------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+
+local textbox = require("wibox.widget.textbox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local lgi = require("lgi")
+local Pango = lgi.Pango
+
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local textset = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ font = "Sans 12",
+ spacing = 0,
+ color = { gray = "#525252" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "desktop.textset") or {})
+end
+
+-- Create a textset widget. It draws the time it is in a textbox.
+-- @param format The time format. Default is " %a %b %d, %H:%M ".
+-- @param timeout How often update the time. Default is 60.
+-- @return A textbox widget
+-----------------------------------------------------------------------------------------------------------------------
+function textset.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ --local funcarg = args.arg or {}
+ --local timeout = args.timeout or { 60 }
+ --local actions = args.actions or {}
+ --local async = args.async or {}
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = textbox()
+ widg:set_font(style.font)
+ widg:set_valign("top")
+
+ -- Some pivate properties of awesome textbox v4.0
+ widg._private.layout:set_justify(true)
+ widg._private.layout:set_spacing(Pango.units_from_double(style.spacing))
+
+ -- data setup
+ local data = {}
+ local timers = {}
+ for i = 1, #args do data[i] = "" end
+
+ -- update info function
+ local function update()
+ local state = {}
+ for _, txt in ipairs(data) do state[#state + 1] = txt end
+ widg:set_markup(string.format('%s', style.color.gray, table.concat(state)))
+ end
+
+ -- Set update timers
+ --------------------------------------------------------------------------------
+ for i, block in ipairs(args) do
+ timers[i] = timer({ timeout = block.timeout or args[1].timeout })
+ if block.async then
+ timers[i]:connect_signal("timeout", function()
+ block.async(function(state) data[i] = block.action(state); update() end)
+ end)
+ else
+ timers[i]:connect_signal("timeout", function()
+ data[i] = block.action(); update()
+ end)
+ end
+ timers[i]:start()
+ timers[i]:emit_signal("timeout")
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call textset module as function
+-----------------------------------------------------------------------------------------------------------------------
+function textset.mt:__call(...)
+ return textset.new(...)
+end
+
+return setmetatable(textset, textset.mt)
diff --git a/awesome/.config/awesome/redflat/float/apprunner.lua b/awesome/.config/awesome/redflat/float/apprunner.lua
new file mode 100644
index 0000000..40b4918
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/apprunner.lua
@@ -0,0 +1,367 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat application launcher widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with application list and quick search
+-- Application list generated by redflat.dfparser
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.menubar v3.5.2
+------ (c) 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+
+local svgbox = require("redflat.gauge.svgbox")
+local dfparser = require("redflat.service.dfparser")
+local redutil = require("redflat.util")
+local decoration = require("redflat.float.decoration")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local apprunner = { applist = {}, command = "", keys = {} }
+
+local programs = {}
+local lastquery
+
+-- key bindings
+apprunner.keys.move = {
+ {
+ {}, "Down", function() apprunner:down() end,
+ { description = "Select next item", group = "Navigation" }
+ },
+ {
+ {}, "Up", function() apprunner:up() end,
+ { description = "Select previous item", group = "Navigation" }
+ },
+}
+
+apprunner.keys.action = {
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+ -- fake keys used for hotkeys helper
+ {
+ {}, "Enter", nil,
+ { description = "Activate item", group = "Action" }
+ },
+ {
+ {}, "Escape", nil,
+ { description = "Close widget", group = "Action" }
+ },
+}
+
+apprunner.keys.all = awful.util.table.join(apprunner.keys.move, apprunner.keys.action)
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ itemnum = 5,
+ geometry = { width = 620, height = 520 },
+ border_margin = { 10, 10, 10, 10 },
+ title_height = 48,
+ prompt_height = 35,
+ title_icon = nil,
+ icon_margin = { 8, 12, 0, 0 },
+ parser = {},
+ list_text_vgap = 4,
+ list_icon_margin = { 6, 12, 6, 6 },
+ name_font = "Sans 12",
+ comment_font = "Sans 12",
+ border_width = 2,
+ keytip = { geometry = { width = 400 } },
+ dimage = redutil.base.placeholder(),
+ color = { border = "#575757", text = "#aaaaaa", highlight = "#eeeeee", main = "#b1222b",
+ bg = "#161616", bg_second = "#181818", wibox = "#202020", icon = "a0a0a0" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.apprunner") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Fuction to build list item
+--------------------------------------------------------------------------------
+local function construct_item(style)
+ local item = {
+ icon = wibox.widget.imagebox(),
+ name = wibox.widget.textbox(),
+ comment = wibox.widget.textbox(),
+ bg = style.color.bg,
+ cmd = ""
+ }
+
+ item.name:set_font(style.name_font)
+ item.comment:set_font(style.comment_font)
+
+ -- Construct item layouts
+ ------------------------------------------------------------
+ local text_vertical = wibox.layout.align.vertical()
+ local text_horizontal = wibox.layout.align.horizontal()
+ text_horizontal:set_left(text_vertical)
+ text_vertical:set_top(wibox.container.margin(item.name, 0, 0, style.list_text_vgap))
+ text_vertical:set_middle(item.comment)
+
+ local item_horizontal = wibox.layout.align.horizontal()
+ item_horizontal:set_left(wibox.container.margin(item.icon, unpack(style.list_icon_margin)))
+ item_horizontal:set_middle(text_horizontal)
+
+ item.layout = wibox.container.background(item_horizontal, item.bg)
+
+ -- Item functions
+ ------------------------------------------------------------
+ function item:set(args)
+ args = args or {}
+
+ local name_text = awful.util.escape(args.Name) or ""
+ item.name:set_markup(name_text)
+
+ local comment_text = args.Comment and awful.util.escape(args.Comment)
+ or args.Name and "No description"
+ or ""
+ item.comment:set_markup(comment_text)
+
+ item.icon:set_image(args.icon_path or style.dimage)
+ item.icon:set_visible((args.Name))
+
+ item.cmd = args.cmdline
+ end
+
+ function item:set_bg(color)
+ item.bg = color
+ item.layout:set_bg(color)
+ end
+
+ function item:set_select()
+ item.layout:set_bg(style.color.main)
+ item.layout:set_fg(style.color.highlight)
+ end
+
+ function item:set_unselect()
+ item.layout:set_bg(item.bg)
+ item.layout:set_fg(style.color.text)
+ end
+
+ function item:run()
+ awful.spawn(item.cmd)
+ end
+
+ ------------------------------------------------------------
+ return item
+end
+
+-- Fuction to build application list
+--------------------------------------------------------------------------------
+local function construct_list(num, progs, style)
+ local list = { selected = 1, position = 1 }
+
+ -- Construct application list
+ ------------------------------------------------------------
+ local list_layout = wibox.layout.flex.vertical()
+ list.layout = wibox.container.background(list_layout, style.color.bg)
+
+ list.items = {}
+ for i = 1, num do
+ list.items[i] = construct_item(style)
+ list.items[i]:set_bg((i % 2) == 1 and style.color.bg or style.color.bg_second)
+ list_layout:add(list.items[i].layout)
+ end
+
+ -- Application list functions
+ ------------------------------------------------------------
+ function list:set_select(index)
+ list.items[list.selected]:set_unselect()
+ list.selected = index
+ list.items[list.selected]:set_select()
+ end
+
+ function list:update(t)
+ for i = list.position, (list.position - 1 + num) do list.items[i - list.position + 1]:set(t[i]) end
+ list:set_select(list.selected)
+ end
+
+ -- First run actions
+ ------------------------------------------------------------
+ list:update(progs)
+ list:set_select(1)
+
+ ------------------------------------------------------------
+ return list
+end
+
+-- Sort function
+--------------------------------------------------------------------------------
+local function sort_by_query(t, query)
+ local l = string.len(query)
+ local function s(a, b)
+ return string.lower(string.sub(a.Name, 1, l)) == query and string.lower(string.sub(b.Name, 1, l)) ~= query
+ end
+ table.sort(t, s)
+end
+
+-- Function to filter application list by quick search input
+--------------------------------------------------------------------------------
+local function list_filtrate(query)
+ if lastquery ~= query then
+ programs.current = {}
+
+ for _, p in ipairs(programs.all) do
+ if string.match(string.lower(p.Name), query) then
+ table.insert(programs.current, p)
+ end
+ end
+
+ sort_by_query(programs.current, query)
+
+ apprunner.applist.position = 1
+ apprunner.applist:update(programs.current)
+ apprunner.applist:set_select(1)
+ lastquery = query
+ end
+end
+
+-- Functions to navigate through application list
+-----------------------------------------------------------------------------------------------------------------------
+function apprunner:down()
+ if self.applist.selected < math.min(self.itemnum, #programs.current) then
+ self.applist:set_select(self.applist.selected + 1)
+ elseif self.applist.selected + self.applist.position - 1 < #programs.current then
+ self.applist.position = self.applist.position + 1
+ self.applist:update(programs.current)
+ end
+end
+
+function apprunner:up()
+ if self.applist.selected > 1 then
+ self.applist:set_select(self.applist.selected - 1)
+ elseif self.applist.position > 1 then
+ self.applist.position = self.applist.position - 1
+ self.applist:update(programs.current)
+ end
+end
+
+-- Keypress handler
+-----------------------------------------------------------------------------------------------------------------------
+local function keypressed_callback(mod, key)
+ for _, k in ipairs(apprunner.keys.all) do
+ if redutil.key.match_prompt(k, mod, key) and k[3] then k[3](); return true end
+ end
+ return false
+end
+
+-- Initialize apprunner widget
+-----------------------------------------------------------------------------------------------------------------------
+function apprunner:init()
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local style = default_style()
+ self.itemnum = style.itemnum
+ self.keytip = style.keytip
+
+ -- get full application list
+ programs.all = dfparser.program_list(style.parser)
+ programs.current = awful.util.table.clone(programs.all)
+
+ -- Create quick search widget
+ --------------------------------------------------------------------------------
+ self.textbox = wibox.widget.textbox()
+ self.textbox:set_ellipsize("start")
+ self.decorated_widget = decoration.textfield(self.textbox, style.field)
+
+ -- Build application list
+ --------------------------------------------------------------------------------
+ self.applist = construct_list(apprunner.itemnum, programs.current, style)
+
+ -- Construct widget layouts
+ --------------------------------------------------------------------------------
+ local prompt_width = style.geometry.width - 2 * style.border_margin[1]
+ - style.title_height - style.icon_margin[1] - style.icon_margin[2]
+ local prompt_layout = wibox.container.constraint(self.decorated_widget, "exact", prompt_width, style.prompt_height)
+
+ local prompt_vertical = wibox.layout.align.vertical()
+ prompt_vertical:set_expand("outside")
+ prompt_vertical:set_middle(prompt_layout)
+
+ local prompt_area_horizontal = wibox.layout.align.horizontal()
+ local title_image = svgbox(style.title_icon)
+ title_image:set_color(style.color.icon)
+ prompt_area_horizontal:set_left(wibox.container.margin(title_image, unpack(style.icon_margin)))
+ prompt_area_horizontal:set_right(prompt_vertical)
+
+ local prompt_area_layout = wibox.container.constraint(prompt_area_horizontal, "exact", nil, style.title_height)
+
+ local area_vertical = wibox.layout.align.vertical()
+ area_vertical:set_top(prompt_area_layout)
+ area_vertical:set_middle(wibox.container.margin(self.applist.layout, 0, 0, style.border_margin[3]))
+ local area_layout = wibox.container.margin(area_vertical, unpack(style.border_margin))
+
+ -- Create floating wibox for apprunner widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:set_widget(area_layout)
+ self.wibox:geometry(style.geometry)
+end
+
+-- Show apprunner widget
+-- Wibox appears on call and hides after "enter" or "esc" pressed
+-----------------------------------------------------------------------------------------------------------------------
+function apprunner:show()
+ if not self.wibox then
+ self:init()
+ else
+ list_filtrate("")
+ self.applist:set_select(1)
+ end
+
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ self.wibox.visible = true
+ redtip:set_pack("Apprunner", self.keys.all, self.keytip.column, self.keytip.geometry)
+
+ return awful.prompt.run({
+ prompt = "",
+ textbox = self.textbox,
+ exe_callback = function () self.applist.items[self.applist.selected]:run() end,
+ done_callback = function () self:hide() end,
+ keypressed_callback = keypressed_callback,
+ changed_callback = list_filtrate,
+ })
+end
+
+function apprunner:hide()
+ self.wibox.visible = false
+ redtip:remove_pack()
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function apprunner:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.move, self.keys.action) end
+ end
+
+ -- self.tip = awful.util.table.join(self.keys.all, self._fake_keys)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return apprunner
diff --git a/awesome/.config/awesome/redflat/float/appswitcher.lua b/awesome/.config/awesome/redflat/float/appswitcher.lua
new file mode 100644
index 0000000..f15783b
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/appswitcher.lua
@@ -0,0 +1,459 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat appswitcher widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Advanced application switcher
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ Familiar Alt Tab by Joren Heit
+------ https://github.com/jorenheit/awesome_alttab
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local type = type
+local math = math
+local unpack = unpack or table.unpack
+local table = table
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+local gears = require("gears")
+
+local pixbuf
+local function load_pixbuf()
+ local _ = require("lgi").Gdk
+ pixbuf = require("lgi").GdkPixbuf
+end
+local is_pixbuf_loaded = pcall(load_pixbuf)
+
+local dfparser = require("redflat.service.dfparser")
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local appswitcher = { clients_list = {}, index = 1, hotkeys = {}, svgsize = 256, keys = {} }
+
+local cache = {}
+local svgcache = {}
+local _empty_surface = redutil.base.placeholder({ txt = " " })
+
+-- key bindings
+appswitcher.keys.move = {
+ {
+ {}, "Right", function() appswitcher:switch() end,
+ { description = "Select next app", group = "Navigation" }
+ },
+ {
+ {}, "Left", function() appswitcher:switch({ reverse = true }) end,
+ { description = "Select previous app", group = "Navigation" }
+ },
+}
+
+appswitcher.keys.action = {
+ {
+ {}, "Return", function() appswitcher:hide() end,
+ { description = "Activate and exit", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+appswitcher.keys.all = awful.util.table.join(appswitcher.keys.move, appswitcher.keys.action)
+
+appswitcher._fake_keys = {
+ {
+ {}, "N", nil,
+ { description = "Select app by key", group = "Navigation" }
+ },
+}
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ wibox_height = 200,
+ label_height = 20,
+ title_height = 20,
+ icon_size = 48,
+ preview_gap = 20,
+ preview_format = 16/10,
+ preview_margin = { 20, 20, 20, 20 },
+ border_margin = { 6, 6, 6, 6 },
+ border_width = 2,
+ parser = {},
+ update_timeout = 1,
+ min_icon_number = 4,
+ keytip = { geometry = { width = 400 }, exit = false },
+ title_font = "Sans 12",
+ hotkeys = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" },
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", preview_bg = "#b1222b80",
+ wibox = "#202020", icon = "#a0a0a0", bg = "#161616", gray = "#575757" },
+ shape = nil
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.appswitcher") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Create icon visual for client
+--------------------------------------------------------------------------------
+local function get_icon_visual(icon_db, c, size)
+ local surface, buf
+
+ if icon_db[string.lower(c.class)] then
+ local icon = icon_db[string.lower(c.class)]
+
+ if type(icon) == "string" and string.match(icon, "%.svg") and is_pixbuf_loaded then
+ if svgcache[icon] then
+ buf = svgcache[icon]
+ else
+ buf = pixbuf.Pixbuf.new_from_file_at_scale(icon, size, size, true)
+ svgcache[icon] = buf
+ end
+ else
+ surface = gears.surface(icon)
+ end
+ else
+ surface = c.icon and gears.surface(c.icon) or _empty_surface
+ end
+
+ return surface, buf
+end
+
+-- Find all clients to be shown
+--------------------------------------------------------------------------------
+local function clients_find(filter)
+ local clients = {}
+ for _, c in ipairs(client.get()) do
+ if not (c.skip_taskbar or c.hidden or c.type == "splash" or c.type == "dock" or c.type == "desktop")
+ and filter(c, mouse.screen) then
+ table.insert(clients, c)
+ end
+ end
+ return clients
+end
+
+-- Loop iterating through table
+--------------------------------------------------------------------------------
+local function iterate(tabl, i, diff)
+ local nxt = i + diff
+
+ if nxt > #tabl then nxt = 1
+ elseif nxt < 1 then nxt = #tabl end
+
+ return nxt
+end
+
+-- Select new focused window
+--------------------------------------------------------------------------------
+local function focus_and_raise(c)
+ if c.minimized then c.minimized = false end
+
+ if not c:isvisible() then
+ awful.tag.viewmore(c:tags(), c.screen)
+ end
+
+ client.focus = c
+ c:raise()
+end
+
+-- Initialize appswitcher widget
+-----------------------------------------------------------------------------------------------------------------------
+function appswitcher:init()
+
+ -- Initialize style vars
+ --------------------------------------------------------------------------------
+ local style = default_style()
+ local icon_db = dfparser.icon_list(style.parser)
+ local iscf = 1 -- icon size correction factor
+
+ self.keytip = style.keytip
+ self._fake_keys[1][4].keyset = style.hotkeys
+ self:set_keys()
+
+ -- Create floating wibox for appswitcher widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ -- Keygrabber
+ --------------------------------------------------------------------------------
+ local function focus_by_key(key)
+ self:switch({ index = awful.util.table.hasitem(style.hotkeys, key) })
+ end
+
+ self.keygrabber = function(mod, key, event)
+ if event == "press" then return false end
+
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return false end
+ end
+
+ if awful.util.table.hasitem(style.hotkeys, key) then focus_by_key(key) end
+ end
+
+ -- Function to form title string for given client (name and tags)
+ --------------------------------------------------------------------------------
+ function self.title_generator(c)
+ local client_tags = {}
+
+ for _, t in ipairs(c:tags()) do
+ client_tags[#client_tags + 1] = string.upper(t.name)
+ end
+
+ local tag_text = string.format('[%s]', style.color.gray, table.concat(client_tags, " "))
+
+ return string.format("%s %s", awful.util.escape(c.name) or "Untitled", tag_text)
+ end
+
+ -- Function to correct wibox size for given namber of icons
+ --------------------------------------------------------------------------------
+ function self.size_correction(inum)
+ local w, h
+ inum = math.max(inum, style.min_icon_number)
+ local expen_h = (inum - 1) * style.preview_gap + style.preview_margin[1] + style.preview_margin[2]
+ + style.border_margin[1] + style.border_margin[2]
+ local expen_v = style.label_height + style.preview_margin[3] + style.preview_margin[4] + style.title_height
+ + style.border_margin[3] + style.border_margin[4]
+
+ -- calculate width
+ local widget_height = style.wibox_height - expen_v + style.label_height
+ local max_width = screen[mouse.screen].geometry.width - 2 * self.wibox.border_width
+ local wanted_width = inum * ((widget_height - style.label_height) * style.preview_format) + expen_h
+
+ -- check if need size correction
+ if wanted_width <= max_width then
+ -- correct width
+ w = wanted_width
+ h = style.wibox_height
+ iscf = 1
+ else
+ -- correct height
+ local wanted_widget_width = (max_width - expen_h) / inum
+ local corrected_height = wanted_widget_width / style.preview_format + expen_v
+
+ w = max_width
+ h = corrected_height
+ iscf = (corrected_height - expen_v) / (style.wibox_height - expen_v)
+ end
+
+ -- set wibox size
+ self.wibox:geometry({ width = w, height = h })
+ end
+
+ -- Create custom widget to draw previews
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height) return width, height end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg.draw(_, _, cr, _, height)
+
+ -- calculate preview pattern size
+ local psize = {
+ width = (height - style.label_height) * style.preview_format,
+ height = (height - style.label_height)
+ }
+
+ -- Shift pack of preview icons to center of widget if needed
+ if #self.clients_list < style.min_icon_number then
+ local tr = (style.min_icon_number - #self.clients_list) * (style.preview_gap + psize.width) / 2
+ cr:translate(tr, 0)
+ end
+
+ -- draw all previews
+ for i = 1, #self.clients_list do
+
+ -- support vars
+ local sc, tr, surface, pixbuf_
+ local c = self.clients_list[i]
+
+ -- create surface and calculate scale and translate factors
+ if c:isvisible() then
+ surface = gears.surface(c.content)
+ local cg = c:geometry()
+
+ if cg.width/cg.height > style.preview_format then
+ sc = psize.width / cg.width
+ tr = {0, (psize.height - sc * cg.height) / 2}
+ else
+ sc = psize.height / cg.height
+ tr = {(psize.width - sc * cg.width) / 2, 0}
+ end
+ else
+ -- surface = gears.surface(icon_db[string.lower(c.class)] or c.icon)
+ surface, pixbuf_ = get_icon_visual(icon_db, c, self.svgsize)
+
+ -- sc = style.icon_size / surface.width * iscf
+ sc = style.icon_size / (surface and surface.width or pixbuf_.width) * iscf
+ tr = {(psize.width - style.icon_size * iscf) / 2, (psize.height - style.icon_size * iscf) / 2}
+ end
+
+ -- translate cairo for every icon
+ if i > 1 then cr:translate(style.preview_gap + psize.width, 0) end
+
+ -- draw background for preview
+ cr:set_source(gears.color(i == self.index and style.color.main or style.color.preview_bg))
+ cr:rectangle(0, 0, psize.width, psize.height)
+ cr:fill()
+
+ -- draw current preview or application icon
+ cr:save()
+ cr:translate(unpack(tr))
+ cr:scale(sc, sc)
+
+ if pixbuf_ then
+ cr:set_source_pixbuf(pixbuf_, 0, 0)
+ else
+ cr:set_source_surface(surface, 0, 0)
+ end
+ cr:paint()
+ cr:restore()
+
+ -- draw label
+ local txt = style.hotkeys[i] or "?"
+ cr:set_source(gears.color(i == self.index and style.color.main or style.color.text))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { psize.width/2, psize.height + style.label_height }, txt)
+ end
+
+ collectgarbage() -- prevents memory leak after complex draw function
+ end
+
+ -- Set widget and create title for wibox
+ --------------------------------------------------------------------------------
+ self.widget = widg
+
+ self.titlebox = wibox.widget.textbox("TEXT")
+ self.titlebox:set_align("center")
+ self.titlebox:set_font(style.title_font)
+
+ local title_layout = wibox.container.constraint(self.titlebox, "exact", nil, style.title_height)
+ local vertical_layout = wibox.layout.fixed.vertical()
+ local widget_bg = wibox.container.background(
+ wibox.container.margin(self.widget, unpack(style.preview_margin)),
+ style.color.bg
+ )
+ vertical_layout:add(title_layout)
+ vertical_layout:add(widget_bg)
+
+ self.wibox:set_widget(wibox.container.margin(vertical_layout, unpack(style.border_margin)))
+
+ -- Set preview icons update timer
+ --------------------------------------------------------------------------------
+ self.update_timer = timer({ timeout = style.update_timeout })
+ self.update_timer:connect_signal("timeout", function() self.widget:emit_signal("widget::redraw_needed") end)
+
+ -- Restart switcher if any client was closed
+ --------------------------------------------------------------------------------
+ client.connect_signal("unmanage",
+ function(c)
+ if self.wibox.visible and awful.util.table.hasitem(self.clients_list, c) then
+ self:hide(true)
+ self:show(cache.args)
+ end
+ end
+ )
+end
+
+-- Show appswitcher widget
+-----------------------------------------------------------------------------------------------------------------------
+function appswitcher:show(args)
+
+ args = args or {}
+ local filter = args.filter
+ local noaction = args.noaction
+
+ if not self.wibox then self:init() end
+ if self.wibox.visible then
+ self:switch(args)
+ return
+ end
+
+ local clients = clients_find(filter)
+ if #clients == 0 then return end
+
+ self.clients_list = clients
+ cache.args = args
+ self.size_correction(#clients)
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ self.update_timer:start()
+ awful.keygrabber.run(self.keygrabber)
+
+ self.index = awful.util.table.hasitem(self.clients_list, client.focus) or 1
+ self.titlebox:set_markup(self.title_generator(self.clients_list[self.index]))
+ if not noaction then self:switch(args) end
+ self.widget:emit_signal("widget::redraw_needed")
+
+ self.wibox.visible = true
+
+ redtip:set_pack(
+ "Appswitcher", self.tip, self.keytip.column, self.keytip.geometry,
+ self.keytip.exit and function() appswitcher:hide(true) end
+ )
+end
+
+-- Hide appswitcher widget
+-----------------------------------------------------------------------------------------------------------------------
+function appswitcher:hide(is_empty_call)
+
+ if not self.wibox then self:init() end
+ if not self.wibox.visible then return end
+ self.wibox.visible = false
+ redtip:remove_pack()
+ self.update_timer:stop()
+ awful.keygrabber.stop(self.keygrabber)
+
+ if not is_empty_call then focus_and_raise(self.clients_list[self.index]) end
+end
+
+-- Toggle appswitcher widget
+-----------------------------------------------------------------------------------------------------------------------
+function appswitcher:switch(args)
+ args = args or {}
+
+ if args.index then
+ if self.clients_list[args.index] then self.index = args.index end
+ else
+ local reverse = args.reverse or false
+ local diff = reverse and -1 or 1
+ self.index = iterate(self.clients_list, self.index, diff)
+ end
+
+ self.titlebox:set_markup(self.title_generator(self.clients_list[self.index]))
+ self.widget:emit_signal("widget::redraw_needed")
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function appswitcher:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.move, self.keys.action) end
+ end
+
+ self.tip = awful.util.table.join(self.keys.all, self._fake_keys)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return appswitcher
diff --git a/awesome/.config/awesome/redflat/float/bartip.lua b/awesome/.config/awesome/redflat/float/bartip.lua
new file mode 100644
index 0000000..6931a15
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/bartip.lua
@@ -0,0 +1,221 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat titlebar helper widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Titlebar info widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+
+local beautiful = require("beautiful")
+local awful = require("awful")
+local wibox = require("wibox")
+
+local redutil = require("redflat.util")
+local redtitle = require("redflat.titlebar")
+local redtip = require("redflat.float.hotkeys")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local bartip = {}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 400, height = 60 },
+ border_width = 2,
+ font = "Sans 14",
+ set_position = nil,
+ names = {},
+ keytip = { geometry = { width = 600 } },
+ shape = nil,
+ margin = { icon = { title = { 10, 10, 2, 2 }, state = { 10, 10, 2, 2 } } },
+ icon = {
+ title = redutil.base.placeholder({ txt = "[]" }),
+ active = redutil.base.placeholder({ txt = "+" }),
+ absent = redutil.base.placeholder({ txt = "!" }),
+ disabled = redutil.base.placeholder({ txt = "X" }),
+ hidden = redutil.base.placeholder({ txt = "↓" }),
+ unknown = redutil.base.placeholder({ txt = "?" }),
+ },
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", wibox = "#202020",
+ gray = "#575757", icon = "#a0a0a0" },
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.bartip") or {})
+end
+
+-- key bindings
+bartip.keys = {}
+bartip.keys.bar = {
+ {
+ { "Mod4" }, "b", function() redtitle.toggle(client.focus); bartip:update() end,
+ { description = "Show/hide titlebar for focused client", group = "Titlebar control" }
+ },
+ {
+ { "Mod4" }, "a", function() redtitle.toggle_all(); bartip:update() end,
+ { description = "Show/hide titlebar for all clients", group = "Titlebar control" }
+ },
+ --{
+ -- { "Mod4" }, "v", function() redtitle.switch(client.focus); bartip:update() end,
+ -- { description = "Switch titlebar view for focused client", group = "Titlebar control" }
+ --},
+ {
+ { "Mod4" }, "n", function() redtitle.global_switch(); bartip:update() end,
+ { description = "Switch titlebar view for all clients", group = "Titlebar control" }
+ },
+}
+bartip.keys.action = {
+ {
+ { "Mod4" }, "Super_L", function() bartip:hide() end,
+ { description = "Close top list widget", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+bartip.keys.all = awful.util.table.join(bartip.keys.bar, bartip.keys.action)
+
+
+-- Initialize widget
+-----------------------------------------------------------------------------------------------------------------------
+function bartip:init()
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local style = default_style()
+ self.style = style
+
+ -- Create floating wibox for top widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:geometry(style.geometry)
+
+ -- Widget layout setup
+ --------------------------------------------------------------------------------
+ self.label = wibox.widget.textbox()
+ self.label:set_align("center")
+ self.label:set_font(style.font)
+
+ local title_icon = svgbox(self.style.icon.title)
+ title_icon:set_color(self.style.color.icon)
+
+ self.state_icon = svgbox()
+
+ --self.wibox:set_widget(self.label)
+ self.wibox:setup({
+ wibox.container.margin(title_icon, unpack(self.style.margin.icon.title)),
+ self.label,
+ wibox.container.margin(self.state_icon, unpack(self.style.margin.icon.state)),
+ layout = wibox.layout.align.horizontal
+ })
+
+ -- Keygrabber
+ --------------------------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event == "release" then
+ for _, k in ipairs(self.keys.action) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ else
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ end
+ end
+
+ -- First run actions
+ --------------------------------------------------------------------------------
+ self:set_keys()
+end
+
+-- Widget actions
+-----------------------------------------------------------------------------------------------------------------------
+
+local function get_title_state(c)
+ if not c then return "unknown" end
+
+ local model = redtitle.get_model(c)
+ local state = not model and "absent"
+ or model.hidden and "disabled"
+ or model.cutted and "hidden"
+ or "active"
+
+ return state, model and model.size or nil
+end
+
+-- Update
+--------------------------------------------------------------------------------
+function bartip:update()
+ local name = self.style.names[redtitle._index] or "Unknown"
+ local state, size = get_title_state(client.focus)
+ local size_mark = size and string.format(" [%d]", size) or ""
+
+ self.label:set_markup(string.format(
+ '%s%s',
+ self.style.color.text, name, self.style.color.gray, size_mark
+ ))
+
+ self.state_icon:set_image(self.style.icon[state])
+ self.state_icon:set_color(state == "absent" and self.style.color.main or self.style.color.icon)
+end
+
+-- Show
+--------------------------------------------------------------------------------
+function bartip:show()
+ if not self.wibox then self:init() end
+
+ if not self.wibox.visible then
+ if self.style.set_position then
+ self.style.set_position(self.wibox)
+ else
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, screen[mouse.screen].workarea)
+
+ self:update()
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+ redtip:set_pack(
+ "Titlebar", self.tip, self.style.keytip.column, self.style.keytip.geometry,
+ function() self:hide() end
+ )
+ end
+end
+
+-- Hide
+--------------------------------------------------------------------------------
+function bartip:hide()
+ self.wibox.visible = false
+ awful.keygrabber.stop(self.keygrabber)
+ redtip:remove_pack()
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function bartip:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.bar, self.keys.action) end
+ end
+
+ self.tip = self.keys.all
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return bartip
diff --git a/awesome/.config/awesome/redflat/float/brightness.lua b/awesome/.config/awesome/redflat/float/brightness.lua
new file mode 100644
index 0000000..e7e36e0
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/brightness.lua
@@ -0,0 +1,62 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat brightness control widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Brightness control using xbacklight
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local string = string
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local rednotify = require("redflat.float.notify")
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local brightness = { dbus_correction = 1 }
+
+local defaults = { down = false, step = 2 }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ notify = {},
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.brightness") or {})
+end
+
+-- Change brightness level
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Change with xbacklight
+------------------------------------------------------------
+function brightness:change_with_xbacklight(args)
+ args = redutil.table.merge(defaults, args or {})
+
+ local command = string.format("xbacklight %s %d", args.down and "-dec" or "-inc", args.step)
+ awful.spawn.easy_async(command, self.info_with_xbacklight)
+end
+
+-- Update brightness level info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Update from xbacklight
+------------------------------------------------------------
+function brightness.info_with_xbacklight()
+ if not brightness.style then brightness.style = default_style() end
+ awful.spawn.easy_async(
+ "xbacklight -get",
+ function(output)
+ rednotify:show(redutil.table.merge(
+ { value = output / 100, text = string.format('%.0f', output) .. "%" },
+ brightness.style.notify
+ ))
+ end
+ )
+end
+
+-----------------------------------------------------------------------------------------------------------------------
+return brightness
diff --git a/awesome/.config/awesome/redflat/float/clientmenu.lua b/awesome/.config/awesome/redflat/float/clientmenu.lua
new file mode 100644
index 0000000..852ede2
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/clientmenu.lua
@@ -0,0 +1,383 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat client menu widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom float widget that provides client actions like the tasklist's window
+-- menu but may be used outside of the tasklist context on any client. Useful
+-- for titlebar click action or other custom client-related keybindings for
+-- faster access of client actions without traveling to the tasklist.
+-----------------------------------------------------------------------------------------------------------------------
+-- Authored by M4he
+-- Some code was taken from
+------ redflat.widget.tasklist
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local ipairs = ipairs
+local table = table
+local beautiful = require("beautiful")
+local awful = require("awful")
+local wibox = require("wibox")
+
+local redutil = require("redflat.util")
+local separator = require("redflat.gauge.separator")
+local redmenu = require("redflat.menu")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local clientmenu = { mt = {}, }
+
+local last = {
+ client = nil,
+ screen = mouse.screen,
+ tag_screen = mouse.screen
+}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = { unknown = redutil.base.placeholder(),
+ minimize = redutil.base.placeholder(),
+ close = redutil.base.placeholder() },
+ micon = { blank = redutil.base.placeholder({ txt = " " }),
+ check = redutil.base.placeholder({ txt = "+" }) },
+ layout_icon = { unknown = redutil.base.placeholder() },
+ actionline = { height = 28 },
+ stateline = { height = 35 },
+ state_iconsize = { width = 20, height = 20 },
+ action_iconsize = { width = 18, height = 18 },
+ separator = { marginh = { 3, 3, 5, 5 }, marginv = { 3, 3, 3, 3 } },
+ tagmenu = { icon_margin = { 2, 2, 2, 2 } },
+ hide_action = { move = true,
+ add = false,
+ min = true,
+ floating = false,
+ sticky = false,
+ ontop = false,
+ below = false,
+ maximized = false },
+ color = { main = "#b1222b", icon = "#a0a0a0", gray = "#404040", highlight = "#eeeeee" },
+ }
+ style.menu = {
+ ricon_margin = { 2, 2, 2, 2 },
+ hide_timeout = 1,
+ select_first = false,
+ nohide = true
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.clientmenu") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Function to build item list for submenu
+--------------------------------------------------------------------------------
+local function tagmenu_items(action, style)
+ local items = {}
+ for _, t in ipairs(last.screen.tags) do
+ if not awful.tag.getproperty(t, "hide") then
+ table.insert(
+ items,
+ { t.name, function() action(t) end, style.micon.blank, style.micon.blank }
+ )
+ end
+ end
+ return items
+end
+
+-- Function to rebuild the submenu entries according to current screen's tags
+--------------------------------------------------------------------------------
+local function tagmenu_rebuild(menu, submenu_index, style)
+ for _, index in ipairs(submenu_index) do
+ local new_items
+ if index == 1 then
+ new_items = tagmenu_items(clientmenu.movemenu_action, style)
+ else
+ new_items = tagmenu_items(clientmenu.addmenu_action, style)
+ end
+ menu.items[index].child:replace_items(new_items)
+ end
+end
+
+-- Function to update tag submenu icons
+--------------------------------------------------------------------------------
+local function tagmenu_update(c, menu, submenu_index, style)
+ -- if the screen has changed (and thus the tags) since the last time the
+ -- tagmenu was built, rebuild it first
+ if last.tag_screen ~= mouse.screen then
+ tagmenu_rebuild(menu, submenu_index, style)
+ last.tag_screen = mouse.screen
+ end
+ for k, t in ipairs(last.screen.tags) do
+ if not awful.tag.getproperty(t, "hide") then
+
+ -- set layout icon for every tag
+ local l = awful.layout.getname(awful.tag.getproperty(t, "layout"))
+
+ local check_icon = style.micon.blank
+ if c then
+ local client_tags = c:tags()
+ check_icon = awful.util.table.hasitem(client_tags, t) and style.micon.check or check_icon
+ end
+
+ for _, index in ipairs(submenu_index) do
+ local submenu = menu.items[index].child
+ if submenu.items[k].icon then
+ submenu.items[k].icon:set_image(style.layout_icon[l] or style.layout_icon.unknown)
+ end
+
+ -- set "checked" icon if tag active for given client
+ -- otherwise set empty icon
+ if c then
+ if submenu.items[k].right_icon then
+ submenu.items[k].right_icon:set_image(check_icon)
+ end
+ end
+
+ -- update position of any visible submenu
+ if submenu.wibox.visible then submenu:show() end
+ end
+ end
+ end
+end
+
+-- Function to construct menu line with state icons
+--------------------------------------------------------------------------------
+local function state_line_construct(state_icons, setup_layout, style)
+ local stateboxes = {}
+
+ for i, v in ipairs(state_icons) do
+ -- create widget
+ stateboxes[i] = svgbox(v.icon)
+ stateboxes[i]:set_forced_width(style.state_iconsize.width)
+ stateboxes[i]:set_forced_height(style.state_iconsize.height)
+
+ -- set widget in line
+ local l = wibox.layout.align.horizontal()
+ l:set_expand("outside")
+ l:set_second(stateboxes[i])
+ setup_layout:add(l)
+
+ -- set mouse action
+ stateboxes[i]:buttons(awful.util.table.join(awful.button({}, 1,
+ function()
+ v.action()
+ stateboxes[i]:set_color(v.indicator(last.client) and style.color.main or style.color.gray)
+ end
+ )))
+ end
+
+ return stateboxes
+end
+
+-- Function to construct menu line with action icons (minimize, close)
+--------------------------------------------------------------------------------
+local function action_line_construct(setup_layout, style)
+ local sep = separator.vertical(style.separator)
+
+ local function actionbox_construct(icon, action)
+ local iconbox = svgbox(icon, nil, style.color.icon)
+ iconbox:set_forced_width(style.action_iconsize.width)
+ iconbox:set_forced_height(style.action_iconsize.height)
+
+ -- center iconbox both vertically and horizontally
+ local vert_wrapper = wibox.layout.align.vertical()
+ vert_wrapper:set_second(iconbox)
+ vert_wrapper:set_expand("outside")
+ local horiz_wrapper = wibox.layout.align.horizontal()
+ horiz_wrapper:set_second(vert_wrapper)
+ horiz_wrapper:set_expand("outside")
+
+ -- wrap into a background container to allow bg color change of area
+ local actionbox = wibox.container.background(horiz_wrapper)
+
+ -- set mouse action
+ actionbox:buttons(awful.util.table.join(awful.button({}, 1,
+ function()
+ action()
+ end
+ )))
+ actionbox:connect_signal("mouse::enter",
+ function()
+ iconbox:set_color(style.color.highlight)
+ actionbox.bg = style.color.main
+ end
+ )
+ actionbox:connect_signal("mouse::leave",
+ function()
+ iconbox:set_color(style.color.icon)
+ actionbox.bg = nil
+ end
+ )
+ return actionbox
+ end
+
+ -- minimize button
+ local minimize_box = actionbox_construct(
+ style.icon.minimize,
+ function()
+ last.client.minimized = not last.client.minimized
+ if style.hide_action["min"] then clientmenu.menu:hide() end
+ end
+ )
+ setup_layout:set_first(minimize_box)
+
+ -- separator
+ setup_layout:set_second(sep)
+
+ -- close button
+ local close_box = actionbox_construct(
+ style.icon.close,
+ function()
+ last.client:kill()
+ clientmenu.menu:hide()
+ end
+ )
+ setup_layout:set_third(close_box)
+end
+
+-- Calculate menu position
+--------------------------------------------------------------------------------
+local function coords_calc(menu)
+ local coords = mouse.coords()
+ coords.x = coords.x - menu.wibox.width / 2 - menu.wibox.border_width
+
+ return coords
+end
+
+-- Initialize window menu widget
+-----------------------------------------------------------------------------------------------------------------------
+function clientmenu:init(style)
+ style = redutil.table.merge(default_style(), style or {})
+
+ self.hide_check = function(action)
+ if style.hide_action[action] then self.menu:hide() end
+ end
+
+ -- Create array of state icons
+ -- associate every icon with action and state indicator
+ --------------------------------------------------------------------------------
+ local function icon_table_generator_prop(property)
+ return {
+ icon = style.icon[property] or style.icon.unknown,
+ action = function() last.client[property] = not last.client[property]; self.hide_check(property) end,
+ indicator = function(c) return c[property] end
+ }
+ end
+
+ local state_icons = {
+ icon_table_generator_prop("floating"),
+ icon_table_generator_prop("sticky"),
+ icon_table_generator_prop("ontop"),
+ icon_table_generator_prop("below"),
+ icon_table_generator_prop("maximized"),
+ }
+
+ -- Construct menu
+ --------------------------------------------------------------------------------
+
+ -- Window action line construction
+ ------------------------------------------------------------
+
+ local actionline_horizontal = wibox.layout.align.horizontal()
+ actionline_horizontal:set_expand("outside")
+ local actionline = wibox.container.constraint(actionline_horizontal, "exact", nil, style.actionline.height)
+ action_line_construct(actionline_horizontal, style)
+
+ -- Window state line construction
+ ------------------------------------------------------------
+
+ -- layouts
+ local stateline_horizontal = wibox.layout.flex.horizontal()
+ local stateline_vertical = wibox.layout.align.vertical()
+ stateline_vertical:set_second(stateline_horizontal)
+ stateline_vertical:set_expand("outside")
+ local stateline = wibox.container.constraint(stateline_vertical, "exact", nil, style.stateline.height)
+
+ -- set all state icons in line
+ local stateboxes = state_line_construct(state_icons, stateline_horizontal, style)
+
+ -- update function for state icons
+ local function stateboxes_update(c, icons, boxes)
+ for i, v in ipairs(icons) do
+ boxes[i]:set_color(v.indicator(c) and style.color.main or style.color.gray)
+ end
+ end
+
+ -- Separators config
+ ------------------------------------------------------------
+ local menusep = { widget = separator.horizontal(style.separator) }
+
+ -- menu item actions
+ self.movemenu_action = function(t)
+ last.client:move_to_tag(t); awful.layout.arrange(t.screen); self.hide_check("move")
+ end
+
+ self.addmenu_action = function(t)
+ last.client:toggle_tag(t); awful.layout.arrange(t.screen); self.hide_check("add")
+ end
+
+ -- Construct tag submenus ("move" and "add")
+ ------------------------------------------------------------
+ local movemenu_items = tagmenu_items(self.movemenu_action, style)
+ local addmenu_items = tagmenu_items(self.addmenu_action, style)
+
+ -- Create menu
+ ------------------------------------------------------------
+ self.menu = redmenu({
+ theme = style.menu,
+ items = {
+ { widget = actionline, focus = true },
+ menusep,
+ { "Move to tag", { items = movemenu_items, theme = style.tagmenu } },
+ { "Add to tag", { items = addmenu_items, theme = style.tagmenu } },
+ menusep,
+ { widget = stateline, focus = true }
+ }
+ })
+
+ -- Widget update functions
+ --------------------------------------------------------------------------------
+ function self:update(c)
+ if self.menu.wibox.visible then
+ stateboxes_update(c, state_icons, stateboxes)
+ tagmenu_update(c, self.menu, { 1, 2 }, style)
+ end
+ end
+
+ -- Signals setup
+ --------------------------------------------------------------------------------
+ local client_signals = {
+ "property::ontop", "property::floating", "property::below", "property::maximized",
+ "tagged", "untagged" -- refresh tagmenu when client's tags change
+ }
+ for _, sg in ipairs(client_signals) do
+ client.connect_signal(sg, function() self:update(last.client) end)
+ end
+end
+
+-- Show window menu widget
+-----------------------------------------------------------------------------------------------------------------------
+function clientmenu:show(c)
+
+ -- init menu if needed
+ if not self.menu then self:init() end
+
+ -- toggle menu
+ if self.menu.wibox.visible and c == last.client and mouse.screen == last.screen then
+ self.menu:hide()
+ else
+ last.client = c
+ last.screen = mouse.screen
+ self.menu:show({ coords = coords_calc(self.menu) })
+
+ if self.menu.hidetimer.started then self.menu.hidetimer:stop() end
+ self:update(c)
+ end
+end
+
+return setmetatable(clientmenu, clientmenu.mt)
diff --git a/awesome/.config/awesome/redflat/float/control.lua b/awesome/.config/awesome/redflat/float/control.lua
new file mode 100644
index 0000000..b8e75a5
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/control.lua
@@ -0,0 +1,358 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat floating window manager --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget to control single flating window size and posioning
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+
+local beautiful = require("beautiful")
+local awful = require("awful")
+local wibox = require("wibox")
+
+local rednotify = require("redflat.float.notify")
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local control = {}
+
+-- Resize mode alias
+local RESIZE_MODE = { FULL = 1, HORIZONTAL = 2, VERTICAL = 3 }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 400, height = 60 },
+ border_width = 2,
+ font = "Sans 14",
+ set_position = nil,
+ notify = {},
+ keytip = { geometry = { width = 600 } },
+ shape = nil,
+ steps = { 1, 10, 20, 50 },
+ default_step = 2,
+ onscreen = true,
+ margin = { icon = { onscreen = { 10, 10, 2, 2 }, mode = { 10, 10, 2, 2 } } },
+ icon = {
+ resize = {},
+ onscreen = redutil.base.placeholder({ txt = "X" }),
+ },
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", wibox = "#202020",
+ gray = "#575757", icon = "#a0a0a0" },
+ }
+
+ style.icon.resize[RESIZE_MODE.FULL] = redutil.base.placeholder({ txt = "F" })
+ style.icon.resize[RESIZE_MODE.HORIZONTAL] = redutil.base.placeholder({ txt = "H" })
+ style.icon.resize[RESIZE_MODE.VERTICAL] = redutil.base.placeholder({ txt = "V" })
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.control") or {})
+end
+
+-- key bindings
+control.keys = {}
+control.keys.control = {
+ {
+ { "Mod4" }, "c", function() control:center() end,
+ { description = "Put window at the center", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "q", function() control:resize() end,
+ { description = "Increase window size", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "a", function() control:resize(true) end,
+ { description = "Decrease window size", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "l", function() control:move("right") end,
+ { description = "Move window to right", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "j", function() control:move("left") end,
+ { description = "Move window to left", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "k", function() control:move("bottom") end,
+ { description = "Move window to bottom", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "i", function() control:move("top") end,
+ { description = "Move window to top", group = "Window control" }
+ },
+ {
+ { "Mod4" }, "n", function() control:switch_resize_mode() end,
+ { description = "Switch moving/resizing mode", group = "Mode" }
+ },
+ {
+ { "Mod4" }, "s", function() control:switch_onscreen() end,
+ { description = "Switch off screen check", group = "Mode" }
+ },
+}
+control.keys.action = {
+ {
+ { "Mod4" }, "Super_L", function() control:hide() end,
+ { description = "Close top list widget", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+control.keys.all = awful.util.table.join(control.keys.control, control.keys.action)
+
+control._fake_keys = {
+ {
+ {}, "N", nil,
+ { description = "Select move/resize step", group = "Mode",
+ keyset = { "1", "2", "3", "4", "5", "6", "7", "8", "9" } }
+ },
+}
+
+
+-- Support function
+-----------------------------------------------------------------------------------------------------------------------
+local function control_off_screen(window)
+ local wa = screen[mouse.screen].workarea
+ local newg = window:geometry()
+
+ if newg.width > wa.width then window:geometry({ width = wa.width, x = wa.x }) end
+ if newg.height > wa.height then window:geometry({ height = wa.height, y = wa.y }) end
+
+ redutil.placement.no_offscreen(window, nil, wa)
+end
+
+-- Initialize widget
+-----------------------------------------------------------------------------------------------------------------------
+function control:init()
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local style = default_style()
+ self.style = style
+ self.client = nil
+ self.step = style.steps[style.default_step]
+
+ self.resize_mode = RESIZE_MODE.FULL
+ self.onscreen = style.onscreen
+
+ -- Create floating wibox for top widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:geometry(style.geometry)
+
+ -- Widget layout setup
+ --------------------------------------------------------------------------------
+ self.label = wibox.widget.textbox()
+ self.label:set_align("center")
+ self.label:set_font(style.font)
+
+ self.onscreen_icon = svgbox(self.style.icon.onscreen)
+ self.onscreen_icon:set_color(self.onscreen and self.style.color.main or self.style.color.icon)
+
+ self.mode_icon = svgbox(self.style.icon.resize[self.resize_mode])
+ self.mode_icon:set_color(self.style.color.icon)
+
+ self.wibox:setup({
+ wibox.container.margin(self.onscreen_icon, unpack(self.style.margin.icon.onscreen)),
+ self.label,
+ wibox.container.margin(self.mode_icon, unpack(self.style.margin.icon.mode)),
+ layout = wibox.layout.align.horizontal
+ })
+
+ -- Keygrabber
+ --------------------------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event == "release" then
+ for _, k in ipairs(self.keys.action) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ else
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ if string.match("123456789", key) then self:choose_step(tonumber(key)) end
+ end
+ end
+
+ -- First run actions
+ --------------------------------------------------------------------------------
+ self:set_keys()
+end
+
+-- Window control
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Put window at center of screen
+--------------------------------------------------------------------------------
+function control:center()
+ if not self.client then return end
+ redutil.placement.centered(self.client, nil, mouse.screen.workarea)
+
+ if self.onscreen then control_off_screen(self.client) end
+ self:update()
+end
+
+-- Change window size
+--------------------------------------------------------------------------------
+function control:resize(is_shrinking)
+ if not self.client then return end
+
+ -- calculate new size
+ local g = self.client:geometry()
+ local d = self.step * (is_shrinking and -1 or 1)
+ local newg
+
+ if self.resize_mode == RESIZE_MODE.FULL then
+ newg = { x = g.x - d, y = g.y - d, width = g.width + 2 * d, height = g.height + 2 * d }
+ elseif self.resize_mode == RESIZE_MODE.HORIZONTAL then
+ newg = { x = g.x - d, width = g.width + 2 * d }
+ elseif self.resize_mode == RESIZE_MODE.VERTICAL then
+ newg = { y = g.y - d, height = g.height + 2 * d }
+ end
+
+ -- validate new size
+ if newg.height and newg.height <= 0 or newg.width and newg.width < 0 then return end
+
+ -- apply new size
+ self.client:geometry(newg)
+ if self.onscreen then control_off_screen(self.client) end
+ self:update()
+end
+
+-- Move by direction
+--------------------------------------------------------------------------------
+function control:move(direction)
+ if not self.client then return end
+
+ local g = self.client:geometry()
+ local d = self.step * ((direction == "left" or direction == "top") and -1 or 1)
+
+ if direction == "left" or direction == "right" then
+ self.client:geometry({ x = g.x + d })
+ else
+ self.client:geometry({ y = g.y + d })
+ end
+
+ if self.onscreen then control_off_screen(self.client) end
+end
+
+
+-- Widget actions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Update
+--------------------------------------------------------------------------------
+function control:update()
+ if not self.client then return end
+
+ local g = self.client:geometry()
+ local size_label = string.format("%sx%s", g.width, g.height)
+
+ self.label:set_markup(string.format(
+ '%s [%d]',
+ self.style.color.text, size_label, self.style.color.gray, self.step
+ ))
+end
+
+-- Select move/resize step by index
+--------------------------------------------------------------------------------
+function control:choose_step(index)
+ if self.style.steps[index] then self.step = self.style.steps[index] end
+ self:update()
+end
+
+-- Switch resize mode
+--------------------------------------------------------------------------------
+function control:switch_resize_mode()
+ self.resize_mode = self.resize_mode + 1
+ if not awful.util.table.hasitem(RESIZE_MODE, self.resize_mode) then self.resize_mode = RESIZE_MODE.FULL end
+
+ self.mode_icon:set_image(self.style.icon.resize[self.resize_mode])
+end
+
+-- Switch onscreen mode
+--------------------------------------------------------------------------------
+function control:switch_onscreen()
+ self.onscreen = not self.onscreen
+ self.onscreen_icon:set_color(self.onscreen and self.style.color.main or self.style.color.icon)
+
+ if self.onscreen then
+ control_off_screen(self.client)
+ self:update()
+ end
+end
+
+-- Show
+--------------------------------------------------------------------------------
+function control:show()
+ if not self.wibox then self:init() end
+
+ if not self.wibox.visible then
+ -- check if focused client floating
+ local layout = awful.layout.get(mouse.screen)
+ local is_floating = client.focus and (client.focus.floating or layout.name == "floating")
+ and not client.focus.maximized
+
+ if not is_floating then
+ rednotify:show(redutil.table.merge({ text = "No floating window focused" }, self.style.notify))
+ return
+ end
+ self.client = client.focus
+
+ -- show widget
+ if self.style.set_position then
+ self.style.set_position(self.wibox)
+ else
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, screen[mouse.screen].workarea)
+
+ self:update()
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+ redtip:set_pack(
+ "Floating window", self.tip, self.style.keytip.column, self.style.keytip.geometry,
+ function() self:hide() end
+ )
+ end
+end
+
+-- Hide
+--------------------------------------------------------------------------------
+function control:hide()
+ self.wibox.visible = false
+ awful.keygrabber.stop(self.keygrabber)
+ redtip:remove_pack()
+ self.client = nil
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function control:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.control, self.keys.action) end
+ end
+
+ self.tip = awful.util.table.join(self.keys.all, self._fake_keys)
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return control
diff --git a/awesome/.config/awesome/redflat/float/decoration.lua b/awesome/.config/awesome/redflat/float/decoration.lua
new file mode 100644
index 0000000..1b32068
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/decoration.lua
@@ -0,0 +1,88 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat decorations --
+-----------------------------------------------------------------------------------------------------------------------
+--
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local awful = require("awful")
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local decor = {}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function button_style()
+ local style = {
+ color = { shadow3 = "#1c1c1c", button = "#575757",
+ shadow4 = "#767676", text = "#cccccc", pressed = "404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.decoration.button") or {})
+end
+
+local function field_style()
+ local style = {
+ color = { bg = "#161616", shadow1 = "#141414", shadow2 = "#313131" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.decoration.field") or {})
+end
+
+-- Button element
+-----------------------------------------------------------------------------------------------------------------------
+function decor.button(textbox, action, style)
+
+ style = redutil.table.merge(button_style(), style or {})
+
+ -- Widget and layouts
+ --------------------------------------------------------------------------------
+ textbox:set_align("center")
+ local button_widget = wibox.container.background(textbox, style.color.button)
+ button_widget:set_fg(style.color.text)
+
+ local bord1 = wibox.container.background(wibox.container.margin(button_widget, 1, 1, 1, 1), style.color.shadow4)
+ local bord2 = wibox.container.background(wibox.container.margin(bord1, 1, 1, 1, 1), style.color.shadow3)
+
+ -- Button
+ --------------------------------------------------------------------------------
+ local press_func = function()
+ button_widget:set_bg(style.color.pressed)
+ end
+ local release_func = function()
+ button_widget:set_bg(style.color.button)
+ action()
+ end
+
+ button_widget:buttons(awful.button({}, 1, press_func, release_func))
+
+ -- Signals
+ --------------------------------------------------------------------------------
+ button_widget:connect_signal(
+ "mouse::leave",
+ function()
+ button_widget:set_bg(style.color.button)
+ end
+ )
+
+ --------------------------------------------------------------------------------
+ return bord2
+end
+
+-- Input text field
+-----------------------------------------------------------------------------------------------------------------------
+function decor.textfield(textbox, style)
+ style = redutil.table.merge(field_style(), style or {})
+ local field = wibox.container.background(textbox, style.color.bg)
+ local bord1 = wibox.container.background(wibox.container.margin(field, 1, 1, 1, 1), style.color.shadow1)
+ local bord2 = wibox.container.background(wibox.container.margin(bord1, 1, 1, 1, 1), style.color.shadow2)
+ return bord2
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return decor
diff --git a/awesome/.config/awesome/redflat/float/hotkeys.lua b/awesome/.config/awesome/redflat/float/hotkeys.lua
new file mode 100644
index 0000000..a3bb7d1
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/hotkeys.lua
@@ -0,0 +1,361 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat hotkeys helper widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with list of hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local math = math
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+
+local redflat = require("redflat")
+local redutil = require("redflat.util")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local hotkeys = { keypack = {}, lastkey = nil, cache = {}, boxes = {} }
+local hasitem = awful.util.table.hasitem
+
+-- key bindings
+hotkeys.keys = { close = { "Escape" }, close_all = { "Super_L" } }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 800 },
+ border_margin = { 10, 10, 10, 10 },
+ tspace = 5,
+ delim = " ",
+ border_width = 2,
+ ltimeout = 0.05,
+ font = "Sans 12",
+ keyfont = "Sans bold 12",
+ titlefont = "Sans bold 14",
+ is_align = false,
+ separator = {},
+ heights = { key = 20, title = 24 },
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", wibox = "#202020",
+ gray = "#575757" },
+ shape = nil
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.hotkeys") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Calculate keytip length
+--------------------------------------------------------------------------------
+local function check_key_len(k)
+ local res = k.key:len()
+ for _, v in pairs(k.mod) do res = res + v:len() + 1 end
+ return res
+end
+
+-- Parse raw key table
+--------------------------------------------------------------------------------
+local keysort = function(a, b)
+ if a.length ~= b.length then
+ return a.length < b.length
+ else
+ return a.key < b.key
+ end
+end
+
+local function parse(rawkeys, columns)
+ local keys = {}
+ columns = columns or 1
+
+ local rk = {}
+ for _, k in ipairs(rawkeys) do if k[#k].description then table.insert(rk, k) end end
+ local p = math.ceil(#rk / columns)
+
+ -- dirty trick for raw sorting
+ local sp = {}
+ for _, v in ipairs(rk) do
+ if not hasitem(sp, v[#v].group) then table.insert(sp, v[#v].group) end
+ end
+ table.sort(rk, function(a, b)
+ local ai, bi = hasitem(sp, a[#a].group), hasitem(sp, b[#b].group)
+ if ai ~= bi then
+ return ai < bi
+ else
+ return a[2] < b[2]
+ end
+ end)
+
+ -- split keys to columns
+ for i = 1, columns do
+ keys[i] = { groups = {}, length = nil, names = {} }
+ local chunk = { unpack(rk, 1, p) }
+ rk = { unpack(rk, p + 1) }
+
+ -- build key column
+ for _, v in ipairs(chunk) do
+ local data = v[#v]
+ local k = {
+ mod = v[1], key = v[2],
+ description = data.description,
+ group = data.group,
+ keyset = data.keyset or { v[2] },
+ length = check_key_len({ mod = v[1], key = v[2] })
+ }
+
+ if not keys[i].groups[k.group] then
+ keys[i].groups[k.group] = {}
+ table.insert(keys[i].names, k.group) -- sorted names list to save group order
+ end
+ table.insert(keys[i].groups[k.group], k)
+
+ -- calculate max tip lenght
+ if not keys[i].length or keys[i].length < k.length then keys[i].length = k.length end
+ end
+
+ -- sort key by lenght inside group
+ for _, group in pairs(keys[i].groups) do table.sort(group, keysort) end
+ end
+
+ return keys
+end
+
+-- Form hotkeys helper text
+--------------------------------------------------------------------------------
+local function build_tip(pack, style, keypressed)
+ local text = {}
+
+ for i, column in ipairs(pack) do
+ local coltxt = {}
+ local height = 0
+
+ for _, name in pairs(column.names) do
+ local group = column.groups[name]
+
+ -- set group title
+ coltxt[#coltxt + 1] = string.format(
+ '%s',
+ style.titlefont, style.color.gray, name
+ )
+ height = height + style.heights.title
+
+ -- build key tip line
+ for _, key in ipairs(group) do
+
+ -- key with align
+ local line = string.format('%s', key.key)
+ if style.is_align then
+ --noinspection StringConcatenationInLoops
+ line = line .. string.rep(" ", column.length - key.length)
+ end
+
+ -- key with mods
+ if #key.mod > 0 then
+ local fm = {}
+ for ki, v in ipairs(key.mod) do fm[ki] = string.format('%s', v) end
+ table.insert(fm, line)
+ line = table.concat(fm, string.format('+', style.color.gray))
+ end
+
+ -- key with description
+ local clr = keypressed and hasitem(key.keyset, keypressed) and style.color.main or style.color.text
+ line = string.format(
+ '%s%s%s',
+ clr, style.keyfont, line, style.delim, key.description
+ )
+ coltxt[#coltxt + 1] = line
+ height = height + style.heights.key
+ end
+ end
+
+ text[i] = { text = table.concat(coltxt, '\n'), height = height }
+ end
+
+ return text
+end
+
+-- Initialize widget
+-----------------------------------------------------------------------------------------------------------------------
+function hotkeys:init()
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local style = default_style()
+ self.style = style
+ self.tip = {}
+
+ -- summary vertical size for all elements except tip textboxes
+ -- used to auto adjust widget height
+ self.vertical_pag = style.border_margin[3] + style.border_margin[4] + style.tspace + 2
+ if style.separator.marginh then
+ self.vertical_pag = self.vertical_pag + style.separator.marginh[3] + style.separator.marginh[4]
+ end
+
+ -- alias
+ local bm = style.border_margin
+
+ -- Create floating wibox for top widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:geometry(style.geometry)
+
+ -- Widget layout setup
+ --------------------------------------------------------------------------------
+ self.layout = wibox.layout.flex.horizontal()
+
+ self.title = wibox.widget.textbox("Title")
+ self.title:set_align("center")
+ self.title:set_font(style.titlefont)
+
+ local _, th = self.title:get_preferred_size()
+ self.vertical_pag = self.vertical_pag + th
+
+ local subtitle = wibox.widget.textbox("Press any key to highlight tip, Escape for exit")
+ subtitle:set_align("center")
+
+ local _, sh = subtitle:get_preferred_size()
+ self.vertical_pag = self.vertical_pag + sh
+
+ self.wibox:setup({
+ {
+ {
+ self.title,
+ subtitle,
+ redflat.gauge.separator.horizontal(style.separator),
+ spacing = style.tspace,
+ layout = wibox.layout.fixed.vertical,
+ },
+ self.layout,
+ layout = wibox.layout.align.vertical,
+ },
+ left = bm[1], right = bm[2], top = bm[3], bottom = bm[4],
+ layout = wibox.container.margin,
+ })
+
+ -- Highlight timer
+ --------------------------------------------------------------------------------
+ local ltimer = timer({ timeout = style.ltimeout })
+ ltimer:connect_signal("timeout",
+ function()
+ ltimer:stop()
+ self:highlight()
+ end
+ )
+
+ -- Keygrabber
+ --------------------------------------------------------------------------------
+ self.keygrabber = function(_, key, event)
+ if event == "release" then
+ if hasitem(self.keys.close, key) then
+ self:hide(); return
+ end
+
+ if hasitem(self.keys.close_all, key) then
+ self:hide()
+ if self.keypack[#self.keypack].on_close then self.keypack[#self.keypack].on_close() end
+ return
+ end
+ end
+
+ self.lastkey = event == "press" and key or nil
+ ltimer:again()
+ end
+end
+
+
+-- Keypack managment
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Set new keypack
+--------------------------------------------------------------------------------
+function hotkeys:set_pack(name, pack, columns, geometry, on_close)
+ if not self.wibox then self:init() end
+
+ if not self.cache[name] then self.cache[name] = parse(pack, columns) end
+ table.insert(
+ self.keypack,
+ { name = name, pack = self.cache[name], geometry = geometry or self.style.geometry, on_close = on_close }
+ )
+ self.title:set_text(name .. " hotkeys")
+ self:highlight()
+ self:update_geometry(self.keypack[#self.keypack].geometry)
+end
+
+-- Remove current keypack
+--------------------------------------------------------------------------------
+function hotkeys:remove_pack()
+ table.remove(self.keypack)
+ self.title:set_text(self.keypack[#self.keypack].name .. " hotkeys")
+ self:highlight()
+ self:update_geometry(self.keypack[#self.keypack].geometry)
+end
+
+-- Calculate and set widget height
+--------------------------------------------------------------------------------
+function hotkeys:update_geometry(predefined)
+ local height = 0
+ for _, column in ipairs(self.tip) do height = math.max(height, column.height) end
+
+ self.wibox:geometry({ width = predefined.width, height = predefined.height or height + self.vertical_pag })
+end
+
+-- Highlight key tip
+--------------------------------------------------------------------------------
+function hotkeys:highlight()
+ self.tip = build_tip(self.keypack[#self.keypack].pack, self.style, self.lastkey)
+
+ self.layout:reset()
+ for i, column in ipairs(self.tip) do
+ if not self.boxes[i] then
+ self.boxes[i] = wibox.widget.textbox()
+ self.boxes[i]:set_valign("top")
+ self.boxes[i]:set_font(self.style.font)
+ end
+
+ self.boxes[i]:set_markup(column.text)
+ self.layout:add(self.boxes[i])
+ end
+end
+
+
+-- Show/hide widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- show
+function hotkeys:show()
+ if not self.wibox then self:init() end
+
+ if not self.wibox.visible then
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+ -- else
+ -- self:hide()
+ end
+end
+
+-- hide
+function hotkeys:hide()
+ self.wibox.visible = false
+ self.lastkey = nil
+ self:highlight()
+ awful.keygrabber.stop(self.keygrabber)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return hotkeys
diff --git a/awesome/.config/awesome/redflat/float/init.lua b/awesome/.config/awesome/redflat/float/init.lua
new file mode 100644
index 0000000..08da504
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.float" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/float/keychain.lua b/awesome/.config/awesome/redflat/float/keychain.lua
new file mode 100644
index 0000000..d98d24f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/keychain.lua
@@ -0,0 +1,202 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat prefix hotkey manager --
+-----------------------------------------------------------------------------------------------------------------------
+-- Emacs like key key sequences
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local string = string
+local table = table
+
+local wibox = require("wibox")
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local redflat = require("redflat")
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local keychain = {}
+local tip_cache = {}
+
+local label_pattern = { Mod1 = "A", Mod4 = "M", Control = "C", Shift = "S" }
+
+-- key bindings
+keychain.service = { close = { "Escape" }, help = { "F1" }, stepback = { "BackSpace" } }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 220, height = 60 },
+ font = "Sans 14 bold",
+ border_width = 2,
+ keytip = { geometry = { width = 500 }, exit = false },
+ color = { border = "#575757", wibox = "#202020" },
+ shape = nil
+ }
+
+ return redflat.util.table.merge(style, redflat.util.table.check(beautiful, "float.keychain") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function build_label(item)
+ if #item[1] == 0 then return item[2] end
+
+ local mods = {}
+ for _, m in ipairs(item[1]) do mods[#mods + 1] = label_pattern[m] end
+ return string.format("%s-%s", table.concat(mods, '-'), item[2])
+end
+
+local function build_tip(store, item, prefix)
+ prefix = prefix or build_label(item)
+ for _, k in ipairs(item[3]) do
+ local p = prefix .. " " .. build_label(k)
+ if type(k[3]) == "table" then
+ build_tip(store, k, p)
+ else
+ table.insert(store, { {}, p, nil, k[#k] })
+ end
+ end
+
+ return store
+end
+
+local function build_fake_keys(keys)
+ local res = {}
+ for _, keygroup in ipairs({
+ { description = "Undo last key", group = "Action", keyname = "stepback" },
+ { description = "Undo sequence", group = "Action", keyname = "close" },
+ { description = "Show hotkeys helper", group = "Action", keyname = "help" },
+ })
+ do
+ for _, k in ipairs(keys[keygroup.keyname]) do
+ table.insert(res, {
+ {}, k, nil,
+ { description = keygroup.description, group = keygroup.group }
+ })
+ end
+ end
+ return res
+end
+
+-- Main widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Initialize keychain widget
+--------------------------------------------------------------------------------
+function keychain:init(style)
+
+ -- Init vars
+ ------------------------------------------------------------
+ self.active = nil
+ self.parents = {}
+ self.sequence = ""
+
+ style = redflat.util.table.merge(default_style(), style or {})
+ self.style = style
+
+ -- Wibox
+ ------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+ self.wibox:geometry(style.geometry)
+
+ self.label = wibox.widget.textbox()
+ self.label:set_align("center")
+ self.wibox:set_widget(self.label)
+
+ self.label:set_font(style.font)
+
+ -- Keygrabber
+ ------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event == "press" then return false end
+
+ -- dirty fix for first key release
+ if self.actkey == key and #mod == 0 then self.actkey = nil; return end
+
+ if awful.util.table.hasitem(self.service.close, key) then self:hide()
+ elseif awful.util.table.hasitem(self.service.stepback, key) then self:undo()
+ elseif awful.util.table.hasitem(self.service.help, key) then redtip:show()
+ else
+ for _, item in ipairs(self.active[3]) do
+ if redutil.key.match_grabber(item, mod, key) then self:activate(item); return end
+ end
+ end
+ end
+end
+
+-- Set current key item
+--------------------------------------------------------------------------------
+function keychain:activate(item, keytip)
+ if not self.wibox then self:init() end
+ self.actkey = keytip and item[2]
+
+ if type(item[3]) == "function" then
+ item[3]()
+ self:hide()
+ else
+ if not self.active then
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+ else
+ self.parents[#self.parents + 1] = self.active
+ end
+
+ self.active = item
+ local label = build_label(self.active)
+ self.sequence = self.sequence == "" and label or self.sequence .. " " .. label
+ self.label:set_text(self.sequence)
+ end
+
+ -- build keys helper tip
+ if keytip then
+ if tip_cache[keytip] then
+ self.tip = tip_cache[keytip]
+ else
+ self.tip = awful.util.table.join(build_tip({}, item), build_fake_keys(self.service))
+ tip_cache[keytip] = self.tip
+ end
+ redtip:set_pack(keytip .. " keychain", self.tip, self.style.keytip.column, self.style.keytip.geometry)
+ end
+end
+
+-- Deactivate last key item
+--------------------------------------------------------------------------------
+function keychain:undo()
+ if #self.parents > 0 then
+ self.sequence = self.sequence:sub(1, - (#build_label(self.active) + 2))
+ self.label:set_text(self.sequence)
+
+ self.active = self.parents[#self.parents]
+ self.parents[#self.parents] = nil
+ else
+ self:hide()
+ end
+end
+
+-- Hide widget
+--------------------------------------------------------------------------------
+function keychain:hide()
+ self.wibox.visible = false
+ awful.keygrabber.stop(self.keygrabber)
+ self.active = nil
+ self.parents = {}
+ self.sequence = ""
+ redtip:remove_pack()
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return keychain
diff --git a/awesome/.config/awesome/redflat/float/notify.lua b/awesome/.config/awesome/redflat/float/notify.lua
new file mode 100644
index 0000000..db62a4f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/notify.lua
@@ -0,0 +1,140 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat notify widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Floating widget with icon, text, and progress bar
+-- special for volume and brightness indication
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local progressbar = require("redflat.gauge.graph.bar")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local notify = { last = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 480, height = 100 },
+ screen_gap = 0,
+ set_position = nil,
+ border_margin = { 20, 20, 20, 20 },
+ elements_margin = { 20, 0, 10, 10 },
+ bar_width = 8,
+ font = "Sans 14",
+ border_width = 2,
+ timeout = 5,
+ icon = nil,
+ progressbar = {},
+ color = { border = "#575757", icon = "#aaaaaa", wibox = "#202020" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.notify") or {})
+end
+
+-- Initialize notify widget
+-----------------------------------------------------------------------------------------------------------------------
+function notify:init()
+
+ local style = default_style()
+ -- local icon = style.icon
+
+ self.style = style
+
+ -- Construct layouts
+ --------------------------------------------------------------------------------
+ local area = wibox.layout.align.horizontal()
+
+ local bar = progressbar(style.progressbar)
+ local image = svgbox()
+ local text = wibox.widget.textbox("100%")
+ text:set_align("center")
+ -- text:set_font(style.font)
+
+ local align_vertical = wibox.layout.align.vertical()
+ bar:set_forced_height(style.bar_width)
+
+ area:set_left(image)
+ area:set_middle(wibox.container.margin(align_vertical, unpack(style.elements_margin)))
+
+ -- Create floating wibox for notify widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:set_widget(wibox.container.margin(area, unpack(style.border_margin)))
+ self.wibox:geometry(style.geometry)
+
+ -- Set info function
+ --------------------------------------------------------------------------------
+ function self:set(args)
+ args = args or {}
+ align_vertical:reset()
+
+ if args.value then
+ bar:set_value(args.value)
+ align_vertical:set_top(text)
+ align_vertical:set_bottom(bar)
+ else
+ align_vertical:set_middle(text)
+ end
+
+ if args.text then
+ text:set_text(args.text)
+ text:set_font(args.font ~= nil and args.font or style.font)
+ end
+
+ image:set_image(args.icon ~= nil and args.icon or style.icon)
+ image:set_color(args.color or style.color.icon)
+ end
+
+ -- Set autohide timer
+ --------------------------------------------------------------------------------
+ self.hidetimer = timer({ timeout = style.timeout })
+ self.hidetimer:connect_signal("timeout", function() self:hide() end)
+
+ -- Signals setup
+ --------------------------------------------------------------------------------
+ self.wibox:connect_signal("mouse::enter", function() self:hide() end)
+end
+
+-- Hide notify widget
+-----------------------------------------------------------------------------------------------------------------------
+function notify:hide()
+ self.wibox.visible = false
+ self.hidetimer:stop()
+end
+
+-- Show notify widget
+-----------------------------------------------------------------------------------------------------------------------
+function notify:show(args)
+ if not self.wibox then self:init() end
+ self:set(args)
+
+ if not self.wibox.visible or mouse.screen.index ~= self.last.screen then
+ if self.style.set_position then self.style.set_position(self.wibox) end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, mouse.screen.workarea)
+ self.wibox.visible = true
+ end
+
+ self.last.screen = mouse.screen.index
+ self.hidetimer:again()
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return notify
diff --git a/awesome/.config/awesome/redflat/float/player.lua b/awesome/.config/awesome/redflat/float/player.lua
new file mode 100644
index 0000000..62f6daf
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/player.lua
@@ -0,0 +1,505 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat audio player widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Music player widget
+-- Display audio track information with mpris2
+-- Using dbus-send to control
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+local math = math
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local progressbar = require("redflat.gauge.graph.bar")
+local dashcontrol = require("redflat.gauge.graph.dash")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local player = { box = {}, listening = false }
+
+local dbus_mpris = "dbus-send --print-reply=literal --session --dest=org.mpris.MediaPlayer2.%s "
+ .. "/org/mpris/MediaPlayer2 "
+
+local dbus_get = dbus_mpris
+ .. "org.freedesktop.DBus.Properties.Get "
+ .. "string:'org.mpris.MediaPlayer2.Player' %s"
+
+local dbus_getall = dbus_mpris
+ .. "org.freedesktop.DBus.Properties.GetAll "
+ .. "string:'org.mpris.MediaPlayer2.Player'"
+
+local dbus_set = dbus_mpris
+ .. "org.freedesktop.DBus.Properties.Set "
+ .. "string:'org.mpris.MediaPlayer2.Player' %s"
+
+local dbus_action = dbus_mpris
+ .. "org.mpris.MediaPlayer2.Player."
+
+-- Helper function to decode URI string format
+-----------------------------------------------------------------------------------------------------------------------
+local function decodeURI(s)
+ return string.gsub(s, '%%(%x%x)', function(hex) return string.char(tonumber(hex, 16)) end)
+end
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 520, height = 150 },
+ screen_gap = 0,
+ set_position = nil,
+ dashcontrol = {},
+ progressbar = {},
+ border_margin = { 20, 20, 20, 20 },
+ elements_margin = { 20, 0, 0, 0 },
+ volume_margin = { 0, 0, 0, 3 },
+ controls_margin = { 0, 0, 18, 8 },
+ buttons_margin = { 0, 0, 3, 3 },
+ pause_margin = { 12, 12, 0, 0 },
+ timeout = 5,
+ line_height = 26,
+ bar_width = 8, -- progress bar height
+ volume_width = 50,
+ titlefont = "Sans 12",
+ timefont = "Sans 12",
+ artistfont = "Sans 12",
+ border_width = 2,
+ icon = {
+ cover = redutil.base.placeholder(),
+ play = redutil.base.placeholder({ txt = "►" }),
+ pause = redutil.base.placeholder({ txt = "[]" }),
+ next_tr = redutil.base.placeholder({ txt = "→" }),
+ prev_tr = redutil.base.placeholder({ txt = "←" }),
+ },
+ color = { border = "#575757", main = "#b1222b",
+ wibox = "#202020", gray = "#575757", icon = "#a0a0a0" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.player") or {})
+end
+
+
+-- Initialize player widget
+-----------------------------------------------------------------------------------------------------------------------
+function player:init(args)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local _player = args.name or "vlc"
+ local style = default_style()
+ local show_album = false
+
+ self.info = { artist = "Unknown", album = "Unknown" }
+ self.style = style
+ self.last = { status = "Stopped", length = 5 * 60 * 1000000, volume = nil }
+
+ -- dbus vars
+ self.command = {
+ get_all = string.format(dbus_getall, _player),
+ get_position = string.format(dbus_get, _player, "string:'Position'"),
+ get_volume = string.format(dbus_get, _player, "string:'Volume'"),
+ set_volume = string.format(dbus_set, _player, "string:'Volume' variant:double:"),
+ action = string.format(dbus_action, _player),
+ set_position = string.format(dbus_action, _player) .. "SetPosition objpath:/not/used int64:",
+ }
+
+ self._actions = { "PlayPause", "Next", "Previous" }
+
+ -- Construct layouts
+ --------------------------------------------------------------------------------
+
+ -- progressbar and icon
+ self.bar = progressbar(style.progressbar)
+ self.box.image = svgbox(style.icon.cover)
+ self.box.image:set_color(style.color.gray)
+
+ -- Text lines
+ ------------------------------------------------------------
+ self.box.title = wibox.widget.textbox("Title")
+ self.box.artist = wibox.widget.textbox("Artist")
+ self.box.title:set_font(style.titlefont)
+ self.box.title:set_valign("top")
+ self.box.artist:set_font(style.artistfont)
+ self.box.artist:set_valign("top")
+
+ local text_area = wibox.layout.fixed.vertical()
+ text_area:add(wibox.container.constraint(self.box.title, "exact", nil, style.line_height))
+ text_area:add(wibox.container.constraint(self.box.artist, "exact", nil, style.line_height))
+
+ -- Control line
+ ------------------------------------------------------------
+
+ -- playback buttons
+ local player_buttons = wibox.layout.fixed.horizontal()
+ local prev_button = svgbox(style.icon.prev_tr, nil, style.color.icon)
+ player_buttons:add(prev_button)
+
+ self.play_button = svgbox(style.icon.play, nil, style.color.icon)
+ player_buttons:add(wibox.container.margin(self.play_button, unpack(style.pause_margin)))
+
+ local next_button = svgbox(style.icon.next_tr, nil, style.color.icon)
+ player_buttons:add(next_button)
+
+ -- time indicator
+ self.box.time = wibox.widget.textbox("0:00")
+ self.box.time:set_font(style.timefont)
+
+ -- volume
+ self.volume = dashcontrol(style.dashcontrol)
+ local volumespace = wibox.container.margin(self.volume, unpack(style.volume_margin))
+ local volume_area = wibox.container.constraint(volumespace, "exact", style.volume_width, nil)
+
+ -- full line
+ local buttons_align = wibox.layout.align.horizontal()
+ buttons_align:set_expand("outside")
+ buttons_align:set_middle(wibox.container.margin(player_buttons, unpack(style.buttons_margin)))
+
+ local control_align = wibox.layout.align.horizontal()
+ control_align:set_middle(buttons_align)
+ control_align:set_right(self.box.time)
+ control_align:set_left(volume_area)
+
+ -- Bring it all together
+ ------------------------------------------------------------
+ local align_vertical = wibox.layout.align.vertical()
+ align_vertical:set_top(text_area)
+ align_vertical:set_middle(wibox.container.margin(control_align, unpack(style.controls_margin)))
+ align_vertical:set_bottom(wibox.container.constraint(self.bar, "exact", nil, style.bar_width))
+ local area = wibox.layout.fixed.horizontal()
+ area:add(self.box.image)
+ area:add(wibox.container.margin(align_vertical, unpack(style.elements_margin)))
+
+ -- Buttons
+ ------------------------------------------------------------
+
+ -- playback controll
+ self.play_button:buttons(awful.util.table.join(awful.button({}, 1, function() self:action("PlayPause") end)))
+ next_button:buttons(awful.util.table.join(awful.button({}, 1, function() self:action("Next") end)))
+ prev_button:buttons(awful.util.table.join(awful.button({}, 1, function() self:action("Previous") end)))
+
+ -- volume
+ self.volume:buttons(awful.util.table.join(
+ awful.button({}, 4, function() self:change_volume( 0.05) end),
+ awful.button({}, 5, function() self:change_volume(-0.05) end)
+ ))
+
+ -- position
+ self.bar:buttons(awful.util.table.join(
+ awful.button(
+ {}, 1, function()
+ local coords = {
+ bar = mouse.current_widget_geometry,
+ wibox = mouse.current_wibox:geometry(),
+ mouse = mouse.coords(),
+ }
+
+ local position = (coords.mouse.x - coords.wibox.x - coords.bar.x) / coords.bar.width
+ awful.spawn.with_shell(self.command.set_position .. math.floor(self.last.length * position))
+ end
+ )
+ ))
+
+ -- switch between artist and album info on mouse click
+ self.box.artist:buttons(awful.util.table.join(
+ awful.button({}, 1,
+ function()
+ show_album = not show_album
+ self.update_artist()
+ end
+ )
+ ))
+
+ -- Create floating wibox for player widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:set_widget(wibox.container.margin(area, unpack(style.border_margin)))
+ self.wibox:geometry(style.geometry)
+
+ -- Update info functions
+ --------------------------------------------------------------------------------
+
+ -- Function to set play button state
+ ------------------------------------------------------------
+ self.set_play_button = function(state)
+ self.play_button:set_image(style.icon[state])
+ end
+
+ -- Function to set info for artist/album line
+ ------------------------------------------------------------
+ self.update_artist = function()
+ if show_album then
+ self.box.artist:set_markup('From ' .. self.info.album)
+ else
+ self.box.artist:set_markup('By ' .. self.info.artist)
+ end
+ end
+
+ -- Set defs
+ ------------------------------------------------------------
+ self.clear_info = function(is_att)
+ self.box.image:set_image(style.icon.cover)
+ self.box.image:set_color(is_att and style.color.main or style.color.gray)
+
+ self.box.time:set_text("0:00")
+ self.bar:set_value(0)
+ -- self.box.title:set_text("Stopped")
+ self.info = { artist = "", album = "" }
+ self.update_artist()
+
+ self.last.volume = nil
+ end
+
+ -- Main update function
+ ------------------------------------------------------------
+ function self:update()
+ if self.last.status ~= "Stopped" then
+ awful.spawn.easy_async(
+ self.command.get_position,
+ function(output, _, _, exit_code)
+
+ -- dirty trick to clean up if player closed
+ if exit_code ~= 0 then
+ self.clear_info(true)
+ self.last.status = "Stopped"
+ return
+ end
+
+ -- set progress bar
+ local position = string.match(output, "int64%s+(%d+)")
+ local progress = position / self.last.length
+ self.bar:set_value(progress)
+
+ -- set current time
+ local ps = math.floor(position / 10^6)
+ local ct = string.format("%d:%02d", math.floor(ps / 60), ps % 60)
+ self.box.time:set_text(ct)
+ end
+ )
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ self.updatetimer = timer({ timeout = style.timeout })
+ self.updatetimer:connect_signal("timeout", function() self:update() end)
+
+ -- Run dbus servise
+ --------------------------------------------------------------------------------
+ if not self.listening then self:listen() end
+ self:initialize_info()
+end
+
+-- Initialize all properties via dbus call
+-- should be called only once for initialization before the dbus signals trigger the updates
+-----------------------------------------------------------------------------------------------------------------------
+function player:initialize_info()
+ awful.spawn.easy_async(
+ self.command.get_all,
+ function(output, _, _, exit_code)
+
+ local data = { Metadata = {} }
+
+ local function parse_dbus_value(ident)
+ local regex = "(" .. ident .. ")%s+([a-z0-9]+)%s+(.-)%s-%)\n"
+ local _, _, value = output:match(regex)
+ if not value then return nil end
+
+ -- check for int64 type field
+ local int64_val = value:match("int64%s+(%d+)")
+ if int64_val then return tonumber(int64_val) end
+
+ -- check for double type field
+ local double_val = value:match("double%s+([%d.]+)")
+ if double_val then return tonumber(double_val) end
+
+ -- check for array type field as table, extract first entry only
+ local array_val = value:match("array%s%[%s+([^%],]+)")
+ if array_val then return { array_val } end
+
+ return value
+ end
+
+ if exit_code == 0 then
+ data.Metadata["xesam:title"] = parse_dbus_value("xesam:title")
+ data.Metadata["xesam:artist"] = parse_dbus_value("xesam:artist")
+ data.Metadata["xesam:album"] = parse_dbus_value("xesam:album")
+ data.Metadata["mpris:artUrl"] = parse_dbus_value("mpris:artUrl")
+ data.Metadata["mpris:length"] = parse_dbus_value("mpris:length")
+ data["Volume"] = parse_dbus_value("Volume")
+ data["Position"] = parse_dbus_value("Position")
+ data["PlaybackStatus"] = parse_dbus_value("PlaybackStatus")
+ self:update_from_metadata(data)
+ end
+ end
+ )
+end
+
+-- Player playback control
+-----------------------------------------------------------------------------------------------------------------------
+function player:action(args)
+ if not awful.util.table.hasitem(self._actions, args) then return end
+ if not self.wibox then self:init() end
+ awful.spawn.with_shell(self.command.action .. args)
+ self:update()
+end
+
+-- Player volume control
+-----------------------------------------------------------------------------------------------------------------------
+function player:change_volume(step)
+ local v = (self.last.volume or 0) + step
+ if v > 1 then v = 1
+ elseif v < 0 then v = 0 end
+
+ self.last.volume = v
+ awful.spawn.with_shell(self.command.set_volume .. v)
+end
+
+-- Hide player widget
+-----------------------------------------------------------------------------------------------------------------------
+function player:hide()
+ self.wibox.visible = false
+ if self.updatetimer.started then self.updatetimer:stop() end
+end
+
+-- Show player widget
+-----------------------------------------------------------------------------------------------------------------------
+function player:show(geometry)
+ if not self.wibox then self:init() end
+
+ if not self.wibox.visible then
+ self:update()
+
+ if geometry then
+ self.wibox:geometry(geometry)
+ elseif self.style.set_position then
+ self.style.set_position(self.wibox)
+ else
+ awful.placement.under_mouse(self.wibox)
+ end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, screen[mouse.screen].workarea)
+
+ self.wibox.visible = true
+ if self.last.status == "Playing" then self.updatetimer:start() end
+ else
+ self:hide()
+ end
+end
+
+-- Update property values from received metadata
+-----------------------------------------------------------------------------------------------------------------------
+function player:update_from_metadata(data)
+ -- empty call
+ if not data then return end
+
+ -- set track info if playing
+ if data.Metadata then
+ -- set song title
+ self.box.title:set_text(data.Metadata["xesam:title"] or "Unknown")
+
+ -- set album or artist info
+
+ self.info.artist = data.Metadata["xesam:artist"] and data.Metadata["xesam:artist"][1] or "Unknown"
+ self.info.album = data.Metadata["xesam:album"] or "Unknown"
+ self.update_artist()
+
+ -- set cover art
+ local has_cover = false
+ if data.Metadata["mpris:artUrl"] then
+ local image = string.match(data.Metadata["mpris:artUrl"], "file://(.+)")
+ if image then
+ self.box.image:set_color(nil)
+ has_cover = self.box.image:set_image(decodeURI(image))
+ end
+ end
+ if not has_cover then
+ -- reset to generic icon if no cover available
+ self.box.image:set_color(self.style.color.gray)
+ self.box.image:set_image(self.style.icon.cover)
+ end
+
+ -- track length
+ if data.Metadata["mpris:length"] then self.last.length = data.Metadata["mpris:length"] end
+ end
+
+ if data.PlaybackStatus then
+
+ -- check player status and set suitable play/pause button image
+ local state = data.PlaybackStatus == "Playing" and "pause" or "play"
+ self.set_play_button(state)
+ self.last.status = data.PlaybackStatus
+
+ -- stop/start update timer
+ if data.PlaybackStatus == "Playing" then
+ if self.wibox.visible then self.updatetimer:start() end
+ else
+ if self.updatetimer.started then self.updatetimer:stop() end
+ self:update()
+ end
+
+ -- clear track info if stoppped
+ if data.PlaybackStatus == "Stopped" then
+ self.clear_info()
+ end
+ end
+
+ -- volume
+ if data.Volume then
+ self.volume:set_value(data.Volume)
+ self.last.volume = data.Volume
+ elseif not self.last.volume then
+ -- try to grab volume explicitly if not supplied
+ awful.spawn.easy_async(
+ self.command.get_volume,
+ function(output, _, _, exit_code)
+
+ if exit_code ~= 0 then
+ return
+ end
+
+ local volume = tonumber(string.match(output, "double%s+([%d.]+)"))
+ if volume then
+ self.volume:set_value(volume)
+ self.last.volume = volume
+ end
+ end
+ )
+ end
+end
+
+-- Dbus signal setup
+-- update some info which avaliable from dbus signal
+-----------------------------------------------------------------------------------------------------------------------
+function player:listen()
+ dbus.request_name("session", "org.freedesktop.DBus.Properties")
+ dbus.add_match(
+ "session",
+ "path=/org/mpris/MediaPlayer2, interface='org.freedesktop.DBus.Properties', member='PropertiesChanged'"
+ )
+ dbus.connect_signal("org.freedesktop.DBus.Properties",
+ function (_, _, data)
+ self:update_from_metadata(data)
+ end
+ )
+
+ self.listening = true
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return player
diff --git a/awesome/.config/awesome/redflat/float/prompt.lua b/awesome/.config/awesome/redflat/float/prompt.lua
new file mode 100644
index 0000000..525e79f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/prompt.lua
@@ -0,0 +1,99 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat promt widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Promt widget with his own wibox placed on center of screen
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.widget.prompt v3.5.2
+------ (c) 2009 Julien Danjou
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local type = type
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local naughty = require("naughty")
+
+local redutil = require("redflat.util")
+local decoration = require("redflat.float.decoration")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local floatprompt = {}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ geometry = { width = 620, height = 120 },
+ margin = { 20, 20, 40, 40 },
+ border_width = 2,
+ naughty = {},
+ color = { border = "#575757", wibox = "#202020" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.prompt") or {})
+end
+
+-- Initialize prompt widget
+-- @param prompt Prompt to use
+-----------------------------------------------------------------------------------------------------------------------
+function floatprompt:init(args)
+
+ args = args or {}
+ local style = default_style()
+ self.style = style
+
+ -- Create prompt widget
+ --------------------------------------------------------------------------------
+ self.widget = wibox.widget.textbox()
+ self.widget:set_ellipsize("start")
+ self.prompt = args.prompt or " Run: "
+ self.decorated_widget = decoration.textfield(self.widget, style.field)
+
+ -- Create floating wibox for promt widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:set_widget(wibox.container.margin(self.decorated_widget, unpack(style.margin)))
+ self.wibox:geometry(style.geometry)
+end
+
+-- Run method for prompt widget
+-- Wibox appears on call and hides after command entered
+-----------------------------------------------------------------------------------------------------------------------
+function floatprompt:run()
+ if not self.wibox then self:init() end
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ self.wibox.visible = true
+
+ awful.prompt.run({
+ prompt = self.prompt,
+ textbox = self.widget,
+ exe_callback = function(input)
+ local result = awful.spawn(input)
+ if type(result) == "string" then
+ local notify_args = redutil.table.merge({ title = "Prompt", text = result }, self.style.naughty)
+ naughty.notify(notify_args)
+ end
+ end,
+ history_path = awful.util.getdir("cache") .. "/history",
+ history_max = 30,
+ completion_callback = awful.completion.shell,
+ done_callback = function () self.wibox.visible = false end,
+ })
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return floatprompt
diff --git a/awesome/.config/awesome/redflat/float/qlaunch.lua b/awesome/.config/awesome/redflat/float/qlaunch.lua
new file mode 100644
index 0000000..813e167
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/qlaunch.lua
@@ -0,0 +1,510 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat quick laucnher widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Quick application launch or switch
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local table = table
+local unpack = unpack or table.unpack
+local string = string
+local math = math
+local io = io
+local os = os
+
+local wibox = require("wibox")
+local awful = require("awful")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redflat = require("redflat")
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local qlaunch = { history = {}, store = {}, keys = {} }
+
+local sw = redflat.float.appswitcher
+local TPI = math.pi * 2
+
+local switcher_keys = {}
+for i = 1, 9 do switcher_keys[tostring(i)] = { app = "", run = "" } end
+
+-- key bindings
+qlaunch.forcemod = { "Control" }
+qlaunch.keys.action = {
+ {
+ {}, "Escape", function() qlaunch:hide(true) end,
+ { description = "Close widget", group = "Action" }
+ },
+ {
+ {}, "Return", function() qlaunch:run_and_hide() end,
+ { description = "Run or rise selected app", group = "Action" }
+ },
+ {
+ {}, "s", function() qlaunch:set_new_app(qlaunch.switcher.selected, client.focus) end,
+ { description = "Bind focused app to selected key", group = "Action" }
+ },
+ {
+ {}, "d", function() qlaunch:set_new_app(qlaunch.switcher.selected) end,
+ { description = "Clear selected key", group = "Action" }
+ },
+ {
+ {}, "r", function() qlaunch:load_config(true) end,
+ { description = "Reload config from disk", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+qlaunch.keys.all = awful.util.table.join({}, qlaunch.keys.action)
+
+qlaunch._fake_keys = {
+ {
+ {}, "N", nil,
+ { description = "Select app (run or rise if selected already) by key", group = "Action",
+ keyset = { "1", "2", "3", "4", "5", "6", "7", "8", "9" } }
+ },
+ {
+ {}, "N", nil,
+ { description = "Select app (launch if selected already) by key", group = "Action" }
+ },
+}
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ df_icon = redutil.base.placeholder({ txt = "X" }),
+ no_icon = redutil.base.placeholder(),
+ parser = {},
+ recoloring = false,
+ notify = {},
+ geometry = { width = 1680, height = 180 },
+ border_margin = { 20, 20, 10, 10 },
+ appline = { iwidth = 160, im = { 10, 10, 5, 5 }, igap = { 0, 0, 10, 10 }, lheight = 30 },
+ state = { gap = 4, radius = 3, size = 10, height = 20, width = 20 },
+ configfile = os.getenv("HOME") .. "/.cache/awesome/applist",
+ label_font = "Sans 14",
+ border_width = 2,
+ keytip = { geometry = { width = 500 }, exit = false },
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", urgent = "#32882d",
+ wibox = "#202020", icon = "#a0a0a0", bg = "#161616", gray = "#575757" },
+ shape = nil
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.qlaunch") or {})
+end
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Get list of clients with given class
+------------------------------------------------------------
+local function get_clients(app)
+ local clients = {}
+ for _, c in ipairs(client.get()) do
+ if c.class:lower() == app then table.insert(clients, c) end
+ end
+ return clients
+end
+
+-- Set focus on given client
+------------------------------------------------------------
+local function focus_and_raise(c)
+ if c.minimized then c.minimized = false end
+ if not c:isvisible() then awful.tag.viewmore(c:tags(), c.screen) end
+
+ client.focus = c
+ c:raise()
+end
+
+-- Build filter for clients with given class
+------------------------------------------------------------
+local function build_filter(app)
+ return function(c)
+ return c.class:lower() == app
+ end
+end
+
+-- Check if file exist
+------------------------------------------------------------
+local function is_file_exists(file)
+ local f = io.open(file, "r")
+ if f then f:close(); return true else return false end
+end
+
+-- Widget construction functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Build application state indicator
+--------------------------------------------------------------------------------
+local function build_state_indicator(style)
+
+ -- Initialize vars
+ ------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ local dx = style.state.size + style.state.gap
+ local ds = style.state.size - style.state.radius
+ local r = style.state.radius
+
+ -- updating values
+ local data = {
+ state = {},
+ height = style.state.height or nil,
+ width = style.state.width or nil
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:setup(clist)
+ data.state = {}
+ for _, c in ipairs(clist) do
+ table.insert(data.state, { focused = client.focus == c, urgent = c.urgent, minimized = c.minimized })
+ end
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return data.width or width, data.height or height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ local n = #data.state
+ local x0 = (width - n * style.state.size - (n - 1) * style.state.gap) / 2
+ local y0 = (height - style.state.size) / 2
+
+ for i = 1, n do
+ cr:set_source(color(
+ data.state[i].focused and style.color.main or
+ data.state[i].urgent and style.color.urgent or
+ data.state[i].minimized and style.color.gray or style.color.icon
+ ))
+ -- draw rounded rectangle
+ cr:arc(x0 + (i -1) * dx + ds, y0 + r, r, -TPI / 4, 0)
+ cr:arc(x0 + (i -1) * dx + ds, y0 + ds, r, 0, TPI / 4)
+ cr:arc(x0 + (i -1) * dx + r, y0 + ds, r, TPI / 4, TPI / 2)
+ cr:arc(x0 + (i -1) * dx + r, y0 + r, r, TPI / 2, 3 * TPI / 4)
+ cr:fill()
+ end
+ end
+
+ ------------------------------------------------------------
+ return widg
+end
+
+-- Build icon with label item
+--------------------------------------------------------------------------------
+local function build_item(key, style)
+ local widg = {}
+
+ -- Label
+ ------------------------------------------------------------
+ local label = wibox.widget({
+ markup = string.format('%s', style.color.text, key),
+ align = "center",
+ font = style.label_font,
+ forced_height = style.appline.lheight,
+ widget = wibox.widget.textbox,
+ })
+
+ widg.background = wibox.container.background(label, style.color.bg)
+
+ -- Icon
+ ------------------------------------------------------------
+ widg.svgbox = redflat.gauge.svgbox()
+ local icon_align = wibox.widget({
+ nil,
+ widg.svgbox,
+ forced_width = style.appline.iwidth,
+ expand = "outside",
+ layout = wibox.layout.align.horizontal,
+ })
+
+ -- State
+ ------------------------------------------------------------
+ widg.state = build_state_indicator(style)
+
+ -- Layout setup
+ ------------------------------------------------------------
+ widg.layout = wibox.layout.align.vertical()
+ widg.layout:set_top(widg.state)
+ widg.layout:set_middle(wibox.container.margin(icon_align, unpack(style.appline.igap)))
+ widg.layout:set_bottom(widg.background)
+
+ ------------------------------------------------------------
+ return widg
+end
+
+-- Build widget with application list
+--------------------------------------------------------------------------------
+local function build_switcher(keys, style)
+
+ -- Init vars
+ ------------------------------------------------------------
+ local widg = { items = {}, selected = nil }
+ local middle_layout = wibox.layout.fixed.horizontal()
+
+ -- Sorted keys
+ ------------------------------------------------------------
+ local sk = {}
+ for k in pairs(keys) do table.insert(sk, k) end
+ table.sort(sk)
+
+ -- Build icon row
+ ------------------------------------------------------------
+ for _, key in ipairs(sk) do
+ widg.items[key] = build_item(key, style)
+ middle_layout:add(wibox.container.margin(widg.items[key].layout, unpack(style.appline.im)))
+ end
+
+ widg.layout = wibox.widget({
+ nil,
+ wibox.container.margin(middle_layout, unpack(style.border_margin)),
+ expand = "outside",
+ layout = wibox.layout.align.horizontal,
+ })
+
+ -- Winget functions
+ ------------------------------------------------------------
+ function widg:update(store, idb)
+ self.selected = nil
+ for key, data in pairs(store) do
+ local icon = data.app == "" and style.no_icon or idb[data.app] or style.df_icon
+ self.items[key].svgbox:set_image(icon)
+ if style.recoloring then self.items[key].svgbox:set_color(style.color.icon) end
+ end
+ self:set_state(store)
+ end
+
+ function widg:set_state(store)
+ for k, item in pairs(self.items) do
+ local clist = get_clients(store[k].app)
+ item.state:setup(clist)
+ end
+ end
+
+ function widg:reset()
+ for _, item in pairs(self.items) do item.background:set_bg(style.color.bg) end
+ self.selected = nil
+ end
+
+ function widg:check_key(key, mod)
+ if self.items[key] then
+ if self.selected then self.items[self.selected].background:set_bg(style.color.bg) end
+ self.items[key].background:set_bg(style.color.main)
+
+ if self.selected == key then
+ local modcheck = #mod == #qlaunch.forcemod
+ for _, v in ipairs(mod) do modcheck = modcheck and awful.util.table.hasitem(qlaunch.forcemod, v) end
+ qlaunch:run_and_hide(modcheck)
+ else
+ self.selected = key
+ end
+ end
+ end
+
+ ------------------------------------------------------------
+ return widg
+end
+
+-- Main widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Build widget
+--------------------------------------------------------------------------------
+function qlaunch:init(args, style)
+
+ -- Init vars
+ ------------------------------------------------------------
+ args = args or {}
+ local keys = args.keys or switcher_keys
+
+ style = redutil.table.merge(default_style(), style or {})
+ self.style = style
+ self.default_switcher_keys = keys
+ self.icon_db = redflat.service.dfparser.icon_list(style.parser)
+
+ self:load_config()
+
+ -- Wibox
+ ------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+ self.wibox:geometry(style.geometry)
+ redutil.placement.centered(self.wibox, nil, screen[mouse.screen].workarea)
+
+ -- Switcher widget
+ ------------------------------------------------------------
+ self.switcher = build_switcher(self.store, style)
+ self.switcher:update(self.store, self.icon_db)
+
+ self.wibox:set_widget(self.switcher.layout)
+ self:set_keys()
+
+ -- Keygrabber
+ ------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event == "press" then return false end
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ self.switcher:check_key(key, mod)
+ end
+
+ -- Connect additional signals
+ ------------------------------------------------------------
+ client.connect_signal("focus", function(c) self:set_last(c) end)
+ awesome.connect_signal("exit", function() self:save_config() end)
+end
+
+-- Widget show/hide
+--------------------------------------------------------------------------------
+function qlaunch:show()
+ if not self.wibox then self:init() end
+
+ self.switcher:set_state(self.store)
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+
+ redtip:set_pack(
+ "Quick launch", self.tip, self.style.keytip.column, self.style.keytip.geometry,
+ self.style.keytip.exit and function() self:hide() end
+ )
+end
+
+function qlaunch:hide()
+ self.wibox.visible = false
+ awful.keygrabber.stop(self.keygrabber)
+ self.switcher:reset()
+ redtip:remove_pack()
+end
+
+function qlaunch:run_and_hide(forced_run)
+ if self.switcher.selected then
+ self:run_or_raise(self.switcher.selected, forced_run)
+ end
+ self:hide()
+end
+
+-- Switch to app
+--------------------------------------------------------------------------------
+function qlaunch:run_or_raise(key, forced_run)
+ local app = self.store[key].app
+ if app == "" then return end
+
+ local clients = get_clients(app)
+ local cnum = #clients
+
+ if cnum == 0 or forced_run then
+ -- open new application
+ if self.store[key].run ~= "" then awful.spawn.with_shell(self.store[key].run) end
+ elseif cnum == 1 then
+ -- switch to sole app
+ focus_and_raise(clients[1])
+ else
+ if awful.util.table.hasitem(clients, client.focus) then
+ -- run selection widget if wanted app focused
+ sw:show({ filter = build_filter(app), noaction = true })
+ else
+ -- switch to last focused if availible or first in list otherwise
+ local last = awful.util.table.hasitem(clients, self.history[app])
+ if last then
+ focus_and_raise(self.history[app])
+ else
+ focus_and_raise(clients[1])
+ end
+ end
+ end
+end
+
+-- Bind new application to given hotkey
+--------------------------------------------------------------------------------
+function qlaunch:set_new_app(key, c)
+ if not key then return end
+
+ if c then
+ local run_command = redutil.read.output(string.format("tr '\\0' ' ' < /proc/%s/cmdline", c.pid))
+ self.store[key] = { app = c.class:lower(), run = run_command }
+ local note = redutil.table.merge({text = string.format("%s binded with '%s'", c.class, key)}, self.style.notify)
+ redflat.float.notify:show(note)
+ else
+ self.store[key] = { app = "", run = "" }
+ local note = redutil.table.merge({text = string.format("'%s' key unbinded", key)}, self.style.notify)
+ redflat.float.notify:show(note)
+ end
+
+ self.switcher:reset()
+ self.switcher:update(self.store, self.icon_db)
+end
+
+-- Save information about last focused client in widget store
+--------------------------------------------------------------------------------
+function qlaunch:set_last(c)
+ if not c.class then return end
+ for _, data in pairs(self.store) do
+ if c.class:lower() == data.app then
+ self.history[data.app] = c
+ break
+ end
+ end
+end
+
+-- Application list save/load
+--------------------------------------------------------------------------------
+function qlaunch:load_config(need_reset)
+ if is_file_exists(self.style.configfile) then
+ for line in io.lines(self.style.configfile) do
+ local key, app, run = string.match(line, "key=(.+);app=(.*);run=(.*);")
+ self.store[key] = { app = app, run = run }
+ end
+ else
+ self.store = self.default_switcher_keys
+ end
+
+ if need_reset then
+ self.switcher:reset()
+ self.switcher:update(self.store, self.icon_db)
+ end
+end
+
+function qlaunch:save_config()
+ local file = io.open(self.style.configfile, "w+")
+ for key, data in pairs(self.store) do
+ file:write(string.format("key=%s;app=%s;run=%s;\n", key, data.app, data.run))
+ end
+ file:close()
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function qlaunch:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join({}, self.keys.action) end
+ end
+
+ self._fake_keys[2][1] = self.forcemod
+ self.tip = awful.util.table.join(self.keys.all, self._fake_keys)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return qlaunch
diff --git a/awesome/.config/awesome/redflat/float/tooltip.lua b/awesome/.config/awesome/redflat/float/tooltip.lua
new file mode 100644
index 0000000..c4aac62
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/tooltip.lua
@@ -0,0 +1,156 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tooltip --
+-----------------------------------------------------------------------------------------------------------------------
+-- Slightly modded awful tooltip
+-- padding added
+-- Proper placement on every text update
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.tooltip v3.5.2
+------ (c) 2009 Sébastien Gross
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local ipairs = ipairs
+local wibox = require("wibox")
+local awful = require("awful")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local tooltip = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ padding = { vertical = 3, horizontal = 5 },
+ timeout = 1,
+ font = "Sans 12",
+ border_width = 2,
+ set_position = nil,
+ color = { border = "#404040", text = "#aaaaaa", wibox = "#202020" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.tooltip") or {})
+end
+
+-- Create a new tooltip
+-----------------------------------------------------------------------------------------------------------------------
+function tooltip.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local objects = args.objects or {}
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Construct tooltip window with wibox and textbox
+ --------------------------------------------------------------------------------
+ local ttp = { wibox = wibox({ type = "tooltip" }), tip = nil }
+ local tb = wibox.widget.textbox()
+ tb:set_align("center")
+
+ ttp.widget = tb
+ ttp.wibox:set_widget(tb)
+ tb:set_font(style.font)
+
+ -- configure wibox properties
+ ttp.wibox.visible = false
+ ttp.wibox.ontop = true
+ ttp.wibox.border_width = style.border_width
+ ttp.wibox.border_color = style.color.border
+ ttp.wibox.shape = style.shape
+ ttp.wibox:set_bg(style.color.wibox)
+ ttp.wibox:set_fg(style.color.text)
+
+ -- Tooltip size configurator
+ --------------------------------------------------------------------------------
+ function ttp:set_geometry()
+ local wibox_sizes = self.wibox:geometry()
+ local w, h = self.widget:get_preferred_size()
+ local requsted_width = w + 2*style.padding.horizontal
+ local requsted_height = h + 2*style.padding.vertical
+
+ if wibox_sizes.width ~= requsted_width or wibox_sizes.height ~= requsted_height then
+ self.wibox:geometry({
+ width = requsted_width,
+ height = requsted_height
+ })
+ end
+ end
+
+ -- Set timer to make delay before tooltip show
+ --------------------------------------------------------------------------------
+ local show_timer = timer({ timeout = style.timeout })
+ show_timer:connect_signal("timeout",
+ function()
+ ttp:set_geometry()
+ if style.set_position then
+ style.set_position(ttp.wibox)
+ else
+ awful.placement.under_mouse(ttp.wibox)
+ end
+ awful.placement.no_offscreen(ttp.wibox)
+ ttp.wibox.visible = true
+ show_timer:stop()
+ end)
+
+ -- Tooltip metods
+ --------------------------------------------------------------------------------
+ function ttp.show()
+ if not show_timer.started then show_timer:start() end
+ end
+
+ function ttp.hide()
+ if show_timer.started then show_timer:stop() end
+ if ttp.wibox.visible then ttp.wibox.visible = false end
+ end
+
+ function ttp:set_text(text)
+ if self.tip ~= text then
+ self.widget:set_text(text)
+ self.tip = text
+
+ if self.wibox.visible then
+ self:set_geometry()
+ self.wibox.x = mouse.coords().x - self.wibox.width / 2
+ awful.placement.no_offscreen(self.wibox)
+ end
+ end
+ end
+
+ function ttp:add_to_object(object)
+ object:connect_signal("mouse::enter", self.show)
+ object:connect_signal("mouse::leave", self.hide)
+ end
+
+ function ttp:remove_from_object(object)
+ object:disconnect_signal("mouse::enter", self.show)
+ object:disconnect_signal("mouse::leave", self.hide)
+ end
+
+ -- Add tooltip to objects
+ --------------------------------------------------------------------------------
+ if objects then
+ for _, object in ipairs(objects) do
+ ttp:add_to_object(object)
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return ttp
+end
+
+-- Config metatable to call tooltip module as function
+-----------------------------------------------------------------------------------------------------------------------
+function tooltip.mt:__call(...)
+ return tooltip.new(...)
+end
+
+return setmetatable(tooltip, tooltip.mt)
diff --git a/awesome/.config/awesome/redflat/float/top.lua b/awesome/.config/awesome/redflat/float/top.lua
new file mode 100644
index 0000000..9c8112a
--- /dev/null
+++ b/awesome/.config/awesome/redflat/float/top.lua
@@ -0,0 +1,379 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat top widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with list of top processes
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local system = require("redflat.system")
+local decoration = require("redflat.float.decoration")
+local redtip = require("redflat.float.hotkeys")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local top = { keys = {} }
+
+-- key bindings
+top.keys.management = {
+ {
+ {}, "c", function() top:set_sort("cpu") end,
+ { description = "Sort by CPU usage", group = "Management" }
+ },
+ {
+ {}, "m", function() top:set_sort("mem") end,
+ { description = "Sort by RAM usage", group = "Management" }
+ },
+}
+
+top.keys.action = {
+ {
+ {}, "k", function() top.kill_selected() end,
+ { description = "Kill process", group = "Action" }
+ },
+ {
+ {}, "Escape", function() top:hide() end,
+ { description = "Close top list widget", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+top.keys.all = awful.util.table.join(top.keys.management, top.keys.action)
+
+top._fake_keys = {
+ {
+ {}, "N", nil,
+ { description = "Select process by key", group = "Management",
+ keyset = { "1", "2", "3", "4", "5", "6", "7", "8", "9" } }
+ },
+}
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ timeout = 2,
+ screen_gap = 0,
+ set_position = nil,
+ geometry = { width = 460, height = 380 },
+ border_margin = { 10, 10, 10, 10 },
+ labels_width = { num = 30, cpu = 70, mem = 120 },
+ title_height = 48,
+ list_side_gap = 8,
+ border_width = 2,
+ bottom_height = 80,
+ button_margin = { 140, 140, 22, 22 },
+ keytip = { geometry = { width = 400 } },
+ title_font = "Sans 14 bold",
+ unit = { { "KB", -1 }, { "MB", 1024 }, { "GB", 1024^2 } },
+ color = { border = "#575757", text = "#aaaaaa", highlight = "#eeeeee", main = "#b1222b",
+ bg = "#161616", bg_second = "#181818", wibox = "#202020" },
+ shape = nil
+
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "float.top") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Sort functions
+--------------------------------------------------------------------------------
+local function sort_by_cpu(a, b)
+ return a.pcpu > b.pcpu
+end
+
+local function sort_by_mem(a, b)
+ return a.mem > b.mem
+end
+
+-- Fuction to build list item
+--------------------------------------------------------------------------------
+local function construct_item(style)
+ local item = {}
+ item.label = {
+ number = wibox.widget.textbox(),
+ name = wibox.widget.textbox(),
+ cpu = wibox.widget.textbox(),
+ mem = wibox.widget.textbox()
+ }
+
+ item.label.cpu:set_align("right")
+ item.label.mem:set_align("right")
+
+ local bg = style.color.bg
+
+ -- Construct item layouts
+ ------------------------------------------------------------
+ local mem_label_with_gap = wibox.container.margin(item.label.mem, 0, style.list_side_gap)
+ local num_label_with_gap = wibox.container.margin(item.label.number, style.list_side_gap)
+
+ local right = wibox.layout.fixed.horizontal()
+ right:add(wibox.container.constraint(item.label.cpu, "exact", style.labels_width.cpu, nil))
+ right:add(wibox.container.constraint(mem_label_with_gap, "exact", style.labels_width.mem, nil))
+
+ local middle = wibox.layout.align.horizontal()
+ middle:set_left(item.label.name)
+
+ local left = wibox.container.constraint(num_label_with_gap, "exact", style.labels_width.num, nil)
+
+ local item_horizontal = wibox.layout.align.horizontal()
+ item_horizontal:set_left(left)
+ item_horizontal:set_middle(middle)
+ item_horizontal:set_right(right)
+ item.layout = wibox.container.background(item_horizontal, bg)
+
+ -- item functions
+ ------------------------------------------------------------
+ function item:set_bg(color)
+ bg = color
+ item.layout:set_bg(color)
+ end
+
+ function item:set_select()
+ item.layout:set_bg(style.color.main)
+ item.layout:set_fg(style.color.highlight)
+ end
+
+ function item:set_unselect()
+ item.layout:set_bg(bg)
+ item.layout:set_fg(style.color.text)
+ end
+
+ function item:set(args)
+ if args.number then item.label.number:set_text(args.number) end
+ if args.name then item.label.name:set_text(args.name) end
+ if args.cpu then item.label.cpu:set_text(args.cpu) end
+ if args.mem then item.label.mem:set_text(args.mem) end
+ if args.pid then item.pid = args.pid end
+ end
+
+ ------------------------------------------------------------
+ return item
+end
+
+-- Fuction to build top list
+--------------------------------------------------------------------------------
+local function list_construct(n, style, select_function)
+ local list = {}
+
+ local list_layout = wibox.layout.flex.vertical()
+ list.layout = wibox.container.background(list_layout, style.color.bg)
+
+ list.items = {}
+ for i = 1, n do
+ list.items[i] = construct_item(style)
+ list.items[i]:set({ number = i})
+ list.items[i]:set_bg((i % 2) == 1 and style.color.bg or style.color.bg_second)
+ list_layout:add(list.items[i].layout)
+
+ list.items[i].layout:buttons(awful.util.table.join(
+ awful.button({ }, 1, function() select_function(i) end)
+ ))
+ end
+
+ return list
+end
+
+-- Initialize top widget
+-----------------------------------------------------------------------------------------------------------------------
+function top:init()
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local number_of_lines = 9 -- number of lines in process list
+ local selected = {}
+ local cpu_storage = { cpu_total = {}, cpu_active = {} }
+ local style = default_style()
+ local sort_function, title, toplist
+
+ self.style = style
+
+ -- Select process function
+ --------------------------------------------------------------------------------
+ local function select_item(i)
+ if selected.number and selected.number ~= i then toplist.items[selected.number]:set_unselect() end
+ toplist.items[i]:set_select()
+ selected.pid = toplist.items[i].pid
+ selected.number = i
+ end
+
+ -- Set sorting rule
+ --------------------------------------------------------------------------------
+ function self:set_sort(args)
+ if args == "cpu" then
+ sort_function = sort_by_cpu
+ title:set({ cpu = "↓CPU", mem = "Memory"})
+ elseif args == "mem" then
+ sort_function = sort_by_mem
+ title:set({ cpu = "CPU", mem = "↓Memory"})
+ end
+ end
+
+ -- Kill selected process
+ --------------------------------------------------------------------------------
+ function self.kill_selected()
+ if selected.number then awful.spawn.with_shell("kill " .. selected.pid) end
+ self:update_list()
+ end
+
+ -- Widget keygrabber
+ --------------------------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event ~= "press" then return end
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ if string.match("123456789", key) then select_item(tonumber(key)) end
+ end
+
+ -- Build title
+ --------------------------------------------------------------------------------
+ title = construct_item(style)
+ title:set_bg(style.color.wibox)
+ title:set({ number = "#", name = "Process Name", cpu = "↓ CPU", mem = "Memory"})
+
+ for _, txtbox in pairs(title.label) do
+ txtbox:set_font(style.title_font)
+ end
+
+ title.label.cpu:buttons(awful.util.table.join(
+ awful.button({ }, 1, function() self:set_sort("cpu") end)
+ ))
+ title.label.mem:buttons(awful.util.table.join(
+ awful.button({ }, 1, function() self:set_sort("mem") end)
+ ))
+
+ -- Build top list
+ --------------------------------------------------------------------------------
+ toplist = list_construct(number_of_lines, style, select_item)
+
+ -- Update function
+ --------------------------------------------------------------------------------
+ function self:update_list()
+ local proc = system.proc_info(cpu_storage)
+ table.sort(proc, sort_function)
+
+ if selected.number then
+ toplist.items[selected.number]:set_unselect()
+ selected.number = nil
+ end
+
+ for i = 1, number_of_lines do
+ toplist.items[i]:set({
+ name = proc[i].name,
+ cpu = string.format("%.1f", proc[i].pcpu * 100),
+ --mem = string.format("%.0f", proc[i].mem) .. " MB",
+ mem = redutil.text.dformat(proc[i].mem, style.unit, 2, " "),
+ pid = proc[i].pid
+ })
+
+ if selected.pid and selected.pid == proc[i].pid then
+ toplist.items[i]:set_select()
+ selected.number = i
+ end
+ end
+ end
+
+ -- Construct widget layouts
+ --------------------------------------------------------------------------------
+ local buttonbox = wibox.widget.textbox("Kill")
+
+ local button_widget = decoration.button(buttonbox, self.kill_selected)
+
+ local button_layout = wibox.container.margin(button_widget, unpack(style.button_margin))
+ local bottom_area = wibox.container.constraint(button_layout, "exact", nil, style.bottom_height)
+
+ local area = wibox.layout.align.vertical()
+ area:set_top(wibox.container.constraint(title.layout, "exact", nil, style.title_height))
+ area:set_middle(toplist.layout)
+ area:set_bottom(bottom_area)
+ local list_layout = wibox.container.margin(area, unpack(style.border_margin))
+
+ -- Create floating wibox for top widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox:set_widget(list_layout)
+ self.wibox:geometry(style.geometry)
+
+ -- Update timer
+ --------------------------------------------------------------------------------
+ self.update_timer = timer({timeout = style.timeout})
+ self.update_timer:connect_signal("timeout", function() self:update_list() end)
+
+ -- First run actions
+ --------------------------------------------------------------------------------
+ self:set_keys()
+ self:set_sort("cpu")
+ self:update_list()
+end
+
+-- Hide top widget
+-----------------------------------------------------------------------------------------------------------------------
+function top:hide()
+ self.wibox.visible = false
+ self.update_timer:stop()
+ awful.keygrabber.stop(self.keygrabber)
+ redtip:remove_pack()
+end
+
+-- Show top widget
+-----------------------------------------------------------------------------------------------------------------------
+function top:show(srt)
+ if not self.wibox then self:init() end
+ if self.wibox.visible then
+ top:hide()
+ else
+ if srt then self:set_sort(srt) end
+ self:update_list()
+
+ if self.style.set_position then
+ self.style.set_position(self.wibox)
+ else
+ awful.placement.under_mouse(self.wibox)
+ end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, screen[mouse.screen].workarea)
+
+ self.wibox.visible = true
+ self.update_timer:start()
+ awful.keygrabber.run(self.keygrabber)
+
+ redtip:set_pack("Top process", self.tip, self.style.keytip.column, self.style.keytip.geometry)
+ end
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function top:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.management, self.keys.action) end
+ end
+
+ self.tip = awful.util.table.join(self.keys.all, self._fake_keys)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return top
diff --git a/awesome/.config/awesome/redflat/gauge/audio/blue.lua b/awesome/.config/awesome/redflat/gauge/audio/blue.lua
new file mode 100644
index 0000000..b87ba27
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/audio/blue.lua
@@ -0,0 +1,80 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat volume indicator widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Indicator with audio icon
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local unpack = unpack or table.unpack
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local reddash = require("redflat.gauge.graph.dash")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local audio = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 100,
+ icon = redutil.base.placeholder(),
+ gauge = reddash.new,
+ dash = {},
+ dmargin = { 10, 0, 0, 0 },
+ color = { icon = "#a0a0a0", mute = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.audio.blue") or {})
+end
+
+-- Create a new audio widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function audio.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Construct widget
+ --------------------------------------------------------------------------------
+ local icon = svgbox(style.icon)
+
+ local layout = wibox.layout.fixed.horizontal()
+ layout:add(icon)
+
+ local dash
+ if style.gauge then
+ dash = style.gauge(style.dash)
+ layout:add(wibox.container.margin(dash, unpack(style.dmargin)))
+ end
+
+ local widg = wibox.container.constraint(layout, "exact", style.width)
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x) if dash then dash:set_value(x) end end
+
+ function widg:set_mute(mute)
+ icon:set_color(mute and style.color.mute or style.color.icon)
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call audio module as function
+-----------------------------------------------------------------------------------------------------------------------
+function audio.mt:__call(...)
+ return audio.new(...)
+end
+
+return setmetatable(audio, audio.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/audio/init.lua b/awesome/.config/awesome/redflat/gauge/audio/init.lua
new file mode 100644
index 0000000..a7f844c
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/audio/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.audio" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/audio/red.lua b/awesome/.config/awesome/redflat/gauge/audio/red.lua
new file mode 100644
index 0000000..bf4eb64
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/audio/red.lua
@@ -0,0 +1,93 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat volume indicator widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Indicator with audio icon
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local string = string
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local audio = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = { volume = redutil.base.placeholder(), mute = redutil.base.placeholder() },
+ step = 0.05,
+ color = { main = "#b1222b", icon = "#a0a0a0", mute = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.audio.red") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function pattern_string(height, value, c1, c2)
+ return string.format("linear:0,%s:0,0:0,%s:%s,%s:%s,%s:1,%s", height, c1, value, c1, value, c2, c2)
+end
+
+-- Create a new audio widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function audio.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Icon widgets
+ ------------------------------------------------------------
+ local icon = {}
+ icon.ready = svgbox(style.icon.volume)
+ icon.ready:set_color(style.color.icon)
+ icon.mute = svgbox(style.icon.mute)
+ icon.mute:set_color(style.color.mute)
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.container.background(icon.ready)
+ widg._data = { level = 0 }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ if x > 1 then x = 1 end
+
+ if self.widget._image then
+ local level = math.floor(x / style.step) * style.step
+
+ if level ~= self._data.level then
+ self._data.level = level
+ local h = self.widget._image.height
+ icon.ready:set_color(pattern_string(h, level, style.color.main, style.color.icon))
+ end
+ end
+ end
+
+ function widg:set_mute(mute)
+ widg:set_widget(mute and icon.mute or icon.ready)
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call audio module as function
+-----------------------------------------------------------------------------------------------------------------------
+function audio.mt:__call(...)
+ return audio.new(...)
+end
+
+return setmetatable(audio, audio.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/graph/bar.lua b/awesome/.config/awesome/redflat/gauge/graph/bar.lua
new file mode 100644
index 0000000..f71fba8
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/graph/bar.lua
@@ -0,0 +1,80 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat progressbar widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Horizontal progresspar
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local progressbar = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ color = { main = "#b1222b", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.graph.bar") or {})
+end
+
+-- Create a new progressbar widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { value = 0 }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ local value = x < 1 and x or 1
+ if self._data.value ~= value then
+ self._data.value = value
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ cr:set_source(color(style.color.gray))
+ cr:rectangle(0, 0, width, height)
+ cr:fill()
+ cr:set_source(color(style.color.main))
+ cr:rectangle(0, 0, self._data.value * width, height)
+ cr:fill()
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call progressbar module as function
+-----------------------------------------------------------------------------------------------------------------------
+function progressbar.mt:__call(...)
+ return progressbar.new(...)
+end
+
+return setmetatable(progressbar, progressbar.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/graph/dash.lua b/awesome/.config/awesome/redflat/gauge/graph/dash.lua
new file mode 100644
index 0000000..c0bcb00
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/graph/dash.lua
@@ -0,0 +1,88 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat dashcontrol widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Horizontal progresspar with stairs form
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local dashcontrol = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ plain = false,
+ bar = { width = 4, num = 10 },
+ color = { main = "#b1222b", gray = "#404040" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.graph.dash") or {})
+end
+
+-- Create a new dashcontrol widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function dashcontrol.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { value = 0, cnum = 0 }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ self._data.value = x < 1 and x or 1
+ local num = math.ceil(widg._data.value * style.bar.num)
+
+ if num ~= self._data.cnum then
+ self._data.cnum = num
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ local wstep = (width - style.bar.width) / (style.bar.num - 1)
+ local hstep = height / style.bar.num
+ --self._data.cnum = math.ceil(widg._data.value * style.bar.num)
+
+ for i = 1, style.bar.num do
+ cr:set_source(color(i > self._data.cnum and style.color.gray or style.color.main))
+ cr:rectangle((i - 1) * wstep, height, style.bar.width, style.plain and -height or - i * hstep)
+ cr:fill()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call dashcontrol module as function
+-----------------------------------------------------------------------------------------------------------------------
+function dashcontrol.mt:__call(...)
+ return dashcontrol.new(...)
+end
+
+return setmetatable(dashcontrol, dashcontrol.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/graph/dots.lua b/awesome/.config/awesome/redflat/gauge/graph/dots.lua
new file mode 100644
index 0000000..ac19017
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/graph/dots.lua
@@ -0,0 +1,109 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat dotcount widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Simple graphical counter
+-- Displaying current value by dots number
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local counter = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ column_num = { 2, 5 }, -- {min, max}
+ row_num = 3,
+ dot_size = 5,
+ dot_gap_h = 5,
+ color = { main = "#b1222b", gray = "#575757" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.graph.dots") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+--local function round(x)
+-- return math.floor(x + 0.5)
+--end
+
+-- Create a new counter widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function counter.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = {
+ count_num = 0,
+ column_num = style.column_num[1]
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_num(num)
+ if num ~= self._data.count_num then
+ self._data.count_num = num
+ self._data.column_num = math.min(
+ math.max(style.column_num[1], math.ceil(num / style.row_num)), style.column_num[2]
+ )
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, _, height)
+ local width = (style.dot_size + style.dot_gap_h) * self._data.column_num - style.dot_gap_h
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+-- local maxnum = style.row_num * data.column_num
+ local gap_v = (height - style.row_num * style.dot_size) / (style.row_num - 1)
+
+ cr:translate(0, height)
+ for i = 1, style.row_num do
+ for j = 1, self._data.column_num do
+ local cc = (j + (i - 1) * self._data.column_num) <= self._data.count_num
+ and style.color.main or style.color.gray
+ cr:set_source(color(cc))
+
+ cr:rectangle(0, 0, style.dot_size, - style.dot_size)
+ cr:fill()
+
+ cr:translate(style.dot_size + style.dot_gap_h, 0)
+ end
+ cr:translate(- (style.dot_gap_h + width), - (style.dot_size + gap_v))
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call dotcount module as function
+-----------------------------------------------------------------------------------------------------------------------
+function counter.mt:__call(...)
+ return counter.new(...)
+end
+
+return setmetatable(counter, counter.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/graph/init.lua b/awesome/.config/awesome/redflat/gauge/graph/init.lua
new file mode 100644
index 0000000..40d6aee
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/graph/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.graph" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/icon/double.lua b/awesome/.config/awesome/redflat/gauge/icon/double.lua
new file mode 100644
index 0000000..487b0b3
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/icon/double.lua
@@ -0,0 +1,96 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat indicator widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Double mage indicator
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local string = string
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local dubgicon = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon1 = redutil.base.placeholder(),
+ icon2 = redutil.base.placeholder(),
+ igap = 8,
+ step = 0.05,
+ is_vertical = false,
+ color = { main = "#b1222b", icon = "#a0a0a0" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.icon.double") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function pattern_string_v(height, value, c1, c2)
+ return string.format("linear:0,%s:0,0:0,%s:%s,%s:%s,%s:1,%s", height, c1, value, c1, value, c2, c2)
+end
+
+local function pattern_string_h(width, value, c1, c2)
+ return string.format("linear:0,0:%s,0:0,%s:%s,%s:%s,%s:1,%s", width, c1, value, c1, value, c2, c2)
+end
+
+-- Create a new dubgicon widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function dubgicon.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local pattern = style.is_vertical and pattern_string_v or pattern_string_h
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local fixed = wibox.layout.fixed.horizontal()
+ local layout = wibox.container.constraint(fixed, "exact", style.width)
+ layout._icon1 = svgbox(style.icon1)
+ layout._icon2 = svgbox(style.icon2)
+ layout._data = { level = { 0, 0 }}
+ fixed:add(wibox.container.margin(layout._icon1, 0, style.igap, 0, 0))
+ fixed:add(layout._icon2)
+
+ -- User functions
+ ------------------------------------------------------------
+ function layout:set_value(value)
+ local level = {
+ math.floor((value[1] < 1 and value[1] or 1) / style.step) * style.step,
+ math.floor((value[2] < 1 and value[2] or 1) / style.step) * style.step
+ }
+
+ for i, widg in ipairs({ self._icon1, self._icon2 }) do
+ if widg._image and level[i] ~= layout._data.level[i] then
+ layout._data.level[i] = level[i]
+
+ local d = style.is_vertical and widg._image.height or widg._image.width
+ widg:set_color(pattern(d, level[i], style.color.main, style.color.icon))
+ end
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return layout
+end
+
+-- Config metatable to call dubgicon module as function
+-----------------------------------------------------------------------------------------------------------------------
+function dubgicon.mt:__call(...)
+ return dubgicon.new(...)
+end
+
+return setmetatable(dubgicon, dubgicon.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/icon/init.lua b/awesome/.config/awesome/redflat/gauge/icon/init.lua
new file mode 100644
index 0000000..fa57e49
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/icon/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.icon" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/icon/single.lua b/awesome/.config/awesome/redflat/gauge/icon/single.lua
new file mode 100644
index 0000000..1cbede4
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/icon/single.lua
@@ -0,0 +1,95 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat indicator widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Image indicator
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local string = string
+
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local gicon = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = redutil.base.placeholder(),
+ step = 0.05,
+ is_vertical = false,
+ color = { main = "#b1222b", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.icon.single") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function pattern_string_v(height, value, c1, c2)
+ return string.format("linear:0,%s:0,0:0,%s:%s,%s:%s,%s:1,%s", height, c1, value, c1, value, c2, c2)
+end
+
+local function pattern_string_h(width, value, c1, c2)
+ return string.format("linear:0,0:%s,0:0,%s:%s,%s:%s,%s:1,%s", width, c1, value, c1, value, c2, c2)
+end
+
+-- Create a new gicon widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function gicon.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local pattern = style.is_vertical and pattern_string_v or pattern_string_h
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.container.background(svgbox(style.icon))
+ widg._data = {
+ color = style.color.main,
+ level = 0,
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ if x > 1 then x = 1 end
+
+ if self.widget._image then
+ local level = math.floor(x / style.step) * style.step
+
+ if level ~= self._data.level then
+ self._data.level = level
+ local d = style.is_vertical and self.widget._image.height or self._image.width
+ self.widget:set_color(pattern(d, level, self._data.color, style.color.icon))
+ end
+ end
+ end
+
+ function widg:set_alert(alert)
+ -- not sure about redraw after alert set
+ self._data.color = alert and style.color.urgent or style.color.main
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call gicon module as function
+-----------------------------------------------------------------------------------------------------------------------
+function gicon.mt:__call(...)
+ return gicon.new(...)
+end
+
+return setmetatable(gicon, gicon.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/init.lua b/awesome/.config/awesome/redflat/gauge/init.lua
new file mode 100644
index 0000000..b07217e
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/monitor/circle.lua b/awesome/.config/awesome/redflat/gauge/monitor/circle.lua
new file mode 100644
index 0000000..dd1cdbe
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/monitor/circle.lua
@@ -0,0 +1,109 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat monitor widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with circle indicator
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local cirmon = { mt = {} }
+local TPI = math.pi * 2
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = nil,
+ line_width = 4,
+ radius = 14,
+ iradius = 6,
+ step = 0.02,
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.monitor.circle") or {})
+end
+
+-- Create a new monitor widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function cirmon.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ local cs = -TPI / 4
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { color = style.color.icon, level = 0, alert = false }
+
+ if style.width then widg:set_forced_width(style.width) end
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ local value = x < 1 and x or 1
+ local level = math.floor(value / style.step) * style.step
+
+ if level ~= self._data.level then
+ self._data.level = level
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_alert(alert)
+ if alert ~= self._data.alert then
+ self._data.alert = alert
+ self._data.color = alert and style.color.main or style.color.icon
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ local size = math.min(width, height)
+ return size, size
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ -- center circle
+ cr:set_source(color(self._data.color))
+ cr:arc(width / 2, height / 2, style.iradius, 0, TPI)
+ cr:fill()
+
+ -- progress circle
+ cr:set_line_width(style.line_width)
+ local cd = { TPI, TPI * self._data.level }
+ for i = 1, 2 do
+ cr:set_source(color(i > 1 and style.color.main or style.color.gray))
+ cr:arc(width / 2, height / 2, style.radius, cs, cs + cd[i])
+ cr:stroke()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call monitor module as function
+-----------------------------------------------------------------------------------------------------------------------
+function cirmon.mt:__call(...)
+ return cirmon.new(...)
+end
+
+return setmetatable(cirmon, cirmon.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/monitor/dash.lua b/awesome/.config/awesome/redflat/gauge/monitor/dash.lua
new file mode 100644
index 0000000..7c2f3d7
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/monitor/dash.lua
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat monitor widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with dash indicator
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local dashmon = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 40,
+ line = { num = 5, height = 4 },
+ color = { main = "#b1222b", urgent = "#00725b", gray = "#575757" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.monitor.dash") or {})
+end
+
+-- Create a new monitor widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function dashmon.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { color = style.color.main, level = 0, alert = false }
+
+ if style.width then widg:set_forced_width(style.width) end
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ local value = x < 1 and x or 1
+ local level = math.ceil(style.line.num * value)
+
+ if level ~= self._data.level then
+ self._data.level = level
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_alert(alert)
+ if alert ~= self._data.alert then
+ self._data.alert = alert
+ self._data.color = alert and style.color.urgent or style.color.main
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ local gap = (height - style.line.height * style.line.num) / (style.line.num - 1)
+ local dy = style.line.height + gap
+
+ for i = 1, style.line.num do
+ cr:set_source(color(i <= self._data.level and self._data.color or style.color.gray))
+ cr:rectangle(0, height - (i - 1) * dy, width, - style.line.height)
+ cr:fill()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call monitor module as function
+-----------------------------------------------------------------------------------------------------------------------
+function dashmon.mt:__call(...)
+ return dashmon.new(...)
+end
+
+return setmetatable(dashmon, dashmon.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/monitor/double.lua b/awesome/.config/awesome/redflat/gauge/monitor/double.lua
new file mode 100644
index 0000000..243a3c9
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/monitor/double.lua
@@ -0,0 +1,130 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat doublemonitor widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with two progressbar and icon
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local unpack = unpack or table.unpack
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local doublemonitor = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ line = { width = 4, v_gap = 6, gap = 4, num = 5 },
+ icon = redutil.base.placeholder(),
+ dmargin = { 10, 0, 0, 0 },
+ width = 100,
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.monitor.double") or {})
+end
+
+-- Create progressbar widget
+-----------------------------------------------------------------------------------------------------------------------
+local function pbar(style)
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { level = { 0, 0 }}
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(value)
+ local level = {
+ math.ceil((value[1] < 1 and value[1] or 1) * style.line.num),
+ math.ceil((value[2] < 1 and value[2] or 1) * style.line.num),
+ }
+
+ if level[1] ~= self._data.level[1] or level[2] ~= self._data.level[2] then
+ self._data.level[1] = level[1]
+ self._data.level[2] = level[2]
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ local wd = (width + style.line.gap) / style.line.num - style.line.gap
+ local dy = (height - (2 * style.line.width + style.line.v_gap)) / 2
+
+ for i = 1, 2 do
+ for k = 1, style.line.num do
+ cr:set_source(color(k <= self._data.level[i] and style.color.main or style.color.gray))
+ cr:rectangle(
+ (k - 1) * (wd + style.line.gap), dy + (i - 1) * (style.line.width + style.line.v_gap),
+ wd, style.line.width
+ )
+ cr:fill()
+ end
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Cunstruct a new doublemonitor widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function doublemonitor.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Construct layout
+ --------------------------------------------------------------------------------
+ local fixed = wibox.layout.fixed.horizontal()
+ fixed:set_forced_width(style.width)
+ local widg = pbar(style)
+ local icon = svgbox(style.icon)
+
+ icon:set_color(style.color.icon)
+
+ fixed:add(icon)
+ fixed:add(wibox.container.margin(widg, unpack(style.dmargin)))
+
+ -- User functions
+ --------------------------------------------------------------------------------
+ function fixed:set_value(value)
+ widg:set_value(value)
+ end
+
+ function fixed:set_alert(alert)
+ icon:set_color(alert and style.color.urgent or style.color.icon)
+ end
+
+ --------------------------------------------------------------------------------
+ return fixed
+end
+
+-- Config metatable to call doublemonitor module as function
+-----------------------------------------------------------------------------------------------------------------------
+function doublemonitor.mt:__call(...)
+ return doublemonitor.new(...)
+end
+
+return setmetatable(doublemonitor, doublemonitor.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/monitor/init.lua b/awesome/.config/awesome/redflat/gauge/monitor/init.lua
new file mode 100644
index 0000000..80aacea
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/monitor/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.monitor" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/monitor/plain.lua b/awesome/.config/awesome/redflat/gauge/monitor/plain.lua
new file mode 100644
index 0000000..82b0e45
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/monitor/plain.lua
@@ -0,0 +1,113 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat monitor widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget with label and progressbar
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local monitor = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ line = { height = 4, y = 30 },
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ text_shift = 22,
+ label = "MON",
+ width = 100,
+ step = 0.05,
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.monitor.plain") or {})
+end
+
+-- Create a new monitor widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function monitor.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { color = style.color.icon, level = 0, alert = false, label = style.label }
+
+ if style.width then widg:set_forced_width(style.width) end
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_value(x)
+ local value = x < 1 and x or 1
+ local level = math.floor(value / style.step) * style.step
+
+ if level ~= self._data.level then
+ self._data.level = level
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_label(label)
+ if label ~= self._data.label then
+ self._data.label = label
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_alert(alert)
+ if alert ~= self._data.alert then
+ self._data.alert = alert
+ self._data.color = alert and style.color.main or style.color.icon
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width)
+
+ -- label
+ cr:set_source(color(self._data.color))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { width/2, style.text_shift }, self._data.label)
+
+ -- progressbar
+ local wd = { width, width * self._data.level }
+ for i = 1, 2 do
+ cr:set_source(color(i > 1 and style.color.main or style.color.gray))
+ cr:rectangle(0, style.line.y, wd[i], style.line.height)
+ cr:fill()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call monitor module as function
+-----------------------------------------------------------------------------------------------------------------------
+function monitor.mt:__call(...)
+ return monitor.new(...)
+end
+
+return setmetatable(monitor, monitor.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/separator.lua b/awesome/.config/awesome/redflat/gauge/separator.lua
new file mode 100644
index 0000000..20d6776
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/separator.lua
@@ -0,0 +1,87 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat separatoe widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Simple graphical separator to decorate panel
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local separator = {}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ marginv = { 0, 0, 0, 0 },
+ marginh = { 0, 0, 0, 0 },
+ color = { shadow1 = "#141414", shadow2 = "#313131" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.separator") or {})
+end
+
+-- Create a new separator widget
+-- Total size two pixels bigger than sum of margins for general direction
+-----------------------------------------------------------------------------------------------------------------------
+local function separator_base(horizontal, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+ if not style.margin then
+ style.margin = horizontal and style.marginh or style.marginv
+ end
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if horizontal then
+ return width, 2 + style.margin[3] + style.margin[4]
+ else
+ return 2 + style.margin[1] + style.margin[2], height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ local w = width - style.margin[1] - style.margin[2]
+ local h = height - style.margin[3] - style.margin[4]
+
+ cr:translate(style.margin[1], style.margin[3])
+ cr:set_source(color(style.color.shadow1))
+ if horizontal then cr:rectangle(0, 0, w, 1) else cr:rectangle(0, 0, 1, h) end
+ cr:fill()
+
+ cr:set_source(color(style.color.shadow2))
+ if horizontal then cr:rectangle(0, 1, w, 1) else cr:rectangle(1, 0, 1, h) end
+ cr:fill()
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Horizontal and vertial variants
+-----------------------------------------------------------------------------------------------------------------------
+function separator.vertical(style)
+ return separator_base(false, style)
+end
+
+function separator.horizontal(style)
+ return separator_base(true, style)
+end
+
+-----------------------------------------------------------------------------------------------------------------------
+return separator
diff --git a/awesome/.config/awesome/redflat/gauge/svgbox.lua b/awesome/.config/awesome/redflat/gauge/svgbox.lua
new file mode 100644
index 0000000..eef63ee
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/svgbox.lua
@@ -0,0 +1,218 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat svg icon widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Imagebox widget modification
+-- Use Gtk PixBuf API to resize svg image
+-- Color setup added
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ wibox.widget.imagebox v3.5.2
+------ (c) 2010 Uli Schlachter
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local string = string
+local type = type
+local pcall = pcall
+local print = print
+local math = math
+
+-- local Gdk = require("lgi").Gdk
+-- local pixbuf = require("lgi").GdkPixbuf
+-- local cairo = require("lgi").cairo
+local base = require("wibox.widget.base")
+local surface = require("gears.surface")
+local color = require("gears.color")
+
+local pixbuf
+local function load_pixbuf()
+ local _ = require("lgi").Gdk
+ pixbuf = require("lgi").GdkPixbuf
+end
+local is_pixbuf_loaded = pcall(load_pixbuf)
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local svgbox = { mt = {} }
+
+-- weak table is useless here
+-- TODO: implement mechanics to clear cache
+local cache = setmetatable({}, { __mode = 'k' })
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Check if given argument is SVG file
+local function is_svg(args)
+ return type(args) == "string" and string.match(args, "%.svg")
+end
+
+-- Check if need scale image
+local function need_scale(widg, width, height)
+ return (widg._image.width ~= width or widg._image.height ~= height) and widg.resize_allowed
+end
+
+-- Cache functions
+local function get_cache(file, width, height)
+ return cache[file .. "-" .. width .. "x" .. height]
+end
+
+local function set_cache(file, width, height, surf)
+ cache[file .. "-" .. width .. "x" .. height] = surf
+end
+
+-- Get cairo pattern
+local function get_current_pattern(cr)
+ cr:push_group()
+ cr:paint()
+ return cr:pop_group()
+end
+
+-- Create Gdk PixBuf from SVG file with given sizes
+local function pixbuf_from_svg(file, width, height)
+ local cached = get_cache(file, width, height)
+
+ if cached then
+ return cached
+ else
+ -- naughty.notify({ text = file })
+ local buf = pixbuf.Pixbuf.new_from_file_at_scale(file, width, height, true)
+ set_cache(file, width, height, buf)
+ return buf
+ end
+end
+
+-- Returns a new svgbox
+-----------------------------------------------------------------------------------------------------------------------
+function svgbox.new(image, resize_allowed, newcolor)
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_image(image_name)
+ local loaded_image
+
+ if type(image_name) == "string" then
+ local success, result = pcall(surface.load, image_name)
+ if not success then
+ print("Error while reading '" .. image_name .. "': " .. result)
+ return false
+ end
+ self.image_name = image_name
+ loaded_image = result
+ else
+ loaded_image = surface.load(image_name)
+ end
+
+ if loaded_image and (loaded_image.height <= 0 or loaded_image.width <= 0) then return false end
+
+ self._image = loaded_image
+ self.is_svg = is_svg(image_name)
+
+ self:emit_signal("widget::redraw_needed")
+ return true
+ end
+
+ function widg:set_color(new_color)
+ if self.color ~= new_color then
+ self.color = new_color
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_resize(allowed)
+ self.resize_allowed = allowed
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_vector_resize(allowed)
+ self.vector_resize_allowed = allowed
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ local fw, fh = self:get_forced_width(), self:get_forced_height()
+ if fw or fh then
+ return fw or width, fh or height
+ else
+ if not self._image then return 0, 0 end
+
+ local w, h = self._image.width, self._image.height
+
+ if self.resize_allowed or w > width or h > height then
+ local aspect = math.min(width / w, height / h)
+ return w * aspect, h * aspect
+ end
+
+ return w, h
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+ if width == 0 or height == 0 or not self._image then return end
+
+ local w, h = self._image.width, self._image.height
+ local aspect = math.min(width / w, height / h)
+
+ cr:save()
+ -- let's scale the image so that it fits into (width, height)
+ if need_scale(self, width, height) then
+ if self.is_svg and self.vector_resize_allowed and is_pixbuf_loaded then
+ -- for vector image
+ local pixbuf_ = pixbuf_from_svg(self.image_name, math.floor(w * aspect), math.floor(h * aspect))
+ cr:set_source_pixbuf(pixbuf_, 0, 0)
+ else
+ -- for raster image
+ cr:scale(aspect, aspect)
+ cr:set_source_surface(self._image, 0, 0)
+ cr:scale(1/aspect, 1/aspect) -- fix this !!!
+ end
+ else
+ cr:set_source_surface(self._image, 0, 0)
+ end
+
+ -- set icon color if need
+ if self.color then
+ local pattern = get_current_pattern(cr)
+ cr:scale(aspect, aspect) -- fix this !!!
+ cr:set_source(color(self.color))
+ cr:scale(1/aspect, 1/aspect) -- fix this !!!
+ cr:mask(pattern, 0, 0)
+ else
+ cr:paint()
+ end
+
+ cr:restore()
+ end
+
+ --------------------------------------------------------------------------------
+ if resize_allowed ~= nil then
+ widg.resize_allowed = resize_allowed
+ else
+ widg.resize_allowed = true
+ end
+
+ widg.color = newcolor
+ widg.vector_resize_allowed = true
+
+ if image then widg:set_image(image) end
+
+ return widg
+end
+
+-- Config metatable to call svgbox module as function
+-----------------------------------------------------------------------------------------------------------------------
+function svgbox.mt:__call(...)
+ return svgbox.new(...)
+end
+
+return setmetatable(svgbox, svgbox.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/tag/blue.lua b/awesome/.config/awesome/redflat/gauge/tag/blue.lua
new file mode 100644
index 0000000..a82faa8
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/blue.lua
@@ -0,0 +1,125 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local bluetag = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 80,
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ text_shift = 32,
+ point = { height = 4, gap = 8, dx = 6, width = 40 },
+ show_min = false,
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.tag.blue") or {})
+end
+
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function bluetag.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = { text = "TEXT" },
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width)
+ local n = #data.state.list
+
+ -- text
+ cr:set_source(color(
+ data.state.active and style.color.main
+ or (n == 0 or data.state.minimized) and style.color.gray
+ or style.color.icon
+ ))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { width / 2, style.text_shift }, data.state.text)
+
+ -- occupied mark
+ local x = (width - style.point.width) / 2
+
+ if n > 0 then
+ local l = (style.point.width - (n - 1) * style.point.dx) / n
+
+ for i = 1, n do
+ local cl = data.state.list[i].focus and style.color.main or
+ data.state.list[i].urgent and style.color.urgent or
+ data.state.list[i].minimized and style.show_min and style.color.gray or
+ style.color.icon
+ cr:set_source(color(cl))
+ cr:rectangle(x + (i - 1) * (style.point.dx + l), style.point.gap, l, style.point.height)
+ cr:fill()
+ end
+ else
+ cr:set_source(color(style.color.gray))
+ cr:rectangle((width - style.point.width) / 2, style.point.gap, style.point.width, style.point.height)
+ cr:fill()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call bluetag module as function
+-----------------------------------------------------------------------------------------------------------------------
+function bluetag.mt:__call(...)
+ return bluetag.new(...)
+end
+
+return setmetatable(bluetag, bluetag.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/tag/green.lua b/awesome/.config/awesome/redflat/gauge/tag/green.lua
new file mode 100644
index 0000000..3bbf29e
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/green.lua
@@ -0,0 +1,89 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local greentag = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 80,
+ margin = { 2, 2, 2, 2 },
+ icon = { unknown = redutil.base.placeholder() },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" },
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.tag.green") or {})
+end
+
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function greentag.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = {},
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.layout.align.horizontal()
+ widg._svgbox = svgbox()
+ widg:set_middle(wibox.container.margin(widg._svgbox, unpack(style.margin)))
+ widg:set_forced_width(data.width)
+ widg:set_expand("outside")
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ local icon = style.icon[awful.layout.getname(state.layout)] or style.icon.unknown
+ self._svgbox:set_image(icon)
+ self._svgbox:set_color(
+ data.state.active and style.color.main
+ or data.state.urgent and style.color.urgent
+ or data.state.occupied and style.color.icon
+ or style.color.gray
+ )
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self.set_forced_width(width)
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call greentag module as function
+-----------------------------------------------------------------------------------------------------------------------
+function greentag.mt:__call(...)
+ return greentag.new(...)
+end
+
+return setmetatable(greentag, greentag.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/tag/init.lua b/awesome/.config/awesome/redflat/gauge/tag/init.lua
new file mode 100644
index 0000000..7148144
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.tag" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/tag/orange.lua b/awesome/.config/awesome/redflat/gauge/tag/orange.lua
new file mode 100644
index 0000000..0e405e5
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/orange.lua
@@ -0,0 +1,141 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local orangetag = { mt = {} }
+local TPI = math.pi * 2
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 50,
+ line_width = 4,
+ radius = 14,
+ iradius = 6,
+ cgap = TPI / 20,
+ show_min = true,
+ min_sections = 1,
+ text = false,
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.tag.orange") or {})
+end
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function orangetag.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = { text = "TEXT" },
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ local sections = math.max(#data.state.list, style.min_sections)
+ local step = (TPI - sections * style.cgap) / sections
+ local cl
+
+ -- active mark
+ cl = data.state.active and style.color.main or (data.state.occupied and style.color.icon or style.color.gray)
+ cr:set_source(color(cl))
+
+ if style.text then
+ -- text
+ redutil.cairo.set_font(cr, style.font)
+ local ext = cr:text_extents(tostring(#data.state.list))
+ cr:move_to((width - ext.width - ext.x_bearing) / 2, (height + ext.height + ext.x_bearing) / 2)
+ cr:show_text(data.state.text)
+ cr:stroke()
+ else
+ -- round
+ cr:arc(width / 2, height / 2, style.iradius, 0, TPI)
+ cr:fill()
+ end
+
+ -- occupied mark
+ cr:set_line_width(style.line_width)
+ for i = 1, sections do
+ local cs = -TPI / 4 + (i - 1) * (step + style.cgap) + style.cgap / 2
+
+ if data.state.list[i] then
+ cl = data.state.list[i].focus and style.color.main or
+ data.state.list[i].urgent and style.color.urgent or
+ data.state.list[i].minimized and style.show_min and style.color.gray or style.color.icon
+ else
+ cl = style.color.gray
+ end
+
+ cr:set_source(color(cl))
+ if sections == 1 then
+ cr:arc(width / 2, height / 2, style.radius, 0, TPI)
+ else
+ cr:arc(width / 2, height / 2, style.radius, cs, cs + step)
+ end
+ cr:stroke()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call orangetag module as function
+-----------------------------------------------------------------------------------------------------------------------
+function orangetag.mt:__call(...)
+ return orangetag.new(...)
+end
+
+return setmetatable(orangetag, orangetag.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/tag/red.lua b/awesome/.config/awesome/redflat/gauge/tag/red.lua
new file mode 100644
index 0000000..cf80607
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/red.lua
@@ -0,0 +1,191 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local redtag = { mt = {} }
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+local function fill_geometry(width, height, geometry)
+ local zero_geometry = { x = 0, y = 0, width = width, height = height }
+ return redutil.table.merge(zero_geometry, geometry)
+end
+
+-- Cairo drawing functions
+--------------------------------------------------------------------------------
+local cairo_draw = {}
+
+-- Tag active mark (line)
+------------------------------------------------------------
+function cairo_draw.active(cr, width, height, geometry)
+ geometry = fill_geometry(width, height, geometry)
+
+ cr:rectangle(geometry.x, geometry.y, geometry.width, geometry.height)
+ cr:fill()
+end
+
+-- Tag focus mark (rhombus)
+------------------------------------------------------------
+function cairo_draw.focus(cr, width, height, geometry)
+ geometry = fill_geometry(width, height, geometry)
+
+ cr:move_to(geometry.x + geometry.width / 2, geometry.y)
+ cr:rel_line_to(geometry.width / 2, geometry.height / 2)
+ cr:rel_line_to(- geometry.width / 2, geometry.height / 2)
+ cr:rel_line_to(- geometry.width / 2, - geometry.height / 2)
+ cr:close_path()
+ cr:fill()
+end
+
+-- Tag occupied mark (label)
+------------------------------------------------------------
+function cairo_draw.occupied(cr, width, height, geometry)
+ geometry = fill_geometry(width, height, geometry)
+
+ cr:move_to(geometry.x, geometry.y)
+ cr:rel_line_to(0, geometry.height)
+ cr:rel_line_to(geometry.width / 2, - geometry.width / 2)
+ cr:rel_line_to(geometry.width / 2, geometry.width / 2)
+ cr:rel_line_to(0, - geometry.height)
+ cr:close_path()
+ cr:fill()
+end
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 80,
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ text_shift = 22,
+ counter = { size = 12, margin = 2, coord = { 40, 35 } },
+ show_counter = true,
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d",
+ wibox = "#202020" }
+ }
+
+ -- functions for state marks
+ style.marks = cairo_draw
+
+ -- geometry for state marks
+ style.geometry = {
+ active = { height = 5, y = 45 },
+ focus = { x = 5, y = 10, width = 10, height = 15 },
+ occupied = { x = 65, y = 10, width = 10, height = 15 }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.tag.red") or {})
+end
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function redtag.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = { text = "TEXT" },
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ -- text
+ cr:set_source(color(style.color.icon))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { width/2, style.text_shift }, data.state.text)
+
+ -- active mark
+ cr:set_source(color(data.state.active and style.color.main or style.color.gray))
+ style.marks.active(cr, width, height, style.geometry.active)
+
+ -- occupied mark
+ if data.state.occupied then
+ cr:set_source(color(data.state.urgent and style.color.urgent or style.color.main))
+ style.marks.occupied(cr, width, height, style.geometry.occupied)
+ end
+
+ -- focus mark
+ if data.state.focus then
+ cr:set_source(color(style.color.main))
+ style.marks.focus(cr, width, height, style.geometry.focus)
+ end
+
+ -- counter
+ if style.show_counter and #data.state.list > 0 then
+ cr:set_font_size(style.counter.size)
+ local ext = cr:text_extents(tostring(#data.state.list))
+ cr:set_source(color(style.color.wibox))
+ cr:rectangle(
+ style.counter.coord[1] - ext.width / 2 - style.counter.margin,
+ style.counter.coord[2] - ext.height / 2 - style.counter.margin,
+ ext.width + 2 * style.counter.margin,
+ ext.height + 2 * style.counter.margin
+ )
+ cr:fill()
+
+ cr:set_source(color(style.color.icon))
+ redutil.cairo.textcentre.full(cr, style.counter.coord, tostring(#data.state.list))
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call redtag module as function
+-----------------------------------------------------------------------------------------------------------------------
+function redtag.mt:__call(...)
+ return redtag.new(...)
+end
+
+return setmetatable(redtag, redtag.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/tag/ruby.lua b/awesome/.config/awesome/redflat/gauge/tag/ruby.lua
new file mode 100644
index 0000000..acd5e16
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/tag/ruby.lua
@@ -0,0 +1,114 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local rubytag = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 50,
+ base = { pad = 5, height = 12, thickness = 2 },
+ mark = { pad = 10, height = 4 },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.tag.ruby") or {})
+end
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function rubytag.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ -- state
+ local cl = data.state.active and style.color.main or style.color.gray
+ cr:set_source(color(cl))
+
+ cr:rectangle(
+ style.base.pad, math.floor((height - style.base.height) / 2),
+ width - 2 * style.base.pad, style.base.height
+ )
+ cr:set_line_width(style.base.thickness)
+ cr:stroke()
+
+ -- focus
+ cl = data.state.focus and style.color.main
+ or data.state.urgent and style.color.urgent
+ or (data.state.occupied and style.color.icon or style.color.gray)
+ cr:set_source(color(cl))
+
+ cr:rectangle(
+ style.mark.pad, math.floor((height - style.mark.height) / 2),
+ width - 2 * style.mark.pad, style.mark.height
+ )
+
+ cr:fill()
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call rubytag module as function
+-----------------------------------------------------------------------------------------------------------------------
+function rubytag.mt:__call(...)
+ return rubytag.new(...)
+end
+
+return setmetatable(rubytag, rubytag.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/task/green.lua b/awesome/.config/awesome/redflat/gauge/task/green.lua
new file mode 100644
index 0000000..f79c638
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/task/green.lua
@@ -0,0 +1,116 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat task widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget includes colored icon
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local unpack = unpack or table.unpack
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local greentask = { mt = {} }
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 40,
+ margin = { 0, 0, 0, 0 },
+ df_icon = redutil.base.placeholder(),
+ counter = { font = "Sans 10", mask = "%d" },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d", wibox = "#202020" },
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.task.green") or {})
+end
+
+
+-- Create a new greentask widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function greentask.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = {},
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.layout.stack()
+
+ widg._svgbox = svgbox()
+ widg._textbox = wibox.widget{
+ align = 'center',
+ valign = 'bottom',
+ font = style.counter.font,
+ widget = wibox.widget.textbox
+ }
+
+ widg._icon_layout = wibox.widget({
+ nil, wibox.container.margin(widg._svgbox, unpack(style.margin)),
+ layout = wibox.layout.align.horizontal,
+ expand = "outside",
+ })
+ widg._text_layout = wibox.widget({
+ nil, nil, widg._textbox,
+ -- nil, nil, wibox.container.background(widg._textbox, style.color.wibox),
+ layout = wibox.layout.align.vertical,
+ })
+
+ widg:add(widg._icon_layout)
+ widg:add(widg._text_layout)
+ widg:set_forced_width(data.width)
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = redutil.table.merge(data.state, state)
+
+ -- icon
+ local icon = state.icon or style.df_icon
+ self._svgbox:set_image(icon)
+ self._svgbox:set_color(
+ data.state.focus and style.color.main
+ or data.state.urgent and style.color.urgent
+ or data.state.minimized and style.color.gray
+ or style.color.icon
+ )
+
+ -- counter
+ self._text_layout:set_visible(state.num > 1)
+ self._textbox:set_markup(
+ string.format('' .. style.counter.mask .. '', style.color.wibox, state.num)
+ )
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self.set_forced_width(width)
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call greentask module as function
+-----------------------------------------------------------------------------------------------------------------------
+function greentask.mt:__call(...)
+ return greentask.new(...)
+end
+
+return setmetatable(greentask, greentask.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/task/init.lua b/awesome/.config/awesome/redflat/gauge/task/init.lua
new file mode 100644
index 0000000..a33b632
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/task/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.gauge.task" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/gauge/task/red.lua b/awesome/.config/awesome/redflat/gauge/task/red.lua
new file mode 100644
index 0000000..2e44fbc
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/task/red.lua
@@ -0,0 +1,120 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat task widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Widget includes label and decorative line
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local redtask = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 40,
+ line = { height = 4, y = 30 },
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ text_shift = 22,
+ counter = { size = 12, margin = 2 },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0",
+ urgent = "#32882d", wibox = "#202020" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.task.red") or {})
+end
+
+-- Create a new redtask widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function redtask.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = { text = "TXT" }
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = redutil.table.merge(data.state, state)
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width)
+
+ -- label
+ cr:set_source(color(data.state.minimized and style.color.gray or style.color.icon))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { width / 2, style.text_shift }, data.state.text)
+
+ -- line
+ local line_color = data.state.focus and style.color.main
+ or data.state.urgent and style.color.urgent
+ or style.color.gray
+ cr:set_source(color(line_color))
+ cr:rectangle(0, style.line.y, width, style.line.height)
+ cr:fill()
+
+ -- counter
+ if data.state.num > 1 then
+ cr:set_font_size(style.counter.size)
+ local ext = cr:text_extents(tostring(data.state.num))
+ cr:set_source(color(style.color.wibox))
+ cr:rectangle(
+ (width - ext.width) / 2 - style.counter.margin, style.line.y,
+ ext.width + 2 * style.counter.margin, style.counter.size
+ )
+ cr:fill()
+
+ cr:set_source(color(style.color.icon))
+ local coord = { width / 2, style.line.y + style.counter.size / 2 }
+ redutil.cairo.textcentre.horizontal(cr, coord, tostring(data.state.num))
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call redtask module as function
+-----------------------------------------------------------------------------------------------------------------------
+function redtask.mt:__call(...)
+ return redtask.new(...)
+end
+
+return setmetatable(redtask, redtask.mt)
diff --git a/awesome/.config/awesome/redflat/gauge/task/ruby.lua b/awesome/.config/awesome/redflat/gauge/task/ruby.lua
new file mode 100644
index 0000000..6727649
--- /dev/null
+++ b/awesome/.config/awesome/redflat/gauge/task/ruby.lua
@@ -0,0 +1,137 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tag widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget to display tag info
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local math = math
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local color = require("gears.color")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local rubytask = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 80,
+ font = { font = "Sans", size = 16, face = 0, slant = 0 },
+ text_shift = 26,
+ point = { size = 4, space = 3, gap = 3 },
+ underline = { height = 20, thickness = 4, gap = 36, dh = 4 },
+ color = { main = "#b1222b", gray = "#575757", icon = "#a0a0a0", urgent = "#32882d" }
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "gauge.task.ruby") or {})
+end
+
+
+-- Create a new tag widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function rubytask.new(style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- updating values
+ local data = {
+ state = { text = "TEXT" },
+ width = style.width or nil
+ }
+
+ -- Create custom widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_state(state)
+ data.state = state
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ function widg:set_width(width)
+ data.width = width
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if data.width then
+ return math.min(width, data.width), height
+ else
+ return width, height
+ end
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width)
+ local n = #data.state.list
+
+ -- text
+ cr:set_source(color(
+ data.state.active and style.color.main
+ or data.state.minimized and style.color.gray
+ or style.color.icon
+ ))
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.horizontal(cr, { width / 2, style.text_shift }, data.state.text)
+
+ -- underline
+ cr:set_source(color(
+ data.state.focus and style.color.main
+ or data.state.minimized and style.color.gray
+ or style.color.icon
+ ))
+
+ cr:move_to(0, style.underline.gap)
+ cr:rel_line_to(width, 0)
+ cr:rel_line_to(0, -style.underline.height)
+ cr:rel_line_to(-style.underline.thickness, style.underline.dh)
+ cr:rel_line_to(0, style.underline.height - style.underline.dh - style.underline.thickness)
+ cr:rel_line_to(2 * style.underline.thickness - width, 0)
+ cr:rel_line_to(0, style.underline.thickness + style.underline.dh - style.underline.height)
+ cr:rel_line_to(-style.underline.thickness, - style.underline.dh)
+ cr:close_path(-style.underline.thickness, 0)
+ cr:fill()
+
+ -- clients counter
+ local x = math.floor((width - style.point.size * n - style.point.space * (n - 1)) / 2)
+ local l = style.point.size + style.point.space
+
+ for i = 1, n do
+ cr:set_source(color(
+ data.state.list[i].focus and style.color.main or
+ data.state.list[i].urgent and style.color.urgent or
+ data.state.list[i].minimized and style.color.gray or
+ style.color.icon
+ ))
+ cr:rectangle(x + (i - 1) * l, style.point.gap, style.point.size, style.point.size)
+ cr:fill()
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call rubytask module as function
+-----------------------------------------------------------------------------------------------------------------------
+function rubytask.mt:__call(...)
+ return rubytask.new(...)
+end
+
+return setmetatable(rubytask, rubytask.mt)
diff --git a/awesome/.config/awesome/redflat/init.lua b/awesome/.config/awesome/redflat/init.lua
new file mode 100644
index 0000000..77cc904
--- /dev/null
+++ b/awesome/.config/awesome/redflat/init.lua
@@ -0,0 +1,12 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+
+return setmetatable(
+ { _NAME = "redflat" },
+ { __index = function(table, key)
+ local module = rawget(table, key)
+ return module or require(table._NAME .. '.' .. key)
+ end }
+)
diff --git a/awesome/.config/awesome/redflat/layout/common.lua b/awesome/.config/awesome/redflat/layout/common.lua
new file mode 100644
index 0000000..b447869
--- /dev/null
+++ b/awesome/.config/awesome/redflat/layout/common.lua
@@ -0,0 +1,371 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat layout shared functions --
+-----------------------------------------------------------------------------------------------------------------------
+-- Hotkeys for layout manipulation
+-- Handlers adapted for work with redflat navigator widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local awful = require("awful")
+local navigator = require("redflat.service.navigator")
+
+local ipairs = ipairs
+
+local alayout = awful.layout
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local common = { handler = {}, last = {}, tips = {}, keys = {}, mouse = {} }
+
+common.wfactstep = 0.05
+
+-- default keys
+common.keys.base = {
+ {
+ { "Mod4" }, "c", function() common.action.kill() end,
+ { description = "Kill application", group = "Action" }
+ },
+ {
+ {}, "Escape", function() common.action.exit() end,
+ { description = "Exit navigation mode", group = "Action" }
+ },
+ {
+ { "Mod4" }, "Escape", function() common.action.exit() end,
+ {} -- hidden key
+ },
+ {
+ { "Mod4" }, "Super_L", function() common.action.exit() end,
+ { description = "Exit navigation mode", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+common.keys.swap = {
+ {
+ { "Mod4" }, "Up", function() awful.client.swap.bydirection("up") end,
+ { description = "Move application up", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Down", function() awful.client.swap.bydirection("down") end,
+ { description = "Move application down", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Left", function() awful.client.swap.bydirection("left") end,
+ { description = "Move application left", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Right", function() awful.client.swap.bydirection("right") end,
+ { description = "Move application right", group = "Movement" }
+ },
+}
+
+common.keys.tile = {
+ {
+ { "Mod4" }, "l", function () awful.tag.incmwfact( common.wfactstep) end,
+ { description = "Increase master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "h", function () awful.tag.incmwfact(-common.wfactstep) end,
+ { description = "Decrease master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4", "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
+ { description = "Increase the number of master clients", group = "Layout" }
+ },
+ {
+ { "Mod4", "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
+ { description = "Decrease the number of master clients", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
+ { description = "Increase the number of columns", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
+ { description = "Decrease the number of columns", group = "Layout" }
+ },
+}
+
+common.keys.corner = {
+ {
+ { "Mod4" }, "l", function () awful.tag.incmwfact( common.wfactstep) end,
+ { description = "Increase master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "h", function () awful.tag.incmwfact(-common.wfactstep) end,
+ { description = "Decrease master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4", "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
+ { description = "Increase the number of master clients", group = "Layout" }
+ },
+ {
+ { "Mod4", "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
+ { description = "Decrease the number of master clients", group = "Layout" }
+ },
+}
+
+common.keys.magnifier = {
+ {
+ { "Mod4" }, "l", function () awful.tag.incmwfact( common.wfactstep) end,
+ { description = "Increase master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "h", function () awful.tag.incmwfact(-common.wfactstep) end,
+ { description = "Decrease master width factor", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "g", function () awful.client.setmaster(client.focus) end,
+ { description = "Set focused client as master", group = "Movement" }
+ },
+}
+
+-- TODO: set real keyset from navigator theme
+common.keys._fake = {
+ {
+ { "Mod4" }, "N1 N2", nil,
+ {
+ description = "Swap clients by key", group = "Movement",
+ keyset = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" }
+ }
+ },
+ {
+ { "Mod4" }, "N1 N1", nil,
+ {
+ description = "Focus client by key", group = "Action",
+ keyset = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0" }
+ }
+ },
+}
+
+-- Common handler actions
+-----------------------------------------------------------------------------------------------------------------------
+common.action = {}
+
+function common.action.exit()
+ navigator:close()
+ common.last = {}
+end
+
+function common.action.kill()
+ client.focus:kill()
+ navigator:restart()
+ common.last.key = nil
+end
+
+-- Keys setup
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Hotkey tips update functions
+--------------------------------------------------------------------------------
+common.updates = {}
+
+local function build_base_tip()
+ return awful.util.table.join(common.keys.swap, common.keys.base, common.keys._fake)
+end
+
+local function build_tile_tip()
+ return awful.util.table.join(common.keys.swap, common.keys.tile, common.keys.base, common.keys._fake)
+end
+
+local function build_corner_tip()
+ return awful.util.table.join(common.keys.swap, common.keys.corner, common.keys.base, common.keys._fake)
+end
+
+local function build_magnifier_tip()
+ return awful.util.table.join(common.keys.magnifier, common.keys.base, common.keys._fake)
+end
+
+local function set_corner_tip()
+ common.tips[alayout.suit.corner.nw] = build_corner_tip()
+ common.tips[alayout.suit.corner.ne] = build_corner_tip()
+ common.tips[alayout.suit.corner.sw] = build_corner_tip()
+ common.tips[alayout.suit.corner.se] = build_corner_tip()
+end
+
+local function set_tile_tip()
+ common.tips[alayout.suit.tile] = build_tile_tip()
+ common.tips[alayout.suit.tile.right] = build_tile_tip()
+ common.tips[alayout.suit.tile.left] = build_tile_tip()
+ common.tips[alayout.suit.tile.top] = build_tile_tip()
+ common.tips[alayout.suit.tile.bottom] = build_tile_tip()
+end
+
+common.updates.swap = function()
+ common.tips[alayout.suit.fair] = build_base_tip()
+ common.tips[alayout.suit.spiral] = build_base_tip()
+ common.tips[alayout.suit.spiral.dwindle] = build_base_tip()
+ set_tile_tip()
+ set_corner_tip()
+end
+
+common.updates.base = function()
+ common.tips[alayout.suit.fair] = build_base_tip()
+ common.tips[alayout.suit.spiral] = build_base_tip()
+ common.tips[alayout.suit.spiral.dwindle] = build_base_tip()
+ common.tips[alayout.suit.magnifier] = build_magnifier_tip()
+ set_tile_tip()
+ set_corner_tip()
+end
+
+common.updates.magnifier = function()
+ common.tips[alayout.suit.magnifier] = build_magnifier_tip()
+end
+
+common.updates.tile = function()
+ set_tile_tip()
+end
+
+common.updates.corner = function()
+ set_corner_tip()
+end
+
+-- Keys setup function
+--------------------------------------------------------------------------------
+function common:set_keys(keys, layout)
+ if keys then common.keys[layout] = keys end -- update keys
+ if self.updates[layout] then self.updates[layout]() end -- update tips
+end
+
+-- Shared keyboard handlers
+-----------------------------------------------------------------------------------------------------------------------
+common.grabbers = {}
+
+-- Base grabbers
+--------------------------------------------------------------------------------
+common.grabbers.base = function(mod, key)
+ for _, k in ipairs(common.keys.base) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+
+ -- if numkey pressed
+ local index = awful.util.table.hasitem(navigator.style.num, key)
+
+ -- swap or focus client
+ if index then
+ if navigator.data[index] and awful.util.table.hasitem(navigator.cls, navigator.data[index].client) then
+ if common.last.key then
+ if common.last.key == index then
+ client.focus = navigator.data[index].client
+ client.focus:raise()
+ else
+ redutil.client.swap(navigator.data[common.last.key].client, navigator.data[index].client)
+ end
+ common.last.key = nil
+ else
+ common.last.key = index
+ end
+
+ return true
+ end
+ end
+end
+
+common.grabbers.swap = function(mod, key)
+ for _, k in ipairs(common.keys.swap) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+common.grabbers.tile = function(mod, key)
+ for _, k in ipairs(common.keys.tile) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+common.grabbers.corner = function(mod, key)
+ for _, k in ipairs(common.keys.corner) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+common.grabbers.magnifier = function(mod, key)
+ for _, k in ipairs(common.keys.magnifier) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+-- Grabbers for awful layouts
+--------------------------------------------------------------------------------
+local function fair_handler(mod, key, event)
+ if event == "press" then return end
+ if common.grabbers.swap(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+local function magnifier_handler(mod, key, event)
+ if event == "press" then return end
+ if common.grabbers.magnifier(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+local function tile_handler(mod, key, event)
+ if event == "press" then return end
+ if common.grabbers.tile(mod, key, event) then return end
+ if common.grabbers.swap(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+local function corner_handler(mod, key, event)
+ if event == "press" then return end
+ if common.grabbers.corner(mod, key, event) then return end
+ if common.grabbers.swap(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+-- Handlers table
+-----------------------------------------------------------------------------------------------------------------------
+common.handler[alayout.suit.fair] = fair_handler
+common.handler[alayout.suit.spiral] = fair_handler
+common.handler[alayout.suit.magnifier] = magnifier_handler
+common.handler[alayout.suit.tile] = tile_handler
+common.handler[alayout.suit.tile.right] = tile_handler
+common.handler[alayout.suit.tile.left] = tile_handler
+common.handler[alayout.suit.tile.top] = tile_handler
+common.handler[alayout.suit.tile.bottom] = tile_handler
+common.handler[alayout.suit.corner.nw] = corner_handler
+common.handler[alayout.suit.corner.ne] = corner_handler
+common.handler[alayout.suit.corner.se] = corner_handler
+common.handler[alayout.suit.corner.sw] = corner_handler
+
+common.handler[alayout.suit.spiral.dwindle] = fair_handler
+
+-- tip dirty setup
+common:set_keys(nil, "base")
+
+
+-- Slightly changed awful mouse move handler
+-----------------------------------------------------------------------------------------------------------------------
+function common.mouse.move(c, context, hints)
+ -- Quit if it isn't a mouse.move on a tiled layout, that's handled elsewhere (WHERE?)
+ if c.floating then return end
+ if context ~= "mouse.move" then return end
+
+ -- move to screen with mouse
+ if mouse.screen ~= c.screen then c.screen = mouse.screen end
+
+ -- check if cutstom layout hadler availible
+ local l = c.screen.selected_tag and c.screen.selected_tag.layout or nil
+ if l == awful.layout.suit.floating then return end
+
+ if l and l.move_handler then
+ l.move_handler(c, context, hints)
+ return
+ end
+
+ -- general handler for tile layouts
+ local c_u_m = mouse.current_client
+ if c_u_m and not c_u_m.floating then
+ if c_u_m ~= c then c:swap(c_u_m) end
+ end
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return common
diff --git a/awesome/.config/awesome/redflat/layout/grid.lua b/awesome/.config/awesome/redflat/layout/grid.lua
new file mode 100644
index 0000000..60fb226
--- /dev/null
+++ b/awesome/.config/awesome/redflat/layout/grid.lua
@@ -0,0 +1,480 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat grid layout --
+-----------------------------------------------------------------------------------------------------------------------
+-- Floating layout with discrete geometry
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local beautiful = require("beautiful")
+
+local ipairs = ipairs
+local pairs = pairs
+local math = math
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local common = require("redflat.layout.common")
+local redutil = require("redflat.util")
+
+local hasitem = awful.util.table.hasitem
+
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local grid = { data = {} }
+grid.name = "grid"
+
+-- default keys
+grid.keys = {}
+grid.keys.move = {
+ {
+ { "Mod4" }, "Up", function() grid.move_to("up") end,
+ { description = "Move window up", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Down", function() grid.move_to("down") end,
+ { description = "Move window down", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Left", function() grid.move_to("left") end,
+ { description = "Move window left", group = "Movement" }
+ },
+ {
+ { "Mod4" }, "Right", function() grid.move_to("right") end,
+ { description = "Move window right", group = "Movement" }
+ },
+ {
+ { "Mod4", "Control" }, "Up", function() grid.move_to("up", true) end,
+ { description = "Move window up by bound", group = "Movement" }
+ },
+ {
+ { "Mod4", "Control" }, "Down", function() grid.move_to("down", true) end,
+ { description = "Move window down by bound", group = "Movement" }
+ },
+ {
+ { "Mod4", "Control" }, "Left", function() grid.move_to("left", true) end,
+ { description = "Move window left by bound", group = "Movement" }
+ },
+ {
+ { "Mod4", "Control" }, "Right", function() grid.move_to("right", true) end,
+ { description = "Move window right by bound", group = "Movement" }
+ },
+}
+
+grid.keys.resize = {
+ {
+ { "Mod4" }, "k", function() grid.resize_to("up") end,
+ { description = "Inrease window size to the up", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "j", function() grid.resize_to("down") end,
+ { description = "Inrease window size to the down", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "h", function() grid.resize_to("left") end,
+ { description = "Inrease window size to the left", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "l", function() grid.resize_to("right") end,
+ { description = "Inrease window size to the right", group = "Resize" }
+ },
+ {
+ { "Mod4", "Shift" }, "k", function() grid.resize_to("up", nil, true) end,
+ { description = "Decrease window size from the up", group = "Resize" }
+ },
+ {
+ { "Mod4", "Shift" }, "j", function() grid.resize_to("down", nil, true) end,
+ { description = "Decrease window size from the down", group = "Resize" }
+ },
+ {
+ { "Mod4", "Shift" }, "h", function() grid.resize_to("left", nil, true) end,
+ { description = "Decrease window size from the left", group = "Resize" }
+ },
+ {
+ { "Mod4", "Shift" }, "l", function() grid.resize_to("right", nil, true) end,
+ { description = "Decrease window size from the right", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "k", function() grid.resize_to("up", true) end,
+ { description = "Increase window size to the up by bound", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "j", function() grid.resize_to("down", true) end,
+ { description = "Increase window size to the down by bound", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "h", function() grid.resize_to("left", true) end,
+ { description = "Increase window size to the left by bound", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "l", function() grid.resize_to("right", true) end,
+ { description = "Increase window size to the right by bound", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control", "Shift" }, "k", function() grid.resize_to("up", true, true) end,
+ { description = "Decrease window size from the up by bound ", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control", "Shift" }, "j", function() grid.resize_to("down", true, true) end,
+ { description = "Decrease window size from the down by bound ", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control", "Shift" }, "h", function() grid.resize_to("left", true, true) end,
+ { description = "Decrease window size from the left by bound ", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control", "Shift" }, "l", function() grid.resize_to("right", true, true) end,
+ { description = "Decrease window size from the right by bound ", group = "Resize" }
+ },
+}
+
+grid.keys.all = awful.util.table.join(grid.keys.move, grid.keys.resize)
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function compare(a ,b) return a < b end
+
+-- Find all rails for given client
+------------------------------------------------------------
+local function get_rail(c)
+ local wa = screen[c.screen].workarea
+ local cls = awful.client.visible(c.screen)
+
+ local rail = { x = { wa.x, wa.x + wa.width }, y = { wa.y, wa.y + wa.height } }
+ table.remove(cls, hasitem(cls, c))
+
+ for _, v in ipairs(cls) do
+ local lg = redutil.client.fullgeometry(v)
+ local xr = lg.x + lg.width
+ local yb = lg.y + lg.height
+
+ if not hasitem(rail.x, lg.x) then table.insert(rail.x, lg.x) end
+ if not hasitem(rail.x, xr) then table.insert(rail.x, xr) end
+ if not hasitem(rail.y, lg.y) then table.insert(rail.y, lg.y) end
+ if not hasitem(rail.y, yb) then table.insert(rail.y, yb) end
+ end
+
+ table.sort(rail.x, compare)
+ table.sort(rail.y, compare)
+
+ return rail
+end
+
+local function update_rail(c) grid.data.rail = get_rail(c) end
+
+-- Calculate cell geometry
+------------------------------------------------------------
+local function make_cell(wa, cellnum)
+ local cell = {
+ x = wa.width / cellnum.x,
+ y = wa.height / cellnum.y
+ }
+
+ -- adapt cell table to work with geometry prop
+ cell.width = cell.x
+ cell.height = cell.y
+
+ return cell
+end
+
+-- Grid rounding
+------------------------------------------------------------
+local function round(a, n)
+ return n * math.floor((a + n / 2) / n)
+end
+
+-- Fit client into grid
+------------------------------------------------------------
+local function fit_cell(g, cell)
+ local ng = {}
+
+ for k, v in pairs(g) do
+ ng[k] = math.ceil(round(v, cell[k]))
+ end
+
+ return ng
+end
+
+-- Check geometry difference
+------------------------------------------------------------
+local function is_diff(g1, g2, cell)
+ for k, v in pairs(g1) do
+ if math.abs(g2[k] - v) >= cell[k] then return true end
+ end
+
+ return false
+end
+
+-- Move client
+-----------------------------------------------------------------------------------------------------------------------
+function grid.move_to(dir, is_rail, k)
+ local ng = {}
+ local data = grid.data
+ local c = client.focus
+
+ if not c then return end
+ if data.last ~= c then
+ data.last = c
+ update_rail(c)
+ end
+
+ local g = redutil.client.fullgeometry(c)
+ k = k or 1
+
+ if dir == "left" then
+ if is_rail then
+ for i = #data.rail.x, 1, - 1 do
+ if data.rail.x[i] < g.x then
+ ng.x = data.rail.x[i]
+ break
+ end
+ end
+ else
+ ng.x = g.x - data.cell.x * k
+ end
+ elseif dir == "right" then
+ if is_rail then
+ for i = 1, #data.rail.x do
+ if data.rail.x[i] > g.x + g.width + 1 then
+ ng.x = data.rail.x[i] - g.width
+ break
+ end
+ end
+ else
+ ng.x = g.x + data.cell.x * k
+ end
+ elseif dir == "up" then
+ if is_rail then
+ for i = #data.rail.y, 1, - 1 do
+ if data.rail.y[i] < g.y then
+ ng.y = data.rail.y[i]
+ break
+ end
+ end
+ else
+ ng.y = g.y - data.cell.y * k
+ end
+ elseif dir == "down" then
+ if is_rail then
+ for i = 1, #data.rail.y do
+ if data.rail.y[i] > g.y + g.height + 1 then
+ ng.y = data.rail.y[i] - g.height
+ break
+ end
+ end
+ else
+ ng.y = g.y + data.cell.y * k
+ end
+ end
+
+ redutil.client.fullgeometry(c, ng)
+end
+
+-- Resize client
+-----------------------------------------------------------------------------------------------------------------------
+grid.resize_to = function(dir, is_rail, is_reverse)
+ local ng = {}
+ local c = client.focus
+ local data = grid.data
+
+ if not c then return end
+ if data.last ~= c then
+ data.last = c
+ update_rail(c)
+ end
+
+ local g = redutil.client.fullgeometry(c)
+ local sign = is_reverse and -1 or 1
+
+ if dir == "up" then
+ if is_rail then
+ -- select loop direction (from min to max or from max to min)
+ local f, l, s = unpack(is_reverse and { 1, #data.rail.y, 1 } or { #data.rail.y, 1, - 1 })
+ for i = f, l, s do
+ if is_reverse and data.rail.y[i] > g.y or not is_reverse and data.rail.y[i] < g.y then
+ ng = { y = data.rail.y[i], height = g.height + g.y - data.rail.y[i] }
+ break
+ end
+ end
+ else
+ ng = { y = g.y - sign * data.cell.y, height = g.height + sign * data.cell.y }
+ end
+ elseif dir == "down" then
+ if is_rail then
+ local f, l, s = unpack(is_reverse and { #data.rail.y, 1, - 1 } or { 1, #data.rail.y, 1 })
+ for i = f, l, s do
+ if is_reverse and data.rail.y[i] < (g.y + g.height - 1)
+ or not is_reverse and data.rail.y[i] > (g.y + g.height + 1) then
+ ng = { height = data.rail.y[i] - g.y }
+ break
+ end
+ end
+ else
+ ng = { height = g.height + sign * data.cell.y }
+ end
+ elseif dir == "left" then
+ if is_rail then
+ local f, l, s = unpack(is_reverse and { 1, #data.rail.x, 1 } or { #data.rail.x, 1, - 1 })
+ for i = f, l, s do
+ if is_reverse and data.rail.x[i] > g.x or not is_reverse and data.rail.x[i] < g.x then
+ ng = { x = data.rail.x[i], width = g.width + g.x - data.rail.x[i] }
+ break
+ end
+ end
+ else
+ ng = { x = g.x - sign * data.cell.x, width = g.width + sign * data.cell.x }
+ end
+ elseif dir == "right" then
+ if is_rail then
+ local f, l, s = unpack(is_reverse and { #data.rail.x, 1, - 1 } or { 1, #data.rail.x, 1 })
+ for i = f, l, s do
+ if is_reverse and data.rail.x[i] < (g.x + g.width)
+ or not is_reverse and data.rail.x[i] > (g.x + g.width + 1) then
+ ng = { width = data.rail.x[i] - g.x }
+ break
+ end
+ end
+ else
+ ng = { width = g.width + sign * data.cell.x }
+ end
+ end
+
+ redutil.client.fullgeometry(c, ng)
+end
+
+-- Keygrabber
+-----------------------------------------------------------------------------------------------------------------------
+grid.maingrabber = function(mod, key)
+ for _, k in ipairs(grid.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+grid.key_handler = function (mod, key, event)
+ if event == "press" then return end
+ if grid.maingrabber(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+
+-- Tile function
+-----------------------------------------------------------------------------------------------------------------------
+function grid.arrange(p)
+
+ -- theme vars
+ local cellnum = beautiful.cellnum or { x = 100, y = 60 }
+
+ -- aliases
+ local wa = p.workarea
+ local cls = p.clients
+
+ -- calculate cell
+ -- fix useless gap correction?
+ grid.data.cell = make_cell({ width = wa.width + 2 * p.useless_gap, height = wa.height + 2 * p.useless_gap }, cellnum)
+
+ -- nothing to tile here
+ if #cls == 0 then return end
+
+ -- tile
+ for _, c in ipairs(cls) do
+ local g = redutil.client.fullgeometry(c)
+
+ g = fit_cell(g, grid.data.cell)
+ redutil.client.fullgeometry(c, g)
+ end
+end
+
+
+-- Mouse moving function
+-----------------------------------------------------------------------------------------------------------------------
+function grid.move_handler(c, _, hints)
+ local g = redutil.client.fullgeometry(c)
+ local hg = { x = hints.x, y = hints.y, width = g.width, height = g.height }
+ if is_diff(hg, g, grid.data.cell) then
+ redutil.client.fullgeometry(c, fit_cell(hg, grid.data.cell))
+ end
+end
+
+
+-- Mouse resizing function
+-----------------------------------------------------------------------------------------------------------------------
+function grid.mouse_resize_handler(c, corner)
+ local g = redutil.client.fullgeometry(c)
+ local cg = g
+
+ -- set_mouse_on_corner(g, corner)
+
+ mousegrabber.run(
+ function (_mouse)
+ for _, v in ipairs(_mouse.buttons) do
+ if v then
+ local ng
+ if corner == "bottom_right" then
+ ng = {
+ width = _mouse.x - g.x,
+ height = _mouse.y - g.y
+ }
+ elseif corner == "bottom_left" then
+ ng = {
+ x = _mouse.x,
+ width = (g.x + g.width) - _mouse.x,
+ height = _mouse.y - g.y
+ }
+ elseif corner == "top_left" then
+ ng = {
+ x = _mouse.x,
+ y = _mouse.y,
+ width = (g.x + g.width) - _mouse.x,
+ height = (g.y + g.height) - _mouse.y
+ }
+ else
+ ng = {
+ y = _mouse.y,
+ width = _mouse.x - g.x,
+ height = (g.y + g.height) - _mouse.y
+ }
+ end
+
+ if ng.width <= 0 then ng.width = nil end
+ if ng.height <= 0 then ng.height = nil end
+ -- if c.maximized_horizontal then ng.width = g.width ng.x = g.x end
+ -- if c.maximized_vertical then ng.height = g.height ng.y = g.y end
+
+ if is_diff(ng, cg, grid.data.cell) then
+ cg = redutil.client.fullgeometry(c, fit_cell(ng, grid.data.cell))
+ end
+
+ return true
+ end
+ end
+ return false
+ end,
+ corner .. "_corner"
+ )
+end
+
+-- Redflat navigator support functions
+-----------------------------------------------------------------------------------------------------------------------
+function grid:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then grid.keys.all = awful.util.table.join(grid.keys.move, grid.keys.resize) end
+ end
+
+ self.tip = awful.util.table.join(self.keys.all, common.keys.base)
+end
+
+function grid.startup()
+ if not grid.tip then grid:set_keys() end
+end
+
+function grid.cleanup()
+ grid.data.last = nil
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return grid
diff --git a/awesome/.config/awesome/redflat/layout/init.lua b/awesome/.config/awesome/redflat/layout/init.lua
new file mode 100644
index 0000000..e7d7975
--- /dev/null
+++ b/awesome/.config/awesome/redflat/layout/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.layout" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/layout/map.lua b/awesome/.config/awesome/redflat/layout/map.lua
new file mode 100644
index 0000000..e430c81
--- /dev/null
+++ b/awesome/.config/awesome/redflat/layout/map.lua
@@ -0,0 +1,688 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat map layout --
+-----------------------------------------------------------------------------------------------------------------------
+-- Tiling with user defined geometry
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local ipairs = ipairs
+local pairs = pairs
+local math = math
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local timer = require("gears.timer")
+
+local redflat = require("redflat")
+local redutil = require("redflat.util")
+local common = require("redflat.layout.common")
+local rednotify = require("redflat.float.notify")
+
+local hasitem = awful.util.table.hasitem
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local map = { data = setmetatable({}, { __mode = "k" }), scheme = setmetatable({}, { __mode = "k" }), keys = {} }
+map.name = "usermap"
+map.notification = true
+map.notification_style = {}
+
+local hitimer
+map.hilight_timeout = 0.2
+
+
+-- default keys
+map.keys.layout = {
+ {
+ { "Mod4" }, "s", function() map.swap_group() end,
+ { description = "Change placement direction for group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "v", function() map.new_group(true) end,
+ { description = "Create new vertical group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "b", function() map.new_group(false) end,
+ { description = "Create new horizontal group", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "v", function() map.insert_group(true) end,
+ { description = "Insert new vertical group before active", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "b", function() map.insert_group(false) end,
+ { description = "Insert new horizontal group before active", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "d", function() map.delete_group() end,
+ { description = "Destroy group", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "d", function() map.clean_groups() end,
+ { description = "Destroy all empty groups", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "a", function() map.set_active() end,
+ { description = "Set active group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "f", function() map.move_to_active() end,
+ { description = "Move focused client to active group", group = "Layout" }
+ },
+ {
+ { "Mod4", "Control" }, "a", function() map.hilight_active() end,
+ { description = "Hilight active group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, ".", function() map.switch_active(1) end,
+ { description = "Activate next group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, ",", function() map.switch_active(-1) end,
+ { description = "Activate previous group", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "]", function() map.move_group(1) end,
+ { description = "Move active group to the top", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "[", function() map.move_group(-1) end,
+ { description = "Move active group to the bottom", group = "Layout" }
+ },
+ {
+ { "Mod4" }, "r", function() map.reset_tree() end,
+ { description = "Reset layout structure", group = "Layout" }
+ },
+}
+
+map.keys.resize = {
+ {
+ { "Mod4" }, "h", function() map.incfactor(nil, 0.1, false) end,
+ { description = "Increase window horizontal size factor", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "l", function() map.incfactor(nil, -0.1, false) end,
+ { description = "Decrease window horizontal size factor", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "k", function() map.incfactor(nil, 0.1, true) end,
+ { description = "Increase window vertical size factor", group = "Resize" }
+ },
+ {
+ { "Mod4" }, "j", function() map.incfactor(nil, -0.1, true) end,
+ { description = "Decrease window vertical size factor", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "h", function() map.incfactor(nil, 0.1, false, true) end,
+ { description = "Increase group horizontal size factor", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "l", function() map.incfactor(nil, -0.1, false, true) end,
+ { description = "Decrease group horizontal size factor", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "k", function() map.incfactor(nil, 0.1, true, true) end,
+ { description = "Increase group vertical size factor", group = "Resize" }
+ },
+ {
+ { "Mod4", "Control" }, "j", function() map.incfactor(nil, -0.1, true, true) end,
+ { description = "Decrease group vertical size factor", group = "Resize" }
+ },
+}
+
+
+map.keys.all = awful.util.table.join(map.keys.layout, map.keys.resize)
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Layout action notifications
+--------------------------------------------------------------------------------
+local function notify(txt)
+ if map.notification then rednotify:show(redutil.table.merge({ text = txt }, map.notification_style)) end
+end
+
+-- Calculate geometry for single client or group
+--------------------------------------------------------------------------------
+local function cut_geometry(wa, is_vertical, size)
+ if is_vertical then
+ local g = { x = wa.x, y = wa.y, width = wa.width, height = size }
+ wa.y = wa.y + size
+ return g
+ else
+ local g = { x = wa.x, y = wa.y, width = size, height = wa.height }
+ wa.x = wa.x + size
+ return g
+ end
+end
+
+-- Build container for single client or group
+--------------------------------------------------------------------------------
+function map.construct_itempack(cls, wa, is_vertical, parent)
+ local pack = { items = {}, wa = wa, cls = { unpack(cls) }, is_vertical = is_vertical, parent = parent }
+
+ -- Create pack of items with base properties
+ ------------------------------------------------------------
+ for i, c in ipairs(cls) do
+ pack.items[i] = { client = c, child = nil, factor = 1 }
+ end
+
+ -- Update pack clients
+ ------------------------------------------------------------
+ function pack:set_cls(clist)
+ local current = { unpack(clist) }
+
+ -- update existing items, remove overage if need
+ for i, item in ipairs(self.items) do
+ if not item.child then
+ if #current > 0 then
+ self.items[i].client = current[1]
+ table.remove(current, 1)
+ else
+ self.items[i] = nil
+ end
+ end
+ end
+
+ -- create additional items if need
+ for _, c in ipairs(current) do
+ self.items[#self.items + 1] = { client = c, child = nil, factor = 1 }
+ end
+ end
+
+ -- Get current pack clients
+ ------------------------------------------------------------
+ function pack:get_cls()
+ local clist = {}
+ for _, item in ipairs(self.items) do if not item.child then clist[#clist + 1] = item.client end end
+ return clist
+ end
+
+ -- Update pack geometry
+ ------------------------------------------------------------
+ function pack:set_wa(workarea)
+ self.wa = workarea
+ end
+
+ -- Get number of items reserved for single client only
+ ------------------------------------------------------------
+ function pack:get_places()
+ local n = 0
+ for _, item in ipairs(self.items) do if not item.child then n = n + 1 end end
+ return n
+ end
+
+ -- Get child index
+ ------------------------------------------------------------
+ function pack:get_child_id(pack_)
+ for i, item in ipairs(self.items) do
+ if item.child == pack_ then return i end
+ end
+ end
+
+ -- Check if container with inheritors keep any real client
+ ------------------------------------------------------------
+ function pack:is_filled()
+ local filled = false
+ for _, item in ipairs(self.items) do
+ if not item.child then
+ return true
+ else
+ filled = filled or item.child:is_filled()
+ end
+ end
+ return filled
+ end
+
+ -- Increase window size factor for item with index
+ ------------------------------------------------------------
+ function pack:incfacror(index, df, vertical)
+ if vertical == self.is_vertical then
+ self.items[index].factor = math.max(self.items[index].factor + df, 0.1)
+ elseif self.parent then
+ local pi = self.parent:get_child_id(self)
+ self.parent:incfacror(pi, df, vertical)
+ end
+ end
+
+ -- Recalculate geometry for every item in container
+ ------------------------------------------------------------
+ function pack:rebuild()
+ -- vars
+ local geometries = {}
+ local weight = 0
+ local area = awful.util.table.clone(self.wa)
+ local direction = self.is_vertical and "height" or "width"
+
+ -- check factor norming
+ for _, item in ipairs(self.items) do
+ if not item.child or item.child:is_filled() then weight = weight + item.factor end
+ end
+ if weight == 0 then return geometries end
+
+ -- geomentry calculation
+ for i, item in ipairs(self.items) do
+ if not item.child or item.child:is_filled() then
+ local size = self.wa[direction] / weight * item.factor
+ local g = cut_geometry(area, self.is_vertical, size, i)
+ if item.child then
+ item.child:set_wa(g)
+ else
+ geometries[item.client] = g
+ end
+ end
+ end
+
+ return geometries
+ end
+
+ return pack
+end
+
+-- Build layout tree
+--------------------------------------------------------------------------------
+local function construct_tree(wa, t)
+
+ -- Initial structure on creation
+ ------------------------------------------------------------
+ local tree = map.scheme[t] and map.scheme[t].construct(wa) or map.base_construct(wa)
+
+ -- Find pack contaner for client
+ ------------------------------------------------------------
+ function tree:get_pack(c)
+ for _, pack in ipairs(self.set) do
+ for i, item in ipairs(pack.items) do
+ if not item.child and c == item.client then return pack, i end
+ end
+ end
+ end
+
+ -- Create new contaner in place of client
+ ------------------------------------------------------------
+ function tree:create_group(c, is_vertical)
+ local parent, index = self:get_pack(c)
+ local new_pack = map.construct_itempack({}, {}, is_vertical, parent)
+
+ self.set[#self.set + 1] = new_pack
+ parent.items[index] = { child = new_pack, factor = 1 }
+ self.active = #self.set
+
+ awful.client.setslave(c)
+ notify("New " .. (is_vertical and "vertical" or "horizontal") .. " group")
+ end
+
+ -- Insert new contaner in before active
+ ------------------------------------------------------------
+ function tree:insert_group(is_vertical)
+ local pack = self.set[self.active]
+ local new_pack = map.construct_itempack({}, pack.wa, is_vertical, pack.parent)
+
+ if pack.parent then
+ for _, item in ipairs(pack.parent.items) do
+ if item.child == pack then item.child = new_pack; break end
+ end
+ end
+ new_pack.items[1] = { child = pack, factor = 1, client = nil }
+
+ table.insert(self.set, self.active, new_pack)
+ pack.parent = new_pack
+ notify("New " .. (is_vertical and "vertical" or "horizontal") .. " group")
+ end
+
+ -- Destroy the given container
+ ------------------------------------------------------------
+ function tree:delete_group(pack)
+ pack = pack or self.set[self.active]
+ local index = hasitem(self.set, pack)
+ local has_child = pack:get_places() < #pack.items
+
+ -- some containers can't be destroyed
+ -- root container
+ if #self.set == 1 then
+ notify("Cant't destroy last group")
+ return
+ end
+
+ -- container with many inheritors
+ if has_child and #pack.items > 1 then
+ notify("Cant't destroy group with inheritors")
+ return
+ end
+
+ -- disconnect container from parent
+ if pack.parent then
+ for i, item in ipairs(pack.parent.items) do
+ if item.child == pack then
+ if has_child then
+ -- container in container case
+ -- inheritor can be transmit to parent without changing geometry
+ item.child = pack.items[1].child
+ else
+ -- container without inheritors can be safaly destroyed
+ table.remove(pack.parent.items, i)
+ end
+ break
+ end
+ end
+ end
+
+ -- destroy container
+ table.remove(self.set, index)
+ if not self.set[self.active] then self.active = #self.set end
+ notify("Group " .. tostring(index) .. " destroyed")
+ end
+
+ -- Destroy all empty containers
+ ------------------------------------------------------------
+ function tree:cleanup()
+ for i = #self.set, 1, -1 do
+ if #self.set[i].items == 0 then
+ tree:delete_group(self.set[i])
+ elseif #self.set[i].items == 1 and self.set[i].items[1].child then
+ self.set[i].items[1].child.wa = self.set[i].wa
+ tree:delete_group(self.set[i])
+ end
+ end
+ end
+
+ -- Recalculate geometry for whole layout
+ ------------------------------------------------------------
+ function tree:rebuild(clist)
+ local current = { unpack(clist) }
+ local geometries = {}
+
+ -- distributing clients among existing contaners
+ for _, pack in ipairs(self.set) do
+ local n = pack:get_places()
+ local chunk = { unpack(current, 1, n) }
+ current = { unpack(current, n + 1) }
+ pack:set_cls(chunk)
+ end
+
+ -- distributing clients among existing contaners
+ if #current > 0 then
+ for _, c in ipairs(current) do
+ if self.autoaim then self.active = self:aim() end
+ local refill = awful.util.table.join(self.set[self.active]:get_cls(), { c })
+ self.set[self.active]:set_cls(refill)
+ end
+ -- local refill = awful.util.table.join(self.set[self.active]:get_cls(), current)
+ -- self.set[self.active]:set_cls(refill)
+ end
+
+ -- recalculate geomery for every container in tree
+ for _, pack in ipairs(self.set) do
+ geometries = awful.util.table.join(geometries, pack:rebuild())
+ end
+
+ return geometries
+ end
+
+ return tree
+end
+
+-- Layout manipulation functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Change container placement direction
+--------------------------------------------------------------------------------
+function map.swap_group()
+ local c = client.focus
+ if not c then return end
+
+ local t = c.screen.selected_tag
+ local pack = map.data[t]:get_pack(c)
+ pack.is_vertical = not pack.is_vertical
+ t:emit_signal("property::layout")
+end
+
+
+-- Create new container for client
+--------------------------------------------------------------------------------
+function map.new_group(is_vertical)
+ local c = client.focus
+ if not c then return end
+
+ local t = c.screen.selected_tag
+ map.data[t].autoaim = false
+ map.data[t]:create_group(c, is_vertical)
+
+ if hitimer then return end
+
+ hitimer = timer({ timeout = map.hilight_timeout })
+ hitimer:connect_signal("timeout",
+ function()
+ redflat.service.navigator.hilight.show(map.data[t].set[map.data[t].active].wa)
+ hitimer:stop()
+ hitimer = nil
+ end
+ )
+ hitimer:start() -- autostart option doesn't work?
+end
+
+-- Destroy active container
+--------------------------------------------------------------------------------
+function map.delete_group()
+ local t = mouse.screen.selected_tag
+ map.data[t].autoaim = false
+ map.data[t]:delete_group()
+ t:emit_signal("property::layout")
+end
+
+-- Check if client exist in layout tree
+--------------------------------------------------------------------------------
+function map.check_client(c)
+ if c.sticky then return true end
+ for _, t in ipairs(c:tags()) do
+ for k, _ in pairs(map.data) do if k == t then return true end end
+ end
+end
+
+-- Remove client from layout tree and change tree structure
+--------------------------------------------------------------------------------
+function map.clean_client(c)
+ for t, _ in pairs(map.data) do
+ local pack, index = map.data[t]:get_pack(c)
+ if pack then table.remove(pack.items, index) end
+ end
+end
+
+-- Destroy all empty containers
+--------------------------------------------------------------------------------
+function map.clean_groups()
+ local t = mouse.screen.selected_tag
+ map.data[t].autoaim = false
+ map.data[t]:cleanup()
+ t:emit_signal("property::layout")
+end
+
+-- Set active container (new client will be allocated to this one)
+--------------------------------------------------------------------------------
+function map.set_active(c)
+ c = c or client.focus
+ if not c then return end
+
+ local t = c.screen.selected_tag
+ local pack = map.data[t]:get_pack(c)
+ if pack then
+ map.data[t].autoaim = false
+ map.data[t].active = hasitem(map.data[t].set, pack)
+ redflat.service.navigator.hilight.show(pack.wa)
+ notify("Active group index: " .. tostring(map.data[t].active))
+ end
+end
+
+-- Hilight active container (navigetor widget feature)
+--------------------------------------------------------------------------------
+function map.hilight_active()
+ local t = mouse.screen.selected_tag
+ local pack = map.data[t].set[map.data[t].active]
+ redflat.service.navigator.hilight.show(pack.wa)
+end
+
+-- Switch active container by index
+--------------------------------------------------------------------------------
+function map.switch_active(n)
+ local t = mouse.screen.selected_tag
+ local na = map.data[t].active + n
+ if map.data[t].set[na] then
+ map.data[t].autoaim = false
+ map.data[t].active = na
+ --local pack = map.data[t].set[na]
+ notify("Active group index: " .. tostring(na))
+ end
+ redflat.service.navigator.hilight.show(map.data[t].set[map.data[t].active].wa)
+end
+
+-- Move client to active container
+--------------------------------------------------------------------------------
+function map.move_to_active(c)
+ c = c or client.focus
+ if not c then return end
+
+ local t = c.screen.selected_tag
+ local pack, index = map.data[t]:get_pack(c)
+ if pack then
+ table.remove(pack.items, index)
+ awful.client.setslave(c)
+ end
+end
+
+-- Increase window size factor for client
+--------------------------------------------------------------------------------
+function map.incfactor(c, df, is_vertical, on_group)
+ c = c or client.focus
+ if not c then return end
+
+ local t = c.screen.selected_tag
+ local pack, index = map.data[t]:get_pack(c)
+ if not pack then return end -- fix this?
+
+ if on_group and pack.parent then
+ index = pack.parent:get_child_id(pack)
+ pack = pack.parent
+ end
+
+ if pack then
+ pack:incfacror(index, df, is_vertical)
+ t:emit_signal("property::layout")
+ end
+end
+
+-- Move element inside his container
+--------------------------------------------------------------------------------
+function map.move_group(dn)
+ local t = mouse.screen.selected_tag
+ local pack = map.data[t].set[map.data[t].active]
+
+ if pack.parent then
+ map.data[t].autoaim = false
+ local i = pack.parent:get_child_id(pack)
+ if pack.parent.items[i + dn] then
+ pack.parent.items[i], pack.parent.items[i + dn] = pack.parent.items[i + dn], pack.parent.items[i]
+ t:emit_signal("property::layout")
+ end
+ end
+end
+
+-- Insert new group before active
+--------------------------------------------------------------------------------
+function map.insert_group(is_vertical)
+ local t = mouse.screen.selected_tag
+ map.data[t].autoaim = false
+ map.data[t]:insert_group(is_vertical)
+ t:emit_signal("property::layout")
+end
+
+-- Reset layout structure
+--------------------------------------------------------------------------------
+function map.reset_tree()
+ local t = mouse.screen.selected_tag
+ map.data[t] = nil
+ t:emit_signal("property::layout")
+end
+
+
+-- Base layout scheme
+-----------------------------------------------------------------------------------------------------------------------
+-- TODO: fix unused arg
+function map.base_set_new_pack(cls, wa, _, parent, factor)
+ local pack = map.construct_itempack(cls, wa, true, parent)
+ table.insert(parent.items, { child = pack, factor = factor or 1 })
+ return pack
+end
+
+map.base_autoaim = true
+
+function map.base_aim(tree)
+ if #tree.set[2].items == 0 then return 2 end
+ local active = #tree.set[3].items > #tree.set[2].items and 2 or 3
+ return active
+end
+
+function map.base_construct(wa)
+ local tree = { set = {}, active = 1, autoaim = map.base_autoaim, aim = map.base_aim }
+
+ tree.set[1] = map.construct_itempack({}, wa, false)
+ tree.set[2] = map.base_set_new_pack({}, wa, true, tree.set[1])
+ tree.set[3] = map.base_set_new_pack({}, wa, true, tree.set[1])
+
+ return tree
+end
+
+-- Tile function
+-----------------------------------------------------------------------------------------------------------------------
+function map.arrange(p)
+ local wa = awful.util.table.clone(p.workarea)
+ local cls = p.clients
+ local data = map.data
+ local t = p.tag or screen[p.screen].selected_tag
+
+ -- nothing to tile here
+ if #cls == 0 then return end
+
+ -- init layout tree
+ if not data[t] then data[t] = construct_tree(wa, t) end
+
+ -- tile
+ p.geometries = data[t]:rebuild(cls)
+end
+
+
+-- Keygrabber
+-----------------------------------------------------------------------------------------------------------------------
+map.maingrabber = function(mod, key)
+ for _, k in ipairs(map.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return true end
+ end
+end
+
+map.key_handler = function (mod, key, event)
+ if event == "press" then return end
+ if map.maingrabber(mod, key) then return end
+ if common.grabbers.swap(mod, key, event) then return end
+ if common.grabbers.base(mod, key, event) then return end
+end
+
+
+-- Redflat navigator support functions
+-----------------------------------------------------------------------------------------------------------------------
+function map:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.layout, map.keys.resize) end
+ end
+
+ self.tip = awful.util.table.join(self.keys.all, common.keys.swap, common.keys.base, common.keys._fake)
+end
+
+function map.startup()
+ if not map.tip then map:set_keys() end
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return map
diff --git a/awesome/.config/awesome/redflat/menu.lua b/awesome/.config/awesome/redflat/menu.lua
new file mode 100644
index 0000000..b8e497b
--- /dev/null
+++ b/awesome/.config/awesome/redflat/menu.lua
@@ -0,0 +1,676 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat menu --
+-----------------------------------------------------------------------------------------------------------------------
+-- awful.menu modification
+-- Custom widget support added
+-- Auto hide option added
+-- Right icon support added to default item constructor
+-- Icon margin added to default item constructor
+-- Auto hotkeys for menu items added
+
+-- Horizontal mode support removed
+-- Add to index and delete item functions removed
+-- menu:clients function removed
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.menu v3.5.2
+------ (c) 2008, 2011 Damien Leone, Julien Danjou, dodo
+-----------------------------------------------------------------------------------------------------------------------
+
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local wibox = require("wibox")
+local awful = require("awful")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local setmetatable = setmetatable
+local string = string
+local ipairs = ipairs
+local pcall = pcall
+local print = print
+local table = table
+local type = type
+local unpack = unpack or table.unpack
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local redtip = require("redflat.float.hotkeys")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local menu = { mt = {}, action = {}, keys = {} }
+
+local _fake_context = { dpi = beautiful.xresources.get_dpi() } -- fix this
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_theme()
+ local style = {
+ border_width = 2,
+ screen_gap = 0,
+ submenu_icon = redutil.base.placeholder({ txt = "▶" }),
+ height = 20,
+ width = 200,
+ font = "Sans 12",
+ icon_margin = { 0, 0, 0, 0 }, -- left icon margin
+ ricon_margin = { 0, 0, 0, 0 }, -- right icon margin
+ nohide = false,
+ auto_expand = true,
+ auto_hotkey = false,
+ svg_scale = { false, false },
+ hide_timeout = 0,
+ select_first = true,
+ keytip = { geometry = { width = 400 } },
+ color = { border = "#575757", text = "#aaaaaa", highlight = "#eeeeee",
+ main = "#b1222b", wibox = "#202020",
+ submenu_icon = nil, right_icon = nil, left_icon = nil },
+ shape = nil
+ }
+ return redutil.table.merge(style, beautiful.menu or {})
+end
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Check if any menu item connected with given key
+-- and run menu item command if found
+--------------------------------------------------------------------------------
+local function check_access_key(_menu, key)
+ local num = awful.util.table.hasitem(_menu.keys, key)
+ if num then
+ _menu:item_enter(num)
+ _menu:exec(num)
+ end
+end
+
+-- Get the elder parent of submenu
+--------------------------------------------------------------------------------
+function menu:get_root()
+ return self.parent and menu.get_root(self.parent) or self
+end
+
+-- Setup case insensitive underline markup to given character in string
+--------------------------------------------------------------------------------
+local function make_u(text, key)
+ local pos = key and string.find(string.lower(text), key) or nil
+
+ if pos then
+ local rkey = string.sub(text, pos, pos)
+ return string.gsub(text, rkey, "" .. rkey .. "", 1)
+ end
+
+ return text
+end
+
+-- Function to set menu or submenu in position
+-----------------------------------------------------------------------------------------------------------------------
+local function set_coords(_menu, screen_idx, m_coords)
+ local s_geometry = redutil.placement.add_gap(screen[screen_idx].workarea, _menu.theme.screen_gap)
+
+ local screen_w = s_geometry.x + s_geometry.width
+ local screen_h = s_geometry.y + s_geometry.height
+
+ local x, y
+ local b = _menu.wibox.border_width
+ local w = _menu.wibox.width + 2 * _menu.wibox.border_width
+ local h = _menu.wibox.height + 2 * _menu.wibox.border_width
+
+ if _menu.parent then
+ local pw = _menu.parent.wibox.width + 2 * _menu.parent.theme.border_width
+ local piy = _menu.parent.wibox.y + _menu.position + _menu.parent.theme.border_width
+
+ y = piy - b
+ x = _menu.parent.wibox.x + pw
+
+ if y + h > screen_h then y = screen_h - h end
+ if x + w > screen_w then x = _menu.parent.wibox.x - w end
+ else
+ if m_coords == nil then
+ m_coords = mouse.coords()
+ m_coords.x = m_coords.x - 1
+ m_coords.y = m_coords.y - 1
+ end
+
+ y = m_coords.y < s_geometry.y and s_geometry.y or m_coords.y
+ x = m_coords.x < s_geometry.x and s_geometry.x or m_coords.x
+
+ if y + h > screen_h then y = screen_h - h end
+ if x + w > screen_w then x = screen_w - w end
+ end
+
+ _menu.wibox.x = x
+ _menu.wibox.y = y
+end
+
+-- Menu keygrabber
+-- A new instance for every submenu should be used
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Menu functions
+--------------------------------------------------------------------------------
+function menu.action.up(_menu, sel)
+ local sel_new = sel - 1 < 1 and #_menu.items or sel - 1
+ _menu:item_enter(sel_new)
+end
+
+function menu.action.down(_menu, sel)
+ local sel_new = sel + 1 > #_menu.items and 1 or sel + 1
+ _menu:item_enter(sel_new)
+end
+
+function menu.action.enter(_menu, sel)
+ if sel > 0 and _menu.items[sel].child then _menu.items[sel].child:show() end
+end
+
+function menu.action.exec(_menu, sel)
+ if sel > 0 then _menu:exec(sel, { exec = true }) end
+end
+
+function menu.action.back(_menu)
+ _menu:hide()
+end
+
+function menu.action.close(_menu)
+ menu.get_root(_menu):hide()
+end
+
+-- Menu keys
+--------------------------------------------------------------------------------
+menu.keys.move = {
+ {
+ {}, "Down", menu.action.down,
+ { description = "Select next item", group = "Navigation" }
+ },
+ {
+ {}, "Up", menu.action.up,
+ { description = "Select previous item", group = "Navigation" }
+ },
+ {
+ {}, "Left", menu.action.back,
+ { description = "Go back", group = "Navigation" }
+ },
+ {
+ {}, "Right", menu.action.enter,
+ { description = "Open submenu", group = "Navigation" }
+ },
+}
+
+menu.keys.action = {
+ {
+ {}, "Escape", menu.action.close,
+ { description = "Close menu", group = "Action" }
+ },
+ {
+ {}, "Return", menu.action.exec,
+ { description = "Activate item", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+menu.keys.all = awful.util.table.join(menu.keys.move, menu.keys.action)
+
+-- this one only displayed in hotkeys helper
+menu._fake_keys = {
+ {
+ {}, "_letter", nil,
+ { description = "Activate item by key", group = "Action" }
+ },
+}
+
+-- Menu keygrabber
+--------------------------------------------------------------------------------
+local grabber = function(_menu, mod, key, event)
+ if event ~= "press" then return end
+ local sel = _menu.sel or 0
+
+ for _, k in ipairs(menu.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](_menu, sel); return false end
+ end
+
+ check_access_key(_menu, key)
+end
+
+-- Execute menu item
+-----------------------------------------------------------------------------------------------------------------------
+function menu:exec(num)
+ local item = self.items[num]
+
+ if not item then return end
+
+ local cmd = item.cmd
+
+ if type(cmd) == "table" then
+ item.child:show()
+ elseif type(cmd) == "string" then
+ if not item.theme.nohide then menu.get_root(self):hide() end
+ awful.spawn(cmd)
+ elseif type(cmd) == "function" then
+ if not item.theme.nohide then menu.get_root(self):hide() end
+ cmd()
+ end
+end
+
+-- Menu item selection functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Select item
+--------------------------------------------------------------------------------
+function menu:item_enter(num, opts)
+ opts = opts or {}
+ local item = self.items[num]
+
+ if item and self.theme.auto_expand and opts.hover and item.child then
+ self.items[num].child:show()
+ end
+
+ if num == nil or self.sel == num or not item then
+ return
+ elseif self.sel then
+ self:item_leave(self.sel)
+ end
+
+ item._background:set_fg(item.theme.color.highlight)
+ item._background:set_bg(item.theme.color.main)
+ if item.icon and item.theme.color.left_icon then item.icon:set_color(item.theme.color.highlight) end
+ if item.right_icon and
+ (item.child and item.theme.color.submenu_icon or not item.child and item.theme.color.right_icon) then
+ item.right_icon:set_color(item.theme.color.highlight)
+ end
+ self.sel = num
+end
+
+-- Unselect item
+--------------------------------------------------------------------------------
+function menu:item_leave(num)
+ if not num then return end
+
+ local item = self.items[num]
+
+ if item then
+ item._background:set_fg(item.theme.color.text)
+ item._background:set_bg(item.theme.color.wibox)
+ if item.icon and item.theme.color.left_icon then item.icon:set_color(item.theme.color.left_icon) end
+ if item.right_icon then
+ if item.child and item.theme.color.submenu_icon then
+ -- if there's a child menu, this is a submenu icon
+ item.right_icon:set_color(item.theme.color.submenu_icon)
+ elseif item.theme.color.right_icon then
+ item.right_icon:set_color(item.theme.color.right_icon)
+ end
+ end
+ if item.child then item.child:hide() end
+ end
+end
+
+-- Menu show/hide functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Show a menu popup.
+-- @param args.coords Menu position defaulting to mouse.coords()
+--------------------------------------------------------------------------------
+function menu:show(args)
+ args = args or {}
+ local screen_index = mouse.screen
+ set_coords(self, screen_index, args.coords)
+ if self.wibox.visible then return end
+
+ -- show menu
+ awful.keygrabber.run(self._keygrabber)
+ self.wibox.visible = true
+ if self.theme.select_first or self.parent then self:item_enter(1) end
+
+ -- check hidetimer
+ if self.hidetimer and self.hidetimer.started then self.hidetimer:stop() end
+
+ -- hotkeys helper
+ -- TODO: optimize code to cache helper (do not rebuild on every show)
+ local tip
+ if self.theme.auto_hotkey then
+ local fk = awful.util.table.clone(menu._fake_keys)
+ fk[1][4].keyset = self.keys
+ tip = awful.util.table.join(menu.keys.all, fk)
+ else
+ tip = menu.keys.all
+ end
+
+ redtip.cache["Menu"] = nil -- dirty trick to renew helper for every menu instance
+ redtip:set_pack("Menu", tip, self.theme.keytip.column, self.theme.keytip.geometry)
+end
+
+-- Hide a menu popup.
+--------------------------------------------------------------------------------
+function menu:hide()
+ if not self.wibox.visible then return end
+
+ self:item_leave(self.sel)
+
+ if self.sel and self.items[self.sel].child then self.items[self.sel].child:hide() end
+
+ self.sel = nil
+ awful.keygrabber.stop(self._keygrabber)
+
+ if self.hidetimer and self.hidetimer.started then self.hidetimer:stop() end
+
+ self.wibox.visible = false
+ redtip:remove_pack()
+end
+
+-- Toggle menu visibility
+--------------------------------------------------------------------------------
+function menu:toggle(args)
+ if self.wibox.visible then
+ self:hide()
+ else
+ self:show(args)
+ end
+end
+
+-- Set user hotkeys
+--------------------------------------------------------------------------------
+function menu:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.move, self.keys.action) end
+ end
+end
+
+-- Clears all items from the menu
+--------------------------------------------------------------------------------
+function menu:clear()
+ self.add_size = 0
+ self.layout:reset()
+ self.items = {}
+ self.keys = {}
+ self.wibox.height = 1
+end
+
+-- Clears and then refills the menu with the given items
+--------------------------------------------------------------------------------
+function menu:replace_items(items)
+ self:clear()
+ for _, item in ipairs(items) do
+ self:add(item)
+ end
+ self.wibox.height = self.add_size > 0 and self.add_size or 1
+end
+
+-- Add a new menu entry.
+-- args.new (Default: redflat.menu.entry) The menu entry constructor.
+-- args.theme (Optional) The menu entry theme.
+-- args.* params needed for the menu entry constructor.
+-- @param args The item params
+-----------------------------------------------------------------------------------------------------------------------
+function menu:add(args)
+ if not args then return end
+
+ -- If widget instead of text label recieved
+ -- just add it to layer, don't try to create menu item
+ ------------------------------------------------------------
+ if type(args[1]) ~= "string" and args.widget then
+ local element = {}
+ element.width, element.height = args.widget:fit(_fake_context, -1, -1)
+ self.add_size = self.add_size + element.height
+ self.layout:add(args.widget)
+
+ if args.focus then
+ args.widget:connect_signal(
+ "mouse::enter",
+ function()
+ self:item_leave(self.sel)
+ self.sel = nil
+ end
+ )
+ end
+
+ return
+ end
+
+ -- Set theme for currents item
+ ------------------------------------------------------------
+ local theme = redutil.table.merge(self.theme, args.theme or {})
+ args.theme = theme
+
+ -- Generate menu item
+ ------------------------------------------------------------
+ args.new = args.new or menu.entry
+ local success, item = pcall(args.new, self, args)
+
+ if not success then
+ print("Error while creating menu entry: " .. item)
+ return
+ end
+
+ if not item.widget then
+ print("Error while checking menu entry: no property widget found.")
+ return
+ end
+
+ item.parent = self
+ item.theme = item.theme or theme
+ item._background = wibox.container.background(item.widget)
+ item._background:set_fg(item.theme.color.text)
+ item._background:set_bg(item.theme.color.wibox)
+
+ -- Add item widget to menu layout
+ ------------------------------------------------------------
+ table.insert(self.items, item)
+ self.layout:add(item._background)
+
+ -- Create bindings
+ ------------------------------------------------------------
+ local num = #self.items
+
+ item._background:buttons(awful.util.table.join(
+ awful.button({}, 3, function () self:hide() end),
+ awful.button({}, 1, function ()
+ self:item_enter(num)
+ self:exec(num)
+ end)
+ ))
+
+ item.widget:connect_signal("mouse::enter", function() self:item_enter(num, { hover = true }) end)
+
+ -- Create submenu if needed
+ ------------------------------------------------------------
+ if type(args[2]) == "table" then
+ if not self.items[#self.items].child then
+ self.items[#self.items].child = menu.new(args[2], self)
+ self.items[#self.items].child.position = self.add_size
+ end
+ end
+
+ ------------------------------------------------------------
+ self.add_size = self.add_size + item.theme.height
+
+ return item
+end
+
+-- Default menu item constructor
+-- @param parent The parent menu
+-- @param args the item params
+-- @return table with all the properties the user wants to change
+-----------------------------------------------------------------------------------------------------------------------
+function menu.entry(parent, args)
+ args = args or {}
+ args.text = args[1] or args.text or ""
+ args.cmd = args[2] or args.cmd
+ args.icon = args[3] or args.icon
+ args.right_icon = args[4] or args.right_icon
+
+ -- Create the item label widget
+ ------------------------------------------------------------
+ local label = wibox.widget.textbox()
+ label:set_font(args.theme.font)
+
+ -- Set hotkey if needed
+ ------------------------------------------------------------
+ local key
+ local text = awful.util.escape(args.text)
+
+ if args.key and not awful.util.table.hasitem(parent.keys, args.key) then
+ key = args.key
+ elseif parent.theme.auto_hotkey then
+ for i = 1, #text do
+ local c = string.sub(string.lower(text), i, i)
+
+ if not awful.util.table.hasitem(parent.keys, c) and string.match(c, "%l") then
+ key = c
+ break
+ end
+ end
+ end
+
+ if key then parent.keys[#parent.keys + 1] = key end
+
+ label:set_markup(make_u(text, key))
+
+ -- Set left icon if needed
+ ------------------------------------------------------------
+ local iconbox
+ local margin = wibox.container.margin(label)
+
+ if args.icon then
+ iconbox = svgbox(args.icon, nil, args.theme.color.left_icon)
+ iconbox:set_vector_resize(args.theme.svg_scale[1])
+ else
+ margin:set_left(args.theme.icon_margin[1])
+ end
+
+ -- Set right icon if needed
+ ------------------------------------------------------------
+ local right_iconbox
+
+ if type(args.cmd) == "table" then
+ right_iconbox = svgbox(args.theme.submenu_icon, nil, args.theme.color.submenu_icon)
+ right_iconbox:set_vector_resize(args.theme.svg_scale[2])
+ elseif args.right_icon then
+ right_iconbox = svgbox(args.right_icon, nil, args.theme.color.right_icon)
+ right_iconbox:set_vector_resize(args.theme.svg_scale[2])
+ end
+
+ -- Construct item layouts
+ ------------------------------------------------------------
+ local left = wibox.layout.fixed.horizontal()
+
+ if iconbox ~= nil then
+ left:add(wibox.container.margin(iconbox, unpack(args.theme.icon_margin)))
+ end
+
+ left:add(margin)
+
+ local layout = wibox.layout.align.horizontal()
+ layout:set_left(left)
+
+ if right_iconbox ~= nil then
+ layout:set_right(wibox.container.margin(right_iconbox, unpack(args.theme.ricon_margin)))
+ end
+
+ local layout_const = wibox.container.constraint(layout, "exact", args.theme.width, args.theme.height)
+
+ ------------------------------------------------------------
+ return {
+ label = label,
+ icon = iconbox,
+ widget = layout_const,
+ cmd = args.cmd,
+ right_icon = right_iconbox
+ }
+end
+
+-- Create new menu
+-----------------------------------------------------------------------------------------------------------------------
+function menu.new(args, parent)
+
+ args = args or {}
+
+ -- Initialize menu object
+ ------------------------------------------------------------
+ local _menu = {
+ item_enter = menu.item_enter,
+ item_leave = menu.item_leave,
+ get_root = menu.get_root,
+ delete = menu.delete,
+ toggle = menu.toggle,
+ hide = menu.hide,
+ show = menu.show,
+ exec = menu.exec,
+ add = menu.add,
+ clear = menu.clear,
+ replace_items = menu.replace_items,
+ items = {},
+ keys = {},
+ parent = parent,
+ layout = wibox.layout.fixed.vertical(),
+ add_size = 0,
+ theme = redutil.table.merge(parent and parent.theme or default_theme(), args.theme or {})
+ }
+
+ -- Create items
+ ------------------------------------------------------------
+ for _, v in ipairs(args) do _menu:add(v) end
+
+ if args.items then
+ for _, v in ipairs(args.items) do _menu:add(v) end
+ end
+
+ _menu._keygrabber = function (...)
+ grabber(_menu, ...)
+ end
+
+ -- create wibox
+ ------------------------------------------------------------
+ _menu.wibox = wibox({
+ type = "popup_menu",
+ ontop = true,
+ fg = _menu.theme.color.text,
+ bg = _menu.theme.color.wibox,
+ border_color = _menu.theme.color.border,
+ border_width = _menu.theme.border_width,
+ shape = _menu.theme.shape
+ })
+
+ _menu.wibox.visible = false
+ _menu.wibox:set_widget(_menu.layout)
+
+ -- set size
+ _menu.wibox.width = _menu.theme.width
+ _menu.wibox.height = _menu.add_size > 0 and _menu.add_size or 1
+
+ -- Set menu autohide timer
+ ------------------------------------------------------------
+ if _menu.theme.hide_timeout > 0 then
+ local root = _menu:get_root()
+
+ -- timer only for root menu
+ -- all submenus will be hidden automatically
+ if root == _menu then
+ _menu.hidetimer = timer({ timeout = _menu.theme.hide_timeout })
+ _menu.hidetimer:connect_signal("timeout", function() _menu:hide() end)
+ end
+
+ -- enter/leave signals for all menu chain
+ _menu.wibox:connect_signal("mouse::enter",
+ function()
+ if root.hidetimer.started then root.hidetimer:stop() end
+ end)
+ _menu.wibox:connect_signal("mouse::leave", function() root.hidetimer:start() end)
+ end
+
+ ------------------------------------------------------------
+ return _menu
+end
+
+-- Config metatable to call menu module as function
+-----------------------------------------------------------------------------------------------------------------------
+function menu.mt:__call(...)
+ return menu.new(...)
+end
+
+return setmetatable(menu, menu.mt)
diff --git a/awesome/.config/awesome/redflat/service/dfparser.lua b/awesome/.config/awesome/redflat/service/dfparser.lua
new file mode 100644
index 0000000..3420fe0
--- /dev/null
+++ b/awesome/.config/awesome/redflat/service/dfparser.lua
@@ -0,0 +1,412 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat desctop file parser --
+-----------------------------------------------------------------------------------------------------------------------
+-- Create application menu analyzing .desktop files in given directories
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.menubar v3.5.2
+------ (c) 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local io = io
+local table = table
+local ipairs = ipairs
+local string = string
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local gears = require("gears")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local dfparser = {}
+local cache = {}
+
+dfparser.terminal = 'uxterm'
+
+local all_icon_folders = { "apps", "actions", "devices", "places", "categories", "status" }
+local all_icon_sizes = { '128x128' , '96x96', '72x72', '64x64', '48x48',
+ '36x36', '32x32', '24x24', '22x22', '16x16', 'scalable' }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icons = { custom_only = false, scalable_only = false, df_icon = nil, theme = nil },
+ desktop_file_dirs = { "/usr/share/applications/" },
+ wm_name = nil,
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "service.dfparser") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Cache functions
+--------------------------------------------------------------------------------
+local function check_cached(req)
+ for k, v in pairs(cache) do
+ local eq = #req == #k
+ for ck, cv in pairs(k) do eq = eq and cv == req[ck] end
+ if eq then return v end
+ end
+ return nil
+end
+
+-- Check whether the icon format is supported
+--------------------------------------------------------------------------------
+local function is_format(icon_file, icon_formats)
+ for _, f in ipairs(icon_formats) do
+ if icon_file:match('%.' .. f) then return true end
+ end
+ return false
+end
+
+-- Find all possible locations of the icon
+--------------------------------------------------------------------------------
+local function all_icon_path(style)
+
+ local icon_theme_paths = {}
+
+ -- add user icon theme
+ if style.theme then
+ table.insert(icon_theme_paths, style.theme .. '/')
+ -- TODO also look in parent icon themes, as in freedesktop.org specification
+ end
+
+ -- add fallback theme
+ if not style.custom_only then table.insert(icon_theme_paths, '/usr/share/icons/hicolor/') end
+
+ -- seach only svg icons if need
+ local current_icon_sizes = style.scalable_only and { 'scalable' } or all_icon_sizes
+
+ -- form all avalible icon dirs
+ local icon_path = {}
+
+ for _, icon_theme_directory in ipairs(icon_theme_paths) do
+ for _, size in ipairs(current_icon_sizes) do
+ for _, folder in ipairs(all_icon_folders) do
+ table.insert(icon_path, icon_theme_directory .. size .. "/" .. folder .. '/')
+ end
+ end
+ end
+
+ -- lowest priority fallbacks
+ if not style.custom_only then
+ table.insert(icon_path, '/usr/share/pixmaps/')
+ table.insert(icon_path, '/usr/share/icons/')
+ end
+
+ return icon_path
+end
+
+-- Lookup an icon in different folders of the filesystem
+-- @param icon_file Short or full name of the icon
+-- @param style.default_icon Return if no icon was found
+-- @param style.icon_theme Full path to custom icon theme
+-- @param style.custom_only Seach only custom theme icons, ignore system
+-- @param style.scalable_only Seach only svg type icons
+-- @return full name of the icon
+-----------------------------------------------------------------------------------------------------------------------
+function dfparser.lookup_icon(icon_file, style)
+
+ style = redutil.table.merge(default_style().icons, style or {})
+
+ local df_icon
+ if style.df_icon and gears.filesystem.file_readable(style.df_icon) then
+ df_icon = style.df_icon
+ end
+
+ -- No icon name
+ if not icon_file or icon_file == "" then return df_icon end
+
+ -- Handle full path icons
+ local icon_formats = style.scalable_only and { "svg" } or { "svg", "png", "gif" }
+
+ if icon_file:sub(1, 1) == '/' then
+ if is_format(icon_file, icon_formats) then
+ return gears.filesystem.file_readable(icon_file) and icon_file or df_icon
+ else
+ icon_file = string.match(icon_file, "([%a%d%-]+)%.")
+ if not icon_file then return df_icon end
+ end
+ end
+
+ -- Find all possible locations to search
+ local icon_path = all_icon_path(style)
+
+ -- Icon searching
+ for _, directory in ipairs(icon_path) do
+
+ -- check if icon format specified and supported
+ if is_format(icon_file, icon_formats) and awful.util.file_readable(directory .. icon_file) then
+ return directory .. icon_file
+ else
+
+ -- check if icon format specified but not supported
+ if string.match(icon_file, "%.")
+ and not string.match(icon_file, "org%.gnome%.") -- ignore gnome naming style
+ and not is_format(icon_file, icon_formats) then
+ icon_file = string.match(icon_file, "[%a%d%-]+")
+ end
+
+ -- icon is probably specified without path and format,
+ -- like 'firefox'. Try to add supported extensions to
+ -- it and see if such file exists.
+ for _, format in ipairs(icon_formats) do
+ local possible_file = directory .. icon_file .. "." .. format
+ if awful.util.file_readable(possible_file) then
+ return possible_file
+ end
+ end
+ end
+ end
+
+ return df_icon
+end
+
+-- Main parsing functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Parse a .desktop file
+-- @param file The .desktop file
+-- @param style Arguments for dfparser.lookup_icon
+-- @return A table with file entries
+--------------------------------------------------------------------------------
+local function parse(file, style)
+
+ local program = { show = true, file = file }
+ local desktop_entry = false
+
+ -- Parse the .desktop file.
+ -- We are interested in [Desktop Entry] group only.
+ for line in io.lines(file) do
+ if not desktop_entry and line == "[Desktop Entry]" then
+ desktop_entry = true
+ else
+ if line:sub(1, 1) == "[" and line:sub(-1) == "]" then
+ -- A declaration of new group - stop parsing
+ break
+ end
+
+ -- Grab the values
+ for key, value in line:gmatch("(%w+)%s*=%s*(.+)") do
+ program[key] = value
+ end
+ end
+ end
+
+ -- In case [Desktop Entry] was not found
+ if not desktop_entry then return nil end
+
+ -- Don't show program if NoDisplay attribute is false
+ if program.NoDisplay and string.lower(program.NoDisplay) == "true" then
+ program.show = false
+ end
+
+ -- Only show the program if there is no OnlyShowIn attribute
+ -- or if it's equal to given wm name
+ if program.OnlyShowIn ~= nil and style.wm_name and not program.OnlyShowIn:match(style.wm_name) then
+ program.show = false
+ end
+
+ -- Look up for a icon.
+ if program.Icon then
+ program.icon_path = dfparser.lookup_icon(program.Icon, style.icons)
+ end
+
+ -- Split categories into a table. Categories are written in one
+ -- line separated by semicolon.
+ if program.Categories then
+ program.categories = {}
+
+ for category in program.Categories:gmatch('[^;]+') do
+ table.insert(program.categories, category)
+ end
+ end
+
+ if program.Exec then
+ -- Substitute Exec special codes as specified in
+ -- http://standards.freedesktop.org/desktop-entry-spec/1.1/ar01s06.html
+ if program.Name == nil then
+ program.Name = '['.. file:match("([^/]+)%.desktop$") ..']'
+ end
+
+ local cmdline = program.Exec:gsub('%%c', program.Name)
+ cmdline = cmdline:gsub('%%[fuFU]', '')
+ cmdline = cmdline:gsub('%%k', program.file)
+
+ if program.icon_path then
+ cmdline = cmdline:gsub('%%i', '--icon ' .. program.icon_path)
+ else
+ cmdline = cmdline:gsub('%%i', '')
+ end
+
+ if program.Terminal == "true" then
+ cmdline = dfparser.terminal .. ' -e ' .. cmdline
+ end
+
+ program.cmdline = cmdline
+ end
+
+ return program
+end
+
+-- Parse a directory with .desktop files
+-- @param dir The directory
+-- @param style Arguments for dfparser.lookup_icon
+-- @return A table with all .desktop entries
+--------------------------------------------------------------------------------
+local function parse_dir(dir, style)
+ local req = awful.util.table.join({ path = dir }, style.icons)
+ local programs = {}
+ local cached = check_cached(req)
+
+ if not cached then
+ local files = redutil.read.output('find '.. dir ..' -maxdepth 1 -name "*.desktop" 2>/dev/null')
+
+ for file in string.gmatch(files, "[^\n]+") do
+ local program = parse(file, style)
+ if program then table.insert(programs, program) end
+ end
+
+ cache[req] = programs
+ else
+ programs = cached
+ end
+
+ return programs
+end
+
+-- Create a new application menu
+-- @param style.icons Arguments for dfparser.lookup_icon
+-- @param style.desktop_file_dirs Table containing all .desktop file directories
+-- @return Applications menu table
+-----------------------------------------------------------------------------------------------------------------------
+function dfparser.menu(style)
+
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Categories list
+ --------------------------------------------------------------------------------
+ local categories = {
+ { app_type = "AudioVideo", name = "Multimedia", icon_name = "applications-multimedia" },
+ { app_type = "Development", name = "Development", icon_name = "applications-development" },
+ { app_type = "Education", name = "Education", icon_name = "applications-science" },
+ { app_type = "Game", name = "Games", icon_name = "applications-games" },
+ { app_type = "Graphics", name = "Graphics", icon_name = "applications-graphics" },
+ { app_type = "Office", name = "Office", icon_name = "applications-office" },
+ { app_type = "Network", name = "Internet", icon_name = "applications-internet" },
+ { app_type = "Settings", name = "Settings", icon_name = "applications-utilities" },
+ { app_type = "System", name = "System Tools", icon_name = "applications-system" },
+ { app_type = "Utility", name = "Accessories", icon_name = "applications-accessories" }
+ }
+
+ -- Find icons for categories
+ --------------------------------------------------------------------------------
+ for _, v in ipairs(categories) do
+ v.icon = dfparser.lookup_icon(v.icon_name, style)
+ end
+
+ -- Find all visible menu items
+ --------------------------------------------------------------------------------
+ local prog_list = {}
+ for _, path in ipairs(style.desktop_file_dirs) do
+ local programs = parse_dir(path, style)
+
+ for _, prog in ipairs(programs) do
+ if prog.show and prog.Name and prog.cmdline then
+ table.insert(prog_list, prog)
+ end
+ end
+ end
+
+ -- Sort menu items by category and create submenu
+ --------------------------------------------------------------------------------
+ local appmenu = {}
+ for _, menu_category in ipairs(categories) do
+ local catmenu = {}
+
+ for i = #prog_list, 1, -1 do
+ if prog_list[i].categories then
+ for _, item_category in ipairs(prog_list[i].categories) do
+ if item_category == menu_category.app_type then
+ table.insert(catmenu, { prog_list[i].Name, prog_list[i].cmdline, prog_list[i].icon_path })
+ table.remove(prog_list, i)
+ end
+ end
+ end
+ end
+ if #catmenu > 0 then table.insert(appmenu, { menu_category.name, catmenu, menu_category.icon }) end
+ end
+
+ -- Collect all items without category to "Other" submenu
+ --------------------------------------------------------------------------------
+ if #prog_list > 0 then
+ local catmenu = {}
+
+ for _, prog in ipairs(prog_list) do
+ table.insert(catmenu, { prog.Name, prog.cmdline, prog.icon_path })
+ end
+
+ table.insert(appmenu, { "Other", catmenu, dfparser.lookup_icon("applications-other") })
+ end
+
+ return appmenu
+end
+
+-- Get list of icons linked with process name
+-- @param style.icons Arguments for dfparser.lookup_icon
+-- @param style.desktop_file_dirs Table containing all .desktop file directories
+-- @return Icon list
+-----------------------------------------------------------------------------------------------------------------------
+function dfparser.icon_list(style)
+
+ style = redutil.table.merge(default_style(), style or {})
+ local list = {}
+
+ for _, path in ipairs(style.desktop_file_dirs) do
+ local programs = parse_dir(path, style)
+
+ for _, prog in ipairs(programs) do
+ if prog.Icon and prog.Exec then
+ local key = string.match(prog.Exec, "[%a%d%.%-/]+")
+ if string.find(key, "/") then key = string.match(key, "[%a%d%.%-]+$") end
+ list[key] = prog.icon_path
+ end
+ end
+ end
+
+ return list
+end
+
+-- Generate table with avaliable programs
+-- without sorting by categories
+-- @param style.icons Arguments for dfparser.lookup_icon
+-- @param style.desktop_file_dirs Table containing all .desktop file directories
+-----------------------------------------------------------------------------------------------------------------------
+function dfparser.program_list(style)
+
+ style = redutil.table.merge(default_style(), style or {})
+ local prog_list = {}
+
+ for _, path in ipairs(style.desktop_file_dirs) do
+ local programs = parse_dir(path, style)
+
+ for _, prog in ipairs(programs) do
+ if prog.show and prog.Name and prog.cmdline then
+ table.insert(prog_list, prog)
+ end
+ end
+ end
+
+ return prog_list
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return dfparser
diff --git a/awesome/.config/awesome/redflat/service/init.lua b/awesome/.config/awesome/redflat/service/init.lua
new file mode 100644
index 0000000..638e98b
--- /dev/null
+++ b/awesome/.config/awesome/redflat/service/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.service" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/service/navigator.lua b/awesome/.config/awesome/redflat/service/navigator.lua
new file mode 100644
index 0000000..4284900
--- /dev/null
+++ b/awesome/.config/awesome/redflat/service/navigator.lua
@@ -0,0 +1,355 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat focus switch util --
+-----------------------------------------------------------------------------------------------------------------------
+-- Visual clinet managment helper
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local math = math
+
+local awful = require("awful")
+local wibox = require("wibox")
+local color = require("gears.color")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redflat = require("redflat")
+local redutil = require("redflat.util")
+local redtip = require("redflat.float.hotkeys")
+local rednotify = require("redflat.float.notify")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local navigator = { action = {}, data = {}, active = false }
+
+navigator.ignored = { "dock", "splash", "desktop" }
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ border_width = 2,
+ marksize = { width = 200, height = 100, r = 20 },
+ gradstep = 100,
+ linegap = 35,
+ timeout = 1,
+ notify = {},
+ keytip = { base = { geometry = { width = 600 }, exit = true } },
+ titlefont = { font = "Sans", size = 28, face = 1, slant = 0 },
+ num = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "F1", "F3", "F4", "F5" },
+ font = { font = "Sans", size = 22, face = 1, slant = 0 },
+ color = { border = "#575757", wibox = "#00000000", bg1 = "#57575740", bg2 = "#57575720",
+ fbg1 = "#b1222b40", fbg2 = "#b1222b20", mark = "#575757", text = "#202020",
+ hbg1 = "#32882d40", hbg2 = "#32882d20" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "service.navigator") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Check geometry intersection
+--------------------------------------------------------------------------------
+local function is_intersect(a, b)
+ return (b.x < a.x + a.width and b.x + b.width > a.x and b.y < a.y + a.height and b.y + b.height > a.y)
+end
+
+-- Window painting
+--------------------------------------------------------------------------------
+function navigator.make_paint(c)
+
+ -- Initialize vars
+ ------------------------------------------------------------
+ local style = navigator.style
+ local widg = wibox.widget.base.make_widget()
+
+ widg._data = {
+ client = c,
+ alert = false,
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:set_client(client_)
+ if widg._data.client ~= client_ then
+ widg._data.client = client_
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ function widg:set_alert(value)
+ if widg._data.alert ~= value then
+ widg._data.alert = value
+ self:emit_signal("widget::redraw_needed")
+ end
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ return width, height
+ end
+
+ -- Draw
+ ------------------------------------------------------------
+ function widg:draw(_, cr, width, height)
+
+ if not widg._data.client then return end
+
+ -- background
+ local bg1, bg2
+ local num = math.ceil((width + height) / style.gradstep)
+
+ if widg._data.alert then
+ bg1, bg2 = style.color.hbg1, style.color.hbg2
+ else
+ local is_focused = widg._data.client == client.focus
+ bg1 = is_focused and style.color.fbg1 or style.color.bg1
+ bg2 = is_focused and style.color.fbg2 or style.color.bg2
+ end
+
+ for i = 1, num do
+ local cc = i % 2 == 1 and bg1 or bg2
+ local l = i * style.gradstep
+
+ cr:set_source(color(cc))
+ cr:move_to(0, (i - 1) * style.gradstep)
+ cr:rel_line_to(0, style.gradstep)
+ cr:rel_line_to(l, - l)
+ cr:rel_line_to(- style.gradstep, 0)
+ cr:close_path()
+ cr:fill()
+ end
+
+ -- rounded rectangle on center
+ local r = style.marksize.r
+ local w, h = style.marksize.width - 2 * r, style.marksize.height - 2 * r
+
+ cr:set_source(color(style.color.mark))
+ cr:move_to((width - w) / 2 - r, (height - h) / 2)
+ cr:rel_curve_to(0, -r, 0, -r, r, -r)
+ cr:rel_line_to(w, 0)
+ cr:rel_curve_to(r, 0, r, 0, r, r)
+ cr:rel_line_to(0, h)
+ cr:rel_curve_to(0, r, 0, r, -r, r)
+ cr:rel_line_to(-w, 0)
+ cr:rel_curve_to(-r, 0, -r, 0, -r, -r)
+ cr:close_path()
+ cr:fill()
+
+ -- label
+ local index = navigator.style.num[awful.util.table.hasitem(navigator.cls, widg._data.client)]
+ local g = redutil.client.fullgeometry(widg._data.client)
+
+ cr:set_source(color(style.color.text))
+ redutil.cairo.set_font(cr, style.titlefont)
+ redutil.cairo.textcentre.full(cr, { width/2, height/2 - style.linegap / 2 }, index)
+ redutil.cairo.set_font(cr, style.font)
+ redutil.cairo.textcentre.full(cr, { width/2, height/2 + style.linegap / 2 }, g.width .. " x " .. g.height)
+ end
+
+ ------------------------------------------------------------
+ return widg
+end
+
+-- Construct wibox
+--------------------------------------------------------------------------------
+function navigator.make_decor(c)
+ local object = {}
+ local style = navigator.style
+
+ -- Create wibox
+ ------------------------------------------------------------
+ object.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ object.client = c
+ object.widget = navigator.make_paint(c)
+ object.wibox:set_widget(object.widget)
+
+ -- User functions
+ ------------------------------------------------------------
+ object.update = {
+ focus = function() object.widget:emit_signal("widget::redraw_needed") end,
+ close = function() navigator:restart() end,
+ geometry = function() redutil.client.fullgeometry(object.wibox, redutil.client.fullgeometry(object.client)) end
+ }
+
+ function object:set_client(client_)
+ object.client = client_
+ object.widget:set_client(client_)
+ redutil.client.fullgeometry(object.wibox, redutil.client.fullgeometry(object.client))
+
+ object.client:connect_signal("focus", object.update.focus)
+ object.client:connect_signal("unfocus", object.update.focus)
+ object.client:connect_signal("property::geometry", object.update.geometry)
+ object.client:connect_signal("unmanage", object.update.close)
+ end
+
+ function object:clear(no_hide)
+ object.client:disconnect_signal("focus", object.update.focus)
+ object.client:disconnect_signal("unfocus", object.update.focus)
+ object.client:disconnect_signal("property::geometry", object.update.geometry)
+ object.client:disconnect_signal("unmanage", object.update.close)
+ object.widget:set_client()
+ if not no_hide then object.wibox.visible = false end
+ end
+
+ ------------------------------------------------------------
+ object:set_client(c)
+ return object
+end
+
+
+-- Main functions
+-----------------------------------------------------------------------------------------------------------------------
+function navigator:init()
+
+ -- Style
+ ------------------------------------------------------------
+ self.style = default_style()
+
+ -- Hilight area
+ ------------------------------------------------------------
+ self.hilight = {}
+
+ -- timer
+ self.hilight.hidetimer = timer({ timeout = self.style.timeout })
+ self.hilight.hidetimer:connect_signal("timeout", function() self.hilight.hide() end)
+
+ -- show/hide
+ function self.hilight.show(g)
+ for i, c in ipairs(self.cls) do
+ self.data[i].widget:set_alert(is_intersect(g, c:geometry()))
+ end
+ self.hilight.hidetimer:again()
+ end
+
+ function self.hilight.hide()
+ for i, _ in ipairs(self.cls) do self.data[i].widget:set_alert(false) end
+ end
+
+ -- close the navigator on tag switch
+ tag.connect_signal('property::selected',
+ function()
+ if navigator.active then self:close() end
+ end
+ )
+
+ -- update navigator if new client spawns
+ client.connect_signal('manage',
+ function()
+ if navigator.active then self:restart() end
+ end
+ )
+
+ -- update navigator if a client gets minimized or restored
+ client.connect_signal('property::minimized',
+ function()
+ if navigator.active then self:restart() end
+ end
+ )
+end
+
+function navigator:run()
+ if not self.style then self:init() end
+
+ -- check clients
+ local s = mouse.screen
+ self.cls = awful.client.tiled(s)
+
+ if #self.cls == 0 or
+ not client.focus or
+ client.focus.fullscreen or
+ awful.util.table.hasitem(navigator.ignored, client.focus.type)
+ then
+ return
+ end
+
+ -- check handler
+ local l = awful.layout.get(client.focus.screen)
+ local handler = l.key_handler or redflat.layout.common.handler[l]
+ if not handler then
+ rednotify:show(redutil.table.merge({ text = "Layout not supported" }, self.style.notify))
+ return
+ end
+
+ -- layout setup if needed
+ if l.startup then l.startup() end
+ local tip = l.tip or redflat.layout.common.tips[l]
+
+ -- activate navition widgets
+ for i, c in ipairs(self.cls) do
+ if not self.data[i] then
+ self.data[i] = self.make_decor(c)
+ else
+ self.data[i]:set_client(c)
+ end
+
+ self.data[i].wibox.visible = true
+ end
+
+ -- run key handler
+ self.grabber_settled = handler
+ awful.keygrabber.run(self.grabber_settled)
+
+ -- set keys tip
+ self.tip_settled = tip
+ if tip then
+ local tip_style = self.style.keytip[awful.layout.getname(l)] or self.style.keytip.base
+ redtip:set_pack(
+ "Layout " .. l.name, tip, tip_style.column, tip_style.geometry,
+ self.style.keytip.base.exit and function() redflat.layout.common.action.exit() end -- fix this?
+ )
+ end
+
+ navigator.active = true
+end
+
+function navigator:close()
+ for i, _ in ipairs(self.cls) do
+ self.data[i]:clear()
+ end
+
+ awful.keygrabber.stop(self.grabber_settled)
+ if self.tip_settled then redtip:remove_pack() end
+
+ local l = client.focus and awful.layout.get(client.focus.screen)
+ if l and l.cleanup then l.cleanup() end
+ self.cls = {}
+
+ navigator.active = false
+end
+
+function navigator:restart()
+ -- update decoration
+ for i, _ in ipairs(self.cls) do self.data[i]:clear(true) end
+ local newcls = awful.client.tiled(mouse.screen)
+ for i = 1, math.max(#self.cls, #newcls) do
+ if newcls[i] then
+ if not self.data[i] then
+ self.data[i] = self.make_decor(newcls[i])
+ else
+ self.data[i]:set_client(newcls[i])
+ end
+
+ self.data[i].wibox.visible = true
+ else
+ self.data[i].wibox.visible = false
+ end
+ end
+
+ self.cls = newcls
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return navigator
diff --git a/awesome/.config/awesome/redflat/startup.lua b/awesome/.config/awesome/redflat/startup.lua
new file mode 100644
index 0000000..490c4c7
--- /dev/null
+++ b/awesome/.config/awesome/redflat/startup.lua
@@ -0,0 +1,44 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat startup check --
+-----------------------------------------------------------------------------------------------------------------------
+-- Save exit reason to file
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local io = io
+
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local startup = { locked = false }
+
+startup.path = "/tmp/awesome-exit-reason"
+--startup.bin = "awesome-client"
+
+local REASON = { RESTART = "restart", EXIT = "exit" }
+
+-- Stamp functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- save restart reason
+function startup.stamp(reason_restart)
+ local file = io.open(startup.path, "w")
+ file:write(reason_restart)
+ file:close()
+end
+
+function startup:activate()
+ -- check if it is first start
+ local reason = redutil.read.file(startup.path)
+ self.is_startup = (not reason or reason == REASON.EXIT) and not self.locked
+
+ -- save reason on exit
+ awesome.connect_signal("exit",
+ function(is_restart) startup.stamp(is_restart and REASON.RESTART or REASON.EXIT) end
+ )
+end
+
+-----------------------------------------------------------------------------------------------------------------------
+return startup
diff --git a/awesome/.config/awesome/redflat/system.lua b/awesome/.config/awesome/redflat/system.lua
new file mode 100644
index 0000000..1e324b4
--- /dev/null
+++ b/awesome/.config/awesome/redflat/system.lua
@@ -0,0 +1,754 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat system --
+-----------------------------------------------------------------------------------------------------------------------
+-- System monitoring functions collected here
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ vicious module
+------ (c) 2010, 2011 Adrian C.
+------ (c) 2009, Lucas de Vries
+------ (c) 2011, Jörg T.
+------ (c) 2011, Adrian C.
+-----------------------------------------------------------------------------------------------------------------------
+
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local tonumber = tonumber
+local io = io
+local os = os
+local string = string
+local math = math
+
+local timer = require("gears.timer")
+local awful = require("awful")
+local redutil = require("redflat.util")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local system = { thermal = {}, dformatted = {}, pformatted = {} }
+
+-- Async settlers generator
+-----------------------------------------------------------------------------------------------------------------------
+function system.simple_async(command, pattern)
+ return function(setup)
+ awful.spawn.easy_async_with_shell(command,
+ function(output)
+ local value = tonumber(string.match(output, pattern))
+ setup(value and { value } or { 0 })
+ end
+ )
+ end
+end
+
+-- Disk usage
+-----------------------------------------------------------------------------------------------------------------------
+function system.fs_info(args)
+ local fs_info = {}
+ args = args or "/"
+
+ -- Get data from df
+ ------------------------------------------------------------
+ local line = redutil.read.output("LC_ALL=C df -kP " .. args .. " | tail -1")
+
+ -- Parse data
+ ------------------------------------------------------------
+ fs_info.size = string.match(line, "^.-[%s]([%d]+)")
+ fs_info.mount = string.match(line, "%%[%s]([%p%w]+)")
+ fs_info.used, fs_info.avail, fs_info.use_p = string.match(line, "([%d]+)[%D]+([%d]+)[%D]+([%d]+)%%")
+
+ -- Format output special for redflat desktop widget
+ ------------------------------------------------------------
+ return { tonumber(fs_info.use_p) or 0, tonumber(fs_info.used) or 0}
+end
+
+-- Qemu image check
+-----------------------------------------------------------------------------------------------------------------------
+local function q_format(size, k)
+ if not size or not k then return 0 end
+ return k == "K" and tonumber(size) or k == "M" and size * 1024 or k == "G" and size * 1024^2 or 0
+end
+
+function system.qemu_image_size(args)
+ local img_info = {}
+
+ -- Get data from qemu-ima
+ ------------------------------------------------------------
+ local line = redutil.read.output("LC_ALL=C qemu-img info " .. args)
+
+ -- Parse data
+ ------------------------------------------------------------
+ local size, k = string.match(line, "disk%ssize:%s([%.%d]+)%s(%w)")
+ img_info.size = q_format(size, k)
+ local vsize, vk = string.match(line, "virtual%ssize:%s([%.%d]+)%s(%w)")
+ img_info.virtual_size = q_format(vsize, vk)
+ img_info.use_p = img_info.virtual_size > 0 and math.floor(img_info.size / img_info.virtual_size * 100) or 0
+
+ -- Format output special for redflat desktop widget
+ ------------------------------------------------------------
+ return { img_info.use_p, img_info.size, off = img_info.size == 0 }
+end
+
+-- Traffic check with vnstat (async)
+-----------------------------------------------------------------------------------------------------------------------
+local function vnstat_format(value, unit)
+ if not value or not unit then return 0 end
+ local v = value:gsub(',', '.')
+ return unit == "B" and tonumber(v)
+ or unit == "KiB" and v * 1024
+ or unit == "MiB" and v * 1024^2
+ or unit == "GiB" and v * 1024^3
+end
+
+function system.vnstat_check(args)
+ local command = string.format("vnstat %s | tail -n 3 | head -n 1", args)
+ return function(setup)
+ awful.spawn.easy_async_with_shell(command,
+ function(output)
+ local x, u = string.match(
+ output, "%s+%d+,%d+%s%w+%s+%|%s+%d+,%d+%s%w+%s+%|%s+(%d+,%d+)%s(%w+)%s+%|%s+.+"
+ )
+ local total = vnstat_format(x, u)
+ setup({ total })
+ end
+ )
+ end
+end
+
+-- Get network speed
+-----------------------------------------------------------------------------------------------------------------------
+function system.net_speed(interface, storage)
+ local up, down = 0, 0
+ local state = 0
+ -- Get network info
+ --------------------------------------------------------------------------------
+ for line in io.lines("/proc/net/dev") do
+
+ -- Match wmaster0 as well as rt0 (multiple leading spaces)
+ local name = string.match(line, "^[%s]?[%s]?[%s]?[%s]?([%w]+):")
+
+ -- Calculate speed for given interface
+ ------------------------------------------------------------
+ if name == interface then
+ state = 1
+ -- received bytes, first value after the name
+ local recv = tonumber(string.match(line, ":[%s]*([%d]+)"))
+ -- transmited bytes, 7 fields from end of the line
+ local send = tonumber(string.match(line, "([%d]+)%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d+%s+%d$"))
+
+ local now = os.time()
+
+ if not storage[interface] then
+ -- default values on the first run
+ storage[interface] = { recv = 0, send = 0 }
+ else
+ -- net stats are absolute, substract our last reading
+ local interval = now - storage[interface].time
+ if interval <= 0 then interval = 1 end
+
+ down = (recv - storage[interface].recv) / interval
+ up = (send - storage[interface].send) / interval
+ end
+
+ -- store totals
+ storage[interface].time = now
+ storage[interface].recv = recv
+ storage[interface].send = send
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return { up, down,state }
+end
+
+-- Get disk speed
+-----------------------------------------------------------------------------------------------------------------------
+function system.disk_speed(disk, storage)
+ local up, down = 0, 0
+
+ -- Get i/o info
+ --------------------------------------------------------------------------------
+ for line in io.lines("/proc/diskstats") do
+
+ -- parse info
+ -- linux kernel documentation: Documentation/iostats.txt
+ local device, read, write = string.match(line, "([^%s]+) %d+ %d+ (%d+) %d+ %d+ %d+ (%d+)")
+
+ -- Calculate i/o for given device
+ ------------------------------------------------------------
+ if device == disk then
+ local now = os.time()
+ local stats = { read, write }
+
+ if not storage[disk] then
+ -- default values on the first run
+ storage[disk] = { stats = stats }
+ else
+ -- check for overflows and counter resets (> 2^32)
+ if stats[1] < storage[disk].stats[1] or stats[2] < storage[disk].stats[2] then
+ storage[disk].stats[1], storage[disk].stats[2] = stats[1], stats[2]
+ end
+
+ -- diskstats are absolute, substract our last reading
+ -- * divide by timediff because we don't know the timer value
+ local interval = now - storage[disk].time
+ if interval <= 0 then interval = 1 end
+
+ up = (stats[1] - storage[disk].stats[1]) / interval
+ down = (stats[2] - storage[disk].stats[2]) / interval
+ end
+
+ -- store totals
+ storage[disk].time = now
+ storage[disk].stats = stats
+ end
+ end
+
+ --------------------------------------------------------------------------------
+ return { up, down }
+end
+
+-- Get MEM info
+-----------------------------------------------------------------------------------------------------------------------
+function system.memory_info()
+ local mem = { buf = {}, swp = {} }
+
+ -- Get MEM info
+ ------------------------------------------------------------
+ for line in io.lines("/proc/meminfo") do
+ for k, v in string.gmatch(line, "([%a]+):[%s]+([%d]+).+") do
+ if k == "MemTotal" then mem.total = math.floor(v/1024)
+ elseif k == "MemFree" then mem.buf.f = math.floor(v/1024)
+ elseif k == "Buffers" then mem.buf.b = math.floor(v/1024)
+ elseif k == "Cached" then mem.buf.c = math.floor(v/1024)
+ elseif k == "SwapTotal" then mem.swp.t = math.floor(v/1024)
+ elseif k == "SwapFree" then mem.swp.f = math.floor(v/1024)
+ end
+ end
+ end
+
+ -- Calculate memory percentage
+ ------------------------------------------------------------
+ mem.free = mem.buf.f + mem.buf.b + mem.buf.c
+ mem.inuse = mem.total - mem.free
+ mem.bcuse = mem.total - mem.buf.f
+ mem.usep = math.floor(mem.inuse / mem.total * 100)
+
+ -- calculate swap percentage
+ mem.swp.inuse = mem.swp.t - mem.swp.f
+ mem.swp.usep = mem.swp.t > 0 and math.floor(mem.swp.inuse / mem.swp.t * 100) or 0
+
+ ------------------------------------------------------------
+ return mem
+end
+
+-- Get cpu usage info
+-----------------------------------------------------------------------------------------------------------------------
+--local storage = { cpu_total = {}, cpu_active = {} } -- storage structure
+
+function system.cpu_usage(storage)
+ local cpu_lines = {}
+ local cpu_usage = {}
+ local diff_time_total
+
+ -- Get CPU stats
+ ------------------------------------------------------------
+ for line in io.lines("/proc/stat") do
+ if string.sub(line, 1, 3) == "cpu" then
+ local digits_in_line = {}
+
+ for i in string.gmatch(line, "[%s]+([^%s]+)") do
+ table.insert(digits_in_line, i)
+ end
+
+ table.insert(cpu_lines, digits_in_line)
+ end
+ end
+
+ -- Calculate usage
+ ------------------------------------------------------------
+ for i, line in ipairs(cpu_lines) do
+
+ -- calculate totals
+ local total_new = 0
+ for _, value in ipairs(line) do total_new = total_new + value end
+
+ local active_new = total_new - (line[4] + line[5])
+
+ -- calculate percentage
+ local diff_total = total_new - (storage.cpu_total[i] or 0)
+ local diff_active = active_new - (storage.cpu_active[i] or 0)
+
+ if i == 1 then diff_time_total = diff_total end
+ if diff_total == 0 then diff_total = 1E-6 end
+
+ cpu_usage[i] = math.floor((diff_active / diff_total) * 100)
+
+ -- store totals
+ storage.cpu_total[i] = total_new
+ storage.cpu_active[i] = active_new
+ end
+
+ -- Format output special for redflat widgets and other system functions
+ ------------------------------------------------------------
+ local total_usage = cpu_usage[1]
+ local core_usage = awful.util.table.clone(cpu_usage)
+ table.remove(core_usage, 1)
+
+ return { total = total_usage, core = core_usage, diff = diff_time_total }
+end
+
+-- Get battery level and charging status
+-----------------------------------------------------------------------------------------------------------------------
+function system.battery(batname)
+ if not batname then return end
+
+ -- Initialzie vars
+ --------------------------------------------------------------------------------
+ local battery = {}
+ local time = "N/A"
+
+ local battery_state = {
+ ["Full\n"] = "↯",
+ ["Unknown\n"] = "⌁",
+ ["Charged\n"] = "↯",
+ ["Charging\n"] = "+",
+ ["Discharging\n"] = "-"
+ }
+
+ local files = {
+ "present", "status", "charge_now",
+ "charge_full", "energy_now", "energy_full",
+ "current_now", "power_now"
+ }
+
+ -- Read info
+ --------------------------------------------------------------------------------
+ for _, v in pairs(files) do
+ battery[v] = redutil.read.file("/sys/class/power_supply/" .. batname .. "/" .. v)
+ end
+
+ -- Check if the battery is present
+ ------------------------------------------------------------
+ if battery.present ~= "1\n" then
+ return { battery_state["Unknown\n"], 0, "N/A" }
+ end
+
+ -- Get state information
+ ------------------------------------------------------------
+ local state = battery_state[battery.status] or battery_state["Unknown\n"]
+ local remaining, capacity
+
+ -- Get capacity information
+ if battery.charge_now then remaining, capacity = battery.charge_now, battery.charge_full
+ elseif battery.energy_now then remaining, capacity = battery.energy_now, battery.energy_full
+ else return {battery_state["Unknown\n"], 0, "N/A"}
+ end
+
+ -- Calculate percentage (but work around broken BAT/ACPI implementations)
+ ------------------------------------------------------------
+ local percent = math.min(math.floor(remaining / capacity * 100), 100)
+
+ -- Get charge information
+ ------------------------------------------------------------
+ local rate
+
+ if battery.current_now then rate = tonumber(battery.current_now)
+ elseif battery.power_now then rate = tonumber(battery.power_now)
+ else return {state, percent, "N/A"}
+ end
+
+ -- Calculate remaining (charging or discharging) time
+ ------------------------------------------------------------
+ if rate ~= nil and rate ~= 0 then
+ local timeleft
+
+ if state == "+" then timeleft = (tonumber(capacity) - tonumber(remaining)) / tonumber(rate)
+ elseif state == "-" then timeleft = tonumber(remaining) / tonumber(rate)
+ else return {state, percent, time}
+ end
+
+ -- calculate time
+ local hoursleft = math.floor(timeleft)
+ local minutesleft = math.floor((timeleft - hoursleft) * 60 )
+
+ time = string.format("%02d:%02d", hoursleft, minutesleft)
+ end
+
+ --------------------------------------------------------------------------------
+ return { state, percent, time }
+end
+
+-- Temperature measure
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Using lm-sensors
+------------------------------------------------------------
+system.lmsensors = { storage = {}, patterns = {}, delay = 1, time = 0 }
+
+function system.lmsensors:update(output)
+ for name, pat in pairs(self.patterns) do
+ local value = string.match(output, pat.match)
+ if value and pat.posthook then value = pat.posthook(value) end
+ value = tonumber(value)
+ self.storage[name] = value and { value } or { 0 }
+ end
+ self.time = os.time()
+end
+
+function system.lmsensors:start(timeout)
+ if self.timer then return end
+
+ self.timer = timer({ timeout = timeout })
+ self.timer:connect_signal("timeout", function()
+ awful.spawn.easy_async("sensors", function(output) system.lmsensors:update(output) end)
+ end)
+
+ self.timer:start()
+ self.timer:emit_signal("timeout")
+end
+
+function system.lmsensors:soft_start(timeout, shift)
+ if self.timer then return end
+
+ timer({
+ timeout = timeout - (shift or 1),
+ autostart = true,
+ single_shot = true,
+ callback = function() self:start(timeout) end
+ })
+end
+
+function system.lmsensors.get(name)
+ if os.time() - system.lmsensors.time > system.lmsensors.delay then
+ local output = redutil.read.output("sensors")
+ system.lmsensors:update(output)
+ end
+ return system.lmsensors.storage[name] or { 0 }
+end
+
+-- Legacy
+------------------------------------------------------------
+--function system.thermal.sensors(args)
+-- local args = args or "'Physical id 0'"
+-- local output = redutil.read.output("sensors | grep " .. args)
+--
+-- local temp = string.match(output, "%+(%d+%.%d)°[CF]")
+--
+-- return temp and { math.floor(tonumber(temp)) } or { 0 }
+--end
+--
+--local sensors_store
+--
+--function system.thermal.sensors_core(args)
+-- args = args or {}
+-- local index = args.index or 0
+--
+-- if args.main then sensors_store = redutil.read.output("sensors | grep Core") end
+-- local line = string.match(sensors_store, "Core " .. index .."(.-)\r?\n")
+--
+-- if not line then return { 0 } end
+--
+-- local temp = string.match(line, "%+(%d+%.%d)°[CF]")
+-- return temp and { math.floor(tonumber(temp)) } or { 0 }
+--end
+
+-- Using hddtemp
+------------------------------------------------------------
+function system.thermal.hddtemp(args)
+ args = args or {}
+ local port = args.port or "7634"
+ local disk = args.disk or "/dev/sda"
+
+ local output = redutil.read.output("echo | curl --connect-timeout 1 -fsm 3 telnet://127.0.0.1:" .. port)
+
+ for mnt, _, temp, _ in output:gmatch("|(.-)|(.-)|(.-)|(.-)|") do
+ if mnt == disk then
+ return temp and { tonumber(temp) }
+ end
+ end
+
+ return { 0 }
+end
+
+-- Using nvidia-settings on sysmem with optimus (bumblebee)
+-- Async
+------------------------------------------------------------
+function system.thermal.nvoptimus(setup)
+ local nvidia_on = string.find(redutil.read.output("cat /proc/acpi/bbswitch"), "ON")
+ if not nvidia_on then
+ setup({ 0, off = true })
+ else
+ awful.spawn.easy_async_with_shell("optirun -b none nvidia-settings -c :8 -q gpucoretemp -t | tail -1",
+ function(output)
+ local value = tonumber(string.match(output, "[^\n]+"))
+ setup({ value or 0, off = false })
+ end
+ )
+ end
+end
+
+-- Direct call of nvidia-smi
+------------------------------------------------------------
+function system.thermal.nvsmi()
+ local temp = string.match(
+ redutil.read.output("nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader"), "%d%d"
+ )
+ -- checks that local temp is not null then returns the convert string to number or if fails returns null
+ return temp and { tonumber(temp) } or { 0 }
+end
+
+-- Using nvidia-smi on sysmem with optimus (nvidia-prime)
+------------------------------------------------------------
+function system.thermal.nvprime()
+ local temp = 0
+ local nvidia_on = string.find(redutil.read.output("prime-select query"), "nvidia")
+
+ if nvidia_on ~= nil then
+ -- reuse function nvsmi
+ temp = system.thermal.nvsmi()[1]
+ end
+
+ return { temp, off = nvidia_on == nil }
+end
+
+-- Get info from transmission-remote client
+-- This function adapted special for async reading
+-----------------------------------------------------------------------------------------------------------------------
+system.transmission = {}
+
+-- Check if transmission client running
+--------------------------------------------------------------------------------
+function system.transmission.is_running(args)
+ local t_client = args or "transmission-gtk"
+ return redutil.read.output("pidof -x " .. t_client) ~= ""
+end
+
+-- Function for torrents sorting (downloading and paused first)
+--------------------------------------------------------------------------------
+function system.transmission.sort_torrent(a, b)
+ return a.status == "Downloading" and b.status ~= "Downloading"
+ or a.status == "Stopped" and b.status ~= "Stopped" and b.status ~= "Downloading"
+end
+
+-- Function to parse 'transmission-remote -l' output
+--------------------------------------------------------------------------------
+function system.transmission.parse(output, show_active_only)
+
+ -- Initialize vars
+ ------------------------------------------------------------
+ local torrent = {
+ seed = { num = 0, speed = 0 },
+ dnld = { num = 0, speed = 0 },
+ list = {},
+ }
+
+ -- Find state and progress for every torrent
+ -- and total upload and downoad speed
+ ------------------------------------------------------------
+ --local status_pos = string.find(output, "Status")
+
+ -- assuming "Up & Down" and "Downloading" is the same thing
+ output = string.gsub(output, "Up & Down", "Downloading")
+
+ -- parse every line
+ for line in string.gmatch(output, "[^\r\n]+") do
+
+ if string.sub(line, 1, 3) == "Sum" then
+ -- get total speed
+ local seed, dnld = string.match(line, "Sum:%s+[%d%.]+%s+%a+%s+([%d%.]+)%s+([%d%.]+)")
+ seed, dnld = tonumber(seed), tonumber(dnld)
+ if seed and dnld then
+ torrent.seed.speed, torrent.dnld.speed = seed, dnld
+ end
+ else
+ -- get torrent info
+ local prog, status, name = string.match(
+ line,
+ "%s+%d+%s+(%d+)%%%s+[%d%.]+%s%a+%s+.+%s+[%d%.]+%s+[%d%.]+%s+[%d%.]+%s+(%a+)%s+(.+)"
+ )
+
+ if prog and status then
+ -- if active only is selected then filter
+ if not show_active_only or (status == "Downloading" or status == "Seeding") then
+ table.insert(torrent.list, { prog = prog, status = status, name = name })
+ end
+
+ if status == "Seeding" then
+ torrent.seed.num = torrent.seed.num + 1
+ elseif status == "Downloading" then
+ torrent.dnld.num = torrent.dnld.num + 1
+ end
+ end
+ end
+ end
+
+ -- Sort torrents
+ ------------------------------------------------------------
+ -- do not need to sort active as transmission-remote automatically sorts
+ if not show_active_only then
+ table.sort(torrent.list, system.transmission.sort_torrent)
+ end
+
+ -- Format output special for redflat desktop widget
+ ------------------------------------------------------------
+ local sorted_prog = {}
+ for _, t in ipairs(torrent.list) do
+ table.insert(sorted_prog, { value = t.prog, text = string.format("%d%% %s", t.prog, t.name) })
+ end
+
+ return {
+ bars = sorted_prog,
+ lines = { { torrent.seed.speed, torrent.seed.num }, { torrent.dnld.speed, torrent.dnld.num } },
+ alert = false
+ }
+end
+
+-- Async transmission meter function
+--------------------------------------------------------------------------------
+function system.transmission.info(setup, args)
+ local command = args.command or "transmission-remote localhost -l"
+
+ awful.spawn.easy_async(command, function(output)
+ -- rather than check if an instance of transmission is running locally, check if there is actually any output
+ -- zero torrents or no program equates to same result
+ if string.len(output) > 0 then
+ local state = system.transmission.parse(output, args.show_active_only)
+
+ if args.speed_only then
+ state.lines[1][2] = state.lines[1][1]
+ state.lines[2][2] = state.lines[2][1]
+ end
+ setup(state)
+ else
+ setup({ bars = {}, lines = { { 0, 0 }, { 0, 0 } }, alert = true })
+ end
+ end)
+end
+
+-- Get processes list and cpu and memory usage for every process
+-- !!! Fixes is needed !!!
+-----------------------------------------------------------------------------------------------------------------------
+local proc_storage = {}
+
+function system.proc_info(cpu_storage)
+ local process = {}
+ local mem_page_size = 4
+
+ -- get processes list with ps utility
+ -- !!! TODO: get processes list from fs directly !!!
+ local output = redutil.read.output("ps -eo pid | tail -n +2")
+
+ -- get total cpu time diff from previous call
+ local cpu_diff = system.cpu_usage(cpu_storage).diff
+
+ -- handle every line in ps output
+ for line in string.gmatch(output, "[^\n]+") do
+ local pid = tonumber(line)
+
+ -- try to get info from /proc
+ local stat = redutil.read.file("/proc/" .. pid .. "/stat")
+
+ -- if process with given pid exist in /proc
+ if stat then
+
+ -- get process name
+ local name = string.match(stat, ".+%((.+)%).+")
+ local proc_stat = { name }
+
+ -- remove process name from stat data to simplify following parsing
+ stat = stat:gsub("%s%(.+%)", "", 1)
+
+ -- the rest of 'stat' data can be splitted by whitespaces
+ -- first chunk is pid so just skip it
+ for m in string.gmatch(stat, "[%s]+([^%s]+)") do
+ table.insert(proc_stat, m)
+ end
+
+ -- get memory usage (RSS)
+ -- !!! RSS is a very crude approximation for memory usage !!!
+ -- !!! TODO: find a more accurate method for real memory usage calculation !!!
+ local mem = proc_stat[23] * mem_page_size
+
+ -- calculate cpu usage for process
+ local proc_time = proc_stat[13] + proc_stat[14]
+ local pcpu = (proc_time - (proc_storage[pid] or 0)) / cpu_diff
+
+ -- save current cpu time for future
+ proc_storage[pid] = proc_time
+
+ -- save results
+ table.insert(process, { pid = pid, name = name, mem = mem, pcpu = pcpu })
+ end
+ end
+
+ return process
+end
+
+-- Output format functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- CPU and memory usage formatted special for desktop widget
+--------------------------------------------------------------------------------
+function system.dformatted.cpumem(storage)
+ local mem = system.memory_info()
+ local cores = {}
+ for i, v in ipairs(system.cpu_usage(storage).core) do
+ table.insert(cores, { value = v, text = string.format("CORE%d %s%%", i - 1, v) })
+ end
+
+ return {
+ bars = cores,
+ lines = { { mem.usep, mem.inuse }, { mem.swp.usep, mem.swp.inuse } }
+ }
+end
+
+-- CPU usage formatted special for panel widget
+--------------------------------------------------------------------------------
+function system.pformatted.cpu(crit)
+ crit = crit or 75
+ local storage = { cpu_total = {}, cpu_active = {} }
+
+ return function()
+ local usage = system.cpu_usage(storage).total
+ return {
+ value = usage / 100,
+ text = usage .. "%",
+ alert = usage > crit
+ }
+ end
+end
+
+-- Memory usage formatted special for panel widget
+--------------------------------------------------------------------------------
+function system.pformatted.mem(crit)
+ crit = crit or 75
+
+ return function()
+ local usage = system.memory_info().usep
+ return {
+ value = usage / 100,
+ text = usage .. "%",
+ alert = usage > crit
+ }
+ end
+end
+
+-- Battery state formatted special for panel widget
+--------------------------------------------------------------------------------
+function system.pformatted.bat(crit)
+ crit = crit or 15
+
+ return function(arg)
+ local state = system.battery(arg)
+ return {
+ value = state[2] / 100,
+ text = state[1] .. " " .. state[2] .. "% " .. state[3],
+ alert = state[2] < crit
+ }
+ end
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return system
diff --git a/awesome/.config/awesome/redflat/titlebar.lua b/awesome/.config/awesome/redflat/titlebar.lua
new file mode 100644
index 0000000..4964fca
--- /dev/null
+++ b/awesome/.config/awesome/redflat/titlebar.lua
@@ -0,0 +1,442 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat titlebar --
+-----------------------------------------------------------------------------------------------------------------------
+-- model titlebar with two view: light and full
+-- Only simple indicators avaliable, no buttons
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.titlebar v3.5.2
+------ (c) 2012 Uli Schlachter
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local error = error
+local table = table
+local unpack = unpack or table.unpack
+
+local awful = require("awful")
+local drawable = require("wibox.drawable")
+local color = require("gears.color")
+local wibox = require("wibox")
+
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local titlebar = { mt = {}, widget = {}, _index = 1, _num = 1 }
+titlebar.list = setmetatable({}, { __mode = 'k' })
+
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local default_style = {
+ size = 8,
+ position = "top",
+ font = "Sans 12 bold",
+ border_margin = { 0, 0, 0, 4 },
+ color = { main = "#b1222b", wibox = "#202020", gray = "#575757",
+ text = "#aaaaaa", icon = "#a0a0a0", urgent = "#32882d" }
+}
+
+local default_mark_style = {
+ size = 20,
+ angle = 0,
+ color = default_style.color
+}
+
+local default_button_style = {
+ list = { unknown = redutil.base.placeholder({ txt = "X" }) },
+ color = default_style.color
+}
+
+local positions = { "left", "right", "top", "bottom" }
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Get titlebar function
+------------------------------------------------------------
+local function get_titlebar_function(c, position)
+ if position == "left" then return c.titlebar_left
+ elseif position == "right" then return c.titlebar_right
+ elseif position == "top" then return c.titlebar_top
+ elseif position == "bottom" then return c.titlebar_bottom
+ else
+ error("Invalid titlebar position '" .. position .. "'")
+ end
+end
+
+-- Get titlebar model
+------------------------------------------------------------
+function titlebar.get_model(c, position)
+ position = position or "top"
+ return titlebar.list[c] and titlebar.list[c][position] or nil
+end
+
+-- Get titlebar client list
+------------------------------------------------------------
+function titlebar.get_clients()
+ local cl = {}
+ for c, _ in pairs(titlebar.list) do table.insert(cl, c) end
+ return cl
+end
+
+
+-- Build client titlebar
+-----------------------------------------------------------------------------------------------------------------------
+function titlebar.new(c, style)
+ if not titlebar.list[c] then titlebar.list[c] = {} end
+ style = redutil.table.merge(default_style, style or {})
+
+ -- Make sure that there is never more than one titlebar for any given client
+ local ret
+ if not titlebar.list[c][style.position] then
+ local tfunction = get_titlebar_function(c, style.position)
+ local d = tfunction(c, style.size)
+
+ local context = { client = c, position = style.position }
+ local base = wibox.container.margin(nil, unpack(style.border_margin))
+
+ ret = drawable(d, context, "redbar")
+ ret:_inform_visible(true)
+ ret:set_bg(style.color.wibox)
+
+ -- add info to model
+ local model = {
+ layouts = {},
+ current = nil,
+ style = style,
+ size = style.size,
+ drawable = ret,
+ hidden = false,
+ cutted = false,
+ tfunction = tfunction,
+ base = base,
+ }
+
+ -- set titlebar base layout
+ ret:set_widget(base)
+
+ -- save titlebar info
+ titlebar.list[c][style.position] = model
+ c:connect_signal("unmanage", function() ret:_inform_visible(false) end)
+ else
+ ret = titlebar.list[c][style.position].drawable
+ end
+
+ return ret
+end
+
+-- Titlebar functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Show client titlebar
+------------------------------------------------------------
+function titlebar.show(c, position)
+ local model = titlebar.get_model(c, position)
+ if model and model.hidden then
+ model.hidden = false
+ model.tfunction(c, not model.cutted and model.size or 0)
+ end
+end
+
+-- Hide client titlebar
+------------------------------------------------------------
+function titlebar.hide(c, position)
+ local model = titlebar.get_model(c, position)
+ if model and not model.hidden then
+ model.tfunction(c, 0)
+ model.hidden = true
+ end
+end
+
+-- Toggle client titlebar
+------------------------------------------------------------
+function titlebar.toggle(c, position)
+ local all_positions = position and { position } or positions
+ for _, pos in ipairs(all_positions) do
+ local model = titlebar.get_model(c, pos)
+ if model then
+ model.tfunction(c, model.hidden and not model.cutted and model.size or 0)
+ model.hidden = not model.hidden
+ end
+ end
+end
+
+-- Add titlebar view model
+------------------------------------------------------------
+function titlebar.add_layout(c, position, layout, size)
+ local model = titlebar.get_model(c, position)
+ if not model then return end
+
+ size = size or model.style.size
+ local l = { layout = layout, size = size }
+ table.insert(model.layouts, l)
+ if #model.layouts > titlebar._num then titlebar._num = #model.layouts end
+
+ if not model.current then
+ model.base:set_widget(layout)
+ model.current = 1
+ if model.size ~= size then
+ model.tfunction(c, size)
+ model.size = size
+ end
+ end
+end
+
+-- Switch titlebar view model
+------------------------------------------------------------
+function titlebar.switch(c, position, index)
+ local model = titlebar.get_model(c, position)
+ if not model or #model.layouts == 1 then return end
+
+ if index then
+ if not model.layouts[index] then return end
+ model.current = index
+ else
+ model.current = (model.current < #model.layouts) and (model.current + 1) or 1
+ end
+ local layout = model.layouts[model.current]
+
+ model.base:set_widget(layout.layout)
+ if not model.cutted and not model.hidden and model.size ~= layout.size then
+ model.tfunction(c, layout.size)
+ end
+ model.size = layout.size
+end
+
+
+-- Titlebar mass actions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Temporary hide client titlebar
+------------------------------------------------------------
+function titlebar.cut_all(cl, position)
+ cl = cl or titlebar.get_clients()
+ --local cutted = {}
+ local all_positions = position and { position } or positions
+
+ for _, pos in ipairs(all_positions) do
+ for _, c in ipairs(cl) do
+ local model = titlebar.get_model(c, pos)
+ if model and not model.cutted then
+ model.cutted = true
+ --table.insert(cutted, c)
+ if not model.hidden then model.tfunction(c, 0) end
+ end
+ end
+ end
+ --return cutted
+end
+
+-- Restore client titlebar if it was cutted
+------------------------------------------------------------
+function titlebar.restore_all(cl, position)
+ cl = cl or titlebar.get_clients()
+ local all_positions = position and { position } or positions
+ for _, pos in ipairs(all_positions) do
+ for _, c in ipairs(cl) do
+ local model = titlebar.get_model(c, pos)
+ if model and model.cutted then
+ model.cutted = false
+ if not model.hidden then model.tfunction(c, model.size) end
+ end
+ end
+ end
+end
+
+-- Mass actions
+------------------------------------------------------------
+function titlebar.toggle_all(cl, position)
+ cl = cl or titlebar.get_clients()
+ for _, c in pairs(cl) do titlebar.toggle(c, position) end
+end
+
+--function titlebar.switch_all(cl, position)
+-- cl = cl or titlebar.get_clients()
+-- for _, c in pairs(cl) do titlebar.switch(c, position) end
+--end
+
+function titlebar.show_all(cl, position)
+ cl = cl or titlebar.get_clients()
+ for _, c in pairs(cl) do titlebar.show(c, position) end
+end
+
+function titlebar.hide_all(cl, position)
+ cl = cl or titlebar.get_clients()
+ for _, c in pairs(cl) do titlebar.hide(c, position) end
+end
+
+-- Global layout switch
+------------------------------------------------------------
+function titlebar.global_switch(index)
+ titlebar._index = index or titlebar._index + 1
+ if titlebar._index > titlebar._num then titlebar._index = 1 end
+
+ for _, c in pairs(titlebar.get_clients()) do
+ for _, position in ipairs(positions) do
+ titlebar.switch(c, position, titlebar._index)
+ end
+ end
+end
+
+
+-- Titlebar indicators
+-----------------------------------------------------------------------------------------------------------------------
+titlebar.mark = {}
+titlebar.button = {}
+
+-- Client mark blank
+------------------------------------------------------------
+function titlebar.mark.base(_, style)
+
+ -- build widget
+ local widg = wibox.widget.base.make_widget()
+ widg._data = { color = style.color.gray }
+ widg._style = redutil.table.merge(default_mark_style, style or {})
+
+ -- widget setup
+ function widg:fit(_, _, width, height)
+ return width, height
+ end
+
+ function widg:draw(_, cr, width, height)
+ local d = math.tan(self._style.angle) * height
+
+ cr:set_source(color(self._data.color))
+ cr:move_to(0, height)
+ cr:rel_line_to(d, - height)
+ cr:rel_line_to(width - d, 0)
+ cr:rel_line_to(-d, height)
+ cr:close_path()
+
+ cr:fill()
+ end
+
+ -- user function
+ function widg:set_active(active)
+ self._data.color = active and style.color.main or style.color.gray
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- widget width setup
+ widg:set_forced_width(style.size)
+
+ return widg
+end
+
+-- Client property indicator
+------------------------------------------------------------
+function titlebar.mark.property(c, prop, style)
+ local w = titlebar.mark.base(c, style)
+ w:set_active(c[prop])
+ c:connect_signal("property::" .. prop, function() w:set_active(c[prop]) end)
+ return w
+end
+
+-- Client focus indicator
+------------------------------------------------------------
+function titlebar.mark.focus(c, style)
+ local w = titlebar.mark.base(c, style)
+ c:connect_signal("focus", function() w:set_active(true) end)
+ c:connect_signal("unfocus", function() w:set_active(false) end)
+ return w
+end
+
+-- Client button blank
+------------------------------------------------------------
+function titlebar.button.base(icon, style, is_inactive)
+ style = redutil.table.merge(default_button_style, style or {})
+
+ -- widget
+ local widg = svgbox(style.list[icon] or style.list.unknown)
+ widg._current_color = style.color.icon
+ widg.is_under_mouse = false
+
+ -- state
+ function widg:set_active(active)
+ widg._current_color = active and style.color.main or style.color.icon
+ widg:set_color(widg.is_under_mouse and style.color.urgent or widg._current_color)
+ --self:emit_signal("widget::redraw_needed")
+ end
+
+ local function update(is_under_mouse)
+ widg.is_under_mouse = is_under_mouse
+ widg:set_color(widg.is_under_mouse and style.color.urgent or widg._current_color)
+ end
+
+ if not is_inactive then
+ widg:connect_signal("mouse::enter", function() update(true) end)
+ widg:connect_signal("mouse::leave", function() update(false) end)
+ end
+
+ widg:set_active(false)
+ return widg
+end
+
+-- Client focus button
+------------------------------------------------------------
+function titlebar.button.focus(c, style)
+ local w = titlebar.button.base("focus", style, true)
+ c:connect_signal("focus", function() w:set_active(true) end)
+ c:connect_signal("unfocus", function() w:set_active(false) end)
+ return w
+end
+
+-- Client property button
+------------------------------------------------------------
+function titlebar.button.property(c, prop, style)
+ local w = titlebar.button.base(prop, style)
+ w:set_active(c[prop])
+ w:buttons(awful.util.table.join(awful.button({ }, 1, function() c[prop] = not c[prop] end)))
+ c:connect_signal("property::" .. prop, function() w:set_active(c[prop]) end)
+ return w
+end
+
+-- Client close button
+------------------------------------------------------------
+function titlebar.button.close(c, style)
+ local w = titlebar.button.base("close", style)
+ w:buttons(awful.util.table.join(awful.button({ }, 1, function() c:kill() end)))
+ return w
+end
+
+-- Client name indicator
+------------------------------------------------------------
+function titlebar.label(c, style, is_highlighted)
+ style = redutil.table.merge(default_style, style or {})
+ local w = wibox.widget.textbox()
+ w:set_font(style.font)
+ w:set_align("center")
+ w._current_color = style.color.text
+
+ local function update()
+ local txt = awful.util.escape(c.name or "Unknown")
+ w:set_markup(string.format('%s', w._current_color, txt))
+ end
+ c:connect_signal("property::name", update)
+
+ if is_highlighted then
+ c:connect_signal("focus", function() w._current_color = style.color.main; update() end)
+ c:connect_signal("unfocus", function() w._current_color = style.color.text; update()end)
+ end
+
+ update()
+ return w
+end
+
+
+-- Remove from list on close
+-----------------------------------------------------------------------------------------------------------------------
+client.connect_signal("unmanage", function(c) titlebar.list[c] = nil end)
+
+
+-- Config metatable to call titlebar module as function
+-----------------------------------------------------------------------------------------------------------------------
+function titlebar.mt:__call(...)
+ return titlebar.new(...)
+end
+
+return setmetatable(titlebar, titlebar.mt)
diff --git a/awesome/.config/awesome/redflat/util/base.lua b/awesome/.config/awesome/redflat/util/base.lua
new file mode 100644
index 0000000..b666759
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/base.lua
@@ -0,0 +1,66 @@
+-- RedFlat util submodule
+
+local cairo = require("lgi").cairo
+local gears = require("gears")
+local wibox = require("wibox")
+local surface = require("gears.surface")
+
+local base = {}
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Advanced buttons setup
+-- Copypasted from awful.widget.common
+-- (c) 2008-2009 Julien Danjou
+--------------------------------------------------------------------------------
+function base.buttons(buttons, object)
+ if buttons then
+ local btns = {}
+
+ for _, b in ipairs(buttons) do
+ -- Create a proxy button object: it will receive the real
+ -- press and release events, and will propagate them the the
+ -- button object the user provided, but with the object as
+ -- argument.
+ local btn = button { modifiers = b.modifiers, button = b.button }
+ btn:connect_signal("press", function () b:emit_signal("press", object) end)
+ btn:connect_signal("release", function () b:emit_signal("release", object) end)
+ btns[#btns + 1] = btn
+ end
+
+ return btns
+ end
+end
+
+-- Create cairo surface from text (useful for themed icons replacement)
+--------------------------------------------------------------------------------
+function base.placeholder(args)
+ args = args or {}
+ local tb = wibox.widget({
+ markup = args.txt or "?",
+ align = "center",
+ valign = "center",
+ widget = wibox.widget.textbox
+ })
+
+ return surface.widget_to_surface(tb, args.width or 24, args.height or 24)
+end
+
+-- Create rectangle cairo surface image
+--------------------------------------------------------------------------------
+function base.image(width, height, geometry, color)
+ local image = cairo.ImageSurface.create(cairo.Format.ARGB32, width, height)
+ local cr = cairo.Context(image)
+ cr:set_source(gears.color(color or "#000000"))
+ cr:rectangle(geometry.x, geometry.y, geometry.width, geometry.height)
+ cr:fill()
+
+ return image
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return base
+
diff --git a/awesome/.config/awesome/redflat/util/cairo.lua b/awesome/.config/awesome/redflat/util/cairo.lua
new file mode 100644
index 0000000..fd65afb
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/cairo.lua
@@ -0,0 +1,35 @@
+-- RedFlat util submodule
+
+
+local cairo = { textcentre = {} }
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Draw text aligned by center
+------------------------------------------------------------
+function cairo.textcentre.full(cr, coord, text)
+ local ext = cr:text_extents(text)
+ cr:move_to(coord[1] - (ext.width/2 + ext.x_bearing), coord[2] - (ext.height/2 + ext.y_bearing))
+ cr:show_text(text)
+end
+
+-- Draw text aligned by center horizontal only
+------------------------------------------------------------
+function cairo.textcentre.horizontal(cr, coord, text)
+ local ext = cr:text_extents(text)
+ cr:move_to(coord[1] - (ext.width/2 + ext.x_bearing), coord[2])
+ cr:show_text(text)
+end
+
+-- Set font
+------------------------------------------------------------
+function cairo.set_font(cr, font)
+ cr:set_font_size(font.size)
+ cr:select_font_face(font.font, font.slant, font.face)
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return cairo
diff --git a/awesome/.config/awesome/redflat/util/client.lua b/awesome/.config/awesome/redflat/util/client.lua
new file mode 100644
index 0000000..3d71de6
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/client.lua
@@ -0,0 +1,54 @@
+-- RedFlat util submodule
+
+local awful = require("awful")
+local client = { floatset = {} }
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+local function size_correction(c, geometry, is_restore)
+ local sign = is_restore and - 1 or 1
+ local bg = sign * 2 * c.border_width
+
+ if geometry.width then geometry.width = geometry.width - bg end
+ if geometry.height then geometry.height = geometry.height - bg end
+end
+
+-- Client geometry correction by border width
+--------------------------------------------------------------------------------
+function client.fullgeometry(c, g)
+ local ng
+
+ if g then
+ if g.width and g.width <= 1 then return end
+ if g.height and g.height <= 1 then return end
+
+ size_correction(c, g, false)
+ ng = c:geometry(g)
+ else
+ ng = c:geometry()
+ end
+
+ size_correction(c, ng, true)
+
+ return ng
+end
+
+-- Smart swap include floating layout
+--------------------------------------------------------------------------------
+function client.swap(c1, c2)
+ local lay = awful.layout.get(c1.screen)
+ if awful.util.table.hasitem(client.floatset, lay) then
+ local g1, g2 = client.fullgeometry(c1), client.fullgeometry(c2)
+
+ client.fullgeometry(c1, g2)
+ client.fullgeometry(c2, g1)
+ end
+
+ c1:swap(c2)
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return client
+
diff --git a/awesome/.config/awesome/redflat/util/desktop.lua b/awesome/.config/awesome/redflat/util/desktop.lua
new file mode 100644
index 0000000..bcdae0c
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/desktop.lua
@@ -0,0 +1,126 @@
+-- RedFlat util submodule
+
+local wibox = require("wibox")
+local awful = require("awful")
+
+local desktop = { build = {} }
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+local function sum(t, n)
+ n = n or #t
+ local s = 0
+ for i = 1, n do s = s + t[i] end
+ return s
+end
+
+local function wposition(grid, n, workarea, dir)
+ local total = sum(grid[dir])
+ local full_gap = sum(grid.edge[dir])
+ local gap = #grid[dir] > 1 and (workarea[dir] - total - full_gap) / (#grid[dir] - 1) or 0
+
+ local current = sum(grid[dir], n - 1)
+ local pos = grid.edge[dir][1] + (n - 1) * gap + current
+
+ return pos
+end
+
+-- Calculate size and position for desktop widget
+------------------------------------------------------------
+function desktop.wgeometry(grid, place, workarea)
+ return {
+ x = wposition(grid, place[1], workarea, "width"),
+ y = wposition(grid, place[2], workarea, "height"),
+ width = grid.width[place[1]],
+ height = grid.height[place[2]]
+ }
+end
+
+-- Edge constructor
+------------------------------------------------------------
+function desktop.edge(direction, zone)
+ local edge = { area = {} }
+
+ edge.wibox = wibox({
+ bg = "#00000000", -- transparent without compositing manager
+ opacity = 0, -- transparent with compositing manager
+ ontop = true,
+ visible = true
+ })
+
+ edge.layout = wibox.layout.fixed[direction]()
+ edge.wibox:set_widget(edge.layout)
+
+ if zone then
+ for i, z in ipairs(zone) do
+ edge.area[i] = wibox.container.margin(nil, 0, 0, z)
+ edge.layout:add(edge.area[i])
+ end
+ end
+
+ return edge
+end
+
+-- Desktop widgets pack constructor
+------------------------------------------------------------
+function desktop.build.static(objects, buttons)
+ for _, object in ipairs(objects) do
+ object.wibox = wibox({ type = "desktop", visible = true, bg = object.body.style.color.wibox })
+ object.wibox:geometry(object.geometry)
+ object.wibox:set_widget(object.body.area)
+
+ if buttons then object.body.area:buttons(buttons) end
+ end
+end
+
+function desktop.build.dynamic(objects, s, bgimage, buttons)
+ s = s or mouse.screen
+ local bg = awful.util.file_readable(bgimage or "") and bgimage or nil
+ local last = { visible = true }
+
+ -- desktop bg wibox
+ local dwibox = wibox({ type = "desktop", visible = true, bg = "#00000000", bgimage = bg })
+ dwibox:geometry(s.workarea)
+ dwibox:setup({
+ buttons = buttons,
+ layout = wibox.layout.align.horizontal
+ })
+
+ -- individual wiboxes (perfomance wisely)
+ for _, object in ipairs(objects) do
+ local clr = object.body.style and object.body.style.color and object.body.style.color.wibox or nil
+
+ object.wibox = wibox({ type = "desktop", visible = true, bg = clr })
+ object.wibox:geometry(object.geometry)
+ object.wibox:set_widget(object.body.area)
+
+ if buttons then object.body.area:buttons(buttons) end
+ end
+
+ -- show widgets only for empty desktop
+ local function update_desktop()
+ local clients = s:get_clients()
+ local visible = #clients == 0
+ if visible ~= last.visible then
+ last.visible = visible
+ dwibox.visible = visible
+ for _, object in ipairs(objects) do object.wibox.visible = visible end
+ end
+ end
+
+ -- better way to check visible clients?
+ local client_signals = {
+ "property::sticky", "property::minimized", "property::screen", "property::hidden",
+ "tagged", "untagged", "list"
+ }
+
+ local tag_signals = { "property::selected", "property::activated" }
+
+ for _, sg in ipairs(client_signals) do client.connect_signal(sg, update_desktop) end
+ for _, sg in ipairs(tag_signals) do tag.connect_signal(sg, update_desktop) end
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return desktop
+
diff --git a/awesome/.config/awesome/redflat/util/init.lua b/awesome/.config/awesome/redflat/util/init.lua
new file mode 100644
index 0000000..671371a
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/init.lua
@@ -0,0 +1,14 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = function(table_, key)
+ local module = rawget(table_, key)
+ return module or require(table_._NAME .. '.' .. key)
+end
+
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.util", wrequire = wrequire }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/util/key.lua b/awesome/.config/awesome/redflat/util/key.lua
new file mode 100644
index 0000000..fcc195e
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/key.lua
@@ -0,0 +1,67 @@
+-- RedFlat util submodule
+
+local unpack = unpack or table.unpack
+
+local table = table
+local awful = require("awful")
+
+local key = {}
+
+key.ignored_mod = { "Unknown", "Mod2" }
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Build awful keys from reflat raw keys table
+------------------------------------------------------------
+function key.build(t)
+ local temp = {}
+
+ for _, v in ipairs(t) do
+ table.insert(temp, awful.key(unpack(v)))
+ end
+
+ return awful.util.table.join(unpack(temp))
+end
+
+-- Check if redflat raw key matched with awful prompt key
+------------------------------------------------------------
+function key.match_prompt(rawkey, mod, _key)
+ for m, _ in pairs(mod) do
+ if awful.util.table.hasitem(key.ignored_mod, m) then
+ mod[m] = nil
+ break
+ end
+ end
+
+ local modcheck = true
+ local count = 0
+
+ for k, _ in pairs(mod) do
+ modcheck = modcheck and awful.util.table.hasitem(rawkey[1], k)
+ count = count + 1
+ end
+
+ return #rawkey[1] == count and modcheck and _key:lower() == rawkey[2]:lower()
+end
+
+-- Check if redflat raw key matched with awful prompt key
+------------------------------------------------------------
+function key.match_grabber(rawkey, mod, _key)
+ for i, m in ipairs(mod) do
+ if awful.util.table.hasitem(key.ignored_mod, m) then
+ table.remove(mod, i)
+ break
+ end
+ end
+
+ local modcheck = #mod == #rawkey[1]
+ for _, v in ipairs(mod) do modcheck = modcheck and awful.util.table.hasitem(rawkey[1], v) end
+ return modcheck and _key:lower() == rawkey[2]:lower()
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return key
+
diff --git a/awesome/.config/awesome/redflat/util/placement.lua b/awesome/.config/awesome/redflat/util/placement.lua
new file mode 100644
index 0000000..dd4e89f
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/placement.lua
@@ -0,0 +1,64 @@
+-- RedFlat util submodule
+
+local awful = require("awful")
+
+local placement = {}
+local direction = { x = "width", y = "height" }
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+function placement.add_gap(geometry, gap)
+ return {
+ x = geometry.x + gap,
+ y = geometry.y + gap,
+ width = geometry.width - 2 * gap,
+ height = geometry.height - 2 * gap
+ }
+end
+
+function placement.no_offscreen(object, gap, area)
+ local geometry = object:geometry()
+ local border = object.border_width
+
+ local screen_idx = object.screen or awful.screen.getbycoord(geometry.x, geometry.y)
+ area = area or screen[screen_idx].workarea
+ if gap then area = placement.add_gap(area, gap) end
+
+ for coord, dim in pairs(direction) do
+ if geometry[coord] + geometry[dim] + 2 * border > area[coord] + area[dim] then
+ geometry[coord] = area[coord] + area[dim] - geometry[dim] - 2*border
+ elseif geometry[coord] < area[coord] then
+ geometry[coord] = area[coord]
+ end
+ end
+
+ object:geometry(geometry)
+end
+
+local function centered_base(is_h, is_v)
+ return function(object, gap, area)
+ local geometry = object:geometry()
+ local new_geometry = {}
+
+ local screen_idx = object.screen or awful.screen.getbycoord(geometry.x, geometry.y)
+ area = area or screen[screen_idx].geometry
+ if gap then area = placement.add_gap(area, gap) end
+
+ if is_h then new_geometry.x = area.x + (area.width - geometry.width) / 2 - object.border_width end
+ if is_v then new_geometry.y = area.y + (area.height - geometry.height) / 2 - object.border_width end
+
+ return object:geometry(new_geometry)
+ end
+end
+
+placement.centered = setmetatable({}, {
+ __call = function(_, ...) return centered_base(true, true)(...) end
+})
+placement.centered.horizontal = centered_base(true, false)
+placement.centered.vertical = centered_base(false, true)
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return placement
+
diff --git a/awesome/.config/awesome/redflat/util/read.lua b/awesome/.config/awesome/redflat/util/read.lua
new file mode 100644
index 0000000..b696885
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/read.lua
@@ -0,0 +1,32 @@
+-- RedFlat util submodule
+
+local io = io
+local assert = assert
+
+local read = {}
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+function read.file(path)
+ local file = io.open(path)
+
+ if file then
+ local output = file:read("*a")
+ file:close()
+ return output
+ else
+ return nil
+ end
+end
+
+function read.output(cmd)
+ local file = assert(io.popen(cmd, 'r'))
+ local output = file:read('*all')
+ file:close()
+
+ return output
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return read
diff --git a/awesome/.config/awesome/redflat/util/table.lua b/awesome/.config/awesome/redflat/util/table.lua
new file mode 100644
index 0000000..68fe121
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/table.lua
@@ -0,0 +1,45 @@
+-- RedFlat util submodule
+
+local awful = require("awful")
+
+local table_ = {}
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Merge two table to new one
+------------------------------------------------------------
+function table_.merge(t1, t2)
+ local ret = awful.util.table.clone(t1)
+
+ for k, v in pairs(t2) do
+ if type(v) == "table" and ret[k] and type(ret[k]) == "table" then
+ ret[k] = table_.merge(ret[k], v)
+ else
+ ret[k] = v
+ end
+ end
+
+ return ret
+end
+
+-- Check if deep key exists
+------------------------------------------------------------
+function table_.check(t, s)
+ local v = t
+
+ for key in string.gmatch(s, "([^%.]+)(%.?)") do
+ if v[key] then
+ v = v[key]
+ else
+ return nil
+ end
+ end
+
+ return v
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return table_
+
diff --git a/awesome/.config/awesome/redflat/util/text.lua b/awesome/.config/awesome/redflat/util/text.lua
new file mode 100644
index 0000000..3e13e13
--- /dev/null
+++ b/awesome/.config/awesome/redflat/util/text.lua
@@ -0,0 +1,41 @@
+-- RedFlat util submodule
+
+local math = math
+local string = string
+
+local text = {}
+
+-- Functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Format string to number with minimum length
+------------------------------------------------------------
+function text.oformat(v, w)
+ local p = math.ceil(math.log10(v))
+ local prec = v <= 10 and w - 1 or p > w and 0 or w - p
+ return string.format('%.' .. prec .. 'f', v)
+end
+
+-- Format output for destop widgets
+------------------------------------------------------------
+function text.dformat(value, unit, w, spacer)
+ w = w or 3
+ spacer = spacer or " "
+ local res = value
+ local add = ""
+
+ for _, v in pairs(unit) do
+ if value > v[2] then
+ res = math.abs(value/v[2])
+ add = v[1]
+ end
+ end
+
+ return text.oformat(res, w) .. spacer .. add
+end
+
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return text
+
diff --git a/awesome/.config/awesome/redflat/widget/battery.lua b/awesome/.config/awesome/redflat/widget/battery.lua
new file mode 100644
index 0000000..a6dab60
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/battery.lua
@@ -0,0 +1,98 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat battery widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Battery charge monitoring widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local rednotify = require("redflat.float.notify")
+local tooltip = require("redflat.float.tooltip")
+local monitor = require("redflat.gauge.monitor.plain")
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local battery = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ timeout = 60,
+ width = nil,
+ widget = monitor.new,
+ notify = {},
+ levels = { 0.05, 0.1, 0.15 }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.battery") or {})
+end
+
+-- Support fucntions
+-----------------------------------------------------------------------------------------------------------------------
+local get_level = function(value, line)
+ for _, v in ipairs(line) do
+ if value < v then return v end
+ end
+end
+
+-- Create a system monitoring widget with additional notification
+-----------------------------------------------------------------------------------------------------------------------
+function battery.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create monitor widget
+ --------------------------------------------------------------------------------
+ local widg = style.widget(style.monitor)
+ widg._last = { value = 1, level = 1 }
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ widg._tp = tooltip({ objects = { widg } }, style.tooltip)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ widg._update = function()
+ local state = args.func(args.arg)
+ widg:set_value(state.value)
+ widg:set_alert(state.alert)
+ widg._tp:set_text(state.text)
+
+ if state.value <= widg._last.value then
+ local level = get_level(state.value, style.levels)
+ if level and level ~= widg._last.level then
+ widg._last.level = level
+ local warning = string.format("Battery charge < %.0f%%", level * 100)
+ rednotify:show(redutil.table.merge({ text = warning }, style.notify))
+ end
+ else
+ widg._last.level = nil
+ end
+
+ widg._last.value = state.value
+ end
+
+ widg._timer = timer({ timeout = style.timeout })
+ widg._timer:connect_signal("timeout", function() widg._update() end)
+ widg._timer:start()
+ widg._timer:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function battery.mt:__call(...)
+ return battery.new(...)
+end
+
+return setmetatable(battery, battery.mt)
diff --git a/awesome/.config/awesome/redflat/widget/binclock.lua b/awesome/.config/awesome/redflat/widget/binclock.lua
new file mode 100644
index 0000000..f976635
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/binclock.lua
@@ -0,0 +1,125 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat binary clock widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Why not?
+-----------------------------------------------------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local os = os
+
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local gears = require("gears")
+local color = require("gears.color")
+
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local binclock = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ width = 60,
+ tooltip = {},
+ dot = { size = 5 },
+ color = { main = "#b1222b", gray = "#575757" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.binclock") or {})
+end
+
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function binary_time(num)
+ local binary = {}
+ for i = 6, 1, -1 do
+ local rest = num % 2
+ binary[i] = rest
+ num = math.floor((num - rest) / 2)
+ end
+ return binary
+end
+
+
+-- Create widget.
+-----------------------------------------------------------------------------------------------------------------------
+function binclock.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local timeout = args.timeout or 60
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = wibox.widget.base.make_widget()
+
+ widg._data = {
+ time = { {}, {}, {} },
+ width = style.width or nil
+ }
+
+ -- User functions
+ ------------------------------------------------------------
+ function widg:update()
+ local date = os.date('*t')
+ self._data.time = { binary_time(date.hour), binary_time(date.min), binary_time(date.sec) }
+
+ self:emit_signal("widget::redraw_needed")
+ end
+
+ -- Fit
+ ------------------------------------------------------------
+ function widg:fit(_, width, height)
+ if self._data.width then
+ return math.min(width, self._data.width), height
+ else
+ return width, height
+ end
+ end
+
+ function widg:draw(_, cr, width, height)
+ local dx = (width - style.dot.size) / 5
+ local dy = (height - style.dot.size) / 2
+
+ for i = 1, 3 do
+ for j = 1, 6 do
+ cr:set_source(color(self._data.time[i][j] == 1 and style.color.main or style.color.gray ))
+ cr:rectangle((j -1) * dx, (i -1) * dy, style.dot.size, style.dot.size)
+ cr:fill()
+ end
+ end
+ end
+
+ -- Set tooltip if need
+ --------------------------------------------------------------------------------
+ local tp
+ if args.dateformat then tp = tooltip({ objects = { widg } }, style.tooltip) end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local timer = gears.timer({ timeout = timeout })
+ timer:connect_signal("timeout",
+ function()
+ widg:update()
+ if args.dateformat then tp:set_text(os.date(args.dateformat)) end
+ end)
+ timer:start()
+ timer:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call textclock module as function
+-----------------------------------------------------------------------------------------------------------------------
+function binclock.mt:__call(...)
+ return binclock.new(...)
+end
+
+return setmetatable(binclock, binclock.mt)
diff --git a/awesome/.config/awesome/redflat/widget/init.lua b/awesome/.config/awesome/redflat/widget/init.lua
new file mode 100644
index 0000000..470ae6e
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/init.lua
@@ -0,0 +1,10 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat library --
+-----------------------------------------------------------------------------------------------------------------------
+
+local wrequire = require("redflat.util").wrequire
+local setmetatable = setmetatable
+
+local lib = { _NAME = "redflat.widget" }
+
+return setmetatable(lib, { __index = wrequire })
diff --git a/awesome/.config/awesome/redflat/widget/keyboard.lua b/awesome/.config/awesome/redflat/widget/keyboard.lua
new file mode 100644
index 0000000..d9a08cb
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/keyboard.lua
@@ -0,0 +1,135 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat keyboard layout indicator widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Indicate and switch keybord layout
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local table = table
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local tooltip = require("redflat.float.tooltip")
+local redmenu = require("redflat.menu")
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local keybd = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = redutil.base.placeholder(),
+ micon = { blank = redutil.base.placeholder({ txt = " " }),
+ check = redutil.base.placeholder({ txt = "+" }) },
+ menu = { color = { right_icon = "#a0a0a0" } },
+ layout_color = { "#a0a0a0", "#b1222b" },
+ fallback_color = "#32882d",
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.keyboard") or {})
+end
+
+-- Initialize layout menu
+-----------------------------------------------------------------------------------------------------------------------
+function keybd:init(layouts, style)
+
+ -- initialize vars
+ style = redutil.table.merge(default_style(), style or {})
+ self.layouts = layouts or {}
+ self.style = style
+ self.objects = {}
+
+ -- tooltip
+ self.tp = tooltip({ objects = {} }, style.tooltip)
+
+ -- construct list of layouts
+ local menu_items = {}
+ for i = 1, #layouts do
+ local command = function() awesome.xkb_set_layout_group(i - 1) end
+ table.insert(menu_items, { layouts[i], command, nil, style.micon.blank })
+ end
+
+ -- initialize menu
+ self.menu = redmenu({ hide_timeout = 1, theme = style.menu, items = menu_items })
+ if self.menu.items[1].right_icon then
+ self.menu.items[1].right_icon:set_image(style.micon.check)
+ end
+
+ -- update layout data
+ self.update = function()
+ local layout = awesome.xkb_get_layout_group() + 1
+ for _, w in ipairs(self.objects) do
+ w:set_color(style.layout_color[layout] or style.fallback_color)
+ end
+
+ -- update tooltip
+ keybd.tp:set_text(self.layouts[layout] or "Unknown")
+
+ -- update menu
+ for i = 1, #self.layouts do
+ local mark = layout == i and style.micon.check or style.micon.blank
+ keybd.menu.items[i].right_icon:set_image(mark)
+ end
+ end
+
+ awesome.connect_signal("xkb::group_changed", self.update)
+end
+
+-- Show layout menu
+-----------------------------------------------------------------------------------------------------------------------
+function keybd:toggle_menu()
+ if not self.menu then return end
+
+ if self.menu.wibox.visible then
+ self.menu:hide()
+ else
+ awful.placement.under_mouse(self.menu.wibox)
+ awful.placement.no_offscreen(self.menu.wibox)
+ self.menu:show({ coords = { x = self.menu.wibox.x, y = self.menu.wibox.y } })
+ end
+end
+
+-- Toggle layout
+-----------------------------------------------------------------------------------------------------------------------
+function keybd:toggle(reverse)
+ if not self.layouts then return end
+
+ local layout = awesome.xkb_get_layout_group()
+ if reverse then
+ layout = layout > 0 and (layout - 1) or (#self.layouts - 1)
+ else
+ layout = layout < (#self.layouts - 1) and (layout + 1) or 0
+ end
+
+ awesome.xkb_set_layout_group(layout)
+end
+
+-- Create a new keyboard indicator widget
+-----------------------------------------------------------------------------------------------------------------------
+function keybd.new(style)
+
+ style = style or {}
+ if not keybd.menu then keybd:init({}) end
+
+ local widg = svgbox(style.icon or keybd.style.icon)
+ widg:set_color(keybd.style.layout_color[1])
+ table.insert(keybd.objects, widg)
+ keybd.tp:add_to_object(widg)
+
+ keybd.update()
+ return widg
+end
+
+-- Config metatable to call keybd module as function
+-----------------------------------------------------------------------------------------------------------------------
+function keybd.mt:__call(...)
+ return keybd.new(...)
+end
+
+return setmetatable(keybd, keybd.mt)
diff --git a/awesome/.config/awesome/redflat/widget/layoutbox.lua b/awesome/.config/awesome/redflat/widget/layoutbox.lua
new file mode 100644
index 0000000..b9a388d
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/layoutbox.lua
@@ -0,0 +1,168 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat layoutbox widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Paintbox widget used to display layout
+-- Layouts menu added
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.widget.layoutbox v3.5.2
+------ (c) 2009 Julien Danjou
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local ipairs = ipairs
+local table = table
+local awful = require("awful")
+local layout = require("awful.layout")
+local beautiful = require("beautiful")
+
+local redmenu = require("redflat.menu")
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local layoutbox = { mt = {} }
+
+local last_tag
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = { unknown = redutil.base.placeholder() },
+ micon = { blank = redutil.base.placeholder({ txt = " " }),
+ check = redutil.base.placeholder({ txt = "+" }) },
+ name_alias = {},
+ menu = { color = { right_icon = "#a0a0a0", left_icon = "#a0a0a0" } },
+ color = { icon = "#a0a0a0" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.layoutbox") or {})
+end
+
+-- Initialize layoutbox
+-----------------------------------------------------------------------------------------------------------------------
+function layoutbox:init(layouts, style)
+
+ style = style or default_style()
+
+ -- Set tooltip
+ ------------------------------------------------------------
+ layoutbox.tp = tooltip({})
+
+ -- Construct layout list
+ ------------------------------------------------------------
+ local items = {}
+ for _, l in ipairs(layouts) do
+ local layout_name = layout.getname(l)
+ local icon = style.icon[layout_name] or style.icon.unknown
+ local text = style.name_alias[layout_name] or layout_name
+ table.insert(items, { text, function() layout.set (l, last_tag) end, icon, style.micon.blank })
+ end
+
+ -- Update tooltip function
+ ------------------------------------------------------------
+ function self:update_tooltip(layout_name)
+ self.tp:set_text(style.name_alias[layout_name] or layout_name)
+ end
+
+ -- Update menu function
+ ------------------------------------------------------------
+ function self:update_menu(t)
+ local cl = awful.tag.getproperty(t, "layout")
+ for i, l in ipairs(layouts) do
+ local mark = cl == l and style.micon.check or style.micon.blank
+ if self.menu.items[i].right_icon then
+ self.menu.items[i].right_icon:set_image(mark)
+ end
+ end
+ end
+
+ -- Initialize menu
+ ------------------------------------------------------------
+ self.menu = redmenu({ theme = style.menu, items = items })
+end
+
+-- Show layout menu
+-----------------------------------------------------------------------------------------------------------------------
+function layoutbox:toggle_menu(t)
+ if self.menu.wibox.visible and t == last_tag then
+ self.menu:hide()
+ else
+ if self.menu.wibox.visible then self.menu.wibox.visible = false end
+ awful.placement.under_mouse(self.menu.wibox)
+ awful.placement.no_offscreen(self.menu.wibox)
+
+ last_tag = t
+ self.menu:show({coords = {x = self.menu.wibox.x, y = self.menu.wibox.y}})
+ self:update_menu(last_tag)
+ end
+end
+
+-- Create a layoutbox widge
+-- @param screen The screen number that the layout will be represented for
+-- @param layouts List of layouts
+-----------------------------------------------------------------------------------------------------------------------
+function layoutbox.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local layouts = args.layouts or awful.layout.layouts
+ local s = args.screen or 1
+ style = redutil.table.merge(default_style(), style or {})
+ local w = svgbox()
+ w:set_color(style.color.icon)
+
+ if not layoutbox.menu then layoutbox:init(layouts, style) end
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ layoutbox.tp:add_to_object(w)
+
+ -- Update function
+ --------------------------------------------------------------------------------
+ local function update()
+ local layout_name = layout.getname(layout.get(s))
+ w:set_image(style.icon[layout_name] or style.icon.unknown)
+ layoutbox:update_tooltip(layout_name)
+
+ if layoutbox.menu.wibox.visible then
+ layoutbox:update_menu(last_tag)
+ end
+ end
+
+ -- Set signals
+ --------------------------------------------------------------------------------
+ tag.connect_signal("property::selected", update)
+ tag.connect_signal("property::layout", update)
+ w:connect_signal("mouse::enter",
+ function()
+ local layout_name = layout.getname(layout.get(s))
+ layoutbox:update_tooltip(layout_name)
+ end
+ )
+ w:connect_signal("mouse::leave",
+ function()
+ if layoutbox.menu.hidetimer and layoutbox.menu.wibox.visible then
+ layoutbox.menu.hidetimer:start()
+ end
+ end
+ )
+
+ --------------------------------------------------------------------------------
+ update()
+ return w
+end
+
+-- Config metatable to call layoutbox module as function
+-----------------------------------------------------------------------------------------------------------------------
+function layoutbox.mt:__call(...)
+ return layoutbox.new(...)
+end
+
+return setmetatable(layoutbox, layoutbox.mt)
diff --git a/awesome/.config/awesome/redflat/widget/mail.lua b/awesome/.config/awesome/redflat/widget/mail.lua
new file mode 100644
index 0000000..f9c6dc5
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/mail.lua
@@ -0,0 +1,196 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat mail widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Check if new mail available using python scripts or curl shell command
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local table = table
+local tonumber = tonumber
+
+local awful = require("awful")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+local naughty = require("naughty")
+
+local rednotify = require("redflat.float.notify")
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local startup = require("redflat.startup")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+local mail = { objects = {}, mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ icon = redutil.base.placeholder(),
+ notify = {},
+ need_notify = true,
+ firstrun = false,
+ color = { main = "#b1222b", icon = "#a0a0a0" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.mail") or {})
+end
+
+-- Mail check functions
+-----------------------------------------------------------------------------------------------------------------------
+mail.checkers = {}
+
+mail.checkers["script"] = { type = "spawn" }
+mail.checkers["script"].action = function(args)
+ return args.script
+end
+
+mail.checkers["curl_imap"] = { type = "spawn" }
+mail.checkers["curl_imap"].action = function(args)
+ local port = args.port or 993
+ local request = "-X 'STATUS INBOX (UNSEEN)'"
+ local head_command = "curl --connect-timeout 5 -fsm 5"
+
+ local curl_req = string.format("%s --url imaps://%s:%s/INBOX -u %s:%s %s -k",
+ head_command, args.server, port, args.mail, args.password, request)
+
+ return curl_req
+end
+
+mail.checkers["imap"] = { type = "plain" }
+mail.checkers["imap"].action = function(args)
+ -- require imap4 library
+ -- need to luarock install imap4 library
+ local imap4 = require "imap4"
+
+ -- grab args or set default values
+ -- gmail requires 'Less secure app access'
+ local port = args.port or 993
+ local url = args.server or "outlook.office365.com"
+ local mailbox = args.mailbox or "Inbox"
+
+ -- setup connection
+ local status, connection = pcall(imap4, url, port, {protocol = 'tlsv1_2'})
+
+ if status ~= false and connection:isCapable('IMAP4rev1') then
+ connection:login(args.username, args.password)
+
+ -- get information
+ local stat = connection:status(mailbox, {'UNSEEN'})
+
+ -- close connection
+ connection:logout()
+
+ -- return unseen email count
+ return stat.UNSEEN
+ else
+ return "0"
+ end
+end
+
+-- Initialize mails structure
+-----------------------------------------------------------------------------------------------------------------------
+function mail:init(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local count = 0
+ local checks = 0
+ local force_notify = false
+ local update_timeout = args.update_timeout or 3600
+ local maillist = args.maillist or {}
+ style = redutil.table.merge(default_style(), style or {})
+
+ self.style = style
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ self.tp = tooltip(nil, style.tooltip)
+ self.tp:set_text("?")
+
+ -- Update info function
+ --------------------------------------------------------------------------------
+ local function mail_count(output)
+ local c = tonumber(string.match(output, "%d+"))
+ checks = checks + 1
+
+ if c then
+ count = count + c
+ if style.need_notify and (count > 0 or force_notify and checks == #maillist) then
+ rednotify:show(redutil.table.merge({ text = count .. " new messages" }, style.notify))
+ end
+ end
+
+ self.tp:set_text(count .. " new messages")
+
+ local color = count > 0 and style.color.main or style.color.icon
+ for _, widg in ipairs(mail.objects) do widg:set_color(color) end
+ end
+
+ self.check_updates = function(is_force)
+ count = 0
+ checks = 0
+ force_notify = is_force
+
+ for _, cmail in ipairs(maillist) do
+ if mail.checkers[cmail.checker].type == "plain" then
+ mail_count(mail.checkers[cmail.checker].action(cmail))
+ elseif mail.checkers[cmail.checker].type == "spawn" then
+ awful.spawn.easy_async(mail.checkers[cmail.checker].action(cmail), mail_count)
+ end
+ end
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ self.timer = timer({ timeout = update_timeout })
+ self.timer:connect_signal("timeout", function() self.check_updates() end)
+ self.timer:start()
+
+ if style.firstrun and startup.is_startup then self.timer:emit_signal("timeout") end
+end
+
+
+-- Create a new mail widget
+-----------------------------------------------------------------------------------------------------------------------
+function mail.new(style)
+
+ if not mail.style then
+ naughty.notify({ title = "Warning!", text = "Mail widget doesn't configured" })
+ mail:init({})
+ end
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(mail.style, style or {})
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = svgbox(style.icon)
+ widg:set_color(style.color.icon)
+ table.insert(mail.objects, widg)
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ mail.tp:add_to_object(widg)
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Update mail info for every widget
+-----------------------------------------------------------------------------------------------------------------------
+function mail:update(is_force)
+ self.check_updates(is_force)
+end
+
+-- Config metatable to call mail module as function
+-----------------------------------------------------------------------------------------------------------------------
+function mail.mt:__call(...)
+ return mail.new(...)
+end
+
+return setmetatable(mail, mail.mt)
diff --git a/awesome/.config/awesome/redflat/widget/minitray.lua b/awesome/.config/awesome/redflat/widget/minitray.lua
new file mode 100644
index 0000000..5a23384
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/minitray.lua
@@ -0,0 +1,175 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat minitray --
+-----------------------------------------------------------------------------------------------------------------------
+-- Tray located on separate wibox
+-- minitray:toggle() used to show/hide wibox
+-- Widget with graphical counter to show how many apps placed in the system tray
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ minitray
+------ http://awesome.naquadah.org/wiki/Minitray
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local table = table
+
+local wibox = require("wibox")
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+local dotcount = require("redflat.gauge.graph.dots")
+local tooltip = require("redflat.float.tooltip")
+
+-- Initialize tables and wibox
+-----------------------------------------------------------------------------------------------------------------------
+local minitray = { widgets = {}, mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ dotcount = {},
+ geometry = { height = 40 },
+ set_position = nil,
+ screen_gap = 0,
+ border_width = 2,
+ color = { wibox = "#202020", border = "#575757" },
+ shape = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.minitray") or {})
+end
+
+-- Initialize minitray floating window
+-----------------------------------------------------------------------------------------------------------------------
+function minitray:init(style)
+
+ -- Create wibox for tray
+ --------------------------------------------------------------------------------
+ local wargs = {
+ ontop = true,
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape,
+ }
+
+ self.wibox = wibox(wargs)
+ self.wibox:geometry(style.geometry)
+
+ self.geometry = style.geometry
+ self.screen_gap = style.screen_gap
+ self.set_position = style.set_position
+
+ -- Create tooltip
+ --------------------------------------------------------------------------------
+ self.tp = tooltip({}, style.tooltip)
+
+ -- Set tray
+ --------------------------------------------------------------------------------
+ local l = wibox.layout.align.horizontal()
+ self.tray = wibox.widget.systray()
+ l:set_middle(self.tray)
+ self.wibox:set_widget(l)
+
+ -- update geometry if tray icons change
+ self.tray:connect_signal('widget::redraw_needed', function()
+ self:update_geometry()
+ end)
+end
+
+-- Show/hide functions for wibox
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Update Geometry
+--------------------------------------------------------------------------------
+function minitray:update_geometry()
+
+ -- Set wibox size and position
+ ------------------------------------------------------------
+ local items = awesome.systray()
+ if items == 0 then items = 1 end
+
+ self.wibox:geometry({ width = self.geometry.width or self.geometry.height * items })
+
+ if self.set_position then
+ self.set_position(self.wibox)
+ else
+ awful.placement.under_mouse(self.wibox)
+ end
+
+ redutil.placement.no_offscreen(self.wibox, self.screen_gap, mouse.screen.workarea)
+end
+
+-- Show
+--------------------------------------------------------------------------------
+function minitray:show()
+ self:update_geometry()
+ self.wibox.visible = true
+end
+
+-- Hide
+--------------------------------------------------------------------------------
+function minitray:hide()
+ self.wibox.visible = false
+end
+
+-- Toggle
+--------------------------------------------------------------------------------
+function minitray:toggle()
+ if self.wibox.visible then
+ self:hide()
+ else
+ self:show()
+ end
+end
+
+-- Create a new tray widget
+-- @param args.timeout Update interval
+-- @param style Settings for dotcount widget
+-----------------------------------------------------------------------------------------------------------------------
+function minitray.new(_, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+-- args = args or {} -- usesless now, leave it be for backward compatibility and future cases
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Initialize minitray window
+ --------------------------------------------------------------------------------
+ if not minitray.wibox then
+ minitray:init(style)
+ end
+
+ -- Create tray widget
+ --------------------------------------------------------------------------------
+ local widg = dotcount(style.dotcount)
+ table.insert(minitray.widgets, widg)
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ minitray.tp:add_to_object(widg)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ function widg:update()
+ local appcount = awesome.systray()
+ self:set_num(appcount)
+ minitray.tp:set_text(appcount .. " apps")
+ end
+
+ minitray.tray:connect_signal('widget::redraw_needed', function() widg:update() end)
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call minitray module as function
+-----------------------------------------------------------------------------------------------------------------------
+function minitray.mt:__call(...)
+ return minitray.new(...)
+end
+
+return setmetatable(minitray, minitray.mt)
diff --git a/awesome/.config/awesome/redflat/widget/net.lua b/awesome/.config/awesome/redflat/widget/net.lua
new file mode 100644
index 0000000..2de7b83
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/net.lua
@@ -0,0 +1,101 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat network widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Network speed monitoring widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local monitor = require("redflat.gauge.icon.double")
+local tooltip = require("redflat.float.tooltip")
+local system = require("redflat.system")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local net = { mt = {} }
+
+local default_args = {
+ speed = { up = 10*1024, down = 10*1024 },
+ autoscale = true,
+ interface = "eth0"
+}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ widget = monitor.new,
+ timeout = 5,
+ digits = 2
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.net") or {})
+end
+
+-- Create a new network widget
+-- @param args.timeout Update interval
+-- @param args.interface Network interface
+-- @param args.autoscale Scale bars, true by default
+-- @param args.speed.up Max upload speed in bytes
+-- @param args.speed.down Max download speed in bytes
+-- @param style Settings for doublebar widget
+-----------------------------------------------------------------------------------------------------------------------
+function net.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local storage = {}
+ local unit = {{ "B", 1 }, { "KB", 1024 }, { "MB", 1024^2 }, { "GB", 1024^3 }}
+ args = redutil.table.merge(default_args, args or {})
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create monitor widget
+ --------------------------------------------------------------------------------
+ local widg = style.widget(style.monitor)
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ local tp = tooltip({ objects = { widg } }, style.tooltip)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local t = timer({ timeout = style.timeout })
+ t:connect_signal("timeout",
+ function()
+ local state = system.net_speed(args.interface, storage)
+ widg:set_value({1,1})
+
+ if args.autoscale then
+ if state[1] > args.speed.up then args.speed.up = state[1] end
+ if state[2] > args.speed.down then args.speed.down = state[2] end
+ end
+
+ if args.alert then
+ widg:set_alert(state[1] > args.alert.up or state[2] > args.alert.down)
+ end
+
+ widg:set_value({ state[2]/args.speed.down, state[1]/args.speed.up })
+ tp:set_text(
+ "↓" .. redutil.text.dformat(state[2], unit, style.digits, " ")
+ .. " ↑" .. redutil.text.dformat(state[1], unit, style.digits, " ")
+ )
+ end
+ )
+ t:start()
+ t:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call net module as function
+-----------------------------------------------------------------------------------------------------------------------
+function net.mt:__call(...)
+ return net.new(...)
+end
+
+return setmetatable(net, net.mt)
diff --git a/awesome/.config/awesome/redflat/widget/pulse.lua b/awesome/.config/awesome/redflat/widget/pulse.lua
new file mode 100644
index 0000000..39279a1
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/pulse.lua
@@ -0,0 +1,215 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat pulseaudio volume control widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Indicate and change volume level using pacmd
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ Pulseaudio volume control
+------ https://github.com/orofarne/pulseaudio-awesome/blob/master/pulseaudio.lua
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local math = math
+local table = table
+local tonumber = tonumber
+local string = string
+local setmetatable = setmetatable
+local awful = require("awful")
+local beautiful = require("beautiful")
+local gears = require("gears")
+local naughty = require("naughty")
+
+local tooltip = require("redflat.float.tooltip")
+local audio = require("redflat.gauge.audio.blue")
+local rednotify = require("redflat.float.notify")
+local redutil = require("redflat.util")
+
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local pulse = { widgets = {}, mt = {} }
+pulse.startup_time = 4
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ notify = {},
+ widget = audio.new,
+ audio = {}
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.pulse") or {})
+end
+
+local change_volume_default_args = {
+ down = false,
+ step = math.floor(65536 / 100 * 5 + 0.5),
+ show_notify = false
+}
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function get_default_sink(args)
+ args = args or {}
+ local type_ = args.type or "sink"
+
+ local cmd = string.format("pacmd dump | grep 'set-default-%s'", type_)
+ local output = redutil.read.output(cmd)
+ local def_sink = string.match(output, "set%-default%-%w+%s(.+)\r?\n")
+
+ return def_sink
+end
+
+-- Change volume level
+-----------------------------------------------------------------------------------------------------------------------
+function pulse:change_volume(args)
+
+ -- initialize vars
+ args = redutil.table.merge(change_volume_default_args, args or {})
+ local diff = args.down and -args.step or args.step
+
+ -- get current volume
+ local v = redutil.read.output(string.format("pacmd dump | grep 'set-%s-volume %s'", self._type, self._sink))
+ local parsed = string.match(v, "0x%x+")
+
+ -- catch possible problems with pacmd output
+ if not parsed then
+ naughty.notify({ title = "Warning!", text = "PA widget can't parse pacmd output" })
+ return
+ end
+
+ local volume = tonumber(parsed)
+
+ -- calculate new volume
+ local new_volume = volume + diff
+
+ if new_volume > 65536 then
+ new_volume = 65536
+ elseif new_volume < 0 then
+ new_volume = 0
+ end
+
+ -- show notify if need
+ if args.show_notify then
+ local vol = new_volume / 65536
+ rednotify:show(
+ redutil.table.merge({ value = vol, text = string.format('%.0f', vol*100) .. "%" }, self._style.notify)
+ )
+ end
+
+ -- set new volume
+ awful.spawn(string.format("pacmd set-%s-volume %s %s", self._type, self._sink, new_volume))
+
+ -- update volume indicators
+ self:update_volume()
+end
+
+-- Set mute
+-----------------------------------------------------------------------------------------------------------------------
+function pulse:mute(args)
+ args = args or {}
+ if not self._type or not self._sink then return end
+
+ local mute = redutil.read.output(string.format("pacmd dump | grep 'set-%s-mute %s'", self._type, self._sink))
+
+ if string.find(mute, "no", -4) then
+ awful.spawn(string.format("pacmd set-%s-mute %s yes", self._type, self._sink))
+ else
+ awful.spawn(string.format("pacmd set-%s-mute %s no", self._type, self._sink))
+ end
+
+ self:update_volume()
+end
+
+-- Update volume level info
+-----------------------------------------------------------------------------------------------------------------------
+function pulse:update_volume(args)
+ args = args or {}
+ if not self._type or not self._sink then return end
+
+ -- initialize vars
+ local volmax = 65536
+ local volume = 0
+
+ -- get current volume and mute state
+ local v = redutil.read.output(string.format("pacmd dump | grep 'set-%s-volume %s'", self._type, self._sink))
+ local m = redutil.read.output(string.format("pacmd dump | grep 'set-%s-mute %s'", self._type, self._sink))
+
+ if v then
+ local pv = string.match(v, "0x%x+")
+ if pv then volume = math.floor(tonumber(pv) * 100 / volmax + 0.5) end
+ end
+
+ local mute = not (m and string.find(m, "no", -4))
+
+ -- update widgets value
+ self:set_value(volume / 100)
+ self:set_mute(mute)
+ self._tooltip:set_text(volume .. "%")
+end
+
+-- Create a new pulse widget
+-- @param timeout Update interval
+-----------------------------------------------------------------------------------------------------------------------
+function pulse.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(default_style(), style or {})
+
+ args = args or {}
+ local timeout = args.timeout or 5
+ local autoupdate = args.autoupdate or false
+
+ -- create widget
+ --------------------------------------------------------------------------------
+ local widg = style.widget(style.audio)
+ gears.table.crush(widg, pulse, true) -- dangerous since widget have own methods, but let it be by now
+
+ widg._type = args.type or "sink"
+ widg._sink = args.sink
+ widg._style = style
+
+ table.insert(pulse.widgets, widg)
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ widg._tooltip = tooltip({ objects = { widg } }, style.tooltip)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ if autoupdate then
+ local t = gears.timer({ timeout = timeout })
+ t:connect_signal("timeout", function() widg:update_volume() end)
+ t:start()
+ end
+
+ -- Set startup timer
+ -- This is workaround if module activated bofore pulseaudio servise start
+ --------------------------------------------------------------------------------
+ if not widg._sink then
+ local st = gears.timer({ timeout = 1 })
+ local counter = 0
+ st:connect_signal("timeout", function()
+ counter = counter + 1
+ widg._sink = get_default_sink({ type = widg._type })
+ if widg._sink then widg:update_volume() end
+ if counter > pulse.startup_time or widg._sink then st:stop() end
+ end)
+ st:start()
+ else
+ widg:update_volume()
+ end
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call pulse module as function
+-----------------------------------------------------------------------------------------------------------------------
+function pulse.mt:__call(...)
+ return pulse.new(...)
+end
+
+return setmetatable(pulse, pulse.mt)
\ No newline at end of file
diff --git a/awesome/.config/awesome/redflat/widget/sysmon.lua b/awesome/.config/awesome/redflat/widget/sysmon.lua
new file mode 100644
index 0000000..fc6d3c5
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/sysmon.lua
@@ -0,0 +1,73 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat sysmon widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Monitoring widget
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local monitor = require("redflat.gauge.monitor.plain")
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local sysmon = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ timeout = 5,
+ width = nil,
+ widget = monitor.new
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.sysmon") or {})
+end
+
+-- Create a new cpu monitor widget
+-----------------------------------------------------------------------------------------------------------------------
+function sysmon.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create monitor widget
+ --------------------------------------------------------------------------------
+ local widg = style.widget(style.monitor)
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ widg._tp = tooltip({ objects = { widg } }, style.tooltip)
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ widg._update = function()
+ local state = args.func(args.arg)
+ widg:set_value(state.value)
+ widg:set_alert(state.alert)
+ widg._tp:set_text(state.text)
+ end
+
+ widg._timer = timer({ timeout = style.timeout })
+ widg._timer:connect_signal("timeout", function() widg._update() end)
+ widg._timer:start()
+ widg._timer:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call module as function
+-----------------------------------------------------------------------------------------------------------------------
+function sysmon.mt:__call(...)
+ return sysmon.new(...)
+end
+
+return setmetatable(sysmon, sysmon.mt)
diff --git a/awesome/.config/awesome/redflat/widget/taglist.lua b/awesome/.config/awesome/redflat/widget/taglist.lua
new file mode 100644
index 0000000..fb034d7
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/taglist.lua
@@ -0,0 +1,210 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat taglist widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget used to display tag info
+-- Separators added
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.widget.taglist v3.5.2
+------ (c) 2008-2009 Julien Danjou
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local pairs = pairs
+local ipairs = ipairs
+local table = table
+local string = string
+local awful = require("awful")
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+local timer = require("gears.timer")
+
+local redutil = require("redflat.util")
+local basetag = require("redflat.gauge.tag")
+local tooltip = require("redflat.float.tooltip")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local taglist = { filter = {}, mt = {} , queue = setmetatable({}, { __mode = 'k' }) }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ tag = {},
+ widget = basetag.blue.new,
+ show_tip = false,
+ timeout = 0.05,
+ separator = nil
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.taglist") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Get info about tag
+--------------------------------------------------------------------------------
+local function get_state(t)
+ local state = { focus = false, urgent = false, list = {} }
+ local client_list = t:clients()
+ local client_count = 0
+
+ for _, c in pairs(client_list) do
+ state.focus = state.focus or client.focus == c
+ state.urgent = state.urgent or c.urgent
+ if not c.skip_taskbar then
+ client_count = client_count + 1
+ table.insert(state.list, { focus = client.focus == c, urgent = c.urgent, minimized = c.minimized })
+ end
+ end
+
+ state.active = t.selected
+ state.occupied = client_count > 0 and not (client_count == 1 and state.focus)
+ state.text = string.upper(t.name)
+ state.layout = awful.tag.getproperty(t, "layout")
+
+ return state
+end
+
+-- Generate tooltip string
+--------------------------------------------------------------------------------
+local function make_tip(t)
+ return string.format("%s (%d apps)", t.name, #(t:clients()))
+end
+
+-- Find all tag to be shown
+--------------------------------------------------------------------------------
+local function filtrate_tags(screen, filter)
+ local tags = {}
+ for _, t in ipairs(screen.tags) do
+ if not awful.tag.getproperty(t, "hide") and filter(t) then
+ table.insert(tags, t)
+ end
+ end
+ return tags
+end
+
+-- Layout composition
+--------------------------------------------------------------------------------
+local function base_pack(layout, widg, i, tags, style)
+ layout:add(widg)
+ if style.separator and i < #tags then
+ layout:add(style.separator)
+ end
+end
+
+
+-- Create a new taglist widget
+-----------------------------------------------------------------------------------------------------------------------
+function taglist.new(args, style)
+
+ if not taglist.queue then taglist:init() end
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local cs = args.screen
+ local layout = args.layout or wibox.layout.fixed.horizontal()
+ local data = setmetatable({}, { __mode = 'k' })
+ local filter = args.filter or taglist.filter.all
+ local hint = args.hint or make_tip
+ local pack = args.pack or base_pack
+
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ if not taglist.tp then taglist.tp = tooltip() end
+
+ -- Update function
+ --------------------------------------------------------------------------------
+ local update = function(s)
+ if s ~= cs then return end
+ local tags = filtrate_tags(s, filter)
+
+ -- Construct taglist
+ ------------------------------------------------------------
+ layout:reset()
+ for i, t in ipairs(tags) do
+ local cache = data[t]
+ local widg
+
+ -- use existing widgets or create new one
+ if cache then
+ widg = cache
+ else
+ widg = style.widget(style.tag)
+ if args.buttons then widg:buttons(redutil.base.buttons(args.buttons, t)) end
+ data[t] = widg
+
+ -- set optional tooltip (what about removing?)
+ if style.show_tip then
+ taglist.tp:add_to_object(widg)
+ widg:connect_signal("mouse::enter", function() taglist.tp:set_text(widg.tip) end)
+ end
+ end
+
+ -- set tag state info to widget
+ local state = get_state(t)
+ widg:set_state(state)
+ widg.tip = hint(t)
+
+ -- add widget and separator to base layout
+ pack(layout, widg, i, tags, style)
+ end
+ ------------------------------------------------------------
+
+ if taglist.queue[s] and taglist.queue[s].started then taglist.queue[s]:stop() end
+ end
+
+ -- Create timer to prevent multiply call
+ --------------------------------------------------------------------------------
+ taglist.queue[cs] = timer({ timeout = style.timeout })
+ taglist.queue[cs]:connect_signal("timeout", function() update(cs) end)
+
+ local uc = function (c) if taglist.queue[c.screen] then taglist.queue[c.screen]:again() end end
+ local ut = function (t) if taglist.queue[t.screen] then taglist.queue[t.screen]:again() end end
+
+ -- Signals setup
+ --------------------------------------------------------------------------------
+ local tag_signals = {
+ "property::selected", "property::icon", "property::hide",
+ "property::activated", "property::name", "property::screen",
+ "property::index", "property::layout"
+ }
+ local client_signals = {
+ "focus", "unfocus", "property::urgent",
+ "tagged", "untagged", "unmanage"
+ }
+
+ for _, sg in ipairs(tag_signals) do awful.tag.attached_connect_signal(nil, sg, ut) end
+ for _, sg in ipairs(client_signals) do client.connect_signal(sg, uc) end
+
+ client.connect_signal("property::screen", function() update(cs) end) -- dirty
+
+ --------------------------------------------------------------------------------
+ update(cs) -- create taglist widget
+ return layout -- return taglist widget
+end
+
+-- Filtering functions
+-- @param t The awful.tag
+-- @param args unused list of extra arguments
+-----------------------------------------------------------------------------------------------------------------------
+function taglist.filter.noempty(t) -- to include all nonempty tags on the screen.
+ return #t:clients() > 0 or t.selected
+end
+
+function taglist.filter.all() -- to include all tags on the screen.
+ return true
+end
+
+-- Config metatable to call taglist module as function
+-----------------------------------------------------------------------------------------------------------------------
+function taglist.mt:__call(...)
+ return taglist.new(...)
+end
+
+return setmetatable(taglist, taglist.mt)
diff --git a/awesome/.config/awesome/redflat/widget/tasklist.lua b/awesome/.config/awesome/redflat/widget/tasklist.lua
new file mode 100644
index 0000000..b434901
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/tasklist.lua
@@ -0,0 +1,895 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat tasklist widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Custom widget used to show apps, see redtask.lua for more info
+-- No icons; labels can be customized in beautiful theme file
+-- Same class clients grouped into one object
+-- Pop-up tooltip with task names
+-- Pop-up menu with window state info
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.widget.tasklist v3.5.2
+------ (c) 2008-2009 Julien Danjou
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local pairs = pairs
+local ipairs = ipairs
+local table = table
+local string = string
+local math = math
+local unpack = unpack or table.unpack
+
+local beautiful = require("beautiful")
+local tag = require("awful.tag")
+local awful = require("awful")
+local wibox = require("wibox")
+local timer = require("gears.timer")
+
+local basetask = require("redflat.gauge.tag.blue")
+local redutil = require("redflat.util")
+local separator = require("redflat.gauge.separator")
+local redmenu = require("redflat.menu")
+local svgbox = require("redflat.gauge.svgbox")
+local dfparser = require("redflat.service.dfparser")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local redtasklist = { filter = {}, winmenu = {}, tasktip = {}, action = {}, mt = {}, }
+
+local last = {
+ client = nil,
+ group = nil,
+ client_list = nil,
+ screen = mouse.screen,
+ tag_screen = mouse.screen,
+ screen_clients = {}
+}
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ appnames = {},
+ iconnames = {},
+ widget = basetask.new,
+ width = 40,
+ char_digit = 3,
+ need_group = true,
+ parser = {},
+ icons = {},
+ timeout = 0.05,
+ custom_icon = false,
+ task = {},
+ task_margin = { 5, 5, 0, 0 }
+ }
+ style.winmenu = {
+ icon = { unknown = redutil.base.placeholder() },
+ micon = { blank = redutil.base.placeholder({ txt = " " }),
+ check = redutil.base.placeholder({ txt = "+" }) },
+ layout_icon = { unknown = redutil.base.placeholder() },
+ titleline = { font = "Sans 16 bold", height = 35 },
+ stateline = { height = 35 },
+ state_iconsize = { width = 20, height = 20 },
+ separator = { marginh = { 3, 3, 5, 5 } },
+ tagmenu = { icon_margin = { 2, 2, 2, 2 } },
+ hide_action = { min = true,
+ move = true,
+ max = false,
+ add = false,
+ floating = false,
+ sticky = false,
+ ontop = false,
+ below = false,
+ maximized = false },
+ color = { main = "#b1222b", icon = "#a0a0a0", gray = "#404040" }
+ }
+ style.tasktip = {
+ border_width = 2,
+ margin = { 10, 10, 5, 5 },
+ timeout = 0.5,
+ sl_highlight = false, -- single line highlight
+ color = { border = "#575757", text = "#aaaaaa", main = "#b1222b", highlight = "#eeeeee",
+ wibox = "#202020", gray = "#575757", urgent = "#32882d" },
+ shape = nil
+
+ }
+ style.winmenu.menu = {
+ ricon_margin = { 2, 2, 2, 2 },
+ hide_timeout = 1,
+ -- color = { submenu_icon = "#a0a0a0", right_icon = "#a0a0a0", left_icon = "#a0a0a0" }
+ nohide = true
+ }
+
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.tasklist") or {})
+end
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Get info about client group
+--------------------------------------------------------------------------------
+local function get_state(c_group, style)
+
+ style = style or {}
+ local names = style.appnames or {}
+ local chars = style.char_digit
+
+ local state = { focus = false, urgent = false, minimized = true, list = {} }
+
+ for _, c in pairs(c_group) do
+ state.focus = state.focus or client.focus == c
+ state.urgent = state.urgent or c.urgent
+ state.minimized = state.minimized and c.minimized
+
+ table.insert(state.list, { focus = client.focus == c, urgent = c.urgent, minimized = c.minimized })
+ end
+
+ local class = c_group[1].class or "Undefined"
+ state.text = names[class] or string.upper(string.sub(class, 1, chars))
+ state.num = #c_group
+ state.icon = style.custom_icon and style.icons[style.iconnames[class] or string.lower(class)]
+
+ return state
+end
+
+-- Function to build item list for submenu
+--------------------------------------------------------------------------------
+local function tagmenu_items(action, style)
+ local items = {}
+ for _, t in ipairs(last.screen.tags) do
+ if not awful.tag.getproperty(t, "hide") then
+ table.insert(
+ items,
+ { t.name, function() action(t) end, style.micon.blank, style.micon.blank }
+ )
+ end
+ end
+ return items
+end
+
+-- Function to rebuild the submenu entries according to current screen's tags
+--------------------------------------------------------------------------------
+local function tagmenu_rebuild(menu, submenu_index, style)
+ for _, index in ipairs(submenu_index) do
+ local new_items
+ if index == 1 then
+ new_items = tagmenu_items(redtasklist.winmenu.movemenu_action, style)
+ else
+ new_items = tagmenu_items(redtasklist.winmenu.addmenu_action, style)
+ end
+ menu.items[index].child:replace_items(new_items)
+ end
+end
+
+-- Function to update tag submenu icons
+--------------------------------------------------------------------------------
+local function tagmenu_update(c, menu, submenu_index, style)
+ -- if the screen has changed (and thus the tags) since the last time the
+ -- tagmenu was built, rebuild it first
+ if last.tag_screen ~= mouse.screen then
+ tagmenu_rebuild(menu, submenu_index, style)
+ last.tag_screen = mouse.screen
+ end
+ for k, t in ipairs(last.screen.tags) do
+ if not awful.tag.getproperty(t, "hide") then
+
+ -- set layout icon for every tag
+ local l = awful.layout.getname(awful.tag.getproperty(t, "layout"))
+
+ local check_icon = style.micon.blank
+ if c then
+ local client_tags = c:tags()
+ check_icon = awful.util.table.hasitem(client_tags, t) and style.micon.check or check_icon
+ end
+
+ for _, index in ipairs(submenu_index) do
+ local submenu = menu.items[index].child
+ if submenu.items[k].icon then
+ submenu.items[k].icon:set_image(style.layout_icon[l] or style.layout_icon.unknown)
+ end
+
+ -- set "checked" icon if tag active for given client
+ -- otherwise set empty icon
+ if c then
+ if submenu.items[k].right_icon then
+ submenu.items[k].right_icon:set_image(check_icon)
+ end
+ end
+
+ -- update position of any visible submenu
+ if submenu.wibox.visible then submenu:show() end
+ end
+ end
+ end
+end
+
+-- Function to construct menu line with state icons
+--------------------------------------------------------------------------------
+local function state_line_construct(state_icons, setup_layout, style)
+ local stateboxes = {}
+
+ for i, v in ipairs(state_icons) do
+ -- create widget
+ stateboxes[i] = svgbox(v.icon)
+ stateboxes[i]:set_forced_width(style.state_iconsize.width)
+ stateboxes[i]:set_forced_height(style.state_iconsize.height)
+
+ -- set widget in line
+ local l = wibox.layout.align.horizontal()
+ l:set_expand("outside")
+ l:set_second(stateboxes[i])
+ setup_layout:add(l)
+
+ -- set mouse action
+ stateboxes[i]:buttons(awful.util.table.join(awful.button({}, 1,
+ function()
+ v.action()
+ stateboxes[i]:set_color(v.indicator(last.client) and style.color.main or style.color.gray)
+ end
+ )))
+ end
+
+ return stateboxes
+end
+
+-- Calculate menu position
+-- !!! Bad code is here !!!
+-- !!! TODO: make variant when panel place on top of screen !!!
+--------------------------------------------------------------------------------
+local function coords_calc(menu, tip_wibox, gap)
+ local coords = {}
+
+ if gap then
+ coords.x = tip_wibox.x + (tip_wibox.width - menu.wibox.width) / 2
+ coords.y = tip_wibox.y - menu.wibox.height - 2 * menu.wibox.border_width + tip_wibox.border_width + gap
+ else
+ coords = mouse.coords()
+ coords.x = coords.x - menu.wibox.width / 2 - menu.wibox.border_width
+ end
+
+ return coords
+end
+
+-- Create tasklist object
+--------------------------------------------------------------------------------
+local function new_task(c_group, style)
+ local task = {}
+ task.widg = style.widget(style.task)
+ task.group = c_group
+ task.l = wibox.container.margin(task.widg, unpack(style.task_margin))
+
+ task.widg:connect_signal("mouse::enter", function() redtasklist.tasktip:show(task.group) end)
+ task.widg:connect_signal("mouse::leave",
+ function()
+ redtasklist.tasktip.hidetimer:start()
+ if not redtasklist.winmenu.menu.hidetimer.started then redtasklist.winmenu.menu.hidetimer:start() end
+ end
+ )
+ return task
+end
+
+-- Find all clients to be shown
+--------------------------------------------------------------------------------
+local function visible_clients(filter, screen)
+ local clients = {}
+
+ for _, c in ipairs(client.get()) do
+ local hidden = c.skip_taskbar or c.hidden or c.type == "splash" or c.type == "dock" or c.type == "desktop"
+
+ if not hidden and filter(c, screen) then
+ table.insert(clients, c)
+ end
+ end
+
+ return clients
+end
+
+-- Split tasks into groups by class
+--------------------------------------------------------------------------------
+local function group_task(clients, need_group)
+ local client_groups = {}
+ local classes = {}
+
+ for _, c in ipairs(clients) do
+ if need_group then
+ local index = awful.util.table.hasitem(classes, c.class or "Undefined")
+ if index then
+ table.insert(client_groups[index], c)
+ else
+ table.insert(classes, c.class or "Undefined")
+ table.insert(client_groups, { c })
+ end
+ else
+ table.insert(client_groups, { c })
+ end
+ end
+
+ return client_groups
+end
+
+-- Form ordered client list special for switch function
+--------------------------------------------------------------------------------
+local function sort_list(client_groups)
+ local list = {}
+
+ for _, g in ipairs(client_groups) do
+ for _, c in ipairs(g) do
+ if not c.minimized then table.insert(list, c) end
+ end
+ end
+
+ return list
+end
+
+-- Create tasktip line
+--------------------------------------------------------------------------------
+local function tasktip_line(style)
+ local line = {}
+
+ -- text
+ line.tb = wibox.widget.textbox()
+
+ -- horizontal align wlayout
+ local horizontal = wibox.layout.fixed.horizontal()
+ horizontal:add(wibox.container.margin(line.tb, unpack(style.margin)))
+
+ -- background for client state mark
+ line.field = wibox.container.background(horizontal)
+
+ -- tasktip line metods
+ function line:set_text(text)
+ line.tb:set_markup(text)
+
+ if style.max_width then
+ line.tb:set_ellipsize("middle")
+ local _, line_h = line.tb:get_preferred_size()
+ line.tb:set_forced_height(line_h)
+ line.tb:set_forced_width(style.max_width)
+ end
+
+ line.field:set_fg(style.color.text)
+ line.field:set_bg(style.color.wibox)
+ end
+
+ function line:mark_focused()
+ line.field:set_bg(style.color.main)
+ line.field:set_fg(style.color.highlight)
+ end
+
+ function line:mark_urgent()
+ line.field:set_bg(style.color.urgent)
+ line.field:set_fg(style.color.highlight)
+ end
+
+ function line:mark_minimized()
+ line.field:set_fg(style.color.gray)
+ end
+
+ return line
+end
+
+-- Switch task
+--------------------------------------------------------------------------------
+local function switch_focus(list, is_reverse)
+ local diff = is_reverse and - 1 or 1
+
+ if #list == 0 then return end
+
+ local index = (awful.util.table.hasitem(list, client.focus) or 1) + diff
+
+ if index < 1 then index = #list
+ elseif index > #list then index = 1
+ end
+
+ -- set focus to new task
+ client.focus = list[index]
+ list[index]:raise()
+end
+
+local function client_group_sort_by_class(a, b)
+ return (a[1].class or "Undefined") < (b[1].class or "Undefined")
+end
+
+-- Build or update tasklist.
+--------------------------------------------------------------------------------
+local function tasklist_construct(client_groups, layout, data, buttons, style)
+
+ layout:reset()
+ local task_full_width = style.width + style.task_margin[1] + style.task_margin[2]
+ layout:set_max_widget_size(task_full_width)
+ layout:set_forced_width(task_full_width * #client_groups)
+
+ -- construct tasklist
+ for i, c_group in ipairs(client_groups) do
+ local task
+
+ -- use existing widgets or create new
+ if data[i] then
+ task = data[i]
+ task.group = c_group
+ else
+ task = new_task(c_group, style)
+ data[i] = task
+ end
+
+ -- set info and buttons to widget
+ local state = get_state(c_group, style)
+ task.widg:set_state(state)
+ task.widg:buttons(redutil.base.buttons(buttons, { group = c_group }))
+
+ -- construct
+ layout:add(task.l)
+ end
+end
+
+-- Construct or update tasktip
+--------------------------------------------------------------------------------
+local function construct_tasktip(c_group, layout, data, buttons, style)
+ layout:reset()
+ local tb_w, tb_h
+ local tip_width = 1
+
+ for i, c in ipairs(c_group) do
+ local line
+
+ -- use existing widgets or create new
+ if data[i] then
+ line = data[i]
+ else
+ line = tasktip_line(style)
+ data[i] = line
+ end
+
+ line:set_text(awful.util.escape(c.name) or "Untitled")
+ tb_w, tb_h = line.tb:get_preferred_size()
+ if line.tb.forced_width then
+ tb_w = math.min(line.tb.forced_width, tb_w)
+ end
+
+ -- set state highlight only for grouped tasks
+ if #c_group > 1 or style.sl_highlight then
+ local state = get_state({ c })
+
+ if state.focus then line:mark_focused() end
+ if state.minimized then line:mark_minimized() end
+ if state.urgent then line:mark_urgent() end
+ end
+
+ -- set buttons
+ local gap = (i - 1) * (tb_h + style.margin[3] + style.margin[4])
+ if buttons then line.field:buttons(redutil.base.buttons(buttons, { group = { c }, gap = gap })) end
+
+ -- add line widget to tasktip layout
+ tip_width = math.max(tip_width, tb_w)
+ layout:add(line.field)
+ end
+
+ -- return tasktip size
+ return {
+ width = tip_width + style.margin[1] + style.margin[2],
+ height = #c_group * (tb_h + style.margin[3] + style.margin[4])
+ }
+end
+
+
+-- Initialize window menu widget
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.winmenu:init(style)
+
+ -- Window managment functions
+ --------------------------------------------------------------------------------
+ self.hide_check = function(action)
+ if style.hide_action[action] then self.menu:hide() end
+ end
+
+ local close = function() last.client:kill(); self.menu:hide() end
+ local minimize = function() last.client.minimized = not last.client.minimized; self.hide_check("min") end
+ -- local maximize = function() last.client.maximized = not last.client.maximized; self.hide_check("max")end
+
+ -- Create array of state icons
+ -- associate every icon with action and state indicator
+ --------------------------------------------------------------------------------
+ local function icon_table_ganerator(property)
+ return {
+ icon = style.icon[property] or style.icon.unknown,
+ action = function() last.client[property] = not last.client[property]; self.hide_check(property) end,
+ indicator = function(c) return c[property] end
+ }
+ end
+
+ local state_icons = {
+ icon_table_ganerator("floating"),
+ icon_table_ganerator("sticky"),
+ icon_table_ganerator("ontop"),
+ icon_table_ganerator("below"),
+ icon_table_ganerator("maximized"),
+ }
+
+ -- Construct menu
+ --------------------------------------------------------------------------------
+
+ -- Client class line (menu title) construction
+ ------------------------------------------------------------
+ local classbox = wibox.widget.textbox()
+ classbox:set_font(style.titleline.font)
+ classbox:set_align ("center")
+
+ local classline = wibox.container.constraint(classbox, "exact", nil, style.titleline.height)
+
+ -- Window state line construction
+ ------------------------------------------------------------
+
+ -- layouts
+ local stateline_horizontal = wibox.layout.flex.horizontal()
+ local stateline_vertical = wibox.layout.align.vertical()
+ stateline_vertical:set_second(stateline_horizontal)
+ stateline_vertical:set_expand("outside")
+ local stateline = wibox.container.constraint(stateline_vertical, "exact", nil, style.stateline.height)
+
+ -- set all state icons in line
+ local stateboxes = state_line_construct(state_icons, stateline_horizontal, style)
+
+ -- update function for state icons
+ local function stateboxes_update(c, icons, boxes)
+ for i, v in ipairs(icons) do
+ boxes[i]:set_color(v.indicator(c) and style.color.main or style.color.gray)
+ end
+ end
+
+ -- Separators config
+ ------------------------------------------------------------
+ local menusep = { widget = separator.horizontal(style.separator) }
+
+ -- Construct tag submenus ("move" and "add")
+ ------------------------------------------------------------
+
+ -- menu item actions
+ self.movemenu_action = function(t)
+ last.client:move_to_tag(t); awful.layout.arrange(t.screen); self.hide_check("move")
+ end
+
+ self.addmenu_action = function(t)
+ last.client:toggle_tag(t); awful.layout.arrange(t.screen); self.hide_check("add")
+ end
+
+ -- menu items
+ local movemenu_items = tagmenu_items(self.movemenu_action, style)
+ local addmenu_items = tagmenu_items(self.addmenu_action, style)
+
+ -- Create menu
+ ------------------------------------------------------------
+ self.menu = redmenu({
+ theme = style.menu,
+ items = {
+ { widget = classline },
+ menusep,
+ { "Move to tag", { items = movemenu_items, theme = style.tagmenu } },
+ { "Add to tag", { items = addmenu_items, theme = style.tagmenu } },
+
+ { "Minimize", minimize, nil, style.icon.minimize or style.icon.unknown },
+ { "Close", close, nil, style.icon.close or style.icon.unknown },
+ menusep,
+ { widget = stateline, focus = true }
+ }
+ })
+
+ -- Widget update functions
+ --------------------------------------------------------------------------------
+ function self:update(c)
+ if self.menu.wibox.visible then
+ classbox:set_text(c.class or "Undefined")
+ stateboxes_update(c, state_icons, stateboxes)
+ tagmenu_update(c, self.menu, { 1, 2 }, style)
+ end
+ end
+
+ -- Signals setup
+ -- Signals which affect window menu only
+ -- and does not connected to tasklist
+ --------------------------------------------------------------------------------
+ local client_signals = {
+ "property::ontop", "property::floating", "property::below", "property::maximized",
+ }
+ for _, sg in ipairs(client_signals) do
+ client.connect_signal(sg, function() self:update(last.client) end)
+ end
+end
+
+-- Show window menu widget
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.winmenu:show(c_group, gap)
+
+ -- do nothing if group of task received
+ -- show state only for single task
+ if #c_group > 1 then return end
+
+ local c = c_group[1]
+
+ -- toggle menu
+ if self.menu.wibox.visible and c == last.client and mouse.screen == last.screen then
+ self.menu:hide()
+ else
+ last.client = c
+ last.screen = mouse.screen
+ self.menu:show({ coords = coords_calc(self.menu, redtasklist.tasktip.wibox, gap) })
+
+ if self.menu.hidetimer.started then self.menu.hidetimer:stop() end
+ self:update(c)
+ end
+end
+
+
+-- Initialize a tasktip
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.tasktip:init(buttons, style)
+
+ local tippat = {}
+
+ -- Create wibox
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ type = "tooltip",
+ bg = style.color.wibox,
+ border_width = style.border_width,
+ border_color = style.color.border,
+ shape = style.shape
+ })
+
+ self.wibox.ontop = true
+
+ self.layout = wibox.layout.fixed.vertical()
+ self.wibox:set_widget(self.layout)
+
+ -- Update function
+ --------------------------------------------------------------------------------
+ function self:update(c_group)
+
+ if not self.wibox.visible then return end
+
+ local wg = construct_tasktip(c_group, self.layout, tippat, buttons, style)
+ self.wibox:geometry(wg)
+ end
+
+ -- Set tasktip autohide timer
+ --------------------------------------------------------------------------------
+ self.hidetimer = timer({ timeout = style.timeout })
+ self.hidetimer:connect_signal("timeout",
+ function()
+ self.wibox.visible = false
+ if self.hidetimer.started then self.hidetimer:stop() end
+ end
+ )
+ self.hidetimer:emit_signal("timeout")
+
+ -- Signals setup
+ --------------------------------------------------------------------------------
+ self.wibox:connect_signal("mouse::enter",
+ function()
+ if self.hidetimer.started then self.hidetimer:stop() end
+ end
+ )
+
+ self.wibox:connect_signal("mouse::leave",
+ function()
+ self.hidetimer:start()
+ if not redtasklist.winmenu.menu.hidetimer.started then redtasklist.winmenu.menu.hidetimer:start() end
+ end
+ )
+end
+
+-- Show tasktip
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.tasktip:show(c_group)
+
+ if self.hidetimer.started then self.hidetimer:stop() end
+
+ if not self.wibox.visible or last.group ~= c_group then
+ self.wibox.visible = true
+ last.group = c_group
+ self:update(c_group)
+ awful.placement.under_mouse(self.wibox)
+ awful.placement.no_offscreen(self.wibox)
+ end
+end
+
+-- Create a new tasklist widget
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ local cs = args.screen
+ local filter = args.filter or redtasklist.filter.currenttags
+
+ style = redutil.table.merge(default_style(), style or {})
+ if style.custom_icon then style.icons = dfparser.icon_list(style.parser) end
+ if style.task.width then style.width = style.task.width end
+
+ redtasklist.winmenu:init(style.winmenu)
+ redtasklist.tasktip:init(args.buttons, style.tasktip)
+
+ local tasklist = wibox.layout.flex.horizontal()
+ local data = {}
+
+ -- Update tasklist
+ --------------------------------------------------------------------------------
+
+ -- Tasklist update function
+ ------------------------------------------------------------
+ local function tasklist_update()
+ local clients = visible_clients(filter, cs)
+ local client_groups = group_task(clients, style.need_group)
+
+ table.sort(client_groups, client_group_sort_by_class)
+ last.screen_clients[cs] = sort_list(client_groups)
+
+ tasklist_construct(client_groups, tasklist, data, args.buttons, style)
+ end
+
+ -- Full update including pop-up widgets
+ ------------------------------------------------------------
+ local function update()
+ tasklist_update()
+ redtasklist.tasktip:update(last.group)
+ redtasklist.winmenu:update(last.client)
+ end
+
+ -- Create timer to prevent multiply call
+ --------------------------------------------------------------------------------
+ tasklist.queue = timer({ timeout = style.timeout })
+ tasklist.queue:connect_signal("timeout", function() update(cs); tasklist.queue:stop() end)
+
+ -- Signals setup
+ --------------------------------------------------------------------------------
+ local client_signals = {
+ "property::urgent", "property::sticky", "property::minimized",
+ "property::name", " property::icon", "property::skip_taskbar",
+ "property::screen", "property::hidden",
+ "tagged", "untagged", "list", "focus", "unfocus"
+ }
+
+ local tag_signals = { "property::selected", "property::activated" }
+
+ -- for _, sg in ipairs(client_signals) do client.connect_signal(sg, update) end
+ -- for _, sg in ipairs(tag_signals) do tag.attached_connect_signal(cs, sg, update) end
+ for _, sg in ipairs(client_signals) do client.connect_signal(sg, function() tasklist.queue:again() end) end
+ for _, sg in ipairs(tag_signals) do tag.attached_connect_signal(cs, sg, function() tasklist.queue:again() end) end
+
+ -- force hide pop-up widgets if any client was closed
+ -- because last vars may be no actual anymore
+ client.connect_signal("unmanage",
+ function()
+ tasklist_update()
+ redtasklist.tasktip.wibox.visible = false
+ redtasklist.winmenu.menu:hide()
+ last.client = nil
+ last.group = nil
+ end
+ )
+
+ -- Construct
+ --------------------------------------------------------------------------------
+ update()
+
+ return tasklist
+end
+
+-- Mouse action functions
+-----------------------------------------------------------------------------------------------------------------------
+
+-- focus/minimize
+function redtasklist.action.select(args)
+ args = args or {}
+ local state = get_state(args.group)
+
+ if state.focus then
+ for _, c in ipairs(args.group) do c.minimized = true end
+ else
+ if state.minimized then
+ for _, c in ipairs(args.group) do c.minimized = false end
+ end
+
+ client.focus = args.group[1]
+ args.group[1]:raise()
+ end
+end
+
+-- close all in group
+function redtasklist.action.close(args)
+ args = args or {}
+ for _, c in ipairs(args.group) do c:kill() end
+end
+
+-- show/close winmenu
+function redtasklist.action.menu(args)
+ args = args or {}
+ redtasklist.winmenu:show(args.group, args.gap)
+end
+
+-- switch to next task
+function redtasklist.action.switch_next()
+ switch_focus(last.screen_clients[mouse.screen])
+end
+
+-- switch to previous task
+function redtasklist.action.switch_prev()
+ switch_focus(last.screen_clients[mouse.screen], true)
+end
+
+
+-- Filtering functions
+-- @param c The client
+-- @param screen The screen we are drawing on
+-----------------------------------------------------------------------------------------------------------------------
+
+-- To include all clients
+--------------------------------------------------------------------------------
+function redtasklist.filter.allscreen()
+ return true
+end
+
+-- To include the clients from all tags on the screen
+--------------------------------------------------------------------------------
+function redtasklist.filter.alltags(c, screen)
+ return c.screen == screen
+end
+
+-- To include only the clients from currently selected tags
+--------------------------------------------------------------------------------
+function redtasklist.filter.currenttags(c, screen)
+ if c.screen ~= screen then return false end
+ if c.sticky then return true end
+
+ local tags = screen.tags
+
+ for _, t in ipairs(tags) do
+ if t.selected then
+ local ctags = c:tags()
+
+ for _, v in ipairs(ctags) do
+ if v == t then return true end
+ end
+ end
+ end
+
+ return false
+end
+
+-- To include only the minimized clients from currently selected tags
+--------------------------------------------------------------------------------
+function redtasklist.filter.minimizedcurrenttags(c, screen)
+ if c.screen ~= screen then return false end
+ if not c.minimized then return false end
+ if c.sticky then return true end
+
+ local tags = screen.tags
+
+ for _, t in ipairs(tags) do
+ if t.selected then
+ local ctags = c:tags()
+
+ for _, v in ipairs(ctags) do
+ if v == t then return true end
+ end
+ end
+ end
+
+ return false
+end
+
+-- To include only the currently focused client
+--------------------------------------------------------------------------------
+function redtasklist.filter.focused(c, screen)
+ return c.screen == screen and client.focus == c
+end
+
+-- Config metatable to call redtasklist module as function
+-----------------------------------------------------------------------------------------------------------------------
+function redtasklist.mt:__call(...)
+ return redtasklist.new(...)
+end
+
+return setmetatable(redtasklist, redtasklist.mt)
diff --git a/awesome/.config/awesome/redflat/widget/textclock.lua b/awesome/.config/awesome/redflat/widget/textclock.lua
new file mode 100644
index 0000000..69cf34b
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/textclock.lua
@@ -0,0 +1,80 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat clock widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Text clock widget with date in tooltip (optional)
+-----------------------------------------------------------------------------------------------------------------------
+-- Some code was taken from
+------ awful.widget.textclock v3.5.2
+------ (c) 2009 Julien Danjou
+-----------------------------------------------------------------------------------------------------------------------
+
+local setmetatable = setmetatable
+local os = os
+local textbox = require("wibox.widget.textbox")
+local beautiful = require("beautiful")
+local gears = require("gears")
+
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local textclock = { mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ font = "Sans 12",
+ tooltip = {},
+ color = { text = "#aaaaaa" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.textclock") or {})
+end
+
+-- Create a textclock widget. It draws the time it is in a textbox.
+-- @param format The time format. Default is " %a %b %d, %H:%M ".
+-- @param timeout How often update the time. Default is 60.
+-- @return A textbox widget
+-----------------------------------------------------------------------------------------------------------------------
+function textclock.new(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local timeformat = args.timeformat or " %a %b %d, %H:%M "
+ local timeout = args.timeout or 60
+ style = redutil.table.merge(default_style(), style or {})
+
+ -- Create widget
+ --------------------------------------------------------------------------------
+ local widg = textbox()
+ widg:set_font(style.font)
+
+ -- Set tooltip if need
+ --------------------------------------------------------------------------------
+ local tp
+ if args.dateformat then tp = tooltip({ objects = { widg } }, style.tooltip) end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ local timer = gears.timer({ timeout = timeout })
+ timer:connect_signal("timeout",
+ function()
+ widg:set_markup('' .. os.date(timeformat) .. "")
+ if args.dateformat then tp:set_text(os.date(args.dateformat)) end
+ end)
+ timer:start()
+ timer:emit_signal("timeout")
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Config metatable to call textclock module as function
+-----------------------------------------------------------------------------------------------------------------------
+function textclock.mt:__call(...)
+ return textclock.new(...)
+end
+
+return setmetatable(textclock, textclock.mt)
diff --git a/awesome/.config/awesome/redflat/widget/updates.lua b/awesome/.config/awesome/redflat/widget/updates.lua
new file mode 100644
index 0000000..779a2e0
--- /dev/null
+++ b/awesome/.config/awesome/redflat/widget/updates.lua
@@ -0,0 +1,413 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- RedFlat updates widget --
+-----------------------------------------------------------------------------------------------------------------------
+-- Show if system updates available using apt-get
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+-----------------------------------------------------------------------------------------------------------------------
+local setmetatable = setmetatable
+local table = table
+local string = string
+local os = os
+local unpack = unpack or table.unpack
+
+local beautiful = require("beautiful")
+local wibox = require("wibox")
+local awful = require("awful")
+local timer = require("gears.timer")
+
+local rednotify = require("redflat.float.notify")
+local tooltip = require("redflat.float.tooltip")
+local redutil = require("redflat.util")
+local svgbox = require("redflat.gauge.svgbox")
+local separator = require("redflat.gauge.separator")
+local redtip = require("redflat.float.hotkeys")
+local startup = require("redflat.startup")
+
+-- Initialize tables for module
+-----------------------------------------------------------------------------------------------------------------------
+-- TODO: weak table for all multi panel widget
+local updates = { objects = {}, mt = {} }
+
+-- Generate default theme vars
+-----------------------------------------------------------------------------------------------------------------------
+local function default_style()
+ local style = {
+ wibox = {
+ geometry = { width = 400, height = 200 },
+ border_width = 2,
+ title_font = "Sans 14 bold",
+ tip_font = "Sans 10",
+ set_position = nil,
+ separator = {},
+ shape = nil,
+ icon = {
+ package = redutil.base.placeholder(),
+ close = redutil.base.placeholder({ txt = "X" }),
+ daily = redutil.base.placeholder(),
+ weekly = redutil.base.placeholder(),
+ normal = redutil.base.placeholder(),
+ silent = redutil.base.placeholder(),
+ },
+ height = { title = 40, state = 50, tip = 20 },
+ margin = { close = { 0, 0, 0, 0 }, state = { 0, 0, 0, 0 }, title = { 0, 0, 0, 0 }, image = { 0, 0, 0, 0 } }
+ },
+ icon = redutil.base.placeholder(),
+ keytip = { geometry = { width = 400 } },
+ notify = {},
+ firstrun = false,
+ need_notify = true,
+ tooltip = {
+ base = {},
+ state = {
+ timeout = 3,
+ set_position = function(w) awful.placement.under_mouse(w) w.y = w.y - 30 end,
+ }
+ },
+ color = { main = "#b1222b", icon = "#a0a0a0", wibox = "#202020", border = "#575757", gray = "#404040",
+ urgent = "#32882d" }
+ }
+ return redutil.table.merge(style, redutil.table.check(beautiful, "widget.updates") or {})
+end
+
+
+local STATE = setmetatable(
+ { keywords = { "NORMAL", "DAILY", "WEEKLY", "SILENT" } },
+ { __index = function(table_, key)
+ return awful.util.table.hasitem(table_.keywords, key) or rawget(table_, key)
+ end }
+)
+
+local tips = {}
+tips[STATE.NORMAL] = "regular notifications"
+tips[STATE.DAILY] = "postponed for a day"
+tips[STATE.WEEKLY] = "postponed for a week"
+tips[STATE.SILENT] = "notifications disabled"
+
+-- key bindings
+updates.keys = {}
+updates.keys.control = {
+ {
+ {}, "1", function() updates.set_mode(STATE.NORMAL) end,
+ { description = "Regular notifications", group = "Notifications" }
+ },
+ {
+ {}, "2", function() updates.set_mode(STATE.DAILY) end,
+ { description = "Postponed for a day", group = "Notifications" }
+ },
+ {
+ {}, "3", function() updates.set_mode(STATE.WEEKLY) end,
+ { description = "Postponed for a week", group = "Notifications" }
+ },
+ {
+ {}, "4", function() updates.set_mode(STATE.SILENT) end,
+ { description = "Notifications disabled", group = "Notifications" }
+ },
+}
+updates.keys.action = {
+ {
+ {}, "u", function() updates:update(true) end,
+ { description = "Check updates", group = "Action" }
+ },
+ {
+ {}, "Escape", function() updates:hide() end,
+ { description = "Close updates widget", group = "Action" }
+ },
+ {
+ { "Mod4" }, "F1", function() redtip:show() end,
+ { description = "Show hotkeys helper", group = "Action" }
+ },
+}
+
+updates.keys.all = awful.util.table.join(updates.keys.control, updates.keys.action)
+
+
+-- Initialize notify widbox
+-----------------------------------------------------------------------------------------------------------------------
+function updates:init(args, style)
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ args = args or {}
+ local update_timeout = args.update_timeout or 3600
+ local command = args.command or "echo 0"
+ local force_notify = false
+ style = redutil.table.merge(default_style(), style or {})
+
+
+ self.style = style
+ self.is_updates = false
+ self.config = awful.util.getdir("cache") .. "/updates"
+
+ -- Create floating wibox for updates widget
+ --------------------------------------------------------------------------------
+ self.wibox = wibox({
+ ontop = true,
+ bg = style.color.wibox,
+ shape = style.shape,
+ border_width = style.wibox.border_width,
+ border_color = style.color.border
+ })
+
+ self.wibox:geometry(style.wibox.geometry)
+
+ -- Floating widget structure
+ --------------------------------------------------------------------------------
+
+ -- main image
+ self.packbox = svgbox(style.wibox.icon.package, nil, style.color.icon)
+
+ -- titlebar
+ self.titlebox = wibox.widget.textbox("0 UPDATES")
+ self.titlebox:set_font(style.wibox.title_font)
+ self.titlebox:set_align("center")
+
+ -- tip line
+ --self.tipbox = wibox.widget.textbox()
+ --self.tipbox:set_font(style.wibox.tip_font)
+ --self.tipbox:set_align("center")
+ --self.tipbox:set_forced_height(style.wibox.height.tip)
+
+ -- close button
+ local closebox = svgbox(style.wibox.icon.close, nil, style.color.icon)
+ closebox:buttons(awful.util.table.join(awful.button({}, 1, function() self:hide() end)))
+ closebox:connect_signal("mouse::enter", function() closebox:set_color(style.color.main) end)
+ closebox:connect_signal("mouse::leave", function() closebox:set_color(style.color.icon) end)
+
+ -- Control buttons
+ ------------------------------------------------------------
+ local statebox = {}
+ local statearea = wibox.layout.flex.horizontal()
+ statearea:set_forced_height(style.wibox.height.state)
+
+ -- color update fucntions
+ local function update_state()
+ for k, box in pairs(statebox) do
+ box:set_color(STATE[k] == self.state and style.color.main or style.color.gray)
+ end
+ --self.tipbox:set_markup(string.format('%s', style.color.gray, tips[self.state]))
+ end
+
+ local function check_alert()
+ local time = os.time()
+ return self.is_updates and
+ ( self.state == STATE.NORMAL
+ or self.state == STATE.DAILY and (time - self.time > 24 * 3600)
+ or self.state == STATE.WEEKLY and (time - self.time > 7 * 24 * 3600))
+ end
+
+ local function update_widget_colors()
+ local is_alert = check_alert()
+ local color = is_alert and style.color.main or style.color.icon
+ for _, w in ipairs(updates.objects) do w:set_color(color) end
+ end
+
+ -- create control buttons
+ function self.set_mode(state)
+ if self.state ~= state then
+ self.state = state
+ self.time = (state == STATE.DAILY or state == STATE.WEEKLY) and os.time() or 0
+ update_state()
+ update_widget_colors()
+ end
+ end
+
+ for state, k in pairs(STATE.keywords) do
+ statebox[k] = svgbox(style.wibox.icon[k:lower()], nil, style.color.gray)
+ local tp = tooltip({ objects = { statebox[k] } }, style.tooltip.state)
+ tp:set_text(tips[state])
+
+ statebox[k]:buttons(awful.util.table.join(
+ awful.button({}, 1, function() self.set_mode(state) end)
+ ))
+
+ local area = wibox.layout.align.horizontal()
+ area:set_middle(statebox[k])
+ area:set_expand("outside")
+
+ statearea:add(area)
+ end
+
+ -- Setup wibox layouts
+ ------------------------------------------------------------
+ local titlebar = wibox.widget({
+ nil,
+ self.titlebox,
+ wibox.container.margin(closebox, unpack(style.wibox.margin.close)),
+ forced_height = style.wibox.height.title,
+ layout = wibox.layout.align.horizontal
+ })
+
+ self.wibox:setup({
+ {
+ nil,
+ wibox.container.margin(titlebar, unpack(style.wibox.margin.title)),
+ separator.horizontal(style.wibox.separator),
+ layout = wibox.layout.align.vertical
+ },
+ {
+ nil,
+ {
+ nil, wibox.container.margin(self.packbox, unpack(style.wibox.margin.image)), nil,
+ expand = "outside",
+ layout = wibox.layout.align.horizontal
+ },
+ --self.tipbox,
+ nil,
+ layout = wibox.layout.align.vertical
+ },
+ wibox.container.margin(statearea, unpack(style.wibox.margin.state)),
+ layout = wibox.layout.align.vertical
+ })
+
+ -- Widget keygrabber
+ --------------------------------------------------------------------------------
+ self.keygrabber = function(mod, key, event)
+ if event ~= "press" then return end
+ for _, k in ipairs(self.keys.all) do
+ if redutil.key.match_grabber(k, mod, key) then k[3](); return end
+ end
+ end
+
+ -- Start up setup
+ ------------------------------------------------------------
+ self:load_state()
+ self:set_keys()
+ update_state()
+
+ -- Set tooltip
+ --------------------------------------------------------------------------------
+ self.tp = tooltip(nil, style.tooltip.base)
+ self.tp:set_text("?")
+
+ -- Update info function
+ --------------------------------------------------------------------------------
+ local function update_count(output)
+ local c = string.match(output, "(%d+)")
+
+ self.is_updates = tonumber(c) > 0
+ local is_alert = check_alert()
+
+ if style.need_notify and (is_alert or force_notify) then
+ rednotify:show(redutil.table.merge({ text = c .. " updates available" }, style.notify))
+ end
+ self.titlebox:set_text(c .. " UPDATES")
+ self.packbox:set_color(tonumber(c) > 0 and style.color.main or style.color.icon)
+
+ if self.tp then self.tp:set_text(c .. " updates") end
+ update_widget_colors()
+ end
+
+ -- Set update timer
+ --------------------------------------------------------------------------------
+ self.check_updates = function(is_force)
+ force_notify = is_force
+ awful.spawn.easy_async_with_shell(command, update_count)
+ end
+
+ updates.timer = timer({ timeout = update_timeout })
+ updates.timer:connect_signal("timeout", function() self.check_updates() end)
+ updates.timer:start()
+
+ if style.firstrun and startup.is_startup then updates.timer:emit_signal("timeout") end
+
+ -- Connect additional signals
+ ------------------------------------------------------------
+ awesome.connect_signal("exit", function() self:save_state() end)
+end
+
+-- Create a new updates widget
+-- @param style Table containing colors and geometry parameters for all elemets
+-----------------------------------------------------------------------------------------------------------------------
+function updates.new(style)
+
+ if not updates.wibox then updates:init({}) end
+
+ -- Initialize vars
+ --------------------------------------------------------------------------------
+ style = redutil.table.merge(updates.style, style or {})
+
+ local widg = svgbox(style.icon)
+ widg:set_color(style.color.icon)
+ table.insert(updates.objects, widg)
+
+ updates.tp:add_to_object(widg)
+
+ --------------------------------------------------------------------------------
+ return widg
+end
+
+-- Show/hide updates wibox
+-----------------------------------------------------------------------------------------------------------------------
+function updates:show()
+ if self.style.wibox.set_position then
+ self.style.wibox.set_position(self.wibox)
+ else
+ redutil.placement.centered(self.wibox, nil, mouse.screen.workarea)
+ end
+ redutil.placement.no_offscreen(self.wibox, self.style.screen_gap, screen[mouse.screen].workarea)
+
+ self.wibox.visible = true
+ awful.keygrabber.run(self.keygrabber)
+ redtip:set_pack("System updates", self.tip, self.style.keytip.column, self.style.keytip.geometry)
+end
+
+function updates:hide()
+ self.wibox.visible = false
+ awful.keygrabber.stop(self.keygrabber)
+ redtip:remove_pack()
+end
+
+function updates:toggle()
+ if self.wibox.visible then
+ self:hide()
+ else
+ self:show()
+ end
+end
+
+-- Save/restore state between sessions
+-----------------------------------------------------------------------------------------------------------------------
+function updates:load_state()
+ local info = redutil.read.file(self.config)
+ if info then
+ local state, time = string.match(info, "(%d)=(%d+)")
+ self.state, self.time = tonumber(state), tonumber(time)
+ else
+ self.state = STATE.NORMAL
+ self.time = 0
+ end
+end
+
+function updates:save_state()
+ local file = io.open(self.config, "w")
+ file:write(string.format("%d=%d", self.state, self.time))
+ file:close()
+end
+
+-- Set user hotkeys
+-----------------------------------------------------------------------------------------------------------------------
+function updates:set_keys(keys, layout)
+ layout = layout or "all"
+ if keys then
+ self.keys[layout] = keys
+ if layout ~= "all" then self.keys.all = awful.util.table.join(self.keys.control, self.keys.action) end
+ end
+
+ self.tip = self.keys.all
+end
+
+-- Update updates info for every widget
+-----------------------------------------------------------------------------------------------------------------------
+function updates:update(is_force)
+ self.check_updates(is_force)
+end
+
+-- Config metatable to call updates module as function
+-----------------------------------------------------------------------------------------------------------------------
+function updates.mt:__call(...)
+ return updates.new(...)
+end
+
+return setmetatable(updates, updates.mt)
diff --git a/awesome/.config/awesome/revelation/LICENSE b/awesome/.config/awesome/revelation/LICENSE
deleted file mode 100644
index 65c5ca8..0000000
--- a/awesome/.config/awesome/revelation/LICENSE
+++ /dev/null
@@ -1,165 +0,0 @@
- GNU LESSER GENERAL PUBLIC LICENSE
- Version 3, 29 June 2007
-
- Copyright (C) 2007 Free Software Foundation, Inc.
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-
- This version of the GNU Lesser General Public License incorporates
-the terms and conditions of version 3 of the GNU General Public
-License, supplemented by the additional permissions listed below.
-
- 0. Additional Definitions.
-
- As used herein, "this License" refers to version 3 of the GNU Lesser
-General Public License, and the "GNU GPL" refers to version 3 of the GNU
-General Public License.
-
- "The Library" refers to a covered work governed by this License,
-other than an Application or a Combined Work as defined below.
-
- An "Application" is any work that makes use of an interface provided
-by the Library, but which is not otherwise based on the Library.
-Defining a subclass of a class defined by the Library is deemed a mode
-of using an interface provided by the Library.
-
- A "Combined Work" is a work produced by combining or linking an
-Application with the Library. The particular version of the Library
-with which the Combined Work was made is also called the "Linked
-Version".
-
- The "Minimal Corresponding Source" for a Combined Work means the
-Corresponding Source for the Combined Work, excluding any source code
-for portions of the Combined Work that, considered in isolation, are
-based on the Application, and not on the Linked Version.
-
- The "Corresponding Application Code" for a Combined Work means the
-object code and/or source code for the Application, including any data
-and utility programs needed for reproducing the Combined Work from the
-Application, but excluding the System Libraries of the Combined Work.
-
- 1. Exception to Section 3 of the GNU GPL.
-
- You may convey a covered work under sections 3 and 4 of this License
-without being bound by section 3 of the GNU GPL.
-
- 2. Conveying Modified Versions.
-
- If you modify a copy of the Library, and, in your modifications, a
-facility refers to a function or data to be supplied by an Application
-that uses the facility (other than as an argument passed when the
-facility is invoked), then you may convey a copy of the modified
-version:
-
- a) under this License, provided that you make a good faith effort to
- ensure that, in the event an Application does not supply the
- function or data, the facility still operates, and performs
- whatever part of its purpose remains meaningful, or
-
- b) under the GNU GPL, with none of the additional permissions of
- this License applicable to that copy.
-
- 3. Object Code Incorporating Material from Library Header Files.
-
- The object code form of an Application may incorporate material from
-a header file that is part of the Library. You may convey such object
-code under terms of your choice, provided that, if the incorporated
-material is not limited to numerical parameters, data structure
-layouts and accessors, or small macros, inline functions and templates
-(ten or fewer lines in length), you do both of the following:
-
- a) Give prominent notice with each copy of the object code that the
- Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the object code with a copy of the GNU GPL and this license
- document.
-
- 4. Combined Works.
-
- You may convey a Combined Work under terms of your choice that,
-taken together, effectively do not restrict modification of the
-portions of the Library contained in the Combined Work and reverse
-engineering for debugging such modifications, if you also do each of
-the following:
-
- a) Give prominent notice with each copy of the Combined Work that
- the Library is used in it and that the Library and its use are
- covered by this License.
-
- b) Accompany the Combined Work with a copy of the GNU GPL and this license
- document.
-
- c) For a Combined Work that displays copyright notices during
- execution, include the copyright notice for the Library among
- these notices, as well as a reference directing the user to the
- copies of the GNU GPL and this license document.
-
- d) Do one of the following:
-
- 0) Convey the Minimal Corresponding Source under the terms of this
- License, and the Corresponding Application Code in a form
- suitable for, and under terms that permit, the user to
- recombine or relink the Application with a modified version of
- the Linked Version to produce a modified Combined Work, in the
- manner specified by section 6 of the GNU GPL for conveying
- Corresponding Source.
-
- 1) Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (a) uses at run time
- a copy of the Library already present on the user's computer
- system, and (b) will operate properly with a modified version
- of the Library that is interface-compatible with the Linked
- Version.
-
- e) Provide Installation Information, but only if you would otherwise
- be required to provide such information under section 6 of the
- GNU GPL, and only to the extent that such information is
- necessary to install and execute a modified version of the
- Combined Work produced by recombining or relinking the
- Application with a modified version of the Linked Version. (If
- you use option 4d0, the Installation Information must accompany
- the Minimal Corresponding Source and Corresponding Application
- Code. If you use option 4d1, you must provide the Installation
- Information in the manner specified by section 6 of the GNU GPL
- for conveying Corresponding Source.)
-
- 5. Combined Libraries.
-
- You may place library facilities that are a work based on the
-Library side by side in a single library together with other library
-facilities that are not Applications and are not covered by this
-License, and convey such a combined library under terms of your
-choice, if you do both of the following:
-
- a) Accompany the combined library with a copy of the same work based
- on the Library, uncombined with any other library facilities,
- conveyed under the terms of this License.
-
- b) Give prominent notice with the combined library that part of it
- is a work based on the Library, and explaining where to find the
- accompanying uncombined form of the same work.
-
- 6. Revised Versions of the GNU Lesser General Public License.
-
- The Free Software Foundation may publish revised and/or new versions
-of the GNU Lesser General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
-Library as you received it specifies that a certain numbered version
-of the GNU Lesser General Public License "or any later version"
-applies to it, you have the option of following the terms and
-conditions either of that published version or of any later version
-published by the Free Software Foundation. If the Library as you
-received it does not specify a version number of the GNU Lesser
-General Public License, you may choose any version of the GNU Lesser
-General Public License ever published by the Free Software Foundation.
-
- If the Library as you received it specifies that a proxy can decide
-whether future versions of the GNU Lesser General Public License shall
-apply, that proxy's public statement of acceptance of any version is
-permanent authorization for you to choose that version for the
-Library.
diff --git a/awesome/.config/awesome/revelation/README.md b/awesome/.config/awesome/revelation/README.md
deleted file mode 100644
index df3c259..0000000
--- a/awesome/.config/awesome/revelation/README.md
+++ /dev/null
@@ -1,169 +0,0 @@
-# revelation.lua
-
-Provides Mac OSX like 'Expose' view of all clients.
-
-This is a fork from [revelation](https://github.com/bioe007/awesome-revelation)
-It is modified from the original revelation.lua for incorporating with awesome 3.5 or later.
-It also have some features.
-
-
-**Now master branch works for both master and stable awesome WM**
-
-## Changes since 2015-09-26
-When all clients are exposing, you can zoom (__Modkey + Shift + hintbox charater__ or __right button__ of the mouse)
-or kill a client (__middle button__ of the mouse) and the position of hintboxes will be updated accordingly.
-
-## Changes since 2014-02-19
-* Now the revlation is able to handle the special clients(float, fullscreen or maximized etc.)
-* When you select an minimized client, the revelation will un-minimized it and then focuse on it.
-* Added an option to change character ordering
-
-## Changes after 2013-12-30
-* Now it is possible, in revelation.init({...}), to change the default settings of
- revelation module.
-
-* Function `revelation(...)` now accept the parameter as a table `{rule={...}, is_excluded=...,
-curr_tag_only=...}`.
-
-1. To add specify rules `revelation({rule={...},...})`.
-2. To exclude the clients matched by the rules instead of including `revelation({rule={...},
-is_excluded=true})`.
-3. `{...,curr_tag_only=true}` make the revelation only collect the client from current
- tags.
-
-
-## Changes from the original revelation
-* Support awesome 3.5 or later
-
-* Add the support of multiple screens. Now multiple 'Expose' views will be shown
- on the multiple screens at the same time.
-
-* The way of selecting and focusing the client was changed. The old way that is
- navigating clients by pressing the keys "j, h, k, l" and then selecting the
- client by pressing key "Enter" was deprecated. Now each client in the 'Expose'
- views come with a letter surrounding by a hint box, you can select the client
- by pressing the corresponding letter in the hint box. The idea and codes of this method
- was copied from the module [hint](https://github.com/zackpete/hints).
-
-* Add zoom mode. Add the function of zooming the client by pressing the right
- button of the mouse.
-
-* The unwanted clients can be excluded by the parameter`{rule={...}....}`.
-
-## Screenshot
-
-![screenshot](./screenshot.png)
-
-
-## Usage
-
-### Installation
- (From user's awesome configuration directory, usually ~/.config/awesome)
-
- 1. Clone the repository:
-
- git clone https://github.com/guotsuan/awesome-revelation revelation
-
- 2. Include it at the top of your rc.lua file:
- `local revelation=require("revelation")`
-
- 3. **Important: Add `revelation.init()` after `beautiful.init()`**
-
- 3. Define a global keybinding (e. g. `ModKey + e`) for revelation in your rc.lua:
-
- globalkeys = awful.util.table.join(
- awful.key({ modkey, }, "Left", awful.tag.viewprev ),
- awful.key({ modkey, }, "Right", awful.tag.viewnext ),
- awful.key({ modkey, }, "Escape", awful.tag.history.restore),
- awful.key({ modkey, }, "e", revelation),
- awful.key({ modkey, }, "j",
- function ()
- awful.client.focus.byidx( 1)
- if client.focus then client.focus:raise() end
- end),
-
- **NOTE:** Always double check the key binding syntax against the version of
- Awesome which you are using.
-
- 4. Restart Awesome (usually __Modkey + Control + r__) and try the keybinding __Modkey + e__.
-
- It should bring up all clients from the current tags on all screens and set the layout to fair.
- You can focus clients with the __cursor__ keys, and then press the __left__ button to select,
- or you can directly focus a client by pressing the corresponding key shown in the hint box.
- Press the right mouse button to zoom the client or __Escape__ to abort.
-
-### Configuration
- Revelation's configuration is done through the init() function
-
- There are three basic settings, shown with default values:
-
- -- The name of the tag created for the 'exposed' view
- revelation.tag_name = 'Revelation'
-
- -- A table of matcher functions (used in client filtering)
- revelation.exact = awful.rules.match
- revelation.any = awful.rules.match_any
-
- -- Character order for selecting clients
- revelation.charorder = "jkluiopyhnmfdsatgvcewqzx1234567890",
-
- The rule matching functions must conform to `awful.rules.match` prototypes.
-
- For client matching rules, we follow the same syntax as awful.rules expects.
- If `rule.any == true`, then we call the `config.match.any` function.
-
-to change the settings, use:
-
- revelation.init({tag_name = ..., match = {...}, charorder = ...})
-
-
-### Examples
- All clients:
-
- awful.key({modkey}, "e", revelation)
-
- To match all urxvt terminals:
-
- awful.key({modkey}, "e", function()
- revelation({rule={class="URxvt"}})
- end)
- To match clients with class 'foo' or 'bar':
-
- awful.key({modkey}, "e", function()
- revelation({
- rule{class={"foo", "bar"},
- any=true}
- })
- end)
-
- To exclude the clients, we set:
-
- awful.key({modkey}, "e", function()
- revelation({rule={class="conky"}, is_excluded=true})
- end)
-
- To set only collect clients from current tag
-
- awful.key({modkey}, "e", function()
- revelation({rule={class="conky"}, is_excluded=true,
- curr_tag_only=true})
- end)
-
-## Credits
-
-### Maintenance
- * Quan Guo
- * Perry Hargrave
-
-### Contributions, many thanks!
- * Daniel Hahler
- * Yauhen Kirylau
- * Nikola Petrov
-
-### Original authors
- * Espen Wiborg
- * Julien Danjou
-
- (c) 20013-2014 Quan Guo
- (c) 2009-12 Perry Hargrave
- (c) 2008 Espen Wiborg, Julien Danjou
diff --git a/awesome/.config/awesome/revelation/init.lua b/awesome/.config/awesome/revelation/init.lua
deleted file mode 100644
index 964d60c..0000000
--- a/awesome/.config/awesome/revelation/init.lua
+++ /dev/null
@@ -1,508 +0,0 @@
--- revelation.lua
---
--- Library that implements Expose like behavior.
---
--- @author Perry Hargrave resixian@gmail.com
--- @author Espen Wiborg espenhw@grumblesmurf.org
--- @author Julien Danjou julien@danjou.info
--- @auther Quan Guo guotsuan@gmail.com
---
--- @copyright 2008 Espen Wiborg, Julien Danjou
--- @copyright 2015 Quan Guo
---
-
-
-local beautiful = require("beautiful")
-local wibox = require("wibox")
-local awful = require('awful')
-local aw_rules = require('awful.rules')
-local pairs = pairs
-local setmetatable = setmetatable
-local naughty = require("naughty")
-local table = table
-local clock = os.clock
-local tostring = tostring
-local capi = {
- awesome = awesome,
- tag = tag,
- client = client,
- keygrabber = keygrabber,
- mousegrabber = mousegrabber,
- mouse = mouse,
- screen = screen
-}
-
--- disable for now.
--- It seems there is not way to pass err handling function into the delayed_call()
-
-local function debuginfo(message)
- message = message or "No information available"
- nid = naughty.notify({ text = tostring(message), timeout = 10 })
-end
-
-local delayed_call = (type(timer) ~= 'table' and require("gears.timer").delayed_call)
-
-local view_only_func
-local toggle_tag_func
-local jump_to_func
-
-
-if type(awful.client.object) == 'table' then
- view_only_func = function (tag) tag:view_only() end
- toggle_tag_func = function (t, c) c:toggle_tag(t) end
- jump_to_func = function(c) c:jump_to() end
-else
- view_only_func = function (tag) awful.tag.viewonly(tag) end
- toggle_tag_func = function (t, c) awful.client.toggletag(t, c) end
- jump_to_func = function(c) awful.client.jumpto(c) end
-end
-
-
-local hintbox = {} -- Table of letter wiboxes with characters as the keys
-local hintindex = {} -- Table of visible clients with the hint letter as the keys
-
-local clients = {} --Table of clients to be exposed after fitlering
-local clientData = {} -- table that holds the positions and sizes of floating clients
-
-local revelation = {
- -- Name of expose tag.
- tag_name = "Revelation",
-
- charorder = "jkluiopyhnmfdsatgvcewqzx1234567890",
-
- -- Match function can be defined by user.
- -- Must accept a `rule` and `client` and return `boolean`.
- -- The rule forms follow `awful.rules` syntax except we also check the
- -- special `rule.any` key. If its true, then we use the `match.any` function
- -- for comparison.
- match = {
- exact = aw_rules.match,
- any = aw_rules.match_any
- },
- property_to_watch={
- minimized = false,
- fullscreen = false,
- maximized_horizontal = false,
- maximized_vertical = false,
- sticky = false,
- ontop = false,
- above = false,
- below = false,
- },
- tags_status = {},
- is_excluded = false,
- curr_tag_only = false,
- font = "monospace 20",
- fg = beautiful.revelation_fg_normal or beautiful.fg_normal or "#DCDCCC",
- bg = beautiful.revelation_bg_normal or beautiful.bg_normal or "#000000",
- border_color = beautiful.revelation_border_color or beautiful.border_focus or "#DCDCCC",
- border_width = beautiful.revelation_border_width or beautiful.border_width or 2,
- hintsize = (type(beautiful.xresources) == 'table' and beautiful.xresources.apply_dpi(beautiful.revelation_hintsize or 50) or 60)
-}
-
-
-
--- Executed when user selects a client from expose view.
---
--- @param restore Function to reset the current tags view.
-local function selectfn(_, t, zt)
- return function(c)
- revelation.restore(t, zt)
- -- Focus and raise
- --
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
-
- if awful.util.table.hasitem(hintindex, c) then
- if c.minimized then
- c.minimized = false
- end
-
- jump_to_func(c)
- end
- end
-end
-
--- Tags all matching clients with tag t
--- @param rule The rule. Conforms to awful.rules syntax.
--- @param clients A table of clients to check.
--- @param t The tag to give matching clients.
-local function match_clients(rule, _clients, t, is_excluded)
-
- local mfc = rule.any and revelation.match.any or revelation.match.exact
- local mf = is_excluded and function(c,_rule) return not mfc(c,_rule) end or mfc
- local flt
-
- for _, c in pairs(_clients) do
- if mf(c, rule) then
- -- Store geometry before setting their tags
- clientData[c] = {}
- clientData[c]["geometry"] = c:geometry()
- flt = awful.client.property.get(c, "floating")
- if flt ~= nil then
- clientData[c]["floating"] = flt
- awful.client.property.set(c, "floating", false)
- end
-
-
- for k,v in pairs(revelation.property_to_watch) do
- clientData[c][k] = c[k]
- c[k] = v
-
- end
- toggle_tag_func(t, c)
- if c:isvisible() then
- table.insert(clients, c)
- end
- end
- end
-
-end
-
-
--- Implement Exposé (ala Mac OS X).
---
--- @param rule A table with key and value to match. [{class=""}]
-function revelation.expose(args)
- args = args or {}
- local rule = args.rule or {}
- local is_excluded = args.is_excluded or revelation.is_excluded
- local curr_tag_only = args.curr_tag_only or revelation.curr_tag_only
-
- local t={}
- local zt={}
-
- clients = {}
- clientData = {}
-
- for scr=1,capi.screen.count() do
- t[scr] = awful.tag.new({revelation.tag_name},
- scr, awful.layout.suit.fair)[1]
- zt[scr] = awful.tag.new({revelation.tag_name.."_zoom"},
- scr, awful.layout.suit.fair)[1]
-
- if curr_tag_only then
- match_clients(rule, awful.client.visible(scr), t[scr], is_excluded)
- else
- match_clients(rule, capi.client.get(scr), t[scr], is_excluded)
- end
-
- view_only_func(t[scr])
- end
-
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- -- No need for awesome WM 3.5.6: capi.awesome.emit_signal("refresh")
- --
- local status, err=pcall(revelation.expose_callback, t, zt, clients)
-
- --revelation.expose_callback(t, zt)
- if not status then
- debuginfo('Oops!, something is wrong in revelation.expose_callback!')
-
- if err.msg then
- debuginfo(err.msg)
- end
-
- if err.code then
- debuginfo('error code is '.. tostring(err.code))
- end
-
- revelation.restore(t, zt)
-
- end
-end
-
-
-function revelation.restore(t, zt)
- for scr=1, capi.screen.count() do
- awful.tag.history.restore(scr)
- t[scr].screen = nil
- end
-
- capi.keygrabber.stop()
- capi.mousegrabber.stop()
-
- for _, c in pairs(clients) do
- if clientData[c] then
- for k,v in pairs(clientData[c]) do
- if v ~= nil then
- if k== "geometry" then
- c:geometry(v)
- elseif k == "floating" then
- awful.client.property.set(c, "floating", v)
- else
- c[k]=v
- end
- end
- end
- end
- end
-
- for scr=1, capi.screen.count() do
- t[scr].activated = false
- zt[scr].activated = false
- end
-
- for i,j in pairs(hintindex) do
- hintbox[i].visible = false
- end
-end
-
-local function hintbox_display_toggle(c, show)
- for char, thisclient in pairs(hintindex) do
- if char and char ~= c then
- hintindex[char] = thisclient
- if show then
- hintbox[char].visible = true
- else
- hintbox[char].visible = false
- end
-
- end
- end
-end
-
-local function hintbox_pos(char)
- local client = hintindex[char]
- local geom = client:geometry()
- hintbox[char].x = math.floor(geom.x + geom.width/2 - revelation.hintsize/2)
- hintbox[char].y = math.floor(geom.y + geom.height/2 - revelation.hintsize/2)
-end
-
-
-function revelation.expose_callback(t, zt, clientlist)
-
- hintindex = {}
- for i,thisclient in pairs(clientlist) do
- -- Move wiboxes to center of visible windows and populate hintindex
- local char = revelation.charorder:sub(i,i)
- if char and char ~= '' then
- hintindex[char] = thisclient
- hintbox_pos(char)
- hintbox[char].visible = true
- hintbox[char].screen = thisclient.screen
- end
- end
-
- local zoomed = false
- local zoomedClient = nil
- local key_char_zoomed = nil
-
- capi.keygrabber.run(function (mod, key, event)
- local c
- if event == "release" then return true end
-
- if awful.util.table.hasitem(mod, "Shift") then
- key_char = string.lower(key)
- c = hintindex[key_char]
- if not zoomed and c ~= nil then
- --debuginfo(c.screen)
- view_only_func(zt[c.screen.index or c.screen])
- toggle_tag_func(zt[c.screen.index or c.screen], c)
- zoomedClient = c
- key_char_zoomed = key_char
- zoomed = true
- -- update the position of this hintbox, since it is zoomed
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- hintbox_pos(key_char)
- hintbox_display_toggle(key_char, false)
-
-
- elseif zoomedClient ~= nil then
- awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
- toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
- hintbox_display_toggle(key_char_zoomed, true)
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- hintbox_pos(key_char_zoomed)
-
- zoomedClient = nil
- zoomed = false
- key_char_zoomed = nil
- end
- end
-
- if hintindex[key] then
- --client.focus = hintindex[key]
- --hintindex[key]:raise()
-
- selectfn(restore,t, zt)(hintindex[key])
-
- for i,j in pairs(hintindex) do
- hintbox[i].visible = false
- end
-
- return false
- end
-
- if key == "Escape" then
- if zoomedClient ~= nil then
- awful.tag.history.restore(zoomedClient.screen)
- toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
- hintbox_display_toggle(string.lower(key), true)
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- hintbox_pos(key_char_zoomed)
-
- zoomedClient = nil
- zoomed = false
- else
- for i,j in pairs(hintindex) do
- hintbox[i].visible = false
- end
- revelation.restore(t, zt)
- return false
- end
- end
-
- return true
- end)
-
- local pressedMiddle = false
-
- local lastClient = nil
- capi.mousegrabber.run(function(mouse)
- local c
-
- if type(awful.client.object) == 'table' then
- c = capi.mouse.current_client
- else
- c = awful.mouse.client_under_pointer()
- end
- if c then
- lastClient = c
- else
- local current_wibox = capi.mouse.current_wibox
- if current_wibox then
- for i = 1, #revelation.charorder do
- local char = revelation.charorder:sub(i,i)
- if hintbox[char] == current_wibox then
- c = lastClient
- break
- end
- end
- end
- end
- local key_char = awful.util.table.hasitem(hintindex, c)
- if mouse.buttons[1] == true then
- if c ~= nil then
- selectfn(restore, t, zt)(c)
-
- for i,j in pairs(hintindex) do
- hintbox[i].visible = false
- end
- return false
- else
- return true
- end
- elseif mouse.buttons[2] == true and pressedMiddle == false and c ~= nil then
- -- is true whenever the button is down.
- pressedMiddle = true
- -- extra variable needed to prevent script from spam-closing windows
- --
- if zoomed == true and zoomedClient ~=nil then
- awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
- toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
- end
- c:kill()
- hintbox[key_char].visible = false
- hintindex[key_char] = nil
- local pos = awful.util.table.hasitem(clients, c)
- table.remove(clients, pos)
-
-
- if zoomed == true and zoomedClient ~=nil then
- hintbox_display_toggle(key_char_zoomed, true)
- zoomedClient = nil
- zoomed = false
- key_char_zoomed = nil
- end
-
- return true
-
- elseif mouse.buttons[2] == false and pressedMiddle == true then
- pressedMiddle = false
- for key, _ in pairs(hintindex) do
- hintbox_pos(key)
- end
- elseif mouse.buttons[3] == true then
- if not zoomed and c ~= nil then
- view_only_func(zt[c.screen.index or c.screen])
- toggle_tag_func(zt[c.screen.index or c.screen], c)
- if key_char ~= nil then
- hintbox_display_toggle(key_char, false)
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- hintbox_pos(key_char)
- end
- zoomedClient = c
- zoomed = true
- key_char_zoomed = key_char
- elseif zoomedClient ~= nil then
- awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
- toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
- hintbox_display_toggle(key_char_zoomed, true)
- if type(delayed_call) == 'function' then
- capi.awesome.emit_signal("refresh")
- end
- hintbox_pos(key_char_zoomed)
-
- zoomedClient = nil
- zoomed = false
- key_char_zoomed = nil
- end
- end
-
- return true
- --Strange but on my machine only fleur worked as a string.
- --stole it from
- --https://github.com/Elv13/awesome-configs/blob/master/widgets/layout/desktopLayout.lua#L175
- end,"fleur")
-
-end
-
--- Create the wiboxes, but don't show them
---
-function revelation.init(args)
- local letterbox = {}
-
- args = args or {}
-
- revelation.tag_name = args.tag_name or revelation.tag_name
- if args.match then
- revelation.match.exact = args.match.exact or revelation.match.exact
- revelation.match.any = args.match.any or revelation.match.any
- end
-
- revelation.charorder = args.charorder or revelation.charorder
-
- for i = 1, #revelation.charorder do
- local char = revelation.charorder:sub(i,i)
- hintbox[char] = wibox({
- fg=revelation.fg,
- bg=revelation.bg,
- border_color=revelation.border_color,
- border_width=revelation.border_width
- })
- hintbox[char].ontop = true
- hintbox[char].width = revelation.hintsize
- hintbox[char].height = revelation.hintsize
- letterbox[char] = wibox.widget.textbox()
- letterbox[char]:set_markup(char.upper(char))
- letterbox[char]:set_font(revelation.font)
- letterbox[char]:set_align("center")
- hintbox[char]:set_widget(letterbox[char])
- end
-end
-
-setmetatable(revelation, { __call = function(_, ...) return revelation.expose(...) end })
-
-return revelation
diff --git a/awesome/.config/awesome/revelation/screenshot.png b/awesome/.config/awesome/revelation/screenshot.png
deleted file mode 100644
index 9cd759e..0000000
Binary files a/awesome/.config/awesome/revelation/screenshot.png and /dev/null differ
diff --git a/awesome/.config/awesome/rules-config.lua b/awesome/.config/awesome/rules-config.lua
new file mode 100644
index 0000000..59d7360
--- /dev/null
+++ b/awesome/.config/awesome/rules-config.lua
@@ -0,0 +1,114 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Rules config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local awful =require("awful")
+local beautiful = require("beautiful")
+local redtitle = require("redflat.titlebar")
+
+-- Initialize tables and vars for the module
+-----------------------------------------------------------------------------------------------------------------------
+local rules = {}
+
+rules.base_properties = {
+ border_width = beautiful.border_width,
+ border_color = beautiful.border_normal,
+ focus = awful.client.focus.filter,
+ raise = true,
+ size_hints_honor = false,
+ screen = awful.screen.preferred,
+}
+
+rules.floating_any = {
+ class = {
+ "Clipflap", "Run.py", "Arandr",
+ "Gpick",
+ "Kruler",
+ "MessageWin", -- kalarm.
+ "Sxiv",
+ "Wpa_gui",
+ "pinentry",
+ "veromix",
+ "xtightvncviewer",
+ "keepassxc",
+ },
+ name={ "Calculatrice","Event Tester",},
+ role = { "AlarmWindow", "pop-up", },
+ type = { "dialog" }
+}
+
+rules.titlebar_exceptions = {
+ class = { "Cavalcade", "Clipflap", "Steam", "Qemu-system-x86_64" }
+}
+
+rules.maximized = {
+ class = { "Emacs24" }
+}
+
+-- Build rule table
+-----------------------------------------------------------------------------------------------------------------------
+function rules:init(args)
+
+ args = args or {}
+ self.base_properties.keys = args.hotkeys.keys.client
+ self.base_properties.buttons = args.hotkeys.mouse.client
+ self.env = args.env or {}
+
+
+ -- Build rules
+ --------------------------------------------------------------------------------
+ self.rules = {
+ {
+ rule = {},
+ properties = args.base_properties or self.base_properties
+ },
+ {
+ rule_any = args.floating_any or self.floating_any,
+ properties = { floating = true, ontop=true }
+ },
+ {
+ rule_any = self.maximized,
+ callback = function(c)
+ c.maximized = true
+ redtitle.cut_all({ c })
+ c.height = c.screen.workarea.height - 2 * c.border_width
+ end
+ },
+ {
+ rule_any = { type = { "normal", "dialog" }},
+ except_any = self.titlebar_exceptions,
+ properties = { titlebars_enabled = true }
+ },
+ {
+ rule_any = { type = { "normal" }},
+ properties = { placement = awful.placement.no_overlap + awful.placement.no_offscreen }
+ },
+
+ -- Tags placement
+ {
+ rule = { instance = "Xephyr" },
+ properties = { tag = self.env.theme == "ruby" and "Test" or "Free", fullscreen = true }
+ },
+
+ -- Jetbrains splash screen fix
+ {
+ rule_any = { class = { "jetbrains-%w+", "java-lang-Thread" } },
+ callback = function(jetbrains)
+ if jetbrains.skip_taskbar then jetbrains.floating = true end
+ end
+ },
+ -- Set Firefox to always map on the tag named "2" on screen 1.
+ -- { rule = { class = "Firefox" },
+ -- properties = { screen = 1, tag = "2" } },
+ }
+
+
+ -- Set rules
+ --------------------------------------------------------------------------------
+ awful.rules.rules = rules.rules
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return rules
\ No newline at end of file
diff --git a/awesome/.config/awesome/signals-config.lua b/awesome/.config/awesome/signals-config.lua
new file mode 100644
index 0000000..56c609e
--- /dev/null
+++ b/awesome/.config/awesome/signals-config.lua
@@ -0,0 +1,103 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Signals config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local awful = require("awful")
+local beautiful = require("beautiful")
+
+local redutil = require("redflat.util")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local signals = {}
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function do_sloppy_focus(c)
+ if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier and awful.client.focus.filter(c) then
+ client.focus = c
+ end
+end
+
+local function fixed_maximized_geometry(c, context)
+ if c.maximized and context ~= "fullscreen" then
+ c:geometry({
+ x = c.screen.workarea.x,
+ y = c.screen.workarea.y,
+ height = c.screen.workarea.height - 2 * c.border_width,
+ width = c.screen.workarea.width - 2 * c.border_width
+ })
+ end
+end
+
+-- Build table
+-----------------------------------------------------------------------------------------------------------------------
+function signals:init(args)
+
+ args = args or {}
+ local env = args.env
+
+ -- actions on every application start
+ client.connect_signal(
+ "manage",
+ function(c)
+ -- put client at the end of list
+ if env.set_slave then awful.client.setslave(c) end
+
+ -- startup placement
+ if awesome.startup
+ and not c.size_hints.user_position
+ and not c.size_hints.program_position
+ then
+ awful.placement.no_offscreen(c)
+ end
+
+ -- put new floating windows to the center of screen
+ if env.set_center and c.floating and not (c.maximized or c.fullscreen) then
+ redutil.placement.centered(c, nil, mouse.screen.workarea)
+ end
+ end
+ )
+
+ -- add missing borders to windows that get unmaximized
+ client.connect_signal(
+ "property::maximized",
+ function(c)
+ if not c.maximized then
+ c.border_width = beautiful.border_width
+ end
+ end
+ )
+
+ -- don't allow maximized windows move/resize themselves
+ client.connect_signal(
+ "request::geometry", fixed_maximized_geometry
+ )
+
+ -- enable sloppy focus, so that focus follows mouse
+ if env.sloppy_focus then
+ client.connect_signal("mouse::enter", do_sloppy_focus)
+ end
+
+ -- hilight border of focused window
+ -- can be disabled since focus indicated by titlebars in current config
+ if env.color_border_focus then
+ client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
+ client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
+ end
+
+ -- wallpaper update on screen geometry change
+ screen.connect_signal("property::geometry", env.wallpaper)
+
+ -- Awesome v4.0 introduce screen handling without restart.
+ -- All redflat panel widgets was designed in old fashioned way and doesn't support this fature properly.
+ -- Since I'm using single monitor setup I have no will to rework panel widgets by now,
+ -- so restart signal added here is simple and dirty workaround.
+ -- You can disable it on your own risk.
+ screen.connect_signal("list", awesome.restart)
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return signals
diff --git a/awesome/.config/awesome/themes/colored/theme.lua b/awesome/.config/awesome/themes/colored/theme.lua
new file mode 100644
index 0000000..bf4c226
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/theme.lua
@@ -0,0 +1,228 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Shared settings for colored themes --
+-----------------------------------------------------------------------------------------------------------------------
+local awful = require("awful")
+
+-- This theme was inherited from another with overwriting some values
+-- Check parent theme to find full settings list and its description
+local theme = require("themes/colorless/theme")
+
+
+-- Common
+-----------------------------------------------------------------------------------------------------------------------
+theme.path = awful.util.get_configuration_dir() .. "themes/colored"
+
+-- Main config
+------------------------------------------------------------
+theme.panel_height = 36 -- panel height
+theme.border_width = 4 -- window border width
+theme.useless_gap = 4 -- useless gap
+
+-- Fonts
+------------------------------------------------------------
+theme.fonts = {
+ main = "Roboto 13", -- main font
+ menu = "Roboto 13", -- main menu font
+ tooltip = "Roboto 13", -- tooltip font
+ notify = "Play bold 14", -- redflat notify popup font
+ clock = "Play bold 12", -- textclock widget font
+ qlaunch = "Play bold 14", -- quick launch key label font
+ keychain = "Play bold 16", -- key sequence tip font
+ title = "Roboto bold 13", -- widget titles font
+ tiny = "Roboto bold 10", -- smallest font for widgets
+ titlebar = "Roboto bold 13", -- client titlebar font
+ hotkeys = {
+ main = "Roboto 14", -- hotkeys helper main font
+ key = "Iosevka Term Light 14", -- hotkeys helper key font (use monospace for align)
+ title = "Roboto bold 16", -- hotkeys helper group title font
+ },
+ player = {
+ main = "Play bold 13", -- player widget main font
+ time = "Play bold 15", -- player widget current time font
+ },
+}
+
+theme.cairo_fonts = {
+ tag = { font = "Play", size = 16, face = 1 }, -- tag widget font
+ appswitcher = { font = "Play", size = 20, face = 1 }, -- appswitcher widget font
+ navigator = {
+ title = { font = "Play", size = 28, face = 1, slant = 0 }, -- window navigation title font
+ main = { font = "Play", size = 22, face = 1, slant = 0 } -- window navigation main font
+ },
+
+ desktop = {
+ textbox = { font = "prototype", size = 24, face = 0 },
+ },
+}
+
+-- Widget icons
+--------------------------------------------------------------------------------
+theme.wicon = {
+ battery = theme.path .. "/widget/battery.svg",
+ wireless = theme.path .. "/widget/wireless.svg",
+ monitor = theme.path .. "/widget/monitor.svg",
+ audio = theme.path .. "/widget/audio.svg",
+ headphones = theme.path .. "/widget/headphones.svg",
+ brightness = theme.path .. "/widget/brightness.svg",
+ keyboard = theme.path .. "/widget/keyboard.svg",
+ mail = theme.path .. "/widget/mail.svg",
+ package = theme.path .. "/widget/package.svg",
+ search = theme.path .. "/widget/search.svg",
+ mute = theme.path .. "/widget/mute.svg",
+ up = theme.path .. "/widget/up.svg",
+ down = theme.path .. "/widget/down.svg",
+ onscreen = theme.path .. "/widget/onscreen.svg",
+ resize = {
+ full = theme.path .. "/widget/resize/full.svg",
+ horizontal = theme.path .. "/widget/resize/horizontal.svg",
+ vertical = theme.path .. "/widget/resize/vertical.svg",
+ },
+ updates = {
+ normal = theme.path .. "/widget/updates/normal.svg",
+ silent = theme.path .. "/widget/updates/silent.svg",
+ weekly = theme.path .. "/widget/updates/weekly.svg",
+ daily = theme.path .. "/widget/updates/daily.svg",
+ },
+}
+
+
+-- Main theme settings
+-- Make it updatabele since it may depends on common and ancestor theme settings
+-----------------------------------------------------------------------------------------------------------------------
+
+-- overwrite ancestor update settings with current theme values
+function theme:update()
+
+ -- setup parent theme settings
+ self:init()
+
+ -- Set hotkey helper size according current fonts and keys scheme
+ --------------------------------------------------------------------------------
+ self.service.navigator.keytip["fairv"] = { geometry = { width = 600 }, exit = true }
+ self.service.navigator.keytip["fairh"] = self.service.navigator.keytip["fairv"]
+
+ self.service.navigator.keytip["tile"] = { geometry = { width = 600 }, exit = true }
+ self.service.navigator.keytip["tileleft"] = self.service.navigator.keytip["tile"]
+ self.service.navigator.keytip["tiletop"] = self.service.navigator.keytip["tile"]
+ self.service.navigator.keytip["tilebottom"] = self.service.navigator.keytip["tile"]
+
+ self.service.navigator.keytip["grid"] = { geometry = { width = 1400 }, column = 2, exit = true }
+ self.service.navigator.keytip["usermap"] = { geometry = { width = 1400 }, column = 2, exit = true }
+
+ -- Desktop file parser
+ --------------------------------------------------------------------------------
+ self.service.dfparser.icons.theme = self.homedir .. "/.icons/ACYLS"
+ self.service.dfparser.icons.custom_only = true
+ self.service.dfparser.icons.scalable_only = true
+
+ -- Menu config
+ --------------------------------------------------------------------------------
+ self.menu.icon_margin = { 4, 7, 7, 8 }
+ self.menu.keytip = { geometry = { width = 400 } }
+
+ -- Panel widgets
+ --------------------------------------------------------------------------------
+
+ -- Double icon indicator
+ ------------------------------------------------------------
+ self.gauge.icon.double.icon1 = self.wicon.down
+ self.gauge.icon.double.icon2 = self.wicon.up
+ self.gauge.icon.double.igap = -6
+
+ -- Volume control
+ ------------------------------------------------------------
+ self.gauge.audio.red.icon = { volume = self.wicon.audio, mute = self.wicon.mute }
+ self.gauge.audio.blue.icon = self.wicon.headphones
+
+ -- Pulseaudio volume control
+ ------------------------------------------------------------
+ self.widget.pulse.notify = { icon = self.wicon.audio }
+
+ -- Keyboard layout indicator
+ ------------------------------------------------------------
+ self.widget.keyboard.icon = self.wicon.keyboard
+
+ -- Mail indicator
+ ------------------------------------------------------------
+ self.widget.mail.icon = self.wicon.mail
+ self.widget.mail.notify = { icon = self.wicon.mail }
+
+ -- System updates indicator
+ ------------------------------------------------------------
+ self.widget.updates.notify = { icon = self.wicon.package }
+ self.widget.updates.wibox.icon.package = self.wicon.package
+ self.widget.updates.wibox.icon.normal = self.wicon.updates.normal
+ self.widget.updates.wibox.icon.silent = self.wicon.updates.silent
+ self.widget.updates.wibox.icon.weekly = self.wicon.updates.weekly
+ self.widget.updates.wibox.icon.daily = self.wicon.updates.daily
+
+ -- Layoutbox
+ ------------------------------------------------------------
+ self.widget.layoutbox.menu.icon_margin = { 8, 12, 9, 9 }
+ self.widget.layoutbox.menu.width = 200
+
+ -- Tasklist
+ ------------------------------------------------------------
+ self.widget.tasklist.winmenu.hide_action = { min = false, move = false }
+ self.widget.tasklist.tasktip.margin = { 8, 8, 4, 4 }
+ self.widget.tasklist.winmenu.tagmenu.width = 150
+
+ -- Floating widgets
+ --------------------------------------------------------------------------------
+
+ -- Top processes
+ ------------------------------------------------------------
+ self.float.top.set_position = function(wibox)
+ local geometry = { x = mouse.screen.workarea.x + mouse.screen.workarea.width,
+ y = mouse.screen.workarea.y }
+ wibox:geometry(geometry)
+ end
+
+ -- Application runner
+ ------------------------------------------------------------
+ self.float.apprunner.title_icon = self.wicon.search
+ self.float.apprunner.keytip = { geometry = { width = 400 } }
+
+ -- Application switcher
+ ------------------------------------------------------------
+ self.float.appswitcher.keytip = { geometry = { width = 400 }, exit = true }
+
+ -- Quick launcher
+ ------------------------------------------------------------
+ self.float.qlaunch.keytip = { geometry = { width = 600 } }
+
+ -- Hotkeys helper
+ ------------------------------------------------------------
+ self.float.hotkeys.geometry = { width = 1800 }
+ self.float.hotkeys.heights = { key = 26, title = 32 }
+
+ -- Key sequence tip
+ ------------------------------------------------------------
+ self.float.keychain.border_width = 0
+ self.float.keychain.keytip = { geometry = { width = 1200 }, column = 2 }
+
+ -- Brightness control
+ ------------------------------------------------------------
+ self.float.brightness.notify = { icon = self.wicon.brightness }
+
+ -- Floating window control helper
+ ------------------------------------------------------------
+ self.float.control.icon = {
+ onscreen = self.wicon.onscreen,
+ resize = {
+ self.wicon.resize.full,
+ self.wicon.resize.horizontal,
+ self.wicon.resize.vertical,
+ },
+ }
+
+ -- Default awesome theme vars
+ --------------------------------------------------------------------------------
+ self.enable_spawn_cursor = false
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+theme:update()
+
+return theme
diff --git a/awesome/.config/awesome/themes/colored/widget/audio.svg b/awesome/.config/awesome/themes/colored/widget/audio.svg
new file mode 100644
index 0000000..9864581
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/audio.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/battery.svg b/awesome/.config/awesome/themes/colored/widget/battery.svg
new file mode 100644
index 0000000..6dfa8e3
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/battery.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/brightness.svg b/awesome/.config/awesome/themes/colored/widget/brightness.svg
new file mode 100644
index 0000000..6560c8b
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/brightness.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/down.svg b/awesome/.config/awesome/themes/colored/widget/down.svg
new file mode 100644
index 0000000..ebb6194
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/down.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/headphones.svg b/awesome/.config/awesome/themes/colored/widget/headphones.svg
new file mode 100644
index 0000000..328c396
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/headphones.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/keyboard.svg b/awesome/.config/awesome/themes/colored/widget/keyboard.svg
new file mode 100644
index 0000000..6d79d7d
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/keyboard.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/mail.svg b/awesome/.config/awesome/themes/colored/widget/mail.svg
new file mode 100644
index 0000000..9148dd5
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/mail.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/monitor.svg b/awesome/.config/awesome/themes/colored/widget/monitor.svg
new file mode 100644
index 0000000..7f4060d
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/monitor.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/mute.svg b/awesome/.config/awesome/themes/colored/widget/mute.svg
new file mode 100644
index 0000000..f0118d2
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/mute.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/onscreen.svg b/awesome/.config/awesome/themes/colored/widget/onscreen.svg
new file mode 100644
index 0000000..3a46e7a
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/onscreen.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/package.svg b/awesome/.config/awesome/themes/colored/widget/package.svg
new file mode 100644
index 0000000..2f3c6ac
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/package.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/resize/full.svg b/awesome/.config/awesome/themes/colored/widget/resize/full.svg
new file mode 100644
index 0000000..8989b51
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/resize/full.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/resize/horizontal.svg b/awesome/.config/awesome/themes/colored/widget/resize/horizontal.svg
new file mode 100644
index 0000000..e98cb78
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/resize/horizontal.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/resize/vertical.svg b/awesome/.config/awesome/themes/colored/widget/resize/vertical.svg
new file mode 100644
index 0000000..8e74db8
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/resize/vertical.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/search.svg b/awesome/.config/awesome/themes/colored/widget/search.svg
new file mode 100644
index 0000000..4b21903
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/search.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/up.svg b/awesome/.config/awesome/themes/colored/widget/up.svg
new file mode 100644
index 0000000..b861217
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/up.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/updates/daily.svg b/awesome/.config/awesome/themes/colored/widget/updates/daily.svg
new file mode 100644
index 0000000..911e820
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/updates/daily.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/updates/normal.svg b/awesome/.config/awesome/themes/colored/widget/updates/normal.svg
new file mode 100644
index 0000000..ae6dc47
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/updates/normal.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/updates/silent.svg b/awesome/.config/awesome/themes/colored/widget/updates/silent.svg
new file mode 100644
index 0000000..748accb
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/updates/silent.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/updates/weekly.svg b/awesome/.config/awesome/themes/colored/widget/updates/weekly.svg
new file mode 100644
index 0000000..c65d6a8
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/updates/weekly.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colored/widget/wireless.svg b/awesome/.config/awesome/themes/colored/widget/wireless.svg
new file mode 100644
index 0000000..54c08ca
--- /dev/null
+++ b/awesome/.config/awesome/themes/colored/widget/wireless.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/awesome.svg b/awesome/.config/awesome/themes/colorless/common/awesome.svg
new file mode 100644
index 0000000..bb623bd
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/awesome.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/blank.svg b/awesome/.config/awesome/themes/colorless/common/blank.svg
new file mode 100644
index 0000000..33e5d39
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/blank.svg
@@ -0,0 +1 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/check.svg b/awesome/.config/awesome/themes/colorless/common/check.svg
new file mode 100644
index 0000000..934b0dc
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/check.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/submenu.svg b/awesome/.config/awesome/themes/colorless/common/submenu.svg
new file mode 100644
index 0000000..6b2f849
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/submenu.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/system.svg b/awesome/.config/awesome/themes/colorless/common/system.svg
new file mode 100644
index 0000000..769aa74
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/system.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/unknown.svg b/awesome/.config/awesome/themes/colorless/common/unknown.svg
new file mode 100644
index 0000000..cdb0adf
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/unknown.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/common/warning.svg b/awesome/.config/awesome/themes/colorless/common/warning.svg
new file mode 100644
index 0000000..5d25727
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/common/warning.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/cornerne.svg b/awesome/.config/awesome/themes/colorless/layouts/cornerne.svg
new file mode 100644
index 0000000..d09d526
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/cornerne.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/cornernw.svg b/awesome/.config/awesome/themes/colorless/layouts/cornernw.svg
new file mode 100644
index 0000000..a2b9152
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/cornernw.svg
@@ -0,0 +1,4 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/cornerse.svg b/awesome/.config/awesome/themes/colorless/layouts/cornerse.svg
new file mode 100644
index 0000000..8c985a3
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/cornerse.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/cornersw.svg b/awesome/.config/awesome/themes/colorless/layouts/cornersw.svg
new file mode 100644
index 0000000..2d299c7
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/cornersw.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/fair.svg b/awesome/.config/awesome/themes/colorless/layouts/fair.svg
new file mode 100644
index 0000000..dc79076
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/fair.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/floating.svg b/awesome/.config/awesome/themes/colorless/layouts/floating.svg
new file mode 100644
index 0000000..d6b0d65
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/floating.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/fullscreen.svg b/awesome/.config/awesome/themes/colorless/layouts/fullscreen.svg
new file mode 100644
index 0000000..573a267
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/fullscreen.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/grid.svg b/awesome/.config/awesome/themes/colorless/layouts/grid.svg
new file mode 100644
index 0000000..e5593f6
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/grid.svg
@@ -0,0 +1,10 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/magnifier.svg b/awesome/.config/awesome/themes/colorless/layouts/magnifier.svg
new file mode 100644
index 0000000..6160621
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/magnifier.svg
@@ -0,0 +1,9 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/map.svg b/awesome/.config/awesome/themes/colorless/layouts/map.svg
new file mode 100644
index 0000000..651ce9c
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/map.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/max.svg b/awesome/.config/awesome/themes/colorless/layouts/max.svg
new file mode 100644
index 0000000..8ff9b21
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/max.svg
@@ -0,0 +1,8 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/spiral.svg b/awesome/.config/awesome/themes/colorless/layouts/spiral.svg
new file mode 100644
index 0000000..d9c1c07
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/spiral.svg
@@ -0,0 +1,10 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/tile.svg b/awesome/.config/awesome/themes/colorless/layouts/tile.svg
new file mode 100644
index 0000000..2cc7262
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/tile.svg
@@ -0,0 +1,7 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/tilebottom.svg b/awesome/.config/awesome/themes/colorless/layouts/tilebottom.svg
new file mode 100644
index 0000000..c31b69d
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/tilebottom.svg
@@ -0,0 +1,7 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/tileleft.svg b/awesome/.config/awesome/themes/colorless/layouts/tileleft.svg
new file mode 100644
index 0000000..054c63f
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/tileleft.svg
@@ -0,0 +1,7 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/layouts/tiletop.svg b/awesome/.config/awesome/themes/colorless/layouts/tiletop.svg
new file mode 100644
index 0000000..0520432
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/layouts/tiletop.svg
@@ -0,0 +1,7 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/player/cover.svg b/awesome/.config/awesome/themes/colorless/player/cover.svg
new file mode 100644
index 0000000..b98bcac
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/player/cover.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/player/next.svg b/awesome/.config/awesome/themes/colorless/player/next.svg
new file mode 100644
index 0000000..9a8df9c
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/player/next.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/player/pause.svg b/awesome/.config/awesome/themes/colorless/player/pause.svg
new file mode 100644
index 0000000..fe62800
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/player/pause.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/player/play.svg b/awesome/.config/awesome/themes/colorless/player/play.svg
new file mode 100644
index 0000000..7677394
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/player/play.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/player/previous.svg b/awesome/.config/awesome/themes/colorless/player/previous.svg
new file mode 100644
index 0000000..7e4e2e6
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/player/previous.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/theme.lua b/awesome/.config/awesome/themes/colorless/theme.lua
new file mode 100644
index 0000000..27908ce
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/theme.lua
@@ -0,0 +1,1454 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Colorless theme --
+-----------------------------------------------------------------------------------------------------------------------
+local awful = require("awful")
+
+local theme = {}
+--local wa = mouse.screen.workarea
+
+-- Color scheme
+-----------------------------------------------------------------------------------------------------------------------
+theme.color = {
+ -- main colors
+ main = "#02606D",
+ gray = "#575757",
+ bg = "#161616",
+ bg_second = "#181818",
+ wibox = "#202020",
+ icon = "#a0a0a0",
+ text = "#aaaaaa",
+ urgent = "#B25500",
+ highlight = "#e0e0e0",
+ border = "#404040",
+
+ -- secondary colors
+ shadow1 = "#141414",
+ shadow2 = "#313131",
+ shadow3 = "#1c1c1c",
+ shadow4 = "#767676",
+
+ button = "#575757",
+ pressed = "#404040",
+
+ desktop_gray = "#404040",
+ desktop_icon = "#606060",
+}
+
+-- Common
+-----------------------------------------------------------------------------------------------------------------------
+theme.path = awful.util.get_configuration_dir() .. "themes/colorless"
+theme.base = awful.util.get_configuration_dir() .. "themes/colorless"
+theme.homedir = os.getenv("HOME")
+
+-- Main config
+------------------------------------------------------------
+
+theme.panel_height = 36 -- panel height
+theme.border_width = 4 -- window border width
+theme.useless_gap = 4 -- useless gap
+
+theme.cellnum = { x = 96, y = 58 } -- grid layout property
+
+theme.wallpaper = theme.path .. "/wallpaper/primary.png" -- wallpaper file
+
+-- Fonts
+------------------------------------------------------------
+theme.fonts = {
+ main = "sans 12", -- main font
+ menu = "sans 12", -- main menu font
+ tooltip = "sans 12", -- tooltip font
+ notify = "sans bold 14", -- redflat notify popup font
+ clock = "sans bold 12", -- textclock widget font
+ qlaunch = "sans bold 14", -- quick launch key label font
+ title = "sans bold 12", -- widget titles font
+ tiny = "sans bold 10", -- smallest font for widgets
+ keychain = "sans bold 14", -- key sequence tip font
+ titlebar = "sans bold 12", -- client titlebar font
+ hotkeys = {
+ main = "sans 12", -- hotkeys helper main font
+ key = "mono 12", -- hotkeys helper key font (use monospace for align)
+ title = "sans bold 14", -- hotkeys helper group title font
+ },
+ player = {
+ main = "sans bold 12", -- player widget main font
+ time = "sans bold 14", -- player widget current time font
+ },
+}
+
+theme.cairo_fonts = {
+ tag = { font = "Sans", size = 16, face = 1 }, -- tag widget font
+ appswitcher = { font = "Sans", size = 22, face = 1 }, -- appswitcher widget font
+ navigator = {
+ title = { font = "Sans", size = 28, face = 1, slant = 0 }, -- window navigation title font
+ main = { font = "Sans", size = 22, face = 1, slant = 0 } -- window navigation main font
+ },
+
+ desktop = {
+ textbox = { font = "Sans", size = 24, face = 1 },
+ },
+}
+
+-- Shared icons
+--------------------------------------------------------------------------------
+theme.icon = {
+ check = theme.path .. "/common/check.svg",
+ blank = theme.path .. "/common/blank.svg",
+ submenu = theme.path .. "/common/submenu.svg",
+ warning = theme.path .. "/common/warning.svg",
+ awesome = theme.path .. "/common/awesome.svg",
+ system = theme.path .. "/common/system.svg",
+ unknown = theme.path .. "/common/unknown.svg",
+}
+
+
+-- Main theme settings
+-- Make it updatabele since it may depends on common
+-----------------------------------------------------------------------------------------------------------------------
+function theme:init()
+
+ -- Service utils config
+ ----------------------------------------------------------------------------------
+ self.service = {}
+
+ -- Window control mode appearance
+ --------------------------------------------------------------------------------
+ self.service.navigator = {
+ border_width = 0, -- window placeholder border width
+ gradstep = 60, -- window placeholder background stripes width
+ marksize = { -- window information plate size
+ width = 160, -- width
+ height = 80, -- height
+ r = 20 -- corner roundness
+ },
+ linegap = 32, -- gap between two lines on window information plate
+ timeout = 1, -- highlight duration
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ titlefont = self.cairo_fonts.navigator.title, -- first line font on window information plate
+ font = self.cairo_fonts.navigator.main, -- second line font on window information plate
+
+ -- array of hot key marks for window placeholders
+ num = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "F1", "F3", "F4", "F5" },
+
+ -- colors
+ color = {
+ border = self.color.main, -- window placeholder border color
+ mark = self.color.gray, -- window information plate background color
+ text = self.color.wibox, -- window information plate text color
+ fbg1 = self.color.main .. "40", -- first background color for focused window placeholder
+ fbg2 = self.color.main .. "20", -- second background color for focused window placeholder
+ hbg1 = self.color.urgent .. "40", -- first background color for highlighted window placeholder
+ hbg2 = self.color.urgent .. "20", -- second background color for highlighted window placeholder
+ bg1 = self.color.gray .. "40", -- first background color for window placeholder
+ bg2 = self.color.gray .. "20" -- second background color for window placeholder
+ }
+ }
+
+ -- layout hotkeys helper settings
+ self.service.navigator.keytip = {}
+
+ -- this one used as fallback when style for certain layout missed
+ self.service.navigator.keytip["base"] = { geometry = { width = 600 }, exit = true }
+
+ -- styles for certain layouts
+ self.service.navigator.keytip["fairv"] = { geometry = { width = 600}, exit = true }
+ self.service.navigator.keytip["fairh"] = self.service.navigator.keytip["fairv"]
+ self.service.navigator.keytip["spiral"] = self.service.navigator.keytip["fairv"]
+ self.service.navigator.keytip["dwindle"] = self.service.navigator.keytip["fairv"]
+
+ self.service.navigator.keytip["tile"] = { geometry = { width = 600 }, exit = true }
+ self.service.navigator.keytip["tileleft"] = self.service.navigator.keytip["tile"]
+ self.service.navigator.keytip["tiletop"] = self.service.navigator.keytip["tile"]
+ self.service.navigator.keytip["tilebottom"] = self.service.navigator.keytip["tile"]
+
+ self.service.navigator.keytip["cornernw"] = { geometry = { width = 600 }, exit = true }
+ self.service.navigator.keytip["cornerne"] = self.service.navigator.keytip["cornernw"]
+ self.service.navigator.keytip["cornerse"] = self.service.navigator.keytip["cornernw"]
+ self.service.navigator.keytip["cornersw"] = self.service.navigator.keytip["cornernw"]
+
+ self.service.navigator.keytip["magnifier"] = { geometry = { width = 600}, exit = true }
+
+ self.service.navigator.keytip["grid"] = { geometry = { width = 1400 }, column = 2, exit = true }
+ self.service.navigator.keytip["usermap"] = { geometry = { width = 1400 }, column = 2, exit = true }
+
+ -- Desktop file parser
+ --------------------------------------------------------------------------------
+ self.service.dfparser = {
+ -- list of path to check desktop files
+ desktop_file_dirs = {
+ '/usr/share/applications/',
+ '/usr/local/share/applications/',
+ '~/.local/share/applications',
+ },
+ -- icon theme settings
+ icons = {
+ theme = nil, -- user icon theme path
+ --theme = "/usr/share/icons/ACYLS", -- for example
+ df_icon = self.icon.system, -- default (fallback) icon
+ custom_only = false, -- use icons from user theme (no system fallback like 'hicolor' allowed) only
+ scalable_only = false -- use vector(svg) icons (no raster icons allowed) only
+ },
+ wm_name = nil -- window manager name
+ }
+
+
+ -- Menu config
+ --------------------------------------------------------------------------------
+ self.menu = {
+ border_width = 4, -- menu border width
+ screen_gap = self.useless_gap + self.border_width, -- minimal space from screen edge on placement
+ height = 32, -- menu item height
+ width = 250, -- menu item width
+ icon_margin = { 8, 8, 8, 8 }, -- space around left icon in menu item
+ ricon_margin = { 9, 9, 9, 9 }, -- space around right icon in menu item
+ nohide = false, -- do not hide menu after item activation
+ auto_expand = true, -- show submenu on item selection (without item activation)
+ auto_hotkey = false, -- automatically set hotkeys for all menu items
+ select_first = true, -- auto select first item when menu shown
+ hide_timeout = 1, -- auto hide timeout (auto hide disables if this set to 0)
+ font = self.fonts.menu, -- menu font
+ submenu_icon = self.icon.submenu, -- icon for submenu items
+ keytip = { geometry = { width = 400 } }, -- hotkeys helper settings
+ shape = nil, -- wibox shape
+ svg_scale = { false, false }, -- use vector scaling for left, right icons in menu item
+ }
+
+ self.menu.color = {
+ border = self.color.wibox, -- menu border color
+ text = self.color.text, -- menu text color
+ highlight = self.color.highlight, -- menu text and icons color for selected item
+ main = self.color.main, -- menu selection color
+ wibox = self.color.wibox, -- menu background color
+ submenu_icon = self.color.icon, -- submenu icon color
+ right_icon = nil, -- right icon color in menu item
+ left_icon = nil, -- left icon color in menu item
+ }
+
+
+ -- Gauge (various elements that used as component for other widgets) style
+ --------------------------------------------------------------------------------
+ self.gauge = { tag = {}, task = {}, icon = {}, audio = {}, monitor = {}, graph = {} }
+
+
+ -- Plain progressbar element
+ ------------------------------------------------------------
+ self.gauge.graph.bar = {
+ color = self.color -- colors (main used)
+ }
+
+ -- Plain monitor (label and progressbar below)
+ --------------------------------------------------------------
+ self.gauge.monitor.plain = {
+ width = 50, -- widget width
+ font = self.cairo_fonts.tag, -- widget font
+ text_shift = 19, -- shift from upper border of widget to lower border of text
+ label = "MON", -- widget text
+ step = 0.05, -- progressbar painting step
+ line = { height = 4, y = 27 }, -- progressbar style
+ color = self.color -- colors (main used)
+ }
+
+ -- Simple monitor with sigle vertical dashed progressbar
+ ------------------------------------------------------------
+ self.gauge.monitor.dash = {
+ width = 10, -- widget width
+ color = self.color, -- colors (main used)
+
+ -- progressbar line style
+ line = {
+ num = 5, -- number of chunks in progressbar
+ height = 3 -- height of progressbar chunk
+ },
+ }
+
+ -- Icon indicator (decoration in some panel widgets)
+ ------------------------------------------------------------
+ self.gauge.icon.single = {
+ icon = self.icon.system, -- default icon
+ is_vertical = false, -- use vertical gradient (horizontal if false)
+ step = 0.02, -- icon painting step
+ color = self.color -- colors (main used)
+ }
+
+ -- Double icon indicator
+ --------------------------------------------------------------
+ self.gauge.icon.double = {
+ icon1 = self.icon.system, -- first icon
+ icon2 = self.icon.system, -- second icon
+ is_vertical = true, -- use vertical gradient (horizontal if false)
+ igap = 4, -- gap between icons
+ step = 0.02, -- icon painting step
+ color = self.color -- colors (main used)
+ }
+
+ -- Double value monitor (double progressbar with icon)
+ --------------------------------------------------------------
+ self.gauge.monitor.double = {
+ icon = self.icon.system, -- default icon
+ width = 90, -- widget width
+ dmargin = { 10, 0, 0, 0 }, -- margins around progressbar area
+ color = self.color, -- colors (main used)
+
+ -- progressbar style
+ line = {
+ width = 4, -- progressbar height
+ v_gap = 6, -- space between progressbar
+ gap = 4, -- gap between progressbar dashes
+ num = 5 -- number of progressbar dashes
+ },
+ }
+
+ -- Separator (decoration used on panel, menu and some other widgets)
+ ------------------------------------------------------------
+ self.gauge.separator = {
+ marginv = { 2, 2, 4, 4 }, -- margins for vertical separator
+ marginh = { 6, 6, 3, 3 }, -- margins for horizontal separator
+ color = self.color -- color (secondary used)
+ }
+
+ -- Step like dash bar (user for volume widgets)
+ ------------------------------------------------------------
+ self.gauge.graph.dash = {
+ bar = {
+ width = 4, -- dash element width
+ num = 10 -- number of dash elements
+ },
+ color = self.color -- color (main used)
+ }
+
+ -- Volume indicator
+ ------------------------------------------------------------
+ self.gauge.audio.blue = {
+ width = 75, -- widget width
+ dmargin = { 10, 0, 2, 2 }, -- margins around dash area
+ icon = self.icon.system, -- volume icon
+
+ -- colors
+ color = { icon = self.color.icon, mute = self.color.urgent },
+
+ -- dash style
+ dash = { bar = { num = 5, width = 4 } },
+ }
+
+ self.gauge.audio.red = {
+ icon = { volume = self.icon.system, mute = self.icon.warning }, -- icons
+ step = 0.05, -- icon painting step
+ color = { main = self.color.main, icon = self.color.icon, mute = self.color.gray } -- custom colors
+ }
+
+ -- Dotcount (used in minitray widget)
+ ------------------------------------------------------------
+ self.gauge.graph.dots = {
+ column_num = { 3, 5 }, -- amount of dot columns (min/max)
+ row_num = 3, -- amount of dot rows
+ dot_size = 5, -- dots size
+ dot_gap_h = 4, -- horizontal gap between dot (with columns number it'll define widget width)
+ color = self.color -- colors (main used)
+ }
+
+ -- Circle shaped monitor
+ --------------------------------------------------------------
+ self.gauge.monitor.circle = {
+ width = 32, -- widget width
+ line_width = 4, -- width of circle
+ iradius = 5, -- radius for center point
+ radius = 11, -- circle radius
+ step = 0.05, -- circle painting step
+ color = self.color -- colors (main used)
+ }
+
+ -- Tag (base element of taglist)
+ ------------------------------------------------------------
+ self.gauge.tag.orange = {
+ width = 38, -- widget width
+ line_width = self.gauge.monitor.circle.line_width, -- width of arcs
+ iradius = self.gauge.monitor.circle.iradius, -- radius for center point
+ radius = self.gauge.monitor.circle.radius, -- arcs radius
+ cgap = 0.314, -- gap between arcs in radians
+ min_sections = 1, -- minimal amount of arcs
+ show_min = false, -- indicate minimized apps by color
+ text = false, -- replace middle circle by text
+ font = self.cairo_fonts.tag, -- font for text
+ color = self.color -- colors (main used)
+ }
+
+ self.gauge.tag.ruby = {
+ width = 40, -- widget width
+ color = self.color, -- colors (main used)
+
+ -- tag state mark
+ base = {
+ pad = 6, -- left/right padding
+ height = 9, -- mark height
+ thickness = 2 -- mark lines thickness
+ },
+
+ -- client focus mark
+ mark = {
+ pad = 10, -- left/right padding
+ height = 3 -- mark height
+ },
+ }
+
+ self.gauge.tag.blue = {
+ width = 103, -- widget width
+ show_min = false, -- indicate minimized apps by color
+ text_shift = 20, -- shift from upper border of widget to lower border of text
+ color = self.color, -- colors (main used)
+ font = self.cairo_fonts.tag, -- font
+
+ -- apps indicator
+ point = {
+ width = 80, -- apps indicator total width
+ height = 3, -- apps indicator total height
+ gap = 27, -- shift from upper border of widget to apps indicator
+ dx = 5 -- gap between apps indicator parts
+ },
+ }
+
+ self.gauge.tag.red = {
+ width = 80, -- widget width
+ text_shift = 19, -- shift from upper border of widget to lower border of text
+ font = self.cairo_fonts.tag, -- font
+ show_counter = true, -- visible/hidden apps counter
+ color = self.color, -- colors (main used)
+
+ -- apps counter
+ counter = {
+ size = 12, -- counter font size
+ margin = 2, -- margin around counter
+ coord = { 40, 28 } -- counter position
+ },
+
+ -- functions for state marks
+ marks = nil,
+
+ -- geometry for state marks
+ geometry = {
+ active = { height = 4, y = 27 }, -- active tag mark
+ focus = { x = 5, y = 7, width = 10, height = 12 }, -- focused tag mark
+ occupied = { x = 68, y = 7, width = 8, height = 12 } -- occupied tag mark
+ }
+ }
+
+ self.gauge.tag.green = {
+ width = 44, -- widget width
+ margin = { 0, 0, 8, 8 }, -- margin around tag icon
+ icon = nil, -- layouts icon list (will be defined below)
+ color = self.color -- colors (main used)
+ }
+
+ -- Task (base element of tasklist)
+ ------------------------------------------------------------
+
+ -- the same structure as blue tag
+ self.gauge.task.blue = {
+ width = 70,
+ show_min = true,
+ text_shift = 20,
+ color = self.color,
+ font = self.cairo_fonts.tag,
+ point = { width = 70, height = 3, gap = 27, dx = 5 },
+ }
+
+ self.gauge.task.ruby = {
+ width = 76,
+ text_shift = 26,
+ color = self.color,
+ font = self.cairo_fonts.tag,
+
+ point = { size = 5, space = 5, gap = 4 },
+ underline = { height = 10, thickness = 3, gap = 34, dh = 0 },
+ }
+
+ self.gauge.task.red = {
+ width = 40, -- widget width
+ text_shift = 19, -- shift from upper border of widget to lower border of text
+ font = self.cairo_fonts.tag, -- font
+ line = { height = 4, y = 27 }, -- application state indicator
+ color = self.color, -- colors (main used)
+
+ -- applications counter
+ counter = {
+ size = 12, -- counter font size
+ margin = 2 -- margin around counter
+ },
+ }
+
+ self.gauge.task.green = {
+ width = 40, -- widget width
+ df_icon = self.icon.system, -- fallback icon
+ margin = { 0, 0, 2, 2 }, -- margin around icon
+ color = self.color -- colors (main used)
+ }
+
+ -- Panel widgets
+ --------------------------------------------------------------------------------
+ self.widget = {}
+
+ -- individual margins for panel widgets
+ ------------------------------------------------------------
+ self.widget.wrapper = {
+ mainmenu = { 12, 10, 6, 6 },
+ layoutbox = { 10, 10, 6, 6 },
+ textclock = { 12, 12, 0, 0 },
+ taglist = { 4, 4, 0, 0 },
+ tray = { 10, 12, 7, 7 },
+ -- tasklist = { 0, 70, 0, 0 }, -- centering tasklist widget
+ }
+
+ -- Textclock
+ ------------------------------------------------------------
+ self.widget.textclock = {
+ font = self.fonts.clock, -- font
+ tooltip = {}, -- redflat tooltip style (see theme.float.tooltip)
+ color = { text = self.color.icon } -- colors
+ }
+
+ -- Binary clock
+ ------------------------------------------------------------
+ self.widget.binclock = {
+ width = 52, -- widget width
+ tooltip = {}, -- redflat tooltip style (see theme.float.tooltip)
+ dot = { size = 5 }, -- mark size
+ color = self.color, -- colors (main used)
+ }
+
+ -- Battery indicator
+ ------------------------------------------------------------
+ self.widget.battery = {
+ timeout = 30, -- update timeout
+ notify = {}, -- redflat notify style (see theme.float.notify)
+
+ -- notification levels
+ levels = { 0.05, 0.1, 0.15, 0.20, 0.25 }
+ }
+
+ -- Minitray
+ ------------------------------------------------------------
+ self.widget.minitray = {
+ dotcount = {}, -- redflat dotcount style (see theme.gauge.graph.dots)
+ border_width = 0, -- floating widget border width
+ geometry = { height = 40 }, -- floating widget size
+ screen_gap = self.useless_gap, -- minimal space from screen edge on floating widget placement
+ shape = nil, -- wibox shape
+ color = { wibox = self.color.wibox, border = self.color.wibox },
+
+ -- function to define floating widget position when shown
+ set_position = function(wibox)
+ local geometry = { x = mouse.screen.workarea.x + mouse.screen.workarea.width,
+ y = mouse.screen.workarea.y }
+ wibox:geometry(geometry)
+ end,
+ }
+
+ -- Pulseaudio volume control
+ ------------------------------------------------------------
+ self.widget.pulse = {
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ widget = nil, -- audio gauge (usually setted by rc file)
+ audio = {} -- style for gauge
+ }
+
+ -- Keyboard layout indicator
+ ------------------------------------------------------------
+ self.widget.keyboard = {
+ icon = self.icon.system, -- widget icon
+ micon = self.icon, -- some common menu icons
+
+ -- list of colors associated with keyboard layouts
+ layout_color = { self.color.icon, self.color.main },
+
+ -- redflat menu style (see theme.menu)
+ menu = { width = 180, color = { right_icon = self.color.icon }, nohide = true }
+ }
+
+ -- Mail indicator
+ ------------------------------------------------------------
+ self.widget.mail = {
+ icon = self.icon.system, -- widget icon
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ need_notify = true, -- show notification on new mail
+ firstrun = true, -- check mail on wm start/restart
+ color = self.color, -- colors (main used)
+ }
+
+ -- System updates indicator
+ ------------------------------------------------------------
+ self.widget.updates = {
+ icon = self.icon.system, -- widget icon
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ need_notify = true, -- show notification on updates
+ firstrun = true, -- check updates on wm start/restart
+ color = self.color, -- colors (main used)
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 400 } },
+
+ -- tooltips style
+ tooltip = { base = {}, state = { timeout = 1 } },
+
+ -- wibox style settings
+ wibox = {
+ geometry = { width = 250, height = 160 }, -- widget size
+ border_width = 0, -- widget border width
+ title_font = self.fonts.title, -- widget title font
+ tip_font = self.fonts.tiny, -- widget state tip font
+ separator = {}, -- redflat separator style (see theme.gauge.separator)
+ shape = nil, -- wibox shape
+ set_position = nil, -- set_position
+
+ -- wibox icons
+ icon = {
+ package = self.icon.system, -- main wibox image
+ close = self.base .. "/titlebar/close.svg", -- close button
+ normal = self.icon.system, -- regular notification
+ daily = self.icon.system, -- defer notification for day
+ weekly = self.icon.system, -- defer notification for 7 day
+ silent = self.icon.system, -- disable notification
+ },
+
+ -- widget areas height
+ height = {
+ title = 28, -- titlebar
+ state = 34, -- control icon area
+ },
+
+ -- widget element margins
+ margin = {
+ close = { 0, 0, 6, 6 }, -- close button
+ title = { 16 + 2*6, 16, 4, 0 }, -- titlebar area
+ state = { 4, 4, 4, 12 }, -- control icon area
+ image = { 0, 0, 2, 4 }, -- main wibox image area
+ },
+ }
+ }
+
+ -- Layoutbox
+ ------------------------------------------------------------
+ self.widget.layoutbox = {
+ micon = self.icon, -- some common menu icons (used: 'blank', 'check')
+ color = self.color -- colors (main used)
+ }
+
+ -- layout icons
+ self.widget.layoutbox.icon = {
+ floating = self.base .. "/layouts/floating.svg",
+ max = self.base .. "/layouts/max.svg",
+ fullscreen = self.base .. "/layouts/fullscreen.svg",
+ tilebottom = self.base .. "/layouts/tilebottom.svg",
+ tileleft = self.base .. "/layouts/tileleft.svg",
+ tile = self.base .. "/layouts/tile.svg",
+ tiletop = self.base .. "/layouts/tiletop.svg",
+ fairv = self.base .. "/layouts/fair.svg",
+ fairh = self.base .. "/layouts/fair.svg",
+ grid = self.base .. "/layouts/grid.svg",
+ usermap = self.base .. "/layouts/map.svg",
+ magnifier = self.base .. "/layouts/magnifier.svg",
+ spiral = self.base .. "/layouts/spiral.svg",
+ cornerne = self.base .. "/layouts/cornerne.svg",
+ cornernw = self.base .. "/layouts/cornernw.svg",
+ cornerse = self.base .. "/layouts/cornerse.svg",
+ cornersw = self.base .. "/layouts/cornersw.svg",
+ unknown = self.icon.unknown, -- this one used as fallback
+ }
+
+ -- redflat menu style (see theme.menu)
+ self.widget.layoutbox.menu = {
+ icon_margin = { 8, 12, 8, 8 },
+ width = 260,
+ auto_hotkey = true,
+ nohide = false,
+ color = { right_icon = self.color.icon, left_icon = self.color.icon }
+ }
+
+ -- human readable aliases for layout names (displayed in menu and tooltip)
+ self.widget.layoutbox.name_alias = {
+ floating = "Floating",
+ fullscreen = "Fullscreen",
+ max = "Maximized",
+ grid = "Grid",
+ usermap = "User Map",
+ tile = "Right Tile",
+ fairv = "Fair Tile",
+ tileleft = "Left Tile",
+ tiletop = "Top Tile",
+ tilebottom = "Bottom Tile",
+ magnifier = "Magnifier",
+ spiral = "Spiral",
+ cornerne = "Corner NE",
+ cornernw = "Corner NW",
+ cornerse = "Corner SE",
+ cornersw = "Corner SW",
+ }
+
+ -- green tag icons
+ self.gauge.tag.green.icon = self.widget.layoutbox.icon
+
+ -- Tasklist
+ --------------------------------------------------------------
+
+ -- main settings
+ self.widget.tasklist = {
+ custom_icon = false, -- use custom applications icons (not every gauge task widget support icons)
+ iconnames = {}, -- icon name aliases for custom applications icons
+ widget = nil, -- task gauge widget (usually setted by rc file)
+ width = 40, -- width of task element in tasklist
+ char_digit = 4, -- number of characters in task element text
+ need_group = true, -- group application instances into one task element
+ parser = {}, -- redlat desktop file parser settings (see theme.service.dfparser)
+ task_margin = { 5, 5, 0, 0 }, -- margins around task element
+ task = self.gauge.task.blue -- style for task gauge widget
+ }
+
+ -- menu settings
+ self.widget.tasklist.winmenu = {
+ micon = self.icon, -- some common menu icons
+ titleline = {
+ font = self.fonts.title, -- menu title height
+ height = 25 -- menu title font
+ },
+ stateline = { height = 30 }, -- height of menu item with state icons
+ state_iconsize = { width = 18, height = 18 }, -- size for state icons
+ layout_icon = self.widget.layoutbox.icon, -- list of layout icons
+ separator = { marginh = { 3, 3, 5, 5 } }, -- redflat separator style (see theme.gauge.separator)
+ color = self.color, -- colors (main used)
+
+ -- main menu style (see theme.menu)
+ menu = { width = 200, color = { right_icon = self.color.icon }, ricon_margin = { 9, 9, 9, 9 } },
+
+ -- tag action submenu style (see theme.menu)
+ tagmenu = { width = 160, color = { right_icon = self.color.icon, left_icon = self.color.icon },
+ icon_margin = { 9, 9, 9, 9 } },
+
+ -- set which action will hide menu after activate
+ hide_action = { min = true, move = true, max = false, add = false, floating = false, sticky = false,
+ ontop = false, below = false, maximized = false },
+ }
+
+ -- menu icons
+ self.widget.tasklist.winmenu.icon = {
+ floating = self.base .. "/titlebar/floating.svg",
+ sticky = self.base .. "/titlebar/pin.svg",
+ ontop = self.base .. "/titlebar/ontop.svg",
+ below = self.base .. "/titlebar/below.svg",
+ close = self.base .. "/titlebar/close.svg",
+ minimize = self.base .. "/titlebar/minimize.svg",
+ maximized = self.base .. "/titlebar/maximized.svg",
+
+ unknown = self.icon.unknown, -- this one used as fallback
+ }
+
+ -- multiline task element tip
+ self.widget.tasklist.tasktip = {
+ border_width = 2, -- tip border width
+ margin = { 10, 10, 5, 5 }, -- margins around text in tip lines
+ timeout = 0.5, -- hide timeout
+ shape = nil, -- wibox shape
+ sl_highlight = false, -- highlight application state when it's single line tip
+ color = self.color, -- colors (main used)
+ }
+
+ -- task text aliases
+ self.widget.tasklist.appnames = {}
+ self.widget.tasklist.appnames["Firefox" ] = "FIFOX"
+ self.widget.tasklist.appnames["Gnome-terminal" ] = "GTERM"
+
+
+ -- Floating widgets
+ --------------------------------------------------------------------------------
+ self.float = { decoration = {} }
+
+ -- Brightness control
+ ------------------------------------------------------------
+ self.float.brightness = {
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ }
+
+ -- Client menu
+ ------------------------------------------------------------
+ self.float.clientmenu = {
+ actionline = { height = 28 }, -- height of menu item with action icons
+ action_iconsize = { width = 18, height = 18 }, -- size for action icons
+ stateline = { height = 30 }, -- height of menu item with state icons
+
+ -- redflat separator style(see theme.gauge.separator)
+ separator = { marginh = { 3, 3, 5, 5 }, marginv = { 3, 3, 3, 3 } },
+
+ -- same elements as for task list menu
+ icon = self.widget.tasklist.winmenu.icon,
+ micon = self.widget.tasklist.winmenu.micon,
+ layout_icon = self.widget.layoutbox.icon,
+ menu = self.widget.tasklist.winmenu.menu,
+ state_iconsize = self.widget.tasklist.winmenu.state_iconsize,
+ tagmenu = self.widget.tasklist.winmenu.tagmenu,
+ hide_action = self.widget.tasklist.winmenu.hide_action,
+ color = self.color,
+ }
+
+ -- Audio player
+ ------------------------------------------------------------
+ self.float.player = {
+ geometry = { width = 490, height = 130 }, -- widget size
+ screen_gap = 2 * self.useless_gap, -- minimal space from screen edge on floating widget placement
+ border_margin = { 15, 15, 15, 15 }, -- margins around widget content
+ elements_margin = { 15, 0, 0, 0 }, -- margins around main player elements (exclude cover art)
+ controls_margin = { 0, 0, 14, 6 }, -- margins around control player elements
+ volume_margin = { 0, 0, 0, 3 }, -- margins around volume element
+ buttons_margin = { 0, 0, 3, 3 }, -- margins around buttons area
+ pause_margin = { 12, 12, 0, 0 }, -- margins around pause button
+ line_height = 26, -- text lines height
+ bar_width = 6, -- progressbar width
+ volume_width = 50, -- volume element width
+ titlefont = self.fonts.player.main, -- track font
+ artistfont = self.fonts.player.main, -- artist/album font
+ timefont = self.fonts.player.time, -- track progress time font
+ border_width = 0, -- widget border width
+ timeout = 1, -- widget update timeout
+ set_position = nil, -- set_position
+ shape = nil, -- wibox shape
+ color = self.color, -- color (main used)
+
+ -- volume dash style (see theme.gauge.graph.dash)
+ dashcontrol = { color = self.color, bar = { num = 7 } },
+
+ -- progressbar style (see theme.gauge.graph.bar)
+ progressbar = { color = self.color },
+ }
+
+ -- widget icons
+ self.float.player.icon = {
+ cover = self.base .. "/player/cover.svg",
+ next_tr = self.base .. "/player/next.svg",
+ prev_tr = self.base .. "/player/previous.svg",
+ play = self.base .. "/player/play.svg",
+ pause = self.base .. "/player/pause.svg"
+ }
+
+ -- Top processes
+ ------------------------------------------------------------
+ self.float.top = {
+ geometry = { width = 460, height = 400 }, -- widget size
+ screen_gap = 2 * self.useless_gap, -- minimal space from screen edge on floating widget placement
+ border_margin = { 20, 20, 10, 0 }, -- margins around widget content
+ button_margin = { 140, 140, 18, 18 }, -- margins around kill button
+ title_height = 40, -- widget title height
+ border_width = 0, -- widget border width
+ bottom_height = 70, -- kill button area height
+ list_side_gap = 8, -- left/rigth borger margin for processes list
+ title_font = self.fonts.title, -- widget title font
+ timeout = 2, -- widget update timeout
+ shape = nil, -- wibox shape
+ color = self.color, -- color (main used)
+
+ -- list columns width
+ labels_width = { num = 30, cpu = 70, mem = 120 },
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 400 } },
+
+ -- placement function
+ set_position = nil,
+ }
+
+ -- Application runner
+ ------------------------------------------------------------
+ self.float.apprunner = {
+ itemnum = 6, -- number of visible items
+ geometry = { width = 620, height = 480 }, -- widget size
+ border_margin = { 24, 24, 24, 24 }, -- margin around widget content
+ icon_margin = { 8, 16, 0, 0 }, -- margins around widget icon
+ title_height = 48, -- height of title (promt and icon) area
+ prompt_height = 35, -- prompt line height
+ title_icon = self.icon.system, -- widget icon
+ border_width = 0, -- widget border width
+ parser = {}, -- desktop file parser settings (see theme.service.dfparser)
+ field = nil, -- redflat text field style(see theme.float.decoration.field)
+ shape = nil, -- wibox shape
+ color = self.color, -- colors (main used)
+
+ name_font = self.fonts.title, -- application title font
+ comment_font = self.fonts.main, -- application comment font
+ list_text_vgap = 4, -- space between application title and comment
+ list_icon_margin = { 6, 12, 6, 6 }, -- margins around applications icons
+ dimage = self.icon.unknown, -- fallback icon for applications
+
+ keytip = { geometry = { width = 400 } }, -- redflat key tip settings
+ }
+
+ -- Application swit`cher
+ ------------------------------------------------------------
+ self.float.appswitcher = {
+ wibox_height = 240, -- widget height
+ label_height = 28, -- height of the area with application mark(key)
+ title_height = 40, -- height of widget title line (application name and tag name)
+ icon_size = 96, -- size of the application icon in preview area
+ preview_gap = 20, -- gap between preview areas
+ shape = nil, -- wibox shape
+
+ -- desktop file parser settings (see theme.service.dfparser)
+ parser = {
+ desktop_file_dirs = awful.util.table.join(
+ self.service.dfparser.desktop_file_dirs,
+ { '~/.local/share/applications-fake' }
+ )
+ },
+
+ border_margin = { 10, 10, 0, 10 }, -- margins around widget content
+ preview_margin = { 15, 15, 15, 15 }, -- margins around application preview
+ preview_format = 16 / 10, -- preview acpect ratio
+ title_font = self.fonts.title, -- font of widget title line
+ border_width = 0, -- widget border width
+ update_timeout = 1 / 12, -- application preview update timeout
+ min_icon_number = 4, -- this one will define the minimal widget width
+ -- (widget will not shrink if number of apps items less then this)
+ color = self.color, -- colors (main used)
+ font = self.cairo_fonts.appswitcher, -- font of application mark(key)
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 400 }, exit = true },
+ }
+
+ -- additional color
+ self.float.appswitcher.color.preview_bg = self.color.main .. "12"
+
+ -- application marks(keys) list
+ self.float.appswitcher.hotkeys = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0",
+ "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" }
+
+ -- Quick launcher
+ ------------------------------------------------------------
+ self.float.qlaunch = {
+ geometry = { width = 1400, height = 170 }, -- widget size
+
+ border_width = 0, -- widget border width
+ border_margin = { 5, 5, 12, 15 }, -- margins around widget content
+ notify = {}, -- redflat notify style (see theme.float.notify)
+ shape = nil, -- wibox shape
+ recoloring = false, -- apply redflat recoloring feature on application icons
+ label_font = self.fonts.qlaunch, -- font of application mark(key)
+ color = self.color, -- colors (main used)
+ df_icon = self.icon.system, -- fallback application icon
+ no_icon = self.icon.unknown, -- icon for unused application slot
+
+ -- desktop file parser settings (see theme.service.dfparser)
+ parser = {
+ desktop_file_dirs = awful.util.table.join(
+ self.service.dfparser.desktop_file_dirs,
+ { '~/.local/share/applications-fake' }
+ )
+ },
+
+ appline = {
+ iwidth = 140, -- application item width
+ im = { 5, 5, 0, 0 }, -- margins around application item area
+ igap = { 0, 0, 5, 15 }, -- margins around application icon itself (will affect icon size)
+ lheight = 26 -- height of application mark(key) area
+ },
+ state = {
+ gap = 5, -- space between application state marks
+ radius = 5, -- application state mark radius
+ size = 10, -- application state mark size
+ height = 14 -- height of application state marks area
+ },
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 600 } },
+
+ -- file to store widget data
+ -- this widget is rare one which need to keep settings between sessions
+ configfile = os.getenv("HOME") .. "/.cache/awesome/applist",
+ }
+
+ -- Hotkeys helper
+ ------------------------------------------------------------
+ self.float.hotkeys = {
+ geometry = { width = 1400 }, -- widget size
+ border_margin = { 20, 20, 8, 10 }, -- margins around widget content
+ border_width = 0, -- widget border width
+ delim = " ", -- text separator between key and description
+ tspace = 5, -- space between lines in widget title
+ is_align = true, -- align keys description (monospace font required)
+ separator = { marginh = { 0, 0, 3, 6 } }, -- redflat separator style (see theme.gauge.separator)
+ font = self.fonts.hotkeys.main, -- keys description font
+ keyfont = self.fonts.hotkeys.key, -- keys font
+ titlefont = self.fonts.hotkeys.title, -- widget title font
+ shape = nil, -- wibox shape
+ color = self.color, -- colors (main used)
+
+ -- manual setup for expected text line heights
+ -- used for auto adjust widget height
+ heights = {
+ key = 20, -- hotkey tip line height
+ title = 22 -- group title height
+ },
+ }
+
+ -- Titlebar helper
+ ------------------------------------------------------------
+ self.float.bartip = {
+ geometry = { width = 260, height = 40 }, -- widget size
+ border_margin = { 10, 10, 10, 10 }, -- margins around widget content
+ border_width = 0, -- widget border widthj
+ font = self.fonts.title, -- widget font
+ set_position = nil, -- placement function
+ shape = nil, -- wibox shape
+ names = { "Mini", "Plain", "Full" }, -- titlebar layout names
+ color = self.color, -- colors (main used)
+
+ -- margin around widget elements
+ margin = { icon = { title = { 10, 10, 8, 8 }, state = { 10, 10, 8, 8 } } },
+
+ -- widget icons
+ icon = {
+ title = self.base .. "/titlebar/title.svg",
+ active = self.base .. "/titlebar/active.svg",
+ hidden = self.base .. "/titlebar/hidden.svg",
+ disabled = self.base .. "/titlebar/disabled.svg",
+ absent = self.base .. "/titlebar/absent.svg",
+ unknown = self.icon.unknown,
+ },
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 540 } },
+ }
+
+ -- Floating window control helper
+ ------------------------------------------------------------
+ self.float.control = {
+ geometry = { width = 260, height = 48 }, -- widget size
+ border_margin = { 10, 10, 10, 10 }, -- margins around widget content
+ border_width = 0, -- widget border widthj
+ font = self.fonts.title, -- widget font
+ steps = { 1, 10, 25, 50, 200 }, -- move/resize step
+ default_step = 3, -- select default step by index
+ onscreen = true, -- no off screen for window placement
+ set_position = nil, -- widget placement function
+ shape = nil, -- wibox shape
+ color = self.color, -- colors (main used)
+
+ -- margin around widget elements
+ margin = { icon = { onscreen = { 10, 10, 8, 8 }, mode = { 10, 10, 8, 8 } } },
+
+ -- widget icons
+ icon = {
+ onscreen = self.icon.system,
+ resize = {},
+ },
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 540 } },
+ }
+
+ -- Key sequence tip
+ ------------------------------------------------------------
+ self.float.keychain = {
+ geometry = { width = 250, height = 56 }, -- default widget size
+ font = self.fonts.keychain, -- widget font
+ border_width = 2, -- widget border width
+ shape = nil, -- wibox shape
+ color = self.color, -- colors (main used)
+
+ -- redflat key tip settings
+ keytip = { geometry = { width = 600 }, column = 1 },
+ }
+
+ -- Tooltip
+ ------------------------------------------------------------
+ self.float.tooltip = {
+ timeout = 0, -- show delay
+ shape = nil, -- wibox shapea
+ font = self.fonts.tooltip, -- widget font
+ border_width = 2, -- widget border width
+ set_position = nil, -- function to setup tooltip position when shown
+ color = self.color, -- colors (main used)
+
+ -- padding around widget content
+ padding = { vertical = 3, horizontal = 6 },
+ }
+
+ -- Floating prompt
+ ------------------------------------------------------------
+ self.float.prompt = {
+ geometry = { width = 620, height = 120 }, -- widget size
+ border_width = 0, -- widget border width
+ margin = { 20, 20, 40, 40 }, -- margins around widget content
+ field = nil, -- redflat text field style (see theme.float.decoration.field)
+ shape = nil, -- wibox shape
+ naughty = {}, -- awesome notification style
+ color = self.color, -- colors (main used)
+ }
+
+ -- Notify (redflat notification widget)
+ ------------------------------------------------------------
+ self.float.notify = {
+ geometry = { width = 484, height = 106 }, -- widget size
+ screen_gap = 2 * self.useless_gap, -- screen edges gap on placement
+ border_margin = { 20, 20, 20, 20 }, -- margins around widget content
+ elements_margin = { 20, 0, 10, 10 }, -- margins around main elements (text and bar)
+ font = self.fonts.notify, -- widget font
+ icon = self.icon.warning, -- default widget icon
+ border_width = 0, -- widget border width
+ timeout = 5, -- hide timeout
+ shape = nil, -- wibox shape
+ color = self.color, -- colors (main used)
+
+ -- progressbar is optional element used for some notifications
+ bar_width = 8, -- progressbar width
+ progressbar = {}, -- redflat progressbar style (see theme.gauge.graph.bar)
+
+ -- placement function
+ set_position = function(wibox)
+ wibox:geometry({ x = mouse.screen.workarea.x + mouse.screen.workarea.width, y = mouse.screen.workarea.y })
+ end,
+ }
+
+ -- Decoration (various elements that used as component for other widgets) style
+ --------------------------------------------------------------------------------
+ self.float.decoration.button = {
+ color = self.color -- colors (secondary used)
+ }
+
+ self.float.decoration.field = {
+ color = self.color -- colors (secondary used)
+ }
+
+
+ -- Titlebar
+ --------------------------------------------------------------------------------
+ self.titlebar = {}
+
+ self.titlebar.base = {
+ position = "top", -- titlebar position
+ font = self.fonts.titlebar, -- titlebar font
+ border_margin = { 0, 0, 0, 4 }, -- margins around titlebar active area
+ color = self.color, -- colors (main used)
+ }
+
+ -- application state marks settings
+ self.titlebar.mark = {
+ color = self.color, -- colors (main used)
+ }
+
+ -- application control icon settings
+ self.titlebar.icon = {
+ color = self.color, -- colors (main used)
+
+ -- icons list
+ list = {
+ focus = self.base .. "/titlebar/focus.svg",
+ floating = self.base .. "/titlebar/floating.svg",
+ ontop = self.base .. "/titlebar/ontop.svg",
+ below = self.base .. "/titlebar/below.svg",
+ sticky = self.base .. "/titlebar/pin.svg",
+ maximized = self.base .. "/titlebar/maximized.svg",
+ minimized = self.base .. "/titlebar/minimize.svg",
+ close = self.base .. "/titlebar/close.svg",
+ menu = self.base .. "/titlebar/menu.svg",
+
+ unknown = self.icon.unknown, -- this one used as fallback
+ }
+ }
+
+ -- Desktop config
+ --------------------------------------------------------------------------------
+ self.desktop = { common = { bar = {}, pack = {} }, speedmeter = {} }
+
+ self.desktop.line_height = 18 -- text and progressbar height for desktop wodgets
+
+ -- desktop widget colors
+ self.desktop.color = {
+ main = self.color.main,
+ gray = self.color.desktop_gray,
+ icon = self.color.desktop_icon,
+ urgent = self.color.urgent,
+ wibox = self.color.bg .. "00"
+ }
+
+ -- Common (various elem, 0.20, 0.25ents that used as component for desktop widgets)
+ --------------------------------------------------------------------------------
+
+ -- Textbox
+ ------------------------------------------------------------
+ self.desktop.common.textbox = {
+ width = nil, -- widget width
+ height = nil, -- widget height
+ draw = "by_left", -- align method ("by_left", "by_right", "by_edges", "by_width")
+ color = self.desktop.color.gray, -- text color
+
+ -- font style
+ font = self.cairo_fonts.desktop.textbox,
+ }
+
+ -- Dashed progressbar
+ ------------------------------------------------------------
+ self.desktop.common.bar.plain = {
+ width = nil, -- widget width
+ height = nil, -- widget height
+ autoscale = false, -- normalize progressbar value
+ maxm = 1, -- the maximum allowed value
+
+ -- color (desktop used)
+ color = self.desktop.color,
+
+ -- progressbar settings
+ chunk = {
+ width = 6, -- bar width
+ gap = 6 -- space between bars
+ }
+ }
+
+ -- Time chart
+ ------------------------------------------------------------
+ self.desktop.common.chart = {
+ width = nil, -- widget width
+ height = nil, -- widget height
+ autoscale = true, -- normalize chart values
+ maxm = 1, -- the maximum allowed value
+ zero_height = 4, -- height for zero value point in chart
+ color = self.desktop.color.gray, -- chart bars color
+
+ -- chart bars settings
+ bar = {
+ width = 5, -- bar width
+ gap = 5 -- space between bars
+ }
+ }
+
+
+ -- Custom shaped vertical progressbar
+ ------------------------------------------------------------
+ self.desktop.common.bar.shaped = {
+ width = nil, -- widget width
+ height = nil, -- widget height
+ autoscale = true, -- normalize chart values
+ maxm = 1, -- the maximum allowed value
+ shape = "corner", -- progressbar chunk shape
+ show = { tooltip = false }, -- show tooltip
+ color = self.desktop.color, -- color (desktop used)
+
+ -- element style
+ chunk = {
+ num = 10, -- number of elements
+ line = 5, -- element line width
+ height = 10 -- element height
+ },
+
+ -- tooltip style
+ tooltip = {},
+ }
+
+ -- Lines (group of progressbars with label in front and text value after it)
+ ------------------------------------------------------------
+ self.desktop.common.pack.lines = {
+ label = { width = 80, draw = "by_width" }, -- label style (see theme.desktop.common.textbox)
+ text = { width = 92, draw = "by_edges" }, -- value style (see theme.desktop.common.textbox)
+ progressbar = {}, -- progressbar style (see theme.desktop.common.bar.plain)
+ line = { height = self.desktop.line_height }, -- text/progressbar height
+ tooltip = {}, -- redflat tooltip style (see theme.float.tooltip)
+ color = self.desktop.color, -- color (desktop used)
+
+ -- show/hide line elements
+ show = { text = true, label = true, tooltip = false },
+
+ -- space between label/text and progressbar
+ gap = { text = 22, label = 16 },
+ }
+
+ -- Widgets
+ --------------------------------------------------------------------------------
+
+ --Custom aligned text block
+ ------------------------------------------------------------
+ self.desktop.textset = {
+ font = "Sans 12", -- font
+ spacing = 0, -- space between lines
+ color = self.desktop.color -- color (desktop used)
+ }
+
+ -- Speed widget (double progressbar with time chart for each of it)
+ ------------------------------------------------------------
+ self.desktop.speedmeter.normal = {
+ barvalue_height = 32, -- height of the area with progressbar and text
+ digits = 2, -- minimal number of digits for progressbar value
+ fullchart_height = 80, -- height of the each area with progressbar, text and chart
+ image_gap = 16, -- space between direction icon and progressbar/chart
+ color = self.desktop.color, -- color (desktop used)
+
+ -- direction icons
+ images = {
+ self.icon.system, -- up
+ self.icon.system -- down
+ },
+
+ -- !!! WARNING some missed style settings for elemets below will be overwritten by widget
+ -- do not try to use full style settings from 'theme.desktop.commom' here
+
+ -- time chart style (see theme.desktop.common.chart)
+ chart = { bar = { width = 6, gap = 3 }, height = 40, zero_height = 4 },
+
+ -- progressbar label and value (see theme.desktop.common.textbox)
+ label = { height = self.desktop.line_height },
+
+ -- progressbar style (see theme.desktop.common.bar.plain)
+ progressbar = { chunk = { width = 16, gap = 6 }, height = 6 },
+ }
+
+ self.desktop.speedmeter.compact = {
+ margins = { label = {}, chart = {} }, -- extra margins for some elements
+ height = { chart = 50 }, -- height of the each area with progressbar, text and chart
+ digits = 2, -- minimal number of digits for progressbar value
+ color = self.desktop.color, -- color (desktop used)
+
+ -- direction icons
+ icon = {
+ up = self.icon.system, -- up
+ down = self.icon.system, -- down
+ margin = { 4, 4, 2, 2 }, -- margins around icon
+ },
+
+ -- !!! WARNING some style settings for elemets below will be overwritten by widget
+ chart = { zero_height = 0 }, -- time chart style (see theme.desktop.common.chart)
+ label = {}, -- progressbar value (see theme.desktop.common.textbox)
+ progressbar = {}, -- double progressbar style (see theme.desktop.common.bar.plain)
+ }
+
+ -- Widget with multiple horizontal and vertical progress bars
+ ------------------------------------------------------------
+ self.desktop.multimeter = {
+ digits = 3, -- minimal number of digits for horizontal progressbar values
+ color = self.desktop.color, -- color (desktop used)
+ labels = {}, -- list of optional labels for horizontal bars
+
+ -- area height
+ height = {
+ upright = 80, -- vertical progressbars height
+ lines = 58, -- horizontal progressbar area height
+ },
+
+ -- widget icon
+ icon = {
+ image = self.icon.system, -- widget icon
+ margin = { 0, 16, 0, 0 }, -- margins around icon
+ full = false -- draw icon in full height of widget
+ },
+ -- !!! WARNING some missed style settings for elemets below will be overwritten by widget
+
+ -- vertical progressbars style (see theme.desktop.common.bar.shaped)
+ upbar = { width = 34, chunk = { height = 17, num = 10, line = 4 } },
+
+ -- horizontal progressbars style (see theme.desktop.common.pack.lines)
+ lines = {},
+ }
+
+ -- Widget with multiple progress bars
+ ------------------------------------------------------------
+ self.desktop.multiline = {
+ digits = 3, -- minimal number of digits for progressbar value
+ margin = { 0, 0, 0, 0 }, -- margin around progressbar list
+ color = self.desktop.color, -- color (desktop used)
+
+ -- widget icon settings
+ icon = { image = nil, margin = { 0, 0, 0, 0 } },
+
+ -- !!! WARNING some missed style settings for elemets below will be overwritten by widget
+
+ -- progressbars style (see theme.desktop.common.pack.lines)
+ lines = { progressbar = {}, tooltip = {} },
+ }
+
+ -- Widget with several text groups in single line
+ -- every group has label and value and icon in the middle
+ ------------------------------------------------------------
+ self.desktop.singleline = {
+ lbox = { draw = "by_width", width = 50 }, -- label style (see theme.desktop.common.textbox)
+ rbox = { draw = "by_edges", width = 60 }, -- value style (see theme.desktop.common.textbox)
+ digits = 2, -- minimal number of digits for value
+ icon = self.icon.system, -- group icon
+ iwidth = 142, -- width for every text group
+ color = self.desktop.color -- color (desktop used)
+ }
+
+ -- Calendar widget with lined up marks
+ ------------------------------------------------------------
+ self.desktop.calendar = {
+ show_pointer = true, -- show date under mouse
+ color = self.desktop.color, -- color (desktop used)
+ -- TODO: check for better font
+ -- today label style
+ label = {
+ gap = 8, -- space between label and pointer
+ sep = "-", -- day/month separator
+ font = { font = "Play", size = 16, face = 1, slant = 0 }, -- font
+ },
+
+ -- days marks style
+ mark = {
+ height = 12, -- mark height
+ width = 25, -- mark width
+ dx = 6, -- pointer arrow width
+ line = 2, -- stroke line width for next month marks
+ },
+ }
+
+ -- Individual styles for certain widgets
+ --------------------------------------------------------------------------------
+ self.individual = { desktop = {} }
+
+ -- Default awesome theme vars
+ --------------------------------------------------------------------------------
+
+ -- colors
+ self.bg_normal = self.color.wibox
+ self.bg_focus = self.color.main
+ self.bg_urgent = self.color.urgent
+ self.bg_minimize = self.color.gray
+
+ self.fg_normal = self.color.text
+ self.fg_focus = self.color.highlight
+ self.fg_urgent = self.color.highlight
+ self.fg_minimize = self.color.highlight
+
+ self.border_normal = self.color.wibox
+ self.border_focus = self.color.wibox
+ self.border_marked = self.color.main
+
+ -- font
+ self.font = self.fonts.main
+
+ -- standart awesome notification widget
+ self.naughty = {}
+
+ self.naughty.base = {
+ timeout = 10,
+ margin = 12,
+ icon_size = 80,
+ font = self.fonts.main,
+ bg = self.color.wibox,
+ fg = self.color.text,
+
+ border_width = 4,
+ border_color = self.color.wibox
+ }
+
+ self.naughty.normal = {
+ height = self.float.notify.geometry.height,
+ width = self.float.notify.geometry.width,
+ }
+
+ self.naughty.low = {
+ timeout = 5,
+ height = self.float.notify.geometry.height,
+ width = self.float.notify.geometry.width,
+ }
+
+ self.naughty.critical = {
+ timeout = 0,
+ border_color = self.color.main
+ }
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+theme:init()
+
+return theme
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/absent.svg b/awesome/.config/awesome/themes/colorless/titlebar/absent.svg
new file mode 100644
index 0000000..8775f60
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/absent.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/active.svg b/awesome/.config/awesome/themes/colorless/titlebar/active.svg
new file mode 100644
index 0000000..94e2201
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/active.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/below.svg b/awesome/.config/awesome/themes/colorless/titlebar/below.svg
new file mode 100644
index 0000000..8ca14c0
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/below.svg
@@ -0,0 +1,4 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/close.svg b/awesome/.config/awesome/themes/colorless/titlebar/close.svg
new file mode 100644
index 0000000..d3c16d2
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/close.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/disabled.svg b/awesome/.config/awesome/themes/colorless/titlebar/disabled.svg
new file mode 100644
index 0000000..b749cf0
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/disabled.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/floating.svg b/awesome/.config/awesome/themes/colorless/titlebar/floating.svg
new file mode 100644
index 0000000..d6b0d65
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/floating.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/focus.svg b/awesome/.config/awesome/themes/colorless/titlebar/focus.svg
new file mode 100644
index 0000000..9831a7c
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/focus.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/hidden.svg b/awesome/.config/awesome/themes/colorless/titlebar/hidden.svg
new file mode 100644
index 0000000..cfafd70
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/hidden.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/maximized.svg b/awesome/.config/awesome/themes/colorless/titlebar/maximized.svg
new file mode 100644
index 0000000..8ff5e34
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/maximized.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/menu.svg b/awesome/.config/awesome/themes/colorless/titlebar/menu.svg
new file mode 100644
index 0000000..6a712a0
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/menu.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/minimize.svg b/awesome/.config/awesome/themes/colorless/titlebar/minimize.svg
new file mode 100644
index 0000000..b749cf0
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/minimize.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/ontop.svg b/awesome/.config/awesome/themes/colorless/titlebar/ontop.svg
new file mode 100644
index 0000000..d39e016
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/ontop.svg
@@ -0,0 +1,6 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/pin.svg b/awesome/.config/awesome/themes/colorless/titlebar/pin.svg
new file mode 100644
index 0000000..da5b938
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/pin.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/colorless/titlebar/title.svg b/awesome/.config/awesome/themes/colorless/titlebar/title.svg
new file mode 100644
index 0000000..707c683
--- /dev/null
+++ b/awesome/.config/awesome/themes/colorless/titlebar/title.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/default/icons/audio.svg b/awesome/.config/awesome/themes/default/icons/audio.svg
new file mode 100644
index 0000000..ab3fd84
--- /dev/null
+++ b/awesome/.config/awesome/themes/default/icons/audio.svg
@@ -0,0 +1,3 @@
+
diff --git a/awesome/.config/awesome/themes/default/layouts/cornerne.png b/awesome/.config/awesome/themes/default/layouts/cornerne.png
deleted file mode 100644
index e7fb61b..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornerne.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornernew.png b/awesome/.config/awesome/themes/default/layouts/cornernew.png
deleted file mode 100644
index aeaf331..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornernew.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornernw.png b/awesome/.config/awesome/themes/default/layouts/cornernw.png
deleted file mode 100644
index bac5672..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornernw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornernww.png b/awesome/.config/awesome/themes/default/layouts/cornernww.png
deleted file mode 100644
index 93b6706..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornernww.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornerse.png b/awesome/.config/awesome/themes/default/layouts/cornerse.png
deleted file mode 100644
index 092a905..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornerse.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornersew.png b/awesome/.config/awesome/themes/default/layouts/cornersew.png
deleted file mode 100644
index 35e900b..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornersew.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornersw.png b/awesome/.config/awesome/themes/default/layouts/cornersw.png
deleted file mode 100644
index 0d519b5..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornersw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/cornersww.png b/awesome/.config/awesome/themes/default/layouts/cornersww.png
deleted file mode 100644
index 2d744fd..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/cornersww.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/dwindle.png b/awesome/.config/awesome/themes/default/layouts/dwindle.png
deleted file mode 100644
index 0ec7a35..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/dwindle.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/dwindlew.png b/awesome/.config/awesome/themes/default/layouts/dwindlew.png
deleted file mode 100644
index 8457892..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/dwindlew.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fairh.png b/awesome/.config/awesome/themes/default/layouts/fairh.png
deleted file mode 100644
index 3c2d36b..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fairh.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fairhw.png b/awesome/.config/awesome/themes/default/layouts/fairhw.png
deleted file mode 100644
index 410e292..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fairhw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fairv.png b/awesome/.config/awesome/themes/default/layouts/fairv.png
deleted file mode 100644
index ad99f4b..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fairv.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fairvw.png b/awesome/.config/awesome/themes/default/layouts/fairvw.png
deleted file mode 100644
index 1a4ee27..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fairvw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/floating.png b/awesome/.config/awesome/themes/default/layouts/floating.png
deleted file mode 100644
index bf74990..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/floating.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/floatingw.png b/awesome/.config/awesome/themes/default/layouts/floatingw.png
deleted file mode 100644
index 7aecb06..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/floatingw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fullscreen.png b/awesome/.config/awesome/themes/default/layouts/fullscreen.png
deleted file mode 100644
index d02f6fc..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fullscreen.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/fullscreenw.png b/awesome/.config/awesome/themes/default/layouts/fullscreenw.png
deleted file mode 100644
index 5c35bfa..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/fullscreenw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/magnifier.png b/awesome/.config/awesome/themes/default/layouts/magnifier.png
deleted file mode 100644
index 2ea2792..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/magnifier.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/magnifierw.png b/awesome/.config/awesome/themes/default/layouts/magnifierw.png
deleted file mode 100644
index 5cd5e16..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/magnifierw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/max.png b/awesome/.config/awesome/themes/default/layouts/max.png
deleted file mode 100644
index 8d20844..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/max.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/maxw.png b/awesome/.config/awesome/themes/default/layouts/maxw.png
deleted file mode 100644
index 85f5ce3..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/maxw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/spiral.png b/awesome/.config/awesome/themes/default/layouts/spiral.png
deleted file mode 100644
index ca41814..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/spiral.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/spiralw.png b/awesome/.config/awesome/themes/default/layouts/spiralw.png
deleted file mode 100644
index d128461..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/spiralw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tile.png b/awesome/.config/awesome/themes/default/layouts/tile.png
deleted file mode 100644
index db1ce15..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tile.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tilebottom.png b/awesome/.config/awesome/themes/default/layouts/tilebottom.png
deleted file mode 100644
index 73a72fe..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tilebottom.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tilebottomw.png b/awesome/.config/awesome/themes/default/layouts/tilebottomw.png
deleted file mode 100644
index 64aa289..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tilebottomw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tileleft.png b/awesome/.config/awesome/themes/default/layouts/tileleft.png
deleted file mode 100644
index 829475a..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tileleft.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tileleftw.png b/awesome/.config/awesome/themes/default/layouts/tileleftw.png
deleted file mode 100644
index 24c3941..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tileleftw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tiletop.png b/awesome/.config/awesome/themes/default/layouts/tiletop.png
deleted file mode 100644
index 1964d4d..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tiletop.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tiletopw.png b/awesome/.config/awesome/themes/default/layouts/tiletopw.png
deleted file mode 100644
index d2eee79..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tiletopw.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/layouts/tilew.png b/awesome/.config/awesome/themes/default/layouts/tilew.png
deleted file mode 100644
index 4451a66..0000000
Binary files a/awesome/.config/awesome/themes/default/layouts/tilew.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/theme.lua b/awesome/.config/awesome/themes/default/theme.lua
index 6dc55b2..f99ef51 100644
--- a/awesome/.config/awesome/themes/default/theme.lua
+++ b/awesome/.config/awesome/themes/default/theme.lua
@@ -10,136 +10,41 @@ local gfs = require("gears.filesystem")
local themes_path =os.getenv("HOME") .. "/.config/awesome/themes/"
local icon_dir = themes_path .. "default/icons/"
-local theme = {}
+local theme = require("themes/colored/theme")
+theme.color.main = "#A30817"
+theme.color.urgent = "#016B84"
+
+
+
+theme:update()
+theme.gauge.audio.blue.dash.plain = true
+theme.gauge.audio.blue.dash.bar.num = 8
+theme.gauge.audio.blue.dash.bar.width = 3
+theme.gauge.audio.blue.dmargin = { 5, 0, 9, 9 }
+theme.gauge.audio.blue.width = 86
+theme.gauge.audio.blue.icon = theme.path .. "/widget/audio.svg"
+theme.widget.tasklist.task = theme.gauge.task.ruby
theme.font = "Roboto Bold 10"
-theme.bg_normal = "#242424"
-theme.bg_focus = "#535d6c"
-theme.bg_urgent = "#ff0000"
-theme.bg_minimize = "#444444"
-theme.bg_systray = theme.bg_normal
+theme.cellnum = { x = 80, y = 43 } -- grid layout property
-theme.fg_normal = "#aaaaaa"
-theme.fg_focus = "#ffffff"
-theme.fg_urgent = "#ffffff"
-theme.fg_minimize = "#ffffff"
-
-theme.useless_gap = dpi(0)
-theme.border_width = dpi(1)
-theme.border_normal = "#000000"
-theme.border_focus = "#535d6c"
-theme.border_marked = "#91231c"
-
-
-
-theme.wibar_height = dpi(28)
--- There are other variable sets
--- overriding the default one when
--- defined, the sets are:
--- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile]
--- tasklist_[bg|fg]_[focus|urgent]
--- titlebar_[bg|fg]_[normal|focus]
--- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color]
--- mouse_finder_[color|timeout|animate_timeout|radius|factor]
--- prompt_[fg|bg|fg_cursor|bg_cursor|font]
--- hotkeys_[bg|fg|border_width|border_color|shape|opacity|modifiers_fg|label_bg|label_fg|group_margin|font|description_font]
--- Example:
---theme.taglist_bg_focus = "#ff0000"
-
--- Generate taglist squares:
-local taglist_square_size = dpi(4)
-theme.taglist_squares_sel = theme_assets.taglist_squares_sel(
- taglist_square_size, theme.fg_normal
-)
-theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel(
- taglist_square_size, theme.fg_normal
-)
-
--- Variables set for theming notifications:
--- notification_font
--- notification_[bg|fg]
--- notification_[width|height|margin]
--- notification_[border_color|border_width|shape|opacity]
-
--- Variables set for theming the menu:
--- menu_[bg|fg]_[normal|focus]
--- menu_[border_color|border_width]
-theme.menu_submenu_icon = themes_path.."default/submenu.png"
-theme.menu_height = dpi(30)
-theme.menu_width = dpi(100)
-
--- You can add as many variables as
--- you wish and access them by using
--- beautiful.variable in your rc.lua
---theme.bg_widget = "#cc0000"
-
--- Define the image to load
-theme.titlebar_close_button_normal = themes_path.."default/titlebar/close_normal.png"
-theme.titlebar_close_button_focus = themes_path.."default/titlebar/close_focus.png"
-
-theme.titlebar_minimize_button_normal = themes_path.."default/titlebar/minimize_normal.png"
-theme.titlebar_minimize_button_focus = themes_path.."default/titlebar/minimize_focus.png"
-
-theme.titlebar_ontop_button_normal_inactive = themes_path.."default/titlebar/ontop_normal_inactive.png"
-theme.titlebar_ontop_button_focus_inactive = themes_path.."default/titlebar/ontop_focus_inactive.png"
-theme.titlebar_ontop_button_normal_active = themes_path.."default/titlebar/ontop_normal_active.png"
-theme.titlebar_ontop_button_focus_active = themes_path.."default/titlebar/ontop_focus_active.png"
-
-theme.titlebar_sticky_button_normal_inactive = themes_path.."default/titlebar/sticky_normal_inactive.png"
-theme.titlebar_sticky_button_focus_inactive = themes_path.."default/titlebar/sticky_focus_inactive.png"
-theme.titlebar_sticky_button_normal_active = themes_path.."default/titlebar/sticky_normal_active.png"
-theme.titlebar_sticky_button_focus_active = themes_path.."default/titlebar/sticky_focus_active.png"
-
-theme.titlebar_floating_button_normal_inactive = themes_path.."default/titlebar/floating_normal_inactive.png"
-theme.titlebar_floating_button_focus_inactive = themes_path.."default/titlebar/floating_focus_inactive.png"
-theme.titlebar_floating_button_normal_active = themes_path.."default/titlebar/floating_normal_active.png"
-theme.titlebar_floating_button_focus_active = themes_path.."default/titlebar/floating_focus_active.png"
-
-theme.titlebar_maximized_button_normal_inactive = themes_path.."default/titlebar/maximized_normal_inactive.png"
-theme.titlebar_maximized_button_focus_inactive = themes_path.."default/titlebar/maximized_focus_inactive.png"
-theme.titlebar_maximized_button_normal_active = themes_path.."default/titlebar/maximized_normal_active.png"
-theme.titlebar_maximized_button_focus_active = themes_path.."default/titlebar/maximized_focus_active.png"
-
---theme.wallpaper = themes_path.."default/background.png"
theme.wallpaper = "~/Images/wallpaper.jpg"
--- You can use your own layout icons like this:
-theme.layout_fairh = themes_path.."default/layouts/fairhw.png"
-theme.layout_fairv = themes_path.."default/layouts/fairvw.png"
-theme.layout_floating = themes_path.."default/layouts/floatingw.png"
-theme.layout_magnifier = themes_path.."default/layouts/magnifierw.png"
-theme.layout_max = themes_path.."default/layouts/maxw.png"
-theme.layout_fullscreen = themes_path.."default/layouts/fullscreenw.png"
-theme.layout_tilebottom = themes_path.."default/layouts/tilebottomw.png"
-theme.layout_tileleft = themes_path.."default/layouts/tileleftw.png"
-theme.layout_tile = themes_path.."default/layouts/tilew.png"
-theme.layout_tiletop = themes_path.."default/layouts/tiletopw.png"
-theme.layout_spiral = themes_path.."default/layouts/spiralw.png"
-theme.layout_dwindle = themes_path.."default/layouts/dwindlew.png"
-theme.layout_cornernw = themes_path.."default/layouts/cornernww.png"
-theme.layout_cornerne = themes_path.."default/layouts/cornernew.png"
-theme.layout_cornersw = themes_path.."default/layouts/cornersww.png"
-theme.layout_cornerse = themes_path.."default/layouts/cornersew.png"
+theme.widget.wrapper = {
+ layoutbox = { 12, 10, 6, 6 },
+ textclock = { 10, 10, 0, 0 },
+ volume = { 4, 9, 3, 3 },
+ network = { 10, 10, 5, 5 },
+ cpuram = { 10, 10, 5, 5 },
+ keyboard = { 10, 10, 4, 4 },
+ mail = { 10, 10, 4, 4 },
+ battery = { 8, 10, 7, 7 },
+ tray = { 8, 8, 7, 7 },
+ tasklist = { 4, 0, 0, 0 }, -- centering tasklist widget
+}
---icon
-
-theme.cpu_icon = icon_dir .. "cpu.png"
-theme.net_up = icon_dir .. "net_up.png"
-theme.net_down = icon_dir .. "net_down.png"
-theme.spr_right = icon_dir .. "spr_right.png"
-theme.mpd_icon = icon_dir .. "mpd.png"
-theme.ram_icon = icon_dir .. "ram.png"
--- Generate Awesome icon:
-theme.awesome_icon = theme_assets.awesome_icon(
- theme.menu_height, theme.bg_focus, theme.fg_focus
-)
-
--- Define the icon theme for application icons. If not set then the icons
--- from /usr/share/icons and /usr/share/icons/hicolor will be used.
-theme.icon_theme = nil
-
return theme
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/awesome/.config/awesome/themes/default/titlebar/close_focus.png b/awesome/.config/awesome/themes/default/titlebar/close_focus.png
deleted file mode 100644
index e4763b6..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/close_focus.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/close_normal.png b/awesome/.config/awesome/themes/default/titlebar/close_normal.png
deleted file mode 100644
index 7702839..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/close_normal.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/floating_focus_active.png b/awesome/.config/awesome/themes/default/titlebar/floating_focus_active.png
deleted file mode 100644
index 80c1b4a..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/floating_focus_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/floating_focus_inactive.png b/awesome/.config/awesome/themes/default/titlebar/floating_focus_inactive.png
deleted file mode 100644
index a96f00c..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/floating_focus_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/floating_normal_active.png b/awesome/.config/awesome/themes/default/titlebar/floating_normal_active.png
deleted file mode 100644
index b9c70ca..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/floating_normal_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/floating_normal_inactive.png b/awesome/.config/awesome/themes/default/titlebar/floating_normal_inactive.png
deleted file mode 100644
index 55cbc0c..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/floating_normal_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/maximized_focus_active.png b/awesome/.config/awesome/themes/default/titlebar/maximized_focus_active.png
deleted file mode 100644
index dad461d..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/maximized_focus_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/maximized_focus_inactive.png b/awesome/.config/awesome/themes/default/titlebar/maximized_focus_inactive.png
deleted file mode 100644
index 3cc46fe..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/maximized_focus_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/maximized_normal_active.png b/awesome/.config/awesome/themes/default/titlebar/maximized_normal_active.png
deleted file mode 100644
index 0bbbf6a..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/maximized_normal_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/maximized_normal_inactive.png b/awesome/.config/awesome/themes/default/titlebar/maximized_normal_inactive.png
deleted file mode 100644
index 5f1e98f..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/maximized_normal_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/minimize_focus.png b/awesome/.config/awesome/themes/default/titlebar/minimize_focus.png
deleted file mode 100644
index ff427b3..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/minimize_focus.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/minimize_normal.png b/awesome/.config/awesome/themes/default/titlebar/minimize_normal.png
deleted file mode 100644
index aa47447..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/minimize_normal.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/ontop_focus_active.png b/awesome/.config/awesome/themes/default/titlebar/ontop_focus_active.png
deleted file mode 100644
index d79c8e2..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/ontop_focus_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/ontop_focus_inactive.png b/awesome/.config/awesome/themes/default/titlebar/ontop_focus_inactive.png
deleted file mode 100644
index 03aef5a..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/ontop_focus_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/ontop_normal_active.png b/awesome/.config/awesome/themes/default/titlebar/ontop_normal_active.png
deleted file mode 100644
index e09f32d..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/ontop_normal_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/ontop_normal_inactive.png b/awesome/.config/awesome/themes/default/titlebar/ontop_normal_inactive.png
deleted file mode 100644
index 9917b9e..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/ontop_normal_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/sticky_focus_active.png b/awesome/.config/awesome/themes/default/titlebar/sticky_focus_active.png
deleted file mode 100644
index 8019463..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/sticky_focus_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/sticky_focus_inactive.png b/awesome/.config/awesome/themes/default/titlebar/sticky_focus_inactive.png
deleted file mode 100644
index 6d7fe40..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/sticky_focus_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/sticky_normal_active.png b/awesome/.config/awesome/themes/default/titlebar/sticky_normal_active.png
deleted file mode 100644
index 0d003ef..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/sticky_normal_active.png and /dev/null differ
diff --git a/awesome/.config/awesome/themes/default/titlebar/sticky_normal_inactive.png b/awesome/.config/awesome/themes/default/titlebar/sticky_normal_inactive.png
deleted file mode 100644
index f1e8789..0000000
Binary files a/awesome/.config/awesome/themes/default/titlebar/sticky_normal_inactive.png and /dev/null differ
diff --git a/awesome/.config/awesome/titlebar-config.lua b/awesome/.config/awesome/titlebar-config.lua
new file mode 100644
index 0000000..cf99707
--- /dev/null
+++ b/awesome/.config/awesome/titlebar-config.lua
@@ -0,0 +1,151 @@
+-----------------------------------------------------------------------------------------------------------------------
+-- Titlebar config --
+-----------------------------------------------------------------------------------------------------------------------
+
+-- Grab environment
+local awful = require("awful")
+local wibox = require("wibox")
+local beautiful = require("beautiful")
+
+-- local redflat = require("redflat")
+local redtitle = require("redflat.titlebar")
+local redutil = require("redflat.util")
+local clientmenu = require("redflat.float.clientmenu")
+
+-- Initialize tables and vars for module
+-----------------------------------------------------------------------------------------------------------------------
+local titlebar = {}
+
+-- Support functions
+-----------------------------------------------------------------------------------------------------------------------
+local function title_buttons(c)
+ return awful.util.table.join(
+ awful.button(
+ { }, 1,
+ function()
+ client.focus = c; c:raise()
+
+ awful.mouse.client.move(c)
+ end
+ ),
+ awful.button(
+ { }, 3,
+ function()
+ client.focus = c; c:raise()
+ clientmenu:show(c)
+ end
+ )
+ )
+end
+
+local function on_maximize(c)
+ -- hide/show title bar
+ local is_max = c.maximized_vertical or c.maximized
+ local action = is_max and "cut_all" or "restore_all"
+ redtitle[action]({ c })
+
+ -- dirty size correction
+ local model = redtitle.get_model(c)
+ if model and not model.hidden then
+ c.height = c:geometry().height + (is_max and model.size or -model.size)
+ if is_max then c.y = c.screen.workarea.y end
+ end
+end
+
+-- Connect titlebar building signal
+-----------------------------------------------------------------------------------------------------------------------
+function titlebar:init()
+
+ local style = {}
+
+ -- titlebar schemes
+ style.base = redutil.table.merge(redutil.table.check(beautiful, "titlebar.base") or {}, { size = 9 })
+ style.iconic = redutil.table.merge(style.base, { size = 24 })
+
+ -- titlebar elements styles
+ style.mark_mini = redutil.table.merge(
+ redutil.table.check(beautiful, "titlebar.mark") or {},
+ { size = 30, gap = 10, angle = 0 }
+ )
+ style.icon = redutil.table.merge(
+ redutil.table.check(beautiful, "titlebar.icon") or {},
+ { gap = 10 }
+ )
+
+ -- titlebar setup for clients
+ client.connect_signal(
+ "request::titlebars",
+ function(c)
+ -- build titlebar and mouse buttons for it
+ local buttons = title_buttons(c)
+ redtitle(c, style.base)
+
+ -- build mini titlebar model
+ local base = wibox.widget({
+ nil,
+ {
+ right = style.mark_mini.gap,
+ redtitle.mark.focus(c, style.mark_mini),
+ layout = wibox.container.margin,
+ },
+ {
+ redtitle.mark.property(c, "floating", style.mark_mini),
+ redtitle.mark.property(c, "sticky", style.mark_mini),
+ redtitle.mark.property(c, "ontop", style.mark_mini),
+ spacing = style.mark_mini.gap,
+ layout = wibox.layout.fixed.horizontal()
+ },
+ buttons = buttons,
+ layout = wibox.layout.align.horizontal,
+ })
+
+ -- build titlebar model with control buttons
+ local title = redtitle.label(c, style.iconic, true)
+ title:buttons(buttons)
+
+ local iconic = wibox.widget({
+ {
+ {
+ redtitle.button.focus(c, style.icon),
+ redtitle.button.property(c, "ontop", style.icon),
+ redtitle.button.property(c, "below", style.icon),
+ spacing = style.icon.gap,
+ layout = wibox.layout.fixed.horizontal()
+ },
+ top = 1, bottom = 1, left = 4, right = style.icon.gap + 2 * 18,
+ widget = wibox.container.margin
+ },
+ title,
+ {
+ {
+ redtitle.button.property(c, "floating", style.icon),
+ redtitle.button.property(c, "sticky", style.icon),
+ redtitle.button.property(c, "minimized", style.icon),
+ redtitle.button.property(c, "maximized", style.icon),
+ redtitle.button.close(c, style.icon),
+ spacing = style.icon.gap,
+ layout = wibox.layout.fixed.horizontal()
+ },
+ top = 1, bottom = 1, right = 4,
+ widget = wibox.container.margin
+ },
+ layout = wibox.layout.align.horizontal,
+ })
+
+ -- Set both models to titlebar
+ redtitle.add_layout(c, nil, base, style.base.size)
+ redtitle.add_layout(c, nil, iconic, style.iconic.size)
+ redtitle.switch(c, nil, redtitle._index)
+
+ -- hide titlebar when window maximized
+ if c.maximized_vertical or c.maximized then on_maximize(c) end
+
+ c:connect_signal("property::maximized_vertical", on_maximize)
+ c:connect_signal("property::maximized", on_maximize)
+ end
+ )
+end
+
+-- End
+-----------------------------------------------------------------------------------------------------------------------
+return titlebar