aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/ui/statusbar
diff options
context:
space:
mode:
authordelta <darkussdelta@gmail.com>2025-07-04 00:38:29 +0200
committerdelta <darkussdelta@gmail.com>2025-07-04 00:38:29 +0200
commitb3530d7c4a102935fa26498a160ee1dc6c1e9c03 (patch)
treed7751206a694bc5de2d6b34b0c077cfcd1855798 /.config/awesome/ui/statusbar
parentdf75ec5ed5e3848c497f0439acb43ec9246ad3e7 (diff)
:3
Diffstat (limited to '.config/awesome/ui/statusbar')
-rw-r--r--.config/awesome/ui/statusbar/consts.lua8
-rw-r--r--.config/awesome/ui/statusbar/init.lua68
-rw-r--r--.config/awesome/ui/statusbar/panel/init.lua76
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/battery.lua1
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/calendar.lua172
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/displays.lua78
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/imagebox.lua720
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/mpris.lua429
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/music.old.lua (renamed from .config/awesome/ui/statusbar/panel/widgets/music.lua)35
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/power_menu.lua16
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/weather.lua0
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/wifi.lua27
-rw-r--r--.config/awesome/ui/statusbar/widgets/displays.lua24
-rw-r--r--.config/awesome/ui/statusbar/widgets/taglist.lua32
-rw-r--r--.config/awesome/ui/statusbar/widgets/taglist_new.lua147
-rw-r--r--.config/awesome/ui/statusbar/widgets/tasklist.lua30
16 files changed, 893 insertions, 970 deletions
diff --git a/.config/awesome/ui/statusbar/consts.lua b/.config/awesome/ui/statusbar/consts.lua
new file mode 100644
index 0000000..00d01bf
--- /dev/null
+++ b/.config/awesome/ui/statusbar/consts.lua
@@ -0,0 +1,8 @@
+local qui = require "quarrel.ui"
+local C = {}
+
+C.BAR_SIZE = 24 + qui.BIG_PADDING * 2
+C.ELEMENT_SIZE = 12
+C.EXPANDED_BAR_SIZE = qui.BIG_PADDING + (qui.BIG_PADDING * 2 + C.ELEMENT_SIZE * 4) * 4 + qui.PADDING * 2
+
+return C
diff --git a/.config/awesome/ui/statusbar/init.lua b/.config/awesome/ui/statusbar/init.lua
index 77a28f7..137ffb8 100644
--- a/.config/awesome/ui/statusbar/init.lua
+++ b/.config/awesome/ui/statusbar/init.lua
@@ -1,18 +1,17 @@
local awful = require "awful"
local beautiful = require "beautiful"
local panel = require "ui.statusbar.panel"
-local phosphor = require "assets.phosphor"
-local qstore = require "quarrel.store"
+local qanim = require "quarrel.animation"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
-local rubato = require "lib.rubato"
local wibox = require "wibox"
+local M = require "ui.statusbar.consts"
+
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"
+local taglist = require "ui.statusbar.widgets.taglist_new"
screen.connect_signal("request::desktop_decoration", function(s)
local bar = qui.popup {
@@ -21,17 +20,16 @@ screen.connect_signal("request::desktop_decoration", function(s)
margins = beautiful.useless_gap * 2,
})
end,
- minimum_height = s.geometry.height - (beautiful.useless_gap * 4 + qvars.border_width * 2),
+ minimum_height = s.geometry.height - (beautiful.useless_gap * 4 + qui.BORDER_WIDTH * 2),
widget = {
{
{
taglist(s),
layout = wibox.layout.fixed.vertical,
- spacing = qvars.padding * 2,
+ spacing = qui.PADDING * 2,
id = "top",
},
nil,
- -- tasklist(s),
{
widget = wibox.container.place,
valign = "bottom",
@@ -44,14 +42,14 @@ screen.connect_signal("request::desktop_decoration", function(s)
widget = wibox.container.place,
{
widget = wibox.container.constraint,
- height = qvars.char_height,
- width = qvars.char_height,
+ height = qui.CHAR_HEIGHT,
+ width = qui.CHAR_HEIGHT,
keyboardlayout,
},
},
clock,
layout = wibox.layout.fixed.vertical,
- spacing = qvars.padding * 2,
+ spacing = qui.PADDING * 2,
},
},
layout = wibox.layout.align.vertical,
@@ -61,51 +59,47 @@ screen.connect_signal("request::desktop_decoration", function(s)
nil,
layout = wibox.layout.align.horizontal,
},
+
+ toggled = false,
}
- local bar_width = bar.width + qvars.border_width * 2
+ local bar_width = bar.width + qui.BORDER_WIDTH * 2
+
+ bar.shape = function(cr, _, h)
+ qui.shape(cr, bar_width, h)
+ end
bar:struts {
left = bar_width + beautiful.useless_gap * 4,
}
- local panel_width
- local panel_toggle = { toggled = false } -- hacky but it works
+ bar.widget.widget.third = panel
- local timed = rubato.timed {
+ local timed = qanim:new {
duration = qvars.anim_duration,
- intro = qvars.anim_intro,
pos = bar_width,
+ easing = qvars.easing,
subscribed = function(pos)
- 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
+ if pos ~= bar_width and bar.toggled then
bar.ontop = true
- elseif pos == bar_width and not panel_toggle.toggled then
- bar.widget.widget.third = nil
+ elseif pos == bar_width and not bar.toggled then
bar.ontop = false
end
bar.shape = function(cr, _, h)
- qvars.shape(cr, pos, h)
+ qui.shape(cr, pos, h)
end
end,
}
- 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,
- }
+ function bar:toggle()
+ self.toggled = not self.toggled
+ if self.toggled then
+ timed:set(bar_width + M.EXPANDED_BAR_SIZE)
+ else
+ timed:set(bar_width)
+ end
+ end
- bar.widget:get_children_by_id("top")[1]:insert(1, panel_toggle)
- qstore.panel_toggle = panel_toggle
+ s.bar = bar
end)
diff --git a/.config/awesome/ui/statusbar/panel/init.lua b/.config/awesome/ui/statusbar/panel/init.lua
index 31c2860..814a5a1 100644
--- a/.config/awesome/ui/statusbar/panel/init.lua
+++ b/.config/awesome/ui/statusbar/panel/init.lua
@@ -1,51 +1,61 @@
-local qvars = require "quarrel.vars"
+local C = require "ui.statusbar.consts"
+local qui = require "quarrel.ui"
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"
+local music = require "ui.statusbar.panel.widgets.mpris"
local wifi = require "ui.statusbar.panel.widgets.wifi"
local panel = wibox.widget {
- widget = wibox.container.margin,
- margins = {
- left = qvars.big_padding,
- },
+ widget = wibox.container.constraint,
+ strategy = "max",
+ width = C.EXPANDED_BAR_SIZE,
+ -- visible = false,
{
+ widget = wibox.container.background,
{
- widget = wibox.container.place,
- valign = "top",
+ widget = wibox.container.margin,
+ margins = {
+ left = qui.BIG_PADDING,
+ },
{
{
- displays.battery,
- displays.audio,
- displays.brightness,
- layout = wibox.layout.fixed.horizontal,
- spacing = qvars.padding,
+ widget = wibox.container.place,
+ valign = "top",
+ {
+ {
+ displays.battery,
+ displays.audio,
+ -- displays.brightness,
+ -- displays.brightness,
+ layout = wibox.layout.flex.horizontal,
+ spacing = qui.PADDING,
+ },
+ wifi,
+ -- battery,
+ music.widget,
+ calendar,
+ layout = wibox.layout.fixed.vertical,
+ spacing = qui.PADDING,
+ },
},
- wifi,
- -- battery,
- -- music,
- calendar,
- layout = wibox.layout.fixed.vertical,
- spacing = qvars.padding,
- },
- },
- {
- widget = wibox.container.background,
- {
- widget = wibox.widget.textbox,
- text = ":)",
+ -- {
+ -- widget = wibox.container.background,
+ -- {
+ -- widget = wibox.widget.textbox,
+ -- text = ":)",
+ -- },
+ -- },
+ -- {
+ -- widget = wibox.container.place,
+ -- valign = "bottom",
+ -- power_menu,
+ -- },
+ layout = wibox.layout.align.vertical,
},
},
- {
- widget = wibox.container.place,
- valign = "bottom",
- power_menu,
- },
- layout = wibox.layout.align.vertical,
},
}
diff --git a/.config/awesome/ui/statusbar/panel/widgets/battery.lua b/.config/awesome/ui/statusbar/panel/widgets/battery.lua
index 52685b7..52cf5da 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/battery.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/battery.lua
@@ -1,6 +1,5 @@
local gears = require "gears"
local lit = require "lib.lit"
-local qbezier = require "quarrel.bezier"
local qui = require "quarrel.ui"
local wibox = require "wibox"
diff --git a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
index 8933543..ddbffc0 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
@@ -1,58 +1,123 @@
local awful = require "awful"
local phosphor = require "assets.phosphor"
local qbind = require "quarrel.bind"
+local qcolor = require "quarrel.color"
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,
+ bg = qcolor.palette.bg.high,
{
widget = wibox.container.margin,
- margins = qvars.big_padding,
+ margins = qui.BORDER_WIDTH,
{
{
{
- widget = wibox.container.place,
- qui.icon {
- icon = phosphor.caret_left_bold,
+ layout = wibox.layout.grid,
+ forced_num_rows = 7,
+ forced_num_cols = 7,
+ -- spacing = (qui.PADDING) / 2,
+ border_width = {
+ inner = qui.BORDER_WIDTH,
+ outer = 0,
},
+ border_color = qcolor.palette.border.variant,
+ id = "grid",
},
{
- widget = wibox.container.place,
- {
- widget = wibox.widget.textbox,
- text = "January 2024",
- },
+ widget = wibox.container.background,
+ bg = qcolor.palette.border(),
+ forced_width = qui.BORDER_WIDTH,
},
+ layout = wibox.layout.fixed.horizontal,
+ },
+ {
+ widget = wibox.container.margin,
+ margins = qui.BIG_PADDING,
{
- widget = wibox.container.place,
- qui.icon {
- icon = phosphor.caret_right_bold,
+ {
+ widget = wibox.container.place,
+ fill_horizontal = true,
+ {
+ widget = wibox.widget.textbox,
+ text = "05\n25",
+ },
},
+ nil,
+ qui.styled {
+ widget = wibox.container.background,
+ bg = qcolor.palette.bg.highest,
+ {
+ {
+ widget = wibox.container.margin,
+ margins = qui.PADDING,
+ {
+ widget = wibox.container.place,
+ qui.icon {
+ icon = phosphor.caret_up_bold,
+ widget = {
+ forced_height = qui.CHAR_HEIGHT / 2,
+ forced_width = qui.CHAR_HEIGHT / 2,
+ },
+ },
+ },
+ },
+ {
+ widget = wibox.container.background,
+ bg = qcolor.palette.border.variant,
+ forced_height = qui.BORDER_WIDTH,
+ },
+ {
+ widget = wibox.container.margin,
+ margins = qui.PADDING,
+ {
+ widget = wibox.container.place,
+ qui.icon {
+ icon = phosphor.caret_down_bold,
+ widget = {
+ forced_height = qui.CHAR_HEIGHT / 2,
+ forced_width = qui.CHAR_HEIGHT / 2,
+ },
+ },
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ -- spacing = qui.PADDING
+ },
+ },
+ layout = wibox.layout.align.vertical,
},
- 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,
+ layout = wibox.layout.fixed.horizontal,
},
},
})
+local grid = calendar:get_children_by_id("grid")[1]
+
-- 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 calendar_table = {
+ {
+ { "Mo", false, true },
+ { "Tu", false, true },
+ { "We", false, true },
+ { "Th", false, true },
+ { "Fr", false, true },
+ { "Sa", false, true },
+ { "Su", false, true },
+ },
+ {},
+ {},
+ {},
+ {},
+ {},
+ {},
+ }
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 })
@@ -68,14 +133,14 @@ function calendar:compute_grid(year, month)
for offset = prev_offset, 1, -1 do
local day = prev_days.day - offset + 1
table.insert(
- calendar_table[1],
+ calendar_table[2],
{ day, day == current.day and prev_month == current.month and prev_year == current.year, false }
)
end
end
do
- local row = 1
+ local row = 2
local weekday = weekday_map[first_day.wday]
for day = 1, days do
table.insert(
@@ -108,14 +173,22 @@ function calendar:compute_grid(year, month)
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]
+ local widget = grid:get_widgets_at(i, j)[1]
+ widget.widget.widget.widget.text = col[1]
if col[2] then
- widget.bg = qvars.colors.yellow
- widget.fg = qvars.colors.bg
+ widget.bg = qcolor.palette.yellow()
+ widget.fg = qcolor.palette.bg()
+ elseif j % 6 == 0 or j % 7 == 0 then
+ widget.bg = col[3] and qcolor.palette.bg.highest or qcolor.palette.bg.high
else
- widget.bg = qvars.colors.bg
- widget.fg = col[3] and qvars.colors.fg or qvars.colors.dim.fg
+ widget.bg = col[3] and qcolor.palette.bg.high or qcolor.palette.bg()
+ end
+
+ if i == 1 then
+ widget.fg = qcolor.palette.fg()
+ elseif not col[2] then
+ -- widget.fg = col[3] and qcolor.palette.fg() or qcolor.palette.fg.low
+ widget.fg = qcolor.palette.fg.low
end
end
end
@@ -125,32 +198,31 @@ local cells = {}
local function cell(content)
local widget = wibox.widget {
widget = wibox.container.background,
- shape = qvars.shape,
+ bg = qcolor.palette.bg.high,
+ -- shape = qui.shape,
{
- widget = wibox.container.place,
- forced_height = qvars.char_height * 1.5,
- forced_width = qvars.char_height * 1.5,
+ widget = wibox.container.margin,
+ margins = qui.PADDING * 1.5,
{
- widget = wibox.widget.textbox,
- markup = content,
+ widget = wibox.container.place,
+ forced_height = qui.CHAR_HEIGHT,
+ forced_width = qui.CHAR_HEIGHT,
+ {
+ 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
+for _ = 1, 49 do
cell()
end
-calendar:get_children_by_id("grid")[1]:add(table.unpack(cells))
-calendar:compute_grid(2024, 1)
+grid:add(table.unpack(cells))
+local current_time = os.date "*t"
+calendar:compute_grid(current_time.year, current_time.month)
+grid:add_row_border(2, qui.BORDER_WIDTH, { color = qcolor.palette.border() })
return calendar
diff --git a/.config/awesome/ui/statusbar/panel/widgets/displays.lua b/.config/awesome/ui/statusbar/panel/widgets/displays.lua
index b52c986..bfb9113 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/displays.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/displays.lua
@@ -1,37 +1,43 @@
-local backlight = require "services.backlight"
+-- local backlight = require "services.backlight"
local battery = require "services.battery"
local phosphor = require "assets.phosphor"
-local qmath = require "quarrel.math"
+-- local qmath = require "quarrel.math"
+local C = require "ui.statusbar.consts"
+local qcolor = require "quarrel.color"
local qui = require "quarrel.ui"
-local qvars = require "quarrel.vars"
local wibox = require "wibox"
local function create_display(icon, color)
+ -- the reason this is done is because ids can't be found with `get_children_by_id` across widget boundaries,
+ -- so we return it as a second value in order to manipulate the icon
+ local d_icon = qui.icon {
+ icon = icon,
+ color = color,
+ widget = {
+ id = "icon",
+ },
+ }
+
return wibox.widget(qui.styled {
widget = wibox.container.background,
+ bg = qcolor.palette.bg.high,
{
widget = wibox.container.margin,
- margins = qvars.big_padding,
+ margins = qui.BIG_PADDING,
{
widget = wibox.container.place,
{
{
widget = wibox.container.radialprogressbar,
max_value = 100,
- border_color = qvars.colors.black,
+ border_color = qcolor.palette.bg.lowest,
color = color,
- border_width = qvars.border_width * 2,
- forced_height = qvars.element_size * 4,
- forced_width = qvars.element_size * 4,
+ border_width = qui.BORDER_WIDTH * 2,
+ forced_height = C.ELEMENT_SIZE * 4,
+ forced_width = C.ELEMENT_SIZE * 4,
{
widget = wibox.container.place,
- qui.icon {
- icon = icon,
- color = color,
- widget = {
- id = "icon",
- },
- },
+ d_icon,
},
id = "indicator",
},
@@ -44,14 +50,15 @@ local function create_display(icon, color)
},
},
layout = wibox.layout.fixed.vertical,
- spacing = qvars.big_padding,
+ spacing = qui.BIG_PADDING,
},
},
},
- })
+ }),
+ d_icon
end
-local d_audio = create_display(phosphor.speaker_simple_high_fill, qvars.colors.fg)
+local d_audio, d_audio_icon = create_display(phosphor.speaker_simple_high_fill, qcolor.palette.fg())
awesome.connect_signal("services::audio", function(volume)
if not volume then
return
@@ -61,30 +68,33 @@ awesome.connect_signal("services::audio", function(volume)
end)
awesome.connect_signal("services::audio::icon", function(icon, color)
d_audio:get_children_by_id("indicator")[1].color = color
- d_audio:get_children_by_id("icon")[1].image = icon
- d_audio:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
+ d_audio_icon.image = icon
+ d_audio_icon.stylesheet = qui.recolor(color)
end)
-local d_battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
+local d_battery, d_battery_icon = create_display(phosphor.battery_vertical_warning_fill, qcolor.palette.red())
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)
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)
+ d_battery_icon.image = icon
+ d_battery_icon.stylesheet = qui.recolor(color)
end)
-local d_brightness = create_display(phosphor.sun_fill, qvars.colors.fg)
-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)
-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)
+-- local d_brightness, d_brightness_icon = create_display(phosphor.sun_fill, qcolor.palette.fg())
+-- 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)
+-- backlight:connect_signal("icon", function(_, icon, color)
+-- d_brightness_icon.image = icon
+-- d_brightness_icon.stylesheet = qui.recolor(color)
+-- end)
-return { audio = d_audio, battery = d_battery, brightness = d_brightness }
+return {
+ audio = d_audio,
+ battery = d_battery, --[[brightness = d_brightness]]
+}
diff --git a/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua b/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
deleted file mode 100644
index 5caadc5..0000000
--- a/.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
+++ /dev/null
@@ -1,720 +0,0 @@
----------------------------------------------------------------------------
--- A widget to display an image.
---
--- The `wibox.widget.imagebox` is part of the Awesome WM's widget system
--- (see @{03-declarative-layout.md}).
---
--- This widget displays an image. The image can be a file,
--- a cairo image surface, or an rsvg handle object (see the
--- [image property](#image)).
---
--- Examples using a `wibox.widget.imagebox`:
--- ---
---
--- @DOC_wibox_widget_defaults_imagebox_EXAMPLE@
---
--- Alternatively, you can declare the `imagebox` widget using the
--- declarative pattern (both variants are strictly equivalent):
---
--- @DOC_wibox_widget_declarative-pattern_imagebox_EXAMPLE@
---
--- @author Uli Schlachter
--- @copyright 2010 Uli Schlachter
--- @widgetmod wibox.widget.imagebox
--- @supermodule wibox.widget.base
----------------------------------------------------------------------------
-
-local lgi = require "lgi"
-local cairo = lgi.cairo
-
-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
-
-local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
-
--- Safe load for optional Rsvg module
-local Rsvg = nil
-do
- 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
-end
-
-local imagebox = { mt = {} }
-
-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
-
- local cache = (rsvg_handle_cache[file] or {})["handle"]
-
- if cache then
- return cache, rsvg_handle_cache[file]
- end
-
- local handle, err
-
- 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)
- end
-
- if not err then
- rsvg_handle_cache[file] = rsvg_handle_cache[file] or {}
- rsvg_handle_cache[file]["handle"] = handle
- return handle, rsvg_handle_cache[file]
- end
-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
-
- ib._private.default = { width = surf.width, height = surf.height }
- ib._private.handle = nil
- ib._private.image = surf
- return true
-end
-
----Apply RsvgHandle for given imagebox widget
-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
-
- ib._private.default = { width = dim.width, height = dim.height }
- ib._private.handle = handle
- ib._private.cache = cache
- ib._private.image = nil
-
- return true
-end
-
----Try to load some image object from file then apply it to imagebox.
----@tparam table ib Imagebox
----@tparam string file Image file name
----@tparam function image_loader Function to load image object from file
----@tparam function image_setter Function to set image object to imagebox
----@treturn boolean True if image was successfully applied
-local function load_and_apply(ib, file, image_loader, image_setter)
- local image_applied
- local object, cache = image_loader(file)
-
- if object then
- image_applied = image_setter(ib, object, cache)
- end
- return image_applied
-end
-
----Update the cached size depending on the stylesheet and dpi.
---
--- 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
-
- 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_style = self._private.handle.set_stylesheet and self._private.stylesheet
-
- local old_size = self._private.default and self._private.default.width
-
- if dpi and dpi ~= self._private.cache.dpi then
- if type(dpi) == "table" then
- self._private.handle:set_dpi_x_y(dpi.x, dpi.y)
- else
- self._private.handle:set_dpi(dpi)
- end
- end
-
- if need_style and self._private.cache.stylesheet ~= self._private.stylesheet then
- self._private.handle:set_stylesheet(self._private.stylesheet)
- end
-
- -- Reload the size.
- if need_dpi or (need_style and self._private.stylesheet ~= self._private.last_stylesheet) then
- set_handle(self, self._private.handle, self._private.cache)
- end
-
- self._private.last_dpi = dpi
- self._private.cache.dpi = dpi
- self._private.last_stylesheet = self._private.stylesheet
- self._private.cache.stylesheet = self._private.stylesheet
-
- -- 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"
- 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
-
- -- For valign = "top" and halign = "left"
- local translate = {
- x = 0,
- y = 0,
- }
-
- update_dpi(self, ctx)
-
- local w, h = self._private.default.width, self._private.default.height
-
- if self._private.resize then
- -- That's for the "fit" policy.
- local aspects = {
- w = width / w,
- h = height / h,
- }
-
- local policy = {
- w = self._private.horizontal_fit_policy or "auto",
- h = self._private.vertical_fit_policy or "auto",
- }
-
- 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
- aspects[aspect] = 1
- elseif policy[aspect] == "none" then
- aspects[aspect] = 1
- elseif policy[aspect] == "auto" then
- aspects[aspect] = math.min(width / w, height / h)
- elseif policy[aspect] == "cover" then
- aspects[aspect] = math.max(width / w, height / h)
- end
- end
-
- if self._private.halign == "center" then
- translate.x = math.floor((width - w * aspects.w) / 2)
- elseif self._private.halign == "right" then
- translate.x = math.floor(width - (w * aspects.w))
- end
-
- if self._private.valign == "center" then
- translate.y = math.floor((height - h * aspects.h) / 2)
- elseif self._private.valign == "bottom" then
- translate.y = math.floor(height - (h * aspects.h))
- end
-
- cr:translate(translate.x, translate.y)
-
- -- Before using the scale, make sure it is below the threshold.
- 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
- 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)))
- end
-
- cr:scale(aspects.w, aspects.h)
- else
- if self._private.halign == "center" then
- 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)
- elseif self._private.valign == "bottom" then
- translate.y = math.floor(height - h)
- end
-
- cr:translate(translate.x, translate.y)
-
- -- Set the clip
- if self._private.clip_shape then
- cr:clip(self._private.clip_shape(cr, w, h, unpack(self._private.clip_args)))
- end
- end
-
- if self._private.handle then
- self._private.handle:render_cairo(cr)
- else
- cr:set_source_surface(self._private.image, 0, 0)
-
- local filter = self._private.scaling_quality
-
- if filter then
- cr:get_source():set_filter(cairo.Filter[filter:upper()])
- end
-
- cr:paint()
- end
-end
-
--- Fit the imagebox into the given geometry
-function imagebox:fit(ctx, width, height)
- if not self._private.default then
- return 0, 0
- end
-
- update_dpi(self, ctx)
-
- local w, h = self._private.default.width, self._private.default.height
-
- if w <= width and h <= height and self._private.upscale == false then
- return w, h
- end
-
- if (w < width or h < height) and self._private.downscale == false then
- return w, h
- end
-
- if self._private.resize or w > width or h > height then
- local aspect = math.min(width / w, height / h)
- return w * aspect, h * aspect
- end
-
- return w, h
-end
-
---- The image rendered by the `imagebox`.
---
--- @property image
--- @tparam[opt=nil] image|nil image
--- @propemits false false
-
---- Set the `imagebox` image.
---
--- The image can be a file, a cairo image surface, or an rsvg handle object
--- (see the [image property](#image)).
--- @method set_image
--- @hidden
--- @tparam image image The image to render.
--- @treturn boolean `true` on success, `false` if the image cannot be used.
--- @usage my_imagebox:set_image(beautiful.awesome_icon)
--- @usage my_imagebox:set_image('/usr/share/icons/theme/my_icon.png')
--- @see image
-function imagebox:set_image(image)
- local setup_succeed
-
- -- Keep the original to prevent the cache from being GCed.
- self._private.original_image = image
-
- if type(image) == "userdata" and not (Rsvg and Rsvg.Handle:is_type_of(image)) then
- -- This function is not documented to handle userdata objects, but
- -- historically it did, and it did by just assuming they refer to a
- -- cairo surface.
- image = surface.load(image)
- end
-
- if type(image) == "string" then
- -- try to load rsvg handle from file
- setup_succeed = load_and_apply(self, image, load_rsvg_handle, set_handle)
-
- if not setup_succeed then
- -- rsvg handle failed, try to load cairo surface with pixbuf
- setup_succeed = load_and_apply(self, image, surface.load, set_surface)
- end
- elseif Rsvg and Rsvg.Handle:is_type_of(image) then
- -- try to apply given rsvg handle
- rsvg_handle_cache[image] = rsvg_handle_cache[image] or {}
- setup_succeed = set_handle(self, image, rsvg_handle_cache[image])
- elseif cairo.Surface:is_type_of(image) then
- -- try to apply given cairo surface
- setup_succeed = set_surface(self, image)
- elseif not image then
- -- nil as argument mean full imagebox reset
- setup_succeed = true
- self._private.handle = nil
- self._private.image = nil
- self._private.default = nil
- 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"
- return true
-end
-
---- Set a clip shape for this imagebox.
---
--- A clip shape defines an area and dimension to which the content should be
--- trimmed.
---
--- @DOC_wibox_widget_imagebox_clip_shape_EXAMPLE@
---
--- @property clip_shape
--- @tparam[opt=gears.shape.rectangle] shape clip_shape A `gears.shape` compatible shape function.
--- @propemits true false
--- @see gears.shape
-
---- Set a clip shape for this imagebox.
---
--- A clip shape defines an area and dimensions to which the content should be
--- trimmed.
---
--- Additional parameters will be passed to the clip shape function.
---
--- @tparam function|gears.shape clip_shape A `gears_shape` compatible shape function.
--- @method set_clip_shape
--- @hidden
--- @see gears.shape
--- @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:emit_signal("property::clip_shape", clip_shape)
-end
-
---- Should the image be resized to fit into the available space?
---
--- Note that `upscale` and `downscale` can affect the value of `resize`.
--- If conflicting values are passed to the constructor, then the result
--- is undefined.
---
--- @DOC_wibox_widget_imagebox_resize_EXAMPLE@
--- @property resize
--- @propemits true false
--- @tparam[opt=true] boolean resize
-
---- Allow the image to be upscaled (made bigger).
---
--- Note that `upscale` and `downscale` can affect the value of `resize`.
--- If conflicting values are passed to the constructor, then the result
--- is undefined.
---
--- @DOC_wibox_widget_imagebox_upscale_EXAMPLE@
--- @property upscale
--- @tparam[opt=self.resize] boolean upscale
--- @see downscale
--- @see resize
-
---- Allow the image to be downscaled (made smaller).
---
--- Note that `upscale` and `downscale` can affect the value of `resize`.
--- If conflicting values are passed to the constructor, then the result
--- is undefined.
---
--- @DOC_wibox_widget_imagebox_downscale_EXAMPLE@
--- @property downscale
--- @tparam[opt=self.resize] boolean downscale
--- @see upscale
--- @see resize
-
---- Set the SVG CSS stylesheet.
---
--- If the image is an SVG (vector graphics), this property allows to set
--- a CSS stylesheet. It can be used to set colors and much more.
---
--- Note that this property is a string, not a path. If the stylesheet is
--- stored on disk, read the content first.
---
---@DOC_wibox_widget_imagebox_stylesheet_EXAMPLE@
---
--- @property stylesheet
--- @tparam[opt=""] string stylesheet
--- @propemits true false
-
---- Set the SVG DPI (dot per inch).
---
--- Force a specific DPI when rendering the `.svg`. For other file formats,
--- this does nothing.
---
--- It can either be a number of a table containing the `x` and `y` keys.
---
--- Please note that DPI and `resize` can "fight" each other and end up
--- making the image smaller instead of bigger.
---
---@DOC_wibox_widget_imagebox_dpi_EXAMPLE@
---
--- @property dpi
--- @tparam[opt=96] number|table dpi
--- @negativeallowed false
--- @propemits true false
--- @see auto_dpi
-
---- Use the object DPI when rendering the SVG.
---
--- By default, the SVG are interpreted as-is. When this property is set,
--- the screen DPI will be passed to the SVG renderer. Depending on which
--- tool was used to create the `.svg`, this may do nothing at all. However,
--- for example, if the `.svg` uses `<text>` elements and doesn't have an
--- hardcoded stylesheet, the result will differ.
---
--- @property auto_dpi
--- @tparam[opt=false] boolean auto_dpi
--- @propemits true false
--- @see dpi
-
-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("property::" .. prop)
- end
-end
-
-function imagebox:set_resize(allowed)
- self._private.resize = allowed
-
- if allowed then
- self._private.downscale = true
- self._private.upscale = true
- self:emit_signal("property::downscale", allowed)
- self:emit_signal("property::upscale", allowed)
- end
-
- 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
- imagebox["set_" .. prop] = function(self, allowed)
- self._private[prop] = allowed
-
- if self._private.resize ~= (self._private.upscale or self._private.downscale) then
- self._private.resize = self._private.upscale or self._private.downscale
- 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)
- end
-end
-
---- Set the horizontal fit policy.
---
--- Here is the result for a 22x32 image:
---
--- @DOC_wibox_widget_imagebox_horizontal_fit_policy_EXAMPLE@
---
--- @property horizontal_fit_policy
--- @tparam[opt="auto"] string horizontal_fit_policy
--- @propertyvalue "auto" Honor the `resize` variable and preserve the aspect ratio.
--- @propertyvalue "none" Do not resize at all.
--- @propertyvalue "fit" Resize to the widget width.
--- @propertyvalue "cover" Resize to fill widget and preserve the aspect ratio.
--- @propemits true false
--- @see vertical_fit_policy
--- @see resize
-
---- Set the vertical fit policy.
---
--- Here is the result for a 32x22 image:
---
--- @DOC_wibox_widget_imagebox_vertical_fit_policy_EXAMPLE@
---
--- @property vertical_fit_policy
--- @tparam[opt="auto"] string vertical_fit_policy
--- @propertyvalue "auto" Honor the `resize` variable and preserve the aspect ratio.
--- @propertyvalue "none" Do not resize at all.
--- @propertyvalue "fit" Resize to the widget height.
--- @propertyvalue "cover" Resize to fill widget and preserve the aspect ratio.
--- @propemits true false
--- @see horizontal_fit_policy
--- @see resize
-
---- The vertical alignment.
---
--- @DOC_wibox_widget_imagebox_valign_EXAMPLE@
---
--- @property valign
--- @tparam[opt="center"] string valign
--- @propertyvalue "top"
--- @propertyvalue "center"
--- @propertyvalue "bottom"
--- @propemits true false
--- @see wibox.container.place
--- @see halign
-
---- The horizontal alignment.
---
--- @DOC_wibox_widget_imagebox_halign_EXAMPLE@
---
--- @property halign
--- @tparam[opt="center"] string halign
--- @propertyvalue "left"
--- @propertyvalue "center"
--- @propertyvalue "right"
--- @propemits true false
--- @see wibox.container.place
--- @see valign
-
---- The maximum scaling factor.
---
--- If an image is scaled too much, it gets very blurry. This
--- property allows to limit the scaling.
--- Use the properties `valign` and `halign` to control how the image will be
--- aligned.
---
--- In the example below, the original size is 22x22
---
--- @DOC_wibox_widget_imagebox_max_scaling_factor_EXAMPLE@
---
--- @property max_scaling_factor
--- @tparam[opt=0] number max_scaling_factor Use `0` for "no limit".
--- @negativeallowed false
--- @propemits true false
--- @see valign
--- @see halign
--- @see scaling_quality
-
---- Set the scaling aligorithm.
---
--- Depending on how the image is used, what is the "correct" way to
--- scale can change. For example, upscaling a pixel art image should
--- not make it blurry. However, scaling up a photo should not make it
--- blocky.
---
---<table class='widget_list' border=1>
--- <tr style='font-weight: bold;'>
--- <th align='center'>Value</th>
--- <th align='center'>Description</th>
--- </tr>
--- <tr><td>fast</td><td>A high-performance filter</td></tr>
--- <tr><td>good</td><td>A reasonable-performance filter</td></tr>
--- <tr><td>best</td><td>The highest-quality available</td></tr>
--- <tr><td>nearest</td><td>Nearest-neighbor filtering (blocky)</td></tr>
--- <tr><td>bilinear</td><td>Linear interpolation in two dimensions</td></tr>
---</table>
---
--- The image used in the example below has a resolution of 32x22 and is
--- intentionally blocky to highlight the difference.
--- It is zoomed by a factor of 3.
---
--- @DOC_wibox_widget_imagebox_scaling_quality_EXAMPLE@
---
--- @property scaling_quality
--- @tparam[opt="good"] string scaling_quality
--- @propertyvalue "fast" A high-performance filter.
--- @propertyvalue "good" A reasonable-performance filter.
--- @propertyvalue "best" The highest-quality available.
--- @propertyvalue "nearest" Nearest-neighbor filtering (blocky).
--- @propertyvalue "bilinear" Linear interpolation in two dimensions.
--- @propemits true false
--- @see resize
--- @see horizontal_fit_policy
--- @see vertical_fit_policy
--- @see max_scaling_factor
-
-local defaults = {
- halign = "left",
- valign = "top",
- horizontal_fit_policy = "auto",
- 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
-
- return value
-end
-
-for prop in pairs(defaults) do
- 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])
- end
-
- imagebox["get_" .. prop] = function(self)
- if self._private[prop] == nil then
- return defaults[prop]
- end
-
- return self._private[prop]
- end
-end
-
---- Returns a new `wibox.widget.imagebox` instance.
---
--- This is the constructor of `wibox.widget.imagebox`. It creates a new
--- instance of imagebox widget.
---
--- Alternatively, the declarative layout syntax can handle
--- `wibox.widget.imagebox` instanciation.
---
--- The image can be a file, a cairo image surface, or an rsvg handle object
--- (see the [image property](#image)).
---
--- Any additional arguments will be passed to the clip shape function.
--- @tparam[opt] image image The image to display (may be `nil`).
--- @tparam[opt] boolean resize_allowed If `false`, the image will be
--- clipped, else it will be resized to fit into the available space.
--- @tparam[opt] function clip_shape A `gears.shape` compatible function.
--- @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 })
-
- gtable.crush(ret, imagebox, true)
- ret._private.resize = true
-
- if image then
- ret:set_image(image)
- end
-
- if resize_allowed ~= nil then
- ret.resize = resize_allowed
- end
-
- ret._private.clip_shape = clip_shape
- ret._private.clip_args = { ... }
-
- return ret
-end
-
-function imagebox.mt:__call(...)
- return new(...)
-end
-
-return setmetatable(imagebox, imagebox.mt)
-
--- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
diff --git a/.config/awesome/ui/statusbar/panel/widgets/mpris.lua b/.config/awesome/ui/statusbar/panel/widgets/mpris.lua
new file mode 100644
index 0000000..c27bf66
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/mpris.lua
@@ -0,0 +1,429 @@
+local custom = require "assets.custom"
+local gdebug = require "gears.debug"
+local phosphor = require "assets.phosphor"
+local playerctl = require "services.playerctl"
+local qcolor = require "quarrel.color"
+local qpersistent = require "quarrel.persistent"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local simpleicons = require "assets.simpleicons"
+local wibox = require "wibox"
+
+local M = {}
+
+local client_icons = { -- this is used to map the mpris clients to icons
+ firefox = simpleicons.librewolf, -- librewolf uses the same player id as firefox
+ spotify = simpleicons.spotify,
+ mpd = custom.vinyl_record_fill,
+ __generic = phosphor.waveform_fill, -- used for any client not in the map
+}
+
+local DEFAULTS = {
+ ---@type string
+ title = "Nothing's playing",
+ artist = {},
+ ---@type string
+ album = "",
+ progresstext = {
+ ---@type string
+ position = "~",
+ ---@type string
+ length = "~",
+ },
+ ---@type number
+ position = 0,
+ ---@type number
+ length = math.huge,
+ client_icon = client_icons.__generic,
+ art = phosphor.music_notes_fill,
+}
+
+local bg_icon = qui.icon {
+ icon = DEFAULTS.client_icon,
+ widget = {
+ forced_width = 0,
+ forced_height = 0,
+ },
+ color = qcolor.palette.bg.highest,
+}
+
+local function to_hms(time)
+ local format = "%i:%02i"
+
+ local h = math.floor(time / 60 ^ 2)
+ local m = math.floor((time / 60) % 60)
+ local s = math.floor(time % 60)
+
+ if h > 0 then
+ format = "%i:" .. format
+ return string.format(format, h, m, s)
+ end
+
+ return string.format(format, m, s)
+end
+
+local function is_empty(str)
+ return (str == nil or #str == 0)
+end
+
+--- mirror of playerctl:list()
+--- why bother mirroring? simple: we need to track changes to the player list
+--- but vanished and appeared simply don't give us an old version to compare with
+---@type Playerctl.data[]
+local players = {}
+
+---@type number
+M.active_player_index = qpersistent.get "active_player_index" --[[@as number]]
+if not M.active_player_index then
+ M.active_player_index = 1
+ gdebug.print_error "failed to get active_player_index from qpersistent, falling back..."
+ qpersistent.store("active_player_index", M.active_player_index)
+end
+
+--- the reason we do this instead of some other hack is this is the only way to draw the icons *without* resizing the mpris container
+--- this happens because in the panel, height is unlimited, and imagebox grows until a hard limit
+---@class wibox.widget.base
+local client_background = wibox.container.background()
+
+function client_background:before_draw_children(_, cr, width, height)
+ cr:save()
+ cr:translate(width - (height / 1.25), -(height * 0.125))
+ ---@diagnostic disable-next-line: missing-parameter
+ wibox.widget.draw_to_cairo_context(bg_icon, cr, height * 1.25, height * 1.25)
+ cr:restore()
+end
+
+M.widget = wibox.widget(qui.styled {
+ widget = wibox.container.background,
+ bg = qcolor.palette.bg.high,
+ {
+ widget = client_background,
+ {
+ widget = wibox.container.margin,
+ margins = qui.BIG_PADDING,
+ {
+ nil,
+ {
+ {
+ {
+ widget = wibox.container.background,
+ bg = qcolor.palette.bg(),
+ shape = qui.shape,
+ {
+ widget = wibox.widget.imagebox,
+ image = DEFAULTS.art,
+ forced_height = qui.CHAR_HEIGHT * 5,
+ forced_width = qui.CHAR_HEIGHT * 5,
+ valign = "center",
+ halign = "center",
+ stylesheet = qui.recolor(qcolor.palette.bg.highest),
+ id = "cover",
+ },
+ },
+ {
+ widget = wibox.container.margin,
+ right = qui.BIG_PADDING,
+ left = qui.BIG_PADDING,
+ {
+ {
+ widget = wibox.container.constraint,
+ height = qui.CHAR_HEIGHT * 2.5,
+ strategy = "max",
+ {
+ widget = wibox.widget.textbox,
+ text = DEFAULTS.title, -- Song
+ id = "song",
+ valign = "top",
+ },
+ },
+ {
+ widget = wibox.container.constraint,
+ height = qui.CHAR_HEIGHT * 2.5,
+ strategy = "max",
+ {
+ widget = wibox.container.background,
+ fg = qcolor.palette.fg.low,
+ {
+ widget = wibox.widget.textbox,
+ text = DEFAULTS.artist_album, -- Artist - Album Name
+ id = "artist_album",
+ valign = "top",
+ },
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ },
+ },
+ layout = wibox.layout.fixed.horizontal,
+ },
+ nil,
+ {
+ widget = wibox.container.margin,
+ top = qui.BIG_PADDING,
+ right = qui.BIG_PADDING,
+ {
+ {
+ widget = wibox.widget.textbox,
+ text = DEFAULTS.progresstext.position .. " / " .. DEFAULTS.progresstext.length, -- position / length
+ id = "progresstext",
+ },
+ {
+ widget = wibox.container.place,
+ {
+ widget = wibox.widget.progressbar,
+ forced_height = qui.PADDING,
+ color = qcolor.palette.yellow(),
+ value = DEFAULTS.position,
+ max_value = DEFAULTS.length,
+ background_color = qcolor.palette.bg.lowest,
+ bar_shape = qui.shape,
+ shape = qui.shape,
+ id = "progressbar",
+ },
+ },
+ layout = wibox.layout.fixed.horizontal,
+ spacing = qui.BIG_PADDING,
+ },
+ },
+ layout = wibox.layout.align.vertical,
+ },
+ {
+ layout = wibox.layout.flex.vertical,
+ spacing = qui.BIG_PADDING,
+ id = "client_list",
+ },
+ layout = wibox.layout.align.horizontal,
+ },
+ },
+ },
+})
+
+local layout = M.widget:get_children_by_id("client_list")[1] --[[@as wibox.layout.flex]]
+local progressbar = M.widget:get_children_by_id("progressbar")[1] --[[@as wibox.widget.progressbar]]
+local progresstext = M.widget:get_children_by_id("progresstext")[1] --[[@as wibox.widget.textbox]]
+local song = M.widget:get_children_by_id("song")[1] --[[@as wibox.widget.textbox]]
+local artist_album = M.widget:get_children_by_id("artist_album")[1] --[[@as wibox.widget.textbox]]
+local cover = M.widget:get_children_by_id("cover")[1] --[[@as wibox.widget.imagebox]]
+
+local function mirror_player_list()
+ players = playerctl:list()
+end
+
+mirror_player_list()
+
+local function handle_metadata(_, player)
+ local title, album, artist, art
+ if player ~= playerctl:list()[M.active_player_index] then
+ return
+ end
+ if player then
+ if player.metadata.title then
+ title = player.metadata.title
+ else
+ title = DEFAULTS.title
+ end
+
+ if player.metadata.album then
+ album = player.metadata.album
+ else
+ album = DEFAULTS.album
+ end
+
+ if player.metadata.artist then
+ artist = player.metadata.artist
+ else
+ artist = DEFAULTS.artist
+ end
+
+ if player.metadata.art and player.metadata.art:match "^file://" then
+ art = player.metadata.art:gsub("^file://", "")
+ else
+ art = DEFAULTS.art
+ end
+ else
+ title = DEFAULTS.title
+ album = DEFAULTS.album
+ artist = DEFAULTS.artist
+ art = DEFAULTS.art
+ end
+
+ artist_album.text = table.concat(artist, ", ") .. ((is_empty(artist) or is_empty(album)) and "" or " - ") .. album
+ song.text = title
+ ---@diagnostic disable-next-line:inject-field
+ cover.image = art
+end
+
+local function handle_position(_, player)
+ if player ~= playerctl:list()[M.active_player_index] then
+ return
+ end
+ local position, length
+ local content = ""
+
+ if player then
+ if player.position then
+ position = player.position / playerctl.unit
+ content = content .. to_hms(position)
+ else
+ position = DEFAULTS.position
+ content = content .. DEFAULTS.progresstext.position
+ end
+
+ content = content .. " / "
+
+ if player.metadata.length then
+ length = player.metadata.length / playerctl.unit
+ content = content .. to_hms(length)
+ else
+ length = DEFAULTS.length
+ content = content .. DEFAULTS.progresstext.length
+ end
+ else
+ position = DEFAULTS.position
+ length = DEFAULTS.length
+ content = DEFAULTS.progresstext.position .. " / " .. DEFAULTS.progresstext.length
+ end
+
+ progresstext.text = content
+ ---@diagnostic disable-next-line:inject-field
+ progressbar.value = position
+ ---@diagnostic disable-next-line:inject-field
+ progressbar.max_value = length
+end
+
+playerctl:connect_signal("player::metadata", handle_metadata)
+playerctl:connect_signal("player::position", handle_position)
+
+local function update_player(player)
+ handle_metadata(nil, player)
+ handle_position(nil, player)
+ qpersistent.store("active_player_index", M.active_player_index)
+
+ local client_icon = client_icons[(player or { name = "__generic" }).name]
+ bg_icon.image = client_icon or client_icons.__generic
+ client_background:emit_signal "widget::redraw_needed"
+
+ for i, child in ipairs(layout.children) do
+ ---@diagnostic disable-next-line:undefined-field
+ child:index_handler(i)
+ end
+end
+
+function M.next_player()
+ local players_length = #layout.children
+ if players_length == 0 then
+ return
+ end
+
+ if M.active_player_index + 1 > players_length then
+ M.active_player_index = 1
+ else
+ M.active_player_index = M.active_player_index + 1
+ end
+
+ update_player(playerctl:list()[M.active_player_index])
+end
+
+function M.previous_player()
+ local players_length = #layout.children
+ if players_length == 0 then
+ return
+ end
+
+ if M.active_player_index - 1 < 1 then
+ M.active_player_index = players_length
+ else
+ M.active_player_index = M.active_player_index - 1
+ end
+
+ update_player(playerctl:list()[M.active_player_index])
+end
+
+---@param diff_player Playerctl.data
+local function recalculate_active_player(diff_player, vanished)
+ if type(diff_player) ~= "table" then
+ return
+ end
+ if #layout.children == 0 then
+ M.active_player_index = 1
+ update_player()
+ return
+ end
+
+ local active_player = players[M.active_player_index]
+ if not active_player then -- we're recovering from a state with no players
+ update_player(diff_player)
+ return
+ end
+
+ if diff_player.instance == active_player.instance and vanished then -- active player vanished; fall back to previous player
+ M.previous_player()
+ else -- non-active player appeared/vanished; try to find active player
+ for i, p in ipairs(playerctl:list()) do
+ if p.instance == active_player.instance then
+ M.active_player_index = i
+ update_player(p)
+ return
+ end
+ end
+
+ gdebug.print_warning(
+ "failed to find active player:\n " .. gdebug.dump_return(active_player, nil, 2):gsub("\n", "\n ")
+ )
+ M.active_player_index = 1
+ update_player(playerctl:list()[M.active_player_index])
+ end
+end
+
+local function register_player(player)
+ local widget = wibox.widget {
+ widget = wibox.container.constraint,
+ width = qui.PADDING,
+ strategy = "min",
+ {
+ widget = wibox.container.background,
+ shape = qui.shape,
+ bg = qcolor.palette.bg.lowest,
+ },
+ index_handler = function(self, index)
+ if M.active_player_index == index then
+ self.widget.bg = qcolor.palette.yellow()
+ else
+ self.widget.bg = qcolor.palette.bg.lowest
+ end
+ end,
+ }
+
+ ---@diagnostic disable-next-line:undefined-field
+ layout:add(widget)
+
+ recalculate_active_player(player, false)
+ mirror_player_list()
+end
+
+local function unregister_player(player)
+ ---@diagnostic disable-next-line:undefined-field
+ layout:remove(#layout.children)
+ recalculate_active_player(player, true)
+ mirror_player_list()
+end
+
+for _, player in ipairs(playerctl:list()) do
+ register_player(player)
+end
+
+-- recover state
+---@diagnostic disable-next-line:undefined-field
+local last_active_player = playerctl:list()[M.active_player_index]
+
+update_player(last_active_player)
+
+playerctl:connect_signal("player::appeared", function(_, player)
+ register_player(player)
+end)
+
+playerctl:connect_signal("player::vanished", function(_, player)
+ unregister_player(player)
+end)
+
+return M
diff --git a/.config/awesome/ui/statusbar/panel/widgets/music.lua b/.config/awesome/ui/statusbar/panel/widgets/music.old.lua
index eea7335..5631f66 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/music.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/music.old.lua
@@ -1,3 +1,4 @@
+-- TODO: update to the new color format
local qnative = require "quarrel.native"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
@@ -12,7 +13,7 @@ local w_title = wibox.widget {
local w_artist = wibox.widget {
widget = wibox.container.background,
- fg = qvars.colors.dim.fg,
+ fg = qcolor.palette.dim.fg,
{
widget = wibox.widget.textbox,
text = "",
@@ -23,35 +24,35 @@ local w_progress_bar = wibox.widget {
widget = wibox.widget.progressbar,
max_value = 0,
value = 0,
- forced_height = qvars.char_height / 2,
+ forced_height = qui.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,
- color = qvars.colors.yellow,
- background_color = qvars.colors.black,
- shape = qvars.shape,
+ - (qui.BIG_PADDING + qui.BIG_PADDING * 2 + qui.PADDING * 2)
+ - (qui.CHAR_HEIGHT / 1.25 + qui.PADDING) * 3,
+ color = qcolor.palette.yellow,
+ background_color = qcolor.palette.black,
+ shape = qui.shape,
}
local music = wibox.widget(qui.styled {
widget = wibox.container.background,
{
widget = wibox.container.margin,
- margins = qvars.big_padding,
+ margins = qui.BIG_PADDING,
{
{
{
widget = wibox.container.background,
- bg = qvars.colors.bg,
- shape = qvars.shape,
+ bg = qcolor.palette.bg,
+ shape = qui.shape,
{
widget = wibox.container.margin,
- margins = qvars.padding,
+ margins = qui.PADDING,
{
{
widget = wibox.container.constraint,
width = qvars.expanded_bar_size
- - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
- height = qvars.char_height,
+ - (qui.BIG_PADDING + qui.BIG_PADDING * 2 + qui.PADDING * 2),
+ height = qui.CHAR_HEIGHT,
{
widget = wibox.container.scroll.horizontal,
speed = 50,
@@ -62,8 +63,8 @@ local music = wibox.widget(qui.styled {
{
widget = wibox.container.constraint,
width = qvars.expanded_bar_size
- - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
- height = qvars.char_height,
+ - (qui.BIG_PADDING + qui.BIG_PADDING * 2 + qui.PADDING * 2),
+ height = qui.CHAR_HEIGHT,
{
widget = wibox.container.scroll.horizontal,
speed = 50,
@@ -82,8 +83,8 @@ local music = wibox.widget(qui.styled {
nil,
{
widget = wibox.container.background,
- bg = qvars.colors.bg,
- shape = qvars.shape,
+ bg = qcolor.palette.bg,
+ shape = qui.shape,
w_progress_bar,
},
layout = wibox.layout.align.vertical,
diff --git a/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua b/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
index feea829..01171df 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/power_menu.lua
@@ -1,19 +1,17 @@
local q = require "quarrel"
local qbind = require "quarrel.bind"
local qui = require "quarrel.ui"
-local qvars = require "quarrel.vars"
local wibox = require "wibox"
return wibox.widget {
qui.styled {
widget = wibox.container.background,
- bg = qvars.colors.black,
{
widget = wibox.widget.textbox,
text = "1",
buttons = {
- qbind:new {
- triggers = qvars.btns.left,
+ qbind {
+ triggers = qbind.btns.left,
press = function()
q.debug "from 1"
end,
@@ -24,13 +22,12 @@ return wibox.widget {
},
qui.styled {
widget = wibox.container.background,
- bg = qvars.colors.black,
{
widget = wibox.widget.textbox,
text = "2",
buttons = {
- qbind:new {
- triggers = qvars.btns.left,
+ qbind {
+ triggers = qbind.btns.left,
press = function()
q.debug "from 2"
end,
@@ -41,13 +38,12 @@ return wibox.widget {
},
qui.styled {
widget = wibox.container.background,
- bg = qvars.colors.black,
{
widget = wibox.widget.textbox,
text = "3",
buttons = {
- qbind:new {
- triggers = qvars.btns.left,
+ qbind {
+ triggers = qbind.btns.left,
press = function()
q.debug "from 3"
end,
diff --git a/.config/awesome/ui/statusbar/panel/widgets/weather.lua b/.config/awesome/ui/statusbar/panel/widgets/weather.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/weather.lua
diff --git a/.config/awesome/ui/statusbar/panel/widgets/wifi.lua b/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
index ad2234f..8ccff95 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/wifi.lua
@@ -1,27 +1,30 @@
local lgi = require "lgi"
local phosphor = require "assets.phosphor"
+local qcolor = require "quarrel.color"
local qui = require "quarrel.ui"
-local qvars = require "quarrel.vars"
local wibox = require "wibox"
local glib = lgi.GLib
+local wifi_icon = qui.icon {
+ icon = phosphor.wifi_x_fill,
+ color = qcolor.palette.red(),
+ widget = {
+ id = "icon",
+ },
+}
+
local wifi = wibox.widget(qui.styled {
widget = wibox.container.background,
+ bg = qcolor.palette.bg.high,
{
widget = wibox.container.margin,
- margins = qvars.big_padding,
+ margins = qui.BIG_PADDING,
{
{
widget = wibox.container.place,
valign = "center",
halign = "center",
- qui.icon {
- icon = phosphor.wifi_x_fill,
- color = qvars.colors.red,
- widget = {
- id = "icon",
- },
- },
+ wifi_icon,
},
{
widget = wibox.widget.textbox,
@@ -29,7 +32,7 @@ local wifi = wibox.widget(qui.styled {
id = "essid",
},
layout = wibox.layout.fixed.horizontal,
- spacing = qvars.padding,
+ spacing = qui.PADDING,
},
},
})
@@ -43,8 +46,8 @@ awesome.connect_signal("services::wifi", function(essid, _, connected)
end)
awesome.connect_signal("services::wifi::icon", function(icon, color)
- wifi:get_children_by_id("icon")[1].image = icon
- wifi:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
+ wifi_icon.image = icon
+ wifi_icon.stylesheet = qui.recolor(color)
end)
return wifi
diff --git a/.config/awesome/ui/statusbar/widgets/displays.lua b/.config/awesome/ui/statusbar/widgets/displays.lua
index 62e4398..96cf84c 100644
--- a/.config/awesome/ui/statusbar/widgets/displays.lua
+++ b/.config/awesome/ui/statusbar/widgets/displays.lua
@@ -1,7 +1,7 @@
local battery = require "services.battery"
local phosphor = require "assets.phosphor"
+local qcolor = require "quarrel.color"
local qui = require "quarrel.ui"
-local qvars = require "quarrel.vars"
local wibox = require "wibox"
local function create_display(icon, color)
@@ -16,28 +16,32 @@ local function create_display(icon, color)
}
end
-local d_battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
+local d_battery = create_display(phosphor.battery_vertical_warning_fill, qcolor.palette.red())
battery:connect_signal("icon", function(_, icon, color)
d_battery.widget.image = icon
d_battery.widget.stylesheet = qui.recolor(color)
end)
-local d_brightness = create_display(phosphor.moon_fill, qvars.colors.fg)
-awesome.connect_signal("services::brightness::icon", function(icon, color)
- d_brightness.widget.image = icon
- d_brightness.widget.stylesheet = qui.recolor(color)
-end)
+-- local d_brightness = create_display(phosphor.moon_fill, qcolor.palette.fg())
+-- awesome.connect_signal("services::brightness::icon", function(icon, color)
+-- d_brightness.widget.image = icon
+-- d_brightness.widget.stylesheet = qui.recolor(color)
+-- end)
-local d_audio = create_display(phosphor.speaker_simple_slash_fill, qvars.colors.red)
+local d_audio = create_display(phosphor.speaker_simple_slash_fill, qcolor.palette.red())
awesome.connect_signal("services::audio::icon", function(icon, color)
d_audio.widget.image = icon
d_audio.widget.stylesheet = qui.recolor(color)
end)
-local d_wifi = create_display(phosphor.wifi_x_fill, qvars.colors.red)
+local d_wifi = create_display(phosphor.wifi_x_fill, qcolor.palette.red())
awesome.connect_signal("services::wifi::icon", function(icon, color)
d_wifi.widget.image = icon
d_wifi.widget.stylesheet = qui.recolor(color)
end)
-return { audio = d_audio, battery = d_battery, brightness = d_brightness, wifi = d_wifi }
+return {
+ audio = d_audio,
+ battery = d_battery, --[[brightness = d_brightness,]]
+ wifi = d_wifi,
+}
diff --git a/.config/awesome/ui/statusbar/widgets/taglist.lua b/.config/awesome/ui/statusbar/widgets/taglist.lua
index df114df..3b81173 100644
--- a/.config/awesome/ui/statusbar/widgets/taglist.lua
+++ b/.config/awesome/ui/statusbar/widgets/taglist.lua
@@ -10,7 +10,7 @@ return function(s)
screen = s,
filter = awful.widget.taglist.filter.all,
layout = {
- spacing = qvars.padding,
+ spacing = qui.PADDING,
layout = wibox.layout.fixed.vertical,
},
widget_template = {
@@ -21,8 +21,8 @@ return function(s)
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,
+ forced_height = qui.CHAR_HEIGHT / 1.5,
+ forced_width = qui.CHAR_HEIGHT / 1.5,
},
}
-- self.widget = wibox.widget {
@@ -33,44 +33,44 @@ return function(s)
if tag.selected then
return
end
- self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.yellow())
end)
self:connect_signal("mouse::leave", function()
if tag.selected then
return
end
- self.widget.stylesheet = qui.recolor(qvars.colors.fg)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.fg())
end)
if tag.selected then
- self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.yellow())
return
end
- self.widget.stylesheet = qui.recolor(qvars.colors.fg)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.fg())
end,
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)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.yellow())
else
- self.widget.stylesheet = qui.recolor(qvars.colors.fg)
+ self.widget.stylesheet = qui.recolor(qcolor.palette.fg())
end
end,
},
buttons = {
- qbind:new {
- triggers = qvars.btns.left,
+ qbind {
+ triggers = qbind.btns.left,
press = function(t)
t:view_only()
end,
hidden = true,
},
- qbind:new {
- mods = qvars.mods.M,
- triggers = qvars.btns.left,
+ qbind {
+ mods = qbind.mods.M,
+ triggers = qbind.btns.left,
press = function(t)
if client.focus then
client.focus:move_to_tag(t)
@@ -78,8 +78,8 @@ return function(s)
end,
hidden = true,
},
- qbind:new {
- triggers = qvars.btns.right,
+ qbind {
+ triggers = qbind.btns.right,
press = awful.tag.viewtoggle,
hidden = true,
},
diff --git a/.config/awesome/ui/statusbar/widgets/taglist_new.lua b/.config/awesome/ui/statusbar/widgets/taglist_new.lua
new file mode 100644
index 0000000..79b8a96
--- /dev/null
+++ b/.config/awesome/ui/statusbar/widgets/taglist_new.lua
@@ -0,0 +1,147 @@
+local awful = require "awful"
+local qbind = require "quarrel.bind"
+local qcolor = require "quarrel.color"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+
+local empty_indicator = wibox.widget {
+ widget = wibox.container.place,
+ {
+ widget = wibox.container.constraint,
+ strategy = "exact",
+ height = qui.PADDING,
+ width = qui.PADDING,
+ {
+ widget = wibox.container.background,
+ bg = qcolor.palette.border.variant,
+ shape = qui.shape,
+ },
+ },
+}
+
+local client_indicator = wibox.widget {
+ widget = wibox.container.place,
+ {
+ widget = wibox.container.constraint,
+ height = qui.CHAR_HEIGHT,
+ width = qui.PADDING,
+ strategy = "exact",
+ {
+ widget = wibox.container.background,
+ shape = qui.shape,
+ bg = qcolor.palette.fg(),
+ },
+ },
+}
+
+local function update_tasklist(layout, tag, indicated_empty)
+ local client_delta = #tag:clients() - #layout.children
+ if client_delta < 0 then
+ for _ = 1, -(client_delta + (indicated_empty and 1 or 0)) do
+ layout:remove(1)
+ end
+ elseif client_delta > 0 then
+ for _ = 1, client_delta do
+ layout:add(client_indicator)
+ end
+ end
+end
+
+return function(s)
+ return awful.widget.taglist {
+ screen = s,
+ filter = awful.widget.taglist.filter.all,
+ layout = {
+ spacing = qui.PADDING,
+ layout = wibox.layout.fixed.vertical,
+ },
+ widget_template = {
+ widget = wibox.container.constraint,
+ strategy = "min",
+ height = qui.CHAR_HEIGHT,
+ qui.styled {
+ widget = wibox.container.background,
+ bg = qcolor.palette.bg.high,
+ {
+ widget = wibox.container.margin,
+ margins = qui.PADDING,
+ {
+ layout = wibox.layout.flex.vertical,
+ spacing = qui.PADDING,
+ },
+ },
+ },
+ create_callback = function(
+ self,
+ tag --[[@as tag]]
+ )
+ if tag.selected then
+ self.widget.border_color = qcolor.palette.yellow()
+ end
+
+ if #tag:clients() ~= 0 then
+ self.widget.widget.spacing = qui.PADDING
+ if self.indicated_empty then
+ self.widget.widget.widget:remove(1)
+ self.indicated_empty = false
+ end
+ else
+ if not self.indicated_empty then
+ self.widget.widget.widget:add(empty_indicator)
+ self.indicated_empty = true
+ end
+ end
+
+ update_tasklist(self.widget.widget.widget, tag, self.indicated_empty)
+ end,
+ update_callback = function(self, tag)
+ if tag.selected then
+ self.widget.border_color = qcolor.palette.yellow()
+ else
+ self.widget.border_color = qcolor.palette.border()
+ end
+
+ if #tag:clients() ~= 0 then
+ self.widget.widget.spacing = qui.PADDING
+ if self.indicated_empty then
+ self.widget.widget.widget:remove(1)
+ self.indicated_empty = false
+ end
+ else
+ self.widget.widget.spacing = nil
+ if not self.indicated_empty then
+ self.widget.widget.widget:add(empty_indicator)
+ self.indicated_empty = true
+ end
+ end
+
+ update_tasklist(self.widget.widget.widget, tag, self.indicated_empty)
+ end,
+ },
+ buttons = {
+ qbind {
+ triggers = qbind.btns.left,
+ press = function(t)
+ t:view_only()
+ end,
+ hidden = true,
+ },
+ qbind {
+ mods = qbind.mods.M,
+ triggers = qbind.btns.left,
+ press = function(t)
+ if client.focus then
+ client.focus:move_to_tag(t)
+ end
+ end,
+ hidden = true,
+ },
+ qbind {
+ triggers = qbind.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
deleted file mode 100644
index 9656185..0000000
--- a/.config/awesome/ui/statusbar/widgets/tasklist.lua
+++ /dev/null
@@ -1,30 +0,0 @@
-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