aboutsummaryrefslogtreecommitdiff
path: root/.config
diff options
context:
space:
mode:
Diffstat (limited to '.config')
-rw-r--r--.config/awesome/assets/phosphor/arrow-clockwise-bold.svg1
-rw-r--r--.config/awesome/assets/phosphor/arrow-clockwise-fill.svg1
-rw-r--r--.config/awesome/assets/phosphor/arrows-in-simple-fill.svg1
-rw-r--r--.config/awesome/assets/phosphor/arrows-out-simple-fill.svg1
-rw-r--r--.config/awesome/assets/phosphor/caret-left-bold.svg1
-rw-r--r--.config/awesome/assets/phosphor/caret-right-bold.svg1
-rw-r--r--.config/awesome/assets/phosphor/init.lua3
-rw-r--r--.config/awesome/assets/phosphor/lock-simple-fill.svg1
-rw-r--r--.config/awesome/assets/phosphor/power-bold.svg1
-rw-r--r--.config/awesome/assets/phosphor/power-fill.svg1
-rw-r--r--.config/awesome/assets/phosphor/sign-out-bold.svg1
-rw-r--r--.config/awesome/assets/phosphor/sign-out-fill.svg1
-rw-r--r--.config/awesome/assets/sounds/vixui-acconnect.wavbin0 -> 548932 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-acdisconnect.wavbin0 -> 548768 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-boot.wavbin0 -> 1317008 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-notifa.wavbin0 -> 548978 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-notifb.wavbin0 -> 548738 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-usbconnect.wavbin0 -> 548782 bytes
-rw-r--r--.config/awesome/assets/sounds/vixui-usbdisconnect.wavbin0 -> 548656 bytes
-rw-r--r--.config/awesome/curious.lua100
-rw-r--r--.config/awesome/misc/autostart.lua6
-rw-r--r--.config/awesome/misc/cfg.lua14
-rw-r--r--.config/awesome/misc/keys.lua137
-rw-r--r--.config/awesome/misc/rules.lua161
-rw-r--r--.config/awesome/prismite.lua9
-rw-r--r--.config/awesome/quarrel/bezier.lua343
-rw-r--r--.config/awesome/quarrel/bind.lua101
-rw-r--r--.config/awesome/quarrel/delegate.lua14
-rw-r--r--.config/awesome/quarrel/fs.lua21
-rw-r--r--.config/awesome/quarrel/init.lua21
-rw-r--r--.config/awesome/quarrel/json.lua516
-rw-r--r--.config/awesome/quarrel/lua-rust.tar.gzbin0 -> 18878 bytes
-rw-r--r--.config/awesome/quarrel/markup.lua30
-rw-r--r--.config/awesome/quarrel/math.lua9
-rw-r--r--.config/awesome/quarrel/native/Cargo.toml7
-rw-r--r--.config/awesome/quarrel/native/init.lua37
-rw-r--r--.config/awesome/quarrel/native/src/lenses/application.rs2
-rw-r--r--.config/awesome/quarrel/native/src/lenses/calculator.rs2
-rw-r--r--.config/awesome/quarrel/native/src/lib.rs22
-rw-r--r--.config/awesome/quarrel/native/src/mpd.rs142
-rw-r--r--.config/awesome/quarrel/native/src/net/mod.rs5
-rw-r--r--.config/awesome/quarrel/native/src/time.rs75
-rw-r--r--.config/awesome/quarrel/native/src/util.rs101
-rw-r--r--.config/awesome/quarrel/store.lua1
-rw-r--r--.config/awesome/quarrel/table.lua23
-rw-r--r--.config/awesome/quarrel/ui.lua94
-rw-r--r--.config/awesome/quarrel/vars.lua45
-rw-r--r--.config/awesome/rc.lua33
-rw-r--r--.config/awesome/services/backlight.lua34
-rw-r--r--.config/awesome/services/battery.lua81
-rw-r--r--.config/awesome/services/common.lua87
-rw-r--r--.config/awesome/services/init.lua1
-rw-r--r--.config/awesome/services/osd.lua7
-rw-r--r--.config/awesome/services/playerctl.lua6
-rw-r--r--.config/awesome/signals/awesome.lua20
-rw-r--r--.config/awesome/signals/client.lua18
-rw-r--r--.config/awesome/signals/init.lua1
-rw-r--r--.config/awesome/signals/naughty.lua292
-rw-r--r--.config/awesome/signals/screen.lua9
-rw-r--r--.config/awesome/stylua.toml5
-rw-r--r--.config/awesome/ui/conductor/init.lua24
-rw-r--r--.config/awesome/ui/decorations/mpd.lua13
-rw-r--r--.config/awesome/ui/decorations/wallpaper.lua30
-rw-r--r--.config/awesome/ui/fresnel/init.lua181
-rw-r--r--.config/awesome/ui/init.lua2
-rw-r--r--.config/awesome/ui/insightful/init.lua80
-rw-r--r--.config/awesome/ui/osd.lua102
-rw-r--r--.config/awesome/ui/powermenu/init.lua114
-rw-r--r--.config/awesome/ui/statusbar/init.lua75
-rw-r--r--.config/awesome/ui/statusbar/panel/init.lua20
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/battery.lua70
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/calendar.lua155
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/displays.lua36
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/imagebox.lua144
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/linegraph.lua154
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/music.lua187
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/power_menu.lua36
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/wifi.lua18
-rw-r--r--.config/awesome/ui/statusbar/widgets/clock.lua8
-rw-r--r--.config/awesome/ui/statusbar/widgets/displays.lua34
-rw-r--r--.config/awesome/ui/statusbar/widgets/keyboardlayout.lua307
-rw-r--r--.config/awesome/ui/statusbar/widgets/taglist.lua127
-rw-r--r--.config/awesome/ui/statusbar/widgets/tasklist.lua30
-rw-r--r--.config/awesome/ui/wicked/_default.lua94
-rw-r--r--.config/awesome/ui/wicked/init.lua258
-rw-r--r--.config/awesome/ui/wicked/widgets/message.lua0
86 files changed, 3216 insertions, 1729 deletions
diff --git a/.config/awesome/assets/phosphor/arrow-clockwise-bold.svg b/.config/awesome/assets/phosphor/arrow-clockwise-bold.svg
new file mode 100644
index 0000000..142f27a
--- /dev/null
+++ b/.config/awesome/assets/phosphor/arrow-clockwise-bold.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M244,56v48a12,12,0,0,1-12,12H184a12,12,0,1,1,0-24H201.1l-19-17.38c-.13-.12-.26-.24-.38-.37A76,76,0,1,0,127,204h1a75.53,75.53,0,0,0,52.15-20.72,12,12,0,0,1,16.49,17.45A99.45,99.45,0,0,1,128,228h-1.37A100,100,0,1,1,198.51,57.06L220,76.72V56a12,12,0,0,1,24,0Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/arrow-clockwise-fill.svg b/.config/awesome/assets/phosphor/arrow-clockwise-fill.svg
new file mode 100644
index 0000000..b4eda78
--- /dev/null
+++ b/.config/awesome/assets/phosphor/arrow-clockwise-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1-5.66-13.66l17-17-10.55-9.65-.25-.24a80,80,0,1,0-1.67,114.78,8,8,0,1,1,11,11.63A95.44,95.44,0,0,1,128,224h-1.32A96,96,0,1,1,195.75,60l10.93,10L226.34,50.3A8,8,0,0,1,240,56Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/arrows-in-simple-fill.svg b/.config/awesome/assets/phosphor/arrows-in-simple-fill.svg
new file mode 100644
index 0000000..ca722d7
--- /dev/null
+++ b/.config/awesome/assets/phosphor/arrows-in-simple-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M120,144v48a8,8,0,0,1-13.66,5.66L88,179.31,53.66,213.66a8,8,0,0,1-11.32-11.32L76.69,168,58.34,149.66A8,8,0,0,1,64,136h48A8,8,0,0,1,120,144ZM213.66,42.34a8,8,0,0,0-11.32,0L168,76.69,149.66,58.34A8,8,0,0,0,136,64v48a8,8,0,0,0,8,8h48a8,8,0,0,0,5.66-13.66L179.31,88l34.35-34.34A8,8,0,0,0,213.66,42.34Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/arrows-out-simple-fill.svg b/.config/awesome/assets/phosphor/arrows-out-simple-fill.svg
new file mode 100644
index 0000000..81816a9
--- /dev/null
+++ b/.config/awesome/assets/phosphor/arrows-out-simple-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M117.66,138.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l34.34-34.35A8,8,0,0,1,117.66,138.34ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72l-34.35,34.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/caret-left-bold.svg b/.config/awesome/assets/phosphor/caret-left-bold.svg
new file mode 100644
index 0000000..413da83
--- /dev/null
+++ b/.config/awesome/assets/phosphor/caret-left-bold.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M168.49,199.51a12,12,0,0,1-17,17l-80-80a12,12,0,0,1,0-17l80-80a12,12,0,0,1,17,17L97,128Z"></path></svg>
diff --git a/.config/awesome/assets/phosphor/caret-right-bold.svg b/.config/awesome/assets/phosphor/caret-right-bold.svg
new file mode 100644
index 0000000..ba52f2b
--- /dev/null
+++ b/.config/awesome/assets/phosphor/caret-right-bold.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M184.49,136.49l-80,80a12,12,0,0,1-17-17L159,128,87.51,56.49a12,12,0,1,1,17-17l80,80A12,12,0,0,1,184.49,136.49Z"></path></svg>
diff --git a/.config/awesome/assets/phosphor/init.lua b/.config/awesome/assets/phosphor/init.lua
index d17eae3..421ceb2 100644
--- a/.config/awesome/assets/phosphor/init.lua
+++ b/.config/awesome/assets/phosphor/init.lua
@@ -1,11 +1,12 @@
local gfs = require "gears.filesystem"
local qfs = require "quarrel.fs"
+---@type table<string, string>
local icons = {}
local phosphor_dir = gfs.get_configuration_dir() .. "assets/phosphor/"
for _, icon in ipairs(qfs.ls_files(phosphor_dir)) do
- if icon:match(".+%.(.+)") == "svg" then
+ if icon:match ".+%.(.+)" == "svg" then
icons[icon:match("(.+)%..+"):gsub("-", "_")] = phosphor_dir .. icon
end
end
diff --git a/.config/awesome/assets/phosphor/lock-simple-fill.svg b/.config/awesome/assets/phosphor/lock-simple-fill.svg
new file mode 100644
index 0000000..55f6ef5
--- /dev/null
+++ b/.config/awesome/assets/phosphor/lock-simple-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/power-bold.svg b/.config/awesome/assets/phosphor/power-bold.svg
new file mode 100644
index 0000000..68d670d
--- /dev/null
+++ b/.config/awesome/assets/phosphor/power-bold.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M116,128V48a12,12,0,0,1,24,0v80a12,12,0,0,1-24,0Zm66.55-82a12,12,0,0,0-13.1,20.1C191.41,80.37,204,103,204,128a76,76,0,0,1-152,0c0-25,12.59-47.63,34.55-61.95A12,12,0,0,0,73.45,46C44.56,64.78,28,94.69,28,128a100,100,0,0,0,200,0C228,94.69,211.44,64.78,182.55,46Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/power-fill.svg b/.config/awesome/assets/phosphor/power-fill.svg
new file mode 100644
index 0000000..3925fa5
--- /dev/null
+++ b/.config/awesome/assets/phosphor/power-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104,104,0,0,0,128,24Zm-8,40a8,8,0,0,1,16,0v64a8,8,0,0,1-16,0Zm8,144A80,80,0,0,1,83.55,61.48a8,8,0,1,1,8.9,13.29,64,64,0,1,0,71.1,0,8,8,0,1,1,8.9-13.29A80,80,0,0,1,128,208Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/sign-out-bold.svg b/.config/awesome/assets/phosphor/sign-out-bold.svg
new file mode 100644
index 0000000..b88c37e
--- /dev/null
+++ b/.config/awesome/assets/phosphor/sign-out-bold.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M116,216a12,12,0,0,1-12,12H48a20,20,0,0,1-20-20V48A20,20,0,0,1,48,28h56a12,12,0,0,1,0,24H52V204h52A12,12,0,0,1,116,216Zm108.49-96.49-40-40a12,12,0,0,0-17,17L187,116H104a12,12,0,0,0,0,24h83l-19.52,19.51a12,12,0,0,0,17,17l40-40A12,12,0,0,0,224.49,119.51Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/phosphor/sign-out-fill.svg b/.config/awesome/assets/phosphor/sign-out-fill.svg
new file mode 100644
index 0000000..a4dda66
--- /dev/null
+++ b/.config/awesome/assets/phosphor/sign-out-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M112,216a8,8,0,0,1-8,8H48a16,16,0,0,1-16-16V48A16,16,0,0,1,48,32h56a8,8,0,0,1,0,16H48V208h56A8,8,0,0,1,112,216Zm109.66-93.66-40-40A8,8,0,0,0,168,88v32H104a8,8,0,0,0,0,16h64v32a8,8,0,0,0,13.66,5.66l40-40A8,8,0,0,0,221.66,122.34Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/assets/sounds/vixui-acconnect.wav b/.config/awesome/assets/sounds/vixui-acconnect.wav
new file mode 100644
index 0000000..3c3a448
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-acconnect.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-acdisconnect.wav b/.config/awesome/assets/sounds/vixui-acdisconnect.wav
new file mode 100644
index 0000000..ef90616
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-acdisconnect.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-boot.wav b/.config/awesome/assets/sounds/vixui-boot.wav
new file mode 100644
index 0000000..38cba2e
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-boot.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-notifa.wav b/.config/awesome/assets/sounds/vixui-notifa.wav
new file mode 100644
index 0000000..4e83a18
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-notifa.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-notifb.wav b/.config/awesome/assets/sounds/vixui-notifb.wav
new file mode 100644
index 0000000..4da95ac
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-notifb.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-usbconnect.wav b/.config/awesome/assets/sounds/vixui-usbconnect.wav
new file mode 100644
index 0000000..c85a7ec
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-usbconnect.wav
Binary files differ
diff --git a/.config/awesome/assets/sounds/vixui-usbdisconnect.wav b/.config/awesome/assets/sounds/vixui-usbdisconnect.wav
new file mode 100644
index 0000000..fa7ad81
--- /dev/null
+++ b/.config/awesome/assets/sounds/vixui-usbdisconnect.wav
Binary files differ
diff --git a/.config/awesome/curious.lua b/.config/awesome/curious.lua
new file mode 100644
index 0000000..3a0bf5d
--- /dev/null
+++ b/.config/awesome/curious.lua
@@ -0,0 +1,100 @@
+local lgi = require "lgi"
+local Gio = lgi.Gio
+local GObject = lgi.GObject
+local GLib = lgi.GLib
+local gpcall = require "gears.protected_call"
+local gtimer = require "gears.timer"
+
+local methods = {}
+
+local interface = Gio.DBusInterfaceInfo {
+ name = "com.twoexem.delta.Curious",
+ methods = {
+ Gio.DBusMethodInfo {
+ name = "Select",
+ out_args = {
+ Gio.DBusArgInfo {
+ name = "widget_tree",
+ signature = "av"
+ }
+ }
+ }
+ }
+}
+
+-- iterate with ipairs, get the length of the array, check if key value from pairs is a number lower than the length and if so, use as a dict key cause it's not gonna work with :add anyway
+local function serialize(builder, t)
+ local array_length = 0
+ for i, _ in ipairs(t) do
+ array_length = i
+ end
+
+ for k, v in pairs(t) do
+ local _type = type(v)
+ local signature
+ local data
+ if _type == "number" then
+ signature = "d"
+ data = v
+ elseif _type == "string" then
+ signature = "s"
+ data = v
+ elseif _type == "boolean" then
+ signature = "b"
+ data = v
+ elseif _type == "thread" or _type == "function" or (_type == "userdata" and not getmetatable(v).__tostring) then
+ local address = tonumber(tostring(v):match("%a+: 0x(%w+)"), 16)
+ signature = "(s(t))"
+ data = { _type, address }
+ elseif _type == "userdata" then
+ if getmetatable(v).emit_signal then -- One of the properties available on any awesome luaobject
+ local _, _, content = tostring(v):match("%a+/(.*)")
+ local stringified = tostring(v)
+ if content then
+ stringified = content
+ end
+ local type, extra, address = stringified:match("(%a+)(.*): 0x(%w+)")
+ if extra ~= "" then
+ extra:sub(2, -2)
+ signature = "(s(st))"
+ data = { type, extra, address }
+ else
+ signature = "(s(t))"
+ data = { type, address }
+ end
+ else
+ signature = "(s())"
+ data = { _type, {}}
+ end
+ end
+
+ if type(k) == "number" and k > array_length then
+ builder:add("v", GLib.Variant(signature, data))
+ else
+ print(type(signature), type(data))
+ local variant = GLib.Variant("{sd}", { "test", 4})
+ builder:add_value(GLib.Variant("v", variant))
+ end
+ end
+end
+
+function methods.Select(parameters, invocation)
+ local builder = GLib.VariantBuilder(GLib.VariantType("av"))
+ serialize(builder, { "test", some_key = "some_value" })
+ local tuple_builder = GLib.VariantBuilder(GLib.VariantType("(av)"))
+ tuple_builder:add_value(builder:_end())
+ -- builder
+ -- invocation:return_value(GLib.Variant("(av)", { builder }))
+ invocation:return_value(tuple_builder:_end())
+end
+
+local function handle_call(_, _, _, _, method, parameters, invocation)
+ if not methods[method] then print("invalid"); return end
+ gpcall(methods[method], parameters, invocation)
+end
+
+local function acquire(connection)
+ connection:register_object("/com/twoexem/delta/Curious", interface, GObject.Closure(handle_call))
+end
+
+local connection = Gio.bus_own_name(Gio.BusType.SESSION, "com.twoexem.delta.Curious", Gio.BusNameOwnerFlags.NONE, GObject.Closure(acquire))
diff --git a/.config/awesome/misc/autostart.lua b/.config/awesome/misc/autostart.lua
index 3cd70f9..b089068 100644
--- a/.config/awesome/misc/autostart.lua
+++ b/.config/awesome/misc/autostart.lua
@@ -1,7 +1,9 @@
local awful = require "awful"
local quarrel = require "quarrel"
-if quarrel.is_restart() then return end
+if quarrel.is_restart() then
+ return
+end
local programs = {
"picom -b",
@@ -11,7 +13,7 @@ local programs = {
"wezterm start --class code_term",
"firefox",
"discord",
- "LD_PRELOAD=/usr/lib/spotify-adblock.so spotify"
+ "LD_PRELOAD=/usr/lib/spotify-adblock.so spotify",
}
for _, program in ipairs(programs) do
diff --git a/.config/awesome/misc/cfg.lua b/.config/awesome/misc/cfg.lua
index 05534b1..aceaa08 100644
--- a/.config/awesome/misc/cfg.lua
+++ b/.config/awesome/misc/cfg.lua
@@ -1,5 +1,4 @@
local awful = require "awful"
-local phosphor = require "assets.phosphor"
local cfg = {
terminal = "wezterm",
@@ -7,32 +6,27 @@ local cfg = {
{
layout = awful.layout.suit.floating,
selected = true,
- icon = phosphor.house_fill
},
{
layout = awful.layout.suit.floating,
- icon = phosphor.browser_fill
},
{
layout = awful.layout.suit.tile.left,
master_width_factor = 0.7,
- icon = phosphor.discord_logo_fill
},
{
layout = awful.layout.suit.tile.top,
master_width_factor = 0.2,
- icon = phosphor.spotify_logo_fill
},
{
layout = awful.layout.suit.tile.right,
- master_width_factor = 0.7,
- icon = phosphor.code_fill
+ -- master_width_factor = 0.7,
},
{
layout = awful.layout.suit.floating,
- icon = phosphor.game_controller_fill
- }
- }
+ },
+ },
+ backlight = "/sys/class/backlight/amdgpu_bl1/",
}
return cfg
diff --git a/.config/awesome/misc/keys.lua b/.config/awesome/misc/keys.lua
index 646be52..9d994ce 100644
--- a/.config/awesome/misc/keys.lua
+++ b/.config/awesome/misc/keys.lua
@@ -1,4 +1,5 @@
local awful = require "awful"
+local backlight = require "services.backlight"
local beautiful = require "beautiful"
local cfg = require "misc.cfg"
local fresnel = require "ui.fresnel"
@@ -6,7 +7,9 @@ local gtimer = require "gears.timer"
local insightful = require "ui.insightful"
local naughty = require "naughty"
local playerctl = require "services.playerctl"
+local powermenu = require "ui.powermenu"
local qbind = require "quarrel.bind"
+local qstore = require "quarrel.store"
local qvars = require "quarrel.vars"
local recording = { false, "" }
@@ -17,11 +20,11 @@ client.connect_signal("request::default_mousebindings", function()
triggers = qvars.btns.left,
press = function(c)
c:activate {
- context = "mouse_click"
+ context = "mouse_click",
}
end,
group = "client",
- desc = "raise client"
+ desc = "raise client",
},
qbind:new {
mods = qvars.mods.M,
@@ -29,11 +32,11 @@ client.connect_signal("request::default_mousebindings", function()
press = function(c)
c:activate {
context = "mouse_click",
- action = "mouse_move"
+ action = "mouse_move",
}
end,
group = "client",
- desc = "move client"
+ desc = "move client",
},
qbind:new {
mods = qvars.mods.M,
@@ -41,12 +44,12 @@ client.connect_signal("request::default_mousebindings", function()
press = function(c)
c:activate {
context = "mouse_click",
- action = "mouse_resize"
+ action = "mouse_resize",
}
end,
group = "client",
- desc = "resize client"
- }
+ desc = "resize client",
+ },
}
end)
@@ -59,7 +62,7 @@ client.connect_signal("request::default_keybindings", function()
c:kill()
end,
group = "client",
- desc = "close"
+ desc = "close",
},
qbind:new {
mods = qvars.mods.M,
@@ -68,7 +71,7 @@ client.connect_signal("request::default_keybindings", function()
c.maximized = not c.maximized
end,
group = "client",
- desc = "(un)maximize"
+ desc = "(un)maximize",
},
qbind:new {
mods = qvars.mods.M,
@@ -79,7 +82,7 @@ client.connect_signal("request::default_keybindings", function()
end)
end,
group = "client",
- desc = "minimize"
+ desc = "minimize",
},
qbind:new {
mods = qvars.mods.M,
@@ -88,8 +91,8 @@ client.connect_signal("request::default_keybindings", function()
c.fullscreen = not c.fullscreen
end,
group = "client",
- desc = "toggle fullscreen"
- }
+ desc = "toggle fullscreen",
+ },
}
end)
@@ -99,7 +102,7 @@ awful.keyboard.append_global_keybindings {
triggers = "r",
press = awesome.restart,
group = "awesome",
- desc = "restart awesome"
+ desc = "restart awesome",
},
qbind:new {
mods = qvars.mods.M,
@@ -108,7 +111,7 @@ awful.keyboard.append_global_keybindings {
insightful:toggle()
end,
group = "awesome",
- desc = "toggle insightful"
+ desc = "toggle insightful",
},
qbind:new {
mods = qvars.mods.M,
@@ -117,36 +120,54 @@ awful.keyboard.append_global_keybindings {
fresnel:show()
end,
group = "awesome",
- desc = "toggle fresnel"
+ desc = "toggle fresnel",
+ },
+ qbind:new {
+ mods = qvars.mods.M,
+ triggers = "p",
+ press = function()
+ qstore.panel_toggle:press()
+ end,
+ group = "awesome",
+ desc = "toggle bar panel",
+ },
+ qbind:new {
+ mods = qvars.mods.M,
+ triggers = "l",
+ press = function()
+ powermenu:toggle()
+ end,
+ group = "awesome",
+ desc = "toggle powermenu",
},
qbind:new {
triggers = "XF86AudioMute",
press = function()
- awful.spawn("wpctl set-mute @DEFAULT_SINK@ toggle")
+ awful.spawn "wpctl set-mute @DEFAULT_SINK@ toggle"
end,
group = "audio",
- desc = "mute"
+ desc = "mute",
},
qbind:new {
triggers = {
{ "XF86AudioRaiseVolume", true },
- { "XF86AudioLowerVolume", false }
+ { "XF86AudioLowerVolume", false },
},
press = function(up)
if up then
- awful.spawn("wpctl set-volume @DEFAULT_SINK@ 5%+")
+ awful.spawn "wpctl set-volume @DEFAULT_SINK@ 5%+"
else
- awful.spawn("wpctl set-volume @DEFAULT_SINK@ 5%-")
+ awful.spawn "wpctl set-volume @DEFAULT_SINK@ 5%-"
end
end,
group = "audio",
- desc = "increase/decrease volume"
+ desc = "increase/decrease volume",
},
qbind:new {
triggers = {
{ "XF86AudioNext", true },
- { "XF86AudioPrev", false }
+ { "XF86AudioPrev", false },
},
press = function(next)
if next then
@@ -156,7 +177,7 @@ awful.keyboard.append_global_keybindings {
end
end,
group = "audio",
- desc = "previous/next song"
+ desc = "previous/next song",
},
qbind:new {
triggers = "XF86AudioPlay",
@@ -164,23 +185,23 @@ awful.keyboard.append_global_keybindings {
playerctl:play_pause()
end,
group = "audio",
- desc = "(un)pause song"
+ desc = "(un)pause song",
},
qbind:new {
triggers = {
{ "XF86MonBrightnessUp", true },
- { "XF86MonBrightnessDown", false }
+ { "XF86MonBrightnessDown", false },
},
press = function(up)
if up then
- awful.spawn("brightnessctl set +51")
+ backlight.set(backlight.get() + 51)
else
- awful.spawn("brightnessctl set 51-")
+ backlight.set(backlight.get() - 51)
end
end,
group = "brightness",
- desc = "increase/decrease brightness"
+ desc = "increase/decrease brightness",
},
qbind:new {
@@ -190,33 +211,49 @@ awful.keyboard.append_global_keybindings {
awful.spawn(cfg.terminal)
end,
group = "launcher",
- desc = "launch terminal"
+ desc = "launch terminal",
},
qbind:new {
triggers = "Print",
press = function()
- local date = os.date("%Y%m%d_%H%M%S")
- local path = os.getenv("HOME") .. "/Pictures/" .. date .. ".png"
+ local date = os.date "%Y%m%d_%H%M%S"
+ local path = os.getenv "HOME" .. "/Pictures/" .. date .. ".png"
-- Can't use naughty.notification cause it gets in the screenshot
-- Also can't use easy_async_with_shell cause it's buggy
- awful.spawn.with_shell("maim --hidecursor " .. path .. " && xclip -selection clipboard -t image/png " .. path .. [[ && notify-send -a "Maim" "Screenshot taken" "Saved at ]] .. path .. [["]])
+ awful.spawn.with_shell(
+ "maim --hidecursor "
+ .. path
+ .. " && xclip -selection clipboard -t image/png "
+ .. path
+ .. [[ && notify-send -a "Maim" "Screenshot taken" "Saved at ]]
+ .. path
+ .. [["]]
+ )
end,
group = "screenshot",
- desc = "take fullscreen screenshot"
+ desc = "take fullscreen screenshot",
},
qbind:new {
mods = qvars.mods.S,
triggers = "Print",
press = function()
- local date = os.date("%Y%m%d_%H%M%S")
- local path = os.getenv("HOME") .. "/Pictures/" .. date .. ".png"
+ local date = os.date "%Y%m%d_%H%M%S"
+ local path = os.getenv "HOME" .. "/Pictures/" .. date .. ".png"
- awful.spawn.with_shell("maim --hidecursor -s " .. path .. " && xclip -selection clipboard -t image/png " .. path .. [[ && notify-send -a "Maim" "Screenshot taken" "Saved at ]] .. path .. [["]])
+ awful.spawn.with_shell(
+ "maim --hidecursor -s "
+ .. path
+ .. " && xclip -selection clipboard -t image/png "
+ .. path
+ .. [[ && notify-send -a "Maim" "Screenshot taken" "Saved at ]]
+ .. path
+ .. [["]]
+ )
end,
group = "screenshot",
- desc = "take region screenshot"
+ desc = "take region screenshot",
},
qbind:new {
@@ -224,45 +261,45 @@ awful.keyboard.append_global_keybindings {
triggers = "Print",
press = function()
if recording[1] then
- awful.spawn("giph --stop")
+ awful.spawn "giph --stop"
naughty.notification {
app_name = "Giph",
title = "Recording stopped",
- message = "Saved at " .. recording[2]
+ message = "Saved at " .. recording[2],
}
recording[1] = false
recording[2] = ""
else
recording[1] = true
- recording[2] = os.getenv("HOME") .. "/Videos/" .. os.date("%Y%m%d_%H%M%S") .. ".mp4"
+ recording[2] = os.getenv "HOME" .. "/Videos/" .. os.date "%Y%m%d_%H%M%S" .. ".mp4"
awful.spawn("giph --format mp4 --framerate 30 " .. recording[2])
naughty.notification {
app_name = "Giph",
- title = "Recording started"
+ title = "Recording started",
}
end
end,
group = "video",
- desc = "toggle recording"
+ desc = "toggle recording",
},
qbind:new {
mods = qvars.mods.M,
triggers = "k",
press = function()
- awful.spawn("xkblayout-state set +1")
+ awful.spawn "xkblayout-state set +1"
end,
group = "keyboard",
- desc = "next keyboard layout"
+ desc = "next keyboard layout",
},
qbind:new {
mods = qvars.mods.MS,
triggers = "k",
press = function()
- awful.spawn("xkblayout-state set -1")
+ awful.spawn "xkblayout-state set -1"
end,
group = "keyboard",
- desc = "previous keyboard layout"
+ desc = "previous keyboard layout",
},
qbind:new {
@@ -270,14 +307,14 @@ awful.keyboard.append_global_keybindings {
triggers = "Up",
press = awful.tag.viewprev,
group = "tag",
- desc = "switch to previous"
+ desc = "switch to previous",
},
qbind:new {
mods = qvars.mods.M,
triggers = "Down",
press = awful.tag.viewnext,
group = "tag",
- desc = "switch to next"
+ desc = "switch to next",
},
qbind:new {
mods = qvars.mods.MC,
@@ -287,6 +324,6 @@ awful.keyboard.append_global_keybindings {
tag.master_width_factor = cfg.tags[tonumber(tag.name)].master_width_factor or beautiful.master_width_factor
end,
group = "tag",
- desc = "reset master width"
- }
+ desc = "reset master width",
+ },
}
diff --git a/.config/awesome/misc/rules.lua b/.config/awesome/misc/rules.lua
index b4d1dfa..92ac596 100644
--- a/.config/awesome/misc/rules.lua
+++ b/.config/awesome/misc/rules.lua
@@ -3,98 +3,99 @@ local beautiful = require "beautiful"
local ruled = require "ruled"
ruled.client.connect_signal("request::rules", function()
- ruled.client.append_rule({
- id = "global",
- rule = {},
- properties = {
- border_width = beautiful.border_width,
- border_color = beautiful.border_normal,
- focus = awful.client.focus.filter,
- raise = true,
- screen = awful.screen.preferred,
- placement = awful.placement.centered+awful.placement.no_offscreen,
- floating = false,
- honor_padding = true
- }
- })
+ ruled.client.append_rules {
+ {
+ id = "global",
+ rule = {},
+ properties = {
+ border_width = beautiful.border_width,
+ border_color = beautiful.border_normal,
+ focus = awful.client.focus.filter,
+ raise = true,
+ screen = awful.screen.preferred,
+ placement = awful.placement.centered + awful.placement.no_offscreen,
+ floating = false,
+ honor_padding = true,
+ },
+ },
- ruled.client.append_rule({
- id = "titlebars",
- rule_any = {
- type = {
- "normal",
- "dialog"
- }
+ {
+ id = "titlebars",
+ rule_any = {
+ type = {
+ "normal",
+ "dialog",
+ },
+ },
+ properties = {
+ titlebars_enabled = true,
+ },
},
- properties = {
- titlebars_enabled = true
- }
- })
- ruled.client.append_rule({
- id = "pip",
- rule = {
- name = "Picture-in-Picture"
+ {
+ id = "pip",
+ rule = {
+ name = "Picture-in-Picture",
+ },
+ properties = {
+ ontop = true,
+ },
},
- properties = {
- ontop = true
- }
- })
- ruled.client.append_rule({
- id = "browser_tag",
- rule_any = {
- instance = { "Navigator" }
+ {
+ id = "browser_tag",
+ rule_any = {
+ instance = { "Navigator" },
+ },
+ properties = {
+ screen = 1,
+ tag = awful.screen.focused().tags[2],
+ },
},
- properties = {
- screen = 1,
- tag = screen[1].tags[2]
- }
- })
- ruled.client.append_rule({
- id = "chat_tag",
- rule_any = {
- class = { "discord" }
+ {
+ id = "chat_tag",
+ rule_any = {
+ class = { "discord" },
+ },
+ properties = {
+ screen = 1,
+ tag = awful.screen.focused().tags[3],
+ },
},
- properties = {
- screen = 1,
- tag = screen[1].tags[3]
- }
- })
-
- ruled.client.append_rule({
- id = "music_tag",
- rule_any = {
- class = { "Spotify" }
+ {
+ id = "music_tag",
+ rule_any = {
+ class = { "Spotify" },
+ },
+ properties = {
+ screen = 1,
+ tag = awful.screen.focused().tags[4],
+ titlebars_enabled = false,
+ },
},
- properties = {
- screen = 1,
- tag = screen[1].tags[4],
- titlebars_enabled = false
- }
- })
- ruled.client.append_rule({
- id = "code_tag",
- rule_any = {
- class = { "lite-xl", "code_term" }
+ {
+ id = "code_tag",
+ rule_any = {
+ class = { "lite-xl", "code_term" },
+ },
+ properties = {
+ screen = 1,
+ tag = awful.screen.focused().tags[5],
+ },
},
- properties = {
- screen = 1,
- tag = screen[1].tags[5]
- }
- })
- ruled.client.append_rule({
- id = "steam",
- rule_any = {
- class = { "steam" }
+ {
+ id = "steam",
+ rule_any = {
+ class = { "steam" },
+ },
+ properties = {
+ screen = 1,
+ tag = awful.screen.focused().tags[6],
+ },
},
- properties = {
- screen = 1,
- tag = screen[1].tags[6]
- }
- })
+ }
end)
diff --git a/.config/awesome/prismite.lua b/.config/awesome/prismite.lua
index 72701b6..5de089f 100644
--- a/.config/awesome/prismite.lua
+++ b/.config/awesome/prismite.lua
@@ -27,13 +27,11 @@ theme.border_marked = qvars.colors.bright.black
theme.notification_icon_size = dpi(32)
theme.notification_border_width = qvars.border_width
theme.notification_border_color = theme.border_normal
+theme.notification_max_width = qvars.char_width * 48
theme.notification_shape = qvars.shape
theme.notification_spacing = theme.useless_gap * 2
-
-naughty.config.presets.critical.bg = theme.bg_normal
-naughty.config.presets.critical.timeout = 3
-naughty.config.presets.critical.fg = theme.fg_normal
-naughty.config.presets.critical.border_color = qvars.colors.red
+
+naughty.config.defaults.timeout = qvars.notif_timeout
naughty.config.defaults.position = "bottom_right"
naughty.config.defaults.border_width = qvars.border_width
@@ -41,4 +39,3 @@ theme.tasklist_plain_task_name = true
theme.enable_spawn_cursor = false
return theme
-
diff --git a/.config/awesome/quarrel/bezier.lua b/.config/awesome/quarrel/bezier.lua
new file mode 100644
index 0000000..4229961
--- /dev/null
+++ b/.config/awesome/quarrel/bezier.lua
@@ -0,0 +1,343 @@
+---------------------------------------------------------------------------
+--- A helper module for computations involving Bézier curves
+--
+-- @author Alex Belykh &lt;albel727@ngs.ru&gt;
+-- @copyright 2021 Alex Belykh
+-- @submodule gears.math
+---------------------------------------------------------------------------
+
+local table_insert = table.insert
+
+local bezier = {}
+
+--- Compute the value of a Bézier curve at a given value of the t parameter.
+--
+-- This function evaluates the given curve `B` of an arbitrary degree
+-- at a given point t.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam number t The value of the t parameter to evaluate the curve at.
+-- @treturn[1] number The value of `B(t)`.
+-- @treturn[2] nil `nil`, if c is empty.
+-- @staticfct gears.math.bezier.curve_evaluate_at
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_evaluate_at(c, t)
+ local from = c
+ local tmp = { nil, nil, nil, nil }
+ while #from > 1 do
+ for i = 1, #from - 1 do
+ tmp[i] = from[i] * (1 - t) + from[i + 1] * t
+ end
+ tmp[#from] = nil
+ from = tmp
+ end
+
+ return from[1]
+end
+
+--- Split a Bézier curve into two curves at a given value of the t parameter.
+--
+-- This function splits the given curve `B` of an arbitrary degree at a point t
+-- into two curves of the same degree `B_left` and `B_right`, such that
+-- `B_left(0)=B(0)`, `B_left(1)=B(t)=B_right(0)`, `B_right(1)=B(1)`.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam number t The value of the t parameter to split the curve at.
+-- @treturn {number,...} The table of control points for `B_left`.
+-- @treturn {number,...} The table of control points for `B_right`.
+-- @staticfct gears.math.bezier.curve_split_at
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_split_at(c, t)
+ local coefs_left, coefs_right = {}, {}
+ local from = c
+ local tmp = { nil, nil, nil, nil }
+ while #from > 0 do
+ table_insert(coefs_left, from[1])
+ table_insert(coefs_right, 1, from[#from])
+ for i = 1, #from - 1 do
+ tmp[i] = from[i] * (1 - t) + from[i + 1] * t
+ end
+ tmp[#from] = nil
+ from = tmp
+ end
+
+ return coefs_left, coefs_right
+end
+
+--- Get the n-th derivative Bézier curve of a Bézier curve.
+--
+-- This function computes control points for the curve that is
+-- the derivative of order `n` in `t`, i.e. `B^(n)(t)`,
+-- of the given curve `B(t)` of an arbitrary degree.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam[opt=1] integer n The order of the derivative to take.
+-- @treturn[1] {number,...} The table of control points of `B^(n)(t)`.
+-- @treturn[2] nil If n is less than 0.
+-- @staticfct gears.math.bezier.curve_derivative
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_derivative(c, n)
+ n = n or 1
+ if n < 0 then
+ return
+ end
+ if n < 1 then
+ return c
+ end
+ local c_len = #c
+ if c_len < n + 1 then
+ return {}
+ end
+
+ local from = c
+ local tmp = {}
+
+ for l = c_len - 1, c_len - n, -1 do
+ for i = 1, l do
+ tmp[i] = (from[i + 1] - from[i]) * l
+ end
+ tmp[l + 1] = nil
+ from = tmp
+ end
+
+ return from
+end
+
+-- This is used instead of plain 0 to try and be compatible
+-- with objects that implement their own arithmetic via metatables.
+local function get_zero(c, zero)
+ return c and c * 0 or zero
+end
+
+--- Compute the value of the n-th derivative of a Bézier curve
+--- at a given value of the t parameter.
+--
+-- This is roughly the same as
+-- `curve_evaluate_at(curve_derivative(c, n), t)`, but the latter
+-- would throw errors or return nil instead of 0 in some cases.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam number t The value of the t parameter to compute the derivative at.
+-- @tparam[opt=1] integer n The order of the derivative to take.
+-- @tparam[opt=nil] number|nil zero The value to return if c is empty.
+-- @treturn[1] number The value of `B^(n)(t)`.
+-- @treturn[2] nil nil, if n is less than 0.
+-- @treturn[3] number|nil The value of the zero parameter, if c is empty.
+-- @staticfct gears.math.bezier.curve_derivative_at
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_derivative_at(c, t, n, zero)
+ local d = bezier.curve_derivative(c, n)
+ if not d then
+ return
+ end
+
+ return bezier.curve_evaluate_at(d, t) or get_zero(c[1], zero)
+end
+
+--- Compute the value of the 1-st derivative of a Bézier curve at t=0.
+--
+-- This is the same as `curve_derivative_at(c, 0)`, but since it's particularly
+-- computationally simple and useful in practice, it has its own function.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam[opt=nil] number|nil zero The value to return if c is empty.
+-- @treturn[1] number The value of `B'(0)`.
+-- @treturn[2] number|nil The value of the zero parameter, if c is empty.
+-- @staticfct gears.math.bezier.curve_derivative_at_zero
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_derivative_at_zero(c, zero)
+ local l = #c
+ if l < 2 then
+ return get_zero(c[1], zero)
+ end
+ return (c[2] - c[1]) * (l - 1)
+end
+
+--- Compute the value of the 1-st derivative of a Bézier curve at t=1.
+--
+-- This is the same as `curve_derivative_at(c, 1)`, but since it's particularly
+-- computationally simple and useful in practice, it has its own function.
+--
+-- @tparam {number,...} c The table of control points of the curve.
+-- @tparam[opt=nil] number|nil zero The value to return if c is empty.
+-- @treturn[1] number The value of `B'(1)`.
+-- @treturn[2] number|nil The value of the zero parameter, if c is empty.
+-- @staticfct gears.math.bezier.curve_derivative_at_one
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_derivative_at_one(c, zero)
+ local l = #c
+ if l < 2 then
+ return get_zero(c[1], zero)
+ end
+ return (c[l] - c[l - 1]) * (l - 1)
+end
+
+--- Get the (n+1)-th degree Bézier curve, that has the same shape as
+-- a given n-th degree Bézier curve.
+--
+-- Given the control points of a curve B of degree n, this function computes
+-- the control points for the curve Q, such that `Q(t) = B(t)`, and
+-- Q has the degree n+1, i.e. it has one control point more.
+--
+-- @tparam {number,...} c The table of control points of the curve B.
+-- @treturn {number,...} The table of control points of the curve Q.
+-- @staticfct gears.math.bezier.curve_elevate_degree
+-- @see wibox.widget.graph.step_hook
+function bezier.curve_elevate_degree(c)
+ local ret = { c[1] }
+ local len = #c
+
+ for i = 1, len - 1 do
+ ret[i + 1] = (i * c[i] + (len - i) * c[i + 1]) / len
+ end
+
+ ret[len + 1] = c[len]
+ return ret
+end
+
+--- Get a cubic Bézier curve that passes through given points (up to 4).
+--
+-- This function takes up to 4 values and returns the 4 control points
+-- for a cubic curve
+--
+-- `B(t) = c0\*(1-t)^3 + 3\*c1\*t\*(1-t)^2 + 3\*c2\*t^2\*(1-t) + c3\*t^3`,
+-- that takes on these values at equidistant values of the t parameter.
+--
+-- If only p0 is given, `B(0)=B(1)=B(for all t)=p0`.
+--
+-- If p0 and p1 are given, `B(0)=p0` and `B(1)=p1`.
+--
+-- If p0, p1 and p2 are given, `B(0)=p0`, `B(1/2)=p1` and `B(1)=p2`.
+--
+-- For 4 points given, `B(0)=p0`, `B(1/3)=p1`, `B(2/3)=p2`, `B(1)=p3`.
+--
+-- @tparam number p0
+-- @tparam[opt] number p1
+-- @tparam[opt] number p2
+-- @tparam[opt] number p3
+-- @treturn number c0
+-- @treturn number c1
+-- @treturn number c2
+-- @treturn number c3
+-- @staticfct gears.math.bezier.cubic_through_points
+-- @see wibox.widget.graph.step_hook
+function bezier.cubic_through_points(p0, p1, p2, p3)
+ if not p1 then
+ return p0, p0, p0, p0
+ end
+ if not p2 then
+ local c1 = (2 * p0 + p1) / 3
+ local c2 = (2 * p1 + p0) / 3
+ return p0, c1, c2, p1
+ end
+ if not p3 then
+ local c1 = (4 * p1 - p2) / 3
+ local c2 = (4 * p1 - p0) / 3
+ return p0, c1, c2, p2
+ end
+ local c1 = (-5 * p0 + 18 * p1 - 9 * p2 + 2 * p3) / 6
+ local c2 = (-5 * p3 + 18 * p2 - 9 * p1 + 2 * p0) / 6
+ return p0, c1, c2, p3
+end
+
+--- Get a cubic Bézier curve with given values and derivatives at endpoints.
+--
+-- This function computes the 4 control points for the cubic curve B, such that
+-- `B(0)=p0`, `B'(0)=d0`, `B(1)=p3`, `B'(1)=d3`.
+--
+-- @tparam number d0 The value of the derivative at t=0.
+-- @tparam number p0 The value of the curve at t=0.
+-- @tparam number p3 The value of the curve at t=1.
+-- @tparam number d3 The value of the derivative at t=1.
+-- @treturn number c0
+-- @treturn number c1
+-- @treturn number c2
+-- @treturn number c3
+-- @staticfct gears.math.bezier.cubic_from_points_and_derivatives
+-- @see wibox.widget.graph.step_hook
+function bezier.cubic_from_points_and_derivatives(d0, p0, p3, d3)
+ local c1 = p0 + d0 / 3
+ local c2 = p3 - d3 / 3
+ return p0, c1, c2, p3
+end
+
+--- Get a cubic Bézier curve with given values at endpoints and starting
+--- derivative, while minimizing (an approximation of) the stretch energy.
+--
+-- This function computes the 4 control points for the cubic curve B, such that
+-- `B(0)=p0`, `B'(0)=d0`, `B(1)=p3`, and
+-- the integral of `(B'(t))^2` on `t=[0,1]` is minimal.
+-- (The actual stretch energy is the integral of `|B'(t)|`)
+--
+-- In practical terms this is almost the same as "the curve of shortest length
+-- connecting given points and having the given starting speed".
+--
+-- @tparam number d0 The value of the derivative at t=0.
+-- @tparam number p0 The value of the curve at t=0.
+-- @tparam number p3 The value of the curve at t=1.
+-- @treturn number c0
+-- @treturn number c1
+-- @treturn number c2
+-- @treturn number c3
+-- @staticfct gears.math.bezier.cubic_from_derivative_and_points_min_stretch
+-- @see wibox.widget.graph.step_hook
+function bezier.cubic_from_derivative_and_points_min_stretch(d0, p0, p3)
+ local c1 = p0 + d0 / 3
+ local c2 = (2 * p0 - c1 + 3 * p3) / 4
+ return p0, c1, c2, p3
+end
+
+--- Get a cubic Bézier curve with given values at endpoints and starting
+--- derivative, while minimizing (an approximation of) the strain energy.
+--
+-- This function computes the 4 control points for the cubic curve B, such that
+-- `B(0)=p0`, `B'(0)=d0`, `B(1)=p3`, and
+-- the integral of `(B''(t))^2` on `t=[0,1]` is minimal.
+--
+-- In practical terms this is almost the same as "the curve of smallest
+-- speed change connecting given points and having the given starting speed".
+--
+-- @tparam number d0 The value of the derivative at t=0.
+-- @tparam number p0 The value of the curve at t=0.
+-- @tparam number p3 The value of the curve at t=1.
+-- @treturn number c0
+-- @treturn number c1
+-- @treturn number c2
+-- @treturn number c3
+-- @staticfct gears.math.bezier.cubic_from_derivative_and_points_min_strain
+-- @see wibox.widget.graph.step_hook
+function bezier.cubic_from_derivative_and_points_min_strain(d, p0, p3)
+ local c1 = p0 + d / 3
+ local c2 = (c1 + p3) / 2
+ return p0, c1, c2, p3
+end
+
+--- Get a cubic Bézier curve with given values at endpoints and starting
+--- derivative, while minimizing the jerk energy.
+--
+-- This function computes the 4 control points for the cubic curve B, such that
+-- `B(0)=p0`, `B'(0)=d0`, `B(1)=p3`, and
+-- the integral of `(B'''(t))^2` on `t=[0,1]` is minimal.
+--
+-- In practical terms this is almost the same as "the curve of smallest
+-- acceleration change connecting given points and having the given
+-- starting speed".
+--
+-- @tparam number d0 The value of the derivative at t=0.
+-- @tparam number p0 The value of the curve at t=0.
+-- @tparam number p3 The value of the curve at t=1.
+-- @treturn number c0
+-- @treturn number c1
+-- @treturn number c2
+-- @treturn number c3
+-- @staticfct gears.math.bezier.cubic_from_derivative_and_points_min_jerk
+-- @see wibox.widget.graph.step_hook
+function bezier.cubic_from_derivative_and_points_min_jerk(d, p0, p3)
+ local c1 = p0 + d / 3
+ local c2 = c1 + (p3 - p0) / 3
+ return p0, c1, c2, p3
+end
+
+return bezier
+
+-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/.config/awesome/quarrel/bind.lua b/.config/awesome/quarrel/bind.lua
index 4cb5d44..a1abf29 100644
--- a/.config/awesome/quarrel/bind.lua
+++ b/.config/awesome/quarrel/bind.lua
@@ -2,56 +2,105 @@ local awful = require "awful"
local gtable = require "gears.table"
local qstore = require "quarrel.store"
+---@class QuarrelBind
local qbind = {}
qstore.bindings = {}
-local function get_binding_function(trigger)
- if type(trigger) == "number" and trigger <= 5 and trigger > 0 then
+---@alias mouse_button
+---| 0 Left mouse button
+---| 1 Middle mouse click
+---| 2 Right mouse button
+---| 3 Scroll up
+---| 4 Scroll down
+
+---@alias bind
+---| mouse_button
+---| string
+
+---@alias modifier
+---| "Mod1" Alt
+---| "Mod4" Super
+---| "Mod5" AltGr
+---| "Shift" Shift
+---| "Control" Ctrl
+
+---@class Trigger
+---@field [1] bind
+---@field [2] any Value passed to the press callback
+
+---@class Binding
+---@field hidden boolean? Whether the binding shows up in the help menu
+---@field mods modifier[]? Modifiers
+---@field press fun(...) | fun(any, ...) Function to run when the trigger is pressed
+---@field desc string? Description
+---@field group string? What group the binding will show up in
+---@field triggers Trigger[] | bind
+
+---Get the corresponding binding creation function for a trigger
+---@param bind bind
+---@return string
+local function get_binding_function(bind)
+ if type(bind) == "number" and bind <= 5 and bind > 0 then
return "button"
- elseif type(trigger) == "string" then
+ elseif type(bind) == "string" then
return "key"
end
- error("trigger can only be a mouse button or a key", 2)
+ error("bind can only be a mouse button or a key", 2)
end
-local function translate_binding(binding, trigger, multiple)
- local value = nil
- if multiple then
- value = trigger[2]
- trigger = trigger[1]
+--- Translate a qbind binding into an awful binding
+---@param binding Binding
+---@param trigger Trigger | bind
+---@param multi boolean specifies whether this is a multi trigger bind
+---@return awful.key
+local function translate_binding(binding, trigger, multi)
+ local awful_binding
+ if multi then
+ awful_binding = {
+ modifiers = binding.mods,
+ [get_binding_function(trigger[1])] = trigger[1],
+ on_press = function(...)
+ binding.press(trigger[2], ...)
+ end,
+ }
+ else
+ awful_binding = {
+ modifiers = binding.mods,
+ [get_binding_function(trigger --[[@as bind]])] = trigger,
+ on_press = binding.press,
+ }
end
- local awful_binding = {
- modifiers = binding.mods,
- [get_binding_function(trigger)] = trigger,
- on_press = multiple and function(...) binding.press(value, ...) end or binding.press
- }
+ awful_binding.description = binding.desc
+ awful_binding.group = binding.group
- if binding.desc then
- awful_binding.description = binding.desc
- end
- if binding.group then
- awful_binding.group = binding.group
- end
-
- return awful[get_binding_function(trigger)](awful_binding)
+ return awful[
+ get_binding_function(multi and trigger[1] or trigger --[[@as bind]])
+ ](awful_binding)
end
+--- Create a new binding
+---@param binding Binding
+---@return awful.key[]
function qbind:new(binding)
- if not binding.hidden then table.insert(qstore.bindings, binding) end
+ if not binding.hidden then
+ table.insert(qstore.bindings, binding)
+ end
binding.mods = binding.mods or {}
local awful_bindings = {}
if type(binding.triggers) == "table" then
- for _, trigger in ipairs(binding.triggers) do
+ for _, trigger in
+ ipairs(binding.triggers --[[@as Trigger[]])
+ do
table.insert(awful_bindings, translate_binding(binding, trigger, true))
end
elseif type(binding.triggers) == "string" or type(binding.triggers) == "number" then
- return translate_binding(binding, binding.triggers, false)
+ return translate_binding(binding, binding.triggers --[[@as bind]], false)
else
- error("binding.triggers can only be a string or a table")
+ error "binding.triggers can only be a string or a table"
end
-- for some reason multi-trigger bindings only work if i do this
diff --git a/.config/awesome/quarrel/delegate.lua b/.config/awesome/quarrel/delegate.lua
new file mode 100644
index 0000000..54db786
--- /dev/null
+++ b/.config/awesome/quarrel/delegate.lua
@@ -0,0 +1,14 @@
+--- Capture `fn`'s upvalues and pass to `delegate`
+---@param delegate fun(env: table<string, any>, _: ...): ...
+---@param fn function
+---@return fun(...): ...
+return function(delegate, fn)
+ local upvalues = {}
+ for i = 1, debug.getinfo(fn, "u").nups do
+ local name, value = debug.getupvalue(fn, i)
+ upvalues[name] = value
+ end
+ return function(...)
+ return delegate(upvalues, ...)
+ end
+end
diff --git a/.config/awesome/quarrel/fs.lua b/.config/awesome/quarrel/fs.lua
index 89a1bc6..502f189 100644
--- a/.config/awesome/quarrel/fs.lua
+++ b/.config/awesome/quarrel/fs.lua
@@ -1,7 +1,12 @@
-local GFile = require "lgi".Gio.File
+local GFile = require("lgi").Gio.File
+---@class QuarrelFs
local qfs = {}
+--- Read a file with the specified format (or "a") and close the file
+---@param path string
+---@param format openmode
+---@return any
function qfs.read(path, format)
local f = assert(io.open(path, "r"))
local c = f:read(format or "a")
@@ -9,13 +14,23 @@ function qfs.read(path, format)
return c
end
+--- List files in a directory
+---@param path string
+---@param absolute boolean?
+---@return table
function qfs.ls_files(path, absolute)
local files = GFile.new_for_path(path):enumerate_children("standard::*", 0)
local files_filtered = {}
- if not files then return {} end
+ if not files then
+ return {}
+ end
- for file in function() return files:next_file() end do
+ for file in
+ function()
+ return files:next_file()
+ end
+ do
if file:get_file_type() == "REGULAR" then
local file_name = file:get_display_name()
file_name = absolute and (path:gsub("[/]*$", "") .. "/" .. file_name) or file_name
diff --git a/.config/awesome/quarrel/init.lua b/.config/awesome/quarrel/init.lua
index 025d899..96f7f5b 100644
--- a/.config/awesome/quarrel/init.lua
+++ b/.config/awesome/quarrel/init.lua
@@ -1,17 +1,22 @@
-local n = require "naughty".notification
+local n = require("naughty").notification
+---@class Quarrel
local quarrel = {}
+--- Send a notification with the specified message
+---@param message any
function quarrel.debug(message)
n { message = tostring(message) }
end
-function quarrel.is_restart()
- awesome.register_xproperty("is_restart", "boolean")
- local restart_detected = awesome.get_xproperty("is_restart") ~= nil
- awesome.set_xproperty("is_restart", true)
-
- return restart_detected
- end
+--- Check if there was a restart
+---@return boolean
+function quarrel.is_restart()
+ awesome.register_xproperty("is_restart", "boolean")
+ local restart_detected = awesome.get_xproperty "is_restart" ~= nil
+ awesome.set_xproperty("is_restart", true)
+
+ return restart_detected
+end
return quarrel
diff --git a/.config/awesome/quarrel/json.lua b/.config/awesome/quarrel/json.lua
index 711ef78..5bcc5ff 100644
--- a/.config/awesome/quarrel/json.lua
+++ b/.config/awesome/quarrel/json.lua
@@ -31,111 +31,103 @@ local json = { _version = "0.1.2" }
local encode
local escape_char_map = {
- [ "\\" ] = "\\",
- [ "\"" ] = "\"",
- [ "\b" ] = "b",
- [ "\f" ] = "f",
- [ "\n" ] = "n",
- [ "\r" ] = "r",
- [ "\t" ] = "t",
+ ["\\"] = "\\",
+ ['"'] = '"',
+ ["\b"] = "b",
+ ["\f"] = "f",
+ ["\n"] = "n",
+ ["\r"] = "r",
+ ["\t"] = "t",
}
-local escape_char_map_inv = { [ "/" ] = "/" }
+local escape_char_map_inv = { ["/"] = "/" }
for k, v in pairs(escape_char_map) do
- escape_char_map_inv[v] = k
+ escape_char_map_inv[v] = k
end
-
local function escape_char(c)
- return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
+ return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
end
-
local function encode_nil(val)
- return "null"
+ return "null"
end
-
local function encode_table(val, stack)
- local res = {}
- stack = stack or {}
-
- -- Circular reference?
- if stack[val] then error("circular reference") end
-
- stack[val] = true
-
- if rawget(val, 1) ~= nil or next(val) == nil then
- -- Treat as array -- check keys are valid and it is not sparse
- local n = 0
- for k in pairs(val) do
- if type(k) ~= "number" then
- error("invalid table: mixed or invalid key types")
- end
- n = n + 1
- end
- if n ~= #val then
- error("invalid table: sparse array")
- end
- -- Encode
- for i, v in ipairs(val) do
- table.insert(res, encode(v, stack))
+ local res = {}
+ stack = stack or {}
+
+ -- Circular reference?
+ if stack[val] then
+ error "circular reference"
end
- stack[val] = nil
- return "[" .. table.concat(res, ",") .. "]"
-
- else
- -- Treat as an object
- for k, v in pairs(val) do
- if type(k) ~= "string" then
- error("invalid table: mixed or invalid key types")
- end
- table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+
+ stack[val] = true
+
+ if rawget(val, 1) ~= nil or next(val) == nil then
+ -- Treat as array -- check keys are valid and it is not sparse
+ local n = 0
+ for k in pairs(val) do
+ if type(k) ~= "number" then
+ error "invalid table: mixed or invalid key types"
+ end
+ n = n + 1
+ end
+ if n ~= #val then
+ error "invalid table: sparse array"
+ end
+ -- Encode
+ for i, v in ipairs(val) do
+ table.insert(res, encode(v, stack))
+ end
+ stack[val] = nil
+ return "[" .. table.concat(res, ",") .. "]"
+ else
+ -- Treat as an object
+ for k, v in pairs(val) do
+ if type(k) ~= "string" then
+ error "invalid table: mixed or invalid key types"
+ end
+ table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
+ end
+ stack[val] = nil
+ return "{" .. table.concat(res, ",") .. "}"
end
- stack[val] = nil
- return "{" .. table.concat(res, ",") .. "}"
- end
end
-
local function encode_string(val)
- return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
+ return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
end
-
local function encode_number(val)
- -- Check for NaN, -inf and inf
- if val ~= val or val <= -math.huge or val >= math.huge then
- error("unexpected number value '" .. tostring(val) .. "'")
- end
- return string.format("%.14g", val)
+ -- Check for NaN, -inf and inf
+ if val ~= val or val <= -math.huge or val >= math.huge then
+ error("unexpected number value '" .. tostring(val) .. "'")
+ end
+ return string.format("%.14g", val)
end
-
local type_func_map = {
- [ "nil" ] = encode_nil,
- [ "table" ] = encode_table,
- [ "string" ] = encode_string,
- [ "number" ] = encode_number,
- [ "boolean" ] = tostring,
+ ["nil"] = encode_nil,
+ ["table"] = encode_table,
+ ["string"] = encode_string,
+ ["number"] = encode_number,
+ ["boolean"] = tostring,
}
-
encode = function(val, stack)
- local t = type(val)
- local f = type_func_map[t]
- if f then
- return f(val, stack)
- end
- error("unexpected type '" .. t .. "'")
+ local t = type(val)
+ local f = type_func_map[t]
+ if f then
+ return f(val, stack)
+ end
+ error("unexpected type '" .. t .. "'")
end
-
function json.encode(val)
- return ( encode(val) )
+ return (encode(val))
end
-
-------------------------------------------------------------------------------
-- Decode
-------------------------------------------------------------------------------
@@ -143,246 +135,238 @@ end
local parse
local function create_set(...)
- local res = {}
- for i = 1, select("#", ...) do
- res[ select(i, ...) ] = true
- end
- return res
+ local res = {}
+ for i = 1, select("#", ...) do
+ res[select(i, ...)] = true
+ end
+ return res
end
-local space_chars = create_set(" ", "\t", "\r", "\n")
-local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
-local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
-local literals = create_set("true", "false", "null")
+local space_chars = create_set(" ", "\t", "\r", "\n")
+local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
+local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
+local literals = create_set("true", "false", "null")
local literal_map = {
- [ "true" ] = true,
- [ "false" ] = false,
- [ "null" ] = nil,
+ ["true"] = true,
+ ["false"] = false,
+ ["null"] = nil,
}
-
local function next_char(str, idx, set, negate)
- for i = idx, #str do
- if set[str:sub(i, i)] ~= negate then
- return i
+ for i = idx, #str do
+ if set[str:sub(i, i)] ~= negate then
+ return i
+ end
end
- end
- return #str + 1
+ return #str + 1
end
-
local function decode_error(str, idx, msg)
- local line_count = 1
- local col_count = 1
- for i = 1, idx - 1 do
- col_count = col_count + 1
- if str:sub(i, i) == "\n" then
- line_count = line_count + 1
- col_count = 1
+ local line_count = 1
+ local col_count = 1
+ for i = 1, idx - 1 do
+ col_count = col_count + 1
+ if str:sub(i, i) == "\n" then
+ line_count = line_count + 1
+ col_count = 1
+ end
end
- end
- error( string.format("%s at line %d col %d", msg, line_count, col_count) )
+ error(string.format("%s at line %d col %d", msg, line_count, col_count))
end
-
local function codepoint_to_utf8(n)
- -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
- local f = math.floor
- if n <= 0x7f then
- return string.char(n)
- elseif n <= 0x7ff then
- return string.char(f(n / 64) + 192, n % 64 + 128)
- elseif n <= 0xffff then
- return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
- elseif n <= 0x10ffff then
- return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
- f(n % 4096 / 64) + 128, n % 64 + 128)
- end
- error( string.format("invalid unicode codepoint '%x'", n) )
+ -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
+ local f = math.floor
+ if n <= 0x7f then
+ return string.char(n)
+ elseif n <= 0x7ff then
+ return string.char(f(n / 64) + 192, n % 64 + 128)
+ elseif n <= 0xffff then
+ return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
+ elseif n <= 0x10ffff then
+ return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, f(n % 4096 / 64) + 128, n % 64 + 128)
+ end
+ error(string.format("invalid unicode codepoint '%x'", n))
end
-
local function parse_unicode_escape(s)
- local n1 = tonumber( s:sub(1, 4), 16 )
- local n2 = tonumber( s:sub(7, 10), 16 )
- -- Surrogate pair?
- if n2 then
- return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
- else
- return codepoint_to_utf8(n1)
- end
+ local n1 = tonumber(s:sub(1, 4), 16)
+ local n2 = tonumber(s:sub(7, 10), 16)
+ -- Surrogate pair?
+ if n2 then
+ return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
+ else
+ return codepoint_to_utf8(n1)
+ end
end
-
local function parse_string(str, i)
- local res = ""
- local j = i + 1
- local k = j
-
- while j <= #str do
- local x = str:byte(j)
-
- if x < 32 then
- decode_error(str, j, "control character in string")
-
- elseif x == 92 then -- `\`: Escape
- res = res .. str:sub(k, j - 1)
- j = j + 1
- local c = str:sub(j, j)
- if c == "u" then
- local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
- or str:match("^%x%x%x%x", j + 1)
- or decode_error(str, j - 1, "invalid unicode escape in string")
- res = res .. parse_unicode_escape(hex)
- j = j + #hex
- else
- if not escape_chars[c] then
- decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
+ local res = ""
+ local j = i + 1
+ local k = j
+
+ while j <= #str do
+ local x = str:byte(j)
+
+ if x < 32 then
+ decode_error(str, j, "control character in string")
+ elseif x == 92 then -- `\`: Escape
+ res = res .. str:sub(k, j - 1)
+ j = j + 1
+ local c = str:sub(j, j)
+ if c == "u" then
+ local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
+ or str:match("^%x%x%x%x", j + 1)
+ or decode_error(str, j - 1, "invalid unicode escape in string")
+ res = res .. parse_unicode_escape(hex)
+ j = j + #hex
+ else
+ if not escape_chars[c] then
+ decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
+ end
+ res = res .. escape_char_map_inv[c]
+ end
+ k = j + 1
+ elseif x == 34 then -- `"`: End of string
+ res = res .. str:sub(k, j - 1)
+ return res, j + 1
end
- res = res .. escape_char_map_inv[c]
- end
- k = j + 1
- elseif x == 34 then -- `"`: End of string
- res = res .. str:sub(k, j - 1)
- return res, j + 1
+ j = j + 1
end
- j = j + 1
- end
-
- decode_error(str, i, "expected closing quote for string")
+ decode_error(str, i, "expected closing quote for string")
end
-
local function parse_number(str, i)
- local x = next_char(str, i, delim_chars)
- local s = str:sub(i, x - 1)
- local n = tonumber(s)
- if not n then
- decode_error(str, i, "invalid number '" .. s .. "'")
- end
- return n, x
+ local x = next_char(str, i, delim_chars)
+ local s = str:sub(i, x - 1)
+ local n = tonumber(s)
+ if not n then
+ decode_error(str, i, "invalid number '" .. s .. "'")
+ end
+ return n, x
end
-
local function parse_literal(str, i)
- local x = next_char(str, i, delim_chars)
- local word = str:sub(i, x - 1)
- if not literals[word] then
- decode_error(str, i, "invalid literal '" .. word .. "'")
- end
- return literal_map[word], x
+ local x = next_char(str, i, delim_chars)
+ local word = str:sub(i, x - 1)
+ if not literals[word] then
+ decode_error(str, i, "invalid literal '" .. word .. "'")
+ end
+ return literal_map[word], x
end
-
local function parse_array(str, i)
- local res = {}
- local n = 1
- i = i + 1
- while 1 do
- local x
- i = next_char(str, i, space_chars, true)
- -- Empty / end of array?
- if str:sub(i, i) == "]" then
- i = i + 1
- break
- end
- -- Read token
- x, i = parse(str, i)
- res[n] = x
- n = n + 1
- -- Next token
- i = next_char(str, i, space_chars, true)
- local chr = str:sub(i, i)
+ local res = {}
+ local n = 1
i = i + 1
- if chr == "]" then break end
- if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
- end
- return res, i
+ while 1 do
+ local x
+ i = next_char(str, i, space_chars, true)
+ -- Empty / end of array?
+ if str:sub(i, i) == "]" then
+ i = i + 1
+ break
+ end
+ -- Read token
+ x, i = parse(str, i)
+ res[n] = x
+ n = n + 1
+ -- Next token
+ i = next_char(str, i, space_chars, true)
+ local chr = str:sub(i, i)
+ i = i + 1
+ if chr == "]" then
+ break
+ end
+ if chr ~= "," then
+ decode_error(str, i, "expected ']' or ','")
+ end
+ end
+ return res, i
end
-
local function parse_object(str, i)
- local res = {}
- i = i + 1
- while 1 do
- local key, val
- i = next_char(str, i, space_chars, true)
- -- Empty / end of object?
- if str:sub(i, i) == "}" then
- i = i + 1
- break
- end
- -- Read key
- if str:sub(i, i) ~= '"' then
- decode_error(str, i, "expected string for key")
- end
- key, i = parse(str, i)
- -- Read ':' delimiter
- i = next_char(str, i, space_chars, true)
- if str:sub(i, i) ~= ":" then
- decode_error(str, i, "expected ':' after key")
- end
- i = next_char(str, i + 1, space_chars, true)
- -- Read value
- val, i = parse(str, i)
- -- Set
- res[key] = val
- -- Next token
- i = next_char(str, i, space_chars, true)
- local chr = str:sub(i, i)
+ local res = {}
i = i + 1
- if chr == "}" then break end
- if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
- end
- return res, i
+ while 1 do
+ local key, val
+ i = next_char(str, i, space_chars, true)
+ -- Empty / end of object?
+ if str:sub(i, i) == "}" then
+ i = i + 1
+ break
+ end
+ -- Read key
+ if str:sub(i, i) ~= '"' then
+ decode_error(str, i, "expected string for key")
+ end
+ key, i = parse(str, i)
+ -- Read ':' delimiter
+ i = next_char(str, i, space_chars, true)
+ if str:sub(i, i) ~= ":" then
+ decode_error(str, i, "expected ':' after key")
+ end
+ i = next_char(str, i + 1, space_chars, true)
+ -- Read value
+ val, i = parse(str, i)
+ -- Set
+ res[key] = val
+ -- Next token
+ i = next_char(str, i, space_chars, true)
+ local chr = str:sub(i, i)
+ i = i + 1
+ if chr == "}" then
+ break
+ end
+ if chr ~= "," then
+ decode_error(str, i, "expected '}' or ','")
+ end
+ end
+ return res, i
end
-
local char_func_map = {
- [ '"' ] = parse_string,
- [ "0" ] = parse_number,
- [ "1" ] = parse_number,
- [ "2" ] = parse_number,
- [ "3" ] = parse_number,
- [ "4" ] = parse_number,
- [ "5" ] = parse_number,
- [ "6" ] = parse_number,
- [ "7" ] = parse_number,
- [ "8" ] = parse_number,
- [ "9" ] = parse_number,
- [ "-" ] = parse_number,
- [ "t" ] = parse_literal,
- [ "f" ] = parse_literal,
- [ "n" ] = parse_literal,
- [ "[" ] = parse_array,
- [ "{" ] = parse_object,
+ ['"'] = parse_string,
+ ["0"] = parse_number,
+ ["1"] = parse_number,
+ ["2"] = parse_number,
+ ["3"] = parse_number,
+ ["4"] = parse_number,
+ ["5"] = parse_number,
+ ["6"] = parse_number,
+ ["7"] = parse_number,
+ ["8"] = parse_number,
+ ["9"] = parse_number,
+ ["-"] = parse_number,
+ ["t"] = parse_literal,
+ ["f"] = parse_literal,
+ ["n"] = parse_literal,
+ ["["] = parse_array,
+ ["{"] = parse_object,
}
-
parse = function(str, idx)
- local chr = str:sub(idx, idx)
- local f = char_func_map[chr]
- if f then
- return f(str, idx)
- end
- decode_error(str, idx, "unexpected character '" .. chr .. "'")
+ local chr = str:sub(idx, idx)
+ local f = char_func_map[chr]
+ if f then
+ return f(str, idx)
+ end
+ decode_error(str, idx, "unexpected character '" .. chr .. "'")
end
-
function json.decode(str)
- if type(str) ~= "string" then
- error("expected argument of type string, got " .. type(str))
- end
- local res, idx = parse(str, next_char(str, 1, space_chars, true))
- idx = next_char(str, idx, space_chars, true)
- if idx <= #str then
- decode_error(str, idx, "trailing garbage")
- end
- return res
+ if type(str) ~= "string" then
+ error("expected argument of type string, got " .. type(str))
+ end
+ local res, idx = parse(str, next_char(str, 1, space_chars, true))
+ idx = next_char(str, idx, space_chars, true)
+ if idx <= #str then
+ decode_error(str, idx, "trailing garbage")
+ end
+ return res
end
-
return json
diff --git a/.config/awesome/quarrel/lua-rust.tar.gz b/.config/awesome/quarrel/lua-rust.tar.gz
new file mode 100644
index 0000000..5ff33fd
--- /dev/null
+++ b/.config/awesome/quarrel/lua-rust.tar.gz
Binary files differ
diff --git a/.config/awesome/quarrel/markup.lua b/.config/awesome/quarrel/markup.lua
new file mode 100644
index 0000000..d206530
--- /dev/null
+++ b/.config/awesome/quarrel/markup.lua
@@ -0,0 +1,30 @@
+--- Apply markup to a file
+---@param content string
+---@param args { bold: boolean, italic: boolean, fg: string, bg: string }
+---@return string
+return function(content, args)
+ args = args or {}
+ if args.bold then
+ content = "<b>" .. content .. "</b>"
+ end
+
+ if args.italic then
+ content = "<i>" .. content .. "</i>"
+ end
+
+ local span_content = ""
+
+ if args.fg or args.bg then
+ if args.fg then
+ span_content = "foreground='" .. args.fg .. "'"
+ end
+
+ if args.bg then
+ span_content = " background='" .. args.bg .. "'"
+ end
+
+ content = "<span " .. span_content .. ">" .. content .. "</span>"
+ end
+
+ return content
+end
diff --git a/.config/awesome/quarrel/math.lua b/.config/awesome/quarrel/math.lua
index 886ce13..b16547b 100644
--- a/.config/awesome/quarrel/math.lua
+++ b/.config/awesome/quarrel/math.lua
@@ -1,5 +1,10 @@
+local gmath = require "gears.math"
+
+---@class QuarrelMath
local qmath = {}
+-- TODO: Finish documenting these functions
+
function qmath.step_value(value, steps)
if value > steps[#steps - 1][1] then
return steps[#steps - 1][2]
@@ -15,6 +20,10 @@ function qmath.translate_range(value, in_min, in_max, out_min, out_max)
return out_min + ((out_max - out_min) / (in_max - in_min)) * (value - in_min)
end
+function qmath.percentage(value, max)
+ return gmath.round(value / max * 100)
+end
+
function qmath.clamp(value, min, max)
return math.max(math.min(value, max), min)
end
diff --git a/.config/awesome/quarrel/native/Cargo.toml b/.config/awesome/quarrel/native/Cargo.toml
index 9cff8fc..8d56c9f 100644
--- a/.config/awesome/quarrel/native/Cargo.toml
+++ b/.config/awesome/quarrel/native/Cargo.toml
@@ -17,6 +17,13 @@ nix = "0.26.2"
chrono = "0.4.24"
itertools = "0.10.5"
html-escape = "0.2.13"
+mpd = { git = "https://github.com/kstep/rust-mpd", features = [ "serde" ], version = "0.1.0" }
+cairo-rs = { git = "https://github.com/gtk-rs/gtk-rs-core.git", version = "0.18.0" }
+gdk-pixbuf = { git = "https://github.com/gtk-rs/gtk-rs-core.git", version = "0.18.0" }
+symphonia = "0.5.3"
+dirs = "5.0.1"
+once_cell = "1.18.0"
+
[lib]
crate-type = ["cdylib"]
diff --git a/.config/awesome/quarrel/native/init.lua b/.config/awesome/quarrel/native/init.lua
index 14c66e5..e5d5aab 100644
--- a/.config/awesome/quarrel/native/init.lua
+++ b/.config/awesome/quarrel/native/init.lua
@@ -1,6 +1,43 @@
+---@meta
+
local old_cpath = package.cpath
local cfg = require("gears.filesystem").get_configuration_dir()
package.cpath = package.cpath .. ";" .. cfg .. "quarrel/native/lib?.so"
+
+---@class Entry
+---@field message string
+---@field exec { [1]: string, [2]: boolean }?
+
+---@alias query fun(input: string): Entry[]
+
+---@class Lenses
+---@field [1] query Calculator lense
+---@field [2] query Application lense
+
+---@alias ReadMode "l" | "n" | string
+
+---@class FileHandle
+---@field read fun(self, mode: ReadMode): string | number
+---@field write fun(self, content: string): number
+---@field lines fun(self): string[]
+---@field rewind fun(self)
+
+---@class Util
+---@field decode_html fun(input: string): string
+---@field open_file fun(path: string): FileHandle
+
+---@class Mpd
+---@field init
+
+---@class Net
+---@field get_essid fun(): string
+
+---@class QuarrelNative
+---@field lenses Lenses
+---@field util Util
+---@field mpd Mpd
+---@field net Net
local qnative = require "qnative"
+
package.cpath = old_cpath
return qnative
diff --git a/.config/awesome/quarrel/native/src/lenses/application.rs b/.config/awesome/quarrel/native/src/lenses/application.rs
index 0857802..72aba8d 100644
--- a/.config/awesome/quarrel/native/src/lenses/application.rs
+++ b/.config/awesome/quarrel/native/src/lenses/application.rs
@@ -73,7 +73,7 @@ pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
return None
};
- return parse_entry(&entry, &path).ok();
+ parse_entry(&entry, &path).ok()
})
.collect();
diff --git a/.config/awesome/quarrel/native/src/lenses/calculator.rs b/.config/awesome/quarrel/native/src/lenses/calculator.rs
index c79dd42..07f1ee2 100644
--- a/.config/awesome/quarrel/native/src/lenses/calculator.rs
+++ b/.config/awesome/quarrel/native/src/lenses/calculator.rs
@@ -10,7 +10,7 @@ use crate::lenses::entry::{
Entry,
};
-pub fn query<'a>(lua: &Lua, input: String) -> LuaResult<LuaTable> {
+pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
let result = match eval(input.trim(), true, Unit::Celsius, false) {
Ok(result) => {
format!("{result}")
diff --git a/.config/awesome/quarrel/native/src/lib.rs b/.config/awesome/quarrel/native/src/lib.rs
index d89b610..472313e 100644
--- a/.config/awesome/quarrel/native/src/lib.rs
+++ b/.config/awesome/quarrel/native/src/lib.rs
@@ -1,8 +1,9 @@
mod lenses;
+mod mpd;
mod net;
+mod util;
use mlua::prelude::*;
-use html_escape::decode_html_entities_to_string;
#[mlua::lua_module]
fn qnative(lua: &Lua) -> LuaResult<LuaTable> {
@@ -10,14 +11,21 @@ fn qnative(lua: &Lua) -> LuaResult<LuaTable> {
lenses.set("1", lua.create_function(lenses::calculator::query)?)?;
lenses.set("2", lua.create_function(lenses::application::query)?)?;
+ let util = lua.create_table()?;
+ util.set("decode_html", lua.create_function(util::decode_html)?)?;
+ util.set("open_file", lua.create_function(util::FileHandle::new)?)?;
+
+ let mpd = lua.create_table()?;
+ mpd.set("init", lua.create_function(mpd::init)?)?;
+
+ let net = lua.create_table()?;
+ net.set("get_essid", lua.create_function(net::get_first_essid)?)?;
+
let exports = lua.create_table()?;
exports.set("lenses", lenses)?;
- exports.set("get_essid", lua.create_function(net::get_first_essid)?)?;
- exports.set("decode_html", lua.create_function(|_: &Lua, string: String| {
- let mut output = String::new();
- decode_html_entities_to_string(string, &mut output);
- Ok(output)
- })?)?;
+ exports.set("mpd", mpd)?;
+ exports.set("net", net)?;
+ exports.set("util", util)?;
Ok(exports)
}
diff --git a/.config/awesome/quarrel/native/src/mpd.rs b/.config/awesome/quarrel/native/src/mpd.rs
new file mode 100644
index 0000000..08c9e42
--- /dev/null
+++ b/.config/awesome/quarrel/native/src/mpd.rs
@@ -0,0 +1,142 @@
+use std::{
+ ffi::c_void,
+ fs::File,
+ net::TcpStream,
+ path::PathBuf,
+ sync::mpsc::channel,
+};
+
+use dirs::home_dir;
+use gdk_pixbuf::{
+ ffi::GdkPixbuf,
+ glib::translate::IntoGlibPtr,
+ traits::PixbufLoaderExt,
+ Pixbuf,
+ PixbufLoader,
+};
+use mlua::{
+ prelude::*,
+ LuaSerdeExt,
+};
+use mpd::Client;
+use once_cell::sync::Lazy;
+use symphonia::{
+ core::{
+ formats::FormatOptions,
+ io::{
+ MediaSourceStream,
+ MediaSourceStreamOptions,
+ },
+ meta::MetadataOptions,
+ probe::Hint,
+ },
+ default::get_probe,
+};
+
+static MPD_MUSIC_PATH: Lazy<PathBuf> = Lazy::new(|| {
+ [
+ home_dir().expect("home directory should be set"),
+ "Music".into(),
+ ]
+ .iter()
+ .collect()
+});
+
+static COVER_FORMATS: [&str; 2] = ["png", "jpg"];
+
+pub struct Connection(Client<TcpStream>);
+
+impl LuaUserData for Connection {
+ fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_method_mut("status", |lua, this: &mut Connection, (): ()| {
+ lua.to_value(&this.0.status().map_err(LuaError::external)?)
+ });
+
+ methods.add_method_mut("song", |lua, this: &mut Connection, (): ()| {
+ Ok(
+ if let Some(song) = this.0.currentsong().map_err(LuaError::external)? {
+ lua.to_value(&song)?
+ } else {
+ LuaNil
+ },
+ )
+ });
+
+ methods.add_method(
+ "get_cover_pixbuf",
+ |_, _: &Connection, file: String| {
+ let song_path = MPD_MUSIC_PATH.join(file);
+ let mut has_external_cover = false;
+ let mut cover_path = PathBuf::new();
+
+ for format in COVER_FORMATS {
+ let cover = song_path
+ .parent()
+ .unwrap()
+ .to_owned()
+ .join(format!("cover.{}", format));
+ if cover.exists() {
+ has_external_cover = cover.exists();
+ cover_path = cover;
+ break;
+ }
+ }
+
+ let mss = MediaSourceStream::new(
+ Box::new(File::open(song_path)?),
+ MediaSourceStreamOptions::default(),
+ );
+
+ let mut probed = get_probe()
+ .format(
+ &Hint::default(),
+ mss,
+ &FormatOptions::default(),
+ &MetadataOptions::default(),
+ )
+ .map_err(LuaError::external)?;
+
+ let visuals;
+
+ if let Some(metadata) = probed.format.metadata().skip_to_latest() {
+ visuals = metadata.visuals();
+ if visuals.is_empty() && has_external_cover {
+ let pixbuf = Pixbuf::from_file(cover_path).map_err(LuaError::external)?;
+
+ return Ok((
+ Some(LuaLightUserData(unsafe {
+ <Pixbuf as IntoGlibPtr<*mut GdkPixbuf>>::into_glib_ptr(pixbuf)
+ .cast::<c_void>()
+ })),
+ Some(true),
+ ));
+ }
+
+ let loader = PixbufLoader::new();
+ loader
+ .write(visuals.first().unwrap().data.as_ref())
+ .map_err(LuaError::external)?;
+ loader.close().map_err(LuaError::external)?;
+
+ return Ok((
+ Some(LuaLightUserData(unsafe {
+ <Pixbuf as IntoGlibPtr<*mut GdkPixbuf>>::into_glib_ptr(
+ loader.pixbuf().expect("Pixbuf should be initialized"),
+ )
+ .cast::<c_void>()
+ })),
+ Some(false),
+ ));
+ }
+
+ Ok((None, None))
+ },
+ );
+ }
+}
+
+pub fn init(_: &Lua, _: ()) -> LuaResult<Connection> {
+ Ok(Connection(
+ Client::connect("localhost:6600").map_err(LuaError::external)?,
+ ))
+}
diff --git a/.config/awesome/quarrel/native/src/net/mod.rs b/.config/awesome/quarrel/native/src/net/mod.rs
index 71eaeea..96c853e 100644
--- a/.config/awesome/quarrel/native/src/net/mod.rs
+++ b/.config/awesome/quarrel/native/src/net/mod.rs
@@ -39,7 +39,12 @@ use wireless::{
ioctl_read_bad!(ioctl_get_interfaces, SIOCGIFCONF, IfConf);
ioctl_read_bad!(ioctl_get_essid, SIOCGIWESSID, IwReq);
+#[allow(clippy::unnecessary_wraps)]
pub fn get_first_essid(_: &Lua, _: ()) -> LuaResult<String> {
+ Ok(get_first_essid_error().unwrap_or(String::new()))
+}
+
+fn get_first_essid_error() -> LuaResult<String> {
type Buffer = [c_char; 1024];
let mut buffer: Buffer = [0; 1024];
diff --git a/.config/awesome/quarrel/native/src/time.rs b/.config/awesome/quarrel/native/src/time.rs
deleted file mode 100644
index 9850822..0000000
--- a/.config/awesome/quarrel/native/src/time.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-use chrono::prelude::*;
-use mlua::{
- prelude::*,
- LuaSerdeExt,
-};
-
-// Taken from https://github.com/chronotope/chrono/issues/69#issuecomment-1510506428
-trait NaiveDateExt {
- fn days_in_month(&self) -> u32;
- fn days_in_year(&self) -> u32;
- fn is_leap_year(&self) -> bool;
-}
-
-impl NaiveDateExt for NaiveDate {
- fn days_in_month(&self) -> u32 {
- let month = self.month();
- match month {
- 1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
- 4 | 6 | 9 | 11 => 30,
- 2 => {
- if self.is_leap_year() {
- 29
- } else {
- 28
- }
- }
- _ => panic!("Invalid month: {}", month),
- }
- }
-
- fn days_in_year(&self) -> u32 {
- if self.is_leap_year() {
- 366
- } else {
- 365
- }
- }
-
- fn is_leap_year(&self) -> bool {
- let year = self.year();
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
- }
-}
-
-struct Day {
- day: u32,
- ce: bool,
- weekday: Weekday,
-}
-
-pub fn get_calendar_table(lua: &Lua, (year, month, day): (i32, u32, u32)) -> LuaResult<LuaTable> {
- let date =
- NaiveDate::from_ymd_opt(year, month, day).ok_or(LuaError::external("invalid date"))?;
- let days: Vec<Day> = (1..=date.days_in_month())
- .map(|day| NaiveDate::from_ymd_opt(date.year(), date.month(), day).unwrap())
- .map(|date| {
- let (ce, year) = date.year_ce();
- Day {
- day: date.day(),
- ce,
- weekday: date.weekday(),
- }
- })
- .collect();
-
- let calendar: Vec<Vec<Day>> = vec![vec![], vec![], vec![], vec![], vec![], vec![], vec![]];
-
- if days[1].weekday != Weekday::Mon {
- get_calendar_table(lua)
- }
-
- if days.last().unwrap().weekday != Weekday::Sun {}
-
- Ok(lua.create_table()?)
-}
diff --git a/.config/awesome/quarrel/native/src/util.rs b/.config/awesome/quarrel/native/src/util.rs
new file mode 100644
index 0000000..85a2574
--- /dev/null
+++ b/.config/awesome/quarrel/native/src/util.rs
@@ -0,0 +1,101 @@
+use std::{
+ cell::RefCell,
+ fs::File,
+ fs::OpenOptions,
+ io::{
+ Read,
+ Seek,
+ Write
+ },
+ rc::Rc,
+ str::FromStr,
+};
+
+use html_escape::decode_html_entities_to_string;
+use mlua::prelude::*;
+use serde::Serialize;
+
+pub fn decode_html(_: &Lua, string: String) -> LuaResult<String> {
+ let mut output = String::new();
+ decode_html_entities_to_string(string, &mut output);
+ Ok(output)
+}
+
+enum ReadMode {
+ Line,
+ Number,
+ All,
+}
+
+impl FromStr for ReadMode {
+ type Err = ();
+
+ fn from_str(value: &str) -> Result<Self, Self::Err> {
+ Ok(match value {
+ "l" => Self::Line,
+ "n" => Self::Number,
+ _ => Self::All,
+ })
+ }
+}
+
+#[derive(Serialize)]
+#[serde(untagged)]
+enum StringOrNumber {
+ String(String),
+ Number(u64),
+}
+
+pub struct FileHandle(Rc<RefCell<File>>);
+
+impl LuaUserData for FileHandle {
+ fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
+ methods.add_method("read", |lua, this: &FileHandle, mode: String| {
+ let content = this.read()?;
+ Ok(lua.to_value(&match ReadMode::from_str(&mode).unwrap() {
+ ReadMode::Line => StringOrNumber::String(
+ content
+ .lines()
+ .next()
+ .map_or_else(String::new, |slice| slice.trim().to_owned()),
+ ),
+ ReadMode::Number => StringOrNumber::Number(
+ content.trim().parse::<u64>().map_err(LuaError::external)?,
+ ),
+ ReadMode::All => StringOrNumber::String(content),
+ }))
+ });
+ methods.add_method("write", |_, this: &FileHandle, content: String| {
+ this.write(content.as_bytes())
+ });
+ methods.add_method("lines", |_, this: &FileHandle, (): ()| {
+ Ok(this
+ .read()?
+ .lines()
+ .map(ToOwned::to_owned)
+ .collect::<Vec<String>>())
+ });
+ methods.add_method("rewind", |_, this: &FileHandle, (): ()| this.rewind());
+ }
+}
+
+impl FileHandle {
+ pub fn new(_: &Lua, path: String) -> LuaResult<Self> {
+ Ok(Self(Rc::new(RefCell::new(File::open(path)?))))
+ // Ok(Self(Rc::new(RefCell::new(OpenOptions::new().write(true).read(true).open(path)?))))
+ }
+
+ fn read(&self) -> LuaResult<String> {
+ let mut content = String::new();
+ self.0.borrow_mut().read_to_string(&mut content)?;
+ Ok(content)
+ }
+
+ fn rewind(&self) -> LuaResult<()> {
+ self.0.borrow_mut().rewind().map_err(LuaError::external)
+ }
+
+ fn write(&self, buf: &[u8]) -> LuaResult<usize> {
+ self.0.borrow_mut().write(buf).map_err(LuaError::external)
+ }
+}
diff --git a/.config/awesome/quarrel/store.lua b/.config/awesome/quarrel/store.lua
index 9f6cff2..9422c21 100644
--- a/.config/awesome/quarrel/store.lua
+++ b/.config/awesome/quarrel/store.lua
@@ -1,3 +1,4 @@
+---@type table
local qstore = {}
return qstore
diff --git a/.config/awesome/quarrel/table.lua b/.config/awesome/quarrel/table.lua
index 13ccbce..2ae15ee 100644
--- a/.config/awesome/quarrel/table.lua
+++ b/.config/awesome/quarrel/table.lua
@@ -1,17 +1,30 @@
+---@class QuarrelTable
local qtable = {}
+--- Map a function on each element in the table
+---@param t table
+---@generic T
+---@param f fun(v: T): T
+---@return table
function qtable.map(t, f)
local nt = {}
- for k,v in pairs(t) do
+ for k, v in pairs(t) do
nt[k] = f(v)
end
return nt
end
+--- Filter a table with a function
+---@param t table
+---@param f fun(v: any): boolean
+---@param dict boolean Whether the supplied table is a dictionary
+---@return table
function qtable.filter(t, f, dict)
local nt = {}
- for k,v in pairs(t) do
- if not f(v) then goto continue end
+ for k, v in pairs(t) do
+ if not f(v) then
+ goto continue
+ end
if dict then
nt[k] = v
else
@@ -40,9 +53,9 @@ function qtable.onext(t, state)
t.__oindex = __gen_oindex(t)
key = t.__oindex[1]
else
- for i = 1,#t.__oindex do
+ for i = 1, #t.__oindex do
if t.__oindex[i] == state then
- key = t.__oindex[i+1]
+ key = t.__oindex[i + 1]
end
end
end
diff --git a/.config/awesome/quarrel/ui.lua b/.config/awesome/quarrel/ui.lua
index 274d48a..1db4a70 100644
--- a/.config/awesome/quarrel/ui.lua
+++ b/.config/awesome/quarrel/ui.lua
@@ -2,69 +2,68 @@ local awful = require "awful"
local gtable = require "gears.table"
local qbind = require "quarrel.bind"
local qvars = require "quarrel.vars"
+local rtimed = require "lib.rubato.timed"
local wibox = require "wibox"
+---@class QuarrelUi
local qui = {}
-function qui.markup_fg(color, text)
- return "<span color=\"" .. color .. "\">" .. text .. "</span>"
-end
-
-function qui.markup_bg(color, text)
- return "<span bgcolor=\"" .. color .. "\">" .. text .. "</span>"
-end
-
+--- Return qvars.text_font with size scaled by factor
+---@param factor number
+---@return string
+---@see QuarrelVars.text_font
function qui.font(factor)
return qvars.text_font .. " " .. qvars.font_size * (factor or 1)
end
+--- Inject background widget styling into target
+---@param target table
+---@return table
function qui.styled(target)
return gtable.crush({
bg = qvars.colors.bg,
border_color = qvars.colors.bright.black,
border_width = qvars.border_width,
- shape = qvars.shape
+ shape = qvars.shape,
}, target)
end
+--- Generate a styled popup
+---@param target table
+---@return table
function qui.popup(target)
target.widget = {
widget = wibox.container.margin,
margins = qvars.big_padding,
- target.widget
+ target.widget,
}
return awful.popup(qui.styled(target))
end
-function qui.tooltip(objects, callback)
- awful.tooltip(qui.styled {
- objects = objects,
- timer_function = callback,
- margin_leftright = qvars.padding,
- margin_topbottom = qvars.padding
- })
-end
-
+--- Generate svg recolor string
+---@param color string
+---@return string
function qui.recolor(color)
return "svg{fill:" .. color .. "}"
end
-function qui.icon(image, color, target)
- local widget = {
+--- Generate icon widget
+---@param args table
+---@return table
+function qui.icon(args)
+ return gtable.crush({
widget = wibox.widget.imagebox,
- image = image,
+ image = args.icon,
forced_width = qvars.char_height,
forced_height = qvars.char_height,
- stylesheet = qui.recolor(color or qvars.colors.fg)
- }
- if target then
- return gtable.crush(widget, target)
- else
- return widget
- end
+ stylesheet = qui.recolor(args.color or qvars.colors.fg),
+ }, args.widget or {})
end
+--- Generate button widget
+---@param args table
+---@return table
function qui.button(args)
args.press = args.press or function(_) end
local widget = wibox.widget(gtable.crush({
@@ -73,7 +72,7 @@ function qui.button(args)
forced_height = qvars.char_height,
forced_width = qvars.char_height,
stylesheet = qui.recolor(qvars.colors.fg),
- press = args.press
+ press = args.press,
}, args.widget or {}))
widget.buttons = {
@@ -82,16 +81,19 @@ function qui.button(args)
press = function()
widget:press()
end,
- hidden = true
- }
+ hidden = true,
+ },
}
return widget
end
+--- Generate toggle widget
+---@param args table
+---@return table
function qui.toggle(args)
args.press = args.press or function(_) end
- local widget = qui.button({
+ local widget = qui.button {
widget = gtable.crush({
toggled = false,
silent_press = function(self, state)
@@ -100,7 +102,7 @@ function qui.toggle(args)
else
self.toggled = not self.toggled
end
-
+
if self.toggled then
self.image = args.on
else
@@ -114,10 +116,30 @@ function qui.toggle(args)
self:silent_press()
end
args.press(self)
- end
- })
+ end,
+ }
return widget
end
+---@param widget wibox.widget.base
+---@param cursor string
+function qui.hoverable(widget, cursor)
+ local hovering = false
+
+ widget:connect_signal("mouse::enter", function()
+ local w = mouse.current_wibox
+ if w then
+ w.cursor = cursor
+ end
+ end)
+
+ widget:connect_signal("mouse::leave", function()
+ local w = mouse.current_wibox
+ if w then
+ w.cursor = "left_ptr"
+ end
+ end)
+end
+
return qui
diff --git a/.config/awesome/quarrel/vars.lua b/.config/awesome/quarrel/vars.lua
index 27da3f2..1983343 100644
--- a/.config/awesome/quarrel/vars.lua
+++ b/.config/awesome/quarrel/vars.lua
@@ -1,19 +1,26 @@
-local btns = require "awful".button.names
+local awful = require "awful"
+local btns = awful.button.names
local gears = require "gears"
local xresources = require "beautiful.xresources"
local x_col = xresources.get_current_theme()
local dpi = xresources.apply_dpi
local wibox = require "wibox"
+---@class QuarrelVars
local qvars = {}
-qvars.anim_duration = 0.15
+qvars.anim_duration = 0.20
qvars.anim_intro = qvars.anim_duration / 4
-qvars.notif_timeout = 3 + qvars.anim_duration * 2
+qvars.notif_timeout = 3
-function qvars.shape(cr,w,h)
- gears.shape.rounded_rect(cr,w,h,dpi(4))
+--- Clip Cairo context
+---@param cr cairo_surface Cairo surface
+---@param w integer Widget width
+---@param h integer Widget height
+---@return nil
+function qvars.shape(cr, w, h)
+ gears.shape.rounded_rect(cr, w, h, dpi(4))
end
qvars.border_width = dpi(1.5)
@@ -21,14 +28,19 @@ qvars.border_width = dpi(1.5)
qvars.padding = dpi(4)
qvars.big_padding = dpi(8)
-qvars.text_font = "Fira Code Nerd Font Mono Medium"
-qvars.font_size = 8
+-- qvars.text_font = "Fira Code Nerd Font Mono Medium"
+-- qvars.text_font = "Iosevka Comfy SemiBold"
+qvars.text_font = "Iosevka Comfy Regular"
+-- qvars.font_size = 8
+qvars.font_size = 9
qvars.font = qvars.text_font .. " " .. qvars.font_size
-local char_width, char_height = wibox.widget {
- widget = wibox.widget.textbox,
- text = "a"
-}:get_preferred_size_at_dpi(screen[1].dpi)
+local char_width, char_height = wibox
+ .widget({
+ widget = wibox.widget.textbox,
+ text = "a",
+ })
+ :get_preferred_size_at_dpi(awful.screen.focused().dpi)
qvars.char_height = char_height
qvars.char_width = char_width
@@ -62,11 +74,11 @@ qvars.colors = {
},
dim = {
- fg = "#8893a5",
- bg = "#20262e"
+ fg = "#77828c",
+ bg = "#161b22",
},
- transparent = "#00000000"
+ transparent = "#00000000",
}
-- taken from https://github.com/bew/dotfiles/blob/ab9bb1935783f7a31ef777b1d7e26d53f35df864/gui/wezterm/cfg_utils.lua
@@ -77,15 +89,16 @@ qvars.mods = setmetatable({ _SHORT_MAP = { C = "Control", S = "Shift", A = "Mod1
resolved_mods[i] = self._SHORT_MAP[key:sub(i, i)]
end
return resolved_mods
- end
+ end,
})
+---@enum buttons
qvars.btns = {
left = btns.LEFT,
right = btns.RIGHT,
middle = btns.MIDDLE,
up = btns.SCROLL_UP,
- down = btns.SCROLL_DOWN
+ down = btns.SCROLL_DOWN,
}
return qvars
diff --git a/.config/awesome/rc.lua b/.config/awesome/rc.lua
index 67a8187..be5b3f1 100644
--- a/.config/awesome/rc.lua
+++ b/.config/awesome/rc.lua
@@ -17,3 +17,36 @@ require "signals"
require "services"
require "misc"
require "ui"
+
+
+-- require "curious"
+-- local gdebug = require "gears.debug"
+--
+-- local gobject = require "gears.object"
+--
+-- local wrap = gobject { class = { _inner = {}}}
+--
+-- local lmonitor = require "lib.lit.monitor"
+-- watch = lmonitor.watch_monitor(function(err, event)
+-- -- if err then print(err) end
+-- -- gdebug.dump(event)
+-- end)
+-- watch:watch("/home/delta/.config/awesome/test.txt")
+-- -- wrap._inner.watch = watch
+-- gdebug.dump(watch)
+
+-- local lit = require "lib.lit"
+-- local gfs = require "gears.filesystem"
+-- if not gfs.file_readable(gfs.get_configuration_dir() .. "/test_restart.txt") then
+-- require "awful".spawn({"touch", gfs.get_configuration_dir() .. "/test_restart.txt"})
+-- awesome.connect_signal("exit", lit.audio.notify_lua_close)
+-- local con = lit.audio.new_connection()
+-- con:get_sinks(function(err, sinks)
+-- if not err then
+-- require "gears.debug".dump(sinks, "sinks")
+-- else
+-- print "lolol error in sinks"
+-- end
+-- end)
+-- -- awesome.restart()
+-- end
diff --git a/.config/awesome/services/backlight.lua b/.config/awesome/services/backlight.lua
new file mode 100644
index 0000000..02ed808
--- /dev/null
+++ b/.config/awesome/services/backlight.lua
@@ -0,0 +1,34 @@
+local backlight = require("lib.lit").backlight.new("amdgpu_bl1", 5)
+local gobject = require "gears.object"
+local gtimer = require "gears.timer"
+local naughty = require "naughty"
+local phosphor = require "assets.phosphor"
+local qmath = require "quarrel.math"
+local qvars = require "quarrel.vars"
+
+local backlight_wrapper = gobject {
+ class = {
+ set = function(level, handler)
+ backlight.set(level, handler)
+ end,
+ get = function()
+ return backlight.get()
+ end,
+ },
+}
+
+backlight:connect_signal("brightness", function(_, brightness)
+ local icon_data = qmath.step_value(brightness, {
+ { 0, "cloud_moon" },
+ { 51, "moon" },
+ { 102, "sun_horizon" },
+ { 153, "sun_dim" },
+ { 204, "sun" },
+ { 255 },
+ })
+
+ backlight_wrapper:emit_signal("icon", phosphor[icon_data .. "_fill"], qvars.colors.fg)
+ backlight_wrapper:emit_signal("value", brightness)
+end)
+
+return backlight_wrapper
diff --git a/.config/awesome/services/battery.lua b/.config/awesome/services/battery.lua
new file mode 100644
index 0000000..98bacc9
--- /dev/null
+++ b/.config/awesome/services/battery.lua
@@ -0,0 +1,81 @@
+local UPower = require("lgi").UPowerGlib
+local gobject = require "gears.object"
+local gtimer = require "gears.timer"
+local phosphor = require "assets.phosphor"
+local qmath = require "quarrel.math"
+local qvars = require "quarrel.vars"
+
+local upower = assert(UPower.Client.new_full())
+local inner
+
+for _, device in ipairs(upower:get_devices()) do
+ if UPower.Device.kind_to_string(device.kind) == "battery" and device.model == "Primary" then
+ inner = device
+ break
+ end
+end
+
+local _level, _state
+
+---@class Battery: gears.object
+---@field _private { level: number, state: string}
+local battery = gobject {
+ class = {
+ set_level = function(self, level)
+ _level = level
+ self:emit_signal("level", level)
+ end,
+ get_level = function()
+ return _level
+ end,
+
+ set_state = function(self, state)
+ _state = state
+ self:emit_signal("state", state)
+ end,
+ get_state = function()
+ return _state
+ end,
+ },
+ enable_properties = true,
+}
+
+local function icon_handler()
+ local icon_data = battery.state == "charging" and { "charging", "green" }
+ or qmath.step_value(battery.level, {
+ { 0, { "empty", "red" } },
+ { 20, { "low", "red" } },
+ { 40, { "medium", "yellow" } },
+ { 60, { "high", "green" } },
+ { 80, { "full", "green" } },
+ { 100 },
+ })
+
+ battery:emit_signal("icon", phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
+end
+
+local function level_handler()
+ battery.level = qmath.percentage(inner.energy, inner.energy_full)
+end
+
+local function state_handler()
+ battery.state = UPower.Device.state_to_string(inner.state)
+end
+
+function inner.on_notify.state()
+ state_handler()
+ icon_handler()
+end
+
+function inner.on_notify.energy()
+ level_handler()
+ icon_handler()
+end
+
+gtimer.delayed_call(function()
+ state_handler()
+ level_handler()
+ icon_handler()
+end)
+
+return battery
diff --git a/.config/awesome/services/common.lua b/.config/awesome/services/common.lua
index b23a064..ad1f998 100644
--- a/.config/awesome/services/common.lua
+++ b/.config/awesome/services/common.lua
@@ -1,52 +1,61 @@
local gfs = require "gears.filesystem"
local gtimer = require "gears.timer"
local phosphor = require "assets.phosphor"
-local qfs = require "quarrel.fs"
local qjson = require "quarrel.json"
local qmath = require "quarrel.math"
local qnative = require "quarrel.native"
local qstore = require "quarrel.store"
local qvars = require "quarrel.vars"
+local UPower = require("lgi").UPowerGlib
-local q = require "quarrel"
-
-local function register(name, service, icon)
+--- Register a service
+---@param name string
+---@param service Service
+local function register(name, service)
gtimer {
- timeout = 0.5,
+ timeout = 1,
call_now = true,
autostart = true,
callback = function()
- local service_result = table.pack(service())
+ local service_result = table.pack(service[1]())
awesome.emit_signal("services::" .. name, table.unpack(service_result))
- awesome.emit_signal("services::" .. name .. "::icon", icon(table.unpack(service_result)))
- end
+ awesome.emit_signal("services::" .. name .. "::icon", service[2](table.unpack(service_result)))
+ end,
}
end
+--- Read a file and automatically close it
+---@param file FileHandle
+---@param format ReadMode?
+---@return string | number
local function read(file, format)
local content = file:read(format or "a")
- file:seek("set")
+ file:rewind()
return content
end
-- create file in case it's not there yet
-if not gfs.file_readable("/tmp/wp_audio_status") then
+if not gfs.file_readable "/tmp/wp_audio_status" then
assert(io.open("/tmp/wp_audio_status", "w")):write("{}"):close()
end
-qstore.audio_file = assert(io.open("/tmp/wp_audio_status", "r"))
-qstore.battery_capacity_file = assert(io.open("/sys/class/power_supply/BAT0/capacity", "r"))
-qstore.battery_status_file = assert(io.open("/sys/class/power_supply/BAT0/status", "r"))
-qstore.brightness_file = assert(io.open("/sys/class/backlight/amdgpu_bl0/actual_brightness", "r"))
-qstore.wifi_file = assert(io.open("/proc/net/wireless", "r"))
+
+qstore.audio_file = qnative.util.open_file "/tmp/wp_audio_status"
+qstore.brightness_file = qnative.util.open_file "/sys/class/backlight/amdgpu_bl1/actual_brightness"
+qstore.wifi_file = qnative.util.open_file "/proc/net/wireless"
-- follows the format `service = { provider, icon_provider }`
+---@class Service
+---@field [1] fun(): ...
+---@field [2] fun(...): path: string, color: string
+
+---@type table<string, Service>
local services = {
audio = {
-- volume, muted
function()
local audio_status = qjson.decode(read(qstore.audio_file))
local default_sink = audio_status["G435 Wireless Gaming Headset Analog Stereo"]
-
+
if not default_sink then
return nil, false
end
@@ -63,29 +72,11 @@ local services = {
{ 25, "none" },
{ 50, "low" },
{ 75, "high" },
- { 100 }
+ { 100 },
})
return phosphor["speaker_simple_" .. icon_data .. "_fill"], qvars.colors.fg
- end
- },
- battery = {
- -- capacity, status
- function()
- return read(qstore.battery_capacity_file, "n"), read(qstore.battery_status_file, "l")
end,
- function(capacity, status)
- local icon_data = status == "Charging" and { "charging", "green" } or qmath.step_value(capacity, {
- { 0, { "empty", "red" } },
- { 20, { "low", "red" } },
- { 40, { "medium", "yellow" } },
- { 60, { "high", "green" } },
- { 80, { "full", "green" } },
- { 100 }
- })
-
- return phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]]
- end
},
brightness = {
-- brightness
@@ -99,29 +90,25 @@ local services = {
{ 102, "sun_horizon" },
{ 153, "sun_dim" },
{ 204, "sun" },
- { 255 }
+ { 255 },
})
return phosphor[icon_data .. "_fill"], qvars.colors.fg
- end
+ end,
},
wifi = {
-- essid, strength, connected
function()
- local lines = {}
-
- for line in qstore.wifi_file:lines() do
- table.insert(lines, line)
- end
- qstore.wifi_file:seek("set")
+ local lines = qstore.wifi_file:lines()
+ qstore.wifi_file:rewind()
- if not lines[3] then
+ if not lines[3] then
return nil, 0, false
end
- local strength = lines[3]:match("^%s*(.*)"):match("^.-%s+.-%s+.-(%S+)%.")
+ local strength = lines[3]:match("^%s*(.*)"):match "^.-%s+.-%s+.-(%S+)%."
- return qnative.get_essid(), math.floor(tonumber(strength) * 10 / 7), true
+ return qnative.net.get_essid(), math.floor(tonumber(strength) * 10 / 7), true
end,
function(_, strength, connected)
if not connected then
@@ -133,14 +120,14 @@ local services = {
{ 25, { "low", "yellow" } },
{ 50, { "medium", "yellow" } },
{ 75, { "high", "green" } },
- { 100 }
+ { 100 },
})
return phosphor["wifi_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]]
- end
- }
+ end,
+ },
}
for name, service in pairs(services) do
- register(name, service[1], service[2])
+ register(name, service)
end
diff --git a/.config/awesome/services/init.lua b/.config/awesome/services/init.lua
index 4ac624f..dc081ff 100644
--- a/.config/awesome/services/init.lua
+++ b/.config/awesome/services/init.lua
@@ -1,2 +1,3 @@
require "services.common"
require "services.playerctl"
+require "services.battery"
diff --git a/.config/awesome/services/osd.lua b/.config/awesome/services/osd.lua
new file mode 100644
index 0000000..c4fa3e7
--- /dev/null
+++ b/.config/awesome/services/osd.lua
@@ -0,0 +1,7 @@
+local battery = require "services.battery"
+local osd = require "ui.osd"
+local phosphor = require "assets.phosphor"
+
+-- battery:connect_signal("icon", function (self, icon, _)
+-- osd.notify(icon, self.level, 100)
+-- end)
diff --git a/.config/awesome/services/playerctl.lua b/.config/awesome/services/playerctl.lua
index 3fb0a3d..f6ee71a 100644
--- a/.config/awesome/services/playerctl.lua
+++ b/.config/awesome/services/playerctl.lua
@@ -1,5 +1,5 @@
-local playerctl = require "lib.bling.signal.playerctl".lib {
- player = { "spotify", "%any" }
+local playerctl = require("lib.bling.signal.playerctl").lib {
+ player = { "spotify", "%any" },
}
playerctl:connect_signal("metadata", function(_, ...)
@@ -39,7 +39,7 @@ playerctl:connect_signal("exit", function(_, ...)
end)
playerctl:connect_signal("no_players", function()
- awesome.emit_signal("services::playerctl::no_players")
+ awesome.emit_signal "services::playerctl::no_players"
end)
return playerctl
diff --git a/.config/awesome/signals/awesome.lua b/.config/awesome/signals/awesome.lua
index 37b9bdb..4ed3d32 100644
--- a/.config/awesome/signals/awesome.lua
+++ b/.config/awesome/signals/awesome.lua
@@ -1,27 +1,31 @@
-- Taken from https://www.reddit.com/r/awesomewm/comments/syjolb/comment/hy0xy35/
-awesome.connect_signal('exit', function(reason_restart)
- if not reason_restart then return end
+awesome.connect_signal("exit", function(reason_restart)
+ if not reason_restart then
+ return
+ end
- local file = io.open('/tmp/awesomewm-last-selected-tags', 'w+')
+ local file = io.open("/tmp/awesomewm-last-selected-tags", "w+")
for s in screen do
- file:write(s.selected_tag.index, '\n')
+ file:write(s.selected_tag.index, "\n")
end
file:close()
end)
-awesome.connect_signal('startup', function()
- local file = io.open('/tmp/awesomewm-last-selected-tags', 'r')
- if not file then return end
+awesome.connect_signal("startup", function()
+ local file = io.open("/tmp/awesomewm-last-selected-tags", "r")
+ if not file then
+ return
+ end
local selected_tags = {}
for line in file:lines() do
table.insert(selected_tags, tonumber(line))
end
-
+
for s in screen do
local i = selected_tags[s.index]
local t = s.tags[i]
diff --git a/.config/awesome/signals/client.lua b/.config/awesome/signals/client.lua
index 31f3d9c..8788735 100644
--- a/.config/awesome/signals/client.lua
+++ b/.config/awesome/signals/client.lua
@@ -1,23 +1,15 @@
local qvars = require "quarrel.vars"
-local rectangle = require "gears.shape".rectangle
+local rectangle = require("gears.shape").rectangle
+local conductor = require "ui.conductor"
--- io.popen spams logs, don't use
--- client.connect_signal("property::name", function(c)
--- if not c.pid then return end
--- local out = io.popen("readlink /proc/" .. c.pid .. "/exe")
--- local name = c.name
--- if out ~= nil then
--- name = out:read("*a"):sub(0, -2):match("[^\\/]+$") or name
--- end
--- c.name = string.lower(name)
--- end)
-
-client.connect_signal("request::manage", function (c)
+client.connect_signal("request::manage", function(c)
c.shape = qvars.shape
if c.maximized then
c.maximized = false
c.maximized = true
end
+
+ -- conductor.update()
end)
local function handle_corners(c)
diff --git a/.config/awesome/signals/init.lua b/.config/awesome/signals/init.lua
index 5641a96..a18290e 100644
--- a/.config/awesome/signals/init.lua
+++ b/.config/awesome/signals/init.lua
@@ -2,4 +2,3 @@ require "signals.naughty"
require "signals.awesome"
require "signals.screen"
require "signals.client"
-
diff --git a/.config/awesome/signals/naughty.lua b/.config/awesome/signals/naughty.lua
index 90594c1..cc096e7 100644
--- a/.config/awesome/signals/naughty.lua
+++ b/.config/awesome/signals/naughty.lua
@@ -1,54 +1,254 @@
-local awful = require "awful"
-local beautiful = require "beautiful"
+local gdebug = require "gears.debug"
local naughty = require "naughty"
-local qvars = require "quarrel.vars"
-local wibox = require "wibox"
-
-naughty.connect_signal("request::display", function(n)
- naughty.layout.box {
- notification = n,
- placement = function(d)
- return awful.placement.right(d, {
- margins = beautiful.useless_gap * 2
- })
- end,
- widget_template = {
- widget = wibox.container.margin,
- margins = qvars.big_padding,
- {
- {
- widget = naughty.widget.icon,
- notification = n
- },
- {
- widget = wibox.container.place,
- valign = "center",
- halign = "center",
- {
- {
- widget = naughty.widget.title,
- notification = n
- },
- {
- widget = naughty.widget.message,
- notification = n
- },
- -- spacing = 4,
- layout = wibox.layout.fixed.vertical,
- }
- },
- fill_space = true,
- spacing = n.icon and qvars.big_padding or 0,
- layout = wibox.layout.fixed.horizontal
- }
- }
+local ndbus = require "naughty.dbus"
+local qdelegate = require "quarrel.delegate"
+local wicked = require "ui.wicked"
+
+---@diagnostic disable-next-line:redundant-parameter
+ndbus._notif_methods.Notify = qdelegate(function(env, sender, object_path, interface, method, parameters, invocation)
+ local appname, replaces_id, app_icon, title, text, actions, hints, expire = env.unpack(parameters.value)
+
+ local args = {}
+ if text ~= "" then
+ args.message = text
+ if title ~= "" then
+ args.title = title
+ end
+ else
+ if title ~= "" then
+ args.message = title
+ else
+ -- FIXME: We have to reply *something* to the DBus invocation.
+ -- Right now this leads to a memory leak, I think.
+ return
+ end
+ end
+
+ if appname ~= "" then
+ args.appname = appname --TODO v6 Remove this.
+ args.app_name = appname
+ end
+
+ local preset = args.preset or env.cst.config.defaults
+ local notification
+ if actions then
+ args.actions = {}
+
+ for i = 1, #actions, 2 do
+ local action_id = actions[i]
+ local action_text = actions[i + 1]
+
+ if action_id == "default" then
+ args.run = function()
+ env.sendActionInvoked(notification.id, "default")
+ notification:destroy(env.cst.notification_closed_reason.dismissed_by_user)
+ end
+ elseif action_id ~= nil and action_text ~= nil then
+ local a = env.naction {
+ name = action_text,
+ id = action_id,
+ position = (i - 1) / 2 + 1,
+ }
+
+ -- Right now `gears` doesn't have a great icon implementation
+ -- and `naughty` doesn't depend on `menubar`, so delegate the
+ -- icon "somewhere" using a request.
+ if hints["action-icons"] and action_id ~= "" then
+ naughty.emit_signal("request::action_icon", a, "dbus", { id = action_id })
+ end
+
+ a:connect_signal("invoked", function()
+ env.sendActionInvoked(notification.id, action_id)
+
+ if not notification.resident then
+ notification:destroy(env.cst.notification_closed_reason.dismissed_by_user)
+ end
+ end)
+
+ table.insert(args.actions, a)
+ end
+ end
+ end
+ args.destroy = function(reason)
+ env.sendNotificationClosed(notification.id, reason)
+ end
+ local legacy_data = { -- This data used to be generated by AwesomeWM's C code
+ type = "method_call",
+ interface = interface,
+ path = object_path,
+ member = method,
+ sender = sender,
+ bus = "session",
}
-end)
+ if
+ not preset.callback
+ or (
+ type(preset.callback) == "function"
+ and preset.callback(legacy_data, appname, replaces_id, app_icon, title, text, actions, hints, expire)
+ )
+ then
+ if app_icon ~= "" then
+ args.app_icon = app_icon
+ end
+
+ if hints.icon_data or hints.image_data or hints["image-data"] then
+ -- Icon data is a bit complex and hence needs special care:
+ -- .value breaks with the array of bytes (ay) that we get here.
+ -- So, bypass it and look up the needed value differently
+ local icon_condidates = {}
+ for k, v in parameters:get_child_value(7 - 1):pairs() do
+ if k == "image-data" then
+ icon_condidates[1] = v -- not deprecated
+ break
+ elseif k == "image_data" then -- deprecated
+ icon_condidates[2] = v
+ elseif k == "icon_data" then -- deprecated
+ icon_condidates[3] = v
+ end
+ end
+
+ -- The order is mandated by the spec.
+ local icon_data = icon_condidates[1] or icon_condidates[2] or icon_condidates[3]
+
+ -- icon_data is an array:
+ -- 1 -> width
+ -- 2 -> height
+ -- 3 -> rowstride
+ -- 4 -> has alpha
+ -- 5 -> bits per sample
+ -- 6 -> channels
+ -- 7 -> data
+
+ -- Get the value as a GVariant and then use LGI's special
+ -- GVariant.data to get that as an LGI byte buffer. That one can
+ -- then by converted to a string via its __tostring metamethod.
+ local data = tostring(icon_data:get_child_value(7 - 1).data)
+ args.image = env.convert_icon(icon_data[1], icon_data[2], icon_data[3], icon_data[6], data)
+
+ -- Convert all animation frames.
+ if naughty.image_animations_enabled then
+ args.images = { args.image }
+
+ if #icon_data > 7 then
+ for frame = 8, #icon_data do
+ data = tostring(icon_data:get_child_value(frame - 1).data)
+
+ table.insert(
+ args.images,
+ env.convert_icon(icon_data[1], icon_data[2], icon_data[3], icon_data[6], data)
+ )
+ end
+ end
+ end
+ end
+
+ -- Alternate ways to set the icon. The specs recommends to allow both
+ -- the icon and image to co-exist since they serve different purpose.
+ -- However in case the icon isn't specified, use the image.
+ args.image = args.image
+ or hints["image-path"] -- not deprecated
+ or hints["image_path"] -- deprecated
+
+ if naughty.image_animations_enabled then
+ args.images = args.images or {}
+ end
+
+ if replaces_id and replaces_id ~= "" and replaces_id ~= 0 then
+ args.replaces_id = replaces_id
+ end
+ if expire and expire > -1 then
+ args.timeout = expire / 1000
+ end
+
+ args.freedesktop_hints = hints
+
+ -- Not very pretty, but given the current format is documented in the
+ -- public API... well, whatever...
+ if hints and hints.urgency then
+ for name, key in pairs(env.urgency) do
+ local b = string.char(hints.urgency)
+ if key == b then
+ args.urgency = name
+ end
+ end
+ end
+
+ args.urgency = args.urgency or "normal"
+
+ -- Try to update existing objects when possible
+ notification = naughty.get_by_id(replaces_id)
+
+ if notification then
+ if not notification._private._unique_sender then
+ -- If this happens, the notification is either trying to
+ -- highjack content created within AwesomeWM or it is garbage
+ -- to begin with.
+ gdebug.print_warning(
+ "A notification has been received, but tried to update "
+ .. "the content of a notification it does not own."
+ )
+ elseif notification._private._unique_sender ~= sender then
+ -- Nothing says you cannot and some scripts may do it
+ -- accidentally, but this is rather unexpected.
+ gdebug.print_warning(
+ "Notification "
+ .. notification.title
+ .. " is being updated"
+ .. "by a different DBus connection ("
+ .. sender
+ .. "), this is "
+ .. "suspicious. The original connection was "
+ .. notification._private._unique_sender
+ )
+ end
+
+ for k, v in pairs(args) do
+ if k == "destroy" then
+ k = "destroy_cb"
+ end
+ notification[k] = v
+ end
+
+ -- Update the icon if necessary.
+ if app_icon ~= notification._private.app_icon then
+ notification._private.app_icon = app_icon
+
+ naughty._emit_signal_if("request::icon", function()
+ if notification._private.icon then
+ return true
+ end
+ end, notification, "dbus_clear", {})
+ end
+
+ -- Even if no property changed, restart the timeout.
+ notification:reset_timeout()
+ else
+ -- Only set the sender for new notifications.
+ args._unique_sender = sender
+ args._foreign = true
+
+ notification = env.nnotif(args)
+
+ notification:connect_signal("destroyed", function(_, r)
+ args.destroy(r)
+ end)
+ end
+
+ invocation:return_value(env.GLib.Variant("(u)", { notification.id }))
+ return
+ end
+
+ invocation:return_value(env.GLib.Variant("(u)", { env.nnotif._gen_next_id() }))
+end, ndbus._notif_methods.Notify)
+
+naughty.connect_signal("request::display", wicked)
naughty.connect_signal("request::display_error", function(message, startup)
naughty.notification {
urgency = "critical",
- title = "Oops, an error happened"..(startup and " during startup!" or "!"),
- message = message
+ title = "Oops, an error happened" .. (startup and " during startup!" or "!"),
+ message = message,
}
+
+ gdebug.print_error("[Error" .. (startup and "during startup" or "") .. "]: " .. message)
end)
diff --git a/.config/awesome/signals/screen.lua b/.config/awesome/signals/screen.lua
index 706bf56..57f4f98 100644
--- a/.config/awesome/signals/screen.lua
+++ b/.config/awesome/signals/screen.lua
@@ -4,8 +4,11 @@ local gtable = require "gears.table"
screen.connect_signal("request::desktop_decoration", function(s)
for i, tag in ipairs(cfg.tags) do
- awful.tag.add(tostring(i), gtable.crush({
- screen = s
- }, tag))
+ awful.tag.add(
+ tostring(i),
+ gtable.crush({
+ screen = s,
+ }, tag)
+ )
end
end)
diff --git a/.config/awesome/stylua.toml b/.config/awesome/stylua.toml
new file mode 100644
index 0000000..5cc0b69
--- /dev/null
+++ b/.config/awesome/stylua.toml
@@ -0,0 +1,5 @@
+call_parentheses = "None"
+indent_type = "Spaces"
+
+[sort_requires]
+enabled = true
diff --git a/.config/awesome/ui/conductor/init.lua b/.config/awesome/ui/conductor/init.lua
index b5ac82b..e6fe552 100644
--- a/.config/awesome/ui/conductor/init.lua
+++ b/.config/awesome/ui/conductor/init.lua
@@ -3,24 +3,6 @@ local q = require "quarrel"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
-awful.keygrabber {
- keybindings = {
- awful.key {
- modifiers = qvars.mods.A,
- key = "Tab",
- on_press = awful.client.focus.history.previous
- },
- awful.key {
- modifiers = qvars.mods.AS,
- key = "Tab",
- on_press = awful.client.focus.history.next
- },
- },
- -- Note that it is using the key name and not the modifier name.
- stop_key = "Mod1",
- stop_event = "release",
- -- start_callback = awful.client.focus.history.disable_tracking,
- stop_callback = awful.client.focus.history.enable_tracking,
- export_keybindings = true,
- autostart = true
-}
+local conductor = {}
+
+return conductor
diff --git a/.config/awesome/ui/decorations/mpd.lua b/.config/awesome/ui/decorations/mpd.lua
new file mode 100644
index 0000000..a03b579
--- /dev/null
+++ b/.config/awesome/ui/decorations/mpd.lua
@@ -0,0 +1,13 @@
+local mpd = {}
+
+function mpd.left() end
+
+function mpd.bottom() end
+
+function mpd.setup(c) end
+
+function mpd:next() end
+
+function mpd:previous() end
+
+function mpd:stop() end
diff --git a/.config/awesome/ui/decorations/wallpaper.lua b/.config/awesome/ui/decorations/wallpaper.lua
index dbe54ee..3a204c2 100644
--- a/.config/awesome/ui/decorations/wallpaper.lua
+++ b/.config/awesome/ui/decorations/wallpaper.lua
@@ -1,4 +1,4 @@
--- local gfs = require "gears.filesystem"
+local qmarkup = require "quarrel.markup"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wallpaper = require "awful.wallpaper"
@@ -16,24 +16,14 @@ screen.connect_signal("request::wallpaper", function(s)
widget = wibox.widget.textbox,
font = qui.font(1.5),
markup = table.concat({
- qui.markup_fg(qvars.colors.red, " ___"),
- qui.markup_fg(qvars.colors.green, " /\\ \\"),
- qui.markup_fg(qvars.colors.yellow, " /::\\ \\"),
- qui.markup_fg(qvars.colors.blue, "/::\\:\\__\\"),
- qui.markup_fg(qvars.colors.pink, "\\/\\::/ /"),
- qui.markup_fg(qvars.colors.cyan, " \\/__/")
- }, "\n")
- }
- -- {
- -- -- image = gfs.get_configuration_dir() .. "assets/nightmare_fuel.png",
- -- image = "/home/delta/Desktop/offline vs online.jpg",
- -- resize = true,
- -- widget = wibox.widget.imagebox,
- -- },
- -- valign = "center",
- -- halign = "center",
- -- tiled = false,
- -- widget = wibox.container.tile,
- }
+ qmarkup(" ___", { fg = qvars.colors.red }),
+ qmarkup(" /\\ \\", { fg = qvars.colors.green }),
+ qmarkup(" /::\\ \\", { fg = qvars.colors.yellow }),
+ qmarkup("/::\\:\\__\\", { fg = qvars.colors.blue }),
+ qmarkup("\\/\\::/ /", { fg = qvars.colors.pink }),
+ qmarkup(" \\/__/", { fg = qvars.colors.cyan }),
+ }, "\n"),
+ },
+ },
}
end)
diff --git a/.config/awesome/ui/fresnel/init.lua b/.config/awesome/ui/fresnel/init.lua
index f31da12..9905741 100644
--- a/.config/awesome/ui/fresnel/init.lua
+++ b/.config/awesome/ui/fresnel/init.lua
@@ -49,10 +49,10 @@ function fresnel:_update(query, scrolled)
self._entries_exec = {}
layout:reset()
-
+
for _, provider in qtable.opairs(qnative.lenses) do
local entries = provider(query)
-
+
table.sort(entries, function(a, b)
return a.message < b.message
end)
@@ -63,72 +63,76 @@ function fresnel:_update(query, scrolled)
self._entries_count = #all_providers
for i, entry in ipairs(all_providers) do
- if i <= self._entries_offset then
- goto continue
- end
- if entries_count == max_entries then break end
- table.insert(self._entries_exec, entry.exec)
+ if i > self._entries_offset then
+ if entries_count == max_entries then
+ break
+ end
+ table.insert(self._entries_exec, entry.exec)
- local entry_widget = wibox.widget {
- widget = wibox.container.background,
- shape = qvars.shape,
- {
- widget = wibox.container.margin,
- margins = qvars.padding,
+ local entry_widget = wibox.widget {
+ widget = wibox.container.background,
+ shape = qvars.shape,
{
- widget = wibox.container.constraint,
- strategy = "max",
- height = qvars.char_height,
+ widget = wibox.container.margin,
+ margins = qvars.padding,
{
+ widget = wibox.container.constraint,
+ strategy = "max",
+ height = qvars.char_height,
{
- widget = wibox.container.background,
- fg = qvars.colors.dim.fg,
+ {
+ widget = wibox.container.background,
+ fg = qvars.colors.dim.fg,
+ {
+ widget = wibox.widget.textbox,
+ text = entry.provider .. " | ",
+ },
+ },
{
widget = wibox.widget.textbox,
- text = entry.provider .. " | "
- }
+ text = entry.message,
+ },
+ spacing = qvars.padding,
+ layout = wibox.layout.fixed.horizontal,
},
- {
- widget = wibox.widget.textbox,
- text = entry.message
- },
- spacing = qvars.padding,
- layout = wibox.layout.fixed.horizontal
- }
- }
- },
- buttons = {
- awful.button {
- modifiers = {},
- button = btn.LEFT,
- on_press = function()
- self:_exec_entry(i)
- end
- }
- },
- _selected = false
- }
+ },
+ },
+ buttons = {
+ awful.button {
+ modifiers = {},
+ button = btn.LEFT,
+ on_press = function()
+ self:_exec_entry(i)
+ end,
+ },
+ },
+ _selected = false,
+ }
- if self._selected_index + self._entries_offset == i then
- entry_widget._selected = true
- entry_widget.bg = qvars.colors.black
- end
+ if self._selected_index + self._entries_offset == i then
+ entry_widget._selected = true
+ entry_widget.bg = qvars.colors.black
+ end
- entry_widget:connect_signal("mouse::enter", function()
- if entry_widget._selected == true then return end
- entry_widget.bg = qvars.colors.black
- end)
+ entry_widget:connect_signal("mouse::enter", function()
+ if entry_widget._selected == true then
+ return
+ end
+ entry_widget.bg = qvars.colors.black
+ end)
- entry_widget:connect_signal("mouse::leave", function()
- if entry_widget._selected == true then return end
- entry_widget.bg = qvars.colors.bg
- end)
+ entry_widget:connect_signal("mouse::leave", function()
+ if entry_widget._selected == true then
+ return
+ end
+ entry_widget.bg = qvars.colors.bg
+ end)
- layout:add(entry_widget)
+ layout:add(entry_widget)
- entries_count = entries_count + 1
- self._visible_entries = entries_count
- ::continue::
+ entries_count = entries_count + 1
+ self._visible_entries = entries_count
+ end
end
status.text = self._entries_offset + self._selected_index .. "/" .. self._entries_count
@@ -141,8 +145,12 @@ fresnel._prompt = al_prompt {
ul_cursor = "low",
bg_cursor = qvars.colors.black,
changed_callback = function(text)
- if fresnel._text == text then return end
- if fresnel._toggled == false then return end
+ if fresnel._text == text then
+ return
+ end
+ if fresnel._toggled == false then
+ return
+ end
fresnel:_update(text)
fresnel._text = text
end,
@@ -154,7 +162,7 @@ fresnel._prompt = al_prompt {
fresnel:hide()
elseif key == "Up" then
local next_index = fresnel._selected_index - 1
- if next_index < 1 and fresnel._entries_offset == 0 then
+ if next_index < 1 and fresnel._entries_offset == 0 then
return
elseif next_index < 1 and fresnel._entries_offset > 0 then
fresnel._entries_offset = fresnel._entries_offset - 1
@@ -165,9 +173,15 @@ fresnel._prompt = al_prompt {
fresnel:_update(fresnel._text, true)
elseif key == "Down" then
local next_index = fresnel._selected_index + 1
- if next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries == fresnel._entries_count then
+ if
+ next_index > fresnel._visible_entries
+ and fresnel._entries_offset + fresnel._visible_entries == fresnel._entries_count
+ then
return
- elseif next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries < fresnel._entries_count then
+ elseif
+ next_index > fresnel._visible_entries
+ and fresnel._entries_offset + fresnel._visible_entries < fresnel._entries_count
+ then
fresnel._entries_offset = fresnel._entries_offset + 1
else
fresnel._selected_index = next_index
@@ -175,7 +189,7 @@ fresnel._prompt = al_prompt {
fresnel:_update(fresnel._text, true)
end
- end
+ end,
}
fresnel._widget = qui.popup {
@@ -184,12 +198,12 @@ fresnel._widget = qui.popup {
placement = function(d)
awful.placement.top(d, {
margins = {
- top = beautiful.useless_gap * 2
- }
+ top = beautiful.useless_gap * 2,
+ },
})
end,
- minimum_width = screen[1].geometry.width / 2,
- maximum_width = screen[1].geometry.width / 2,
+ minimum_width = awful.screen.focused().geometry.width / 2,
+ maximum_width = awful.screen.focused().geometry.width / 2,
widget = {
{
widget = wibox.container.background,
@@ -202,13 +216,13 @@ fresnel._widget = qui.popup {
{
{
widget = wibox.widget.textbox,
- text = ">"
+ text = ">",
},
{
widget = wibox.container.margin,
margins = {
left = qvars.padding,
- right = qvars.padding
+ right = qvars.padding,
},
{
widget = wibox.container.constraint,
@@ -217,34 +231,37 @@ fresnel._widget = qui.popup {
{
widget = wibox.container.background,
fg = qvars.colors.fg,
- fresnel._prompt.textbox
- }
- }
+ fresnel._prompt.textbox,
+ },
+ },
},
{
widget = wibox.widget.textbox,
text = "0/0",
- id = "status"
+ id = "status",
},
- layout = wibox.layout.align.horizontal
- }
- }
+ layout = wibox.layout.align.horizontal,
+ },
+ },
},
{
widget = wibox.container.margin,
margins = {
- top = qvars.padding
+ top = qvars.padding,
},
{
spacing = qvars.padding,
layout = wibox.layout.fixed.vertical,
- id = "entry_layout"
- }
+ id = "entry_layout",
+ },
},
- layout = wibox.layout.align.vertical
- }
+ layout = wibox.layout.align.vertical,
+ },
}
-fresnel._widget.maximum_height = qvars.big_padding * 2 + (qvars.padding * 2 + qvars.char_height) * (1 + 10) + qvars.padding + qvars.padding * 9
+fresnel._widget.maximum_height = qvars.big_padding * 2
+ + (qvars.padding * 2 + qvars.char_height) * (1 + 10)
+ + qvars.padding
+ + qvars.padding * 9
function fresnel:show()
self._toggled = true
@@ -271,7 +288,7 @@ fresnel._timed = rubato.timed {
else
fresnel._widget.visible = true
end
- end
+ end,
}
return fresnel
diff --git a/.config/awesome/ui/init.lua b/.config/awesome/ui/init.lua
index e41644f..dd93ad1 100644
--- a/.config/awesome/ui/init.lua
+++ b/.config/awesome/ui/init.lua
@@ -1,2 +1,4 @@
require "ui.statusbar"
require "ui.decorations"
+require "ui.conductor"
+require "ui.osd"
diff --git a/.config/awesome/ui/insightful/init.lua b/.config/awesome/ui/insightful/init.lua
index e8a4a4d..3dcbbea 100644
--- a/.config/awesome/ui/insightful/init.lua
+++ b/.config/awesome/ui/insightful/init.lua
@@ -64,7 +64,7 @@ insightful._keymap = {
XF86AudioStop = "⏹",
[tostring(btn.LEFT)] = mouse .. "Left",
[tostring(btn.MIDDLE)] = mouse .. "Middle",
- [tostring(btn.RIGHT)] = mouse .. "Right"
+ [tostring(btn.RIGHT)] = mouse .. "Right",
}
insightful._widget = qui.popup {
@@ -73,17 +73,17 @@ insightful._widget = qui.popup {
placement = function(d)
awful.placement.top(d, {
margins = {
- top = beautiful.useless_gap * 2
- }
+ top = beautiful.useless_gap * 2,
+ },
})
end,
- minimum_height = screen[1].geometry.height / 2,
- minimum_width = screen[1].geometry.width / 2,
+ minimum_height = awful.screen.focused().geometry.height / 2,
+ minimum_width = awful.screen.focused().geometry.width / 2,
widget = {
layout = wibox.layout.fixed.vertical,
spacing = qvars.big_padding,
- id = "layout_container"
- }
+ id = "layout_container",
+ },
}
function insightful:_generate()
@@ -98,55 +98,59 @@ function insightful:_generate()
grouped_binds[group] = {}
end
- table.insert(grouped_binds[group], {
+ table.insert(grouped_binds[group], {
mods = keybind.mods,
triggers = keybind.triggers,
- desc = keybind.desc
+ desc = keybind.desc,
})
end
for group, keybinds in qtable.opairs(grouped_binds) do
local group_layout = {
spacing = qvars.padding,
- layout = wibox.layout.fixed.vertical
+ layout = wibox.layout.fixed.vertical,
}
for _, keybind in ipairs(keybinds) do
local key_layout = {
- layout = wibox.layout.fixed.horizontal
+ layout = wibox.layout.fixed.horizontal,
}
local key_and_desc_layout = {
nil, -- key
nil,
nil, -- description?
- layout = wibox.layout.align.horizontal
+ layout = wibox.layout.align.horizontal,
}
-
+
for _, mod in ipairs(keybind.mods) do
- table.insert(key_layout, 1, qui.styled {
- widget = wibox.container.background,
- bg = qvars.colors.bright.black,
- border_width = 0,
- {
- widget = wibox.container.margin,
- margins = qvars.padding,
+ table.insert(
+ key_layout,
+ 1,
+ qui.styled {
+ widget = wibox.container.background,
+ bg = qvars.colors.bright.black,
+ border_width = 0,
{
- widget = wibox.widget.textbox,
- text = insightful._keymap[mod] or mod
- }
+ widget = wibox.container.margin,
+ margins = qvars.padding,
+ {
+ widget = wibox.widget.textbox,
+ text = insightful._keymap[mod] or mod,
+ },
+ },
}
- })
+ )
table.insert(key_layout, 2, {
widget = wibox.widget.textbox,
- text = " + "
+ text = " + ",
})
end
if type(keybind.triggers) == "string" or type(keybind.triggers) == "number" then
table.insert(key_layout, {
widget = wibox.widget.textbox,
- text = insightful._keymap[tostring(keybind.triggers)] or keybind.triggers
+ text = insightful._keymap[tostring(keybind.triggers)] or keybind.triggers,
})
elseif type(keybind.triggers) == "table" then
local display_trigger = {}
@@ -155,7 +159,7 @@ function insightful:_generate()
end
table.insert(key_layout, {
widget = wibox.widget.textbox,
- text = table.concat(display_trigger, "/")
+ text = table.concat(display_trigger, "/"),
})
end
@@ -165,16 +169,16 @@ function insightful:_generate()
fg = qvars.colors.dim.fg,
{
widget = wibox.widget.textbox,
- text = keybind.desc
- }
+ text = keybind.desc,
+ },
}
end
key_and_desc_layout[1] = key_layout
table.insert(group_layout, key_and_desc_layout)
- end
-
+ end
+
layout_container:add {
{
{
@@ -187,16 +191,16 @@ function insightful:_generate()
margins = qvars.padding,
{
widget = wibox.widget.textbox,
- text = group
- }
- }
+ text = group,
+ },
+ },
},
nil,
- layout = wibox.layout.align.horizontal
+ layout = wibox.layout.align.horizontal,
},
group_layout,
spacing = qvars.padding,
- layout = wibox.layout.fixed.vertical
+ layout = wibox.layout.fixed.vertical,
}
end
end
@@ -213,11 +217,11 @@ local timed = rubato.timed {
else
insightful._widget.visible = true
end
- end
+ end,
}
function insightful:toggle()
- if first_time then
+ if first_time then
insightful:_generate()
first_time = false
end
diff --git a/.config/awesome/ui/osd.lua b/.config/awesome/ui/osd.lua
new file mode 100644
index 0000000..fc74ed9
--- /dev/null
+++ b/.config/awesome/ui/osd.lua
@@ -0,0 +1,102 @@
+--- Heavy inspiration from a design made by https://github.com/tsukki9696
+
+local awful = require "awful"
+local beautiful = require "beautiful"
+local gtimer = require "gears.timer"
+local phosphor = require "assets.phosphor"
+local qmath = require "quarrel.math"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local rubato = require "lib.rubato"
+local wibox = require "wibox"
+
+local osd = {}
+
+local widget = qui.popup {
+ ontop = true,
+ visible = false,
+ placement = function(d)
+ awful.placement.top(d, {
+ margins = {
+ top = beautiful.useless_gap * 2,
+ },
+ })
+ end,
+ minimum_height = qvars.char_height * 2,
+ -- minimum_width = awful.screen.focused().geometry.width / 2,
+ widget = {
+ {
+ widget = wibox.container.place,
+
+ qui.icon {
+ icon = phosphor.speaker_simple_none_fill,
+ widget = {
+ forced_height = qvars.char_height * 1.2,
+ forced_width = qvars.char_height * 1.2,
+ id = "icon",
+ },
+ },
+ },
+ {
+ widget = wibox.container.place,
+ {
+ widget = wibox.widget.progressbar,
+ max_value = 100,
+ value = 20,
+ forced_height = qvars.char_height / 1.5,
+ forced_width = qvars.expanded_bar_size
+ - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2)
+ - (qvars.char_height / 1.25 + qvars.padding) * 3,
+ color = qvars.colors.yellow,
+ background_color = qvars.colors.black,
+ shape = qvars.shape,
+ id = "progress",
+ },
+ },
+
+ {
+ widget = wibox.widget.textbox,
+ text = "20%",
+ font = qui.font(1.2),
+ id = "percentage",
+ },
+ layout = wibox.layout.fixed.horizontal,
+ spacing = qvars.big_padding,
+ },
+}
+
+local timer
+
+local anim = rubato.timed {
+ duration = qvars.anim_duration,
+ intro = qvars.anim_intro,
+ pos = 0,
+ subscribed = function(pos)
+ widget.opacity = pos
+ if pos == 0 then
+ widget.visible = false
+ elseif not widget.visible then
+ widget.visible = true
+ elseif pos == 1 then
+ timer:start()
+ end
+ end,
+}
+
+timer = gtimer {
+ timeout = 1,
+ callback = function()
+ anim.target = 0
+ end,
+ single_shot = true,
+}
+
+function osd.notify(icon, value, max)
+ anim.target = 1
+ widget:get_children_by_id("icon")[1].image = icon
+ widget:get_children_by_id("progress")[1].value = value
+ widget:get_children_by_id("progress")[1].max_value = max
+ widget:get_children_by_id("percentage")[1].text = tostring(qmath.percentage(value, max)) .. "%"
+end
+
+return osd
diff --git a/.config/awesome/ui/powermenu/init.lua b/.config/awesome/ui/powermenu/init.lua
new file mode 100644
index 0000000..81d2ea3
--- /dev/null
+++ b/.config/awesome/ui/powermenu/init.lua
@@ -0,0 +1,114 @@
+local awful = require "awful"
+local phosphor = require "assets.phosphor"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local rubato = require "lib.rubato"
+local wibox = require "wibox"
+
+local function create_button(title, icon, color, exec)
+ return wibox.widget {
+ widget = wibox.container.background,
+ shape = qvars.shape,
+ {
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ {
+ qui.styled {
+ widget = wibox.container.background,
+ border_color = color,
+ {
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ qui.icon {
+ widget = {
+ forced_height = qvars.char_height * 4 - qvars.big_padding * 2,
+ forced_width = qvars.char_height * 4 - qvars.big_padding * 2,
+ },
+ icon = icon,
+ color = color,
+ },
+ },
+ },
+ {
+ widget = wibox.container.place,
+ {
+ widget = wibox.widget.textbox,
+ text = title,
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ spacing = qvars.big_padding,
+ exec = exec,
+ },
+ },
+ select = function(self)
+ self.bg = qvars.colors.black
+ end,
+ }
+end
+
+local powermenu = {}
+local toggled = false
+
+screen.connect_signal("request::desktop_decoration", function(s)
+ powermenu._widget = qui.popup {
+ ontop = true,
+ visible = false,
+ minimum_width = s.geometry.width,
+ minimum_height = s.geometry.height,
+ bg = qvars.colors.bg .. "ee",
+ border_width = 0,
+ widget = {
+ widget = wibox.container.place,
+ qui.styled {
+ widget = wibox.container.background,
+ {
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ {
+ layout = wibox.layout.fixed.horizontal,
+ spacing = qvars.big_padding * 2,
+ id = "list",
+ },
+ },
+ },
+ },
+ }
+
+ local layout = powermenu._widget.widget:get_children_by_id("list")[1]
+
+ layout:add(create_button("Shutdown", phosphor.power_bold, qvars.colors.red, function()
+ awful.spawn "poweroff"
+ end))
+ layout:add(create_button("Log out", phosphor.sign_out_bold, qvars.colors.green, function()
+ awesome.quit()
+ end))
+ layout:add(create_button("Lock", phosphor.lock_simple_fill, qvars.colors.blue, function()
+ require("quarrel").debug "locked!l"
+ end))
+ layout:add(create_button("Restart", phosphor.arrow_clockwise_bold, qvars.colors.pink, function()
+ awful.spawn "reboot"
+ end))
+end)
+
+local timed = rubato.timed {
+ duration = qvars.anim_duration,
+ intro = qvars.anim_intro,
+ pos = 0,
+ subscribed = function(pos)
+ powermenu._widget.opacity = pos
+
+ if pos == 0 then
+ powermenu._widget.visible = false
+ else
+ powermenu._widget.visible = true
+ end
+ end,
+}
+
+function powermenu:toggle()
+ timed.target = toggled and 0 or 1
+ toggled = not toggled
+end
+
+return powermenu
diff --git a/.config/awesome/ui/statusbar/init.lua b/.config/awesome/ui/statusbar/init.lua
index d4f2001..77a28f7 100644
--- a/.config/awesome/ui/statusbar/init.lua
+++ b/.config/awesome/ui/statusbar/init.lua
@@ -1,9 +1,8 @@
local awful = require "awful"
local beautiful = require "beautiful"
-local gcolor = require "gears.color"
local panel = require "ui.statusbar.panel"
local phosphor = require "assets.phosphor"
-local qbind = require "quarrel.bind"
+local qstore = require "quarrel.store"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local rubato = require "lib.rubato"
@@ -13,38 +12,26 @@ local clock = require "ui.statusbar.widgets.clock"
local displays = require "ui.statusbar.widgets.displays"
local keyboardlayout = require "ui.statusbar.widgets.keyboardlayout"
local taglist = require "ui.statusbar.widgets.taglist"
+local tasklist = require "ui.statusbar.widgets.tasklist"
screen.connect_signal("request::desktop_decoration", function(s)
- local expand_button = wibox.widget {
- widget = wibox.container.place,
- valign = "center",
- halign = "center",
- {
- widget = wibox.widget.imagebox,
- image = gcolor.recolor_image(phosphor.caret_right_fill, qvars.colors.fg),
- forced_width = qvars.char_height,
- forced_height = qvars.char_height
- },
- _expanded = false
- }
-
local bar = qui.popup {
placement = function(d)
- local place = awful.placement.left
- return place(d, {
- margins = beautiful.useless_gap * 2
+ return awful.placement.left(d, {
+ margins = beautiful.useless_gap * 2,
})
end,
minimum_height = s.geometry.height - (beautiful.useless_gap * 4 + qvars.border_width * 2),
widget = {
{
{
- expand_button,
- taglist,
+ taglist(s),
layout = wibox.layout.fixed.vertical,
spacing = qvars.padding * 2,
+ id = "top",
},
nil,
+ -- tasklist(s),
{
widget = wibox.container.place,
valign = "bottom",
@@ -55,11 +42,16 @@ screen.connect_signal("request::desktop_decoration", function(s)
displays.wifi,
{
widget = wibox.container.place,
- keyboardlayout
+ {
+ widget = wibox.container.constraint,
+ height = qvars.char_height,
+ width = qvars.char_height,
+ keyboardlayout,
+ },
},
clock,
layout = wibox.layout.fixed.vertical,
- spacing = qvars.padding * 2
+ spacing = qvars.padding * 2,
},
},
layout = wibox.layout.align.vertical,
@@ -74,23 +66,24 @@ screen.connect_signal("request::desktop_decoration", function(s)
local bar_width = bar.width + qvars.border_width * 2
bar:struts {
- left = bar_width + beautiful.useless_gap * 4
+ left = bar_width + beautiful.useless_gap * 4,
}
local panel_width
+ local panel_toggle = { toggled = false } -- hacky but it works
local timed = rubato.timed {
duration = qvars.anim_duration,
intro = qvars.anim_intro,
pos = bar_width,
subscribed = function(pos)
- if pos ~= bar_width and expand_button._expanded then
+ if pos ~= bar_width and panel_toggle.toggled then
bar.widget.widget.third = panel
if panel_width == nil then
panel_width = bar.widget.widget.third.width
end
bar.ontop = true
- elseif pos == bar_width and not expand_button._expanded then
+ elseif pos == bar_width and not panel_toggle.toggled then
bar.widget.widget.third = nil
bar.ontop = false
end
@@ -98,25 +91,21 @@ screen.connect_signal("request::desktop_decoration", function(s)
bar.shape = function(cr, _, h)
qvars.shape(cr, pos, h)
end
- end
+ end,
}
- expand_button.buttons = {
- qbind:new {
- triggers = qvars.btns.left,
- press = function()
- if expand_button._expanded then
- timed.target = bar_width
- else
- timed.target = bar_width + qvars.expanded_bar_size
- -- timed.target = bar_width + qvars.big_padding + (qvars.big_padding * 2 + qvars.element_size * 4) * 3 + qvars.padding * 2
- end
-
- -- q.debug(tostring(panel_width))
- expand_button._expanded = not expand_button._expanded
- end,
- hidden = true
- }
+ panel_toggle = qui.toggle {
+ off = phosphor.arrows_out_simple_fill,
+ on = phosphor.arrows_in_simple_fill,
+ press = function(self)
+ if not self.toggled then
+ timed.target = bar_width
+ else
+ timed.target = bar_width + qvars.expanded_bar_size
+ end
+ end,
}
-
+
+ bar.widget:get_children_by_id("top")[1]:insert(1, panel_toggle)
+ qstore.panel_toggle = panel_toggle
end)
diff --git a/.config/awesome/ui/statusbar/panel/init.lua b/.config/awesome/ui/statusbar/panel/init.lua
index 7685451..31c2860 100644
--- a/.config/awesome/ui/statusbar/panel/init.lua
+++ b/.config/awesome/ui/statusbar/panel/init.lua
@@ -1,6 +1,8 @@
local qvars = require "quarrel.vars"
local wibox = require "wibox"
+local battery = require "ui.statusbar.panel.widgets.battery"
+local calendar = require "ui.statusbar.panel.widgets.calendar"
local displays = require "ui.statusbar.panel.widgets.displays"
local music = require "ui.statusbar.panel.widgets.music"
local power_menu = require "ui.statusbar.panel.widgets.power_menu"
@@ -9,7 +11,7 @@ local wifi = require "ui.statusbar.panel.widgets.wifi"
local panel = wibox.widget {
widget = wibox.container.margin,
margins = {
- left = qvars.big_padding
+ left = qvars.big_padding,
},
{
{
@@ -24,25 +26,27 @@ local panel = wibox.widget {
spacing = qvars.padding,
},
wifi,
- music,
+ -- battery,
+ -- music,
+ calendar,
layout = wibox.layout.fixed.vertical,
- spacing = qvars.padding
- }
+ spacing = qvars.padding,
+ },
},
{
widget = wibox.container.background,
{
widget = wibox.widget.textbox,
- text = ":)"
- }
+ text = ":)",
+ },
},
{
widget = wibox.container.place,
valign = "bottom",
- power_menu
+ power_menu,
},
layout = wibox.layout.align.vertical,
- }
+ },
}
return panel
diff --git a/.config/awesome/ui/statusbar/panel/widgets/battery.lua b/.config/awesome/ui/statusbar/panel/widgets/battery.lua
new file mode 100644
index 0000000..52685b7
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/battery.lua
@@ -0,0 +1,70 @@
+local gears = require "gears"
+local lit = require "lib.lit"
+local qbezier = require "quarrel.bezier"
+local qui = require "quarrel.ui"
+local wibox = require "wibox"
+
+local widget = wibox.widget {
+ widget = wibox.container.constraint,
+ height = 120,
+ width = 120,
+ strategy = "exact",
+ {
+ widget = lit.widget.linechart,
+ -- max_value = 30,
+ -- step_width = 10,
+ -- scale = true,
+ -- stack = false,
+ -- forced_height = 30,
+ -- step_hook = curvaceous
+ -- values = { 1, 10, 100 },
+ fill = true,
+ fill_color = "#00ff00",
+ -- fill_border = true,
+ fill_border_color = "#ff0000",
+ draw_bg = function(cr, width, _, min, max, transform)
+ cr:set_line_width(1)
+ local min_abs = math.abs(min)
+ local dash_pattern = { 6, 4 }
+ local rendered_zero, zero_overlap = false, false
+ for i = 0, 4 do
+ local temp = ((min_abs + max) * (i / 4)) - min_abs
+ rendered_zero = rendered_zero or temp == 0
+ if rendered_zero and not zero_overlap and min < 0 then
+ cr:set_source_rgba(gears.color.parse_color "#0000ff")
+ zero_overlap = true
+ else
+ cr:set_dash(dash_pattern, 1, 0)
+ cr:set_source_rgba(gears.color.parse_color "#ff0000ff")
+ end
+ local y = transform(temp)
+ cr:move_to(0, y)
+ cr:line_to(width, y)
+ cr:stroke()
+ cr:set_dash({}, 0, 0)
+ end
+
+ if not rendered_zero then
+ cr:set_source_rgba(gears.color.parse_color "#0000ff")
+ local h_0 = transform(0)
+ cr:move_to(0, h_0)
+ cr:line_to(width, h_0)
+ cr:stroke()
+ end
+ end,
+ },
+}
+
+-- for _ = 1, 100 do
+-- widget.widget:add_value(math.random(0, 30))
+-- end
+
+-- require "gears.timer" {
+-- autostart = true,
+-- timeout = 0.2,
+-- callback = function ()
+-- widget.widget:add_value(math.random(0, 30))
+-- end
+-- }
+
+return widget
diff --git a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
index 8b13789..8933543 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
@@ -1 +1,156 @@
+local awful = require "awful"
+local phosphor = require "assets.phosphor"
+local qbind = require "quarrel.bind"
+local qmarkup = require "quarrel.markup"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+local weekday_map = { 7, 1, 2, 3, 4, 5, 6 }
+
+local calendar = wibox.widget(qui.styled {
+ widget = wibox.container.background,
+ {
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ {
+ {
+ {
+ widget = wibox.container.place,
+ qui.icon {
+ icon = phosphor.caret_left_bold,
+ },
+ },
+ {
+ widget = wibox.container.place,
+ {
+ widget = wibox.widget.textbox,
+ text = "January 2024",
+ },
+ },
+ {
+ widget = wibox.container.place,
+ qui.icon {
+ icon = phosphor.caret_right_bold,
+ },
+ },
+ layout = wibox.layout.align.horizontal,
+ expand = "outside",
+ },
+ {
+ layout = wibox.layout.grid,
+ forced_num_rows = 7,
+ forced_num_cols = 7,
+ spacing = qvars.padding,
+ id = "grid",
+ },
+ layout = wibox.layout.fixed.vertical,
+ spacing = qvars.big_padding,
+ },
+ },
+})
+
+-- Logic heavily inspired by https://github.com/Sinomor/dotfiles/blob/e409f9a84bf40daf1e39c0179ec749232ed827c9/home/.config/awesome/ui/control/moment/calendar.lua#L134-L173
+function calendar:compute_grid(year, month)
+ local calendar_table = { {}, {}, {}, {}, {}, {} }
+ local current = os.date("*t", os.time())
+ local first_day = os.date("*t", os.time { year = year, month = month, day = 1 })
+ local last_day = os.date("*t", os.time { year = year, month = month + 1, day = 0 })
+
+ local days = last_day.day
+
+ local prev_days = os.date("*t", os.time { year = year, month = month, day = 0 })
+ local prev_offset = weekday_map[first_day.wday] - 1
+ local prev_month = month - 1 == -1 and 12 or month - 1
+ local prev_year = prev_month == 12 and year - 1 or year
+
+ if prev_offset ~= -1 then
+ for offset = prev_offset, 1, -1 do
+ local day = prev_days.day - offset + 1
+ table.insert(
+ calendar_table[1],
+ { day, day == current.day and prev_month == current.month and prev_year == current.year, false }
+ )
+ end
+ end
+
+ do
+ local row = 1
+ local weekday = weekday_map[first_day.wday]
+ for day = 1, days do
+ table.insert(
+ calendar_table[row],
+ { day, day == current.day and month == current.month and year == current.year, true }
+ )
+ if weekday == 7 then
+ row = row + 1
+ weekday = 1
+ else
+ weekday = weekday + 1
+ end
+ end
+
+ local next_month = month + 1 == 13 and 1 or month + 1
+ local next_year = next_month == 1 and year + 1 or year
+ for day = 1, 42 - prev_offset - days do
+ table.insert(
+ calendar_table[row],
+ { day, day == current.day and next_month + 1 == current.month and next_year == current.year, false }
+ )
+ if weekday == 7 then
+ row = row + 1
+ weekday = 1
+ else
+ weekday = weekday + 1
+ end
+ end
+ end
+
+ for i, row in ipairs(calendar_table) do
+ for j, col in ipairs(row) do
+ local widget = self:get_children_by_id("grid")[1]:get_widgets_at(i + 1, j)[1]
+ widget.widget.widget.text = col[1]
+ if col[2] then
+ widget.bg = qvars.colors.yellow
+ widget.fg = qvars.colors.bg
+ else
+ widget.bg = qvars.colors.bg
+ widget.fg = col[3] and qvars.colors.fg or qvars.colors.dim.fg
+ end
+ end
+ end
+end
+
+local cells = {}
+local function cell(content)
+ local widget = wibox.widget {
+ widget = wibox.container.background,
+ shape = qvars.shape,
+ {
+ widget = wibox.container.place,
+ forced_height = qvars.char_height * 1.5,
+ forced_width = qvars.char_height * 1.5,
+ {
+ widget = wibox.widget.textbox,
+ markup = content,
+ },
+ },
+ }
+ table.insert(cells, widget)
+end
+
+cell "Mo"
+cell "Tu"
+cell "We"
+cell "Th"
+cell "Fr"
+cell(qmarkup("Sa", { bold = true }))
+cell(qmarkup("Su", { bold = true }))
+
+for _ = 1, 42 do
+ cell()
+end
+calendar:get_children_by_id("grid")[1]:add(table.unpack(cells))
+calendar:compute_grid(2024, 1)
+
+return calendar
diff --git a/.config/awesome/ui/statusbar/panel/widgets/displays.lua b/.config/awesome/ui/statusbar/panel/widgets/displays.lua
index de15bd5..b52c986 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/displays.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/displays.lua
@@ -1,3 +1,5 @@
+local backlight = require "services.backlight"
+local battery = require "services.battery"
local phosphor = require "assets.phosphor"
local qmath = require "quarrel.math"
local qui = require "quarrel.ui"
@@ -23,23 +25,29 @@ local function create_display(icon, color)
forced_width = qvars.element_size * 4,
{
widget = wibox.container.place,
- qui.icon(icon, color, { id = "icon" })
+ qui.icon {
+ icon = icon,
+ color = color,
+ widget = {
+ id = "icon",
+ },
+ },
},
- id = "indicator"
+ id = "indicator",
},
{
widget = wibox.container.place,
{
widget = wibox.widget.textbox,
text = "0%",
- id = "text"
- }
+ id = "text",
+ },
},
layout = wibox.layout.fixed.vertical,
- spacing = qvars.big_padding
- }
- }
- }
+ spacing = qvars.big_padding,
+ },
+ },
+ },
})
end
@@ -58,23 +66,23 @@ awesome.connect_signal("services::audio::icon", function(icon, color)
end)
local d_battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
-awesome.connect_signal("services::battery", function(capacity)
- d_battery:get_children_by_id("indicator")[1].value = capacity
- d_battery:get_children_by_id("text")[1].text = capacity .. "%"
+battery:connect_signal("level", function(_, level)
+ d_battery:get_children_by_id("indicator")[1].value = level
+ d_battery:get_children_by_id("text")[1].text = level .. "%"
end)
-awesome.connect_signal("services::battery::icon", function(icon, color)
+battery:connect_signal("icon", function(_, icon, color)
d_battery:get_children_by_id("indicator")[1].color = color
d_battery:get_children_by_id("icon")[1].image = icon
d_battery:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
end)
local d_brightness = create_display(phosphor.sun_fill, qvars.colors.fg)
-awesome.connect_signal("services::brightness", function(brightness)
+backlight:connect_signal("value", function(_, brightness)
brightness = math.floor(qmath.translate_range(brightness, 0, 255, 0, 100))
d_brightness:get_children_by_id("indicator")[1].value = brightness
d_brightness:get_children_by_id("text")[1].text = brightness .. "%"
end)
-awesome.connect_signal("services::brightness::icon", function(icon, color)
+backlight:connect_signal("icon", function(_, icon, color)
d_brightness:get_children_by_id("icon")[1].image = icon
d_brightness:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
end)
diff --git a/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua b/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
index 8c6e8a5..5caadc5 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
@@ -24,13 +24,13 @@
-- @supermodule wibox.widget.base
---------------------------------------------------------------------------
-local lgi = require("lgi")
+local lgi = require "lgi"
local cairo = lgi.cairo
-local base = require("wibox.widget.base")
-local surface = require("gears.surface")
-local gtable = require("gears.table")
-local gdebug = require("gears.debug")
+local base = require "wibox.widget.base"
+local gdebug = require "gears.debug"
+local gtable = require "gears.table"
+local surface = require "gears.surface"
local setmetatable = setmetatable
local type = type
local math = math
@@ -40,7 +40,9 @@ local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility
-- Safe load for optional Rsvg module
local Rsvg = nil
do
- local success, err = pcall(function() Rsvg = lgi.Rsvg end)
+ local success, err = pcall(function()
+ Rsvg = lgi.Rsvg
+ end)
if not success then
gdebug.print_warning(debug.traceback("Could not load Rsvg: " .. tostring(err)))
end
@@ -48,14 +50,16 @@ end
local imagebox = { mt = {} }
-local rsvg_handle_cache = setmetatable({}, { __mode = 'k' })
+local rsvg_handle_cache = setmetatable({}, { __mode = "k" })
---Load rsvg handle form image file
-- @tparam string file Path to svg file.
-- @return Rsvg handle
-- @treturn table A table where cached data can be stored.
local function load_rsvg_handle(file)
- if not Rsvg then return end
+ if not Rsvg then
+ return
+ end
local cache = (rsvg_handle_cache[file] or {})["handle"]
@@ -65,7 +69,7 @@ local function load_rsvg_handle(file)
local handle, err
- if file:match("<[?]?xml") or file:match("<svg") then
+ if file:match "<[?]?xml" or file:match "<svg" then
handle, err = Rsvg.Handle.new_from_data(file)
else
handle, err = Rsvg.Handle.new_from_file(file)
@@ -81,7 +85,9 @@ end
---Apply cairo surface for given imagebox widget
local function set_surface(ib, surf)
local is_surf_valid = surf.width > 0 and surf.height > 0
- if not is_surf_valid then return false end
+ if not is_surf_valid then
+ return false
+ end
ib._private.default = { width = surf.width, height = surf.height }
ib._private.handle = nil
@@ -93,7 +99,9 @@ end
local function set_handle(ib, handle, cache)
local dim = handle:get_dimensions()
local is_handle_valid = dim.width > 0 and dim.height > 0
- if not is_handle_valid then return false end
+ if not is_handle_valid then
+ return false
+ end
ib._private.default = { width = dim.width, height = dim.height }
ib._private.handle = handle
@@ -124,18 +132,15 @@ end
-- It's necessary because a single RSVG handle can be used by
-- many imageboxes. So DPI and Stylesheet need to be set each time.
local function update_dpi(self, ctx)
- if not self._private.handle then return end
+ if not self._private.handle then
+ return
+ end
- local dpi = self._private.auto_dpi and
- ctx.dpi or
- self._private.dpi or
- nil
+ local dpi = self._private.auto_dpi and ctx.dpi or self._private.dpi or nil
- local need_dpi = dpi and
- self._private.last_dpi ~= dpi
+ local need_dpi = dpi and self._private.last_dpi ~= dpi
- local need_style = self._private.handle.set_stylesheet and
- self._private.stylesheet
+ local need_style = self._private.handle.set_stylesheet and self._private.stylesheet
local old_size = self._private.default and self._private.default.width
@@ -163,14 +168,16 @@ local function update_dpi(self, ctx)
-- This can happen in the constructor when `dpi` is set after `image`.
if old_size and old_size ~= self._private.default.width then
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("widget::layout_changed")
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal "widget::layout_changed"
end
end
-- Draw an imagebox with the given cairo context in the given geometry.
function imagebox:draw(ctx, cr, width, height)
- if width == 0 or height == 0 or not self._private.default then return end
+ if width == 0 or height == 0 or not self._private.default then
+ return
+ end
-- For valign = "top" and halign = "left"
local translate = {
@@ -186,15 +193,15 @@ function imagebox:draw(ctx, cr, width, height)
-- That's for the "fit" policy.
local aspects = {
w = width / w,
- h = height / h
+ h = height / h,
}
local policy = {
w = self._private.horizontal_fit_policy or "auto",
- h = self._private.vertical_fit_policy or "auto"
+ h = self._private.vertical_fit_policy or "auto",
}
- for _, aspect in ipairs {"w", "h"} do
+ for _, aspect in ipairs { "w", "h" } do
if self._private.upscale == false and (w < width and h < height) then
aspects[aspect] = 1
elseif self._private.downscale == false and (w >= width and h >= height) then
@@ -209,15 +216,15 @@ function imagebox:draw(ctx, cr, width, height)
end
if self._private.halign == "center" then
- translate.x = math.floor((width - w*aspects.w)/2)
+ translate.x = math.floor((width - w * aspects.w) / 2)
elseif self._private.halign == "right" then
- translate.x = math.floor(width - (w*aspects.w))
+ translate.x = math.floor(width - (w * aspects.w))
end
if self._private.valign == "center" then
- translate.y = math.floor((height - h*aspects.h)/2)
+ translate.y = math.floor((height - h * aspects.h) / 2)
elseif self._private.valign == "bottom" then
- translate.y = math.floor(height - (h*aspects.h))
+ translate.y = math.floor(height - (h * aspects.h))
end
cr:translate(translate.x, translate.y)
@@ -226,25 +233,25 @@ function imagebox:draw(ctx, cr, width, height)
local threshold, max_factor = self._private.max_scaling_factor, math.max(aspects.w, aspects.h)
if threshold and threshold > 0 and threshold < max_factor then
- aspects.w = (aspects.w*threshold)/max_factor
- aspects.h = (aspects.h*threshold)/max_factor
+ aspects.w = (aspects.w * threshold) / max_factor
+ aspects.h = (aspects.h * threshold) / max_factor
end
-- Set the clip
if self._private.clip_shape then
- cr:clip(self._private.clip_shape(cr, w*aspects.w, h*aspects.h, unpack(self._private.clip_args)))
+ cr:clip(self._private.clip_shape(cr, w * aspects.w, h * aspects.h, unpack(self._private.clip_args)))
end
cr:scale(aspects.w, aspects.h)
else
if self._private.halign == "center" then
- translate.x = math.floor((width - w)/2)
+ translate.x = math.floor((width - w) / 2)
elseif self._private.halign == "right" then
translate.x = math.floor(width - w)
end
if self._private.valign == "center" then
- translate.y = math.floor((height - h)/2)
+ translate.y = math.floor((height - h) / 2)
elseif self._private.valign == "bottom" then
translate.y = math.floor(height - h)
end
@@ -274,7 +281,9 @@ end
-- Fit the imagebox into the given geometry
function imagebox:fit(ctx, width, height)
- if not self._private.default then return 0, 0 end
+ if not self._private.default then
+ return 0, 0
+ end
update_dpi(self, ctx)
@@ -349,11 +358,13 @@ function imagebox:set_image(image)
self._private.default = nil
end
- if not setup_succeed then return false end
+ if not setup_succeed then
+ return false
+ end
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("widget::layout_changed")
- self:emit_signal("property::image")
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal "widget::layout_changed"
+ self:emit_signal "property::image"
return true
end
@@ -383,8 +394,8 @@ end
-- @see clip_shape
function imagebox:set_clip_shape(clip_shape, ...)
self._private.clip_shape = clip_shape
- self._private.clip_args = {...}
- self:emit_signal("widget::redraw_needed")
+ self._private.clip_args = { ... }
+ self:emit_signal "widget::redraw_needed"
self:emit_signal("property::clip_shape", clip_shape)
end
@@ -468,14 +479,14 @@ end
-- @propemits true false
-- @see dpi
-for _, prop in ipairs {"stylesheet", "dpi", "auto_dpi"} do
+for _, prop in ipairs { "stylesheet", "dpi", "auto_dpi" } do
imagebox["set_" .. prop] = function(self, value)
-- It will be set in :fit and :draw. The handle is shared
-- by multiple imagebox, so it cannot be set just once.
self._private[prop] = value
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("widget::layout_changed")
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal "widget::layout_changed"
self:emit_signal("property::" .. prop)
end
end
@@ -490,12 +501,12 @@ function imagebox:set_resize(allowed)
self:emit_signal("property::upscale", allowed)
end
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("widget::layout_changed")
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal "widget::layout_changed"
self:emit_signal("property::resize", allowed)
end
-for _, prop in ipairs {"downscale", "upscale" } do
+for _, prop in ipairs { "downscale", "upscale" } do
imagebox["set_" .. prop] = function(self, allowed)
self._private[prop] = allowed
@@ -504,9 +515,9 @@ for _, prop in ipairs {"downscale", "upscale" } do
self:emit_signal("property::resize", self._private.resize)
end
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("widget::layout_changed")
- self:emit_signal("property::"..prop, allowed)
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal "widget::layout_changed"
+ self:emit_signal("property::" .. prop, allowed)
end
end
@@ -542,7 +553,6 @@ end
-- @see horizontal_fit_policy
-- @see resize
-
--- The vertical alignment.
--
-- @DOC_wibox_widget_imagebox_valign_EXAMPLE@
@@ -627,30 +637,34 @@ end
-- @see max_scaling_factor
local defaults = {
- halign = "left",
- valign = "top",
+ halign = "left",
+ valign = "top",
horizontal_fit_policy = "auto",
- vertical_fit_policy = "auto",
- max_scaling_factor = 0,
- scaling_quality = "good"
+ vertical_fit_policy = "auto",
+ max_scaling_factor = 0,
+ scaling_quality = "good",
}
local function get_default(prop, value)
- if value == nil then return defaults[prop] end
+ if value == nil then
+ return defaults[prop]
+ end
return value
end
for prop in pairs(defaults) do
- imagebox["set_"..prop] = function(self, value)
- if value == self._private[prop] then return end
+ imagebox["set_" .. prop] = function(self, value)
+ if value == self._private[prop] then
+ return
+ end
self._private[prop] = get_default(prop, value)
- self:emit_signal("widget::redraw_needed")
- self:emit_signal("property::"..prop, self._private[prop])
+ self:emit_signal "widget::redraw_needed"
+ self:emit_signal("property::" .. prop, self._private[prop])
end
- imagebox["get_"..prop] = function(self)
+ imagebox["get_" .. prop] = function(self)
if self._private[prop] == nil then
return defaults[prop]
end
@@ -678,7 +692,7 @@ end
-- @treturn wibox.widget.imagebox A new `wibox.widget.imagebox` widget instance.
-- @constructorfct wibox.widget.imagebox
local function new(image, resize_allowed, clip_shape, ...)
- local ret = base.make_widget(nil, nil, {enable_properties = true})
+ local ret = base.make_widget(nil, nil, { enable_properties = true })
gtable.crush(ret, imagebox, true)
ret._private.resize = true
@@ -692,7 +706,7 @@ local function new(image, resize_allowed, clip_shape, ...)
end
ret._private.clip_shape = clip_shape
- ret._private.clip_args = {...}
+ ret._private.clip_args = { ... }
return ret
end
diff --git a/.config/awesome/ui/statusbar/panel/widgets/linegraph.lua b/.config/awesome/ui/statusbar/panel/widgets/linegraph.lua
deleted file mode 100644
index 9a42632..0000000
--- a/.config/awesome/ui/statusbar/panel/widgets/linegraph.lua
+++ /dev/null
@@ -1,154 +0,0 @@
-local gcolor = require "gears.color"
-local gtable = require "gears.table"
-local wibox = require "wibox"
-
-local linegraph = { mt = {} }
-
-function linegraph:fit(_, width, height)
- if #self._private.values < 2 then
- return 0, 0
- end
- return width, height
-end
-
-function linegraph:draw(_, cr, width, height)
- if #self._private.values < 2 then
- return
- end
- local line_width = self._private.line_width
- local values = self._private.values
-
- local max, min = self._private.max or 0, self._private.min or 0
- if not (self._private.max and self._private.min) then
- for _, value in ipairs(values) do
- if not self._private.max then
- max = max < value and value or max
- end
- if not self._private.min then
- min = min > value and value or min
- end
- end
- end
-
- local usable_height = height - line_width
- local min_abs = math.abs(min)
- local h_factor = usable_height / (min_abs + max)
-
- local function transform(value)
- return usable_height - math.floor((value + min_abs) * h_factor) + line_width / 2
- end
-
- local graph_values = {}
- for i = 1, #values, math.ceil(#values / width) do
- table.insert(graph_values, transform(values[i]))
- end
-
- if self._private.draw_bg then
- cr:save()
- self._private.draw_bg(cr, width, height, min, max, transform)
- cr:restore()
- end
-
- cr:set_line_width(line_width)
- cr:set_source(gcolor(self.color))
- cr:move_to(line_width / 2, graph_values[1])
- for i = 2, #graph_values do
- cr:line_to((width - line_width / 2) / (#graph_values - 1) * (i - 1), graph_values[i])
- end
-
- if self._private.fill then
- cr:line_to(width - line_width / 2, transform(min))
- cr:line_to(line_width / 2, transform(min))
- cr:line_to(line_width / 2, graph_values[1])
- cr:stroke_preserve()
- cr:set_source(gcolor(self.fill_color))
- cr:fill()
- else
- cr:stroke()
- end
-end
-
-function linegraph:set_values(values)
- self._private.values = values
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_values()
- return self._private.values
-end
-
-function linegraph:set_draw_bg(draw_bg)
- self._private.draw_bg = draw_bg
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_draw_bg()
- return self._private.draw_bg
-end
-
-function linegraph:set_max(max)
- self._private.max = max
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_max()
- return self._private.max
-end
-
-function linegraph:set_min(min)
- self._private.max = min
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_min()
- return self._private.min
-end
-
-function linegraph:set_line_width(line_width)
- self._private.line_width = line_width
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:set_color(color)
- self._private.color = color
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_color()
- return self._private.color
-end
-
-function linegraph:set_fill_color(fill_color)
- self._private.fill_color = fill_color
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_fill_color()
- return self._private.fill_color
-end
-
-function linegraph:set_fill(fill)
- self._private.fill = fill
- self:emit_signal "widget::redraw_needed"
-end
-
-function linegraph:get_fill()
- return self._private.fill
-end
-
-local function new()
- local ret = wibox.widget.base.make_widget(nil, nil, { enable_properties = true })
- gtable.crush(ret, linegraph, true)
-
- ret.line_width = 1
- ret.color = "#ffffff"
- ret.fill_color = "#000000"
-
- return ret
-end
-
-function linegraph.mt:__call()
- return new()
-end
-
-return setmetatable(linegraph, linegraph.mt)
diff --git a/.config/awesome/ui/statusbar/panel/widgets/music.lua b/.config/awesome/ui/statusbar/panel/widgets/music.lua
index 3eedb55..eea7335 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/music.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/music.lua
@@ -1,28 +1,10 @@
-local cairo = require "lgi".cairo
-local gcolor = require "gears.color"
-local gsurface = require "gears.surface"
-local imagebox = require "ui.statusbar.panel.widgets.imagebox"
-local phosphor = require "assets.phosphor"
-local playerctl = require "services.playerctl"
local qnative = require "quarrel.native"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wibox = require "wibox"
-local default_cover = phosphor.vinyl_record_fill
local default_text = "Nothing playing"
-local function faded_cover(cover)
- local surface = gsurface(cover)
- local w,h = gsurface.get_size(surface)
- local cr = cairo.Context(surface)
- local pattern = gcolor(qvars.colors.bg .. "aa")
- cr:rectangle(0, 0, w, h)
- cr:set_source(pattern)
- cr:fill_preserve()
- return surface
-end
-
local w_title = wibox.widget {
widget = wibox.widget.textbox,
text = "Nothing playing",
@@ -33,20 +15,8 @@ local w_artist = wibox.widget {
fg = qvars.colors.dim.fg,
{
widget = wibox.widget.textbox,
- text = ""
- }
-}
-
-local w_cover = wibox.widget {
- widget = imagebox,
- image = default_cover,
- stylesheet = qui.recolor(qvars.colors.bright.black),
- forced_height = qvars.char_height * 6 + qvars.big_padding * 2,
- forced_width = qvars.expanded_bar_size - qvars.big_padding,
- horizontal_fit_policy = "cover",
- vertical_fit_policy = "cover",
- valign = "center",
- halign = "center"
+ text = "",
+ },
}
local w_progress_bar = wibox.widget {
@@ -54,100 +24,22 @@ local w_progress_bar = wibox.widget {
max_value = 0,
value = 0,
forced_height = qvars.char_height / 2,
- forced_width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2) - (qvars.char_height / 1.25 + qvars.padding) * 3,
+ forced_width = qvars.expanded_bar_size
+ - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2)
+ - (qvars.char_height / 1.25 + qvars.padding) * 3,
color = qvars.colors.yellow,
background_color = qvars.colors.black,
shape = qvars.shape,
}
-local w_play_pause = qui.toggle {
- widget = {
- forced_height = qvars.char_height / 1.25,
- forced_width = qvars.char_height / 1.25
- },
- off = phosphor.play_fill,
- on = phosphor.pause_fill,
- manual = true,
- press = function()
- playerctl:play_pause()
- end
-}
-
-local w_skip_forward = qui.button {
- widget = {
- forced_height = qvars.char_height / 1.25,
- forced_width = qvars.char_height / 1.25
- },
- image = phosphor.skip_forward_fill,
- press = function()
- playerctl:next()
- end
-}
-
-local w_skip_back = qui.button {
- widget = {
- forced_height = qvars.char_height / 1.25,
- forced_width = qvars.char_height / 1.25
- },
- image = phosphor.skip_back_fill,
- press = function()
- playerctl:previous()
- end
-}
-
local music = wibox.widget(qui.styled {
widget = wibox.container.background,
{
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
{
- widget = wibox.container.background,
- bg = qvars.colors.black
- },
- w_cover,
- {
- widget = wibox.container.margin,
- margins = qvars.big_padding,
{
{
- {
- widget = wibox.container.background,
- bg = qvars.colors.bg,
- shape = qvars.shape,
- {
- widget = wibox.container.margin,
- margins = qvars.padding,
- {
- {
- widget = wibox.container.constraint,
- width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
- height = qvars.char_height,
- {
- widget = wibox.container.scroll.horizontal,
- speed = 50,
- step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
- w_title
- }
- },
- {
- widget = wibox.container.constraint,
- width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
- height = qvars.char_height,
- {
- widget = wibox.container.scroll.horizontal,
- speed = 50,
- step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
- w_artist
- }
- },
- layout = wibox.layout.fixed.vertical
- }
- }
- },
- nil,
- nil,
- layout = wibox.layout.align.horizontal
- },
- nil,
- {
widget = wibox.container.background,
bg = qvars.colors.bg,
shape = qvars.shape,
@@ -155,29 +47,53 @@ local music = wibox.widget(qui.styled {
widget = wibox.container.margin,
margins = qvars.padding,
{
- w_play_pause,
- w_skip_back,
{
- widget = wibox.container.place,
- w_progress_bar
+ widget = wibox.container.constraint,
+ width = qvars.expanded_bar_size
+ - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
+ height = qvars.char_height,
+ {
+ widget = wibox.container.scroll.horizontal,
+ speed = 50,
+ step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
+ w_title,
+ },
},
- w_skip_forward,
- layout = wibox.layout.fixed.horizontal,
- spacing = qvars.padding
- }
- }
+ {
+ widget = wibox.container.constraint,
+ width = qvars.expanded_bar_size
+ - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
+ height = qvars.char_height,
+ {
+ widget = wibox.container.scroll.horizontal,
+ speed = 50,
+ step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
+ w_artist,
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ },
+ },
},
- layout = wibox.layout.align.vertical
- }
+ nil,
+ nil,
+ layout = wibox.layout.align.horizontal,
+ },
+ nil,
+ {
+ widget = wibox.container.background,
+ bg = qvars.colors.bg,
+ shape = qvars.shape,
+ w_progress_bar,
+ },
+ layout = wibox.layout.align.vertical,
},
- layout = wibox.layout.stack
- }
+ },
})
awesome.connect_signal("services::playerctl::metadata", function(title, artist, album_path)
- w_title.text = title ~= "" and qnative.decode_html(title) or default_text
- w_artist.widget.text = qnative.decode_html(artist)
- w_cover.image = faded_cover(album_path)
+ w_title.text = title ~= "" and qnative.util.decode_html(title) or default_text
+ w_artist.widget.text = qnative.util.decode_html(artist)
end)
awesome.connect_signal("services::playerctl::position", function(position, length)
@@ -186,15 +102,10 @@ awesome.connect_signal("services::playerctl::position", function(position, lengt
end)
awesome.connect_signal("services::playerctl::no_players", function()
- w_title = default_text
- w_artist = ""
- w_cover.image = default_cover
+ w_title.text = default_text
+ w_artist.text = ""
w_progress_bar.value = 0
w_progress_bar.max_value = 0
end)
-awesome.connect_signal("services::playerctl::playback_status", function(playing)
- w_play_pause:silent_press(playing)
-end)
-
return music
diff --git a/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua b/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
index cf0de28..feea829 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
@@ -4,7 +4,7 @@ local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wibox = require "wibox"
-local power_menu = wibox.widget {
+return wibox.widget {
qui.styled {
widget = wibox.container.background,
bg = qvars.colors.black,
@@ -15,12 +15,12 @@ local power_menu = wibox.widget {
qbind:new {
triggers = qvars.btns.left,
press = function()
- q.debug("from 1")
+ q.debug "from 1"
end,
- hidden = true
- }
- }
- }
+ hidden = true,
+ },
+ },
+ },
},
qui.styled {
widget = wibox.container.background,
@@ -32,12 +32,12 @@ local power_menu = wibox.widget {
qbind:new {
triggers = qvars.btns.left,
press = function()
- q.debug("from 2")
+ q.debug "from 2"
end,
- hidden = true
- }
- }
- }
+ hidden = true,
+ },
+ },
+ },
},
qui.styled {
widget = wibox.container.background,
@@ -49,14 +49,12 @@ local power_menu = wibox.widget {
qbind:new {
triggers = qvars.btns.left,
press = function()
- q.debug("from 3")
+ q.debug "from 3"
end,
- hidden = true
- }
- }
- }
+ hidden = true,
+ },
+ },
+ },
},
- layout = wibox.layout.flex.horizontal
+ layout = wibox.layout.flex.horizontal,
}
-
-return power_menu
diff --git a/.config/awesome/ui/statusbar/panel/widgets/wifi.lua b/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
index 579474e..ad2234f 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
@@ -1,7 +1,9 @@
+local lgi = require "lgi"
local phosphor = require "assets.phosphor"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wibox = require "wibox"
+local glib = lgi.GLib
local wifi = wibox.widget(qui.styled {
widget = wibox.container.background,
@@ -13,17 +15,23 @@ local wifi = wibox.widget(qui.styled {
widget = wibox.container.place,
valign = "center",
halign = "center",
- qui.icon(phosphor.wifi_x_fill, qvars.colors.red, { id = "icon" })
+ qui.icon {
+ icon = phosphor.wifi_x_fill,
+ color = qvars.colors.red,
+ widget = {
+ id = "icon",
+ },
+ },
},
{
widget = wibox.widget.textbox,
text = "Disconnected",
- id = "essid"
+ id = "essid",
},
layout = wibox.layout.fixed.horizontal,
- spacing = qvars.padding
- }
- }
+ spacing = qvars.padding,
+ },
+ },
})
awesome.connect_signal("services::wifi", function(essid, _, connected)
diff --git a/.config/awesome/ui/statusbar/widgets/clock.lua b/.config/awesome/ui/statusbar/widgets/clock.lua
index ff57a36..c186dc5 100644
--- a/.config/awesome/ui/statusbar/widgets/clock.lua
+++ b/.config/awesome/ui/statusbar/widgets/clock.lua
@@ -1,13 +1,11 @@
local qvars = require "quarrel.vars"
local wibox = require "wibox"
-local clock = wibox.widget {
+return wibox.widget {
widget = wibox.container.place,
{
format = "%H\n%M",
widget = wibox.widget.textclock,
- font = qvars.font
- }
+ font = qvars.font,
+ },
}
-
-return clock
diff --git a/.config/awesome/ui/statusbar/widgets/displays.lua b/.config/awesome/ui/statusbar/widgets/displays.lua
index 44ff2c6..62e4398 100644
--- a/.config/awesome/ui/statusbar/widgets/displays.lua
+++ b/.config/awesome/ui/statusbar/widgets/displays.lua
@@ -1,3 +1,4 @@
+local battery = require "services.battery"
local phosphor = require "assets.phosphor"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
@@ -8,32 +9,35 @@ local function create_display(icon, color)
widget = wibox.container.place,
valign = "center",
halign = "center",
- qui.icon(icon, color)
+ qui.icon {
+ icon = icon,
+ color = color,
+ },
}
end
-local battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
-awesome.connect_signal("services::battery::icon", function(icon, color)
- battery.widget.image = icon
- battery.widget.stylesheet = qui.recolor(color)
+local d_battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
+battery:connect_signal("icon", function(_, icon, color)
+ d_battery.widget.image = icon
+ d_battery.widget.stylesheet = qui.recolor(color)
end)
-local brightness = create_display(phosphor.moon_fill, qvars.colors.fg)
+local d_brightness = create_display(phosphor.moon_fill, qvars.colors.fg)
awesome.connect_signal("services::brightness::icon", function(icon, color)
- brightness.widget.image = icon
- brightness.widget.stylesheet = qui.recolor(color)
+ d_brightness.widget.image = icon
+ d_brightness.widget.stylesheet = qui.recolor(color)
end)
-local audio = create_display(phosphor.speaker_simple_slash_fill, qvars.colors.red)
+local d_audio = create_display(phosphor.speaker_simple_slash_fill, qvars.colors.red)
awesome.connect_signal("services::audio::icon", function(icon, color)
- audio.widget.image = icon
- audio.widget.stylesheet = qui.recolor(color)
+ d_audio.widget.image = icon
+ d_audio.widget.stylesheet = qui.recolor(color)
end)
-local wifi = create_display(phosphor.wifi_x_fill, qvars.colors.red)
+local d_wifi = create_display(phosphor.wifi_x_fill, qvars.colors.red)
awesome.connect_signal("services::wifi::icon", function(icon, color)
- wifi.widget.image = icon
- wifi.widget.stylesheet = qui.recolor(color)
+ d_wifi.widget.image = icon
+ d_wifi.widget.stylesheet = qui.recolor(color)
end)
-return { audio = audio, battery = battery, brightness = brightness, wifi = wifi }
+return { audio = d_audio, battery = d_battery, brightness = d_brightness, wifi = d_wifi }
diff --git a/.config/awesome/ui/statusbar/widgets/keyboardlayout.lua b/.config/awesome/ui/statusbar/widgets/keyboardlayout.lua
index 0bbbf14..d9302ff 100644
--- a/.config/awesome/ui/statusbar/widgets/keyboardlayout.lua
+++ b/.config/awesome/ui/statusbar/widgets/keyboardlayout.lua
@@ -10,12 +10,12 @@
-- @supermodule wibox.widget.base
---------------------------------------------------------------------------
-local capi = {awesome = awesome}
+local capi = { awesome = awesome }
local setmetatable = setmetatable
-local textbox = require("wibox.widget.textbox")
-local button = require("awful.button")
-local widget_base = require("wibox.widget.base")
-local gdebug = require("gears.debug")
+local button = require "awful.button"
+local gdebug = require "gears.debug"
+local textbox = require "wibox.widget.textbox"
+local widget_base = require "wibox.widget.base"
--- Keyboard Layout widget.
-- awful.widget.keyboardlayout
@@ -24,109 +24,109 @@ local keyboardlayout = { mt = {} }
-- As to the country-code-like symbols below, refer to the names of XKB's
-- data files in /.../xkb/symbols/*.
keyboardlayout.xkeyboard_country_code = {
- ["ad"] = true, -- Andorra
- ["af"] = true, -- Afganistan
- ["al"] = true, -- Albania
- ["am"] = true, -- Armenia
- ["ara"] = true, -- Arabic
- ["at"] = true, -- Austria
- ["az"] = true, -- Azerbaijan
- ["ba"] = true, -- Bosnia and Herzegovina
- ["bd"] = true, -- Bangladesh
- ["be"] = true, -- Belgium
- ["bg"] = true, -- Bulgaria
- ["br"] = true, -- Brazil
- ["bt"] = true, -- Bhutan
- ["bw"] = true, -- Botswana
- ["by"] = true, -- Belarus
- ["ca"] = true, -- Canada
- ["cd"] = true, -- Congo
- ["ch"] = true, -- Switzerland
- ["cm"] = true, -- Cameroon
- ["cn"] = true, -- China
- ["cz"] = true, -- Czechia
- ["de"] = true, -- Germany
- ["dk"] = true, -- Denmark
- ["ee"] = true, -- Estonia
- ["epo"] = true, -- Esperanto
- ["es"] = true, -- Spain
- ["et"] = true, -- Ethiopia
- ["eu"] = true, -- EurKey
- ["fi"] = true, -- Finland
- ["fo"] = true, -- Faroe Islands
- ["fr"] = true, -- France
- ["gb"] = true, -- United Kingdom
- ["ge"] = true, -- Georgia
- ["gh"] = true, -- Ghana
- ["gn"] = true, -- Guinea
- ["gr"] = true, -- Greece
- ["hr"] = true, -- Croatia
- ["hu"] = true, -- Hungary
- ["ie"] = true, -- Ireland
- ["il"] = true, -- Israel
- ["in"] = true, -- India
- ["iq"] = true, -- Iraq
- ["ir"] = true, -- Iran
- ["is"] = true, -- Iceland
- ["it"] = true, -- Italy
- ["jp"] = true, -- Japan
- ["ke"] = true, -- Kenya
- ["kg"] = true, -- Kyrgyzstan
- ["kh"] = true, -- Cambodia
- ["kr"] = true, -- Korea
- ["kz"] = true, -- Kazakhstan
- ["la"] = true, -- Laos
+ ["ad"] = true, -- Andorra
+ ["af"] = true, -- Afganistan
+ ["al"] = true, -- Albania
+ ["am"] = true, -- Armenia
+ ["ara"] = true, -- Arabic
+ ["at"] = true, -- Austria
+ ["az"] = true, -- Azerbaijan
+ ["ba"] = true, -- Bosnia and Herzegovina
+ ["bd"] = true, -- Bangladesh
+ ["be"] = true, -- Belgium
+ ["bg"] = true, -- Bulgaria
+ ["br"] = true, -- Brazil
+ ["bt"] = true, -- Bhutan
+ ["bw"] = true, -- Botswana
+ ["by"] = true, -- Belarus
+ ["ca"] = true, -- Canada
+ ["cd"] = true, -- Congo
+ ["ch"] = true, -- Switzerland
+ ["cm"] = true, -- Cameroon
+ ["cn"] = true, -- China
+ ["cz"] = true, -- Czechia
+ ["de"] = true, -- Germany
+ ["dk"] = true, -- Denmark
+ ["ee"] = true, -- Estonia
+ ["epo"] = true, -- Esperanto
+ ["es"] = true, -- Spain
+ ["et"] = true, -- Ethiopia
+ ["eu"] = true, -- EurKey
+ ["fi"] = true, -- Finland
+ ["fo"] = true, -- Faroe Islands
+ ["fr"] = true, -- France
+ ["gb"] = true, -- United Kingdom
+ ["ge"] = true, -- Georgia
+ ["gh"] = true, -- Ghana
+ ["gn"] = true, -- Guinea
+ ["gr"] = true, -- Greece
+ ["hr"] = true, -- Croatia
+ ["hu"] = true, -- Hungary
+ ["ie"] = true, -- Ireland
+ ["il"] = true, -- Israel
+ ["in"] = true, -- India
+ ["iq"] = true, -- Iraq
+ ["ir"] = true, -- Iran
+ ["is"] = true, -- Iceland
+ ["it"] = true, -- Italy
+ ["jp"] = true, -- Japan
+ ["ke"] = true, -- Kenya
+ ["kg"] = true, -- Kyrgyzstan
+ ["kh"] = true, -- Cambodia
+ ["kr"] = true, -- Korea
+ ["kz"] = true, -- Kazakhstan
+ ["la"] = true, -- Laos
["latam"] = true, -- Latin America
["latin"] = true, -- Latin
- ["lk"] = true, -- Sri Lanka
- ["lt"] = true, -- Lithuania
- ["lv"] = true, -- Latvia
- ["ma"] = true, -- Morocco
- ["mao"] = true, -- Maori
- ["me"] = true, -- Montenegro
- ["mk"] = true, -- Macedonia
- ["ml"] = true, -- Mali
- ["mm"] = true, -- Myanmar
- ["mn"] = true, -- Mongolia
- ["mt"] = true, -- Malta
- ["mv"] = true, -- Maldives
- ["ng"] = true, -- Nigeria
- ["nl"] = true, -- Netherlands
- ["no"] = true, -- Norway
- ["np"] = true, -- Nepal
- ["ph"] = true, -- Philippines
- ["pk"] = true, -- Pakistan
- ["pl"] = true, -- Poland
- ["pt"] = true, -- Portugal
- ["ro"] = true, -- Romania
- ["rs"] = true, -- Serbia
- ["ru"] = true, -- Russia
- ["se"] = true, -- Sweden
- ["si"] = true, -- Slovenia
- ["sk"] = true, -- Slovakia
- ["sn"] = true, -- Senegal
- ["sy"] = true, -- Syria
- ["th"] = true, -- Thailand
- ["tj"] = true, -- Tajikistan
- ["tm"] = true, -- Turkmenistan
- ["tr"] = true, -- Turkey
- ["tw"] = true, -- Taiwan
- ["tz"] = true, -- Tanzania
- ["ua"] = true, -- Ukraine
- ["us"] = true, -- USA
- ["uz"] = true, -- Uzbekistan
- ["vn"] = true, -- Vietnam
- ["za"] = true, -- South Africa
+ ["lk"] = true, -- Sri Lanka
+ ["lt"] = true, -- Lithuania
+ ["lv"] = true, -- Latvia
+ ["ma"] = true, -- Morocco
+ ["mao"] = true, -- Maori
+ ["me"] = true, -- Montenegro
+ ["mk"] = true, -- Macedonia
+ ["ml"] = true, -- Mali
+ ["mm"] = true, -- Myanmar
+ ["mn"] = true, -- Mongolia
+ ["mt"] = true, -- Malta
+ ["mv"] = true, -- Maldives
+ ["ng"] = true, -- Nigeria
+ ["nl"] = true, -- Netherlands
+ ["no"] = true, -- Norway
+ ["np"] = true, -- Nepal
+ ["ph"] = true, -- Philippines
+ ["pk"] = true, -- Pakistan
+ ["pl"] = true, -- Poland
+ ["pt"] = true, -- Portugal
+ ["ro"] = true, -- Romania
+ ["rs"] = true, -- Serbia
+ ["ru"] = true, -- Russia
+ ["se"] = true, -- Sweden
+ ["si"] = true, -- Slovenia
+ ["sk"] = true, -- Slovakia
+ ["sn"] = true, -- Senegal
+ ["sy"] = true, -- Syria
+ ["th"] = true, -- Thailand
+ ["tj"] = true, -- Tajikistan
+ ["tm"] = true, -- Turkmenistan
+ ["tr"] = true, -- Turkey
+ ["tw"] = true, -- Taiwan
+ ["tz"] = true, -- Tanzania
+ ["ua"] = true, -- Ukraine
+ ["us"] = true, -- USA
+ ["uz"] = true, -- Uzbekistan
+ ["vn"] = true, -- Vietnam
+ ["za"] = true, -- South Africa
}
-- Callback for updating current layout.
-local function update_status (self)
+local function update_status(self)
self._current = awesome.xkb_get_layout_group()
local text = ""
if #self._layout > 0 then
-- Please note that the group number reported by xkb_get_layout_group
-- is lower by one than the group numbers reported by xkb_get_group_names.
- local name = self._layout[self._current+1]
+ local name = self._layout[self._current + 1]
if name then
text = name
end
@@ -155,53 +155,45 @@ function keyboardlayout.get_groups_from_group_names(group_names)
-- pattern.
local pattern_and_callback_pairs = {
-- vendor/file(section):group_idx
- ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. idx_pat .. "$"]
- = function(token, pattern)
- local vendor, file, section, group_idx = string.match(token, pattern)
- return vendor, file, section, group_idx
- end,
+ ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. idx_pat .. "$"] = function(token, pattern)
+ local vendor, file, section, group_idx = string.match(token, pattern)
+ return vendor, file, section, group_idx
+ end,
-- vendor/file(section)
- ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. "$"]
- = function(token, pattern)
- local vendor, file, section = string.match(token, pattern)
- return vendor, file, section, 1
- end,
+ ["^" .. word_pat .. "/" .. word_pat .. sec_pat .. "$"] = function(token, pattern)
+ local vendor, file, section = string.match(token, pattern)
+ return vendor, file, section, 1
+ end,
-- vendor/file:group_idx
- ["^" .. word_pat .. "/" .. word_pat .. idx_pat .. "$"]
- = function(token, pattern)
- local vendor, file, group_idx = string.match(token, pattern)
- return vendor, file, nil, group_idx
- end,
+ ["^" .. word_pat .. "/" .. word_pat .. idx_pat .. "$"] = function(token, pattern)
+ local vendor, file, group_idx = string.match(token, pattern)
+ return vendor, file, nil, group_idx
+ end,
-- vendor/file
- ["^" .. word_pat .. "/" .. word_pat .. "$"]
- = function(token, pattern)
- local vendor, file = string.match(token, pattern)
- return vendor, file, nil, 1
- end,
+ ["^" .. word_pat .. "/" .. word_pat .. "$"] = function(token, pattern)
+ local vendor, file = string.match(token, pattern)
+ return vendor, file, nil, 1
+ end,
-- file(section):group_idx
- ["^" .. word_pat .. sec_pat .. idx_pat .. "$"]
- = function(token, pattern)
- local file, section, group_idx = string.match(token, pattern)
- return nil, file, section, group_idx
- end,
+ ["^" .. word_pat .. sec_pat .. idx_pat .. "$"] = function(token, pattern)
+ local file, section, group_idx = string.match(token, pattern)
+ return nil, file, section, group_idx
+ end,
-- file(section)
- ["^" .. word_pat .. sec_pat .. "$"]
- = function(token, pattern)
- local file, section = string.match(token, pattern)
- return nil, file, section, 1
- end,
+ ["^" .. word_pat .. sec_pat .. "$"] = function(token, pattern)
+ local file, section = string.match(token, pattern)
+ return nil, file, section, 1
+ end,
-- file:group_idx
- ["^" .. word_pat .. idx_pat .. "$"]
- = function(token, pattern)
- local file, group_idx = string.match(token, pattern)
- return nil, file, nil, group_idx
- end,
+ ["^" .. word_pat .. idx_pat .. "$"] = function(token, pattern)
+ local file, group_idx = string.match(token, pattern)
+ return nil, file, nil, group_idx
+ end,
-- file
- ["^" .. word_pat .. "$"]
- = function(token, pattern)
- local file = string.match(token, pattern)
- return nil, file, nil, 1
- end
+ ["^" .. word_pat .. "$"] = function(token, pattern)
+ local file = string.match(token, pattern)
+ return nil, file, nil, 1
+ end,
}
-- Split 'group_names' into 'tokens'. The separator is "+".
@@ -229,10 +221,10 @@ function keyboardlayout.get_groups_from_group_names(group_names)
section = string.gsub(section, "%(([%w-_]+)%)", "%1")
end
- table.insert(layout_groups, { vendor = vendor,
- file = file,
- section = section,
- group_idx = tonumber(group_idx) })
+ table.insert(
+ layout_groups,
+ { vendor = vendor, file = file, section = section, group_idx = tonumber(group_idx) }
+ )
break
end
end
@@ -243,10 +235,10 @@ end
-- Callback for updating list of layouts
local function update_layout(self)
- self._layout = {};
+ self._layout = {}
local layouts = keyboardlayout.get_groups_from_group_names(awesome.xkb_get_group_names())
if layouts == nil or layouts[1] == nil then
- gdebug.print_error("Failed to get list of keyboard groups")
+ gdebug.print_error "Failed to get list of keyboard groups"
return
end
if #layouts == 1 then
@@ -270,7 +262,7 @@ end
-- @treturn awful.widget.keyboardlayout A keyboard layout widget.
function keyboardlayout.new()
local widget = textbox()
- local self = widget_base.make_widget(widget, nil, {enable_properties=true})
+ local self = widget_base.make_widget(widget, nil, { enable_properties = true })
self.widget = widget
@@ -288,30 +280,31 @@ function keyboardlayout.new()
self.set_layout = function(group_number)
if (0 > group_number) or (group_number > #self._layout) then
- error("Invalid group number: " .. group_number ..
- "expected number from 0 to " .. #self._layout)
- return;
+ error("Invalid group number: " .. group_number .. "expected number from 0 to " .. #self._layout)
+ return
end
- awesome.xkb_set_layout_group(group_number);
+ awesome.xkb_set_layout_group(group_number)
end
- update_layout(self);
+ update_layout(self)
-- callback for processing layout changes
- capi.awesome.connect_signal("xkb::map_changed",
- function () update_layout(self) end)
- capi.awesome.connect_signal("xkb::group_changed",
- function () update_status(self) end);
+ capi.awesome.connect_signal("xkb::map_changed", function()
+ update_layout(self)
+ end)
+ capi.awesome.connect_signal("xkb::group_changed", function()
+ update_status(self)
+ end)
-- Mouse bindings
self.buttons = {
- button({ }, 1, self.next_layout)
+ button({}, 1, self.next_layout),
}
return self
end
-local _instance = nil;
+local _instance = nil
function keyboardlayout.mt:__call(...)
if _instance == nil then
@@ -320,8 +313,6 @@ function keyboardlayout.mt:__call(...)
return _instance
end
-
return setmetatable(keyboardlayout, keyboardlayout.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
-
diff --git a/.config/awesome/ui/statusbar/widgets/taglist.lua b/.config/awesome/ui/statusbar/widgets/taglist.lua
index 1072426..df114df 100644
--- a/.config/awesome/ui/statusbar/widgets/taglist.lua
+++ b/.config/awesome/ui/statusbar/widgets/taglist.lua
@@ -1,75 +1,88 @@
local awful = require "awful"
-local gcolor = require "gears.color"
-local gdebug = require "gears.debug"
local phosphor = require "assets.phosphor"
local qbind = require "quarrel.bind"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wibox = require "wibox"
-return awful.widget.taglist {
- screen = screen[1],
- filter = awful.widget.taglist.filter.all,
- layout = {
- spacing = qvars.padding,
- layout = wibox.layout.fixed.vertical
- },
- widget_template = {
- widget = wibox.container.place,
- valign = "center",
- halign = "center",
- create_callback = function(self, tag)
- self.widget = qui.icon(tag.icon)
-
- self:connect_signal("mouse::enter", function()
- if tag.selected then return end
- self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
- end)
+return function(s)
+ return awful.widget.taglist {
+ screen = s,
+ filter = awful.widget.taglist.filter.all,
+ layout = {
+ spacing = qvars.padding,
+ layout = wibox.layout.fixed.vertical,
+ },
+ widget_template = {
+ widget = wibox.container.place,
+ valign = "center",
+ halign = "center",
+ create_callback = function(self, tag)
+ self.widget = qui.icon {
+ icon = phosphor[next(tag:clients()) and "circle_fill" or "circle_bold"],
+ widget = {
+ forced_height = qvars.char_height / 1.5,
+ forced_width = qvars.char_height / 1.5,
+ },
+ }
+ -- self.widget = wibox.widget {
+ --
+ -- }
- self:connect_signal("mouse::leave", function()
- if tag.selected then return end
- self.widget.stylesheet = qui.recolor(qvars.colors.fg)
- end)
+ self:connect_signal("mouse::enter", function()
+ if tag.selected then
+ return
+ end
+ self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
+ end)
- if tag.selected then
- self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
- return
- end
+ self:connect_signal("mouse::leave", function()
+ if tag.selected then
+ return
+ end
+ self.widget.stylesheet = qui.recolor(qvars.colors.fg)
+ end)
- self.widget.stylesheet = qui.recolor(qvars.colors.fg)
- end,
- update_callback = function(self, tag)
- -- self.widget.icon = phosphor[next(tag:clients()) and "circle_fill" or "circle_bold"]
+ if tag.selected then
+ self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
+ return
+ end
- if tag.selected then
- self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
- else
self.widget.stylesheet = qui.recolor(qvars.colors.fg)
- end
- end
- },
- buttons = {
- qbind:new {
- triggers = qvars.btns.left,
- press = function(t)
- t:view_only()
end,
- hidden = true
- },
- qbind:new {
- mods = qvars.mods.M,
- triggers = qvars.btns.left,
- press = function(t)
- if client.focus then
- client.focus:move_to_tag(t)
+ update_callback = function(self, tag)
+ self.widget.image = phosphor[next(tag:clients()) and "circle_fill" or "circle_bold"]
+
+ if tag.selected then
+ self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
+ else
+ self.widget.stylesheet = qui.recolor(qvars.colors.fg)
end
end,
- hidden = true
},
- qbind:new {
- triggers = qvars.btns.right,
- press = awful.tag.viewtoggle,
- hidden = true
+ buttons = {
+ qbind:new {
+ triggers = qvars.btns.left,
+ press = function(t)
+ t:view_only()
+ end,
+ hidden = true,
+ },
+ qbind:new {
+ mods = qvars.mods.M,
+ triggers = qvars.btns.left,
+ press = function(t)
+ if client.focus then
+ client.focus:move_to_tag(t)
+ end
+ end,
+ hidden = true,
+ },
+ qbind:new {
+ triggers = qvars.btns.right,
+ press = awful.tag.viewtoggle,
+ hidden = true,
+ },
},
}
-}
+end
diff --git a/.config/awesome/ui/statusbar/widgets/tasklist.lua b/.config/awesome/ui/statusbar/widgets/tasklist.lua
new file mode 100644
index 0000000..9656185
--- /dev/null
+++ b/.config/awesome/ui/statusbar/widgets/tasklist.lua
@@ -0,0 +1,30 @@
+local awful = require "awful"
+local gears = require "gears"
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+
+return function(s)
+ return awful.widget.tasklist {
+ screen = s,
+ filter = awful.widget.tasklist.filter.currenttags,
+ -- buttons = tasklist_buttons,
+ layout = {
+ spacing = qvars.padding,
+ layout = wibox.layout.flex.vertical,
+ },
+ widget_template = {
+ widget = wibox.container.place,
+ valign = "center",
+ halign = "center",
+ -- {
+ -- widget = awful.widget.clienticon,
+
+ -- }
+ {
+ widget = awful.widget.clienticon,
+ forced_width = qvars.char_height,
+ forced_height = qvars.char_height,
+ },
+ },
+ }
+end
diff --git a/.config/awesome/ui/wicked/_default.lua b/.config/awesome/ui/wicked/_default.lua
deleted file mode 100644
index 25283f9..0000000
--- a/.config/awesome/ui/wicked/_default.lua
+++ /dev/null
@@ -1,94 +0,0 @@
-----------------------------------------------------------------------------
---- The default widget template for the notifications.
---
--- @author Emmanuel Lepage Vallee &lt;elv1313@gmail.com&gt;
--- @copyright 2019 Emmanuel Lepage Vallee
--- @classmod naughty.widget._default
-----------------------------------------------------------------------------
-
-local wibox = require("wibox")
-local actionlist = require("naughty.list.actions")
-local wtitle = require("naughty.widget.title")
-local wmessage = require("naughty.widget.message")
-local wicon = require("naughty.widget.icon")
-local wbg = require("naughty.container.background")
-local beautiful = require("beautiful")
-local dpi = require("beautiful").xresources.apply_dpi
-
--- It is not worth doing a special widget for this.
-local function notif_size()
- local constraint = wibox.container.constraint()
- constraint:set_strategy("max")
- constraint:set_width(beautiful.notification_max_width or dpi(500))
-
- rawset(constraint, "set_notification", function(_, notif)
- constraint._private.notification = setmetatable({notif}, {__mode = "v"})
- local s = false
-
- if notif.width and notif.width ~= beautiful.notification_max_width then
- constraint.width = notif.width
- s = true
- end
- if notif.height then
- constraint.height = notif.height
- s = true
- end
-
- constraint.strategy = s and "exact" or "max"
- end)
-
- rawset(constraint, "get_notification", function()
- return constraint._private.notification[1]
- end)
-
- return constraint
-end
-
--- It is not worth doing a special widget for this either.
-local function notif_margins()
- local margins = wibox.container.margin()
- margins:set_margins(beautiful.notification_margin or 4)
-
- rawset(margins, "set_notification", function(_, notif)
- if notif.margin then
- margins:set_margins(notif.margin)
- end
- end)
-
- return margins
-end
-
--- Used as a fallback when no widget_template is provided, emulate the legacy
--- widget.
-return {
- {
- {
- {
- {
- wicon,
- {
- widget = wibox.container.place,
- valign = "center",
- halign = "center",
- {
- wtitle,
- wmessage,
- -- spacing = 4,
- layout = wibox.layout.fixed.vertical,
- }
- },
- fill_space = true,
- -- spacing = 4,
- layout = wibox.layout.fixed.horizontal
- },
- actionlist,
- -- spacing = 10,
- layout = wibox.layout.fixed.vertical,
- },
- widget = notif_margins,
- },
- id = "background_role",
- widget = wbg,
- },
- widget = notif_size,
-}
diff --git a/.config/awesome/ui/wicked/init.lua b/.config/awesome/ui/wicked/init.lua
index 76d77cf..ddbf912 100644
--- a/.config/awesome/ui/wicked/init.lua
+++ b/.config/awesome/ui/wicked/init.lua
@@ -1,97 +1,203 @@
local awful = require "awful"
-local debug = require "gears.debug"
-local default = require "ui.wicked._default"
-local gtimer = require "gears.timer"
+local beautiful = require "beautiful"
+local gshape = require "gears.shape"
local naughty = require "naughty"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
--- local rubato = require "lib.rubato"
local wibox = require "wibox"
+local rtimed = require("lib.rubato").timed
+local easing = require("lib.rubato").easing
+local gtimer = require "gears.timer"
+local qmarkup = require "quarrel.markup"
-local wicked = {}
+return function(n)
+ local intertext_margin = (n.title ~= "" or n.message ~= "") and qvars.padding or 0
+ local title_height = n.title ~= "" and qvars.char_height or 0
+ local message_height = n.message ~= "" and qvars.char_height or 0
+ -- local app_name_height = n.app_name ~= "" and
+ local app_name
+ if n.app_name == "" then
+ app_name = n._private._foreign and "Unknown" or "Awesome"
+ else
+ app_name = n.app_name
+ end
-wicked._active_notififcations = {}
+ local notif = naughty.layout.box {
+ notification = n,
+ placement = function(d)
+ return awful.placement.right(d, {
+ margins = beautiful.useless_gap * 2,
+ })
+ end,
+ bg = qvars.colors.transparent,
+ border_width = 0,
+ shape = gshape.rectangle,
+ widget_template = {
+ widget = wibox.container.constraint,
+ height = qvars.big_padding * 2
+ + qvars.char_height
+ + qvars.border_width
+ + qvars.big_padding * 2
+ -- + title_height
+ -- + message_height
+ -- + intertext_margin,
+ + (
+ n.icon and qvars.char_height * 2 + qvars.padding
+ or (title_height + message_height + intertext_margin)
+ ),
-function wicked:notify(n)
- -- local notif = wibox.widget {
- local notif = qui.popup {
- -- widget = {
- -- {
- -- {
- -- widget = naughty.widget.icon,
- -- notification = n,
- -- forced_height = 0,
- -- forced_width = 0,
- -- clip_shape = qvars.shape,
- -- id = "icon_role"
- -- },
- -- {
- -- {
- -- widget = naughty.widget.title,
- -- notification = n
- -- },
- -- {
- -- widget = naughty.widget.message,
- -- notification = n
- -- },
- -- layout = wibox.layout.fixed.vertical
- -- },
- -- layout = wibox.layout.fixed.horizontal,
- -- spacing = qvars.padding
- -- },
- -- widget = wibox.container.margin,
- -- margins = qvars.padding
- -- },
- widget = {
- -- {
- {
- widget = naughty.widget.icon,
- notification = n
- },
- {
- widget = wibox.container.place,
- valign = "center",
- halign = "center",
+ strategy = "exact",
+ {
+ qui.styled {
+ widget = wibox.container.background,
+ point = function(geo, args)
+ return {
+ x = args.parent.width,
+ y = args.parent.height - geo.height,
+ }
+ end,
{
{
- widget = naughty.widget.title,
- notification = n
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ {
+ {
+ widget = wibox.widget.textbox,
+ markup = qmarkup(app_name, { bold = true }),
+ },
+ nil,
+ {
+
+ widget = wibox.container.radialprogressbar,
+ max_value = qvars.notif_timeout,
+ border_color = qvars.colors.black,
+ color = qvars.colors.yellow,
+ border_width = qvars.border_width,
+ forced_height = qvars.char_height,
+ forced_width = qvars.char_height,
+ id = "progress",
+ },
+ layout = wibox.layout.align.horizontal,
+ },
},
{
- widget = naughty.widget.message,
- notification = n
+ widget = wibox.container.constraint,
+ height = qvars.border_width,
+ width = beautiful.notification_max_width,
+ strategy = "exact",
+ {
+ widget = wibox.container.background,
+ bg = qvars.colors.bright.black,
+ },
},
- -- spacing = 4,
- layout = wibox.layout.fixed.vertical,
- }
+ {
+ widget = wibox.container.margin,
+ margins = qvars.big_padding,
+ {
+ widget = wibox.container.constraint,
+ height = n.icon and qvars.char_height * 2 + qvars.padding
+ or (title_height + message_height + intertext_margin),
+ strategy = "exact",
+ {
+ {
+ widget = wibox.container.background,
+ {
+ widget = naughty.widget.icon,
+ shape = qvars.shape,
+ notification = n,
+ },
+ },
+ {
+ {
+ widget = wibox.container.constraint,
+ height = title_height,
+ strategy = "exact",
+ {
+ widget = wibox.widget.textbox,
+ text = n.title or "",
+ },
+ },
+ {
+ widget = wibox.container.constraint,
+ height = message_height,
+ strategy = "exact",
+ {
+ widget = wibox.widget.textbox,
+ text = n.message or "",
+ },
+ },
+ spacing = intertext_margin,
+ layout = wibox.layout.fixed.vertical,
+ },
+ fill_space = true,
+ spacing = n.icon and qvars.big_padding or nil,
+ layout = wibox.layout.fixed.horizontal,
+ },
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ },
+ id = "bg",
},
- fill_space = true,
- -- spacing = 4,
- layout = wibox.layout.fixed.horizontal
- -- },
- -- actionlist,
- -- spacing = 10,
- -- layout = wibox.layout.fixed.vertical,
+ layout = wibox.layout.manual,
+ id = "manual",
+ },
},
- placement = awful.placement.centered,
- ontop = true
}
- gtimer {
- timeout = qvars.notif_timeout,
- autostart = true,
- callback = function()
- notif.visible = false
- notif = nil
- end
+ local hiding = false
+ local old_destroy = notif._private.destroy_callback
+
+ local progress = rtimed {
+ duration = n.timeout,
+ pos = 0,
+ easing = easing.none,
+ clamp_position = true,
+ subscribed = function(pos)
+ notif.widget:get_children_by_id("progress")[1].value = pos
+ end,
+ }
+
+ local position = rtimed {
+ duration = qvars.anim_duration * 2,
+ intro = qvars.anim_intro * 2,
+ pos = 0,
+ easing = easing.quadratic,
+ clamp_position = true,
+ subscribed = function(pos)
+ gtimer.delayed_call(function()
+ notif.widget.widget:move(1, function(geo, args)
+ if pos == 0 and hiding then
+ old_destroy()
+ end
+ return {
+ x = args.parent.width - pos,
+ y = args.parent.height - geo.height,
+ }
+ end)
+ end)
+ end,
+ }
+ local opacity = rtimed {
+ duration = qvars.anim_duration * 2,
+ intro = qvars.anim_intro * 2,
+ easing = easing.quadratic,
+ pos = 0,
+ clamp_position = true,
+ subscribed = function(pos)
+ notif.opacity = pos
+ end,
}
- -- local icon = notif.widget:get_children_by_id("icon_role")[1]
+ n:disconnect_signal("destroyed", notif._private.destroy_callback)
+ function notif._private.destroy_callback()
+ opacity.target = 0
+ position.target = 0
+ hiding = true
+ end
+ n:weak_connect_signal("destroyed", notif._private.destroy_callback)
- -- if n.image then
- -- icon.forced_height = dpi(32)
- -- icon.forced_width = dpi(32)
- -- end
+ opacity.target = 1
+ position.target = qvars.char_width * 48
+ progress.target = qvars.notif_timeout
end
-
-return wicked
diff --git a/.config/awesome/ui/wicked/widgets/message.lua b/.config/awesome/ui/wicked/widgets/message.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.config/awesome/ui/wicked/widgets/message.lua