add layout env edge menu rules signal
This commit is contained in:
parent
a345c86326
commit
8b1c4c1a4a
76
awesome/.config/awesome/edges-config.lua
Normal file
76
awesome/.config/awesome/edges-config.lua
Normal file
@ -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
|
100
awesome/.config/awesome/env-config.lua
Normal file
100
awesome/.config/awesome/env-config.lua
Normal file
@ -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 self.terminal .. "-e ncmpcpp"
|
||||
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
|
27
awesome/.config/awesome/ercheck-config.lua
Normal file
27
awesome/.config/awesome/ercheck-config.lua
Normal file
@ -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
|
871
awesome/.config/awesome/keys-config.lua
Normal file
871
awesome/.config/awesome/keys-config.lua
Normal file
@ -0,0 +1,871 @@
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- Hotkeys and mouse buttons config --
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- Grab environment
|
||||
local table = table
|
||||
local awful = require("awful")
|
||||
local redflat = require("redflat")
|
||||
|
||||
-- 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({ }, 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)
|
||||
|
||||
-- Emacs like key sequences
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- initial key
|
||||
local keyseq = { { env.mod }, "c", {}, {} }
|
||||
|
||||
-- group
|
||||
keyseq[3] = {
|
||||
{ {}, "k", {}, {} }, -- application kill group
|
||||
{ {}, "c", {}, {} }, -- client managment group
|
||||
{ {}, "r", {}, {} }, -- client managment group
|
||||
{ {}, "n", {}, {} }, -- client managment group
|
||||
{ {}, "g", {}, {} }, -- run or rise group
|
||||
{ {}, "f", {}, {} }, -- launch application group
|
||||
}
|
||||
|
||||
-- quick launch key sequence actions
|
||||
for i = 1, 9 do
|
||||
local ik = tostring(i)
|
||||
table.insert(keyseq[3][5][3], {
|
||||
{}, ik, function() qlaunch:run_or_raise(ik) end,
|
||||
{ description = "Run or rise application №" .. ik, group = "Run or Rise", keyset = { ik } }
|
||||
})
|
||||
table.insert(keyseq[3][6][3], {
|
||||
{}, ik, function() qlaunch:run_or_raise(ik, true) end,
|
||||
{ description = "Launch application №".. ik, group = "Quick Launch", keyset = { ik } }
|
||||
})
|
||||
end
|
||||
|
||||
-- application kill sequence actions
|
||||
keyseq[3][1][3] = {
|
||||
{
|
||||
{}, "f", function() if client.focus then client.focus:kill() end end,
|
||||
{ description = "Kill focused client", group = "Kill application", keyset = { "f" } }
|
||||
},
|
||||
{
|
||||
{}, "a", kill_all,
|
||||
{ description = "Kill all clients with current tag", group = "Kill application", keyset = { "a" } }
|
||||
},
|
||||
}
|
||||
|
||||
-- client managment sequence actions
|
||||
keyseq[3][2][3] = {
|
||||
{
|
||||
{}, "p", function () toggle_placement(env) end,
|
||||
{ description = "Switch master/slave window placement", group = "Clients managment", keyset = { "p" } }
|
||||
},
|
||||
}
|
||||
|
||||
keyseq[3][3][3] = {
|
||||
{
|
||||
{}, "f", restore_client,
|
||||
{ description = "Restore minimized client", group = "Clients managment", keyset = { "f" } }
|
||||
},
|
||||
{
|
||||
{}, "a", restore_all,
|
||||
{ description = "Restore all clients with current tag", group = "Clients managment", keyset = { "a" } }
|
||||
},
|
||||
}
|
||||
|
||||
keyseq[3][4][3] = {
|
||||
{
|
||||
{}, "f", function() if client.focus then client.focus.minimized = true end end,
|
||||
{ description = "Minimized focused client", group = "Clients managment", keyset = { "f" } }
|
||||
},
|
||||
{
|
||||
{}, "a", minimize_all,
|
||||
{ description = "Minimized all clients with current tag", group = "Clients managment", keyset = { "a" } }
|
||||
},
|
||||
{
|
||||
{}, "e", minimize_all_except_focused,
|
||||
{ description = "Minimized all clients except focused", group = "Clients managment", keyset = { "e" } }
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
-- 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 = "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 = "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 }, "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 }, "c", function() redflat.float.keychain:activate(keyseq, "User") end,
|
||||
{ description = "[Hold] User key sequence", 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 }, "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
|
||||
}
|
||||
}
|
||||
|
||||
-- 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" }
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
awful.button({}, 8, function(c) c:kill() end)
|
||||
)
|
||||
|
||||
-- Set root hotkeys
|
||||
--------------------------------------------------------------------------------
|
||||
root.keys(self.keys.root)
|
||||
root.buttons(self.mouse.root)
|
||||
end
|
||||
|
||||
-- End
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
return hotkeys
|
86
awesome/.config/awesome/layout-config.lua
Normal file
86
awesome/.config/awesome/layout-config.lua
Normal file
@ -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
|
96
awesome/.config/awesome/menu.lua
Normal file
96
awesome/.config/awesome/menu.lua
Normal file
@ -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
|
2
awesome/.config/awesome/redflat/.gitignore
vendored
Normal file
2
awesome/.config/awesome/redflat/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
# IDE settings
|
||||
.idea
|
39
awesome/.config/awesome/redflat/.luacheckrc
Normal file
39
awesome/.config/awesome/redflat/.luacheckrc
Normal file
@ -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",
|
||||
}
|
201
awesome/.config/awesome/redflat/desktop/calendar.lua
Normal file
201
awesome/.config/awesome/redflat/desktop/calendar.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/desktop/common/bar/init.lua
Normal file
10
awesome/.config/awesome/redflat/desktop/common/bar/init.lua
Normal file
@ -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 })
|
114
awesome/.config/awesome/redflat/desktop/common/bar/plain.lua
Normal file
114
awesome/.config/awesome/redflat/desktop/common/bar/plain.lua
Normal file
@ -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)
|
144
awesome/.config/awesome/redflat/desktop/common/bar/shaped.lua
Normal file
144
awesome/.config/awesome/redflat/desktop/common/bar/shaped.lua
Normal file
@ -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)
|
121
awesome/.config/awesome/redflat/desktop/common/chart.lua
Normal file
121
awesome/.config/awesome/redflat/desktop/common/chart.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/desktop/common/init.lua
Normal file
10
awesome/.config/awesome/redflat/desktop/common/init.lua
Normal file
@ -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 })
|
10
awesome/.config/awesome/redflat/desktop/common/pack/init.lua
Normal file
10
awesome/.config/awesome/redflat/desktop/common/pack/init.lua
Normal file
@ -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 })
|
137
awesome/.config/awesome/redflat/desktop/common/pack/lines.lua
Normal file
137
awesome/.config/awesome/redflat/desktop/common/pack/lines.lua
Normal file
@ -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)
|
@ -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)
|
158
awesome/.config/awesome/redflat/desktop/common/textbox.lua
Normal file
158
awesome/.config/awesome/redflat/desktop/common/textbox.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/desktop/init.lua
Normal file
10
awesome/.config/awesome/redflat/desktop/init.lua
Normal file
@ -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 })
|
136
awesome/.config/awesome/redflat/desktop/multiline.lua
Normal file
136
awesome/.config/awesome/redflat/desktop/multiline.lua
Normal file
@ -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)
|
167
awesome/.config/awesome/redflat/desktop/multimeter.lua
Normal file
167
awesome/.config/awesome/redflat/desktop/multimeter.lua
Normal file
@ -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)
|
138
awesome/.config/awesome/redflat/desktop/singleline.lua
Normal file
138
awesome/.config/awesome/redflat/desktop/singleline.lua
Normal file
@ -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)
|
173
awesome/.config/awesome/redflat/desktop/speedmeter/compact.lua
Normal file
173
awesome/.config/awesome/redflat/desktop/speedmeter/compact.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/desktop/speedmeter/init.lua
Normal file
10
awesome/.config/awesome/redflat/desktop/speedmeter/init.lua
Normal file
@ -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 })
|
199
awesome/.config/awesome/redflat/desktop/speedmeter/normal.lua
Normal file
199
awesome/.config/awesome/redflat/desktop/speedmeter/normal.lua
Normal file
@ -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)
|
98
awesome/.config/awesome/redflat/desktop/textset.lua
Normal file
98
awesome/.config/awesome/redflat/desktop/textset.lua
Normal file
@ -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('<span color="%s">%s</span>', 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)
|
367
awesome/.config/awesome/redflat/float/apprunner.lua
Normal file
367
awesome/.config/awesome/redflat/float/apprunner.lua
Normal file
@ -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
|
459
awesome/.config/awesome/redflat/float/appswitcher.lua
Normal file
459
awesome/.config/awesome/redflat/float/appswitcher.lua
Normal file
@ -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('<span color="%s">[%s]</span>', 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
|
221
awesome/.config/awesome/redflat/float/bartip.lua
Normal file
221
awesome/.config/awesome/redflat/float/bartip.lua
Normal file
@ -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(
|
||||
'<span color="%s">%s</span><span color="%s">%s</span>',
|
||||
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
|
62
awesome/.config/awesome/redflat/float/brightness.lua
Normal file
62
awesome/.config/awesome/redflat/float/brightness.lua
Normal file
@ -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
|
383
awesome/.config/awesome/redflat/float/clientmenu.lua
Normal file
383
awesome/.config/awesome/redflat/float/clientmenu.lua
Normal file
@ -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)
|
358
awesome/.config/awesome/redflat/float/control.lua
Normal file
358
awesome/.config/awesome/redflat/float/control.lua
Normal file
@ -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(
|
||||
'<span color="%s">%s</span><span color="%s"> [%d]</span>',
|
||||
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
|
88
awesome/.config/awesome/redflat/float/decoration.lua
Normal file
88
awesome/.config/awesome/redflat/float/decoration.lua
Normal file
@ -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
|
361
awesome/.config/awesome/redflat/float/hotkeys.lua
Normal file
361
awesome/.config/awesome/redflat/float/hotkeys.lua
Normal file
@ -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(
|
||||
'<span font="%s" color="%s">%s</span>',
|
||||
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('<b>%s</b>', 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('<b>%s</b>', v) end
|
||||
table.insert(fm, line)
|
||||
line = table.concat(fm, string.format('<span color="%s">+</span>', 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(
|
||||
'<span color="%s"><span font="%s">%s</span>%s%s</span>',
|
||||
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
|
10
awesome/.config/awesome/redflat/float/init.lua
Normal file
10
awesome/.config/awesome/redflat/float/init.lua
Normal file
@ -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 })
|
202
awesome/.config/awesome/redflat/float/keychain.lua
Normal file
202
awesome/.config/awesome/redflat/float/keychain.lua
Normal file
@ -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
|
140
awesome/.config/awesome/redflat/float/notify.lua
Normal file
140
awesome/.config/awesome/redflat/float/notify.lua
Normal file
@ -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
|
506
awesome/.config/awesome/redflat/float/player.lua
Normal file
506
awesome/.config/awesome/redflat/float/player.lua
Normal file
@ -0,0 +1,506 @@
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- 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('<span color="' .. style.color.gray .. '">From </span>' .. self.info.album)
|
||||
else
|
||||
self.box.artist:set_markup('<span color="' .. style.color.gray .. '">By </span>' .. 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
|
99
awesome/.config/awesome/redflat/float/prompt.lua
Normal file
99
awesome/.config/awesome/redflat/float/prompt.lua
Normal file
@ -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
|
510
awesome/.config/awesome/redflat/float/qlaunch.lua
Normal file
510
awesome/.config/awesome/redflat/float/qlaunch.lua
Normal file
@ -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('<span color="%s">%s</span>', 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
|
156
awesome/.config/awesome/redflat/float/tooltip.lua
Normal file
156
awesome/.config/awesome/redflat/float/tooltip.lua
Normal file
@ -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)
|
379
awesome/.config/awesome/redflat/float/top.lua
Normal file
379
awesome/.config/awesome/redflat/float/top.lua
Normal file
@ -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
|
80
awesome/.config/awesome/redflat/gauge/audio/blue.lua
Normal file
80
awesome/.config/awesome/redflat/gauge/audio/blue.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/audio/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/audio/init.lua
Normal file
@ -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 })
|
93
awesome/.config/awesome/redflat/gauge/audio/red.lua
Normal file
93
awesome/.config/awesome/redflat/gauge/audio/red.lua
Normal file
@ -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)
|
80
awesome/.config/awesome/redflat/gauge/graph/bar.lua
Normal file
80
awesome/.config/awesome/redflat/gauge/graph/bar.lua
Normal file
@ -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)
|
88
awesome/.config/awesome/redflat/gauge/graph/dash.lua
Normal file
88
awesome/.config/awesome/redflat/gauge/graph/dash.lua
Normal file
@ -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)
|
109
awesome/.config/awesome/redflat/gauge/graph/dots.lua
Normal file
109
awesome/.config/awesome/redflat/gauge/graph/dots.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/graph/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/graph/init.lua
Normal file
@ -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 })
|
96
awesome/.config/awesome/redflat/gauge/icon/double.lua
Normal file
96
awesome/.config/awesome/redflat/gauge/icon/double.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/icon/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/icon/init.lua
Normal file
@ -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 })
|
95
awesome/.config/awesome/redflat/gauge/icon/single.lua
Normal file
95
awesome/.config/awesome/redflat/gauge/icon/single.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/init.lua
Normal file
@ -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 })
|
109
awesome/.config/awesome/redflat/gauge/monitor/circle.lua
Normal file
109
awesome/.config/awesome/redflat/gauge/monitor/circle.lua
Normal file
@ -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)
|
98
awesome/.config/awesome/redflat/gauge/monitor/dash.lua
Normal file
98
awesome/.config/awesome/redflat/gauge/monitor/dash.lua
Normal file
@ -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)
|
130
awesome/.config/awesome/redflat/gauge/monitor/double.lua
Normal file
130
awesome/.config/awesome/redflat/gauge/monitor/double.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/monitor/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/monitor/init.lua
Normal file
@ -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 })
|
113
awesome/.config/awesome/redflat/gauge/monitor/plain.lua
Normal file
113
awesome/.config/awesome/redflat/gauge/monitor/plain.lua
Normal file
@ -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)
|
87
awesome/.config/awesome/redflat/gauge/separator.lua
Normal file
87
awesome/.config/awesome/redflat/gauge/separator.lua
Normal file
@ -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
|
218
awesome/.config/awesome/redflat/gauge/svgbox.lua
Normal file
218
awesome/.config/awesome/redflat/gauge/svgbox.lua
Normal file
@ -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)
|
125
awesome/.config/awesome/redflat/gauge/tag/blue.lua
Normal file
125
awesome/.config/awesome/redflat/gauge/tag/blue.lua
Normal file
@ -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)
|
89
awesome/.config/awesome/redflat/gauge/tag/green.lua
Normal file
89
awesome/.config/awesome/redflat/gauge/tag/green.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/gauge/tag/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/tag/init.lua
Normal file
@ -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 })
|
141
awesome/.config/awesome/redflat/gauge/tag/orange.lua
Normal file
141
awesome/.config/awesome/redflat/gauge/tag/orange.lua
Normal file
@ -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)
|
191
awesome/.config/awesome/redflat/gauge/tag/red.lua
Normal file
191
awesome/.config/awesome/redflat/gauge/tag/red.lua
Normal file
@ -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)
|
114
awesome/.config/awesome/redflat/gauge/tag/ruby.lua
Normal file
114
awesome/.config/awesome/redflat/gauge/tag/ruby.lua
Normal file
@ -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)
|
116
awesome/.config/awesome/redflat/gauge/task/green.lua
Normal file
116
awesome/.config/awesome/redflat/gauge/task/green.lua
Normal file
@ -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('<span background="%s">' .. style.counter.mask .. '</span>', 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)
|
10
awesome/.config/awesome/redflat/gauge/task/init.lua
Normal file
10
awesome/.config/awesome/redflat/gauge/task/init.lua
Normal file
@ -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 })
|
120
awesome/.config/awesome/redflat/gauge/task/red.lua
Normal file
120
awesome/.config/awesome/redflat/gauge/task/red.lua
Normal file
@ -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)
|
137
awesome/.config/awesome/redflat/gauge/task/ruby.lua
Normal file
137
awesome/.config/awesome/redflat/gauge/task/ruby.lua
Normal file
@ -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)
|
12
awesome/.config/awesome/redflat/init.lua
Normal file
12
awesome/.config/awesome/redflat/init.lua
Normal file
@ -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 }
|
||||
)
|
371
awesome/.config/awesome/redflat/layout/common.lua
Normal file
371
awesome/.config/awesome/redflat/layout/common.lua
Normal file
@ -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
|
480
awesome/.config/awesome/redflat/layout/grid.lua
Normal file
480
awesome/.config/awesome/redflat/layout/grid.lua
Normal file
@ -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
|
10
awesome/.config/awesome/redflat/layout/init.lua
Normal file
10
awesome/.config/awesome/redflat/layout/init.lua
Normal file
@ -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 })
|
688
awesome/.config/awesome/redflat/layout/map.lua
Normal file
688
awesome/.config/awesome/redflat/layout/map.lua
Normal file
@ -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
|
676
awesome/.config/awesome/redflat/menu.lua
Normal file
676
awesome/.config/awesome/redflat/menu.lua
Normal file
@ -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, "<u>" .. rkey .. "</u>", 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)
|
412
awesome/.config/awesome/redflat/service/dfparser.lua
Normal file
412
awesome/.config/awesome/redflat/service/dfparser.lua
Normal file
@ -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
|
10
awesome/.config/awesome/redflat/service/init.lua
Normal file
10
awesome/.config/awesome/redflat/service/init.lua
Normal file
@ -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 })
|
355
awesome/.config/awesome/redflat/service/navigator.lua
Normal file
355
awesome/.config/awesome/redflat/service/navigator.lua
Normal file
@ -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
|
44
awesome/.config/awesome/redflat/startup.lua
Normal file
44
awesome/.config/awesome/redflat/startup.lua
Normal file
@ -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
|
753
awesome/.config/awesome/redflat/system.lua
Normal file
753
awesome/.config/awesome/redflat/system.lua
Normal file
@ -0,0 +1,753 @@
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- RedFlat system --
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- System monitoring functions collected here
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- Some code was taken from
|
||||
------ vicious module
|
||||
------ (c) 2010, 2011 Adrian C. <anrxc@sysphere.org>
|
||||
------ (c) 2009, Lucas de Vries <lucas@glacicle.com>
|
||||
------ (c) 2011, Jörg T. <jthalheim@gmail.com>
|
||||
------ (c) 2011, Adrian C. <anrxc@sysphere.org>
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- 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
|
||||
|
||||
-- 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
|
||||
-- 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 }
|
||||
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
|
442
awesome/.config/awesome/redflat/titlebar.lua
Normal file
442
awesome/.config/awesome/redflat/titlebar.lua
Normal file
@ -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('<span color="%s">%s</span>', 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)
|
66
awesome/.config/awesome/redflat/util/base.lua
Normal file
66
awesome/.config/awesome/redflat/util/base.lua
Normal file
@ -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
|
||||
|
35
awesome/.config/awesome/redflat/util/cairo.lua
Normal file
35
awesome/.config/awesome/redflat/util/cairo.lua
Normal file
@ -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
|
54
awesome/.config/awesome/redflat/util/client.lua
Normal file
54
awesome/.config/awesome/redflat/util/client.lua
Normal file
@ -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
|
||||
|
126
awesome/.config/awesome/redflat/util/desktop.lua
Normal file
126
awesome/.config/awesome/redflat/util/desktop.lua
Normal file
@ -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
|
||||
|
14
awesome/.config/awesome/redflat/util/init.lua
Normal file
14
awesome/.config/awesome/redflat/util/init.lua
Normal file
@ -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 })
|
67
awesome/.config/awesome/redflat/util/key.lua
Normal file
67
awesome/.config/awesome/redflat/util/key.lua
Normal file
@ -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
|
||||
|
64
awesome/.config/awesome/redflat/util/placement.lua
Normal file
64
awesome/.config/awesome/redflat/util/placement.lua
Normal file
@ -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
|
||||
|
32
awesome/.config/awesome/redflat/util/read.lua
Normal file
32
awesome/.config/awesome/redflat/util/read.lua
Normal file
@ -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
|
45
awesome/.config/awesome/redflat/util/table.lua
Normal file
45
awesome/.config/awesome/redflat/util/table.lua
Normal file
@ -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_
|
||||
|
41
awesome/.config/awesome/redflat/util/text.lua
Normal file
41
awesome/.config/awesome/redflat/util/text.lua
Normal file
@ -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
|
||||
|
99
awesome/.config/awesome/redflat/widget/battery.lua
Normal file
99
awesome/.config/awesome/redflat/widget/battery.lua
Normal file
@ -0,0 +1,99 @@
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
-- 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)
|
125
awesome/.config/awesome/redflat/widget/binclock.lua
Normal file
125
awesome/.config/awesome/redflat/widget/binclock.lua
Normal file
@ -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)
|
10
awesome/.config/awesome/redflat/widget/init.lua
Normal file
10
awesome/.config/awesome/redflat/widget/init.lua
Normal file
@ -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 })
|
135
awesome/.config/awesome/redflat/widget/keyboard.lua
Normal file
135
awesome/.config/awesome/redflat/widget/keyboard.lua
Normal file
@ -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)
|
168
awesome/.config/awesome/redflat/widget/layoutbox.lua
Normal file
168
awesome/.config/awesome/redflat/widget/layoutbox.lua
Normal file
@ -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)
|
196
awesome/.config/awesome/redflat/widget/mail.lua
Normal file
196
awesome/.config/awesome/redflat/widget/mail.lua
Normal file
@ -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)
|
175
awesome/.config/awesome/redflat/widget/minitray.lua
Normal file
175
awesome/.config/awesome/redflat/widget/minitray.lua
Normal file
@ -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)
|
101
awesome/.config/awesome/redflat/widget/net.lua
Normal file
101
awesome/.config/awesome/redflat/widget/net.lua
Normal file
@ -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)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user