366 lines
9.7 KiB
Lua
Executable file
366 lines
9.7 KiB
Lua
Executable file
local wibox = require("wibox")
|
|
local beautiful = require("beautiful")
|
|
local dpi = beautiful.xresources.apply_dpi
|
|
local awful = require("awful")
|
|
local gears = require("gears")
|
|
local rubato = require(tostring(...):match(".*awedock") .. ".rubato")
|
|
|
|
local function helpers()
|
|
local function overloaded()
|
|
local fns = {}
|
|
local mt = {}
|
|
local function oerror()
|
|
return error("Invalid argument types to overloaded function")
|
|
end
|
|
function mt:__call(...)
|
|
local arg = { ... }
|
|
local default = self.default
|
|
local signature = {}
|
|
for i, arg in ipairs({ ... }) do
|
|
signature[i] = type(arg)
|
|
end
|
|
signature = table.concat(signature, ",")
|
|
return (fns[signature] or self.default)(...)
|
|
end
|
|
function mt:__index(key)
|
|
local signature = {}
|
|
local function __newindex(self, key, value)
|
|
print(key, type(key), value, type(value))
|
|
signature[#signature + 1] = key
|
|
fns[table.concat(signature, ",")] = value
|
|
print("bind", table.concat(signature, ", "))
|
|
end
|
|
local function __index(self, key)
|
|
print("I", key, type(key))
|
|
signature[#signature + 1] = key
|
|
return setmetatable({}, { __index = __index, __newindex = __newindex })
|
|
end
|
|
return __index(self, key)
|
|
end
|
|
function mt:__newindex(key, value)
|
|
fns[key] = value
|
|
end
|
|
return setmetatable({ default = oerror }, mt)
|
|
end
|
|
--}}}
|
|
|
|
local function dec_hex(IN)
|
|
local B, K, OUT, I, D = 16, "0123456789ABCDEF", "", 0
|
|
while IN > 0 do
|
|
I = I + 1
|
|
IN, D = math.floor(IN / B), (IN % B) + 1
|
|
OUT = string.sub(K, D, D) .. OUT
|
|
end
|
|
return #OUT == 2 and OUT or "0" .. OUT
|
|
end
|
|
|
|
-- color helpers {{{
|
|
local color = {}
|
|
|
|
color.col_shift = overloaded()
|
|
color.col_shift.string.number = function(c, s)
|
|
local r, g, b, o = gears.color.parse_color(c)
|
|
return "#" .. dec_hex(r * 255 + s) .. dec_hex(g * 255 + s) .. dec_hex(b * 255 + s) .. dec_hex(o * 255)
|
|
end
|
|
color.col_shift.string.number.number.number = function(c, sr, sg, sb)
|
|
local r, g, b, o = gears.color.parse_color(c)
|
|
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255)
|
|
end
|
|
color.col_shift.string.number.number.number.number = function(c, sr, sg, sb, so)
|
|
local r, g, b, o = gears.color.parse_color(c)
|
|
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255 + so)
|
|
end
|
|
|
|
color.col_diff = function(f, s)
|
|
local fr, fg, fb, fo = gears.color.parse_color(f)
|
|
local sr, sg, sb, so = gears.color.parse_color(s)
|
|
return sr - fr, sg - fg, sb - fb, so - fo
|
|
end
|
|
--}}}
|
|
return {
|
|
color = color,
|
|
}
|
|
end
|
|
|
|
local chel = helpers().color
|
|
|
|
--local function init(s, h, o, shape, pinneds)
|
|
local function init(args)
|
|
local s = args.screen
|
|
local h = args.height or dpi(50)
|
|
local o = args.offset or 5
|
|
local inner_shape = args.inner_shape or gears.shape.rectangle
|
|
local outer_shape = args.outer_shape or gears.shape.rectangle
|
|
local pinneds = args.pinneds
|
|
|
|
-- tasklist creation {{{
|
|
local tasklist = awful.widget.tasklist({
|
|
screen = s,
|
|
source = function()
|
|
local ret = {}
|
|
for _, t in ipairs(s.tags) do
|
|
gears.table.merge(ret, t:clients())
|
|
end
|
|
return ret
|
|
end, --sorts clients in order of their tags
|
|
filter = awful.widget.tasklist.filter.alltags,
|
|
forced_height = h,
|
|
layout = {
|
|
layout = wibox.layout.fixed.horizontal,
|
|
},
|
|
widget_template = {
|
|
{
|
|
{
|
|
nil,
|
|
{
|
|
{
|
|
awful.widget.clienticon,
|
|
widget = wibox.container.place,
|
|
halign = "center",
|
|
valign = "center",
|
|
},
|
|
widget = wibox.container.margin,
|
|
margins = h / 10,
|
|
},
|
|
{
|
|
{
|
|
wibox.widget.base.make_widget(),
|
|
forced_height = h / 10,
|
|
forced_width = h / 10,
|
|
id = "status",
|
|
bg = beautiful.dock_unfocused_indicator_bg or "#484E5B",
|
|
shape = inner_shape,
|
|
widget = wibox.container.background,
|
|
},
|
|
widget = wibox.container.place, --so the bg widget doesnt get stretched
|
|
},
|
|
layout = wibox.layout.align.vertical,
|
|
},
|
|
id = "bg",
|
|
widget = wibox.container.background,
|
|
bg = beautiful.dock_bg or "#061115",
|
|
shape = inner_shape,
|
|
},
|
|
widget = wibox.container.margin,
|
|
margins = h / 10,
|
|
forced_height = h,
|
|
forced_width = h,
|
|
create_callback = function(self, c, _, _)
|
|
local function hover(p, t) --so gc can collect all the timed objects that are flying around
|
|
local on_hover = rubato.timed({
|
|
intro = 0.02,
|
|
outro = 0.02,
|
|
duration = 0.2,
|
|
rate = 30,
|
|
pos = p,
|
|
subscribed = function(pos)
|
|
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
|
|
end,
|
|
})
|
|
on_hover.target = t
|
|
end
|
|
self:connect_signal("mouse::enter", function()
|
|
hover(0, 20)
|
|
end)
|
|
self:connect_signal("mouse::leave", function()
|
|
hover(20, 0)
|
|
end)
|
|
self:add_button(awful.button({
|
|
modifiers = {},
|
|
button = 1,
|
|
on_press = function()
|
|
if not c.active then
|
|
c:activate({
|
|
context = "through_dock",
|
|
switch_to_tag = true,
|
|
})
|
|
else
|
|
c.minimized = true
|
|
end
|
|
end,
|
|
}))
|
|
end,
|
|
update_callback = function(self, c, _, _) --praying to the gc that this is getting cleared properly, didnt show problems in testing
|
|
collectgarbage("collect")
|
|
local status_w = rubato.timed({
|
|
intro = 0.02,
|
|
outro = 0.02,
|
|
duration = 0.1,
|
|
rate = 30,
|
|
pos = self:get_children_by_id("status")[1].forced_width,
|
|
subscribed = function(pos)
|
|
self:get_children_by_id("status")[1].forced_width = pos
|
|
end,
|
|
})
|
|
local bg_col = beautiful.dock_unfocused_indicator_bg or "#484E5B"
|
|
local bg_focus_col = beautiful.dock_indicator_bg or "#6791C9"
|
|
local sh_r, sh_g, sh_b, _ = chel.col_diff(bg_col, bg_focus_col)
|
|
|
|
local status_c = rubato.timed({
|
|
intro = 0.04,
|
|
outro = 0.04,
|
|
duration = 0.2,
|
|
rate = 30,
|
|
pos = 0,
|
|
subscribed = function(pos)
|
|
self:get_children_by_id("status")[1].bg = chel.col_shift(
|
|
bg_col,
|
|
math.floor(pos * (255 * sh_r)),
|
|
math.floor((sh_g * 255) * pos),
|
|
math.floor((sh_b * 255) * pos)
|
|
)
|
|
end,
|
|
})
|
|
--this here sets width and colors depending on the status of the client a widget in the tasklist represents
|
|
if c.active then
|
|
status_w.target = h / 2
|
|
status_c.target = 1
|
|
elseif c.minimized then
|
|
status_w.target = h / 10
|
|
status_c.target = 0
|
|
else
|
|
status_w.target = h / 3
|
|
status_c.target = 0
|
|
end
|
|
end,
|
|
},
|
|
})
|
|
|
|
-- }}}
|
|
-- the funny desktop starters {{{
|
|
local pinned_apps = pinneds and { layout = wibox.layout.fixed.horizontal } or nil
|
|
if pinneds then
|
|
for _, p in ipairs(pinneds) do
|
|
pinned_apps[#pinned_apps + 1] = wibox.widget({
|
|
{
|
|
{
|
|
nil,
|
|
{
|
|
{
|
|
{
|
|
widget = wibox.widget.imagebox,
|
|
image = p.icon,
|
|
resize = true,
|
|
},
|
|
margins = dpi(5),
|
|
widget = wibox.container.margin,
|
|
},
|
|
widget = wibox.container.place,
|
|
halign = "center",
|
|
valign = "center",
|
|
},
|
|
{
|
|
{
|
|
wibox.widget.base.make_widget(),
|
|
forced_height = h / 10,
|
|
forced_width = h / 10,
|
|
id = "status",
|
|
shape = inner_shape,
|
|
widget = wibox.container.background,
|
|
},
|
|
widget = wibox.container.place, --so the bg widget doesnt get stretched
|
|
halign = "center",
|
|
},
|
|
layout = wibox.layout.align.vertical,
|
|
},
|
|
widget = wibox.container.background,
|
|
shape = inner_shape,
|
|
id = "bg",
|
|
buttons = awful.button({}, 1, function()
|
|
awful.spawn.easy_async(p.start_cmd)
|
|
end),
|
|
},
|
|
widget = wibox.container.margin,
|
|
margins = h / 10,
|
|
forced_width = h,
|
|
forced_height = h,
|
|
})
|
|
local self = pinned_apps[#pinned_apps]
|
|
local function hover(po, t) --so gc can collect all the timed objects that are flying around
|
|
local on_hover = rubato.timed({
|
|
intro = 0.02,
|
|
outro = 0.02,
|
|
duration = 0.2,
|
|
rate = 30,
|
|
pos = po,
|
|
subscribed = function(pos)
|
|
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
|
|
end,
|
|
})
|
|
on_hover.target = t
|
|
end
|
|
self:connect_signal("mouse::enter", function()
|
|
hover(0, 20)
|
|
end)
|
|
self:connect_signal("mouse::leave", function()
|
|
hover(20, 0)
|
|
end)
|
|
self:add_button(
|
|
awful.button({ --this is very hacky. Please do NOT COPY if you are looking for suggestions on how to implement this
|
|
modifiers = {},
|
|
button = 1,
|
|
on_press = function() end,
|
|
})
|
|
)
|
|
end
|
|
end
|
|
-- }}}
|
|
local dock_box = awful.popup({
|
|
ontop = true,
|
|
screen = s,
|
|
x = s.geometry.x + s.geometry.width / 2,
|
|
y = s.geometry.y + s.geometry.height - (h + o),
|
|
shape = outer_shape,
|
|
widget = {
|
|
{
|
|
{
|
|
pinned_apps,
|
|
tasklist,
|
|
layout = wibox.layout.fixed.horizontal,
|
|
},
|
|
widget = wibox.container.margin,
|
|
margin = dpi(5),
|
|
},
|
|
widget = wibox.container.background,
|
|
bg = beautiful.dock_bg or "#061115",
|
|
shape = inner_shape,
|
|
},
|
|
})
|
|
|
|
dock_box:connect_signal("property::width", function() --for centered placement, wanted to keep the offset
|
|
dock_box.x = s.geometry.x + s.geometry.width / 2 - dock_box.width / 2
|
|
end)
|
|
|
|
local autohideanim = rubato.timed({
|
|
intro = 0.3,
|
|
outro = 0.1,
|
|
duration = 0.4,
|
|
pos = 0,
|
|
rate = 60,
|
|
easing = rubato.quadratic,
|
|
subscribed = function(pos)
|
|
dock_box.y = s.geometry.y + s.geometry.height - ((pos * h) + o)
|
|
dock_box.opacity = pos
|
|
end,
|
|
})
|
|
local autohidetimer = gears.timer({
|
|
timeout = 2,
|
|
single_shot = true,
|
|
callback = function()
|
|
autohideanim.target = 0
|
|
end,
|
|
})
|
|
dock_box:connect_signal("mouse::leave", function()
|
|
autohidetimer:again()
|
|
end)
|
|
dock_box:connect_signal("mouse::enter", function()
|
|
autohideanim.target = 1
|
|
autohidetimer:stop()
|
|
end)
|
|
return dock_box
|
|
end
|
|
|
|
return {
|
|
init = init,
|
|
}
|