aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.config/awesome/assets/phosphor/bell-simple-slash-fill.svg1
-rw-r--r--.config/awesome/misc/autostart.lua1
-rw-r--r--.config/awesome/misc/init.lua2
-rw-r--r--.config/awesome/misc/keys.lua8
-rw-r--r--.config/awesome/quarrel/debug.lua39
-rw-r--r--.config/awesome/quarrel/persistent.lua18
-rw-r--r--.config/awesome/quarrel/ui/init.lua3
-rw-r--r--.config/awesome/services/dnd.lua18
-rw-r--r--.config/awesome/services/time.lua18
-rw-r--r--.config/awesome/signals/client.lua26
-rw-r--r--.config/awesome/test_rc.lua22
-rw-r--r--.config/awesome/ui/fresnel/text_input.lua934
-rw-r--r--.config/awesome/ui/init.lua16
-rw-r--r--.config/awesome/ui/osd/providers/mpris.lua3
-rw-r--r--.config/awesome/ui/statusbar/init.lua32
-rw-r--r--.config/awesome/ui/statusbar/panel/init.lua14
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/calendar.lua143
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/notifs/consts.lua13
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/notifs/init.lua0
-rw-r--r--.config/awesome/ui/statusbar/panel/widgets/notifs/widgets/notif.lua214
-rw-r--r--.config/awesome/ui/statusbar/widgets/dnd.lua34
-rw-r--r--.config/awesome/ui/tidy/init.lua94
-rw-r--r--.config/awesome/ui/wicked/consts.lua6
-rw-r--r--.config/awesome/ui/wicked/init.lua16
24 files changed, 1566 insertions, 109 deletions
diff --git a/.config/awesome/assets/phosphor/bell-simple-slash-fill.svg b/.config/awesome/assets/phosphor/bell-simple-slash-fill.svg
new file mode 100644
index 0000000..f98e66f
--- /dev/null
+++ b/.config/awesome/assets/phosphor/bell-simple-slash-fill.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" fill="#000000" viewBox="0 0 256 256"><path d="M221.84,192v0a1.85,1.85,0,0,1-3,.28L83.27,43.19a4,4,0,0,1,.8-6A79.55,79.55,0,0,1,129.17,24C173,24.66,207.8,61.1,208,104.92c.14,34.88,8.31,61.54,13.82,71A15.89,15.89,0,0,1,221.84,192ZM160,216H96.22A8.19,8.19,0,0,0,88,223.47,8,8,0,0,0,96,232h63.74a8.19,8.19,0,0,0,8.26-7.47A8,8,0,0,0,160,216ZM53.84,34.62A8,8,0,1,0,42,45.38L58.79,63.85A79.42,79.42,0,0,0,47.93,104c0,35.09-8.15,62-13.7,71.73a16.42,16.42,0,0,0,.09,16.68A15.78,15.78,0,0,0,47.91,200H182.62l19.45,21.38a8,8,0,0,0,11.85-10.76Z"></path></svg> \ No newline at end of file
diff --git a/.config/awesome/misc/autostart.lua b/.config/awesome/misc/autostart.lua
index 291e39d..de79c65 100644
--- a/.config/awesome/misc/autostart.lua
+++ b/.config/awesome/misc/autostart.lua
@@ -5,6 +5,7 @@ if qpersistent.is_restart() then
return
end
+-- local programs = {}
local programs = {
"picom -b",
"sxhkd",
diff --git a/.config/awesome/misc/init.lua b/.config/awesome/misc/init.lua
index d3c36b2..069046a 100644
--- a/.config/awesome/misc/init.lua
+++ b/.config/awesome/misc/init.lua
@@ -1,3 +1,3 @@
require "misc.keys"
require "misc.rules"
-require "misc.autostart"
+-- require "misc.autostart"
diff --git a/.config/awesome/misc/keys.lua b/.config/awesome/misc/keys.lua
index b36808b..b7dc4c4 100644
--- a/.config/awesome/misc/keys.lua
+++ b/.config/awesome/misc/keys.lua
@@ -12,6 +12,7 @@ local mpris = require "ui.statusbar.panel.widgets.mpris"
local playerctl = require "services.playerctl"
local powermenu = require "ui.powermenu"
local qbind = require "quarrel.bind"
+local dnd = require "services.dnd"
local recording = { false, "" }
@@ -371,4 +372,11 @@ awful.keyboard.append_global_keybindings {
group = "misc",
desc = "scroll up/down",
},
+ qbind {
+ mods = qbind.mods.M,
+ triggers = "`",
+ press = function()
+ dnd.dnd = not dnd.dnd
+ end
+ }
}
diff --git a/.config/awesome/quarrel/debug.lua b/.config/awesome/quarrel/debug.lua
new file mode 100644
index 0000000..54fc317
--- /dev/null
+++ b/.config/awesome/quarrel/debug.lua
@@ -0,0 +1,39 @@
+local n = require("naughty").notification
+local gdebug = require "gears.debug"
+
+---@class QuarrelDebug
+local M = {}
+
+--- Send a notification with the specified message
+---@param message any
+function M.debug(message)
+ if type(message) == "table" then
+ gdebug.dump(message, "data", 8)
+ n { message = "Dumped table!", app_name = "QDebug", level = "debug" }
+ else
+ n { message = tostring(message), app_name = "QDebug", level = "debug" }
+ end
+end
+
+--- Print an info message to stdout and send a notification at the same time
+---@param message any
+function M.info(message)
+ print("[QDebug]: " .. tostring(message))
+ n { message = message, app_name = "QDebug", level = "info" }
+end
+
+--- Print a warning to stderr and send a notification at the same time
+---@param message any
+function M.warn(message)
+ gdebug.print_warning("[QDebug]: " .. tostring(message))
+ n { message = message, app_name = "QDebug", level = "warn" }
+end
+
+--- Print an error to stderr and send a notification at the same time
+---@param message any
+function M.error(message)
+ gdebug.print_warning("[QDebug]: " .. tostring(message))
+ n { message = message, app_name = "QDebug", level = "error" }
+end
+
+return M
diff --git a/.config/awesome/quarrel/persistent.lua b/.config/awesome/quarrel/persistent.lua
index 2b15c89..193affc 100644
--- a/.config/awesome/quarrel/persistent.lua
+++ b/.config/awesome/quarrel/persistent.lua
@@ -2,7 +2,7 @@ local gdebug = require "gears.debug"
local qfs = require "quarrel.fs"
local qjson = require "quarrel.json"
-awesome.register_xproperty("is_restart", "boolean")
+-- awesome.register_xproperty("is_restart", "boolean")
---@alias QPersistentValue string|number|table|nil|boolean
@@ -29,7 +29,13 @@ end
--- Check if there was a restart
---@return boolean
function qpersistent.is_restart()
- return awesome.get_xproperty "is_restart" ~= nil
+ local f=io.open("/tmp/qpersistent-marker", "r")
+ if f then
+ io.close(f)
+ end
+
+ return not not f
+ -- return awesome.get_xproperty "is_restart" ~= nil
end
do
@@ -55,7 +61,13 @@ awesome.connect_signal("exit", function(restart)
end
if not qpersistent.is_restart() then
- awesome.set_xproperty("is_restart", true)
+ local f = io.open("/tmp/qpersistent-marker", "w")
+ if not f then
+ gdebug.print_error "failed to create the marker file"
+ return
+ end
+ f:close()
+ -- awesome.set_xproperty("is_restart", true)
end
end)
diff --git a/.config/awesome/quarrel/ui/init.lua b/.config/awesome/quarrel/ui/init.lua
index 2b63694..5e68b1d 100644
--- a/.config/awesome/quarrel/ui/init.lua
+++ b/.config/awesome/quarrel/ui/init.lua
@@ -79,9 +79,10 @@ function M.recolor(color)
end
--- Generates icon widget
----@param args table
+---@param args? table
---@return table
function M.separator(args)
+ args = args or {}
return wibox.widget(gtable.crush({
widget = wibox.container.background,
bg = qcolor.palette.border(),
diff --git a/.config/awesome/services/dnd.lua b/.config/awesome/services/dnd.lua
new file mode 100644
index 0000000..d64583c
--- /dev/null
+++ b/.config/awesome/services/dnd.lua
@@ -0,0 +1,18 @@
+local gobject = require "gears.object"
+
+local inner = false
+
+local M = gobject {
+ class = {
+ set_dnd = function(self, value)
+ inner = value
+ self:emit_signal("dnd", inner)
+ end,
+ get_dnd = function()
+ return inner
+ end
+ },
+ enable_properties = true,
+}
+
+return M
diff --git a/.config/awesome/services/time.lua b/.config/awesome/services/time.lua
new file mode 100644
index 0000000..ec33b31
--- /dev/null
+++ b/.config/awesome/services/time.lua
@@ -0,0 +1,18 @@
+local gobject = require "gears.object"
+
+local current = os.date "*t"
+
+local M = gobject {
+ class = {
+ update_current_date = function(self)
+ current = os.date "*t"
+ self:emit_signal("current", current)
+ end,
+ get_current_date = function()
+ return current
+ end
+ },
+ enable_properties = true,
+}
+
+return M
diff --git a/.config/awesome/signals/client.lua b/.config/awesome/signals/client.lua
index f0b5136..2a24863 100644
--- a/.config/awesome/signals/client.lua
+++ b/.config/awesome/signals/client.lua
@@ -1,5 +1,7 @@
local qui = require "quarrel.ui"
local rectangle = require("gears.shape").rectangle
+local qdebug = require "quarrel.debug"
+local gtimer = require "gears.timer"
-- local conductor = require "ui.conductor"
client.connect_signal("request::manage", function(c)
@@ -24,3 +26,27 @@ end
client.connect_signal("property::maximized", handle_corners)
client.connect_signal("property::fullscreen", handle_corners)
+
+client.connect_signal("focus", function(c)
+ if c.instance == "steamwebhelper" then
+ local was_maximized = c.maximized
+ c.maximized = false
+
+ local geo = c:geometry()
+ c:geometry {
+ x = geo.x,
+ y = geo.y,
+ width = geo.width - 1,
+ height = geo.height - 1
+ }
+
+ gtimer {
+ callback = function()
+ c:geometry(geo)
+ c.maximized = was_maximized
+ end,
+ single_shot = true,
+ timeout = 0.5
+ }
+ end
+end)
diff --git a/.config/awesome/test_rc.lua b/.config/awesome/test_rc.lua
new file mode 100644
index 0000000..2882e7a
--- /dev/null
+++ b/.config/awesome/test_rc.lua
@@ -0,0 +1,22 @@
+local awful = require "awful"
+local gshape = require "gears.shape"
+local wibox = require "wibox"
+
+awful.popup {
+ width = 300,
+ shape = function(cr, _, height)
+ gshape.rectangle(cr, 200, height)
+ end,
+ border_color = "#ff0000",
+ border_width = 10,
+ placement = awful.placement.centered,
+ widget = {
+ widget = wibox.container.background,
+ bg = "#00ff00",
+ fg = "#0000ff",
+ {
+ widget = wibox.widget.textbox,
+ text = ("testing"):rep(10, "\n")
+ }
+ }
+}
diff --git a/.config/awesome/ui/fresnel/text_input.lua b/.config/awesome/ui/fresnel/text_input.lua
new file mode 100644
index 0000000..2dc7368
--- /dev/null
+++ b/.config/awesome/ui/fresnel/text_input.lua
@@ -0,0 +1,934 @@
+-------------------------------------------
+-- @author https://github.com/Kasper24
+-- @copyright 2021-2025 Kasper24
+-------------------------------------------
+local lgi = require('lgi')
+local Gtk = lgi.require('Gtk', '3.0')
+local Gdk = lgi.require('Gdk', '3.0')
+local Pango = lgi.Pango
+local awful = require("awful")
+local gtable = require("gears.table")
+local gtimer = require("gears.timer")
+local gcolor = require("gears.color")
+local wibox = require("wibox")
+local qcolor = require "quarrel.color"
+local abs = math.abs
+local ipairs = ipairs
+local string = string
+local capi = {
+ awesome = awesome,
+ root = root,
+ tag = tag,
+ client = client,
+ mouse = mouse,
+ mousegrabber = mousegrabber
+}
+
+local text_input = {
+ mt = {}
+}
+
+local properties = {
+ "unfocus_keys",
+ "unfocus_on_root_clicked", "unfocus_on_client_clicked", "unfocus_on_client_focus",
+ "unfocus_on_mouse_leave", "unfocus_on_tag_change",
+ "focus_on_subject_mouse_enter", "unfocus_on_subject_mouse_leave",
+ "click_timeout",
+ "reset_on_unfocus",
+ "text_color",
+ "placeholder", "initial",
+ "pattern", "obscure",
+ "cursor_blink", "cursor_blink_rate","cursor_size", "cursor_bg",
+ "selection_bg"
+}
+
+text_input.patterns = {
+ numbers = "[%d.]*",
+ numbers_one_decimal = "%d*%.?%d*",
+ round_numbers = "[0-9]*",
+ email = "%S+@%S+%.%S+",
+ time = "%d%d?:%d%d:%d%d?|%d%d?:%d%d",
+ date = "%d%d%d%d%-%d%d%-%d%d|%d%d?/%d%d?/%d%d%d%d|%d%d?%.%d%d?%.%d%d%d%d",
+ phone = "%+?%d[%d%-%s]+%d",
+ url = "https?://[%w-_%.]+%.[%w]+/?[%w-_%.?=%+]*",
+ email = "[%w._%-%+]+@[%w._%-]+%.%w+",
+ alphanumeric = "%w+",
+ letters = "[a-zA-Z]+"
+}
+
+local function build_properties(prototype, prop_names)
+ for _, prop in ipairs(prop_names) do
+ if not prototype["set_" .. prop] then
+ prototype["set_" .. prop] = function(self, value)
+ if self._private[prop] ~= value then
+ self._private[prop] = value
+ self:emit_signal("widget::redraw_needed")
+ self:emit_signal("property::" .. prop, value)
+ end
+ return self
+ end
+ end
+ if not prototype["get_" .. prop] then
+ prototype["get_" .. prop] = function(self)
+ return self._private[prop]
+ end
+ end
+ end
+end
+
+local function has_value(tab, val)
+ for _, value in ipairs(tab) do
+ if val:lower():find(value:lower(), 1, true) then
+ return true
+ end
+ end
+ return false
+end
+
+local function is_word_char(c)
+ if string.find(c, "[{[(,.:;_-+=@/ ]") then
+ return false
+ else
+ return true
+ end
+end
+
+local function cword_start(s, pos)
+ local i = pos
+ if i > 1 then
+ i = i - 1
+ end
+ while i >= 1 and not is_word_char(s:sub(i, i)) do
+ i = i - 1
+ end
+ while i >= 1 and is_word_char(s:sub(i, i)) do
+ i = i - 1
+ end
+ if i <= #s then
+ i = i + 1
+ end
+ return i
+end
+
+local function cword_end(s, pos)
+ local i = pos
+ while i <= #s and not is_word_char(s:sub(i, i)) do
+ i = i + 1
+ end
+ while i <= #s and is_word_char(s:sub(i, i)) do
+ i = i + 1
+ end
+ return i
+end
+
+local function set_mouse_cursor(cursor)
+ capi.root.cursor(cursor)
+ local wibox = capi.mouse.current_wibox
+ if wibox then
+ wibox.cursor = cursor
+ end
+end
+
+local function single_double_triple_tap(self, args)
+ local wp = self._private
+
+ if wp.click_timer == nil then
+ wp.click_timer = gtimer {
+ timeout = wp.click_timeout,
+ autostart = false,
+ call_now = false,
+ single_shot = true,
+ callback = function()
+ wp.click_count = 0
+ end
+ }
+ end
+
+ wp.click_timer:again()
+ wp.click_count = wp.click_count + 1
+ if wp.click_count == 1 then
+ args.on_single_click()
+ elseif wp.click_count == 2 then
+ args.on_double_click()
+ elseif wp.click_count == 3 then
+ args.on_triple_click()
+ wp.click_count = 0
+ end
+end
+
+local function run_keygrabber(self)
+ local wp = self._private
+ wp.keygrabber = awful.keygrabber.run(function(modifiers, key, event)
+ if event ~= "press" then
+ self:emit_signal("key::release", modifiers, key, event)
+ return
+ end
+ self:emit_signal("key::press", modifiers, key, event)
+
+ -- Convert index array to hash table
+ local mod = {}
+ for _, v in ipairs(modifiers) do
+ mod[v] = true
+ end
+
+ if mod.Control then
+ if key == "a" then
+ self:select_all()
+ elseif key == "c" then
+ self:copy()
+ elseif key == "v" then
+ self:paste()
+ elseif key == "b" or key == "Left" then
+ self:set_cursor_index_to_word_start()
+ elseif key == "f" or key == "Right" then
+ self:set_cursor_index_to_word_end()
+ elseif key == "d" then
+ self:delete_next_word()
+ elseif key == "BackSpace" then
+ self:delete_previous_word()
+ end
+ elseif mod.Shift and key:wlen() ~= 1 then
+ if key =="Left" then
+ self:decremeant_selection_end_index()
+ elseif key == "Right" then
+ self:increamant_selection_end_index()
+ end
+ else
+ if has_value(wp.unfocus_keys, key) then
+ self:unfocus()
+ end
+
+ if mod.Shift and key == "Insert" then
+ self:paste()
+ elseif key == "Home" then
+ self:set_cursor_index(0)
+ elseif key == "End" then
+ self:set_cursor_index_to_end()
+ elseif key == "BackSpace" then
+ self:delete_text()
+ elseif key == "Delete" then
+ self:delete_text_after_cursor()
+ elseif key == "Left" then
+ self:decremeant_cursor_index()
+ elseif key == "Right" then
+ self:increamant_cursor_index()
+ elseif not mod.Mod1 and not mod.Mod4 and key:wlen() == 1 then
+ self:update_text(key)
+ end
+ end
+ end)
+end
+
+function text_input:set_widget_template(widget_template)
+ local wp = self._private
+
+ wp.text_widget = widget_template:get_children_by_id("text_role")[1]
+ wp.text_widget.forced_width = math.huge
+ local text_draw = wp.text_widget.draw
+ if self:get_initial() then
+ self:replace_text(self:get_initial())
+ end
+
+ local placeholder_widget = widget_template:get_children_by_id("placeholder_role")
+ if placeholder_widget then
+ placeholder_widget = placeholder_widget[1]
+ end
+
+ function wp.text_widget:draw(context, cr, width, height)
+ local _, logical_rect = self._private.layout:get_pixel_extents()
+
+ -- Selection bg
+ cr:set_source(gcolor.change_opacity(wp.selection_bg, wp.selection_opacity))
+ cr:rectangle(
+ wp.selection_start_x,
+ logical_rect.y - 3,
+ wp.selection_end_x - wp.selection_start_x,
+ logical_rect.y + logical_rect.height + 6
+ )
+ cr:fill()
+
+ -- Cursor
+ cr:set_source(gcolor.change_opacity(wp.cursor_bg, wp.cursor_opacity))
+ cr:set_line_width(wp.cursor_width)
+ cr:move_to(wp.cursor_x, logical_rect.y - 3)
+ cr:line_to(wp.cursor_x, logical_rect.y + logical_rect.height + 6)
+ cr:stroke()
+
+ cr:set_source(gcolor(wp.text_color))
+ text_draw(self, context, cr, width, height)
+
+ if self:get_text() == "" and placeholder_widget then
+ placeholder_widget.visible = true
+ elseif placeholder_widget then
+ placeholder_widget.visible = false
+ end
+ end
+
+ local function on_drag(_, lx, ly)
+ lx, ly = wp.hierarchy:get_matrix_from_device():transform_point(lx, ly)
+ if abs(lx - wp.press_pos.lx) > 2 or abs(ly - wp.press_pos.ly) > 2 then
+ if self:get_mode() ~= "overwrite" then
+ self:set_selection_start_index_from_x_y(wp.press_pos.lx, wp.press_pos.ly)
+ end
+ self:set_selection_end_index_from_x_y(lx, ly)
+ end
+ end
+
+ wp.text_widget:connect_signal("button::press", function(_, lx, ly, button, mods, find_widgets_result)
+ if gtable.hasitem(mods, "Mod4") or button ~= 1 then
+ return
+ end
+
+ single_double_triple_tap(self, {
+ on_single_click = function()
+ self:focus()
+ self:set_cursor_index_from_x_y(lx, ly)
+ end,
+ on_double_click = function()
+ self:set_selection_to_word()
+ end,
+ on_triple_click = function()
+ self:select_all()
+ end
+ })
+
+ wp.press_pos = { lx = lx, ly = ly }
+ wp.hierarchy = find_widgets_result.hierarchy
+ find_widgets_result.drawable:connect_signal("mouse::move", on_drag)
+ end)
+
+ wp.text_widget:connect_signal("button::release", function(_, lx, ly, button, mods, find_widgets_result)
+ if button == 1 then
+ find_widgets_result.drawable:disconnect_signal("mouse::move", on_drag)
+ end
+ end)
+
+ wp.text_widget:connect_signal("mouse::enter", function()
+ set_mouse_cursor("xterm")
+ end)
+
+ wp.text_widget:connect_signal("mouse::leave", function(_, find_widgets_result)
+ if self:get_focused() == false then
+ set_mouse_cursor("left_ptr")
+ end
+
+ find_widgets_result.drawable:disconnect_signal("mouse::move", on_drag)
+ if wp.unfocus_on_mouse_leave then
+ self:unfocus()
+ end
+ end)
+
+ self:set_widget(widget_template)
+end
+
+function text_input:get_mode()
+ return self._private.mode
+end
+
+function text_input:set_focused(focused)
+ if focused == true then
+ self:focus()
+ else
+ self:unfocus()
+ end
+end
+
+function text_input:set_pattern(pattern)
+ self._private.pattern = text_input.patterns[pattern]
+end
+
+function text_input:set_obscure(obscure)
+ self._private.obscure = obscure
+ self:set_text(self:get_text())
+end
+
+function text_input:toggle_obscure()
+ self:set_obscure(not self._private.obscure)
+end
+
+function text_input:set_initial(initial)
+ self._private.initial = initial
+ self:replace_text(initial)
+end
+
+function text_input:update_text(text)
+ if self:get_mode() == "insert" then
+ self:insert_text(text)
+ else
+ self:overwrite_text(text)
+ end
+end
+
+function text_input:set_text(text)
+ self._private.text_buffer = text
+
+ if self:get_obscure() then
+ self:get_text_widget():set_text(string.rep("*", #text))
+ else
+ self:get_text_widget():set_text(text)
+ end
+end
+
+function text_input:replace_text(text)
+ self._private.text_buffer = text
+
+ if self:get_obscure() then
+ self:set_text(string.rep("*", #text))
+ else
+ self:set_text(text)
+ end
+
+ self:set_cursor_index(#text)
+end
+
+function text_input:insert_text(text)
+ local wp = self._private
+
+ local old_text = self:get_text()
+ local cursor_index = self:get_cursor_index()
+ local left_text = old_text:sub(1, cursor_index) .. text
+ local right_text = old_text:sub(cursor_index + 1)
+ local new_text = left_text .. right_text
+ if wp.pattern then
+ new_text = new_text:match(wp.pattern)
+ if new_text then
+ self:set_text(new_text)
+ self:set_cursor_index(self:get_cursor_index() + #text)
+ self:emit_signal("property::text", self:get_text())
+ end
+ else
+ self:set_text(new_text)
+ self:set_cursor_index(self:get_cursor_index() + #text)
+ self:emit_signal("property::text", self:get_text())
+ end
+end
+
+function text_input:overwrite_text(text)
+ local wp = self._private
+
+ local start_pos = wp.selection_start
+ local end_pos = wp.selection_end
+ if start_pos > end_pos then
+ start_pos, end_pos = end_pos, start_pos
+ end
+
+ local old_text = self:get_text()
+ local left_text = old_text:sub(1, start_pos)
+ local right_text = old_text:sub(end_pos + 1)
+ local new_text = left_text .. text .. right_text
+
+ if wp.pattern then
+ new_text = new_text:match(wp.pattern)
+ if new_text then
+ self:set_text(new_text)
+ self:set_cursor_index(#left_text + 1)
+ self:emit_signal("property::text", self:get_text())
+ end
+ else
+ self:set_text(new_text)
+ self:set_cursor_index(#left_text + 1)
+ self:emit_signal("property::text", self:get_text())
+ end
+end
+
+function text_input:copy()
+ local wp = self._private
+ if self:get_mode() == "overwrite" then
+ local text = self:get_text()
+ local start_pos = self._private.selection_start
+ local end_pos = self._private.selection_end
+ if start_pos > end_pos then
+ start_pos, end_pos = end_pos + 1, start_pos
+ end
+ text = text:sub(start_pos, end_pos)
+ wp.clipboard:set_text(text, -1)
+ end
+end
+
+function text_input:paste()
+ local wp = self._private
+
+ wp.clipboard:request_text(function(clipboard, text)
+ if text then
+ self:update_text(text)
+ end
+ end)
+end
+
+function text_input:delete_next_word()
+ local old_text = self:get_text()
+ local cursor_index = self:get_cursor_index()
+
+ local left_text = old_text:sub(1, cursor_index)
+ local right_text = old_text:sub(cword_end(old_text, cursor_index + 1))
+ self:set_text(left_text .. right_text)
+ self:emit_signal("property::text", self:get_text())
+end
+
+function text_input:delete_previous_word()
+ local old_text = self:get_text()
+ local cursor_index = self:get_cursor_index()
+ local wstart = cword_start(old_text, cursor_index + 1) - 1
+ local left_text = old_text:sub(1, wstart)
+ local right_text = old_text:sub(cursor_index + 1)
+ self:set_text(left_text .. right_text)
+ self:set_cursor_index(wstart)
+ self:emit_signal("property::text", self:get_text())
+end
+
+function text_input:delete_text()
+ if self:get_mode() == "insert" then
+ self:delete_text_before_cursor()
+ else
+ self:overwrite_text("")
+ end
+end
+
+function text_input:delete_text_before_cursor()
+ local cursor_index = self:get_cursor_index()
+ if cursor_index > 0 then
+ local old_text = self:get_text()
+ local left_text = old_text:sub(1, cursor_index - 1)
+ local right_text = old_text:sub(cursor_index + 1)
+ self:set_text(left_text .. right_text)
+ self:set_cursor_index(cursor_index - 1)
+ self:emit_signal("property::text", self:get_text())
+ end
+end
+
+function text_input:delete_text_after_cursor()
+ local cursor_index = self:get_cursor_index()
+ if cursor_index < #self:get_text() then
+ local old_text = self:get_text()
+ local left_text = old_text:sub(1, cursor_index)
+ local right_text = old_text:sub(cursor_index + 2)
+ self:set_text(left_text .. right_text)
+ self:emit_signal("property::text", self:get_text())
+ end
+end
+
+function text_input:get_text()
+ return self._private.text_buffer or ""
+end
+
+function text_input:get_text_widget()
+ return self._private.text_widget
+end
+
+function text_input:show_selection()
+ self._private.selection_opacity = 1
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+end
+
+function text_input:hide_selection()
+ self._private.selection_opacity = 0
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+end
+
+function text_input:select_all()
+ if self:get_text() == "" then
+ return
+ end
+
+ self:set_selection_start_index(0)
+ self:set_selection_end_index(#self:get_text())
+end
+
+function text_input:set_selection_to_word()
+ if self:get_text() == "" then
+ return
+ end
+
+ local word_start_index = cword_start(self:get_text(), self:get_cursor_index() + 1) - 1
+ local word_end_index = cword_end(self:get_text(), self:get_cursor_index() + 1) - 1
+
+ self:set_selection_start_index(word_start_index)
+ self:set_selection_end_index(word_end_index)
+end
+
+function text_input:set_selection_start_index(index)
+ if #self:get_text() == 0 then
+ return
+ end
+
+ index = math.max(math.min(index, #self:get_text()), 0)
+
+ local layout = self:get_text_widget()._private.layout
+ local strong_pos, weak_pos = layout:get_caret_pos(index)
+ if strong_pos then
+ self._private.selection_start = index
+ self._private.selection_start_x = strong_pos.x / Pango.SCALE
+ self._private.selection_start_y = strong_pos.y / Pango.SCALE
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+ end
+end
+
+function text_input:set_selection_end_index(index)
+ if #self:get_text() == 0 then
+ return
+ end
+
+ index = math.max(math.min(index, #self:get_text()), 0)
+
+ local layout = self:get_text_widget()._private.layout
+ local strong_pos, weak_pos = layout:get_caret_pos(index)
+ if strong_pos then
+ if self:get_mode() ~= "overwrite" and index ~= self._private.selection_start then
+ self._private.mode = "overwrite"
+ self:show_selection()
+ self:hide_cursor()
+ end
+
+ self._private.selection_end = index
+ self._private.selection_end_x = strong_pos.x / Pango.SCALE
+ self._private.selection_end_y = strong_pos.y / Pango.SCALE
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+ end
+end
+
+function text_input:increamant_selection_end_index()
+ if self:get_mode() == "insert" then
+ self:set_selection_start_index(self:get_cursor_index())
+ self:set_selection_end_index(self:get_cursor_index() + 1)
+ else
+ self:set_selection_end_index(self._private.selection_end + 1)
+ end
+end
+
+function text_input:decremeant_selection_end_index()
+ if self:get_mode() == "insert" then
+ self:set_selection_start_index(self:get_cursor_index())
+ self:set_selection_end_index(self:get_cursor_index() - 1)
+ else
+ self:set_selection_end_index(self._private.selection_end - 1)
+ end
+end
+
+function text_input:set_selection_start_index_from_x_y(x, y)
+ local layout = self:get_text_widget()._private.layout
+ local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE)
+ if index then
+ self:set_selection_start_index(index)
+ else
+ local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents()
+ if x < logical_rect.x + logical_rect.width then
+ self:set_selection_start_index(0)
+ else
+ self:set_selection_start_index(#self:get_text())
+ end
+ end
+end
+
+function text_input:set_selection_end_index_from_x_y(x, y)
+ local layout = self:get_text_widget()._private.layout
+ local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE)
+ if index then
+ self:set_selection_end_index(index + trailing)
+ else
+ local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents()
+ if x < logical_rect.x + logical_rect.width then
+ self:set_selection_end_index(0)
+ else
+ self:set_selection_end_index(#self:get_text())
+ end
+ end
+end
+
+function text_input:show_cursor()
+ self._private.cursor_opacity = 1
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+end
+
+function text_input:hide_cursor()
+ self._private.cursor_opacity = 0
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+end
+
+function text_input:set_cursor_index(index)
+ index = math.max(math.min(index, #self:get_text()), 0)
+
+ local layout = self:get_text_widget()._private.layout
+ local strong_pos, weak_pos = layout:get_cursor_pos(index)
+ if strong_pos then
+ if strong_pos == self._private.cursor_index and self._private.mode == "insert" then
+ return
+ end
+
+ if self:get_focused() and self:get_mode() ~= "insert" then
+ self:show_cursor()
+ end
+
+ self._private.cursor_index = index
+ self._private.mode = "insert"
+
+ self._private.cursor_x = strong_pos.x / Pango.SCALE
+ self._private.cursor_y = strong_pos.y / Pango.SCALE
+
+ self:hide_selection()
+
+ self:get_text_widget():emit_signal("widget::redraw_needed")
+ end
+end
+
+function text_input:set_cursor_index_from_x_y(x, y)
+ local layout = self:get_text_widget()._private.layout
+ local index, trailing = layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE)
+
+ if index then
+ self:set_cursor_index(index)
+ else
+ local pixel_rect, logical_rect = self:get_text_widget()._private.layout:get_pixel_extents()
+ if x < logical_rect.x + logical_rect.width then
+ self:set_cursor_index(0)
+ else
+ self:set_cursor_index(#self:get_text())
+ end
+ end
+end
+
+function text_input:set_cursor_index_to_word_start()
+ self:set_cursor_index(cword_start(self:get_text(), self:get_cursor_index() + 1) - 1)
+end
+
+function text_input:set_cursor_index_to_word_end()
+ self:set_cursor_index(cword_end(self:get_text(), self:get_cursor_index() + 1) - 1)
+end
+
+function text_input:set_cursor_index_to_end()
+ self:set_cursor_index(#self:get_text())
+end
+
+function text_input:increamant_cursor_index()
+ if self:get_mode() == "insert" then
+ self:set_cursor_index(self:get_cursor_index() + 1)
+ else
+ local start_pos = self._private.selection_start
+ local end_pos = self._private.selection_end
+ if start_pos > end_pos then
+ start_pos, end_pos = end_pos, start_pos
+ end
+ self:set_cursor_index(end_pos)
+ end
+end
+
+function text_input:decremeant_cursor_index()
+ if self:get_mode() == "insert" then
+ self:set_cursor_index(self:get_cursor_index() - 1)
+ else
+ local start_pos = self._private.selection_start
+ local end_pos = self._private.selection_end
+ if start_pos > end_pos then
+ start_pos, end_pos = end_pos, start_pos
+ end
+ self:set_cursor_index(start_pos)
+ end
+end
+
+function text_input:get_cursor_index()
+ return self._private.cursor_index
+end
+
+function text_input:set_focus_on_subject_mouse_enter(subject)
+ subject:connect_signal("mouse::enter", function()
+ self:focus()
+ end)
+end
+
+function text_input:set_unfocus_on_subject_mouse_leave(subject)
+ subject:connect_signal("mouse::leave", function()
+ self:unfocus()
+ end)
+end
+
+function text_input:get_focused()
+ return self._private.focused
+end
+
+function text_input:focus()
+ local wp = self._private
+
+ if self:get_focused() == true then
+ return
+ end
+
+ -- Do it first, so the cursor won't change back when unfocus was called on the focused text input
+ capi.awesome.emit_signal("text_input::focus", self)
+
+ set_mouse_cursor("xterm")
+
+ if self:get_mode() == "insert" then
+ self:show_cursor()
+ end
+
+ run_keygrabber(self)
+
+ if wp.cursor_blink then
+ if wp.cursor_blink_timer == nil then
+ wp.cursor_blink_timer = gtimer {
+ timeout = wp.cursor_blink_rate,
+ autostart = false,
+ call_now = false,
+ single_shot = false,
+ callback = function()
+ if self._private.cursor_opacity == 1 then
+ self:hide_cursor()
+ elseif self:get_mode() == "insert" then
+ self:show_cursor()
+ end
+ end
+ }
+ end
+ wp.cursor_blink_timer:start()
+ end
+
+
+ wp.focused = true
+ self:emit_signal("focus")
+end
+
+function text_input:unfocus(context)
+ local wp = self._private
+ if self:get_focused() == false then
+ return
+ end
+
+ set_mouse_cursor("left_ptr")
+ self:hide_cursor()
+ wp.cursor_blink_timer:stop()
+ self:hide_selection()
+ if self.reset_on_unfocus == true then
+ self:replace_text("")
+ end
+
+ awful.keygrabber.stop(wp.keygrabber)
+ wp.focused = false
+ self:emit_signal("unfocus", context or "normal", self:get_text())
+end
+
+function text_input:toggle()
+ local wp = self._private
+
+ if self:get_focused() == false then
+ self:focus()
+ else
+ self:unfocus()
+ end
+end
+
+local function new()
+ local widget = wibox.container.background()
+ gtable.crush(widget, text_input, true)
+
+ local wp = widget._private
+
+ wp.focused = false
+ wp.clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
+ wp.cursor_index = 0
+ wp.mode = "insert"
+ wp.click_count = 0
+
+ wp.cursor_x = 0
+ wp.cursor_y = 0
+ wp.cursor_opacity = 0
+ wp.selection_start_x = 0
+ wp.selection_end_x = 0
+ wp.selection_start_y = 0
+ wp.selection_end_y = 0
+ wp.selection_opacity = 0
+
+ wp.click_timeout = 0.2
+
+ wp.unfocus_keys = { "Escape", "Return" }
+ wp.unfocus_on_root_clicked = true
+ wp.unfocus_on_client_clicked = true
+ wp.unfocus_on_mouse_leave = false
+ wp.unfocus_on_tag_change = true
+ wp.unfocus_on_other_text_input_focus = true
+ wp.unfocus_on_client_focus = true
+
+ wp.focus_on_subject_mouse_enter = nil
+ wp.unfocus_on_subject_mouse_leave = nil
+
+ wp.reset_on_unfocus = false
+
+ wp.pattern = nil
+ wp.obscure = false
+
+ wp.placeholder = ""
+ wp.text_color = qcolor.palette.fg()
+ wp.text = ""
+
+ wp.cursor_width = 2
+ wp.cursor_bg = qcolor.palette.fg()
+ wp.cursor_blink = true
+ wp.cursor_blink_rate = 0.6
+
+ wp.selection_bg = qcolor.palette.bg.high
+
+ widget:set_widget_template(wibox.widget {
+ layout = wibox.layout.stack,
+ {
+ widget = wibox.widget.textbox,
+ id = "placeholder_role",
+ text = wp.placeholder
+ },
+ {
+ widget = wibox.widget.textbox,
+ id = "text_role",
+ text = wp.text
+ }
+ })
+
+ capi.tag.connect_signal("property::selected", function()
+ if wp.unfocus_on_tag_change then
+ widget:unfocus()
+ end
+ end)
+
+ capi.awesome.connect_signal("text_input::focus", function(text_input)
+ if wp.unfocus_on_other_text_input_focus and text_input ~= widget then
+ widget:unfocus()
+ end
+ end)
+
+ capi.client.connect_signal("focus", function()
+ if wp.unfocus_on_client_focus then
+ widget:unfocus()
+ end
+ end)
+
+ awful.mouse.append_global_mousebindings({
+ awful.button({"Any"}, 1, function()
+ if wp.unfocus_on_root_clicked then
+ widget:unfocus()
+ end
+ end),
+ awful.button({"Any"}, 3, function()
+ if wp.unfocus_on_root_clicked then
+ widget:unfocus()
+ end
+ end)
+ })
+
+ capi.client.connect_signal("button::press", function()
+ if wp.unfocus_on_client_clicked then
+ widget:unfocus()
+ end
+ end)
+
+ capi.awesome.connect_signal("colorscheme::changed", function(old_colorscheme_to_new_map)
+ wp.text_color = old_colorscheme_to_new_map[wp.text_color]
+ wp.cursor_bg = old_colorscheme_to_new_map[wp.cursor_bg]
+ wp.selection_bg = old_colorscheme_to_new_map[wp.selection_bg]
+ end)
+
+ return widget
+end
+
+function text_input.mt:__call(...)
+ return new()
+end
+
+build_properties(text_input, properties)
+
+return setmetatable(text_input, text_input.mt)
diff --git a/.config/awesome/ui/init.lua b/.config/awesome/ui/init.lua
index 8ba64f9..efcdd2f 100644
--- a/.config/awesome/ui/init.lua
+++ b/.config/awesome/ui/init.lua
@@ -2,3 +2,19 @@ require "ui.statusbar"
require "ui.decorations"
-- require "ui.tidy"
-- require "ui.osd"
+
+-- local awful = require "awful"
+-- local wibox = require "wibox"
+--
+-- awful.popup {
+-- widget = {
+-- widget = wibox.container.background,
+-- bg = "#ff0000",
+-- opacity = 0.5,
+-- {
+-- widget = wibox.widget.textbox,
+-- text = "test"
+-- }
+-- }
+-- }
+--
diff --git a/.config/awesome/ui/osd/providers/mpris.lua b/.config/awesome/ui/osd/providers/mpris.lua
new file mode 100644
index 0000000..babb0ff
--- /dev/null
+++ b/.config/awesome/ui/osd/providers/mpris.lua
@@ -0,0 +1,3 @@
+local M = {}
+
+
diff --git a/.config/awesome/ui/statusbar/init.lua b/.config/awesome/ui/statusbar/init.lua
index 137ffb8..0a1198a 100644
--- a/.config/awesome/ui/statusbar/init.lua
+++ b/.config/awesome/ui/statusbar/init.lua
@@ -5,6 +5,7 @@ local qanim = require "quarrel.animation"
local qui = require "quarrel.ui"
local qvars = require "quarrel.vars"
local wibox = require "wibox"
+local dnd = require "ui.statusbar.widgets.dnd"
local M = require "ui.statusbar.consts"
@@ -31,29 +32,26 @@ screen.connect_signal("request::desktop_decoration", function(s)
},
nil,
{
- widget = wibox.container.place,
- valign = "bottom",
+ dnd,
+ displays.brightness,
+ displays.audio,
+ displays.battery,
+ displays.wifi,
{
- displays.brightness,
- displays.audio,
- displays.battery,
- displays.wifi,
+ widget = wibox.container.place,
{
- widget = wibox.container.place,
- {
- widget = wibox.container.constraint,
- height = qui.CHAR_HEIGHT,
- width = qui.CHAR_HEIGHT,
- keyboardlayout,
- },
+ widget = wibox.container.constraint,
+ height = qui.CHAR_HEIGHT,
+ width = qui.CHAR_HEIGHT,
+ keyboardlayout,
},
- clock,
- layout = wibox.layout.fixed.vertical,
- spacing = qui.PADDING * 2,
},
+ clock,
+ layout = wibox.layout.fixed.vertical,
+ spacing = qui.PADDING * 2,
},
layout = wibox.layout.align.vertical,
- expand = "outside",
+ expand = "inside",
},
nil,
nil,
diff --git a/.config/awesome/ui/statusbar/panel/init.lua b/.config/awesome/ui/statusbar/panel/init.lua
index 814a5a1..7e54560 100644
--- a/.config/awesome/ui/statusbar/panel/init.lua
+++ b/.config/awesome/ui/statusbar/panel/init.lua
@@ -36,23 +36,11 @@ local panel = wibox.widget {
wifi,
-- battery,
music.widget,
- calendar,
+ calendar.widget,
layout = wibox.layout.fixed.vertical,
spacing = qui.PADDING,
},
},
- -- {
- -- widget = wibox.container.background,
- -- {
- -- widget = wibox.widget.textbox,
- -- text = ":)",
- -- },
- -- },
- -- {
- -- widget = wibox.container.place,
- -- valign = "bottom",
- -- power_menu,
- -- },
layout = wibox.layout.align.vertical,
},
},
diff --git a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
index ddbffc0..c3f0424 100644
--- a/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
+++ b/.config/awesome/ui/statusbar/panel/widgets/calendar.lua
@@ -1,14 +1,36 @@
-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 wibox = require "wibox"
-local weekday_map = { 7, 1, 2, 3, 4, 5, 6 }
+local WEEKDAY_MAP = { 7, 1, 2, 3, 4, 5, 6 }
-local calendar = wibox.widget(qui.styled {
+local M = {}
+
+local l_grid = wibox.widget {
+ layout = wibox.layout.grid,
+ forced_num_rows = 7,
+ forced_num_cols = 7,
+ border_width = {
+ inner = qui.BORDER_WIDTH,
+ outer = 0,
+ },
+ border_color = qcolor.palette.border.variant,
+}
+
+local w_month = wibox.widget {
+ widget = wibox.widget.textbox,
+ text = "-",
+}
+
+local w_year = wibox.widget {
+ widget = wibox.widget.textbox,
+ text = "-",
+}
+
+local offset = 0
+
+M.widget = wibox.widget(qui.styled {
widget = wibox.container.background,
bg = qcolor.palette.bg.high,
{
@@ -16,18 +38,7 @@ local calendar = wibox.widget(qui.styled {
margins = qui.BORDER_WIDTH,
{
{
- {
- 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",
- },
+ l_grid,
{
widget = wibox.container.background,
bg = qcolor.palette.border(),
@@ -43,9 +54,17 @@ local calendar = wibox.widget(qui.styled {
widget = wibox.container.place,
fill_horizontal = true,
{
- widget = wibox.widget.textbox,
- text = "05\n25",
- },
+ {
+ widget = wibox.container.place,
+ w_month,
+ },
+ qui.separator {
+ size = qui.BORDER_WIDTH
+ },
+ w_year,
+ layout = wibox.layout.fixed.vertical,
+ spacing = qui.PADDING
+ }
},
nil,
qui.styled {
@@ -86,7 +105,6 @@ local calendar = wibox.widget(qui.styled {
},
},
layout = wibox.layout.fixed.vertical,
- -- spacing = qui.PADDING
},
},
layout = wibox.layout.align.vertical,
@@ -97,11 +115,32 @@ local calendar = wibox.widget(qui.styled {
},
})
-local grid = calendar:get_children_by_id("grid")[1]
+function M:render(grid)
+ for i, row in ipairs(grid) do
+ for j, col in ipairs(row) do
+ local widget = l_grid:get_widgets_at(i, j)[1]
+ widget.widget.widget.widget.text = col[1]
+ if col[2] then
+ 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 = 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 = qcolor.palette.fg.low
+ end
+ end
+ end
+end
-- 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 = {
+function M:compute(year, month)
+ local grid = {
{
{ "Mo", false, true },
{ "Tu", false, true },
@@ -125,7 +164,7 @@ function calendar:compute_grid(year, month)
local days = last_day.day
local prev_days = os.date("*t", os.time { year = year, month = month, day = 0 })
- local prev_offset = weekday_map[first_day.wday] - 1
+ local prev_offset = WEEKDAY_MAP[first_day.wday] - 1
local prev_month = month - 1 == -1 and 12 or month - 1
local prev_year = prev_month == 12 and year - 1 or year
@@ -133,7 +172,7 @@ function calendar:compute_grid(year, month)
for offset = prev_offset, 1, -1 do
local day = prev_days.day - offset + 1
table.insert(
- calendar_table[2],
+ grid[2],
{ day, day == current.day and prev_month == current.month and prev_year == current.year, false }
)
end
@@ -141,10 +180,10 @@ function calendar:compute_grid(year, month)
do
local row = 2
- local weekday = weekday_map[first_day.wday]
+ local weekday = WEEKDAY_MAP[first_day.wday]
for day = 1, days do
table.insert(
- calendar_table[row],
+ grid[row],
{ day, day == current.day and month == current.month and year == current.year, true }
)
if weekday == 7 then
@@ -159,7 +198,7 @@ function calendar:compute_grid(year, month)
local next_year = next_month == 1 and year + 1 or year
for day = 1, 42 - prev_offset - days do
table.insert(
- calendar_table[row],
+ grid[row],
{ day, day == current.day and next_month + 1 == current.month and next_year == current.year, false }
)
if weekday == 7 then
@@ -171,35 +210,16 @@ function calendar:compute_grid(year, month)
end
end
- for i, row in ipairs(calendar_table) do
- for j, col in ipairs(row) do
- local widget = grid:get_widgets_at(i, j)[1]
- widget.widget.widget.widget.text = col[1]
- if col[2] then
- 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 = 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
+ w_month.text = month
+ w_year.text = year
+ self:render(grid)
end
-local cells = {}
-local function cell(content)
- local widget = wibox.widget {
+-- Set up the widget
+for _ = 1, 49 do
+ local cell = wibox.widget {
widget = wibox.container.background,
bg = qcolor.palette.bg.high,
- -- shape = qui.shape,
{
widget = wibox.container.margin,
margins = qui.PADDING * 1.5,
@@ -209,20 +229,15 @@ local function cell(content)
forced_width = qui.CHAR_HEIGHT,
{
widget = wibox.widget.textbox,
- markup = content,
+ markup = "",
},
},
},
}
- table.insert(cells, widget)
-end
-
-for _ = 1, 49 do
- cell()
+ l_grid:add(cell)
end
-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() })
+M:compute(current_time.year, current_time.month)
+l_grid:add_row_border(2, qui.BORDER_WIDTH, { color = qcolor.palette.border() })
-return calendar
+return M
diff --git a/.config/awesome/ui/statusbar/panel/widgets/notifs/consts.lua b/.config/awesome/ui/statusbar/panel/widgets/notifs/consts.lua
new file mode 100644
index 0000000..c864483
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/notifs/consts.lua
@@ -0,0 +1,13 @@
+local qcolor = require "quarrel.color"
+
+local C = {}
+
+C.NOTIF_TIMEOUT = 3
+C.LEVEL_COLORS = {
+ debug = qcolor.palette.purple(),
+ info = qcolor.palette.blue(),
+ warn = qcolor.palette.orange(),
+ error = qcolor.palette.red(),
+}
+
+return C
diff --git a/.config/awesome/ui/statusbar/panel/widgets/notifs/init.lua b/.config/awesome/ui/statusbar/panel/widgets/notifs/init.lua
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/notifs/init.lua
diff --git a/.config/awesome/ui/statusbar/panel/widgets/notifs/widgets/notif.lua b/.config/awesome/ui/statusbar/panel/widgets/notifs/widgets/notif.lua
new file mode 100644
index 0000000..b2b66b2
--- /dev/null
+++ b/.config/awesome/ui/statusbar/panel/widgets/notifs/widgets/notif.lua
@@ -0,0 +1,214 @@
+local awful = require "awful"
+local beautiful = require "beautiful"
+local gshape = require "gears.shape"
+local naughty = require "naughty"
+local qanim = require "quarrel.animation"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+local rtimed = require("lib.rubato").timed
+local easing = require("lib.rubato").easing
+local consts = require "ui.wicked.consts"
+local gtimer = require "gears.timer"
+local qcolor = require "quarrel.color"
+local qmarkup = require "quarrel.markup"
+
+local M = require "ui.wicked.consts"
+
+function M.new(n, _, n_args)
+ local intertext_margin = (n.title ~= "" or n.message ~= "") and qui.PADDING or 0
+ local title_height = n.title ~= "" and qui.CHAR_HEIGHT or 0
+ local message_height = n.message ~= "" and qui.CHAR_HEIGHT or 0
+ local app_name
+ if n.app_name == "" then
+ app_name = n._private._foreign and "Unknown" or "Awesome"
+ else
+ app_name = n.app_name
+ end
+
+ local w_progress
+
+ local level_color = consts.LEVEL_COLORS[n_args.level] or (n.urgency == "critical" and qcolor.palette.yellow())
+
+ if n.timeout > 0 then
+ w_progress = wibox.widget {
+ widget = wibox.container.radialprogressbar,
+ max_value = M.NOTIF_TIMEOUT,
+ border_color = qcolor.palette.bg.lowest,
+ color = qcolor.palette.yellow(),
+ border_width = qui.PADDING / 2,
+ forced_height = qui.CHAR_HEIGHT,
+ forced_width = qui.CHAR_HEIGHT,
+ }
+ end
+
+ local w_notif = naughty.layout.box {
+ notification = n,
+ placement = function(d)
+ return awful.placement.right(d, {
+ margins = beautiful.useless_gap * 2,
+ })
+ end,
+ bg = qcolor.palette.transparent,
+ border_width = 0,
+ shape = gshape.rectangle,
+ widget_template = {
+ widget = wibox.container.constraint,
+ height = qui.BIG_PADDING * 2
+ + qui.CHAR_HEIGHT
+ + qui.BORDER_WIDTH
+ + qui.BIG_PADDING * 2
+ + (n.icon and qui.CHAR_HEIGHT * 2 + qui.PADDING or (title_height + message_height + intertext_margin)),
+
+ strategy = "exact",
+ {
+ qui.styled {
+ widget = wibox.container.background,
+ forced_width = beautiful.notification_max_width,
+ point = function(geo, args)
+ return {
+ x = args.parent.width,
+ y = args.parent.height - geo.height,
+ }
+ end,
+ {
+ widget = wibox.container.margin,
+ margins = qui.BIG_PADDING,
+ {
+ {
+ widget = wibox.container.constraint,
+ width = beautiful.notification_max_width - (qui.BIG_PADDING + qui.BORDER_WIDTH) * 2 - (level_color and qui.BIG_PADDING + qui.PADDING or 0),
+ strategy = "max",
+ {
+ widget = wibox.container.place,
+ content_fill_horizontal = true,
+ {
+ {
+ {
+ widget = wibox.widget.textbox,
+ markup = qmarkup(app_name, { bold = true }),
+ },
+ nil,
+ w_progress,
+ layout = wibox.layout.align.horizontal,
+ },
+ {
+ widget = wibox.container.constraint,
+ height = qui.BORDER_WIDTH,
+ strategy = "exact",
+ {
+ widget = wibox.container.background,
+ bg = qcolor.palette.border(),
+ },
+ },
+ {
+ widget = wibox.container.constraint,
+ height = n.icon and qui.CHAR_HEIGHT * 2 + qui.PADDING
+ or (title_height + message_height + intertext_margin),
+ strategy = "exact",
+ {
+ {
+ widget = naughty.widget.icon,
+ shape = qui.shape,
+ notification = n,
+ },
+ {
+ {
+ widget = wibox.container.constraint,
+ height = title_height,
+ strategy = "exact",
+ {
+ widget = wibox.widget.textbox,
+ text = n.title or "",
+ },
+ },
+ {
+ widget = wibox.container.constraint,
+ height = message_height,
+ strategy = "exact",
+ {
+ widget = wibox.widget.textbox,
+ text = n.message or "",
+ },
+ },
+ spacing = intertext_margin,
+ layout = wibox.layout.fixed.vertical,
+ },
+ fill_space = true,
+ spacing = n.icon and qui.BIG_PADDING,
+ layout = wibox.layout.fixed.horizontal,
+ },
+ },
+ layout = wibox.layout.fixed.vertical,
+ spacing = qui.BIG_PADDING,
+ },
+ },
+ },
+ {
+ forced_width = qui.PADDING,
+ widget = wibox.container.background,
+ bg = level_color,
+ shape = qui.shape,
+ },
+ layout = wibox.layout.fixed.horizontal,
+ spacing = level_color and qui.BIG_PADDING,
+ },
+ },
+ id = "bg",
+ },
+ layout = wibox.layout.manual,
+ },
+ },
+ }
+
+ local hiding = false
+
+ local t_position = qanim:new {
+ duration = qvars.anim_duration,
+ pos = 0,
+ easing = qvars.easing,
+ subscribed = function(pos)
+ gtimer.delayed_call(function()
+ w_notif.widget.widget:move(1, function(geo, args)
+ if pos == 0 and hiding then
+ old_destroy()
+ end
+ return {
+ x = args.parent.width - pos,
+ y = args.parent.height - geo.height,
+ }
+ end)
+ end)
+ end,
+ }
+ local t_opacity = rtimed {
+ duration = qvars.anim_duration,
+ intro = qvars.anim_intro,
+ easing = easing.quadratic,
+ pos = 0,
+ clamp_position = true,
+ subscribed = function(pos)
+ w_notif.opacity = pos
+ end,
+ }
+
+ n:disconnect_signal("destroyed", w_notif._private.destroy_callback)
+ function w_notif._private.destroy_callback()
+ t_opacity.target = 0
+ t_position:set(0)
+ hiding = true
+ end
+ n:weak_connect_signal("destroyed", w_notif._private.destroy_callback)
+
+ t_opacity.target = 1
+ t_position:set(beautiful.notification_max_width)
+ if t_progress then
+ t_progress.target = M.NOTIF_TIMEOUT
+ end
+end
+
+return setmetatable(M, {
+ __call = function(_, ...)
+ return M.new(...)
+ end,
+})
diff --git a/.config/awesome/ui/statusbar/widgets/dnd.lua b/.config/awesome/ui/statusbar/widgets/dnd.lua
new file mode 100644
index 0000000..37d96b7
--- /dev/null
+++ b/.config/awesome/ui/statusbar/widgets/dnd.lua
@@ -0,0 +1,34 @@
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+local dnd = require "services.dnd"
+local qcolor = require "quarrel.color"
+local phosphor = require "assets.phosphor"
+local qui = require "quarrel.ui"
+local qdebug = require "quarrel.debug"
+
+local w = wibox.widget {
+ widget = wibox.container.background,
+ shape = qui.shape,
+ qui.padded {
+ widget = wibox.container.place,
+ qui.icon {
+ icon = phosphor.bell_simple_slash_fill,
+ color = qcolor.palette.bg(),
+ widget = {
+ forced_height = qui.CHAR_HEIGHT - qui.PADDING * 2,
+ forced_width = qui.CHAR_HEIGHT - qui.PADDING * 2
+ }
+ }
+ },
+ -- visible = false
+}
+
+dnd:connect_signal("dnd", function (_, value)
+ -- this is a giant hack
+ -- why is it here? cause otherwise the align layout freaks out
+ -- and counts the hidden widget when reserving space *and* when drawing, offsetting the rest of the widgets in the process
+ -- w.visible = value
+ w.bg = qcolor.palette[value and "yellow" or "bg"]()
+end)
+
+return w
diff --git a/.config/awesome/ui/tidy/init.lua b/.config/awesome/ui/tidy/init.lua
new file mode 100644
index 0000000..ff3b603
--- /dev/null
+++ b/.config/awesome/ui/tidy/init.lua
@@ -0,0 +1,94 @@
+local awful = require "awful"
+local gshape = require "gears.shape"
+local gtable = require "gears.table"
+local phosphor = require "assets.phosphor"
+local q = require "quarrel"
+local qcolor = require "quarrel.color"
+local qui = require "quarrel.ui"
+local qvars = require "quarrel.vars"
+local wibox = require "wibox"
+
+local M = {}
+
+M.last_focused_client = nil
+M.class_map = {
+ ["org.wezfurlong.wezterm"] = "Wezterm",
+}
+
+M._popup = qui.popup {
+ -- visible = false,
+ ontop = true,
+ placement = "right",
+ shape = function(cr, w, h)
+ gshape.partially_rounded_rect(cr, w, h, true, false, false, true, qui.BORDER_RADIUS)
+ end,
+ -- x = awful.screen.focused().geometry.width,
+ -- minimum_width = width,
+ -- maximum_width = width,
+ -- maximum_height = max_height,
+ widget = awful.widget.tasklist {
+ screen = awful.screen.focused(),
+ filter = awful.widget.tasklist.filter.allscreen,
+ source = function(s)
+ local ret = gtable.clone(s.all_clients, false)
+ -- q.debug(ret)
+ table.sort(ret, function(a, b)
+ return a.class == b.class and (a.pid or 0) < (b.pid or 0) or a.class < b.class
+ end)
+ return ret
+ end,
+ layout = {
+ spacing = qui.BIG_PADDING,
+ layout = wibox.layout.fixed.vertical,
+ },
+ widget_template = qui.styled {
+ widget = wibox.container.background,
+ bg = qcolor.palette.bg.high,
+ qui.padded_big {
+ {
+ widget = wibox.container.place,
+ {
+ widget = wibox.container.constraint,
+ strategy = "max",
+ height = qui.CHAR_HEIGHT,
+ width = qui.CHAR_HEIGHT,
+ {
+ widget = wibox.widget.imagebox,
+ id = "icon_role",
+ },
+ },
+ },
+ {
+ widget = wibox.container.constraint,
+ strategy = "max",
+ width = qui.CHAR_WIDTH * 24,
+ {
+ widget = wibox.widget.textbox,
+ id = "client_name",
+ },
+ },
+ layout = wibox.layout.fixed.horizontal,
+ spacing = qui.PADDING,
+ },
+ create_callback = function(self, c)
+ self:get_children_by_id("client_name")[1].text = M.class_map[c.class] or c.class
+ if c.active then
+ c.wasactive = true
+ self.border_color = qcolor.palette.yellow()
+ end
+ end,
+ update_callback = function(self, c)
+ self:get_children_by_id("client_name")[1].text = M.class_map[c.class] or c.class
+ if c.active then
+ c.wasactive = true
+ self.border_color = qcolor.palette.yellow()
+ elseif c.wasactive then
+ c.wasactive = false
+ self.border_color = qcolor.palette.border()
+ end
+ end,
+ },
+ },
+}
+
+return M
diff --git a/.config/awesome/ui/wicked/consts.lua b/.config/awesome/ui/wicked/consts.lua
index c864483..31e31d5 100644
--- a/.config/awesome/ui/wicked/consts.lua
+++ b/.config/awesome/ui/wicked/consts.lua
@@ -3,6 +3,12 @@ local qcolor = require "quarrel.color"
local C = {}
C.NOTIF_TIMEOUT = 3
+C.LEVEL_PRIORITIES = {
+ debug = 0,
+ info = 1,
+ warn = 2,
+ error = 3
+}
C.LEVEL_COLORS = {
debug = qcolor.palette.purple(),
info = qcolor.palette.blue(),
diff --git a/.config/awesome/ui/wicked/init.lua b/.config/awesome/ui/wicked/init.lua
index dd3324d..e82d408 100644
--- a/.config/awesome/ui/wicked/init.lua
+++ b/.config/awesome/ui/wicked/init.lua
@@ -12,6 +12,7 @@ local consts = require "ui.wicked.consts"
local gtimer = require "gears.timer"
local qcolor = require "quarrel.color"
local qmarkup = require "quarrel.markup"
+local dnd = require "services.dnd"
local M = require "ui.wicked.consts"
@@ -28,6 +29,11 @@ function M.new(n, _, n_args)
local w_progress, t_progress
+ if ((consts.LEVEL_PRIORITIES[n_args.level] or 0) < consts.LEVEL_PRIORITIES.warn and n.urgency ~= "critical") and dnd.dnd then
+ n:destroy()
+ return
+ end
+
local level_color = consts.LEVEL_COLORS[n_args.level] or (n.urgency == "critical" and qcolor.palette.yellow())
if n.timeout > 0 then
@@ -68,9 +74,6 @@ function M.new(n, _, n_args)
+ qui.CHAR_HEIGHT
+ qui.BORDER_WIDTH
+ qui.BIG_PADDING * 2
- -- + title_height
- -- + message_height
- -- + intertext_margin,
+ (n.icon and qui.CHAR_HEIGHT * 2 + qui.PADDING or (title_height + message_height + intertext_margin)),
strategy = "exact",
@@ -78,7 +81,6 @@ function M.new(n, _, n_args)
qui.styled {
widget = wibox.container.background,
forced_width = beautiful.notification_max_width,
- -- border_color = border_color,
point = function(geo, args)
return {
x = args.parent.width,
@@ -158,20 +160,14 @@ function M.new(n, _, n_args)
},
},
},
- -- {
- -- widget = wibox.container.constraint,
- -- strategy = "max",
- -- widget = wibox.container.place,
{
forced_width = qui.PADDING,
widget = wibox.container.background,
bg = level_color,
shape = qui.shape,
- -- },
},
layout = wibox.layout.fixed.horizontal,
spacing = level_color and qui.BIG_PADDING,
- -- expand = "outside"
},
},
id = "bg",