diff --git a/.gitmodules b/.gitmodules index 1a3d6b5..8a4eed4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "awesome/src/lib/color"] path = awesome/src/lib/color url = https://github.com/andOrlando/color +[submodule "awesome/src/lib/dbus_proxy"] + path = awesome/src/lib/dbus_proxy + url = https://github.com/stefano-m/lua-dbus_proxy diff --git a/awesome/src/assets/userpfp/crylia.png b/awesome/src/assets/userpfp/crylia.png index 671fbe2..8711b3f 100644 Binary files a/awesome/src/assets/userpfp/crylia.png and b/awesome/src/assets/userpfp/crylia.png differ diff --git a/awesome/src/core/notifications.lua b/awesome/src/core/notifications.lua index f933042..94e5834 100644 --- a/awesome/src/core/notifications.lua +++ b/awesome/src/core/notifications.lua @@ -404,7 +404,7 @@ naughty.connect_signal( local box = naughty.layout.box { notification = n, - timeout = 3, + timeout = 5, type = "notification", screen = screen.primary, shape = function(cr, width, height) @@ -413,6 +413,10 @@ naughty.connect_signal( widget_template = w_template } + awful.spawn.easy_async_with_shell( + "paplay /usr/share/sounds/freedesktop/stereo/message.oga" + ) + box.buttons = {} n.buttons = {} end diff --git a/awesome/src/core/rules.lua b/awesome/src/core/rules.lua index 84c7f8d..e5aa85e 100644 --- a/awesome/src/core/rules.lua +++ b/awesome/src/core/rules.lua @@ -37,26 +37,6 @@ awful.rules.rules = { properties = { titlebars_enabled = true } - }, - { - id = "games", - rule_any = { - class = { - "steam_app_.%d+", - "gta5.exe", - }, - }, - properties = { - tag = "9", - switchtotag = true, - fullscreen = true, - screen = screen[1], - floating = true, - }, - focus = true, - callback = function(c) - awful.screen.focused() - end } } diff --git a/awesome/src/core/signals.lua b/awesome/src/core/signals.lua index 02c19f3..f8c6033 100644 --- a/awesome/src/core/signals.lua +++ b/awesome/src/core/signals.lua @@ -121,15 +121,20 @@ function Hover_signal(widget, bg_override, fg_override, border_override, icon_ov local b_timed_border = rubato.timed { duration = 0.3, pos = math.floor(bbo) } local function update_bg() - widget:set_bg("#" .. color.utils.rgba_to_hex { r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos }) + widget:set_bg("#" .. + color.utils.rgba_to_hex { math.min(r_timed_bg.pos, 255), math.min(g_timed_bg.pos, 255), + math.min(b_timed_bg.pos, 255) }) end local function update_fg() - widget:set_fg("#" .. color.utils.rgba_to_hex { r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos }) + widget:set_fg("#" .. color.utils.rgba_to_hex { math.min(r_timed_fg.pos, 255), math.min(g_timed_fg.pos, 255), + math.min(b_timed_fg.pos, 255) }) end local function update_border() - widget:set_border_color("#" .. color.utils.rgba_to_hex { r_timed_border.pos, g_timed_border.pos, b_timed_border.pos }) + widget:set_border_color("#" .. + color.utils.rgba_to_hex { math.min(r_timed_border.pos, 255), math.min(g_timed_border.pos, 255), + math.min(b_timed_border.pos, 255) }) end r_timed_bg:subscribe(update_bg) @@ -260,24 +265,8 @@ function Hover_signal(widget, bg_override, fg_override, border_override, icon_ov --widget:connect_signal("mouse::leave", mouse_leave) end - local button_press = function() - --[[ if old_bg or bg_override then - if bg_override then - bg_override = bg_override .. "bb" - end - widget.bg = bg_override or old_bg .. "bb" - end - if fg_override or old_fg then - if fg_override then - fg_override = fg_override .. "bb" - end - widget.fg = fg_override or old_fg .. "bb" - end ]] - --widget:disconnect_signal("mouse::leave", mouse_leave) - end - widget:connect_signal("mouse::enter", mouse_enter) - widget:connect_signal("button::press", button_press) + --widget:connect_signal("button::press", button_press) --widget:connect_signal("button::release", button_release) widget:connect_signal("mouse::leave", mouse_leave) end diff --git a/awesome/src/dbus/bluetooth_dbus.lua b/awesome/src/dbus/bluetooth_dbus.lua index ce453e0..d488339 100644 --- a/awesome/src/dbus/bluetooth_dbus.lua +++ b/awesome/src/dbus/bluetooth_dbus.lua @@ -1,6 +1,6 @@ local awful = require("awful") local gears = require("gears") -local dbus_proxy = require("dbus_proxy") +local dbus_proxy = require("src.lib.dbus_proxy") local lgi = require("lgi") local naughty = require("naughty") diff --git a/awesome/src/lib/dbus_proxy b/awesome/src/lib/dbus_proxy new file mode 160000 index 0000000..c9253bd --- /dev/null +++ b/awesome/src/lib/dbus_proxy @@ -0,0 +1 @@ +Subproject commit c9253bde3fa5a64261953d1b196c57fabf9f8561 diff --git a/awesome/src/lib/overflow_widget/overflow.lua b/awesome/src/lib/overflow_widget/overflow.lua index 69d55f4..8b4d98f 100644 --- a/awesome/src/lib/overflow_widget/overflow.lua +++ b/awesome/src/lib/overflow_widget/overflow.lua @@ -325,20 +325,20 @@ function overflow:set_scroll_factor(factor) local function update_scroll() - self._private.scroll_factor = overflow.rubato_timed.pos + self._private.scroll_factor = self.rubato_timed.pos self:emit_signal("widget::layout_changed") self:emit_signal("property::scroll_factor", factor) end -- Make sure it only subscribes once if first_call then - overflow.rubato_timed:subscribe(update_scroll) + self.rubato_timed:subscribe(update_scroll) --first_call = false end -- Set the target to the new target + remaining target from last scroll. This makes it scroll faster and correctly. - overflow.rubato_timed.target = math.min(1, - math.max(factor + (overflow.rubato_timed.target - overflow.rubato_timed.pos), 0)) + self.rubato_timed.target = math.min(1, + math.max(factor + (self.rubato_timed.target - self.rubato_timed.pos), 0)) end function overflow:get_scroll_factor() diff --git a/awesome/src/modules/calendar/calendar.lua b/awesome/src/modules/calendar/calendar.lua index 5cfb5a1..9713ac9 100644 --- a/awesome/src/modules/calendar/calendar.lua +++ b/awesome/src/modules/calendar/calendar.lua @@ -389,7 +389,6 @@ local function create_tasks() end end - return tasks end @@ -405,7 +404,7 @@ local selected_day = { return function(s) -- The calendar grid - local calendar_matrix = wibox.widget { layout = wibox.layout.grid } + local calendar_matrix = wibox.widget { layout = wibox.layout.grid, spacing = dpi(2) } local weeks = wibox.widget { layout = wibox.layout.fixed.vertical } @@ -541,7 +540,7 @@ return function(s) border_color = border, border_width = Theme_config.calendar.day.border_width, shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(0)) + gears.shape.rounded_rect(cr, width, height, dpi(8)) end }, widget = wibox.container.constraint, @@ -642,7 +641,7 @@ return function(s) border_color = border, border_width = Theme_config.calendar.day.border_width, shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(0)) + gears.shape.rounded_rect(cr, width, height, dpi(8)) end }, widget = wibox.container.constraint, @@ -752,7 +751,7 @@ return function(s) border_color = border, border_width = Theme_config.calendar.day.border_width, shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(0)) + gears.shape.rounded_rect(cr, width, height, dpi(8)) end }, widget = wibox.container.constraint, diff --git a/awesome/src/modules/calendar/init.lua b/awesome/src/modules/calendar/init.lua new file mode 100644 index 0000000..a6b421f --- /dev/null +++ b/awesome/src/modules/calendar/init.lua @@ -0,0 +1,1005 @@ +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gtable = require("gears.table") +local gobject = require("gears.object") +local gshape = require("gears.shape") +local gcolor = require("gears.color") +local wibox = require("wibox") + +local ical_parser = require("src.tools.ical_parser")() +--local task_info = require("src.modules.calendar.task_info") + +local icondir = awful.util.getdir("config") .. "src/assets/icons/calendar/" + +local calendar = { mt = {} } +calendar.tasks = {} + +calendar._private = {} + +-- Month lookup table +calendar._private.months = { + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December" +} + +-- Weeks shortname lookup table +calendar._private.weeks = { + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + "Sun" +} + +--- A date table to keep track of the needed date +calendar.date = { + day = tonumber(os.date("%d")) or 1, + month = tonumber(os.date("%m")) or 1, + year = tonumber(os.date("%Y")) or 1970 +} + +---Checks how many days a month has and returns the ammount. Also takes leap years into account. +---@param month number|nil +---@param year number|nil +---@return integer last_day The last day of the month +function calendar:get_last_day_in_month(month, year) + month = month or self.date.month + year = year or self.date.year + + local last_day = { + [1] = 31, + [2] = 28, + [3] = 31, + [4] = 30, + [5] = 31, + [6] = 30, + [7] = 31, + [8] = 31, + [9] = 30, + [10] = 31, + [11] = 30, + [12] = 31 + } + + if (month == 2) and (math.floor(year % 4) == 0) then + return 29 + else + return last_day[month] + end +end + +---Takes a date and returns the weekday of that month. +---@param day number|nil +---@param month number|nil +---@param year number|nil +---@return number +function calendar:weekday_for_day(day, month, year) + day = day or self.date.day + month = month or self.date.month + year = year or self.date.year + + --[[ + The algorithm uses the march as the first month of the year and february + january + as the 11th and 12th month of last year. This is also the reason we substract the month by 2 + ]] + month = month - 2 + if month == 0 then + month = 12 + year = year - 1 + elseif month == -1 then + month = 11 + year = year - 1 + end + + -- Forgot what the algorithm was called + local w = ((day + math.floor(2.6 * month - 0.2) - 2 * tonumber(tostring(year):match("([0-9]+)[0-9][0-9]")) + + tonumber(tostring(year):match("[0-9][0-9]([0-9]+)")) + + math.floor(tonumber(tostring(year):match("[0-9][0-9]([0-9]+)")) / 4) + + math.floor(tonumber(tostring(year):match("([0-9]+)[0-9][0-9]")) / 4)) % 7) + + -- If the week should start on monday, sunday is default. Since the function returns 0 - 6, we have to add 1 for lua's tables + if w == 0 then w = 7 end + + return w +end + +---Calculated how many weeks are in month. +---@param month number|nil +---@param year number|nil +---@return integer +function calendar:weeks_in_month(month, year) + month = month or self.date.month + year = year or self.date.year + + return math.ceil((calendar:get_last_day_in_month(month, year) + calendar:weekday_for_day(1) - 1) / 7) +end + +function calendar:check_event_uid(uid) + for _, cal in ipairs(calendar.tasks) do + for _, task in ipairs(cal) do + if task.uid == uid then + return true + end + end + end + return false +end + +function calendar:get_tasks() + if not ical_parser or not ical_parser.VCALENDAR then return end + local tasks = {} + for _, cal in ipairs(ical_parser.VCALENDAR) do + for _, event in ipairs(cal.VEVENT) do + if not self:check_event_uid(event.UID) then + local start_time + if event.DTSTART then + start_time = event.DTSTART.DTSTART + end + local end_time + if event.DTEND then + end_time = event.DTEND.DTEND + end + -- Get repeat cases + if event.RRULE then + if event.RRULE.FREQ == "DAILY" then + elseif event.RRULE.FREQ == "WEEKLY" then + local year_counter, month_counter, day_counter = start_time.year, start_time.month, + start_time.day + end_time = event.RRULE.UNTIL + if not event.RRULE.UNTIL then + end_time = { + year = start_time.year + 1000, + month = start_time.month, + day = start_time.day + } + end + + while (year_counter < end_time.year) or (month_counter < end_time.month) or (day_counter <= end_time.day) do + table.insert(tasks, { + date_start = { + year = year_counter, + month = month_counter, + day = day_counter, + hour = start_time.hour or 0, + minute = start_time.min or 0, + second = start_time.sec or 0 + }, + date_end = { + year = year_counter, + month = month_counter, + day = day_counter, + hour = end_time.hour or 0, + minute = end_time.min or 0, + second = end_time.sec or 0 + }, + summary = event.SUMMARY, + location = event.LOCATION, + description = event.DESCRIPTION, + uid = event.UID + }) + day_counter = day_counter + 7 + local month_length = calendar:get_last_day_in_month(month_counter, year_counter) + if day_counter > month_length then + day_counter = day_counter - month_length + month_counter = month_counter + 1 + if month_counter > 12 then + month_counter = 1 + year_counter = year_counter + 1 + end + end + end + elseif event.RRULE.FREQ == "MONTHLY" then + elseif event.RRULE.FREQ == "YEARLY" then + end_time = event.RRULE.UNTIL + if not event.RRULE.UNTIL then + end_time = { + year = start_time.year + 1000, + month = start_time.month, + day = start_time.day + } + end + for i = start_time.year, end_time.year, 1 do + table.insert(tasks, { + date_start = { + year = i, + month = start_time.month, + day = start_time.day, + hour = start_time.hour or 0, + minute = start_time.min or 0, + second = start_time.sec or 0 + }, + date_end = { + year = i, + month = end_time.month, + day = end_time.day, + hour = end_time.hour or 0, + minute = end_time.min or 0, + second = end_time.sec or 0 + }, + summary = event.SUMMARY, + location = event.LOCATION, + description = event.DESCRIPTION, + url = event.URL.URL, + uid = event.UID + }) + end + end + -- If RRULE is empty we just add a single day event + else + table.insert(tasks, { + date_start = { + year = start_time.year, + month = start_time.month, + day = start_time.day, + hour = start_time.hour or 0, + minute = start_time.min or 0, + second = start_time.sec or 0 + }, + date_end = { + year = start_time.year, + month = start_time.month, + day = start_time.day, + hour = start_time.hour or 0, + minute = start_time.min or 0, + second = start_time.sec or 0 + }, + summary = event.SUMMARY, + description = event.DESCRIPTION, + location = event.LOCATION, + url = event.URL, + uid = event.UID, + }) + end + if event.VALARM then + -- send a notification 15 minutes before an event starts + + end + end + end + end + table.insert(self.tasks, tasks) +end + +---!Fix later, I have no idea how to calculate it and the internet has no clue either +calendar._private.calendar_weeks_widget = wibox.widget { layout = wibox.layout.fixed.vertical } +---Creates the widget that displays the calendar week +function calendar:create_calendar_weeks_widget() + self._private.calendar_weeks_widget:reset() + -- Loop over every month until the current month and calculate for each month if there is a prior week number or next week number + local start_week = 1 + + local end_week = start_week + calendar:weeks_in_month() - 1 + + -- Loop from the first calendar week in this month to the last (4-6 in min-max) + for i = start_week, end_week, 1 do + self._private.calendar_weeks_widget:add(wibox.widget { + { + { + text = i, + id = "num", + align = "center", + valign = "top", + widget = wibox.widget.textbox, + }, + id = "background", + fg = Theme_config.calendar.day.fg_unfocus, + widget = wibox.container.background, + }, + strategy = "exact", + height = dpi(120), + width = dpi(40), + widget = wibox.container.constraint + }) + end +end + +calendar._private.weekdays = wibox.widget { layout = wibox.layout.flex.horizontal } +---Creates a little widget that holds a short weekday name e.g. Mon... +function calendar:create_weekdays_widget() + self._private.weekdays:reset() + for i = 1, 7, 1 do + self._private.weekdays:add(wibox.widget { + { + text = self._private.weeks[i], + align = "center", + valign = "center", + widget = wibox.widget.textbox, + }, + bg = Theme_config.calendar.weekdays.bg, + fg = Theme_config.calendar.weekdays.fg, + widget = wibox.container.background, + }) + end +end + +calendar._private.calendar_matrix = wibox.widget { layout = wibox.layout.grid, spacing = dpi(2), forced_num_cols = 7 } +---Creates the calendar matrix widget +function calendar:create_calendar_widget() + self._private.calendar_matrix:reset() + local months_t = {} + + for i, month in ipairs(self._private.months) do + months_t[i] = { + name = month, + first_day = self:weekday_for_day(1, i, self.date.year), + last_day = self:weekday_for_day(calendar:get_last_day_in_month(i, self.date.year), i, self.date.year), + day_count = self:get_last_day_in_month(i, self.date.year), + weeks = self:weeks_in_month(i, self.date.year), + } + end + + ---Creates a layout with all tasks that match for a given date + ---@param day number + ---@param month number + ---@param year number + ---@return wibox.widget|nil layout Tasks in a vertical fixed layout or nil if there is no task + local function get_tasks_for_day(day, month, year) + if not self.tasks or #self.tasks == 0 then return end + local tasks_layout = { + layout = require("src.lib.overflow_widget.overflow").vertical, + scrollbar_width = 0, + step = dpi(50), + spacing = dpi(2) + } + for _, cal in ipairs(self.tasks) do + for _, task in ipairs(cal) do + if (task.date_start.year == year) and (task.date_start.month == month) and (task.date_start.day == day) then + local tw = wibox.widget { + { + { + text = task.summary, + align = "left", + halign = "center", + font = "JetBrainsMono Nerd Font, bold 10", + widget = wibox.widget.textbox + }, + margins = dpi(2), + widget = wibox.container.margin + }, + fg = Theme_config.calendar.task.fg, + bg = Theme_config.calendar.task.bg, + shape = Theme_config.calendar.task.shape, + forced_height = dpi(20), + widget = wibox.container.background + } + + --[[ local ti = task_info { + summary = task.summary, + description = task.description, + location = task.location, + url = task.url, + uid = task.uid, + date_start = task.date_start, + date_end = task.date_end, + } ]] + + local task_info_widget = wibox.widget { + { + { -- Task detail + { -- Calendar color + widget = wibox.container.background, + shape = function(cr, _, height) + gshape.rounded_rect(cr, dpi(10), height, dpi(8)) + end, + }, + { + { -- Summary + widget = wibox.widget.textbox, + text = task.summary, + valign = "center", + align = "left", + id = "summary", + }, + { -- Date long + widget = wibox.widget.textbox, + text = task.date_long, + valign = "center", + align = "right", + id = "date_long", + }, + { -- From - To + widget = wibox.widget.textbox, + text = task.from_to, + valign = "center", + align = "left", + id = "from_to", + }, + { -- Repeat information + widget = wibox.widget.textbox, + text = task.repeat_info, + valign = "center", + align = "right", + id = "repeat_info", + }, + layout = wibox.layout.fixed.vertical, + }, + layout = wibox.layout.fixed.horizontal + }, + { -- Location + { + widget = wibox.widget.imagebox, + image = gcolor.recolor_image(icondir .. "location.svg", + Theme_config.calendar.border_color), + resize = false, + valign = "center", + halign = "center", + }, + { + widget = wibox.widget.textbox, + text = task.location, + valign = "center", + align = "left", + id = "location", + }, + id = "location_container", + layout = wibox.layout.fixed.horizontal + }, + { -- Alarm + { + widget = wibox.widget.imagebox, + image = gcolor.recolor_image(icondir .. "alarm.svg", Theme_config.calendar.fg), + resize = false, + valign = "center", + halign = "center", + }, + { + widget = wibox.widget.textbox, + text = task.alarm, + valign = "center", + align = "left", + id = "alarm", + }, + id = "alarm_container", + layout = wibox.layout.fixed.horizontal + }, + id = "task_detail", + layout = wibox.layout.fixed.vertical + }, + bg = Theme_config.calendar.bg, + fg = Theme_config.calendar.fg, + shape = function(cr, _, height) + gshape.rounded_rect(cr, height, height, dpi(8)) + end, + widget = wibox.container.background, + } + + local task_popup = awful.popup { + widget = task_info_widget, + ontop = true, + visible = true, + bg = "#00000000", + x = mouse.coords().x, + y = mouse.coords().y, + screen = self.screen + } + + tw:connect_signal("button::down", function() + --ti:toggle() + task_popup.visible = not task_popup.visible + end) + + Hover_signal(tw) + + table.insert(tasks_layout, tw) + end + end + end + return tasks_layout + end + + -- Create the last months days that are still present in this month + if months_t[self.date.month].first_day ~= 1 then + local column = 1 + local last_month = self.date.month - 1 + local year = self.date.year + if last_month == 0 then + year = year - 1 + last_month = 12 + end + + local last_month_length = self:get_last_day_in_month(last_month, year) + + for i = last_month_length - months_t[self.date.month].first_day + 2, last_month_length, 1 do + local border = Theme_config.calendar.day.border_color + local bg = Theme_config.calendar.day.bg_unfocus + local fg = Theme_config.calendar.day.fg_unfocus + + local y = tonumber(os.date("%Y")) + local m = tonumber(os.date("%m")) + + if (i == self.date.day) and (m == last_month) and (y == year) then + bg = Theme_config.calendar.day.bg_focus + fg = Theme_config.calendar.day.fg_focus + end + + local day = wibox.widget { + { + { + { + { + { + { + { -- Day + widget = wibox.widget.textbox, + align = "center", + valign = "center", + text = math.floor(i), + id = "day_text", + }, + widget = wibox.container.margin, + margins = dpi(2), + }, + id = "day_bg", + widget = wibox.container.background, + bg = bg, + shape = Theme_config.calendar.day.shape, + fg = fg, + }, + widget = wibox.container.place, + valign = "center", + halign = "center", + }, + { + get_tasks_for_day(math.floor(i), last_month, year), + widget = wibox.container.margin, + margins = dpi(4), + id = "day_tasks", + }, + id = "tasks", + spacing = dpi(4), + layout = wibox.layout.fixed.vertical + }, + id = "day_bg", + widget = wibox.container.margin, + top = dpi(4) + }, + id = "background", + widget = wibox.container.background, + bg = Theme_config.calendar.day.bg_unfocus, + fg = Theme_config.calendar.day.fg_unfocus, + border_color = border, + border_width = Theme_config.calendar.day.border_width, + shape = Theme_config.calendar.day.shape, + }, + id = "day", + widget = wibox.container.constraint, + width = dpi(100), + height = dpi(120), + strategy = "exact" + } + + self._private.calendar_matrix:add_widget_at(day, 1, column) + column = column + 1 + end + + end + + -- Create the days in this month + local row = 1 + local col = months_t[self.date.month].first_day + for i = 1, months_t[self.date.month].day_count, 1 do + local border = Theme_config.calendar.day.border_color + local bg = Theme_config.calendar.day.bg + local fg = Theme_config.calendar.day.fg + + local m = tonumber(os.date("%m")) + local y = tonumber(os.date("%Y")) + if (i == self.date.day) and (m == self.date.month) and (y == self.date.year) then + bg = Theme_config.calendar.day.bg_focus + fg = Theme_config.calendar.day.fg_focus + end + + local day = wibox.widget { + { + { + { + { + { + { + { -- Day + widget = wibox.widget.textbox, + align = "center", + valign = "center", + text = math.floor(i), + id = "day_text", + }, + widget = wibox.container.margin, + margins = dpi(2), + }, + id = "day_bg", + widget = wibox.container.background, + bg = bg, + shape = Theme_config.calendar.day.shape, + fg = fg, + }, + widget = wibox.container.place, + valign = "center", + halign = "center", + }, + { + get_tasks_for_day(math.floor(i), self.date.month, self.date.year), + widget = wibox.container.margin, + margins = dpi(4) + }, + id = "tasks", + spacing = dpi(4), + layout = wibox.layout.fixed.vertical + }, + widget = wibox.container.margin, + top = dpi(4) + }, + id = "background", + widget = wibox.container.background, + bg = Theme_config.calendar.day.bg, + fg = Theme_config.calendar.day.fg, + border_color = border, + border_width = Theme_config.calendar.day.border_width, + shape = Theme_config.calendar.day.shape, + }, + widget = wibox.container.constraint, + width = dpi(100), + height = dpi(120), + strategy = "exact" + } + + self._private.calendar_matrix:add_widget_at(day, row, col) + col = col + 1 + if col > 7 then + row = row + 1 + col = 1 + end + end + + -- Create the next months days that are still present in this month + if months_t[self.date.month].last_day ~= 7 then + local next_month = self.date.month + 1 + local year = self.date.year + if next_month == 13 then + year = year + 1 + next_month = 1 + end + + for i = 1, 7 - months_t[self.date.month].last_day, 1 do + local border = Theme_config.calendar.day.border_color + local bg = Theme_config.calendar.day.bg_unfocus + local fg = Theme_config.calendar.day.fg_unfocus + + local m = tonumber(os.date("%m")) + local y = tonumber(os.date("%Y")) + if (i == self.date.day) and (m == next_month) and (y == year) then + bg = Theme_config.calendar.day.bg_focus + fg = Theme_config.calendar.day.fg_focus + end + local day = wibox.widget { + { + { + { + { + { + { + { -- Day + widget = wibox.widget.textbox, + align = "center", + valign = "center", + text = math.floor(i), + id = "day_text", + }, + widget = wibox.container.margin, + margins = dpi(2), + }, + id = "day_bg", + widget = wibox.container.background, + bg = bg, + shape = Theme_config.calendar.day.shape, + fg = fg, + }, + widget = wibox.container.place, + valign = "center", + halign = "center", + }, + { + get_tasks_for_day(math.floor(i), next_month, year), + widget = wibox.container.margin, + margins = dpi(4) + }, + id = "tasks", + spacing = dpi(4), + layout = wibox.layout.fixed.vertical + }, + widget = wibox.container.margin, + top = dpi(4) + }, + id = "background", + widget = wibox.container.background, + bg = Theme_config.calendar.day.bg_unfocus, + fg = Theme_config.calendar.day.fg_unfocus, + border_color = border, + border_width = Theme_config.calendar.day.border_width, + shape = Theme_config.calendar.day.shape, + }, + widget = wibox.container.constraint, + width = dpi(100), + height = dpi(120), + strategy = "exact" + } + self._private.calendar_matrix:add_widget_at(day, months_t[self.date.month].weeks, + months_t[self.date.month].last_day + i) + end + end +end + +function calendar.new(args) + args = args or {} + local ret = gobject { enable_properties = true, enable_auto_signals = true } + gtable.crush(ret, calendar, true) + + local calendar_widget = wibox.widget { + { + { + { + { + { -- Add new iCal button + { + { + widget = wibox.widget.imagebox, + resize = false, + image = gcolor.recolor_image(icondir .. "add_ical.svg", Theme_config.calendar.add_ical.fg_focus), + halign = "center", + valign = "center" + }, + id = "add_ical", + shape = Theme_config.calendar.add_ical.shape, + bg = Theme_config.calendar.add_ical.bg, + widget = wibox.container.background + }, + widget = wibox.container.margin, + margins = dpi(4) + }, + { -- New task button + { + { + widget = wibox.widget.imagebox, + resize = false, + image = gcolor.recolor_image(icondir .. "add_task.svg", Theme_config.calendar.add_task.fg), + halign = "center", + valign = "center" + }, + id = "add_task", + shape = Theme_config.calendar.add_task.shape, + bg = Theme_config.calendar.add_task.bg, + widget = wibox.container.background + }, + widget = wibox.container.margin, + margins = dpi(4) + }, + layout = wibox.layout.fixed.vertical + }, + widget = wibox.container.constraint, + strategy = "exact", + height = dpi(75) + }, + ret._private.calendar_weeks_widget, + id = "weekdaysnum", + layout = wibox.layout.fixed.vertical + }, + { + { + { --Header + { -- Month year switcher + { -- Prev arrow + widget = wibox.widget.imagebox, + resize = true, + image = icondir .. "chevron-left.svg", + valign = "center", + halign = "center", + id = "prev_month", + }, + { + { -- Month + widget = wibox.widget.textbox, + text = ret._private.months[ret.date.month], + id = "month", + valign = "center", + align = "center" + }, + widget = wibox.container.constraint, + strategy = "exact", + width = dpi(150) + }, + { -- Next year arrow + widget = wibox.widget.imagebox, + resize = true, + image = icondir .. "chevron-right.svg", + valign = "center", + halign = "center", + id = "next_month", + }, + layout = wibox.layout.fixed.horizontal + }, + nil, + { -- Year year switcher + { -- Prev arrow + widget = wibox.widget.imagebox, + resize = true, + image = icondir .. "chevron-left.svg", + valign = "center", + halign = "center", + id = "prev_year" + }, + { + { -- Year + widget = wibox.widget.textbox, + text = calendar.date.year, + id = "year", + valign = "center", + align = "center" + }, + widget = wibox.container.constraint, + strategy = "exact", + width = dpi(150) + }, + { -- Next year arrow + widget = wibox.widget.imagebox, + resize = true, + image = icondir .. "chevron-right.svg", + valign = "center", + halign = "center", + id = "next_year" + }, + layout = wibox.layout.fixed.horizontal + }, + layout = wibox.layout.align.horizontal + }, + widget = wibox.container.constraint, + height = dpi(40), + strategy = "exact" + }, + { -- Weekdays + ret._private.weekdays, + widget = wibox.container.background + }, + ret._private.calendar_matrix, + id = "calendar", + spacing = dpi(5), + layout = wibox.layout.fixed.vertical + }, + id = "lay1", + layout = wibox.layout.fixed.horizontal, + }, + widget = wibox.container.background, + bg = Theme_config.calendar.bg, + border_color = Theme_config.calendar.border_color, + border_width = Theme_config.calendar.border_width, + border_strategy = "inner", + fg = Theme_config.calendar.fg, + shape = Theme_config.calendar.shape, + } + + ret:get_tasks() + + -- Init calendar + ret:create_calendar_widget() + ret:create_weekdays_widget() + ret:create_calendar_weeks_widget() + + ret.widget = awful.popup { + widget = calendar_widget, + screen = args.screen, + ontop = true, + bg = "#00000000", + visible = false, + x = 3750, + y = 60 + } + + calendar_widget:get_children_by_id("add_ical")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + awful.spawn.easy_async_with_shell( + "zenity --file-selection --title='Select an ICalendar file' --file-filter='iCalendar File | *.ics'", + function(path_to_file) + path_to_file = string.gsub(path_to_file, "\n", "") + if not path_to_file then return end + ical_parser:add_calendar(path_to_file) + ret:get_tasks() + ret:create_calendar_widget() + end + ) + end) + ) + ) + + calendar_widget:get_children_by_id("add_task")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + awful.spawn.easy_async_with_shell( + "zenity --info --text='Soon TM'", + function() + + end + ) + end) + ) + ) + + calendar_widget:get_children_by_id("prev_month")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + ret.date.month = ret.date.month - 1 + if ret.date.month == 0 then + ret.date.month = 12 + ret.date.year = ret.date.year - 1 + end + calendar_widget:get_children_by_id("month")[1].text = ret._private.months[ret.date.month] + calendar_widget:get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + ) + ) + + calendar_widget:get_children_by_id("next_month")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + ret.date.month = ret.date.month + 1 + if ret.date.month == 13 then + ret.date.month = 1 + ret.date.year = ret.date.year + 1 + end + calendar_widget:get_children_by_id("month")[1].text = ret._private.months[ret.date.month] + calendar_widget:get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + ) + ) + + --- Calendar switch year back + calendar_widget:get_children_by_id("prev_year")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + ret.date.year = ret.date.year - 1 + calendar_widget:get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + ) + ) + + --- Calendar switch year forward + calendar_widget:get_children_by_id("next_year")[1]:buttons( + gtable.join( + awful.button({}, 1, function() + ret.date.year = ret.date.year + 1 + calendar_widget:get_children_by_id("year")[1].text = ret.date.year + ret:create_calendar_weeks_widget() + ret:create_calendar_widget() + end) + ) + ) + + awesome.connect_signal("calendar::toggle", function() + if mouse.screen == args.screen then + ret.widget.visible = not ret.widget.visible + end + end) +end + +function calendar.mt:__call(...) + return calendar.new(...) +end + +return setmetatable(calendar, calendar.mt) diff --git a/awesome/src/modules/calendar/task_info.lua b/awesome/src/modules/calendar/task_info.lua new file mode 100644 index 0000000..d6d4df2 --- /dev/null +++ b/awesome/src/modules/calendar/task_info.lua @@ -0,0 +1,125 @@ +-- Awesome Libs +local awful = require("awful") +local dpi = require("beautiful").xresources.apply_dpi +local gcolor = require("gears.color") +local gtable = require("gears.table") +local gshape = require("gears.shape") +local gobject = require("gears.object") +local wibox = require("wibox") + +local icondir = awful.util.getdir("config") .. "src/assets/icons/calendar/" + +local task_info = { mt = {} } +task_info._private = {} + +function task_info.new(args) + args = args or {} + if not args.task then return end + args.screen = args.screen or awful.screen.focused() + local ret = gobject {} + gtable.crush(ret, task_info, true) + + local task_info_widget = wibox.widget { + { + { -- Task detail + { -- Calendar color + widget = wibox.container.background, + shape = function(cr, _, height) + gshape.rounded_rect(cr, dpi(10), height, dpi(8)) + end, + }, + { + { -- Summary + widget = wibox.widget.textbox, + text = ret.summary, + valign = "center", + align = "left", + id = "summary", + }, + { -- Date long + widget = wibox.widget.textbox, + text = ret.date_long, + valign = "center", + align = "right", + id = "date_long", + }, + { -- From - To + widget = wibox.widget.textbox, + text = ret.from_to, + valign = "center", + align = "left", + id = "from_to", + }, + { -- Repeat information + widget = wibox.widget.textbox, + text = ret.repeat_info, + valign = "center", + align = "right", + id = "repeat_info", + }, + layout = wibox.layout.fixed.vertical, + }, + layout = wibox.layout.fixed.horizontal + }, + { -- Location + { + widget = wibox.widget.imagebox, + image = gcolor.recolor_image(icondir .. "location.svg", Theme_config.calendar.task_info.location_icon_color), + resize = false, + valign = "center", + halign = "center", + }, + { + widget = wibox.widget.textbox, + text = ret.location, + valign = "center", + align = "left", + id = "location", + }, + id = "location_container", + layout = wibox.layout.fixed.horizontal + }, + { -- Alarm + { + widget = wibox.widget.imagebox, + image = gcolor.recolor_image(icondir .. "alarm.svg", Theme_config.calendar.task_info.alarm_icon_color), + resize = false, + valign = "center", + halign = "center", + }, + { + widget = wibox.widget.textbox, + text = ret.alarm, + valign = "center", + align = "left", + id = "alarm", + }, + id = "alarm_container", + layout = wibox.layout.fixed.horizontal + }, + id = "task_detail", + layout = wibox.layout.fixed.vertical + }, + bg = Theme_config.calendar.task_info.bg, + fg = Theme_config.calendar.task_info.fg, + shape = Theme_config.calendar.task_info.shape, + widget = wibox.container.background, + } + + ret.widget = awful.popup { + widget = task_info_widget, + ontop = true, + visible = true, + bg = "#00000000", + x = mouse.coords().x, + y = mouse.coords().y, + screen = args.screen + } + +end + +function task_info.mt:__call(...) + task_info.new(...) +end + +return setmetatable(task_info, task_info.mt) diff --git a/awesome/src/modules/crylia_bar/dock.lua b/awesome/src/modules/crylia_bar/dock.lua index 8517259..964d580 100644 --- a/awesome/src/modules/crylia_bar/dock.lua +++ b/awesome/src/modules/crylia_bar/dock.lua @@ -3,7 +3,6 @@ -------------------------------------------------------------------------------------------------------------- -- Awesome Libs local awful = require("awful") -local async = require("async") local dpi = require("beautiful").xresources.apply_dpi local Gio = require("lgi").Gio local gears = require("gears") @@ -170,9 +169,12 @@ return function(screen) local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) } local col = Theme_config.dock.indicator_bg for _, c in ipairs(client.get()) do - local icon_name = pr.icon - if icon_name:match(string.lower(c.class or c.name)) or c.class:match(string.lower(icon_name)) or - c.name:match(string.lower(icon_name)) then + local icon_name = string.lower(pr.icon) + if not c or not c.valid then return end + if not c.class then c.class = "" end + local class = string.lower(c.class) + icon_name = string.match(icon_name, ".*/(.*)%.[svg|png]") + if class == icon_name or class:match(icon_name) or icon_name:match(class) then if c == client.focus then col = Theme_config.dock.indicator_focused_bg elseif c.urgent then diff --git a/awesome/src/modules/init.lua b/awesome/src/modules/init.lua index 6013147..3d2b35c 100644 --- a/awesome/src/modules/init.lua +++ b/awesome/src/modules/init.lua @@ -27,6 +27,6 @@ awful.screen.connect_for_each_screen( require("src.modules.notification-center.init")(s) require("src.modules.window_switcher.init")(s) require("src.modules.application_launcher.init")(s) - require("src.modules.calendar.calendar")(s) + require("src.modules.calendar.init") { screen = s } end ) diff --git a/awesome/src/modules/notification-center/init.lua b/awesome/src/modules/notification-center/init.lua index 9d18df2..3973fef 100644 --- a/awesome/src/modules/notification-center/init.lua +++ b/awesome/src/modules/notification-center/init.lua @@ -8,6 +8,8 @@ local dpi = require("beautiful").xresources.apply_dpi local gears = require("gears") local wibox = require("wibox") +local rubato = require("src.lib.rubato") + -- Icon directory path local icondir = awful.util.getdir("config") .. "src/assets/icons/notifications/" @@ -84,92 +86,44 @@ return function(s) halign = "right", } - local left_button = wibox.widget { - { - { - widget = wibox.container.background, - bg = Theme_config.notification_center.dnd.disabled, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(8)) - end, - forced_height = dpi(30), - forced_width = dpi(30), - id = "circle" - }, - left = dpi(5), - right = dpi(5), - widget = wibox.container.margin, - id = "margin" - }, - visible = true, - valign = "center", - halign = "left", - widget = wibox.container.place, - } + local color = Theme_config.notification_center.dnd.disabled - local right_button = wibox.widget { - { - { - widget = wibox.container.background, - bg = Theme_config.notification_center.dnd.border_enabled, - shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(8)) - end, - forced_height = dpi(30), - forced_width = dpi(30), - id = "circle" - }, - left = dpi(5), - right = dpi(5), - widget = wibox.container.margin, - id = "margin" - }, - valign = "center", - halign = "right", - visible = false, - widget = wibox.container.place, - } + local function toggle_animation(pos) + if pos > 43 then return end + return function(_, _, cr, width, height) + cr:set_source(gears.color(Theme_config.notification_center.dnd.bg)); + cr:paint(); + cr:set_source(gears.color(color)) + cr:move_to(pos, 0) + local x = pos + local y = 5 + local newwidth = width / 2 - 10 + local newheight = height - 10 - local rubato = require("src.lib.rubato") + local radius = height / 6.0 + local degrees = math.pi / 180.0; - local rubato_timed = rubato.timed { duration = 1, pos = 0 } + cr:new_sub_path() + cr:arc(x + newwidth - radius, y + radius, radius, -90 * degrees, 0 * degrees) + cr:arc(x + newwidth - radius, y + newheight - radius, radius, 0 * degrees, 90 * degrees) + cr:arc(x + radius, y + newheight - radius, radius, 90 * degrees, 180 * degrees) + cr:arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees) + cr:close_path() + cr:fill() + end + end + + local rubato_timed local toggle_button = wibox.widget { { - id = "background", widget = wibox.widget { fit = function(_, width, height) return width, height end, - draw = function(_, _, cr, width, height) - -- Clear for next drawing - --cr:set_operator(cairo.Operator.CLEAR); - local function move_dnd() - cr:set_source(gears.color(Theme_config.notification_center.dnd.bg)); - cr:paint(); - cr:set_source(gears.color(Theme_config.notification_center.dnd.disabled)) - cr:move_to(rubato_timed.pos, 0) - local x = rubato_timed.pos - local y = 5 - local newwidth = width / 2 - 10 - local newheight = height - 10 - - local radius = height / 6.0 - local degrees = math.pi / 180.0; - - cr:new_sub_path() - cr:arc(x + newwidth - radius, y + radius, radius, -90 * degrees, 0 * degrees) - cr:arc(x + newwidth - radius, y + newheight - radius, radius, 0 * degrees, 90 * degrees) - cr:arc(x + radius, y + newheight - radius, radius, 90 * degrees, 180 * degrees) - cr:arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees) - cr:close_path() - cr:fill() - end - - rubato_timed:subscribe(move_dnd) - rubato_timed.target = width / 2 + 5 - end - } + draw = toggle_animation(0, Theme_config.notification_center.dnd.disabled), + }, + id = "background", }, active = false, widget = wibox.container.background, @@ -183,23 +137,36 @@ return function(s) end, } - toggle_button:connect_signal( - "button::press", - function() - if toggle_button.active then - toggle_button.active = not toggle_button.active - toggle_button.border_color = Theme_config.notification_center.dnd.border_disabled - User_config.dnd = false - rubato_timed.target = 5 - else - toggle_button.active = not toggle_button.active - toggle_button.border_color = Theme_config.notification_center.dnd.border_enabled - User_config.dnd = true - rubato_timed.target = 50 + toggle_button:buttons( + gears.table.join( + awful.button({}, 1, function() + if toggle_button.active then + toggle_button.active = not toggle_button.active + toggle_button.border_color = Theme_config.notification_center.dnd.border_disabled + color = Theme_config.notification_center.dnd.disabled + User_config.dnd = false + rubato_timed.target = 5 + else + toggle_button.active = not toggle_button.active + toggle_button.border_color = Theme_config.notification_center.dnd.border_enabled + color = Theme_config.notification_center.dnd.enabled + User_config.dnd = true + rubato_timed.target = 43 + end end - end + ) + ) ) + rubato_timed = rubato.timed { + duration = 0.5, + pos = 5, + subscribed = function(pos) + toggle_button:get_children_by_id("background")[1].draw = toggle_animation(pos) + toggle_button:emit_signal("widget::redraw_needed") + end + } + local dnd = wibox.widget { { { diff --git a/awesome/src/modules/notification-center/song_info.lua b/awesome/src/modules/notification-center/song_info.lua index 1e97ce9..f31569b 100644 --- a/awesome/src/modules/notification-center/song_info.lua +++ b/awesome/src/modules/notification-center/song_info.lua @@ -482,7 +482,8 @@ return function(s) autostart = true, call_now = true, callback = function() - get_spotify_metadata() + --!Rewrite entire playerctl module for better performance + --get_spotify_metadata() end } diff --git a/awesome/src/theme/theme_config.lua b/awesome/src/theme/theme_config.lua index 31cddf0..fd737ac 100644 --- a/awesome/src/theme/theme_config.lua +++ b/awesome/src/theme/theme_config.lua @@ -149,6 +149,9 @@ Theme_config.calendar = { fg = color["Grey100"], border_color = color["Grey800"], border_width = dpi(2), + shape = function(cr, w, h) + gears.shape.rounded_rect(cr, w, h, dpi(8)) + end, day = { today_border_color = color["Blue200"], bg = color["Grey900"], @@ -160,7 +163,7 @@ Theme_config.calendar = { border_color = color["Grey800"], border_width = dpi(2), shape = function(cr, width, height) - gears.shape.rounded_rect(cr, width, height, dpi(4)) + gears.shape.rounded_rect(cr, width, height, dpi(8)) end, }, task = { diff --git a/awesome/src/theme/user_config.lua b/awesome/src/theme/user_config.lua index a14fe93..5a5d4f9 100644 --- a/awesome/src/theme/user_config.lua +++ b/awesome/src/theme/user_config.lua @@ -20,11 +20,8 @@ User_config = { "picom --experimental-backends", "xfce4-power-manager", "light-locker --lock-on-suspend --lock-on-lid &", - "spotify", - "discord", "/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1", "setxkbmap -option caps:swapescape", - "jamesdsp" }, --[[ diff --git a/awesome/src/tools/auto_starter.lua b/awesome/src/tools/auto_starter.lua index dd13865..4807b7f 100644 --- a/awesome/src/tools/auto_starter.lua +++ b/awesome/src/tools/auto_starter.lua @@ -1,7 +1,20 @@ local awful = require("awful") +local Gio = require("lgi").Gio +local gears = require("gears") return function(table) for _, t in ipairs(table) do awful.spawn(t); end + local path = gears.filesystem.get_xdg_config_home() .. "autostart/" + local handler = io.popen("ls " .. path) + if not handler then return end + + for file in handler:lines() do + local app = Gio.DesktopAppInfo.new_from_filename(path .. file) + if app then + Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(Gio.DesktopAppInfo.get_string(app, + "Exec"), nil, 0)) + end + end end diff --git a/awesome/src/tools/gio_icon_lookup.lua b/awesome/src/tools/gio_icon_lookup.lua index c43411a..e6b1fc0 100644 --- a/awesome/src/tools/gio_icon_lookup.lua +++ b/awesome/src/tools/gio_icon_lookup.lua @@ -39,9 +39,9 @@ function Get_icon(class, name) local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon") if icon_string then icon_string = string.lower(icon_string) - if icon_string:match(class) or class:match(icon_string) then + if icon_string == class or icon_string == name then return Get_gicon_path(app_info.get_icon(app)) - elseif icon_string:match(name) or name:match(icon_string) then + elseif icon_string:match(class) then return Get_gicon_path(app_info.get_icon(app)) end end diff --git a/awesome/src/tools/helpers/audio.lua b/awesome/src/tools/helpers/audio.lua index 75602ab..a6e54fd 100644 --- a/awesome/src/tools/helpers/audio.lua +++ b/awesome/src/tools/helpers/audio.lua @@ -1,5 +1,23 @@ local awful = require("awful") +--[[ local lgi = require("lgi") +local pulseaudio = require("lua_libpulse_glib") +local ppretty = require("pl.ppretty") + +local pa = pulseaudio.new() + +local ctx = pa:context("My Test App") + +ctx:connect(nil, function(state) + if state == 4 then + print("Connection is ready") + + ctx:get_sinks(function(sinks) + ppretty.dump(sinks) + end) + end +end) ]] + awful.spawn.with_line_callback( [[bash -c "LC_ALL=C pactl subscribe"]], { diff --git a/awesome/src/tools/helpers/cpu_usage.lua b/awesome/src/tools/helpers/cpu_usage.lua index 55201e2..e4cdefc 100644 --- a/awesome/src/tools/helpers/cpu_usage.lua +++ b/awesome/src/tools/helpers/cpu_usage.lua @@ -4,12 +4,13 @@ local watch = awful.widget.watch local total_prev = 0 local idle_prev = 0 +--!Find a better way that doesn't need manual GC since it has a huge performance impact watch( [[ cat "/proc/stat" | grep '^cpu ' ]], 3, function(_, stdout) - local user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice = - stdout:match("(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s") + local user, nice, system, idle, iowait, irq, softirq, steal = + stdout:match("(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s") local total = user + nice + system + idle + iowait + irq + softirq + steal @@ -21,6 +22,7 @@ watch( total_prev = total idle_prev = idle + collectgarbage("collect") end ) diff --git a/awesome/src/tools/helpers/init.lua b/awesome/src/tools/helpers/init.lua index 87470cb..a3b2b71 100644 --- a/awesome/src/tools/helpers/init.lua +++ b/awesome/src/tools/helpers/init.lua @@ -1,8 +1,9 @@ require("src.tools.helpers.cpu_temp") -require("src.tools.helpers.cpu_usage") +--!Find a better way that doesn't need manual GC since it has a huge performance impact +--require("src.tools.helpers.cpu_usage") require("src.tools.helpers.cpu_freq") require("src.tools.helpers.ram") require("src.tools.helpers.gpu_usage") require("src.tools.helpers.gpu_temp") require("src.tools.helpers.audio") ---require("src.tools.helpers.backlight") +require("src.tools.helpers.backlight") diff --git a/awesome/src/tools/helpers/playerctl.lua b/awesome/src/tools/helpers/playerctl.lua new file mode 100644 index 0000000..5d3471e --- /dev/null +++ b/awesome/src/tools/helpers/playerctl.lua @@ -0,0 +1,345 @@ +-- 99.9% Stolen from bling + +local gobject = require("gears.object") +local gtable = require("gears.table") +local gtimer = require("gears.timer") +local gstring = require("gears.string") + +local playerctl = { mt = {} } +playerctl._private = {} + +function playerctl:play_pause(player) + player = player or self._private.manager.players[1] + if player then + player:play_pause() + end +end + +function playerctl:next(player) + player = player or self._private.manager.players[1] + if player then + player:next() + end +end + +function playerctl:previous(player) + player = player or self._private.manager.players[1] + if player then + player:previous() + end +end + +function playerctl:cycle_loop(player) + player = player or self._private.manager.players[1] + if player then + local loop_status = player.loop_status + if loop_status == "NONE" then + player:set_loop_status("TRACK") + elseif loop_status == "TRACK" then + player:set_loop_status("PLAYLIST") + elseif loop_status == "PLAYLIST" then + player:set_loop_status("NONE") + end + end +end + +function playerctl:cycle_shuffle(player) + player = player or self._private.manager.players[1] + if player then + player:set_shuffle(not player.shuffle) + end +end + +function playerctl:set_position(position, player) + player = player or self._private.manager.players[1] + if player then + player:set_position(position * 1000000) + end +end + +function playerctl:get_manager() + return self._private.manager +end + +function playerctl:get_current_player() + return self._private.manager.players[1].name +end + +local function emit_metadata_callback(self, title, artist, art_url, album, new, player_name) + title = gstring.xml_escape(title) + artist = gstring.xml_escape(artist) + album = gstring.xml_escape(album) + + if player_name == "spotify" then + art_url = art_url:gsub("open.spotify.com", "i.scdn.co") + end + + if not art_url or art_url == "" then + else + awesome.emit_signal("playerctl::title_artist_album", title, artist, "", player_name) + self:emit_signal("metadata", title, artist, "", album, new, player_name) + end +end + +local function metadata_callback(self, player, metadata) + if self.update_on_activity then + self._private.manager:mover_player_to_front(player) + end + + local data = metadata.value + local title = data["xesam:title"] or "" + local artist = data["xesam:artist"] or "" + for i = 2, #data["xesam:artist"] do + artist = artist .. ", " .. data["xesam:artist"][i] + end + local art_url = data["mpris:artUrl"] or "" + local album = data["xesam:album"] or "" + + if player == self._private.manager.players[1] then + if (not player == self._private.last_player) or (not title == self._private.manager.last_title) or + (not artist == self._private.manager.last_artist) or (not art_url == self._private.manager.last_art_url) then + if (title == "") and (artist == "") and (art_url == "") then return end + + if (not self._private.metadata_timer) and self._private.metadata_timer.started then + self._private.metadata_timer:stop() + end + + self._private.metadata_timer = gtimer { + timeout = 1, + autostart = true, + single_shot = true, + callback = function() + emit_metadata_callback(self, title, artist, art_url, album, true, player.name) + end + } + + self._private.manager.pos_timer:again() + self._private.manager.last_title = title + self._private.manager.last_artist = artist + self._private.manager.last_art_url = art_url + self._private.last_player = player + end + end +end + +local function pos_callback(self) + local player = self._private.manager.players[1] + if player then + local pos = player:get_position() / 1000000 + local dur = (player.metadata.value["mpris:length"] or 0) / 1000000 + if (not pos == self._private.last_pos) or (not dur == self._private.last_length) then + self._private.pos = pos + self._private.dur = dur + self:emit_signal("position", pos, dur, player.player_name) + end + end +end + +local function playback_status_callback(self, player, status) + if self.update_on_activity then + self._private.manager:mover_player_to_front(player) + end + + if player == self._private.manager.players[1] then + self._private.active_player = player + + if status == "PLAYING" then + self:emit_signal("playerctl::playback_status", true, player.player_name) + awesome.emit_signal("playerctl::playback_status", true, player.player_name) + else + self:emit_signal("playerctl::playback_status", false, player.player_name) + awesome.emit_signal("playerctl::playback_status", false, player.player_name) + end + end +end + +local function loop_callback(self, player, loop_status) + if self.update_on_activity then + self._private.manager:mover_player_to_front(player) + end + + if player == self._private.manager.players[1] then + self._private.active_player = player + self:emit_signal("loop_status", loop_status, player.player_name) + end + +end + +local function shuffle_callback(self, player, shuffle) + if self.update_on_activity then + self._private.manager:mover_player_to_front(player) + end + + if player == self._private.manager.players[1] then + self._private.active_player = player + self:emit_signal("shuffle", shuffle, player.player_name) + end +end + +local function exit_callback(self, player) + if player == self._private.manager.players[1] then + self:emit_signal("playerctl::exit", player.player_name) + end +end + +local function name_is_selected(self, name) + if self.ignore[name.name] then + return false + end + if self.priority > 0 then + for _, arg in pairs(self.priority) do + if arg == name.name or arg == "%any" then + return true + end + end + return false + end +end + +local function init_player(self, name) + if name_is_selected(self, name) then + local player = self._private.Playerctl.Player.new_from_name(name) + self._private.manager:manage_player(player) + player.on_metadata = function(p, m) + metadata_callback(self, p, m) + end + player.on_playback_status = function(p, s) + playback_status_callback(self, p, s) + end + player.on_loop_status = function(p, s) + loop_callback(self, p, s) + end + player.on_shuffle = function(p, s) + shuffle_callback(self, p, s) + end + player.on_exit = function(p) + exit_callback(self, p) + end + + if not self._private.pos_timer.started then + self._private.pos_timer:start() + end + end +end + +local function player_compare(self, a, b) + local player_a = self._private.Playerctl.Player(a) + local player_b = self._private.Playerctl.Player(b) + local i = math.huge + local ai = nil + local bi = nil + + if player_a == player_b then + return 0 + end + + for index, name in ipairs(self.priority) do + if name == "%any" then + i = (i == math.huge) and index or i + elseif name == player_a.player_name then + ai = ai or index + elseif name == player_b.player_name then + bi = bi or index + end + end + + if not ai and not bi then + return 0 + elseif not ai then + return (bi < i) and 1 or -1 + elseif not bi then + return (ai < i) and -1 or 1 + elseif ai == bi then + return 0 + else + return (ai < bi) and -1 or 1 + end +end + +local function get_current_player(self, player) + local title = player:get_title() or "Unknown" + local artist = player:get_artist() or "Unknown" + local album = player:get_album() or "Unknown" + local art_url = player:print_metadata_prop("mpris:artUtl") or "" + + emit_metadata_callback(self, title, artist, art_url, album, false, player.player_name) + playback_status_callback(self, player, player.playback_status) + loop_callback(self, player, player.loop_status) +end + +local function start_manager(self) + self._private.manager = self.private.Playerctl.PlayerManager() + + if #self.priority > 0 then + self._private.manager:set_sort_func(function(a, b) + return player_compare(self, a, b) + end) + end + + self._private.pos_timer = gtimer { + timeout = 1, + callback = function() + pos_callback(self) + end + } + + for _, name in ipairs(self._private.manager.player_names) do + init_player(self, name) + end + + if self._private.manager.players[1] then + get_current_player(self, self._private.manager.players[1]) + end + + local _self = self + + function self._private.manager:on_name_appeared(name) + init_player(_self, name) + end + + function self._private.manager:on_player_appeared(player) + if player == self.players[1] then + _self._private.active_player = player + end + end + + function self._private.manager:on_player_vanished(player) + if #self.players == 0 then + _self._private.metadata_timer:stop() + _self._private.pos_timer:stop() + _self:emit_signal("playerctl::noplayers") + awesome.emit_signal("playerctl::noplayers") + elseif player == _self._private.active_player then + _self._private.active_player = self.players[1] + get_current_player(_self, _self._private.active_player) + end + end +end + +function playerctl.new(args) + args = args or {} + + local ret = gobject {} + gtable.crush(ret, playerctl, true) + + ret.update_on_activity = true + ret.interval = 1 + + + ret._private = {} + + ret._private.Playerctl = require("lgi").Playerctl + ret._private.manager = nil + + gtimer.delayed_call(function() + start_manager(ret) + end) + + return ret +end + +function playerctl.mt:__call(...) + return playerctl.new(...) +end + +return setmetatable(playerctl, playerctl.mt) diff --git a/awesome/src/tools/ical_parser.lua b/awesome/src/tools/ical_parser.lua index 7490f99..e7ac7a0 100644 --- a/awesome/src/tools/ical_parser.lua +++ b/awesome/src/tools/ical_parser.lua @@ -1,6 +1,14 @@ -local ical = {} +local gfilesystem = require("gears.filesystem") +local gobject = require("gears.object") +local gtable = require("gears.table") +local naughty = require("naughty") + +local json = require("src.lib.json-lua.json-lua") + +local ical = { mt = {} } ical.VCALENDAR = {} ical._private = {} +ical._private.cache = {} ical._private.parser = {} --[[ @@ -63,24 +71,74 @@ ical._private.parser = {} DTSTAMP = "...", ]] ----Takes a path to an .ical file then parses it into a lua table and returns it ----@param path string Path to the .ical file ----@return table | nil calendar New calendar table or nil on error -function ical.new(path) - local handler = io.open(path, "r") +function ical._private.add_to_cache(file, vcal) + -- Copy file to src/config/files/calendar/ + local path = gfilesystem.get_configuration_dir() .. "src/config/" + local file_name = file:match(".*/(.*)") + if not + os.execute("cp " .. + file .. " " .. gfilesystem.get_configuration_dir() .. "src/config/files/calendar/" .. file_name) then + naughty.notification({ + app_name = "Systemnotification", + title = "Error", + text = "Could not copy file to config/files/calendar/", + timeout = 0, + urgency = "critical", + }) + return + end + local handler = io.open(path .. "calendar.json", "r") + if not handler then return end + local json_data = json:decode(handler:read("a")) + handler:close() + if not (type(json_data) == "table") then return end + table.insert(json_data, { + file = file_name, + VCALENDAR = vcal, + }) + + json_data = json:encode(json_data) + + handler = io.open(path .. "calendar.json", "w") + if not handler then return end + handler:write(json_data) + handler:close() +end + +function ical:add_calendar(file) + local handler = io.open(file, "r") if not handler then return end -- Check if the line is a BEGIN:VCALENDAR local v, k = handler:read("l"):match("([A-Z]+):([A-Z]+)") + local vcal = {} if v:match("BEGIN") and k:match("VCALENDAR") then - table.insert(ical.VCALENDAR, ical._private.parser.VCALENDAR(handler)) - return ical + vcal = self._private.parser.VCALENDAR(handler) + table.insert(self.VCALENDAR, vcal) + self._private.add_to_cache(file, vcal) + end +end + +function ical.new(args) + args = args or {} + local ret = gobject {} + gtable.crush(ret, ical, true) + local path = gfilesystem.get_configuration_dir() .. "src/config/calendar.json" + local handler = io.open(path, "r") + if not handler then return end + local json_data = json:decode(handler:read("a")) + handler:close() + if not (type(json_data) == "table") then return end + --Load into the cache + for _, v in ipairs(json_data) do + ret._private.cache[v.file] = v.VCALENDAR + table.insert(ret.VCALENDAR, v.VCALENDAR) end return ical end -function ical._private.parser.VEVENT(handler) +function ical._private.parser:VEVENT(handler) local VEVENT = {} while true do @@ -92,11 +150,11 @@ function ical._private.parser.VEVENT(handler) local v, k = line:match("(.*):(.*)") if v:match("CREATED") then - VEVENT.CREATED = ical._private.parser.to_datetime(k) + VEVENT.CREATED = self._private.parser.to_datetime(k) elseif v:match("LAST-MODIFIED") then - VEVENT.LAST_MODIFIED = ical._private.parser.to_datetime(k) + VEVENT.LAST_MODIFIED = self._private.parser.to_datetime(k) elseif v:match("DTSTAMP") then - VEVENT.DTSTAMP = ical._private.parser.to_datetime(k) + VEVENT.DTSTAMP = self._private.parser.to_datetime(k) elseif v:match("UID") then VEVENT.UID = k elseif v:match("SUMMARY") then @@ -104,20 +162,20 @@ function ical._private.parser.VEVENT(handler) elseif v:match("RRULE") then VEVENT.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), - UNTIL = ical._private.parser.to_datetime(k:match("UNTIL=([TZ0-9]+)")), + UNTIL = self._private.parser.to_datetime(k:match("UNTIL=([TZ0-9]+)")), WKST = k:match("WKST=([A-Z]+)"), COUNT = k:match("COUNT=([0-9]+)"), INTERVAL = k:match("INTERVAL=([0-9]+)") } elseif v:match("DTSTART") then VEVENT.DTSTART = { - DTSTART = ical._private.parser.to_datetime(k), + DTSTART = self._private.parser.to_datetime(k), TZID = v:match("TZID=([a-zA-Z-\\/]+)"), VALUE = v:match("VALUE=([A-Z]+)") } elseif v:match("DTEND") then VEVENT.DTEND = { - DTEND = ical._private.parser.to_datetime(k), + DTEND = self._private.parser.to_datetime(k), TZID = v:match("TZID=([a-zA-Z-\\/]+)"), VALUE = v:match("VALUE=([A-Z]+)") } @@ -134,11 +192,12 @@ function ical._private.parser.VEVENT(handler) } elseif v:match("BEGIN") then if k:match("VALARM") then - VEVENT.VALARM = ical._private.parser.VALARM(handler) + VEVENT.VALARM = self._private.parser:VALARM(handler) end + elseif v:match("UID") then + VEVENT.UID = k end end - --VEVENT.duration = VEVENT.DTSTART.DTSTART - VEVENT.DTEND.DTEND return VEVENT @@ -153,7 +212,7 @@ function ical._private.parser.alarm_to_time(alarm) return time .. unit end -function ical._private.parser.VALARM(handler) +function ical._private.parser:VALARM(handler) local VALARM = {} while true do @@ -169,7 +228,7 @@ function ical._private.parser.VALARM(handler) elseif v:match("TRIGGER;VALUE=DURATION") then VALARM.TRIGGER = { VALUE = v:match("VALUE=(.*):"), - TRIGGER = ical._private.parser.alarm_to_time(k) + TRIGGER = self._private.parser.alarm_to_time(k) } elseif v:match("DESCRIPTION") then VALARM.DESCRIPTION = k @@ -179,7 +238,7 @@ function ical._private.parser.VALARM(handler) return VALARM end -function ical._private.parser.VCALENDAR(handler) +function ical._private.parser:VCALENDAR(handler) local VCALENDAR = {} VCALENDAR.VEVENT = {} VCALENDAR.VTIMEZONE = {} @@ -199,9 +258,9 @@ function ical._private.parser.VCALENDAR(handler) VCALENDAR.VERSION = k elseif v:match("BEGIN") then if k:match("VTIMEZONE") then - VCALENDAR.VTIMEZONE = ical._private.parser.VTIMEZONE(handler) + VCALENDAR.VTIMEZONE = self._private.parser:VTIMEZONE(handler) elseif k:match("VEVENT") then - table.insert(VCALENDAR.VEVENT, ical._private.parser.VEVENT(handler)) + table.insert(VCALENDAR.VEVENT, self._private.parser:VEVENT(handler)) end end end @@ -211,7 +270,7 @@ function ical._private.parser.VCALENDAR(handler) return VCALENDAR end -function ical._private.parser.VTIMEZONE(handler) +function ical._private.parser:VTIMEZONE(handler) local VTIMEZONE = {} while true do @@ -227,9 +286,9 @@ function ical._private.parser.VTIMEZONE(handler) end if v:match("BEGIN") then if k:match("DAYLIGHT") then - VTIMEZONE.DAYLIGHT = ical._private.parser.DAYLIGHT(handler) + VTIMEZONE.DAYLIGHT = self._private.parser:DAYLIGHT(handler) elseif k:match("STANDARD") then - VTIMEZONE.STANDARD = ical._private.parser.STANDARD(handler) + VTIMEZONE.STANDARD = self._private.parser:STANDARD(handler) end end end @@ -237,7 +296,7 @@ function ical._private.parser.VTIMEZONE(handler) return VTIMEZONE end -function ical._private.parser.DAYLIGHT(handler) +function ical._private.parser:DAYLIGHT(handler) local DAYLIGHT = {} while true do @@ -249,13 +308,13 @@ function ical._private.parser.DAYLIGHT(handler) local v, k = line:match("(.*):(.*)") if v:match("TZOFFSETFROM") then - DAYLIGHT.TZOFFSETFROM = ical._private.parser.offset(k) + DAYLIGHT.TZOFFSETFROM = self._private.parser.offset(k) elseif v:match("TZOFFSETTO") then - DAYLIGHT.TZOFFSETTO = ical._private.parser.offset(k) + DAYLIGHT.TZOFFSETTO = self._private.parser.offset(k) elseif v:match("TZNAME") then DAYLIGHT.TZNAME = k elseif v:match("DTSTART") then - DAYLIGHT.DTSTART = ical._private.parser.to_datetime(k) + DAYLIGHT.DTSTART = self._private.parser.to_datetime(k) elseif v:match("RRULE") then DAYLIGHT.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), @@ -271,7 +330,7 @@ end ---Parses the STANDARD property into a table ---@param handler table ---@return table STANDARD The STANDARD property as a table -function ical._private.parser.STANDARD(handler) +function ical._private.parser:STANDARD(handler) local STANDARD = {} -- Read each line until END:STANDARD is read @@ -285,13 +344,13 @@ function ical._private.parser.STANDARD(handler) -- Break down each line into the property:value local v, k = line:match("(.*):(.*)") if v:match("TZOFFSETFROM") then - STANDARD.TZOFFSETFROM = ical._private.parser.offset(k) + STANDARD.TZOFFSETFROM = self._private.parser.offset(k) elseif v:match("TZOFFSETTO") then - STANDARD.TZOFFSETTO = ical._private.parser.offset(k) + STANDARD.TZOFFSETTO = self._private.parser.offset(k) elseif v:match("TZNAME") then STANDARD.TZNAME = k elseif v:match("DTSTART") then - STANDARD.DTSTART = ical._private.parser.to_datetime(k) + STANDARD.DTSTART = self._private.parser.to_datetime(k) elseif v:match("RRULE") then STANDARD.RRULE = { FREQ = k:match("FREQ=([A-Z]+)"), @@ -329,4 +388,8 @@ function ical._private.parser.offset(offset) return s * (tonumber(h) * 3600 + tonumber(m) * 60) end -return ical +function ical.mt:__call(...) + return ical.new(...) +end + +return setmetatable(ical, ical.mt) diff --git a/awesome/src/widgets/taglist.lua b/awesome/src/widgets/taglist.lua index e562aac..5c6c0ba 100644 --- a/awesome/src/widgets/taglist.lua +++ b/awesome/src/widgets/taglist.lua @@ -67,64 +67,17 @@ local list_update = function(widget, buttons, _, _, objects) tag_widget:buttons(create_buttons(buttons, object)) - --#region Rubato and Color animation - - -- Background rubato init - local r_timed_bg = rubato.timed { duration = 0.5 } - local g_timed_bg = rubato.timed { duration = 0.5 } - local b_timed_bg = rubato.timed { duration = 0.5 } - - -- starting color - r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos = color.utils.hex_to_rgba(Theme_config.taglist.bg) - - - -- Foreground rubato init - local r_timed_fg = rubato.timed { duration = 0.5 } - local g_timed_fg = rubato.timed { duration = 0.5 } - local b_timed_fg = rubato.timed { duration = 0.5 } - - -- starting color - r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos = color.utils.hex_to_rgba(Theme_config.taglist.fg) - - -- Subscribable function to have rubato set the bg/fg color - local function update_bg() - tag_widget:set_bg("#" .. - color.utils.rgba_to_hex { math.max(0, r_timed_bg.pos), math.max(0, g_timed_bg.pos), math.max(0, b_timed_bg.pos) }) - end - - local function update_fg() - tag_widget:set_fg("#" .. - color.utils.rgba_to_hex { math.max(0, r_timed_fg.pos), math.max(0, g_timed_fg.pos), math.max(0, b_timed_fg.pos) }) - end - - -- Subscribe to the function bg and fg - r_timed_bg:subscribe(update_bg) - g_timed_bg:subscribe(update_bg) - b_timed_bg:subscribe(update_bg) - r_timed_fg:subscribe(update_fg) - g_timed_fg:subscribe(update_fg) - b_timed_fg:subscribe(update_fg) - - -- Both functions to set a color, if called they take a new color - local function set_bg(newbg) - r_timed_bg.target, g_timed_bg.target, b_timed_bg.target = color.utils.hex_to_rgba(newbg) - end - - local function set_fg(newfg) - r_timed_fg.target, g_timed_fg.target, b_timed_fg.target = color.utils.hex_to_rgba(newfg) - end - tag_widget.container.margin.label:set_text(object.index) -- Use the wraper function to call the set_bg and set_fg based on the client state - if object.urgent == true then - set_bg(Theme_config.taglist.bg_urgent) - set_fg(Theme_config.taglist.fg_urgent) - elseif object == awful.screen.focused().selected_tag then - set_bg(Theme_config.taglist.bg_focus) - set_fg(Theme_config.taglist.fg_focus) + if object == awful.screen.focused().selected_tag then + tag_widget:set_bg(Theme_config.taglist.bg_focus) + tag_widget:set_fg(Theme_config.taglist.fg_focus) + elseif object.urgent == true then + tag_widget:set_bg(Theme_config.taglist.bg_urgent) + tag_widget:set_fg(Theme_config.taglist.fg_urgent) else - set_fg(Theme_config.taglist.fg) - set_bg(Theme_config.taglist.bg) + tag_widget:set_bg(Theme_config.taglist.bg) + tag_widget:set_fg(Theme_config.taglist.fg) end --#endregion @@ -154,6 +107,16 @@ local list_update = function(widget, buttons, _, _, objects) strategy = "exact", layout = wibox.container.constraint, }) + + --[[ awful.spawn.easy_async_with_shell( + "ps -o cmd " .. client.pid .. " | tail -n 1", + function(stdout) + local cmd = stdout:gsub("\n", "") + local app_info = Gio.AppInfo.create_from_commandline(cmd, client.name, {}) + local exec = Gio.AppInfo.get_executable(app_info) + icon:get_children_by_id("icon")[1].image = Get_icon(exec) + end + ) ]] end Hover_signal(tag_widget) diff --git a/awesome/src/widgets/tasklist.lua b/awesome/src/widgets/tasklist.lua index 140096b..2ec50ad 100644 --- a/awesome/src/widgets/tasklist.lua +++ b/awesome/src/widgets/tasklist.lua @@ -94,54 +94,6 @@ local list_update = function(widget, buttons, label, _, objects) local text, _ = label(object, task_widget.container.layout_it.title) - - --#region Rubato and Color animation - - -- Background rubato init - local r_timed_bg = rubato.timed { duration = 0.5 } - local g_timed_bg = rubato.timed { duration = 0.5 } - local b_timed_bg = rubato.timed { duration = 0.5 } - - -- starting color - r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos = color.utils.hex_to_rgba(Theme_config.tasklist.bg) - - - -- Foreground rubato init - local r_timed_fg = rubato.timed { duration = 0.5 } - local g_timed_fg = rubato.timed { duration = 0.5 } - local b_timed_fg = rubato.timed { duration = 0.5 } - - -- starting color - r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos = color.utils.hex_to_rgba(Theme_config.tasklist.fg) - - -- Subscribable function to have rubato set the bg/fg color - local function update_bg() - task_widget:set_bg("#" .. color.utils.rgba_to_hex { r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos }) - end - - local function update_fg() - task_widget:set_fg("#" .. color.utils.rgba_to_hex { r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos }) - end - - -- Subscribe to the function bg and fg - r_timed_bg:subscribe(update_bg) - g_timed_bg:subscribe(update_bg) - b_timed_bg:subscribe(update_bg) - r_timed_fg:subscribe(update_fg) - g_timed_fg:subscribe(update_fg) - b_timed_fg:subscribe(update_fg) - - -- Both functions to set a color, if called they take a new color - local function set_bg(newbg) - r_timed_bg.target, g_timed_bg.target, b_timed_bg.target = color.utils.hex_to_rgba(newbg) - end - - local function set_fg(newfg) - r_timed_fg.target, g_timed_fg.target, b_timed_fg.target = color.utils.hex_to_rgba(newfg) - end - - --#endregion - if object == client.focus then if text == nil or text == '' then task_widget.container.layout_it.title:set_margins(0) @@ -159,11 +111,11 @@ local list_update = function(widget, buttons, label, _, objects) task_tool_tip:remove_from_object(task_widget) end end - set_bg(Theme_config.tasklist.bg_focus) - set_fg(Theme_config.tasklist.fg_focus) + task_widget:set_bg(Theme_config.tasklist.bg_focus) + task_widget:set_fg(Theme_config.tasklist.fg_focus) task_widget.container.layout_it.title:set_text(text) else - set_bg(Theme_config.tasklist.bg) + task_widget:set_bg(Theme_config.tasklist.bg) task_widget.container.layout_it.title:set_text('') end