yes, I'm very commit lazy

This commit is contained in:
2023-03-19 19:22:02 +01:00
parent 4f3fb75687
commit f399235db0
107 changed files with 11120 additions and 10906 deletions

View File

@@ -8,13 +8,13 @@
---------------------------------------------------------------------------
local setmetatable = setmetatable
local beautiful = require("beautiful")
local gtable = require("gears.table")
local base = require("wibox.widget.base")
local gstring = require("gears.string")
local akeygrabber = require("awful.keygrabber")
local akey = require("awful.key")
local textbox = require("wibox.widget.textbox")
local beautiful = require('beautiful')
local gtable = require('gears.table')
local base = require('wibox.widget.base')
local gstring = require('gears.string')
local akeygrabber = require('awful.keygrabber')
local akey = require('awful.key')
local textbox = require('wibox.widget.textbox')
local capi = {
selection = selection,
@@ -28,15 +28,15 @@ local inputbox = { mt = {} }
local function text_with_cursor(text, cursor_pos, self)
local char, spacer, text_start, text_end
local cursor_fg = beautiful.inputbox_cursor_fg or "#313131"
local cursor_bg = beautiful.inputbox_cursor_bg or "#0dccfc"
local placeholder_text = self.hint_text or ""
local placeholder_fg = beautiful.inputbox_placeholder_fg or "#777777"
local highlight_bg = beautiful.inputbox_highlight_bg or "#35ffe4"
local highlight_fg = beautiful.inputbox_highlight_fg or "#000000"
local cursor_fg = beautiful.inputbox_cursor_fg or '#313131'
local cursor_bg = beautiful.inputbox_cursor_bg or '#0dccfc'
local placeholder_text = self.hint_text or ''
local placeholder_fg = beautiful.inputbox_placeholder_fg or '#777777'
local highlight_bg = beautiful.inputbox_highlight_bg or '#35ffe4'
local highlight_fg = beautiful.inputbox_highlight_fg or '#000000'
if text == "" then
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. "</span>"
if text == '' then
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. '</span>'
end
local offset = 0
@@ -45,13 +45,13 @@ local function text_with_cursor(text, cursor_pos, self)
end
if #text < cursor_pos then
char = " "
spacer = ""
char = ' '
spacer = ''
text_start = gstring.xml_escape(text)
text_end = ""
text_end = ''
else
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
spacer = " "
spacer = ' '
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
text_end = gstring.xml_escape(text:sub(cursor_pos + offset + 1))
end
@@ -65,10 +65,10 @@ local function text_with_cursor(text, cursor_pos, self)
return text_start_highlight ..
"<span foreground='" .. highlight_fg .. "' background='" .. highlight_bg .. "'>" ..
text_highlighted .. "</span>" .. text_end_highlight
text_highlighted .. '</span>' .. text_end_highlight
else
return text_start .. "<span background='" .. cursor_bg .. "' foreground='" .. cursor_fg .. "'>" ..
char .. "</span>" .. text_end .. spacer
char .. '</span>' .. text_end .. spacer
end
end
@@ -90,23 +90,23 @@ inputbox.set_widget = base.set_widget_common
--- Clears the current text
function inputbox:clear()
self:set_text("")
self:set_text('')
end
function inputbox:get_text()
return self._private.text or ""
return self._private.text or ''
end
function inputbox:set_text(text)
self._private.text = text
self.markup = text_with_cursor(self:get_text(), #self:get_text(), self)
self:emit_signal("property::text", text)
self:emit_signal('property::text', text)
end
--- Stop the keygrabber and mousegrabber
function inputbox:stop()
if (not self.akeygrabber) or (not self.akeygrabber.is_running) then return end
self:emit_signal("stopped")
self:emit_signal('stopped')
self.akeygrabber.stop()
end
@@ -116,16 +116,16 @@ function inputbox:focus()
self:run()
end
self:connect_signal("button::press", function()
self:connect_signal('button::press', function()
if capi.mouse.current_widget ~= self then
self:emit_signal("keygrabber::stop", "")
self:emit_signal('keygrabber::stop', '')
end
end)
end
--- Init the inputbox and start the keygrabber
function inputbox:run()
if not self._private.text then self._private.text = "" end
if not self._private.text then self._private.text = '' end
-- Init the cursor position, but causes on refocus the cursor to move to the left
local cursor_pos = #self:get_text() + 1
@@ -136,24 +136,22 @@ function inputbox:run()
self.akeygrabber = akeygrabber {
autostart = true,
start_callback = function()
self:emit_signal("started")
self:emit_signal('started')
end,
stop_callback = function(_, stop_key)
if stop_key == "Return" then
self:emit_signal("submit", self:get_text(), stop_key)
-- Only reset text on enter as on escape you might want to continue later
self:set_text("")
if stop_key == 'Return' then
self:emit_signal('submit', self:get_text(), stop_key)
else
self:emit_signal("stopped", stop_key)
self:emit_signal('stopped', stop_key)
end
end,
stop_key = { "Escape", "Return" },
stop_key = { 'Escape', 'Return' },
keybindings = {
--lShift, rShift = #50, #62
--lControl, rControl = #37, #105
akey {
modifiers = { "Shift" },
key = "Left", -- left
modifiers = { 'Shift' },
key = 'Left', -- left
on_press = function()
if cursor_pos > 1 then
local offset = (self._private.text:sub(cursor_pos - 1, cursor_pos - 1):wlen() == -1) and 1 or 0
@@ -178,12 +176,12 @@ function inputbox:run()
cursor_pos = #self._private.text + 1
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Shift", "Left")
end
self:emit_signal('inputbox::key_pressed', 'Shift', 'Left')
end,
},
akey {
modifiers = { "Shift" },
key = "Right", -- right
modifiers = { 'Shift' },
key = 'Right', -- right
on_press = function()
if #self._private.text >= cursor_pos then
if not self._private.highlight.cur_pos_end then
@@ -209,29 +207,29 @@ function inputbox:run()
cursor_pos = #self._private.text + 1
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Shift", "Right")
end
self:emit_signal('inputbox::key_pressed', 'Shift', 'Right')
end,
},
akey {
modifiers = { "Control" },
key = "a", -- a
modifiers = { 'Control' },
key = 'a', -- a
on_press = function()
-- Mark the entire text
self._private.highlight = {
cur_pos_start = 1,
cur_pos_end = #self._private.text
cur_pos_end = #self._private.text,
}
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Control", "a")
end
self:emit_signal('inputbox::key_pressed', 'Control', 'a')
end,
},
akey {
modifiers = { "Control" },
key = "v", -- v
modifiers = { 'Control' },
key = 'v', -- v
on_press = function()
local sel = capi.selection()
if sel then
sel = sel:gsub("\n", "")
sel = sel:gsub('\n', '')
if self._private.highlight and self._private.highlight.cur_pos_start and
self._private.highlight.cur_pos_end then
-- insert the text into the selected part
@@ -248,35 +246,35 @@ function inputbox:run()
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Control", "v")
end
self:emit_signal('inputbox::key_pressed', 'Control', 'v')
end,
},
akey {
modifiers = { "Control" },
key = "c", -- c
modifiers = { 'Control' },
key = 'c', -- c
on_press = function()
--TODO
end
end,
},
akey {
modifiers = { "Control" },
key = "x", -- x
modifiers = { 'Control' },
key = 'x', -- x
on_press = function()
--TODO
end
end,
},
akey {
modifiers = { "Control" },
key = "Left", -- left
modifiers = { 'Control' },
key = 'Left', -- left
on_press = function()
-- Find all spaces
local spaces = {}
local t, i = self._private.text, 0
while t:find("%s") do
i = t:find("%s")
while t:find('%s') do
i = t:find('%s')
table.insert(spaces, i)
t = t:sub(1, i - 1) .. "-" .. t:sub(i + 1)
t = t:sub(1, i - 1) .. '-' .. t:sub(i + 1)
end
local cp = 1
@@ -292,14 +290,14 @@ function inputbox:run()
cursor_pos = #self._private.text + 1
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Control", "Left")
end
self:emit_signal('inputbox::key_pressed', 'Control', 'Left')
end,
},
akey {
modifiers = { "Control" },
key = "Right", -- right
modifiers = { 'Control' },
key = 'Right', -- right
on_press = function()
local next_space = self._private.text:sub(cursor_pos):find("%s")
local next_space = self._private.text:sub(cursor_pos):find('%s')
if next_space then
cursor_pos = cursor_pos + next_space
else
@@ -312,12 +310,12 @@ function inputbox:run()
cursor_pos = #self._private.text + 1
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", "Control", "Right")
end
self:emit_signal('inputbox::key_pressed', 'Control', 'Right')
end,
},
akey {
modifiers = {},
key = "BackSpace", --BackSpace
key = 'BackSpace', --BackSpace
on_press = function()
-- If text is highlighted delete that, else just delete the character to the left
if self._private.highlight and self._private.highlight.cur_pos_start and
@@ -337,12 +335,12 @@ function inputbox:run()
end
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", nil, "BackSpace")
end
self:emit_signal('inputbox::key_pressed', nil, 'BackSpace')
end,
},
akey {
modifiers = {},
key = "Delete", --delete
key = 'Delete', --delete
on_press = function()
-- If text is highlighted delete that, else just delete the character to the right
if self._private.highlight and self._private.highlight.cur_pos_start and
@@ -359,41 +357,41 @@ function inputbox:run()
end
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", nil, "Delete")
end
self:emit_signal('inputbox::key_pressed', nil, 'Delete')
end,
},
akey {
modifiers = {},
key = "Left", --left
key = 'Left', --left
on_press = function()
-- Move cursor ro the left
if cursor_pos > 1 then
cursor_pos = cursor_pos - 1
end
self._private.highlight = {}
end
end,
},
akey {
modifiers = {},
key = "Right", --right
key = 'Right', --right
on_press = function()
-- Move cursor to the right
if cursor_pos <= #self._private.text then
cursor_pos = cursor_pos + 1
end
self._private.highlight = {}
end
end,
},
--self.keybindings
},
keypressed_callback = function(_, modifiers, key)
if modifiers[1] == "Shift" then
if modifiers[1] == 'Shift' then
if key:wlen() == 1 then
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
string.upper(key) .. self._private.text:sub(cursor_pos))
cursor_pos = cursor_pos + #key
end
elseif modifiers[1] == "Mod2" or "" then
elseif modifiers[1] == 'Mod2' or '' then
if key:wlen() == 1 then
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
key .. self._private.text:sub(cursor_pos))
@@ -407,8 +405,8 @@ function inputbox:run()
cursor_pos = #self._private.text + 1
end
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
self:emit_signal("inputbox::key_pressed", modifiers, key)
end
self:emit_signal('inputbox::key_pressed', modifiers, key)
end,
}
end
@@ -426,6 +424,7 @@ end
-- @treturn awful.widget.inputbox The inputbox widget.
-- @constructorfct awful.widget.inputbox
function inputbox.new(args)
args = args or {}
-- directly pass a possible default text(this is not meant to be a hint)
local w = textbox()
@@ -437,7 +436,7 @@ function inputbox.new(args)
w.keybindings = args.keybindings or {}
w.hint_text = args.hint_text
w.markup = args.text or text_with_cursor("", 1, w)
w.markup = args.text or text_with_cursor('', 1, w)
return w
end

View File

@@ -1,11 +1,11 @@
local base = require("wibox.widget.base")
local gtable = require("gears.table")
local gcolor = require("gears.color")
local dpi = require("beautiful").xresources.apply_dpi
local wibox = require("wibox")
local gshape = require("gears.shape")
local rubato = require("src.lib.rubato")
local abutton = require("awful.button")
local base = require('wibox.widget.base')
local gtable = require('gears.table')
local gcolor = require('gears.color')
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local gshape = require('gears.shape')
local rubato = require('src.lib.rubato')
local abutton = require('awful.button')
local toggle_widget = { mt = {} }
@@ -52,7 +52,7 @@ function toggle_widget:toggle_animation(pos, color)
cr:move_to(pos, 0)
local x = pos
local y = 5
local newwidth = width / 2 - 10
local newwidth = width / 2 - 6
local newheight = height - 10
local radius = height / 6.0
@@ -88,7 +88,7 @@ function toggle_widget.new(args)
end,
draw = ret:toggle_animation(0, ret.newcolor),
},
id = "background",
id = 'background',
},
active = false,
widget = wibox.container.background,
@@ -106,9 +106,9 @@ function toggle_widget.new(args)
duration = 0.2,
pos = 5,
subscribed = function(pos)
ret.toggle_button:get_children_by_id("background")[1].draw = ret:toggle_animation(pos, ret.newcolor)
ret.toggle_button:emit_signal("widget::redraw_needed")
end
ret.toggle_button:get_children_by_id('background')[1].draw = ret:toggle_animation(pos, ret.newcolor)
ret.toggle_button:emit_signal('widget::redraw_needed')
end,
}
ret:set_widget(wibox.widget {
@@ -116,27 +116,27 @@ function toggle_widget.new(args)
{
args.text and {
text = args.text,
valign = "center",
align = "center",
valign = 'center',
align = 'center',
widget = wibox.widget.textbox,
id = "clearall"
id = 'clearall',
} or nil,
ret.toggle_button,
spacing = args.text and dpi(10) or dpi(0),
layout = wibox.layout.fixed.horizontal,
id = "layout12"
id = 'layout12',
},
id = "background4",
id = 'background4',
fg = args.fg,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(12))
end,
widget = wibox.container.background
widget = wibox.container.background,
},
id = "place",
id = 'place',
widget = wibox.container.place,
valign = "bottom",
halign = "right",
valign = 'bottom',
halign = 'right',
})
ret.toggle_button:buttons(
@@ -147,7 +147,7 @@ function toggle_widget.new(args)
else
ret:set_enabled()
end
ret:emit_signal("dnd::toggle", ret.active)
ret:emit_signal('dnd::toggle', ret.active)
end
)
)

View File

@@ -1,12 +1,40 @@
---@diagnostic disable: lowercase-global
-----------------------------------------------------------------------------------------
-- █████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███╗ ███╗███████╗██╗ ██╗███╗ ███╗ --
-- ██╔══██╗██║ ██║██╔════╝██╔════╝██╔═══██╗████╗ ████║██╔════╝██║ ██║████╗ ████║ --
-- ███████║██║ █╗ ██║█████╗ ███████╗██║ ██║██╔████╔██║█████╗ ██║ █╗ ██║██╔████╔██║ --
-- ██╔══██║██║███╗██║██╔══╝ ╚════██║██║ ██║██║╚██╔╝██║██╔══╝ ██║███╗██║██║╚██╔╝██║ --
-- ██║ ██║╚███╔███╔╝███████╗███████║╚██████╔╝██║ ╚═╝ ██║███████╗╚███╔███╔╝██║ ╚═╝ ██║ --
-- ╚═╝ ╚═╝ ╚══╝╚══╝ ╚══════╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝ --
-----------------------------------------------------------------------------------------
--[[
╭─────────────────────────────────────────────────────────────────╮
│ ______ ___ ________ │
│ / ____/______ __/ (_)___ _ /_ __/ /_ ___ ____ ___ ___ │
│ / / / ___/ / / / / / __ `/ / / / __ \/ _ \/ __ `__ \/ _ \ │
│ / /___/ / / /_/ / / / /_/ / / / / / / / __/ / / / / / __/ │
│ \____/_/ \__, /_/_/\__,_/ /_/ /_/ /_/\___/_/ /_/ /_/\___/ │
│ /____/ │
╰─────────────────────────────────────────────────────────────────╯
]]
--#region prints
io.stdout:write([[
]] .. '\n\27[32m' .. [[╭─────────────────────────────────────────────────────────────────╮
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ ______ ___ ________ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / ____/______ __/ (_)___ _ /_ __/ /_ ___ ____ ___ ___ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / / / ___/ / / / / / __ `/ / / / __ \/ _ \/ __ `__ \/ _ \ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / /___/ / / /_/ / / / /_/ / / / / / / / __/ / / / / / __/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ \____/_/ \__, /_/_/\__,_/ /_/ /_/ /_/\___/_/ /_/ /_/\___/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ /____/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[╰─────────────────────────────────────────────────────────────────╯
]] .. '\27[0m\n')
io.stderr:write([[
]] .. '\n\27[32m' .. [[╭─────────────────────────────────────────────────────────────────╮
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ ______ ___ ________ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / ____/______ __/ (_)___ _ /_ __/ /_ ___ ____ ___ ___ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / / / ___/ / / / / / __ `/ / / / __ \/ _ \/ __ `__ \/ _ \ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ / /___/ / / /_/ / / / /_/ / / / / / / / __/ / / / / / __/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ \____/_/ \__, /_/_/\__,_/ /_/ /_/ /_/\___/_/ /_/ /_/\___/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[│]] .. '\27[1;36m' .. [[ /____/ ]] .. '\27[32m' .. [[│
]] .. '\27[32m' .. [[╰─────────────────────────────────────────────────────────────────╯
]] .. '\27[0m\n')
--#endregion
-- Initialising, order is important!
awesome = awesome
client = client
@@ -20,18 +48,20 @@ tag = tag
-- Do not touch as this is used to share some variable settings files
Global_config = {}
require("src.core.error_handling")
require("src.theme.user_config")
require("src.theme.theme_config")
require("src.tools.gio_icon_lookup")
require("src.theme.init")
require("src.tools.hex_to_rgba")
require("src.core.signals")
require("src.core.notifications")
require("src.core.rules")
require("src.bindings.global_buttons")
require("src.bindings.bind_to_tags")
require("src.modules.init")
require("src.tools.auto_starter")(User_config.autostart)
require('src.core.error_handling')
require('src.theme.user_config')
require('src.theme.theme_config')
require('src.tools.gio_icon_lookup')
require('src.theme.init')
require('src.tools.hex_to_rgba')
require('src.core.signals')
require('src.core.notifications')
require('src.core.rules')
require('src.bindings.global_buttons')
require('src.bindings.bind_to_tags')
require('src.modules.init')
--require('src.tools.auto_starter')(User_config.autostart)
require("src.config.setup")()
--require('src.core.setup')()
--require('src.tools.helpers.pulseaudio')()

View File

@@ -0,0 +1 @@
<svg id="ct" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" shape-rendering="geometricPrecision" text-rendering="geometricPrecision"><defs><linearGradient id="ct-s-path1-stroke" x1="-0.024162" y1="0.504999" x2="0.975838" y2="0.504455" spreadMethod="pad" gradientUnits="objectBoundingBox" gradientTransform="translate(0 0)"><stop id="ct-s-path1-stroke-0" offset="0%" stop-color="#faa3ff"/><stop id="ct-s-path1-stroke-1" offset="50%" stop-color="#ffd9fd"/><stop id="ct-s-path1-stroke-2" offset="100%" stop-color="#7ef2ff"/></linearGradient></defs><path id="ct-s-path1" d="M281.200226,185.600197L215.59979,316.799803L346.800008,316.8l-32.800004,65.6h-131.200023l-32.800005-65.600197L248.400073,120h196.799951h196.799951l-32.800004,65.6h-65.600012L461.599945,382.4h-65.600011l85.280014-196.799803-68.470031.000003L445.200024,120l-32.390106,65.6h-131.609692" transform="translate(-139.999975-.535)" fill="#fff" fill-opacity="0" stroke="url(#ct-s-path1-stroke)" stroke-width="16" stroke-linecap="round" stroke-linejoin="round" stroke-dashoffset="5"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#00000000">
<path d="M0 0h24v24H0z" />
<path fill="#ef9a9a" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
</svg>

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

View File

@@ -1,7 +1,12 @@
-- Awesome Libs
local awful = require("awful")
local gears = require("gears")
local globalkeys = require("src.bindings.global_keys")
local akey = require('awful.key')
local ascreen = require('awful.screen')
local atag = require('awful.tag')
local gtable = require('gears.table')
-- Local libs
local globalkeys = require('src.bindings.global_keys')
local modkey = User_config.modkey
local capi = {
@@ -10,63 +15,34 @@ local capi = {
}
for i = 1, 9 do
globalkeys = gears.table.join(globalkeys,
-- View tag only
awful.key(
{ modkey },
"#" .. i + 9,
function()
local screen = awful.screen.focused()
globalkeys = gtable.join(globalkeys,
akey({ modkey }, '#' .. i + 9, function()
local screen = ascreen.focused()
local tag = screen.tags[i]
if tag then
tag:view_only()
end
capi.client.emit_signal("tag::switched")
end,
{ description = "View Tag " .. i, group = "Tag" }
),
-- Brings the window over without chaning the tag, reverts automatically on tag change
awful.key(
{ modkey, "Control" },
"#" .. i + 9,
capi.client.emit_signal('tag::switched')
end, { description = 'Switch to tag ' .. i, group = 'Tag' }),
akey({ modkey, 'Control' }, '#' .. i + 9,
function()
local screen = awful.screen.focused()
local screen = ascreen.focused()
local tag = screen.tags[i]
if tag then
awful.tag.viewtoggle(tag)
atag.viewtoggle(tag)
end
end,
{ description = "Toggle Tag " .. i, group = "Tag" }
),
-- Brings the window over without chaning the tag, reverts automatically on tag change
awful.key(
{ modkey, "Shift" },
"#" .. i + 9,
function()
local screen = awful.screen.focused()
end, { description = 'View tag ' .. i, group = 'Tag' }),
akey({ modkey, 'Shift' }, '#' .. i + 9, function()
local screen = ascreen.focused()
if capi.client.focus then
local tag = screen.tags[i]
if tag then
capi.client.focus:move_to_tag(tag)
end
end
end,
{ description = "Move focused client on tag " .. i, group = "Tag" }
),
-- Brings the window over without chaning the tag, reverts automatically on tag change
awful.key(
{ modkey, "Control", "Shift" },
"#" .. i + 9,
function()
local screen = awful.screen.focused()
local tag = screen.tags[i]
if tag then
awful.tag.viewtoggle(tag)
end
end,
{ description = "Move focused client on tag " .. i, group = "Tag" }
)
end, { description = 'Move focused client to tag ' .. i, group = 'Tag' })
)
end
capi.root.keys(globalkeys)

View File

@@ -1,19 +1,20 @@
-- Awesome Libs
local awful = require("awful")
local gears = require("gears")
local abutton = require('awful.button')
local gtable = require('gears.table')
local amouse = require('awful.mouse')
local modkey = User_config.modkey
return gears.table.join(
awful.button({}, 1, function(c)
c:emit_signal("request::activate", "mouse_click", { raise = true })
return gtable.join {
abutton({}, 1, function(c)
c:emit_signal('request::activate', 'mouse_click', { raise = true })
end),
awful.button({ modkey }, 1, function(c)
c:emit_signal("request::activate", "mouse_click", { raise = true })
awful.mouse.client.move(c)
abutton({ modkey }, 1, function(c)
c:emit_signal('request::activate', 'mouse_click', { raise = true })
amouse.client.move(c)
end),
awful.button({ modkey }, 3, function(c)
c:emit_signal("request::activate", "mouse_click", { raise = true })
awful.mouse.client.resize(c)
end)
)
abutton({ modkey }, 3, function(c)
c:emit_signal('request::activate', 'mouse_click', { raise = true })
amouse.client.resize(c)
end),
}

View File

@@ -1,61 +1,156 @@
-- Awesome Libs
local awful = require("awful")
local gears = require("gears")
local capi = {
client = client
}
local aclient = require('awful.client')
local akey = require('awful.key')
local ascreen = require('awful.screen')
local gtable = require('gears.table')
local modkey = User_config.modkey
return gears.table.join(
awful.key(
{ modkey },
"#41",
function(c)
return gtable.join(
--#region Basic interactions
akey({ modkey }, '#24', function(c)
c:kill()
end, { description = 'Close client', group = 'Client' }),
akey({ modkey }, '#41', function(c)
c.fullscreen = not c.fullscreen
c:raise()
end,
{ description = "Toggle fullscreen", group = "Client" }
),
awful.key(
{ modkey },
"#24",
function(c)
c:kill()
end,
{ description = "Close focused client", group = "Client" }
),
awful.key(
{ modkey },
"#42",
awful.client.floating.toggle,
{ description = "Toggle floating window", group = "Client" }
),
awful.key(
{ modkey },
"#58",
function(c)
end, { description = 'Toggle fullscreen', group = 'Client' }),
akey({ modkey }, '#42',
aclient.floating.toggle,
{ description = 'Toggle floating', group = 'Client' }),
akey({ modkey }, '#57', function(c)
c.minimized = true
end, { description = 'Minimize', group = 'Client' }),
akey({ modkey }, '#58', function(c)
c.maximized = not c.maximized
c:raise()
end,
{ description = "(un)maximize", group = "Client" }
),
awful.key(
{ modkey },
"#57",
function(c)
if c == capi.client.focus then
c.minimized = true
else
c.minimized = false
end, { description = 'Toggle maximize', group = 'Client' }),
--#endregion
--#region Client focus movement
akey({ modkey }, '#44', function(c)
aclient.focus.global_bydirection('up', c)
end, { description = 'Move client a screen up', group = 'Client' }),
akey({ modkey }, '#111', function(c)
aclient.focus.global_bydirection('up', c)
end, { description = 'Move client a screen up', group = 'Client' }),
akey({ modkey }, '#43', function(c)
aclient.focus.global_bydirection('left', c)
end, { description = 'Move client a screen left', group = 'Client' }),
akey({ modkey }, '#113', function(c)
aclient.focus.global_bydirection('left', c)
end, { description = 'Move client a screen left', group = 'Client' }),
akey({ modkey }, '#46', function(c)
aclient.focus.global_bydirection('right', c)
end, { description = 'Move client a screen right', group = 'Client' }),
akey({ modkey }, '#114', function(c)
aclient.focus.global_bydirection('right', c)
end, { description = 'Move client a screen right', group = 'Client' }),
akey({ modkey }, '#45', function(c)
aclient.focus.global_bydirection('down', c)
end, { description = 'Move client a screen down', group = 'Client' }),
akey({ modkey }, '#116', function(c)
aclient.focus.global_bydirection('down', c)
end, { description = 'Move client a screen down', group = 'Client' }),
--#endregion
--#region Screen movement
akey({ modkey, 'Shift' }, '#44', function(c)
local s = ascreen.focus_bydirection('Up', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen up', group = 'Client' }),
akey({ modkey, 'Shift' }, '#111', function(c)
local s = ascreen.focus_bydirection('Up', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
end,
{ description = "(un)hide", group = "Client" }
)
c:emit_signal('request::activate')
c:raise()
c:activate {
--switch_to_tag = true,
raise = true,
context = 'somet_reason',
}
end, { description = 'Move client a screen up', group = 'Client' }),
akey({ modkey, 'Shift' }, '#43', function(c)
c:move_to_screen(ascreen.focus_bydirection('left', c.screen))
c.first_tag:view_only()
client.focus = c
c:raise()
c:activate {
--switch_to_tag = true,
raise = true,
context = 'somet_reason',
}
end, { description = 'Move client a screen left', group = 'Client' }),
akey({ modkey, 'Shift' }, '#113', function(c)
local s = ascreen.focus_bydirection('left', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen left', group = 'Client' }),
akey({ modkey, 'Shift' }, '#46', function(c)
local s = ascreen.focus_bydirection('Right', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen right', group = 'Client' }),
akey({ modkey, 'Shift' }, '#114', function(c)
local s = ascreen.focus_bydirection('Right', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen right', group = 'Client' }),
akey({ modkey, 'Shift' }, '#45', function(c)
local s = ascreen.focus_bydirection('Down', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen down', group = 'Client' }),
akey({ modkey, 'Shift' }, '#116', function(c)
local s = ascreen.focus_bydirection('Down', c.screen)
c:move_to_screen(s)
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
end
c:emit_signal('request::activate')
c:raise()
end, { description = 'Move client a screen down', group = 'Client' })
--#endregion
)

View File

@@ -1,12 +1,13 @@
-- Awesome Libs
local gears = require("gears")
local awful = require("awful")
local gtable = require('gears.table')
local abutton = require('awful.button')
local atag = require('awful.tag')
local capi = {
root = root
}
capi.root.buttons = gears.table.join(
awful.button({}, 4, awful.tag.viewnext),
awful.button({}, 5, awful.tag.viewprev)
capi.root.buttons = gtable.join(
abutton({}, 4, atag.viewnext),
abutton({}, 5, atag.viewprev)
)

View File

@@ -1,11 +1,21 @@
-- Awesome libs
local gears = require("gears")
local awful = require("awful")
local hotkeys_popup = require("awful.hotkeys_popup")
local ruled = require("ruled")
local akeygrabber = require('awful.keygrabber')
local akey = require('awful.key')
local gtable = require('gears.table')
local atag = require('awful.tag')
local aclient = require('awful.client')
local aspawn = require('awful.spawn')
local alayout = require('awful.layout')
local ascreen = require('awful.screen')
local hotkeys_popup = require('awful.hotkeys_popup')
local ruled = require('ruled')
-- Third party libs
local json = require("src.lib.json-lua.json-lua")
-- Local libs
local config = require('src.tools.config')
local audio_helper = require('src.tools.helpers.audio')
local backlight_helper = require('src.tools.helpers.backlight')
local powermenu = require('src.modules.powermenu.init')
local kb_helper = require('src.tools.helpers.kb_helper')
local capi = {
awesome = awesome,
@@ -15,301 +25,290 @@ local capi = {
local modkey = User_config.modkey
awful.keygrabber {
akeygrabber {
keybindings = {
awful.key {
modifiers = { "Mod1" },
key = "Tab",
akey {
modifiers = { 'Mod1' },
key = 'Tab',
on_press = function()
capi.awesome.emit_signal("window_switcher::select_next")
end
}
capi.awesome.emit_signal('window_switcher::select_next')
end,
},
},
root_keybindings = {
awful.key {
modifiers = { "Mod1" },
key = "Tab",
akey {
modifiers = { 'Mod1' },
key = 'Tab',
on_press = function()
end
}
end,
},
stop_key = "Mod1",
stop_event = "release",
},
stop_key = 'Mod1',
stop_event = 'release',
start_callback = function()
capi.awesome.emit_signal("toggle_window_switcher")
capi.awesome.emit_signal('toggle_window_switcher')
end,
stop_callback = function()
capi.awesome.emit_signal("window_switcher::raise")
capi.awesome.emit_signal("toggle_window_switcher")
capi.awesome.emit_signal('window_switcher::raise')
capi.awesome.emit_signal('toggle_window_switcher')
end,
export_keybindings = true,
}
return gears.table.join(
awful.key(
return gtable.join(
akey(
{ modkey },
"#39",
'#39',
hotkeys_popup.show_help,
{ description = "Cheat sheet", group = "Awesome" }
{ description = 'Cheat sheet', group = 'Awesome' }
),
-- Tag browsing
awful.key(
--[[ akey(
{ modkey },
"#113",
awful.tag.viewprev,
{ description = "View previous tag", group = "Tag" }
'#113',
atag.viewprev,
{ description = 'View previous tag', group = 'Tag' }
),
awful.key(
akey(
{ modkey },
"#114",
awful.tag.viewnext,
{ description = "View next tag", group = "Tag" }
),
awful.key(
'#114',
atag.viewnext,
{ description = 'View next tag', group = 'Tag' }
), ]]
akey(
{ modkey },
"#66",
awful.tag.history.restore,
{ description = "Go back to last tag", group = "Tag" }
'#66',
atag.history.restore,
{ description = 'Go back to last tag', group = 'Tag' }
),
awful.key(
akey(
{ modkey },
"#44",
'#44',
function()
awful.client.focus.byidx(1)
aclient.focus.byidx(1)
end,
{ description = "Focus next client by index", group = "Client" }
{ description = 'Focus next client by index', group = 'Client' }
),
awful.key(
akey(
{ modkey },
"#45",
'#45',
function()
awful.client.focus.byidx(-1)
aclient.focus.byidx(-1)
end,
{ description = "Focus previous client by index", group = "Client" }
{ description = 'Focus previous client by index', group = 'Client' }
),
awful.key(
{ modkey, "Shift" },
"#44",
akey(
{ modkey, 'Shift' },
'#44',
function()
awful.client.swap.byidx(1)
aclient.swap.byidx(1)
end,
{ description = "Swap with next client by index", group = "Client" }
{ description = 'Swap with next client by index', group = 'Client' }
),
awful.key(
{ modkey, "Shift" },
"#45",
akey(
{ modkey, 'Shift' },
'#45',
function()
awful.client.swap.byidx(-1)
aclient.swap.byidx(-1)
end,
{ description = "Swap with previous client by index", group = "Client" }
{ description = 'Swap with previous client by index', group = 'Client' }
),
awful.key(
{ modkey, "Control" },
"#44",
akey(
{ modkey, 'Control' },
'#44',
function()
awful.screen.focus_relative(1)
ascreen.focus_relative(1)
end,
{ description = "Focus the next screen", group = "Screen" }
{ description = 'Focus the next screen', group = 'Screen' }
),
awful.key(
{ modkey, "Control" },
"#45",
akey(
{ modkey, 'Control' },
'#45',
function()
awful.screen.focus_relative(-1)
ascreen.focus_relative(-1)
end,
{ description = "Focus the previous screen", group = "Screen" }
{ description = 'Focus the previous screen', group = 'Screen' }
),
awful.key(
akey(
{ modkey },
"#30",
awful.client.urgent.jumpto,
{ description = "Jump to urgent client", group = "Client" }
'#30',
aclient.urgent.jumpto,
{ description = 'Jump to urgent client', group = 'Client' }
),
awful.key(
akey(
{ modkey },
"#36",
'#36',
function()
awful.spawn(User_config.terminal)
aspawn(User_config.terminal)
end,
{ description = "Open terminal", group = "Applications" }
{ description = 'Open terminal', group = 'Applications' }
),
awful.key(
{ modkey, "Control" },
"#27",
akey(
{ modkey, 'Control' },
'#27',
capi.awesome.restart,
{ description = "Reload awesome", group = "Awesome" }
{ description = 'Reload awesome', group = 'Awesome' }
),
awful.key(
akey(
{ modkey },
"#46",
'#46',
function()
awful.tag.incmwfact(0.05)
atag.incmwfact(0.05)
end,
{ description = "Increase client width", group = "Layout" }
{ description = 'Increase client width', group = 'Layout' }
),
awful.key(
akey(
{ modkey },
"#43",
'#43',
function()
awful.tag.incmwfact(-0.05)
atag.incmwfact(-0.05)
end,
{ description = "Decrease client width", group = "Layout" }
{ description = 'Decrease client width', group = 'Layout' }
),
awful.key(
{ modkey, "Control" },
"#43",
akey(
{ modkey, 'Control' },
'#43',
function()
awful.tag.incncol(1, nil, true)
atag.incncol(1, nil, true)
end,
{ description = "Increase the number of columns", group = "Layout" }
{ description = 'Increase the number of columns', group = 'Layout' }
),
awful.key(
{ modkey, "Control" },
"#46",
akey(
{ modkey, 'Control' },
'#46',
function()
awful.tag.incncol(-1, nil, true)
atag.incncol(-1, nil, true)
end,
{ description = "Decrease the number of columns", group = "Layout" }
{ description = 'Decrease the number of columns', group = 'Layout' }
),
awful.key(
{ modkey, "Shift" },
"#65",
akey(
{ modkey, 'Shift' },
'#65',
function()
awful.layout.inc(-1)
alayout.inc(-1)
end,
{ description = "Select previous layout", group = "Layout" }
{ description = 'Select previous layout', group = 'Layout' }
),
awful.key(
{ modkey, "Shift" },
"#36",
akey(
{ modkey, 'Shift' },
'#36',
function()
awful.layout.inc(1)
alayout.inc(1)
end,
{ description = "Select next layout", group = "Layout" }
{ description = 'Select next layout', group = 'Layout' }
),
awful.key(
akey(
{ modkey },
"#40",
'#40',
function()
capi.awesome.emit_signal("application_launcher::show")
capi.awesome.emit_signal('application_launcher::show')
end,
{ descripton = "Application launcher", group = "Application" }
{ descripton = 'Application launcher', group = 'Application' }
),
awful.key(
akey(
{ modkey },
"#26",
'#26',
function()
awful.spawn(User_config.file_manager)
aspawn(User_config.file_manager)
end,
{ descripton = "Open file manager", group = "System" }
{ descripton = 'Open file manager', group = 'System' }
),
awful.key(
{ modkey, "Shift" },
"#26",
akey(
{ modkey, 'Shift' },
'#26',
function()
capi.awesome.emit_signal("module::powermenu:show")
powermenu:toggle()
end,
{ descripton = "Session options", group = "System" }
{ descripton = 'Session options', group = 'System' }
),
awful.key(
akey(
{},
"#107",
'#107',
function()
awful.spawn(User_config.screenshot_program)
aspawn(User_config.screenshot_program)
end,
{ description = "Screenshot", group = "Applications" }
{ description = 'Screenshot', group = 'Applications' }
),
awful.key(
akey(
{},
"XF86AudioLowerVolume",
'XF86AudioLowerVolume',
function(c)
awful.spawn.easy_async_with_shell("pactl set-sink-volume @DEFAULT_SINK@ -2%", function()
capi.awesome.emit_signal("widget::volume_osd:rerun")
end)
audio_helper.sink_volume_down()
end,
{ description = "Lower volume", group = "System" }
{ description = 'Lower volume', group = 'System' }
),
awful.key(
akey(
{},
"XF86AudioRaiseVolume",
'XF86AudioRaiseVolume',
function(c)
awful.spawn.easy_async_with_shell("pactl set-sink-volume @DEFAULT_SINK@ +2%", function()
capi.awesome.emit_signal("widget::volume_osd:rerun")
end)
audio_helper.sink_volume_up()
end,
{ description = "Increase volume", group = "System" }
{ description = 'Increase volume', group = 'System' }
),
awful.key(
akey(
{},
"XF86AudioMute",
'XF86AudioMute',
function(c)
awful.spawn("pactl set-sink-mute @DEFAULT_SINK@ toggle")
capi.awesome.emit_signal("widget::volume_osd:rerun")
audio_helper.sink_toggle_mute()
end,
{ description = "Mute volume", group = "System" }
{ description = 'Mute volume', group = 'System' }
),
awful.key(
akey(
{},
"XF86MonBrightnessUp",
'XF86MonBrightnessUp',
function(c)
backlight_helper.brightness_increase()
end,
{ description = "Raise backlight brightness", group = "System" }
{ description = 'Raise backlight brightness', group = 'System' }
),
awful.key(
akey(
{},
"XF86MonBrightnessDown",
'XF86MonBrightnessDown',
function(c)
backlight_helper.brightness_decrease()
end,
{ description = "Lower backlight brightness", group = "System" }
{ description = 'Lower backlight brightness', group = 'System' }
),
awful.key(
akey(
{},
"XF86AudioPlay",
'XF86AudioPlay',
function(c)
awful.spawn("playerctl play-pause")
aspawn('playerctl play-pause')
end,
{ description = "Play / Pause audio", group = "System" }
{ description = 'Play / Pause audio', group = 'System' }
),
awful.key(
akey(
{},
"XF86AudioNext",
'XF86AudioNext',
function(c)
awful.spawn("playerctl next")
aspawn('playerctl next')
end,
{ description = "Play / Pause audio", group = "System" }
{ description = 'Play / Pause audio', group = 'System' }
),
awful.key(
akey(
{},
"XF86AudioPrev",
'XF86AudioPrev',
function(c)
awful.spawn("playerctl previous")
aspawn('playerctl previous')
end,
{ description = "Play / Pause audio", group = "System" }
{ description = 'Play / Pause audio', group = 'System' }
),
awful.key(
akey(
{ modkey },
"#65",
'#65',
function()
capi.awesome.emit_signal("kblayout::toggle")
kb_helper:cycle_layout()
end,
{ description = "Toggle keyboard layout", group = "System" }
{ description = 'Cycle keyboard layout', group = 'System' }
),
awful.key(
akey(
{ modkey },
"#22",
'#22',
function()
capi.mousegrabber.run(
function(m)
if m.buttons[1] then
local handler = io.open("/home/crylia/.config/awesome/src/config/floating.json", "r")
if not handler then return end
local data_table = json:decode(handler:read("a")) or {}
handler:close()
if type(data_table) ~= "table" then return end
local data = config.read_json('/home/crylia/.config/awesome/src/config/floating.json')
if type(data) ~= 'table' then return end
local c = capi.mouse.current_client
if not c then return end
@@ -320,8 +319,8 @@ return gears.table.join(
WM_INSTANCE = c.instance,
}
-- Check if data_table already had the client then return
for _, v in ipairs(data_table) do
-- Check if data already had the client then return
for _, v in ipairs(data) do
if v.WM_NAME == client_data.WM_NAME and
v.WM_CLASS == client_data.WM_CLASS and
v.WM_INSTANCE == client_data.WM_INSTANCE then
@@ -329,43 +328,33 @@ return gears.table.join(
end
end
table.insert(data_table, client_data)
table.insert(data, client_data)
ruled.client.append_rule {
rule = { class = c.class, instance = c.instance },
properties = {
floating = true
floating = true,
},
}
c.floating = true
handler = io.open("/home/crylia/.config/awesome/src/config/floating.json", "w")
if not handler then return end
handler:write(json:encode(data_table))
handler:close()
config.write_json('/home/crylia/.config/awesome/src/config/floating.json', data)
capi.mousegrabber.stop()
end
return true
end,
"crosshair"
'crosshair'
)
end
),
awful.key(
{ modkey, "Shift" },
"#22",
akey(
{ modkey, 'Shift' },
'#22',
function()
capi.mousegrabber.run(
function(m)
if m.buttons[1] then
local handler = io.open("/home/crylia/.config/awesome/src/config/floating.json", "r")
if not handler then return end
local data_table = json:decode(handler:read("a")) or {}
handler:close()
if type(data_table) ~= "table" then return end
local data = config.read_json('/home/crylia/.config/awesome/src/config/floating.json')
local c = capi.mouse.current_client
if not c then return end
@@ -376,14 +365,14 @@ return gears.table.join(
}
-- Remove client_data from data_table
for k, v in ipairs(data_table) do
for k, v in ipairs(data) do
if v.WM_CLASS == client_data.WM_CLASS and
v.WM_INSTANCE == client_data.WM_INSTANCE then
table.remove(data_table, k)
table.remove(data, k)
ruled.client.remove_rule {
rule = { class = c.class, instance = c.instance },
properties = {
floating = true
floating = true,
},
}
c.floating = false
@@ -391,15 +380,12 @@ return gears.table.join(
end
end
handler = io.open("/home/crylia/.config/awesome/src/config/floating.json", "w")
if not handler then return end
handler:write(json:encode(data_table))
handler:close()
config.write_json('/home/crylia/.config/awesome/src/config/floating.json', data)
capi.mousegrabber.stop()
end
return true
end,
"crosshair"
'crosshair'
)
end
)

View File

@@ -2,33 +2,38 @@
-- This class is to output an error if you fuck up the config --
----------------------------------------------------------------
-- Awesome Libs
local naughty = require("naughty")
local naughty = require('naughty')
local gfilesystem = require('gears.filesystem')
local capi = {
awesome = awesome,
}
if capi.awesome.startup_errors then
naughty.notify({ preset = naughty.config.presets.critical,
title = "Oops, there were errors during startup!",
text = capi.awesome.startup_errors })
naughty.notify { preset = naughty.config.presets.critical,
title = 'Oops, there were errors during startup!',
text = capi.awesome.startup_errors,
gfilesystem.get_configuration_dir() .. 'src/assets/CT.svg',
}
end
do
local in_error = false
capi.awesome.connect_signal(
"debug::error",
'debug::error',
function(err)
if in_error then
return
end
in_error = true
naughty.notify({
naughty.notification {
preset = naughty.config.presets.critical,
title = "ERROR",
text = tostring(err)
})
title = 'ERROR',
app_name = 'System Notification',
message = tostring(err),
icon = gfilesystem.get_configuration_dir() .. 'src/assets/CT.svg',
}
in_error = false
end
)

View File

@@ -2,347 +2,331 @@
-- The Notification defaults --
-------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local menubar = require('menubar')
local naughty = require("naughty")
local wibox = require("wibox")
local rubato = require("src.lib.rubato")
local aspawn = require('awful.spawn')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gshape = require('gears.shape')
local naughty = require('naughty')
local wibox = require('wibox')
local abutton = require('awful.button')
local gtable = require('gears.table')
local rubato = require('src.lib.rubato')
local hover = require('src.tools.hover')
local capi = {
client = client,
screen = screen,
}
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/notifications/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/notifications/'
naughty.config.defaults.ontop = true
naughty.config.defaults.icon_size = dpi(80)
naughty.config.defaults.timeout = Theme_config.notification.timeout
naughty.config.defaults.title = "System Notification"
naughty.config.defaults.timeout = 5
naughty.config.defaults.title = 'System Notification'
naughty.config.defaults.margin = dpi(10)
naughty.config.defaults.position = Theme_config.notification.position
naughty.config.defaults.shape = Theme_config.notification.shape
naughty.config.defaults.border_width = Theme_config.notification.border_width
naughty.config.defaults.border_color = Theme_config.notification.border_color
naughty.config.defaults.spacing = Theme_config.notification.spacing
Theme.notification_spacing = Theme_config.notification.corner_spacing
naughty.connect_signal('request::icon', function(n, context, hints)
if context ~= 'app_icon' then
return
end
local path = menubar.utils.lookup_icon(hints.app_icon) or menubar.utils.lookup_icon(hints.app_icon:lower())
if path then
n.icon = path
end
end)
naughty.connect_signal("request::display", function(n)
naughty.connect_signal('request::display', function(n)
if User_config.dnd then
n:destroy()
else
if n.urgency == "critical" then
n.title = string.format("<span foreground='%s' font='JetBrainsMono Nerd Font, ExtraBold 16'>%s</span>",
Theme_config.notification.fg_urgent_title, n.title) or ""
n.message = string.format("<span foreground='%s'>%s</span>", Theme_config.notification.fg_urgent_message,
n.message) or ""
n.app_name = string.format("<span foreground='%s'>%s</span>", Theme_config.notification.fg_urgent_app_name,
n.app_name) or ""
n.bg = Theme_config.notification.bg_urgent
else
n.title = string.format("<span foreground='%s' font='JetBrainsMono Nerd Font, ExtraBold 16'>%s</span>",
Theme_config.notification.fg_normal_title, n.title) or ""
n.message = string.format("<span foreground='%s'>%s</span>", Theme_config.notification.fg_normal_message,
n.message) or ""
n.bg = Theme_config.notification.bg_normal
n.timeout = n.timeout or Theme_config.notification.timeout or 3
if not n.icon then n.icon = gfilesystem.get_configuration_dir() .. 'src/assets/CT.svg' end
if not n.app_name then n.app_name = 'System' end
if not n.title then n.title = 'System Notification' end
if not n.message then n.message = 'No message provided' end
local color = Theme_config.notification.bg_normal
if n.urgency == 'critical' then
color = Theme_config.notification.fg_urgent_message
end
local use_image = false
if n.app_name == "Spotify" then
if n.app_name == 'Spotify' then
n.actions = {
naughty.action {
program = "Spotify",
id = "skip-prev",
icon = gears.color.recolor_image(icondir .. "skip-prev.svg",
Theme_config.notification.spotify_button_icon_color)
program = 'Spotify',
id = 'skip-prev',
name = 'Previous',
position = 1,
}, naughty.action {
program = "Spotify",
id = "play-pause",
icon = gears.color.recolor_image(icondir .. "play-pause.svg",
Theme_config.notification.spotify_button_icon_color)
program = 'Spotify',
id = 'play-pause',
name = 'Play/Pause',
position = 2,
}, naughty.action {
program = "Spotify",
id = "skip-next",
icon = gears.color.recolor_image(icondir .. "skip-next.svg",
Theme_config.notification.spotify_button_icon_color)
program = 'Spotify',
id = 'skip-next',
name = 'Next',
position = 3,
},
}
}
use_image = true
n.resident = true
end
local action_template_widget
if use_image then
action_template_widget = wibox.template {
{
{
{
{
id = "icon_role",
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
},
id = "centered",
valign = "center",
halign = "center",
widget = wibox.container.place
},
margins = dpi(5),
widget = wibox.container.margin
},
forced_height = dpi(35),
forced_width = dpi(35),
bg = Theme_config.notification.action_bg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background,
id = "bgrnd"
},
id = "mrgn",
top = dpi(10),
bottom = dpi(10),
widget = wibox.container.margin
}
else
action_template_widget = wibox.template {
{
{
{
{
id = "text_role",
font = "JetBrainsMono Nerd Font, Regular 12",
widget = wibox.widget.textbox
},
id = "centered",
widget = wibox.container.place
},
margins = dpi(5),
widget = wibox.container.margin
},
fg = Theme_config.notification.action_fg,
bg = Theme_config.notification.action_bg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background,
id = "bgrnd"
},
id = "mrgn",
top = dpi(10),
bottom = dpi(10),
widget = wibox.container.margin
}
if n.category == 'device.added' or n.category == 'network.connected' then
aspawn('ogg123 /usr/share/sounds/Pop/stereo/notification/device-added.oga')
elseif n.category == 'device.removed' or n.category == 'network.disconnected' then
aspawn('ogg123 /usr/share/sounds/Pop/stereo/notification/device-removed.oga')
elseif n.category == 'device.error' or n.category == 'im.error' or n.category == 'network.error' or n.category ==
'transfer.error' then
aspawn('ogg123 ogg123 /usr/share/sounds/Pop/stereo/alert/battery-low.oga')
elseif n.category == 'email.arrived' then
aspawn('ogg123 /usr/share/sounds/Pop/stereo/notification/message-new-email.oga')
end
local actions_template = wibox.widget {
local action_template = wibox.widget {
notification = n,
base_layout = wibox.widget {
spacing = dpi(40),
layout = wibox.layout.fixed.horizontal
spacing = dpi(90),
layout = wibox.layout.flex.horizontal,
},
widget_template = {
{
{
widget = wibox.widget.textbox,
id = 'text_role',
valign = 'center',
halign = 'center',
font = 'JetBrainsMono Nerd Font, Bold 16',
},
widget = wibox.container.constraint,
height = dpi(35),
strategy = 'exact',
},
id = 'background_role',
widget = wibox.container.background,
bg = color,
fg = Theme_config.notification.bg,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
},
widget_template = action_template_widget,
style = {
underline_normal = false,
underline_selected = true
underline_selected = false,
shape_normal = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
--Don't remove or it will break
bg_normal = color,
bg_selected = color,
fg_normal = Theme_config.notification.bg,
fg_selected = Theme_config.notification.bg,
},
widget = naughty.list.actions
widget = naughty.list.actions,
}
local arc_start = n.timeout
-- Hack to get the action buttons to work even after update
--[[ for i = 1, #action_template._private.layout.children, 1 do
hover.bg_hover { widget = action_template._private.layout.children[i].children[1], overlay = 12, press_overlay = 24 }
end
if (#action_template._private.layout.children > 0) and action_template._private.notification[1].actions[1].program == 'Spotify' then
action_template._private.layout.children[1].children[1]:connect_signal('button::press', function()
aspawn('playerctl previous')
end)
action_template._private.layout.children[2].children[1]:connect_signal('button::press', function()
aspawn('playerctl play-pause')
end)
action_template._private.layout.children[3].children[1]:connect_signal('button::press', function()
aspawn('playerctl next')
end)
end ]]
local start_timer = n.timeout
if n.timeout == 0 then
arc_start = 10
start_timer = 5
end
local w_template = wibox.template {
local notification = wibox.template {
widget = wibox.widget {
{
{
{
{ -- Title
{
{
{ -- Icon
{
{
{
{
{
{
{
image = gears.color.recolor_image(icondir .. "notification-outline.svg",
Theme_config.notification.icon_color),
resize = false,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
notification = n,
widget = naughty.widget.icon,
image = n.icon,
resize = true,
},
right = dpi(5),
widget = wibox.container.margin
widget = wibox.container.background,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(4))
end,
},
widget = wibox.container.place,
},
widget = wibox.container.constraint,
strategy = 'exact',
width = dpi(20),
height = dpi(20),
},
{ -- Title
{
markup = n.app_name or 'System Notification',
align = "center",
valign = "center",
widget = wibox.widget.textbox
notification = n,
widget = naughty.widget.title,
markup = [[<span foreground="]] ..
Theme_config.notification.bg .. [[" font="JetBrainsMono Nerd Font, Bold 16">]] .. (n.app_name or
'Unknown App') .. [[</span> | <span font="JetBrainsMono Nerd Font, Regular 16">]] .. (n.title or 'System Notification') .. [[</span>]],
halign = 'left',
valign = 'center',
},
layout = wibox.layout.fixed.horizontal
widget = wibox.container.constraint,
width = dpi(430),
height = dpi(35),
strategy = 'max',
},
fg = Theme_config.notification.fg_appname,
widget = wibox.container.background
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
margins = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
left = dpi(10),
},
nil,
{
{
{
text = os.date("%H:%M"),
widget = wibox.widget.textbox
},
id = "background",
fg = Theme_config.notification.fg_time,
widget = wibox.container.background
{ -- Clock
widget = wibox.widget.textclock,
format = '%H:%M',
font = 'JetBrainsMono Nerd Font, Bold 16',
fg = Theme_config.notification.bg,
halign = 'right',
valign = 'center',
},
{ -- Close button
{
{
{
{
{
font = User_config.font.specify .. ", 10",
text = "",
align = "center",
valign = "center",
widget = wibox.widget.textbox
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. 'close.svg', Theme_config.notification.bg),
resize = true,
halign = 'center',
valign = 'center',
},
start_angle = 4.71239,
thickness = dpi(2),
min_value = 0,
max_value = arc_start,
value = arc_start,
max_value = start_timer,
value = start_timer,
widget = wibox.container.arcchart,
id = "arc_chart"
id = 'arc',
},
id = "background1",
fg = Theme_config.notification.fg_close,
bg = Theme_config.notification.bg_close,
widget = wibox.container.background
fg = Theme_config.notification.bg_close,
bg = color,
widget = wibox.container.background,
id = 'arc_bg',
},
strategy = "exact",
width = dpi(20),
height = dpi(20),
strategy = 'exact',
width = dpi(18),
height = dpi(18),
widget = wibox.container.constraint,
id = "const1"
},
margins = dpi(10),
left = dpi(5),
widget = wibox.container.margin,
id = "arc_margin"
},
layout = wibox.layout.fixed.horizontal,
id = "arc_app_layout_2"
},
id = "arc_app_layout",
layout = wibox.layout.align.horizontal
right = dpi(5),
widget = wibox.container.margin,
},
id = "arc_app_bg",
border_color = Theme_config.notification.title_border_color,
border_width = Theme_config.notification.title_border_width,
widget = wibox.container.background
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.background,
bg = color,
fg = '#212121',
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
},
{ -- Main body
{ -- Image
{
{
{
{
{
notification = n,
image = n.icon,
resize = true,
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
clip_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 10)
end
valign = 'center',
halign = 'center',
upscale = true,
resize_strategy = 'scale',
widget = naughty.widget.icon,
},
width = naughty.config.defaults.icon_size,
height = naughty.config.defaults.icon_size,
strategy = "exact",
widget = wibox.container.constraint
widget = wibox.container.background,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(10))
end,
},
halign = "center",
valign = "top",
widget = wibox.container.place
},
left = dpi(20),
bottom = dpi(15),
top = dpi(15),
right = dpi(10),
widget = wibox.container.margin
widget = wibox.container.constraint,
strategy = 'exact',
height = dpi(128),
width = dpi(128),
},
{
{
{
widget = naughty.widget.title,
align = "left"
},
{
notification = n,
widget = naughty.widget.message,
align = "left"
font = 'JetBrainsMono Nerd Font, Regular 10',
halign = 'left',
valign = 'center',
},
widget = wibox.container.constraint,
strategy = 'exact',
height = dpi(128),
},
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
},
{ -- Spacer
{
actions_template,
widget = wibox.container.place
widget = wibox.container.background,
bg = Theme_config.notification.action_bg,
},
layout = wibox.layout.fixed.vertical
widget = wibox.container.constraint,
strategy = 'exact',
height = dpi(2),
},
left = dpi(10),
bottom = dpi(10),
top = dpi(10),
right = dpi(20),
widget = wibox.container.margin
action_template,
spacing = dpi(15),
id = 'main_layout',
layout = wibox.layout.fixed.vertical,
},
layout = wibox.layout.fixed.horizontal
widget = wibox.container.margin,
margins = dpi(15),
},
id = "widget_layout",
layout = wibox.layout.fixed.vertical
bg = '#212121',
border_color = '#414141',
border_width = dpi(2),
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
widget = wibox.container.background,
},
id = "min_size",
strategy = "min",
width = dpi(100),
widget = wibox.container.constraint
widget = wibox.container.constraint,
strategy = 'exact',
width = dpi(600),
},
id = "max_size",
strategy = "max",
width = Theme.notification_max_width or dpi(500),
widget = wibox.container.constraint
},
id = "background",
bg = Theme_config.notification.bg,
border_color = Theme_config.notification.border_color,
border_width = Theme_config.notification.border_width,
shape = Theme_config.notification.shape_inside,
widget = wibox.container.background
},
update_callback = function()
end
}
local close = w_template:get_widget().max_size.min_size.widget_layout.arc_app_bg.arc_app_layout.arc_app_layout_2.arc_margin
.const1.background1
local arc = close.arc_chart
if #action_template._private.layout.children < 1 then
notification:get_widget().children[1].children[1].children[1].children[3] = nil
end
local arc_bg = notification:get_widget().children[1].children[1].children[1].children[1].children[1].children[2].children[1].children[2].children[1].children[1]
local arc = arc_bg.children[1]
local timeout = n.timeout
@@ -352,45 +336,36 @@ naughty.connect_signal("request::display", function(n)
duration = n.timeout,
pos = n.timeout,
easing = rubato.linear,
clamp_position = true,
subscribed = function(value)
arc.value = value
end
end,
}
rubato_timer.target = 0
w_template:get_widget():connect_signal(
"mouse::enter",
function()
notification:get_widget():connect_signal('mouse::enter', function()
n.timeout = 99999
rubato_timer.pause = true
end
)
end)
w_template:get_widget():connect_signal(
"mouse::leave",
function()
notification:get_widget():connect_signal('mouse::leave', function()
n.timeout = rubato_timer.pos
rubato_timer.pause = false
rubato_timer.target = 0
end
)
end)
end
Hover_signal(close)
hover.bg_hover { widget = arc_bg }
close:connect_signal("button::press", function()
arc_bg:connect_signal('button::press', function()
n:destroy()
end)
w_template:get_widget():connect_signal("button::press", function(_, _, _, key)
if key == 3 then
n:destroy()
end
-- Raise the client on click
if key == 1 then
notification:get_widget():buttons { gtable.join(
abutton({}, 1, function()
for _, client in ipairs(capi.client.get()) do
if client.name:match(n.app_name) then
if client.class:lower():match(n.app_name:lower()) then
if not client:isvisible() and client.first_tag then
client.first_tag:view_only()
end
@@ -398,44 +373,209 @@ naughty.connect_signal("request::display", function(n)
client:raise()
end
end
end
end),
abutton({}, 3, function()
n:destroy()
end)
), }
local box = naughty.layout.box {
notification = n,
timeout = 5,
type = "notification",
type = 'notification',
screen = capi.screen.primary,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 10)
end,
widget_template = w_template
widget_template = notification,
}
box.buttons = {}
n.buttons = {}
-- This is stupid but there is on way to clone the notifaction widget and being able to modify only the clone
--[=[ naughty.emit_signal('notification_surface', wibox.template {
widget = wibox.widget {
{
{
{
{ -- Title
{
{
{ -- Icon
{
{
{
{
notification = n,
widget = naughty.widget.icon,
--image = n.icon or '',
resize = true,
},
widget = wibox.container.background,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(4))
end,
},
widget = wibox.container.place,
},
widget = wibox.container.constraint,
strategy = 'exact',
width = dpi(20),
height = dpi(20),
},
{ -- Title
{
notification = n,
widget = naughty.widget.title,
markup = [[<span foreground="]] ..
Theme_config.notification.bg .. [[" font="JetBrainsMono Nerd Font, Bold 16">]] .. (n.app_name or
'Unknown App') .. [[</span> | <span font="JetBrainsMono Nerd Font, Regular 16">]] .. (n.title or 'System Notification') .. [[</span>]],
halign = 'left',
valign = 'center',
},
widget = wibox.container.constraint,
width = dpi(280),
height = dpi(35),
strategy = 'max',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin,
left = dpi(10),
},
nil,
{
{
{ -- Clock
widget = wibox.widget.textclock,
format = '%H:%M',
font = 'JetBrainsMono Nerd Font, Bold 16',
fg = Theme_config.notification.bg,
halign = 'right',
valign = 'center',
},
{ -- Close button
{
{
{
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. 'close.svg', Theme_config.notification.bg),
resize = true,
halign = 'center',
valign = 'center',
},
start_angle = 4.71239,
thickness = dpi(2),
min_value = 0,
max_value = start_timer,
value = start_timer,
widget = wibox.container.arcchart,
id = 'arc',
},
fg = Theme_config.notification.bg_close,
bg = color,
widget = wibox.container.background,
id = 'arc_bg',
},
strategy = 'exact',
width = dpi(18),
height = dpi(18),
widget = wibox.container.constraint,
},
left = dpi(5),
widget = wibox.container.margin,
},
layout = wibox.layout.fixed.horizontal,
},
right = dpi(5),
widget = wibox.container.margin,
},
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.background,
bg = color,
fg = '#212121',
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
},
{ -- Main body
{ -- Image
{
{
notification = n,
--image = n.icon or '',
valign = 'center',
halign = 'center',
upscale = true,
resize_strategy = 'scale',
widget = naughty.widget.icon,
},
widget = wibox.container.background,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(10))
end,
},
widget = wibox.container.constraint,
strategy = 'exact',
height = dpi(128),
width = dpi(128),
},
{
{
notification = n,
widget = naughty.widget.message,
text = n.message,
font = 'JetBrainsMono Nerd Font, Regular 8',
halign = 'left',
valign = 'center',
},
widget = wibox.container.constraint,
strategy = 'exact',
height = dpi(128),
},
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
},
},
widget = wibox.container.margin,
margins = dpi(15),
},
bg = '#212121',
border_color = '#414141',
border_width = dpi(2),
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
widget = wibox.container.background,
},
widget = wibox.container.constraint,
strategy = 'exact',
width = dpi(600),
},
}) ]=]
end
end)
naughty.connect_signal(
"destroyed",
function()
end
)
naughty.connect_signal(
"invoked",
function(_, action)
if action.program == "Spotify" then
if action.id == "skip-prev" then
awful.spawn("playerctl previous")
end
if action.id == "play-pause" then
awful.spawn("playerctl play-pause")
end
if action.id == "skip-next" then
awful.spawn("playerctl next")
end
end
end
)
--[[
naughty.notification {
app_name = 'Spotify',
title = 'The Beatles - Here Comes The Sun',
message = 'Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.',
icon = '/home/crylia/Bilder/57384097.jpg',
timeout = 30,
actions = {
naughty.action {
name = 'amet',
position = 1,
text = 'Test',
},
naughty.action {
name = 'Lorem ipsum dolor sit amet',
position = 2,
},
naughty.action {
name = 'Lorem',
position = 3,
},
},
}
]]

View File

@@ -3,56 +3,98 @@
-------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local beautiful = require("beautiful")
local ruled = require("ruled")
local aclient = require('awful.client')
local aplacement = require('awful.placement')
local ascreen = require('awful.screen')
local ruled = require('ruled')
local json = require("src.lib.json-lua.json-lua")
local config = require('src.tools.config')
awful.rules.rules = {
{
awesome.register_xproperty('_NET_WM_BYPASS_COMPOSITOR', 'boolean')
ruled.client.connect_signal('request::rules', function()
ruled.client.append_rule {
rule = {},
properties = {
border_width = beautiful.border_width,
border_color = beautiful.border_normal,
focus = awful.client.focus.filter,
border_width = Theme.border_width,
border_color = Theme.border_normal,
maximized = false,
maximized_horizontal = false,
maximized_vertical = false,
focus = aclient.focus.filter,
raise = true,
keys = require("src.bindings.client_keys"),
buttons = require("src.bindings.client_buttons"),
screen = awful.screen.preferred,
placement = awful.placement.under_mouse + awful.placement.no_overlap + awful.placement.no_offscreen +
awful.placement.centered
}
keys = require('src.bindings.client_keys'),
buttons = require('src.bindings.client_buttons'),
screen = ascreen.preferred,
placement = aplacement.under_mouse + aplacement.no_overlap + aplacement.no_offscreen + aplacement.centered,
},
{
id = "titlebar",
}
ruled.client.append_rule {
rule_any = {
type = {
"normal",
"dialog",
"modal",
"utility"
}
'normal',
'dialog',
},
},
properties = {
titlebars_enabled = true
}
}
titlebars_enabled = true,
},
}
local handler = io.open("/home/crylia/.config/awesome/src/config/floating.json", "r")
ruled.client.append_rule {
rule_any = {
class = {
'proton-bridge',
'1password',
'protonvpn',
'Steam',
},
},
properties = {
minimized = true,
},
}
ruled.client.append_rule {
rule_any = {
class = {
'discord',
'spotify',
},
},
properties = {
tag = '1',
screen = 2,
},
}
if not handler then return end
local data = json:decode(handler:read("a"))
handler:close()
ruled.client.append_rule {
rule_any = {
class = {
'steam_app_990080',
},
},
callback = function(c)
c:set_xproperty('_NET_WM_BYPASS_COMPOSITOR', true)
c:connect_signal('focus', function()
c:set_xproperty('_NET_WM_BYPASS_COMPOSITOR', true)
end)
c:connect_signal('raised', function()
c:set_xproperty('_NET_WM_BYPASS_COMPOSITOR', true)
end)
end,
}
if type(data) ~= "table" then return end
end)
do
local data = config.read_json('/home/crylia/.config/awesome/src/config/floating.json')
for _, c in ipairs(data) do
ruled.client.append_rule {
rule = { class = c.WM_CLASS, instance = c.WM_INSTANCE },
properties = {
floating = true
floating = true,
},
}
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -1,256 +1,74 @@
---@diagnostic disable: undefined-field
-- Awesome Libs
local awful = require("awful")
local gears = require("gears")
local aplacement = require('awful.placement')
local gtimer = require('gears.timer')
local ascreen = require('awful.screen')
local ruled = require('ruled')
local color = require("src.lib.color")
local rubato = require("src.lib.rubato")
local config = require('src.tools.config')
local capi = {
awesome = awesome,
mouse = mouse,
screen = screen,
client = client,
tag = tag
tag = tag,
}
capi.screen.connect_signal("added", function()
capi.screen.connect_signal('added', function()
capi.awesome.restart()
end)
capi.screen.connect_signal("removed", function()
capi.screen.connect_signal('removed', function()
capi.awesome.restart()
end)
capi.client.connect_signal("manage", function(c)
capi.client.connect_signal('manage', function(c)
if capi.awesome.startup and not c.size_hints.user_porition and not c.size_hints.program_position then
awful.placement.no_offscreen(c)
end
if c.class == "Brave-browser" then
c.floating = false
aplacement.no_offscreen(c)
end
if c.transient_for then
c.floating = true
end
if c.fullscreen then
gears.timer.delayed_call(function()
gtimer.delayed_call(function()
if c.valid then
c:geometry(c.screen.geometry)
end
end)
end
local data = config.read_json('/home/crylia/.config/awesome/src/config/floating.json')
for _, c in ipairs(data) do
ruled.client.append_rule {
rule = { class = c.WM_CLASS, instance = c.WM_INSTANCE },
properties = {
floating = true,
},
}
end
end)
capi.client.connect_signal('unmanage', function(c)
if #awful.screen.focused().clients > 0 then
awful.screen.focused().clients[1]:emit_signal(
'request::activate',
'mouse_enter', {
raise = true
if #ascreen.focused().clients > 0 then
ascreen.focused().clients[1]:emit_signal('request::activate', 'mouse_enter', {
raise = true,
})
end
end)
capi.tag.connect_signal('property::selected', function(c)
if #awful.screen.focused().clients > 0 then
awful.screen.focused().clients[1]:emit_signal(
'request::activate',
'mouse_enter', {
raise = true
if #ascreen.focused().clients > 0 then
ascreen.focused().clients[1]:emit_signal('request::activate', 'mouse_enter', {
raise = true,
})
end
end)
-- Sloppy focus
--[[ client.connect_signal("mouse::enter", function(c)
--[[ client.connect_signal('mouse::enter', function(c)
c:emit_signal(
"request::activate",
"mouse_enter",{
raise = true
'request::activate',
'mouse_enter', {
raise = true,
})
end) ]]
--- Takes a wibox.container.background and connects four signals to it
---@param widget wibox.container.background a background widget
---@param bg_override string | nil overrides the default bg hover color
---@param fg_override string | nil overrides the default fg hover color
---@param border_override string | nil overrides the default border hover color
---@param icon_override string | nil the old icon color
---@param icon_override_hover string | nil the hover effect color
function Hover_signal(widget, bg_override, fg_override, border_override, icon_override, icon_override_hover)
local old_wibox, old_cursor, old_bg, old_fg, old_border
widget.bg = widget.bg or "#000000"
widget.fg = widget.fg or "#000000"
widget.border_color = widget.border_color or "#000000"
local icon = nil
if icon_override and icon_override_hover then
icon = widget:get_children_by_id("icon")[1].icon
widget.icon = widget:get_children_by_id("icon")[1]
end
local _, rb, gb, bb = widget.bg:get_rgba()
local _, rf, gf, bf = widget.fg:get_rgba()
local rbo, gbo, bbo = color.utils.hex_to_rgba(widget.border_color)
local r_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(rb * 255), rate = 24 }
local g_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(gb * 255), rate = 24 }
local b_timed_bg = rubato.timed { duration = 0.3, pos = math.floor(bb * 255), rate = 24 }
local r_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(rf * 255), rate = 24 }
local g_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(gf * 255), rate = 24 }
local b_timed_fg = rubato.timed { duration = 0.3, pos = math.floor(bf * 255), rate = 24 }
local r_timed_border = rubato.timed { duration = 0.3, pos = math.floor(rbo), rate = 24 }
local g_timed_border = rubato.timed { duration = 0.3, pos = math.floor(gbo), rate = 24 }
local b_timed_border = rubato.timed { duration = 0.3, pos = math.floor(bbo), rate = 24 }
local function update_bg()
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 { 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 { 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)
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)
r_timed_border:subscribe(update_border)
g_timed_border:subscribe(update_border)
b_timed_border:subscribe(update_border)
local function set_bg(newbg)
r_timed_bg.target, g_timed_bg.target, b_timed_bg.target = newbg[1], newbg[2], newbg[3]
end
local function set_fg(newfg)
r_timed_fg.target, g_timed_fg.target, b_timed_fg.target = newfg[1], newfg[2], newfg[3]
end
local function set_border(newborder)
r_timed_border.target, g_timed_border.target, b_timed_border.target = newborder[1], newborder[2], newborder[3]
end
local _, rbg, gbg, bbg, abg = widget.bg:get_rgba()
old_bg = RGB_to_hex(rbg, gbg, bbg)
local _, rfg, gfg, bfg, afg = widget.fg:get_rgba()
old_fg = RGB_to_hex(rfg, gfg, bfg)
old_border = widget.border_color
local rborder, gborder, bborder = color.utils.hex_to_rgba(old_border)
local function match_hex(hex1, hex2)
local r1, g1, b1 = color.utils.hex_to_rgba(hex1)
local r2, g2, b2 = color.utils.hex_to_rgba(hex2)
return math.abs(r1 - r2) <= 100 and math.abs(g1 - g2) <= 100 and math.abs(b1 - b2) <= 100
end
--[[
local button_release = function()
if old_bg or bg_override then
if bg_override then
bg_override = bg_override .. "dd"
end
widget.bg = bg_override or old_bg .. "dd"
end
if fg_override or old_fg then
if fg_override then
fg_override = fg_override .. "dd"
end
widget.fg = fg_override or old_fg .. "dd"
end
end ]]
local mouse_leave = function()
if old_bg then
local r, g, b = color.utils.hex_to_rgba(old_bg)
set_bg({ r, g, b })
end
if old_fg then
local r, g, b = color.utils.hex_to_rgba(old_fg)
set_fg({ r, g, b })
end
if old_border then
local r, g, b = color.utils.hex_to_rgba(old_border)
set_border({ r, g, b })
end
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
if widget.icon and icon_override and icon_override_hover then
widget.icon.image = gears.color.recolor_image(icon, icon_override)
end
end
local mouse_enter = function()
_, rbg, gbg, bbg, abg = widget.bg:get_rgba()
if not match_hex(RGB_to_hex(rbg, gbg, bbg), old_bg) then
old_bg = RGB_to_hex(rbg, gbg, bbg)
set_bg({ rbg * 0.9 * 255, gbg * 0.9 * 255, bbg * 0.9 * 255 })
end
if old_bg then
if bg_override then
rbg, gbg, bbg = color.utils.hex_to_rgba(bg_override)
set_bg({ rbg, gbg, bbg })
else
set_bg({ rbg * 0.9 * 255, gbg * 0.9 * 255, bbg * 0.9 * 255 })
end
end
_, rfg, gfg, bfg, afg = widget.fg:get_rgba()
if not match_hex(RGB_to_hex(rfg, gfg, bfg), old_fg) then
old_fg = RGB_to_hex(rfg, gfg, bfg)
set_fg({ rfg * 0.9 * 255, gfg * 0.9 * 255, bfg * 0.9 * 255 })
end
if fg_override or old_fg then
if fg_override then
rfg, gfg, bfg = color.utils.hex_to_rgba(fg_override)
set_fg({ rfg, gfg, bfg })
else
set_fg({ rfg * 0.9 * 255, gfg * 0.9 * 255, bfg * 0.9 * 255 })
end
end
if not match_hex(old_border, widget.border_color) then
old_border = widget.border_color
rborder, gborder, bborder = color.utils.hex_to_rgba(old_border)
end
if border_override or old_border then
if border_override then
rborder, gborder, bborder = color.utils.hex_to_rgba(border_override)
set_border({ rborder, gborder, bborder })
else
set_border({ rborder * 0.9, gborder * 0.9, bborder * 0.9 })
end
end
if icon and widget.icon and icon_override and icon_override_hover then
widget.icon.image = gears.color.recolor_image(icon, icon_override_hover)
end
local w = capi.mouse.current_wibox
if w then
old_cursor, old_wibox = w.cursor, w
w.cursor = "hand1"
end
--widget:connect_signal("mouse::leave", mouse_leave)
end
widget:connect_signal("mouse::enter", mouse_enter)
--widget:connect_signal("button::press", button_press)
--widget:connect_signal("button::release", button_release)
widget:connect_signal("mouse::leave", mouse_leave)
end

View File

@@ -0,0 +1,627 @@
local math = math
-- Awesome libs
local abutton = require('awful.button')
local atitlebar = require('awful.titlebar')
local atooltip = require('awful.tooltip')
local cairo = require('lgi').cairo
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gdk = require('lgi').Gdk
local gfilesystem = require('gears.filesystem')
local gsurface = require('gears.surface')
local gtimer = require('gears.timer')
local wibox = require('wibox')
local json = require('src.lib.json-lua.json-lua')
gdk.init {}
local capi = {
mouse = mouse,
client = client,
}
local instance = nil
local titlebar = {}
local titlebar_position = User_config.titlebar_position
-- Converts the given hex color to hsv
local function hex2hsv(color)
local r, g, b = gcolor.parse_color(color)
local C_max = math.max(r, g, b)
local C_min = math.min(r, g, b)
local delta = C_max - C_min
local H, S, V
if delta == 0 then
H = 0
elseif C_max == r then
H = 60 * (((g - b) / delta) % 6)
elseif C_max == g then
H = 60 * (((b - r) / delta) + 2)
elseif C_max == b then
H = 60 * (((r - g) / delta) + 4)
end
if C_max == 0 then
S = 0
else
S = delta / C_max
end
V = C_max
return H, S * 100, V * 100
end
-- Converts the given hsv color to hex
local function hsv2hex(H, S, V)
S = S / 100
V = V / 100
if H > 360 then H = 360 end
if H < 0 then H = 0 end
local C = V * S
local X = C * (1 - math.abs(((H / 60) % 2) - 1))
local m = V - C
local r_, g_, b_ = 0, 0, 0
if H >= 0 and H < 60 then
r_, g_, b_ = C, X, 0
elseif H >= 60 and H < 120 then
r_, g_, b_ = X, C, 0
elseif H >= 120 and H < 180 then
r_, g_, b_ = 0, C, X
elseif H >= 180 and H < 240 then
r_, g_, b_ = 0, X, C
elseif H >= 240 and H < 300 then
r_, g_, b_ = X, 0, C
elseif H >= 300 and H < 360 then
r_, g_, b_ = C, 0, X
end
local r, g, b = (r_ + m) * 255, (g_ + m) * 255, (b_ + m) * 255
return ('#%02x%02x%02x'):format(math.floor(r), math.floor(g), math.floor(b))
end
-- Calculates the relative luminance of the given color
local function relative_luminance(color)
local r, g, b = gcolor.parse_color(color)
local function from_sRGB(u) return u <= 0.0031308 and 25 * u / 323 or ((200 * u + 11) / 211) ^ (12 / 5) end
return 0.2126 * from_sRGB(r) + 0.7152 * from_sRGB(g) + 0.0722 * from_sRGB(b)
end
-- Rotates the hue of the given hex color by the specified angle (in degrees)
local function rotate_hue(color, angle)
local H, S, V = hex2hsv(color)
angle = math.max(math.min(angle or 0, 360), 0)
H = (H + angle) % 360
return hsv2hex(H, S, V)
end
-- Lightens a given hex color by the specified amount
local function lighten(color, amount)
local r, g, b
r, g, b = gcolor.parse_color(color)
r = 255 * r
g = 255 * g
b = 255 * b
r = r + math.floor(2.55 * amount)
g = g + math.floor(2.55 * amount)
b = b + math.floor(2.55 * amount)
r = r > 255 and 255 or r
g = g > 255 and 255 or g
b = b > 255 and 255 or b
return ('#%02x%02x%02x'):format(r, g, b)
end
-- Darkens a given hex color by the specified amount
local function darken(color, amount)
local r, g, b
r, g, b = gcolor.parse_color(color)
r = 255 * r
g = 255 * g
b = 255 * b
r = math.max(0, r - math.floor(r * (amount / 100)))
g = math.max(0, g - math.floor(g * (amount / 100)))
b = math.max(0, b - math.floor(b * (amount / 100)))
return ('#%02x%02x%02x'):format(r, g, b)
end
-- Returns a vertical gradient pattern going from cololr_1 -> color_2
local function duotone_gradient_vertical(color_1, color_2, height, offset_1, offset_2)
local fill_pattern = cairo.Pattern.create_linear(0, 0, 0, height)
local r, g, b, a
r, g, b, a = gcolor.parse_color(color_1)
fill_pattern:add_color_stop_rgba(offset_1 or 0, r, g, b, a)
r, g, b, a = gcolor.parse_color(color_2)
fill_pattern:add_color_stop_rgba(offset_2 or 1, r, g, b, a)
return fill_pattern
end
-- Returns a horizontal gradient pattern going from cololr_1 -> color_2
local function duotone_gradient_horizontal(color_1, color_2, width, offset_1, offset_2)
local fill_pattern = cairo.Pattern.create_linear(0, 0, width, 0)
local r, g, b, a
r, g, b, a = gcolor.parse_color(color_1)
fill_pattern:add_color_stop_rgba(offset_1 or 0, r, g, b, a)
r, g, b, a = gcolor.parse_color(color_2)
fill_pattern:add_color_stop_rgba(offset_2 or 1, r, g, b, a)
return fill_pattern
end
local function save(tbl, filename)
local handler = io.open(filename, 'w')
if not handler then return nil end
handler:write(json:encode(tbl))
handler:close()
end
local function load(file)
local handler = io.open(file, 'r')
if not handler then return nil end
local data = json:decode(handler:read('*a'))
assert(data, 'Failed to load file: ' .. file)
handler:close()
return data
end
local function set_color_rule(c, color)
if (not c) or (not c.instance) then return end
titlebar.color_rules[c.instance .. titlebar_position] = color
save(titlebar.color_rules, titlebar.color_rules_filepath)
end
local function get_color_rule(c)
if (not c) or (not c.instance) then return end
return titlebar.color_rules[c.instance .. titlebar_position]
end
---Gets the dominant color of a client for the purpose of setting the titlebar color
---@param client any
---@return string hex color
local function get_dominant_color(client)
local tally = {}
local content = gsurface(client.content)
local cgeo = client:geometry()
local x_offset, y_offset = 2, 2
local color
if titlebar_position == 'top' then
for x_pos = 0, math.floor(cgeo.width / 2), 2 do
for y_pos = 0, 8, 1 do
color = '#' .. gdk.pixbuf_get_from_surface(content, x_offset + x_pos, y_offset + y_pos, 1, 1
):get_pixels():gsub('.', function(c)
return ('%02x'):format(c:byte())
end)
if not tally[color] then
tally[color] = 1
else
tally[color] = tally[color] + 1
end
end
end
elseif titlebar_position == 'left' then
x_offset = 0
for y_pos = 0, math.floor(cgeo.height / 2), 2 do
for x_pos = 0, 8, 1 do
color = '#' .. gdk.pixbuf_get_from_surface(content, x_offset + x_pos, y_offset + y_pos, 1, 1
):get_pixels():gsub('.', function(c)
return ('%02x'):format(c:byte())
end)
if not tally[color] then
tally[color] = 1
else
tally[color] = tally[color] + 1
end
end
end
end
local mode_c = 0
for kolor, kount in pairs(tally) do
if kount > mode_c then
mode_c = kount
color = kolor
end
end
set_color_rule(client, color)
return color
end
local function create_button_image(name, is_focused, event, is_on)
titlebar.key = titlebar.key or {}
titlebar.key.close_color = Theme_config.titlebar.close
titlebar.key.minimize_color = Theme_config.titlebar.minimize
titlebar.key.maximize_color = Theme_config.titlebar.maximize
titlebar.key.floating_color = Theme_config.titlebar.floating
titlebar.key.ontop_color = Theme_config.titlebar.ontop
titlebar.key.sticky_color = Theme_config.titlebar.sticky
local focus_state = is_focused and 'focused' or 'unfocused'
local key_img
if is_on ~= nil then
local toggle_state = is_on and 'on' or 'off'
key_img = ('%s_%s_%s_%s'):format(name, toggle_state, focus_state, event)
else
key_img = ('%s_%s_%s'):format(name, focus_state, event)
end
if titlebar.key[key_img] then return titlebar.key[key_img] end
local key_color = key_img .. '_color'
if not titlebar.key[key_color] then
local key_base_color = name .. '_color'
local base_color = titlebar.key[key_base_color] or rotate_hue(hsv2hex(math.random(0, 360), 70, 90), 33)
titlebar.key[key_base_color] = base_color
local button_color = base_color
local H = hex2hsv(base_color)
if not is_focused and event ~= 'hover' then
button_color = hsv2hex(H, 0, 50)
end
button_color = (event == 'hover') and lighten(button_color, 25) or
(event == 'press') and darken(button_color, 25) or button_color
titlebar.key[key_color] = button_color
end
local button_size = Theme_config.titlebar.button_size
local surface = cairo.ImageSurface.create('ARGB32', button_size, button_size)
local cr = cairo.Context.create(surface)
cr:arc(button_size / 2, button_size / 2, button_size / 2, math.rad(0), math.rad(360))
cr:set_source_rgba(gcolor.parse_color(titlebar.key[key_color] or '#fefefa'))
cr.antialias = cairo.Antialias.BEST
cr:fill()
titlebar.key[key_img] = surface
return titlebar.key[key_img]
end
---Returns a button widget for the titlebar
---@param c client
---@param name string Name for the tooltip and the correct button image
---@param button_callback function callback function called when the button is pressed
---@param property string|nil client state, e.g. active or inactive
---@return wibox.widget button widget
local function create_titlebar_button(c, name, button_callback, property)
local button_img = wibox.widget.imagebox(nil, false)
local tooltip = atooltip {
text = name,
delay_show = 0.5,
margins_leftright = 12,
margins_topbottom = 6,
timeout = 0.25,
align = 'bottom_right',
}
tooltip:add_to_object(button_img)
local is_on, is_focused
local event = 'normal'
local function update()
is_focused = c.active
-- If the button is for a property that can be toggled
if property then
is_on = c[property]
button_img.image = create_button_image(name, is_focused, event, is_on)
else
button_img.image = create_button_image(name, is_focused, event)
end
end
c:connect_signal('unfocus', update)
c:connect_signal('focus', update)
if property then c:connect_signal('property::' .. property, update) end
button_img:connect_signal('mouse::enter', function()
event = 'hover'
update()
end)
button_img:connect_signal('mouse::leave', function()
event = 'normal'
update()
end)
button_img.buttons = abutton({}, 1, function()
event = 'press'
update()
end, function()
if button_callback then
event = 'normal'
button_callback()
else
event = 'hover'
end
update()
end)
button_img.id = 'button_image'
update()
return wibox.widget {
{
{
button_img,
widget = wibox.container.constraint,
height = Theme_config.titlebar.button_size,
width = Theme_config.titlebar.button_size,
strategy = 'exact',
},
widget = wibox.container.margin,
margins = dpi(5),
},
widget = wibox.container.place,
}
end
---Get the mouse bindings for the titlebar
---@param c client
---@return table all mouse bindings for the titlebar
local function get_titlebar_mouse_bindings(c)
local clicks = 0
local tolerance = 4
local buttons = { abutton({}, 1, function()
local cx, cy = capi.mouse.coords().x, capi.mouse.coords().y
local delta = 250 / 1000
clicks = clicks + 1
if clicks == 2 then
local nx, ny = capi.mouse.coords().x, capi.mouse.coords().y
if math.abs(cx - nx) <= tolerance and math.abs(cy - ny) <= tolerance then
c.maximized = not c.maximized
end
else
c:activate { context = 'titlebar', action = 'mouse_move' }
end
-- Start a timer to clear the click count
gtimer.weak_start_new(delta, function() clicks = 0 end)
end), abutton({}, 2, function()
c.color = get_dominant_color(c)
set_color_rule(c, c.color)
add_titlebar(c)
end), abutton({}, 3, function()
c:activate { context = 'mouse_click', action = 'mouse_resize' }
end), }
return buttons
end
---Creates a title widget for the titlebar
---@param c client
---@return wibox.widget The title widget
local function create_titlebar_title(c)
local title_widget = wibox.widget {
halign = 'center',
ellipsize = 'middle',
opacity = c.active and 1 or 0.7,
valign = 'center',
widget = wibox.widget.textbox,
}
local function update()
title_widget.markup = ("<span foreground='%s'>%s</span>"):format(
(((relative_luminance('#fefefa') + 0.05) / (relative_luminance(c.color) + 0.05)) >= 7 and true)
and '#fefefa' or '#242424', c.name)
end
c:connect_signal('property::name', update)
c:connect_signal('unfocus', function()
title_widget.opacity = 0.7
end)
c:connect_signal('focus', function() title_widget.opacity = 1 end)
update()
return {
title_widget,
widget = wibox.container.margin,
margins = Theme_config.titlebar.title_margin,
}
end
---Creates the widget for a titlebar item
---@param c client
---@param name string The name of the item
---@return wibox.widget|nil widget The titlebar item widget
local function get_titlebar_item(c, name)
if titlebar_position == 'top' then
if name == 'close' then return create_titlebar_button(c, name, function() c:kill() end)
elseif name == 'maximize' then
return create_titlebar_button(c, name, function() c.maximized = not c.maximized end, 'maximized')
elseif name == 'minimize' then
return create_titlebar_button(c, name, function() c.minimized = true end)
elseif name == 'ontop' then
return create_titlebar_button(c, name, function() c.ontop = not c.ontop end, 'ontop')
elseif name == 'floating' then
return create_titlebar_button(c, name, function()
c.floating = not c.floating
if c.floating then
c.maximized = false
end
end, 'floating')
elseif name == 'sticky' then
return create_titlebar_button(c, name, function()
c.sticky = not c.sticky
return c.sticky
end, 'sticky')
elseif name == 'title' then
return create_titlebar_title(c)
elseif name == 'icon' then
return wibox.widget {
atitlebar.widget.iconwidget(c),
widget = wibox.container.margin,
margins = dpi(5),
}
end
elseif titlebar_position == 'left' then
if name == 'close' then
return create_titlebar_button(c, name, function() c:kill() end)
elseif name == 'maximize' then
return create_titlebar_button(c, name, function() c.maximized = not c.maximized end, 'maximized')
elseif name == 'minimize' then
return create_titlebar_button(c, name, function() c.minimized = true end)
elseif name == 'ontop' then
return create_titlebar_button(c, name, function() c.ontop = not c.ontop end, 'ontop')
elseif name == 'floating' then
return create_titlebar_button(c, name, function()
c.floating = not c.floating
if c.floating then
c.maximized = false
end
end, 'floating')
elseif name == 'sticky' then
return create_titlebar_button(c, name, function()
c.sticky = not c.sticky
return c.sticky
end, 'sticky')
elseif name == 'icon' then
return wibox.widget {
atitlebar.widget.iconwidget(c),
widget = wibox.container.margin,
margins = dpi(5),
}
end
end
end
---Groups together the titlebar items for left, center, right placement
---@param c client
---@param group table|string The name of the group or a table of item names
---@return wibox.widget|nil widget The titlebar item widget
local function create_titlebar_items(c, group)
if not group then return nil end
if type(group) == 'string' then return create_titlebar_title(c) end
local layout
if titlebar_position == 'left' then
layout = wibox.widget {
layout = wibox.layout.fixed.vertical,
}
elseif titlebar_position == 'top' then
layout = wibox.widget {
layout = wibox.layout.fixed.horizontal,
}
end
local item
for _, name in ipairs(group) do
item = get_titlebar_item(c, name)
if item then layout:add(item) end
end
return layout
end
---Adds the titlebar to the left of a client
---@param c client
function add_titlebar(c)
if titlebar_position == 'top' then
atitlebar(c, {
size = Theme_config.titlebar.size,
bg = gcolor.transparent,
position = 'top',
}):setup {
{
{
create_titlebar_items(c, User_config.titlebar_items.left_and_bottom),
widget = wibox.container.margin,
left = dpi(5),
},
{
create_titlebar_items(c, User_config.titlebar_items.middle),
buttons = get_titlebar_mouse_bindings(c),
layout = wibox.layout.flex.horizontal,
},
{
create_titlebar_items(c, User_config.titlebar_items.right_and_top),
widget = wibox.container.margin,
right = dpi(5),
},
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.background,
bg = duotone_gradient_vertical(
lighten(c.color, 1),
c.color,
Theme_config.titlebar.size,
0,
0.5
),
}
elseif titlebar_position == 'left' then
atitlebar(c, {
size = Theme_config.titlebar.size,
bg = gcolor.transparent,
position = 'left',
}):setup {
{
{
create_titlebar_items(c, User_config.titlebar_items.right_and_top),
widget = wibox.container.margin,
top = dpi(5),
},
{
create_titlebar_items(c, User_config.titlebar_items.middle),
buttons = get_titlebar_mouse_bindings(c),
layout = wibox.layout.flex.vertical,
},
{
create_titlebar_items(c, User_config.titlebar_items.left_and_bottom),
widget = wibox.container.margin,
left = dpi(5),
},
layout = wibox.layout.align.vertical,
},
widget = wibox.container.background,
bg = duotone_gradient_horizontal(
lighten(c.color, 1),
c.color,
Theme_config.titlebar.size,
0,
0.5
),
}
end
if not c.floating then
atitlebar.hide(c, titlebar_position)
end
c:connect_signal('property::maximized', function()
if not c.floating then
--if not client or not client.focus then return end
atitlebar.hide(c, titlebar_position)
elseif c.floating and (not (c.maximized or c.fullscreen)) then
atitlebar.show(c, titlebar_position)
end
end)
c:connect_signal('property::floating', function()
if not c.floating then
--if not client or not client.focus then return end
atitlebar.hide(c, titlebar_position)
elseif c.floating and (not (c.maximized or c.fullscreen)) then
atitlebar.show(c, titlebar_position)
end
end)
end
if not instance then
instance = setmetatable(titlebar, { __call = function()
titlebar.color_rules_filepath = gfilesystem.get_configuration_dir() .. '/src/config/' .. 'color_rules.json'
titlebar.color_rules = load(titlebar.color_rules_filepath) or {}
capi.client.connect_signal('request::titlebars', function(c)
c._cb_add_window_decorations = function()
gtimer.weak_start_new(0.5, function()
c.color = get_dominant_color(c)
add_titlebar(c)
c:disconnect_signal('request::activate', c._cb_add_window_decorations)
end)
end
local color = get_color_rule(c)
if color then
c.color = color
add_titlebar(c)
else
c.color = Theme_config.titlebar.color
add_titlebar(c)
c:connect_signal('request::activate', c._cb_add_window_decorations)
end
end)
capi.client.connect_signal('request::manage', function(c)
if not c.floating then
--if not client or not client.focus then return end
atitlebar.hide(c, titlebar_position)
elseif c.floating and (not (c.maximized or c.fullscreen)) then
atitlebar.show(c, titlebar_position)
end
end)
end, })
end
return instance

View File

@@ -1,60 +0,0 @@
local setmetatable = setmetatable
local base = require("wibox.widget.base")
local gtable = require("gears.table")
local wibox = require("wibox")
local module = { mt = {} }
function module:layout(_, width, height)
if self._private.widget then
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
end
end
function module:fit(context, width, height)
local w, h = 0, 0
if self._private.widget then
w, h = base.fit_widget(self, context, self._private.widget, width, height)
end
return w, h
end
module.set_widget = base.set_widget_common
function module:set_widget_template(widget_template)
self._private.widget_template = widget_template
self:set_widget(widget_template)
end
function module:get_widget()
return self._private.widget
end
function module:get_children()
return { self._private.widget }
end
function module:set_children(children)
self:set_widget(children[1])
end
function module:reset()
self._private.widget_template = nil
self:set_widget(nil)
end
local function new(args)
local self = base.make_widget(nil, nil, { enable_properties = true })
gtable.crush(self, module, true)
self:set_widget(wibox.widget.textbox("Hello World!"))
return self
end
function module.mt:__call(...)
return new(...)
end
return setmetatable(module, module.mt)

View File

@@ -3,26 +3,31 @@
--------------------------------------
-- Awesome libs
local abutton = require("awful.button")
local aspawn = require("awful.spawn")
local base = require("wibox.widget.base")
local dpi = require("beautiful").xresources.apply_dpi
local gcolor = require("gears.color")
local gfilesystem = require("gears").filesystem
local Gio = require("lgi").Gio
local gtable = require("gears.table")
local wibox = require("wibox")
local abutton = require('awful.button')
local aspawn = require('awful.spawn')
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears').filesystem
local Gio = require('lgi').Gio
local gtable = require('gears.table')
local wibox = require('wibox')
-- Third party libs
local json = require("src.lib.json-lua.json-lua")
local cm = require("src.modules.context_menu.init")
local cm = require('src.modules.context_menu.init')
local dock = require('src.modules.crylia_bar.dock')
-- Local libs
local config = require('src.tools.config')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
mouse = mouse,
}
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/context_menu/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/context_menu/'
local application_grid = { mt = {} }
@@ -31,11 +36,11 @@ local application_grid = { mt = {} }
This is done here once because it would be unnecessary to do it for every instance
]]
do
local dir = gfilesystem.get_configuration_dir() .. "src/config"
local dir = gfilesystem.get_configuration_dir() .. 'src/config'
gfilesystem.make_directories(dir)
dir = dir .. "/applications.json"
dir = dir .. '/applications.json'
if not gfilesystem.file_readable(dir) then
aspawn("touch " .. dir)
aspawn('touch ' .. dir)
end
end
@@ -125,55 +130,55 @@ local function get_applications_from_file()
{
{
{ -- Icon
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
image = Get_gicon_path(app_info.get_icon(app)) or
Get_gicon_path(app_info.get_icon(app),
Gio.DesktopAppInfo.get_string(desktop_app_info, "X-AppImage-Old-Icon")) or "",
Gio.DesktopAppInfo.get_string(desktop_app_info, 'X-AppImage-Old-Icon')) or '',
resize = true,
widget = wibox.widget.imagebox
widget = wibox.widget.imagebox,
},
height = dpi(64),
width = dpi(64),
strategy = "exact",
widget = wibox.container.constraint
strategy = 'exact',
widget = wibox.container.constraint,
},
{
{ -- Name
text = app_info.get_name(app),
align = "center",
valign = "center",
widget = wibox.widget.textbox
align = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
strategy = "exact",
strategy = 'exact',
width = dpi(170),
-- Prevents widget from overflowing
height = dpi(40),
widget = wibox.container.constraint
widget = wibox.container.constraint,
},
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
halign = "center",
valign = "center",
widget = wibox.container.place
halign = 'center',
valign = 'center',
widget = wibox.container.place,
},
margins = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
},
name = app_info.get_name(app),
comment = Gio.DesktopAppInfo.get_string(desktop_app_info, "Comment") or "",
exec = Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"),
keywords = Gio.DesktopAppInfo.get_string(desktop_app_info, "Keywords") or "",
categories = Gio.DesktopAppInfo.get_categories(desktop_app_info) or "",
terminal = Gio.DesktopAppInfo.get_string(desktop_app_info, "Terminal") == "true",
comment = Gio.DesktopAppInfo.get_string(desktop_app_info, 'Comment') or '',
exec = Gio.DesktopAppInfo.get_string(desktop_app_info, 'Exec'),
keywords = Gio.DesktopAppInfo.get_string(desktop_app_info, 'Keywords') or '',
categories = Gio.DesktopAppInfo.get_categories(desktop_app_info) or '',
terminal = Gio.DesktopAppInfo.get_string(desktop_app_info, 'Terminal') == 'true',
actions = Gio.DesktopAppInfo.list_actions(desktop_app_info),
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or "",
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or '',
border_color = Theme_config.application_launcher.application.border_color,
border_width = Theme_config.application_launcher.application.border_width,
bg = Theme_config.application_launcher.application.bg,
fg = Theme_config.application_launcher.application.fg,
shape = Theme_config.application_launcher.application.shape,
widget = wibox.container.background
widget = wibox.container.background,
}
local context_menu = cm {
widget_template = wibox.widget {
@@ -183,122 +188,113 @@ local function get_applications_from_file()
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
},
spacing = dpi(10),
entries = {
{
name = "Execute as sudo",
icon = gcolor.recolor_image(icondir .. "launch.svg",
name = 'Execute as sudo',
icon = gcolor.recolor_image(icondir .. 'launch.svg',
Theme_config.application_launcher.application.cm_icon_color),
callback = function()
capi.awesome.emit_signal("application_launcher::show")
aspawn("/home/crylia/.config/awesome/src/scripts/start_as_admin.sh " .. app_widget.exec)
end
capi.awesome.emit_signal('application_launcher::show')
aspawn('/home/crylia/.config/awesome/src/scripts/start_as_admin.sh ' .. app_widget.exec)
end,
},
{
name = "Pin to dock",
icon = gcolor.recolor_image(icondir .. "pin.svg",
name = 'Pin to dock',
icon = gcolor.recolor_image(icondir .. 'pin.svg',
Theme_config.application_launcher.application.cm_icon_color),
callback = function()
-- Open dock.js and read all its content into a table, add the new app into the table and write it back
local file_path = gfilesystem.get_configuration_dir() .. "src/config/dock.json"
local handler = io.open(file_path, "r")
if not handler then return end
local dock_table = json:decode(handler:read("a")) or {}
handler:close()
assert(type(dock_table) == "table", "dock_table is not a table")
table.insert(dock_table, {
name = app_widget.name or "",
--[[ async.read_json(gfilesystem.get_configuration_dir() .. 'src/config/dock.json', function(data)
table.insert(data, {
name = app_widget.name or '',
icon = Get_gicon_path(app_info.get_icon(app)) or
Get_gicon_path(app_info.get_icon(app),
Gio.DesktopAppInfo.get_string(desktop_app_info, "X-AppImage-Old-Icon")) or "",
comment = app_widget.comment or "",
exec = app_widget.exec or "",
keywords = app_widget.keywords or "",
categories = app_widget.categories or "",
terminal = app_widget.terminal or "",
actions = app_widget.actions or "",
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or ""
Gio.DesktopAppInfo.get_string(desktop_app_info, 'X-AppImage-Old-Icon')) or '',
comment = app_widget.comment or '',
exec = app_widget.exec or '',
keywords = app_widget.keywords or '',
categories = app_widget.categories or '',
terminal = app_widget.terminal or '',
actions = app_widget.actions or '',
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or ''
})
local dock_encoded = json:encode(dock_table)
handler = io.open(file_path, "w")
if not handler then return end
handler:write(dock_encoded)
handler:close()
capi.awesome.emit_signal("dock::changed")
end
async.write_json(gfilesystem.get_configuration_dir() .. 'src/config/dock.json', data, function()
capi.awesome.emit_signal('dock::changed')
end)
end) ]]
dock:get_dock_for_screen(capi.mouse.screen):pin_element {
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or '',
}
end,
},
{
name = "Add to desktop",
icon = gcolor.recolor_image(icondir .. "desktop.svg",
name = 'Add to desktop',
icon = gcolor.recolor_image(icondir .. 'desktop.svg',
Theme_config.application_launcher.application.cm_icon_color),
callback = function()
capi.awesome.emit_signal("application_launcher::show")
capi.awesome.emit_signal("desktop::add_to_desktop", {
capi.awesome.emit_signal('application_launcher::show')
capi.awesome.emit_signal('desktop::add_to_desktop', {
label = app_info.get_name(app),
icon = Get_gicon_path(app_info.get_icon(app)) or "",
exec = Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"),
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or ""
icon = Get_gicon_path(app_info.get_icon(app)) or '',
exec = Gio.DesktopAppInfo.get_string(desktop_app_info, 'Exec'),
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or '',
})
end
}
}
end,
},
},
}
-- Hide context menu when the mouse leaves it
context_menu:connect_signal("mouse::leave", function()
context_menu:connect_signal('mouse::leave', function()
context_menu.visible = false
end)
-- Execute command on left click and hide launcher, right click to show context menu
app_widget:buttons(
gtable.join(
abutton({
abutton {
modifiers = {},
button = 1,
on_release = function()
Gio.AppInfo.launch_uris_async(app)
capi.awesome.emit_signal("application_launcher::show")
end
}),
abutton({
capi.awesome.emit_signal('application_launcher::show')
end,
},
abutton {
modifiers = {},
button = 3,
on_release = function()
context_menu:toggle()
end
})
end,
}
)
)
Hover_signal(app_widget)
hover.bg_hover { widget = app_widget }
table.insert(list, app_widget)
end
end
@@ -308,48 +304,41 @@ end
---Takes the search filter and returns a list of applications in the correct order
---@param search_filter any
function application_grid:set_applications(search_filter)
local filter = search_filter or self.filter or ""
local filter = search_filter or self.filter or ''
-- Reset to first position
self._private.curser = {
x = 1,
y = 1
y = 1,
}
local grid = wibox.widget {
homogenous = true,
expand = false,
spacing = dpi(10),
id = "grid",
id = 'grid',
-- 200 is the application element width + 10 spacing
forced_num_cols = math.floor((capi.mouse.screen.geometry.width / 100 * 60) / 200),
forced_num_rows = 7,
orientation = "vertical",
layout = wibox.layout.grid
orientation = 'vertical',
layout = wibox.layout.grid,
}
-- Read the dock.json file and get all apps, these are needed to read/write the launch count
local handler = io.open(gfilesystem.get_configuration_dir() .. "src/config/applications.json", "r")
if not handler then return end
local dock_encoded = handler:read("a") or "{}"
local dock = json:decode(dock_encoded)
assert(type(dock) == "table", "dock is not a table")
local data = config.read_json(gfilesystem.get_configuration_dir() .. 'src/config/applications.json')
local mylist = {}
for _, application in ipairs(self.app_list) do
-- Match the filter for the name, categories and keywords
if string.match(string.lower(application.name or ""), string.lower(filter)) or
string.match(string.lower(application.categories or ""), string.lower(filter)) or
string.match(string.lower(application.keywords or ""), string.lower(filter)) then
if string.match(string.lower(application.name or ''), string.lower(filter)) or
string.match(string.lower(application.categories or ''), string.lower(filter)) or
string.match(string.lower(application.keywords or ''), string.lower(filter)) then
-- If there are no elements in the table, set everything to 0
if #dock == 0 then
if #data == 0 then
application.counter = 0
end
-- Read the counter for the matching app
for _, app in ipairs(dock) do
for _, app in ipairs(data) do
if app.desktop_file == application.desktop_file then
application.counter = app.counter or 0
break;
@@ -380,7 +369,7 @@ function application_grid:set_applications(search_filter)
-- Check if the curser is currently at the same position as the app
capi.awesome.connect_signal(
"update::selected",
'update::selected',
function()
if self._private.curser.y == pos.row and self._private.curser.x == pos.col then
app.border_color = Theme_config.application_launcher.application.border_color_active
@@ -391,7 +380,7 @@ function application_grid:set_applications(search_filter)
)
end
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
self:set_widget(grid)
end
@@ -401,7 +390,7 @@ function application_grid:move_up()
if self._private.curser.y < 1 then
self._private.curser.y = 1
end
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
end
-- Move the curser down by one, making sure it doesn't go out of bounds
@@ -411,7 +400,7 @@ function application_grid:move_down()
if self._private.curser.y > grid_rows then
self._private.curser.y = grid_rows
end
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
end
-- Move the curser left by one, making sure it doesn't go out of bounds
@@ -420,7 +409,7 @@ function application_grid:move_left()
if self._private.curser.x < 1 then
self._private.curser.x = 1
end
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
end
-- Move the curser right by one, making sure it doesn't go out of bounds
@@ -430,7 +419,7 @@ function application_grid:move_right()
if self._private.curser.x > grid_cols then
self._private.curser.x = grid_cols
end
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
end
--- Execute the currently selected app and add to the launch count
@@ -441,17 +430,9 @@ function application_grid:execute()
-- Launch the application async
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0))
local file_path = gfilesystem.get_configuration_dir() .. "src/config/applications.json"
local handler = io.open(file_path, "r")
if not handler then return end
local dock_encoded = handler:read("a") or "{}"
local dock = json:decode(dock_encoded)
assert(type(dock) == "table", "dock is not a table")
local data = config.read_json(gfilesystem.get_configuration_dir() .. 'src/config/applications.json')
-- Increase the counter by one then rewrite to the file, its a bit hacky but it works
for _, prog in ipairs(dock) do
for _, prog in ipairs(data) do
if prog.desktop_file:match(selected_widget.desktop_file) then
prog.counter = prog.counter + 1
-- I don't like goto's, but its the easiest way here(PR is welcome).
@@ -462,25 +443,21 @@ function application_grid:execute()
local prog = {
name = selected_widget.name,
desktop_file = selected_widget.desktop_file,
counter = 1
counter = 1,
}
table.insert(dock, prog)
table.insert(data, prog)
end
::continue::
handler:close()
handler = io.open(file_path, "w")
if not handler then return end
handler:write(json:encode_pretty(dock))
handler:close()
config.write_json(gfilesystem.get_configuration_dir() .. 'src/config/applications.json', data)
end
-- Reset the grid cursor
function application_grid:reset()
self._private.curser = {
x = 1,
y = 1
y = 1,
}
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
end
function application_grid.new(args)
@@ -496,8 +473,4 @@ function application_grid.new(args)
return w
end
function application_grid.mt:__call(...)
return application_grid.new(...)
end
return setmetatable(application_grid, application_grid.mt)
return setmetatable(application_grid, { __call = function(...) return application_grid.new(...) end })

View File

@@ -3,17 +3,17 @@
--------------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local akeygrabber = require("awful.keygrabber")
local aplacement = require("awful.placement")
local apopup = require("awful.popup")
local awidget = require("awful.widget")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears.table")
local wibox = require("wibox")
local abutton = require('awful.button')
local akeygrabber = require('awful.keygrabber')
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local awidget = require('awful.widget')
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears.table')
local wibox = require('wibox')
-- Own libs
local app_grid = require("src.modules.application_launcher.application")
local app_grid = require('src.modules.application_launcher.application')
local capi = {
awesome = awesome,
@@ -23,18 +23,17 @@ local capi = {
-- This grid object is shared to avoid having multipe unnecessary instances
local application_grid = app_grid {}
local application_launcher = { mt = {} }
local application_launcher = {}
function application_launcher.new(args)
args = args or {}
-- Create a new inputbox
local searchbar = awidget.inputbox {
hint_text = "Search...",
valign = "center",
halign = "left",
hint_text = 'Search...',
valign = 'center',
halign = 'left',
}
-- Application launcher popup
local application_container = apopup {
widget = {
@@ -48,7 +47,7 @@ function application_launcher.new(args)
margins = 5,
},
widget = wibox.container.constraint,
strategy = "exact",
strategy = 'exact',
height = dpi(50),
},
widget = wibox.container.background,
@@ -57,22 +56,22 @@ function application_launcher.new(args)
border_color = Theme_config.application_launcher.searchbar.border_color,
border_width = Theme_config.application_launcher.searchbar.border_width,
shape = Theme_config.application_launcher.searchbar.shape,
id = "searchbar_bg"
id = 'searchbar_bg',
},
{
application_grid,
layout = require("src.lib.overflow_widget.overflow").vertical,
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
step = dpi(100),
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
margins = dpi(20),
widget = wibox.container.margin
widget = wibox.container.margin,
},
height = args.screen.geometry.height / 100 * 60,
strategy = "exact",
strategy = 'exact',
widget = wibox.container.constraint,
},
ontop = true,
@@ -82,7 +81,7 @@ function application_launcher.new(args)
placement = aplacement.centered,
bg = Theme_config.application_launcher.bg,
border_color = Theme_config.application_launcher.border_color,
border_width = Theme_config.application_launcher.border_width
border_width = Theme_config.application_launcher.border_width,
}
gtable.crush(application_container, application_launcher, true)
@@ -91,31 +90,31 @@ function application_launcher.new(args)
searchbar:buttons(gtable.join {
abutton({}, 1, function()
searchbar:focus()
end)
end),
})
--#region Hover signals to change the cursor to a text cursor
local old_cursor, old_wibox
searchbar:connect_signal("mouse::enter", function()
searchbar:connect_signal('mouse::enter', function()
local wid = capi.mouse.current_wibox
if wid then
old_cursor, old_wibox = wid.cursor, wid
wid.cursor = "xterm"
wid.cursor = 'xterm'
end
end)
searchbar:connect_signal("mouse::leave", function()
searchbar:connect_signal('mouse::leave', function()
old_wibox.cursor = old_cursor
old_wibox = nil
end)
--#endregion
-- Get a reference to the searchbar background value
local searchbar_bg = application_container.widget:get_children_by_id("searchbar_bg")[1]
local searchbar_bg = application_container.widget:get_children_by_id('searchbar_bg')[1]
-- Toggle visible for the application launcher and init the searchbar
capi.awesome.connect_signal("application_launcher::show", function()
capi.awesome.connect_signal('application_launcher::show', function()
if capi.mouse.screen == args.screen then
capi.awesome.emit_signal("update::selected")
capi.awesome.emit_signal('update::selected')
if capi.mouse.screen == args.screen then
application_container.visible = not application_container.visible
end
@@ -123,76 +122,76 @@ function application_launcher.new(args)
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_active
searchbar:focus()
else
searchbar:set_text("")
searchbar:set_text('')
akeygrabber.stop()
end
end
end)
-- Execute the currently selected application, reset the searchbar and hide the launcher
searchbar:connect_signal("submit", function(_, text)
searchbar:connect_signal('submit', function(_, text)
application_grid:execute()
capi.awesome.emit_signal("application_launcher::show")
searchbar:set_text("")
capi.awesome.emit_signal('application_launcher::show')
searchbar:set_text('')
application_grid:set_applications(searchbar:get_text())
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_color
end)
-- Hide the application launcher when the keygrabber stops and reset the searchbar
searchbar:connect_signal("stopped", function(_, stop_key)
if stop_key == "Escape" then
capi.awesome.emit_signal("application_launcher::show")
searchbar:connect_signal('stopped', function(_, stop_key)
if stop_key == 'Escape' then
capi.awesome.emit_signal('application_launcher::show')
end
searchbar:set_text("")
searchbar:set_text('')
application_grid:set_applications(searchbar:get_text())
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_color
end)
-- When started change the background for the searchbar
searchbar:connect_signal("started", function()
searchbar:connect_signal('started', function()
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_active
end)
-- On every keypress in the searchbar check for certain inputs
searchbar:connect_signal("inputbox::key_pressed", function(_, modkey, key)
if key == "Escape" then -- Escape to stop the keygrabber, hide the launcher and reset the searchbar
searchbar:connect_signal('inputbox::key_pressed', function(_, modkey, key)
if key == 'Escape' then -- Escape to stop the keygrabber, hide the launcher and reset the searchbar
searchbar:stop()
capi.awesome.emit_signal("application_launcher::show")
capi.awesome.emit_signal('application_launcher::show')
application_grid:reset()
searchbar:set_text("")
elseif key == "Down" or key == "Right" then --If down or right is pressed initiate the grid navigation
if key == "Down" then
searchbar:set_text('')
elseif key == 'Down' or key == 'Right' then --If down or right is pressed initiate the grid navigation
if key == 'Down' then
application_grid:move_down()
elseif key == "Right" then
elseif key == 'Right' then
application_grid:move_right()
end
searchbar:stop()
--New keygrabber to allow for key navigation
akeygrabber.run(function(mod, key2, event)
if event == "press" then
if key2 == "Down" then
if event == 'press' then
if key2 == 'Down' then
application_grid:move_down()
elseif key2 == "Up" then
elseif key2 == 'Up' then
local old_y = application_grid._private.curser.y
application_grid:move_up()
if old_y - application_grid._private.curser.y == 0 then
searchbar:focus()
end
elseif key2 == "Left" then
elseif key2 == 'Left' then
application_grid:move_left()
elseif key2 == "Right" then
elseif key2 == 'Right' then
application_grid:move_right()
elseif key2 == "Return" then
elseif key2 == 'Return' then
akeygrabber.stop()
application_grid:execute()
capi.awesome.emit_signal("application_launcher::show")
capi.awesome.emit_signal('application_launcher::show')
application_grid:reset()
searchbar:set_text("")
searchbar:set_text('')
application_grid:set_applications(searchbar:get_text())
elseif key2 == "Escape" then
capi.awesome.emit_signal("application_launcher::show")
elseif key2 == 'Escape' then
capi.awesome.emit_signal('application_launcher::show')
application_grid:reset()
searchbar:set_text("")
searchbar:set_text('')
application_grid:set_applications(searchbar:get_text())
akeygrabber.stop()
end
@@ -205,8 +204,4 @@ function application_launcher.new(args)
end)
end
function application_launcher.mt:__call(...)
return application_launcher.new(...)
end
return setmetatable(application_launcher, application_launcher.mt)
return setmetatable(application_launcher, { __call = function(_, ...) return application_launcher.new(...) end })

View File

@@ -0,0 +1,575 @@
-- Awesome Libs
local abutton = require('awful.button')
local aspawn = require('awful.spawn')
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local gfilesystem = require('gears.filesystem')
local wibox = require('wibox')
-- Third party libs
local rubato = require('src.lib.rubato')
-- Local libs
local audio_helper = require('src.tools.helpers.audio')
local hover = require('src.tools.hover')
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/audio/'
local audio_controller = {}
--#region wibox.widget.base boilerplate
function audio_controller:layout(_, width, height)
if self._private.widget then
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
end
end
function audio_controller:fit(context, width, height)
local w, h = 0, 0 ---@type number|nil, number|nil
if self._private.widget then
w, h = base.fit_widget(self, context, self._private.widget, width, height)
end
return w, h
end
--#endregion
---Set the default source asynchronously
---@param sink any
function audio_controller:set_default_sink(sink)
if not sink then return end
aspawn('pactl set-default-sink ' .. sink)
self:emit_signal('AC::device_changed')
end
---Set the default source asynchronously
function audio_controller:set_default_source(source)
if not source then return end
aspawn('pactl set-default-source ' .. source)
self:emit_signal('AC::device_changed')
end
---Get the default sink asynchronously
---@param callback function returns the default sink as string
function audio_controller:get_default_sink_async(callback)
aspawn.easy_async_with_shell('pactl get-default-sink', function(stdout) callback(stdout:gsub('\n', '')) end)
end
---Takes a sink and name and returns a new device widget, the device_type is for the color
---@param device string sink
---@param name string name of the device
---@param device_type string sink or source
---@return wibox.widget
function audio_controller:get_device_widget(device, name, device_type)
--remove leading spaces from name
name = name:gsub('^%s*(.-)%s*$', '%1')
local icon_color, fg
if device_type == 'source' then
icon_color = Theme_config.volume_controller.device_microphone_fg
fg = Theme_config.volume_controller.device_microphone_fg
elseif device_type == 'sink' then
icon_color = Theme_config.volume_controller.device_headphones_fg
fg = Theme_config.volume_controller.device_headphones_fg
end
local device_widget = wibox.widget {
{
{
{
{
id = 'icon',
resize = true,
image = gcolor.recolor_image(icondir .. 'volume-high.svg', icon_color),
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
widget = wibox.container.constraint,
width = dpi(24),
height = dpi(24),
strategy = 'exact',
},
{
{
id = 'name',
text = name,
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
widget = wibox.container.constraint,
height = dpi(24),
strategy = 'exact',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
margins = dpi(10),
widget = wibox.container.margin,
},
bg = Theme_config.volume_controller.device_bg,
fg = fg,
border_color = Theme_config.volume_controller.device_border_color,
border_width = Theme_config.volume_controller.device_border_width,
shape = Theme_config.volume_controller.device_shape,
widget = wibox.container.background,
sink = device,
}
if device_type == 'sink' then
device_widget:buttons(gtable.join(
abutton({}, 1, function()
self:set_default_sink(device)
end)
))
elseif device_type == 'source' then
device_widget:buttons(gtable.join(
abutton({}, 1, function()
self:set_default_source(device)
end)
))
end
self:connect_signal('AC::device_changed', function(new_sink)
if device_widget.device == new_sink then
device_widget.bg = Theme_config.volume_controller.device_headphones_selected_bg
device_widget.fg = Theme_config.volume_controller.device_headphones_selected_fg
device_widget:get_children_by_id('icon')[1].image = gcolor.recolor_image(icondir .. 'volume-high.svg', Theme_config.volume_controller.device_headphones_selected_fg)
else
device_widget.bg = Theme_config.volume_controller.device_bg
device_widget.fg = fg
device_widget:get_children_by_id('icon')[1].image = gcolor.recolor_image(icondir .. 'volume-high.svg', icon_color)
end
end)
hover.bg_hover { widget = device_widget }
return device_widget
end
---Get all sink devices
---@param callback function returns a list of sinks
function audio_controller:get_sink_devices_async(callback)
-- This command gets all audio sources and their descriptions in this format: "source_name;source_description\n"
aspawn.easy_async_with_shell([=[
LC_ALL=C pactl list sinks | awk '/Name:/ { name=$0 } /Description:/ { sub(/Name: /, "", name); sub(/Description: /, "", $0); print name ";" $0 }'
]=], function(stdout)
local sinks = wibox.layout.fixed.vertical {}
for line in stdout:gmatch('[^\r\n]+') do
-- Call the callback function with the name and description
local s, n = line:match('(.-);(.+)')
table.insert(sinks, self:get_device_widget(s, n, 'sink'))
end
self.sinks = sinks
callback()
end)
end
---Get all source devices
---@param callback function returns a list of sources
function audio_controller:get_source_devices_async(callback)
-- This command gets all audio sources and their descriptions in this format: "source_name;source_description\n"
aspawn.easy_async_with_shell([=[
LC_ALL=C pactl list sources | awk '/Name:/ { name=$0 } /Description:/ { sub(/Name: /, "", name); sub(/Description: /, "", $0); print name ";" $0 }'
]=], function(stdout)
local sources = wibox.layout.fixed.vertical {}
for line in stdout:gmatch('[^\r\n]+') do
local s, n = line:match('(.-);(.+)')
table.insert(sources, self:get_device_widget(s, n, 'source'))
end
self.sources = sources
callback()
end)
end
---Creates a new audio controller
---@return wibox.widget auio_controller the audio controller widget
function audio_controller.new()
local w = base.make_widget_from_value(wibox.widget {
{
{
{ -- sink Device selector
{
{
resize = false,
image = gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color),
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
id = 'sink_dd_icon',
},
{
{
text = 'Output Devices',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
},
margins = dpi(5),
widget = wibox.container.margin,
},
layout = wibox.layout.fixed.horizontal,
},
id = 'sink_dd_shape',
bg = Theme_config.volume_controller.list_bg,
fg = Theme_config.volume_controller.list_headphones_fg,
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background,
},
{ -- sink dropdown
{
{
{
spacing = dpi(10),
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
step = dpi(50),
id = 'sink_list',
},
margins = dpi(10),
widget = wibox.container.margin,
},
border_color = Theme_config.volume_controller.list_border_color,
border_width = Theme_config.volume_controller.list_border_width,
id = 'sink_list_shape',
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background,
},
id = 'sink_height',
strategy = 'exact',
height = 0,
width = dpi(300),
widget = wibox.container.constraint,
},
{ -- Spacer
widget = wibox.container.background,
forced_height = dpi(10),
},
{ -- source Device selector
{
{
resize = false,
image = gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color),
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
id = 'source_dd_icon',
},
{
{
text = 'Input Devices',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
},
margins = dpi(5),
widget = wibox.container.margin,
},
layout = wibox.layout.fixed.horizontal,
},
id = 'source_dd_shape',
bg = Theme_config.volume_controller.list_bg,
fg = Theme_config.volume_controller.list_headphones_fg,
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background,
},
{ -- source dropdown
{
{
{
spacing = dpi(10),
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
step = dpi(50),
id = 'source_list',
},
margins = dpi(10),
widget = wibox.container.margin,
},
border_color = Theme_config.volume_controller.list_border_color,
border_width = Theme_config.volume_controller.list_border_width,
id = 'source_list_shape',
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background,
},
id = 'source_height',
strategy = 'exact',
height = 0,
width = dpi(300),
widget = wibox.container.constraint,
},
{ -- Spacer
widget = wibox.container.background,
forced_height = dpi(10),
},
{ -- sink volume slider
{
{
{
resize = true,
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icondir .. 'volume-high.svg', Theme_config.volume_controller.volume_fg),
id = 'sink_icon',
},
widget = wibox.container.constraint,
width = dpi(26),
height = dpi(26),
strategy = 'exact',
},
{
bar_shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(5))
end,
bar_height = dpi(5),
bar_color = Theme_config.volume_controller.border_color,
bar_active_color = Theme_config.volume_controller.volume_fg,
handle_color = Theme_config.volume_controller.volume_fg,
handle_shape = gshape.circle,
handle_border_color = Theme_config.volume_controller.volume_fg,
handle_width = dpi(15),
handle_cursor = 'left_ptr',
maximum = 100,
forced_height = 0, -- No idea why its needed but it makes the widget not go into infinity
value = 50,
widget = wibox.widget.slider,
id = 'sink_slider',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.constraint,
width = dpi(300),
height = dpi(26),
strategy = 'exact',
},
{ -- Spacer
widget = wibox.container.background,
forced_height = dpi(10),
},
{ -- source volume slider
{
{
{
resize = true,
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icondir .. 'microphone.svg', Theme_config.volume_controller.volume_fg),
id = 'source_icon',
},
widget = wibox.container.constraint,
width = dpi(26),
height = dpi(26),
strategy = 'exact',
},
{
bar_shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(5))
end,
bar_height = dpi(5),
bar_color = Theme_config.volume_controller.border_color,
bar_active_color = Theme_config.volume_controller.volume_fg,
handle_color = Theme_config.volume_controller.volume_fg,
handle_shape = gshape.circle,
handle_border_color = Theme_config.volume_controller.volume_fg,
handle_width = dpi(15),
handle_cursor = 'left_ptr',
maximum = 100,
forced_height = 0, -- No idea why its needed but it makes the widget not go into infinity
value = 50,
widget = wibox.widget.slider,
id = 'source_slider',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.constraint,
width = dpi(400),
height = dpi(26),
strategy = 'exact',
},
layout = wibox.layout.fixed.vertical,
},
margins = dpi(15),
widget = wibox.container.margin,
},
-- The parent margin doesn't render without an empty widget here???
widget = wibox.container.margin,
})
assert(w, 'Failed to create volume controller widget')
gtable.crush(w, audio_controller, true)
local sink_icon = w:get_children_by_id('sink_icon')[1]
local sink_slider = w:get_children_by_id('sink_slider')[1]
sink_slider:connect_signal('property::value', function(_, value)
audio_helper.set_sink_volume(value)
end)
-- Set the volume and icon
audio_helper:connect_signal('sink::get', function(_, muted, volume)
volume = tonumber(volume)
assert(type(muted) == 'boolean' and type(volume) == 'number', 'audio::get signal expects boolean and number')
if w.sink_volume == volume and w.sink_muted == muted then return end
w.sink_volume = volume
w.sink_muted = muted
if muted then
sink_icon:set_image(gcolor.recolor_image(icondir .. 'volume-mute.svg', Theme_config.volume_controller.volume_fg))
else
local icon = icondir .. 'volume'
if volume == 0 then
icon = icon .. '-mute'
elseif volume > 0 and volume < 34 then
icon = icon .. '-low'
elseif volume >= 34 and volume < 67 then
icon = icon .. '-medium'
elseif volume >= 67 then
icon = icon .. '-high'
end
sink_slider:set_value(volume)
sink_icon:set_image(gcolor.recolor_image(icon .. '.svg', Theme_config.volume_controller.volume_fg))
end
end)
local source_icon = w:get_children_by_id('source_icon')[1]
local source_slider = w:get_children_by_id('source_slider')[1]
-- Microphone slider change event
source_slider:connect_signal('property::value', function(_, value)
audio_helper.set_source_volume(value)
end)
--- Set the source volume and icon
audio_helper:connect_signal('source::get', function(_, muted, volume)
volume = tonumber(volume)
assert(type(muted) == 'boolean' and type(volume) == 'number', 'microphone::get signal expects boolean and number')
if w.source_volume == volume and w.source_muted == muted then return end
w.source_volume = volume
w.source_muted = muted
if muted then
source_icon:set_image(gcolor.recolor_image(icondir .. 'microphone-off.svg', Theme_config.volume_controller.microphone_fg))
else
if not volume then return end
source_slider:set_value(tonumber(volume))
if volume > 0 then
source_icon:set_image(gcolor.recolor_image(icondir .. 'microphone.svg', Theme_config.volume_controller.microphone_fg))
else
source_icon:set_image(gcolor.recolor_image(icondir .. 'microphone-off.svg', Theme_config.volume_controller.microphone_fg))
end
end
end)
local sink_dd_shape = w:get_children_by_id('sink_dd_shape')[1]
local sink_height = w:get_children_by_id('sink_height')[1]
local sink_dd_icon = w:get_children_by_id('sink_dd_icon')[1]
local rubato_timer = rubato.timed {
duration = 0.2,
pos = sink_height.height,
clamp_position = true,
subscribed = function(v)
sink_height.height = v
end,
}
sink_dd_shape:buttons(gtable.join {
abutton({}, 1, function()
if sink_height.height == 0 then
local size = dpi((#w.sinks * 44) + ((#w.sinks - 1) * 10) + 20)
if #w.sinks > 4 then
size = dpi(226)
end
rubato_timer.target = size
sink_dd_shape.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
sink_dd_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color))
else
rubato_timer.target = 0
sink_dd_shape.shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 4)
end
sink_dd_icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color))
end
end),
})
local source_dd_shape = w:get_children_by_id('source_dd_shape')[1]
local source_height = w:get_children_by_id('source_height')[1]
local source_dd_icon = w:get_children_by_id('source_dd_icon')[1]
local rubato_timer = rubato.timed {
duration = 0.2,
pos = source_height.height,
clamp_position = true,
subscribed = function(v)
source_height.height = v
end,
}
source_dd_shape:buttons(gtable.join {
abutton({}, 1, function()
if source_height.height == 0 then
local size = dpi(((#w.sources * 44) + ((#w.sources - 1) * 10) + 20))
if #w.sources > 4 then
size = dpi(226)
end
rubato_timer.target = size
source_dd_shape.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
source_dd_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color))
else
rubato_timer.target = 0
source_dd_shape.shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 4)
end
source_dd_icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.volume_controller.device_headphones_selected_icon_color))
end
end),
})
local sink_list = w:get_children_by_id('sink_list')[1]
w:get_sink_devices_async(function()
sink_list.children = w.sinks
end)
local source_list = w:get_children_by_id('source_list')[1]
w:get_source_devices_async(function()
source_list.children = w.sources
end)
hover.bg_hover { widget = sink_dd_shape }
hover.bg_hover { widget = source_dd_shape }
return w
end
return setmetatable(audio_controller, { __call = function() return audio_controller.new() end })

View File

@@ -1,553 +0,0 @@
-----------------------------------
-- This is the volume controller --
-----------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local gobject = require("gears.object")
local capi = {
awesome = awesome,
mousegrabber = mousegrabber,
}
local rubato = require("src.lib.rubato")
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
local volume_controler = { mt = {} }
function volume_controler.get_device_widget()
local device = wibox.widget {
{
{
{
id = "icon",
resize = false,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
},
spacing = dpi(10),
{
text = name,
id = "node",
widget = wibox.widget.textbox
},
id = "device_layout",
layout = wibox.layout.fixed.horizontal
},
id = "device_margin",
margins = dpi(9),
widget = wibox.container.margin
},
id = "background",
bg = Theme_config.volume_controller.device_bg,
border_color = Theme_config.volume_controller.device_border_color,
border_width = Theme_config.volume_controller.device_border_width,
shape = Theme_config.volume_controller.device_shape,
widget = wibox.container.background
}
if true then
device:connect_signal(
"button::press",
function(_, _, _, key)
if key == 1 then
if node then
--awful.spawn("./.config/awesome/src/scripts/vol.sh set_sink " .. node)
--capi.awesome.emit_signal("update::bg_sink", node)
end
end
end
)
--[[ capi.awesome.connect_signal(
"update::bg_sink",
function(new_node)
if node == new_node then
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
Theme_config.volume_controller.device_icon_color)
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
Hover_signal(device)
else
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
Theme_config.volume_controller.device_headphones_selected_icon_color)
device.bg = Theme_config.volume_controller.device_bg
device.fg = Theme_config.volume_controller.device_headphones_fg
Hover_signal(device)
end
end
) ]]
else
device:connect_signal(
"button::press",
function(_, _, _, key)
if key == 1 then
if node then
--awful.spawn("./.config/awesome/src/scripts/mic.sh set_source " .. node)
--capi.awesome.emit_signal("update::bg_source", node)
end
end
end
)
--[[ capi.awesome.connect_signal(
"update::bg_source",
function(new_node)
if node == new_node then
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
Theme_config.volume_controller.device_icon_color)
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
Hover_signal(device)
else
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
Theme_config.volume_controller.device_microphone_selected_icon_color)
device.bg = Theme_config.volume_controller.device_bg
device.fg = Theme_config.volume_controller.device_microphone_fg
Hover_signal(device)
end
end
) ]]
end
return device
end
-- Get all source devices
function volume_controler:get_source_devices()
end
-- Get all input devices
function volume_controler:get_input_devices()
end
function volume_controler:toggle()
volume_controler.popup.visible = not volume_controler.popup.visible
end
function volume_controler.run(args)
args = args or {}
local ret = gobject {}
local w = wibox.widget {
{
{
-- Audio Device selector
{
{
{
{
{
resize = false,
image = gears.color.recolor_image(icondir .. "menu-down.svg",
Theme_config.volume_controller.device_headphones_selected_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "icon"
},
id = "center",
halign = "center",
valign = "center",
widget = wibox.container.place,
},
{
{
text = "Output Device",
widget = wibox.widget.textbox,
id = "device_name"
},
margins = dpi(5),
widget = wibox.container.margin
},
id = "audio_volume",
layout = wibox.layout.fixed.horizontal
},
id = "audio_bg",
bg = Theme_config.volume_controller.list_bg,
fg = Theme_config.volume_controller.list_headphones_fg,
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background
},
id = "audio_selector_margin",
left = dpi(10),
right = dpi(10),
top = dpi(10),
widget = wibox.container.margin
},
{
id = "volume_list",
widget = {
{
{
{
{
spacing = dpi(10),
layout = require("src.lib.overflow_widget.overflow").vertical,
scrollbar_width = 0,
step = dpi(50),
id = "volume_device_list",
},
id = "margin",
margins = dpi(10),
widget = wibox.container.margin
},
id = "place",
height = dpi(200),
strategy = "max",
widget = wibox.container.constraint
},
border_color = Theme_config.volume_controller.list_border_color,
border_width = Theme_config.volume_controller.list_border_width,
id = "volume_device_background",
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background
},
left = dpi(10),
right = dpi(10),
widget = wibox.container.margin
},
forced_height = 0
},
-- Microphone selector
{
{
{
{
{
resize = false,
image = gears.color.recolor_image(icondir .. "menu-down.svg",
Theme_config.volume_controller.device_microphone_selected_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "icon",
},
id = "center",
halign = "center",
valign = "center",
widget = wibox.container.place,
},
{
{
text = "Input Device",
widget = wibox.widget.textbox,
id = "device_name"
},
margins = dpi(5),
widget = wibox.container.margin
},
id = "mic_volume",
layout = wibox.layout.fixed.horizontal
},
id = "mic_bg",
bg = Theme_config.volume_controller.list_bg,
fg = Theme_config.volume_controller.list_microphone_fg,
shape = Theme_config.volume_controller.selector_shape,
widget = wibox.container.background
},
id = "mic_selector_margin",
left = dpi(10),
right = dpi(10),
top = dpi(10),
widget = wibox.container.margin
},
{
id = "mic_list",
widget = {
{
{
{
{
spacing = dpi(10),
layout = require("src.lib.overflow_widget.overflow").vertical,
id = "volume_device_list",
scrollbar_width = 0,
step = dpi(50),
},
id = "margin",
margins = dpi(10),
widget = wibox.container.margin
},
id = "place",
height = dpi(200),
strategy = "max",
widget = wibox.container.constraint
},
id = "volume_device_background",
border_color = Theme_config.volume_controller.list_border_color,
border_width = Theme_config.volume_controller.list_border_width,
shape = Theme_config.volume_controller.list_shape,
widget = wibox.container.background
},
left = dpi(10),
right = dpi(10),
widget = wibox.container.margin
},
forced_height = 0
},
-- Audio volume slider
{
{
{
resize = false,
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_controller.volume_fg),
id = "icon",
},
{
{
bar_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(5))
end,
bar_height = dpi(5),
bar_color = Theme_config.volume_controller.border_color,
bar_active_color = Theme_config.volume_controller.volume_fg,
handle_color = Theme_config.volume_controller.volume_fg,
handle_shape = gears.shape.circle,
handle_border_color = Theme_config.volume_controller.volume_fg,
handle_width = dpi(12),
maximum = 100,
forced_height = dpi(26),
widget = wibox.widget.slider,
id = "slider"
},
left = dpi(5),
id = "slider_margin",
widget = wibox.container.margin
},
id = "audio_volume",
layout = wibox.layout.align.horizontal
},
id = "audio_volume_margin",
top = dpi(10),
left = dpi(10),
right = dpi(10),
widget = wibox.container.margin
},
-- Microphone volume slider
{
{
{
resize = false,
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "microphone.svg", Theme_config.volume_controller.microphone_fg),
id = "icon"
},
{
{
bar_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(5))
end,
bar_height = dpi(5),
bar_color = Theme_config.volume_controller.device_border_color,
bar_active_color = Theme_config.volume_controller.microphone_fg,
handle_color = Theme_config.volume_controller.microphone_fg,
handle_shape = gears.shape.circle,
handle_border_color = Theme_config.volume_controller.microphone_fg,
handle_width = dpi(12),
maximum = 100,
forced_height = dpi(26),
widget = wibox.widget.slider,
id = "slider"
},
left = dpi(5),
id = "slider_margin",
widget = wibox.container.margin
},
id = "mic_volume",
layout = wibox.layout.align.horizontal
},
id = "mic_volume_margin",
left = dpi(10),
right = dpi(10),
top = dpi(10),
widget = wibox.container.margin
},
id = "controller_layout",
layout = wibox.layout.fixed.vertical
},
id = "controller_margin",
margins = dpi(10),
widget = wibox.container.margin
},
bg = Theme_config.volume_controller.bg,
border_color = Theme_config.volume_controller.border_color,
border_width = Theme_config.volume_controller.border_width,
shape = Theme_config.volume_controller.shape,
forced_width = dpi(400),
widget = wibox.container.background
}
ret.widget = w
ret.audio_dropdown = w:get_children_by_id("audio_list")[1]
ret.mic_dropdown = w:get_children_by_id("mic_list")[1]
ret.audio_slider = w:get_children_by_id("slider")[1]
ret.mic_slider = w:get_children_by_id("slider")[1]
-- Main container
ret.popup = awful.popup {
widget = w,
ontop = true,
bg = Theme_config.volume_controller.bg,
stretch = false,
visible = false,
screen = args.screen,
--! Calculate the popup position instead of hardcoding it
placement = function(c) awful.placement.align(c,
{ position = "top_right", margins = { right = dpi(305), top = dpi(60) } })
end,
shape = Theme_config.volume_controller.shape,
}
-- Set the volume and icon
capi.awesome.connect_signal(
"audio::get",
function(muted, volume)
if muted then
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
.recolor_image(icondir .. "volume-mute.svg", Theme_config.volume_controller.volume_fg))
else
volume = tonumber(volume)
if not volume then
return
end
local icon = icondir .. "volume"
if volume < 1 then
icon = icon .. "-mute"
elseif volume >= 1 and volume < 34 then
icon = icon .. "-low"
elseif volume >= 34 and volume < 67 then
icon = icon .. "-medium"
elseif volume >= 67 then
icon = icon .. "-high"
end
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.slider_margin.slider:
set_value(volume)
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
.recolor_image(icon
.. ".svg", Theme_config.volume_controller.volume_fg))
end
end
)
-- Get microphone volume
capi.awesome.connect_signal(
"microphone::get",
function(muted, volume)
if muted then
--volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(0))
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
else
volume = tonumber(volume)
if not volume then
return
end
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(volume))
if volume > 0 then
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
.. "microphone.svg", Theme_config.volume_controller.microphone_fg))
else
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
end
end
end
)
-- Microphone slider change event
ret.widget:connect_signal(
"property::value",
function()
end
)
-- Slide animation
ret.audio_dropdown:connect_signal(
"button::press",
function(_, _, _, key)
if key == 1 then
local rubato_timer = rubato.timed {
duration = 0.4,
intro = 0.1,
outro = 0.1,
pos = mic_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
mic_list.forced_height = v
end
}
if mic_list.forced_height == 0 then
rubato_timer.target = dpi(200)
mic_selector_margin.mic_bg.shape = function(cr, width, height)
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
Theme_config.volume_controller.device_microphone_selected_icon_color))
else
rubato_timer.target = 0
mic_bg.shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(4))
end
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
Theme_config.volume_controller.device_microphone_selected_icon_color))
end
end
end
)
-- Slide animation
ret.mic_dropdown:connect_signal(
"button::press",
function(_, _, _, key)
if key == 1 then
local rubato_timer = rubato.timed {
duration = 0.4,
intro = 0.1,
outro = 0.1,
pos = volume_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
volume_list.forced_height = v
end
}
if volume_list.forced_height == 0 then
rubato_timer.target = dpi(200)
audio_bg.shape = function(cr, width, height)
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
Theme_config.volume_controller.device_headphones_selected_icon_color))
else
rubato_timer.target = 0
audio_bg.shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(4))
end
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
Theme_config.volume_controller.device_headphones_selected_icon_color))
end
end
end
)
return ret
end
function volume_controler.mt:__call(...)
return volume_controler.run(...)
end
return setmetatable(volume_controler, volume_controler.mt)

View File

@@ -3,151 +3,136 @@
-----------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local gobject = require("gears.object")
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local gtimer = require('gears.timer')
local wibox = require('wibox')
local capi = {
awesome = awesome,
mouse = mouse,
}
local audio_helper = require('src.tools.helpers.audio')
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/audio/'
local osd = { mt = {} }
local osd = {}
function osd:run()
self.visible = true
if self.timer.started then
self.timer:again()
else
self.timer:start()
end
end
function osd.new(args)
args = args or {}
args.screen = args.screen or 1
local ret = gobject {}
ret.w = wibox.widget {
local w = apopup {
widget = {
{
{
{ -- Volume Icon
image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_osd.icon_color),
valign = "center",
halign = "center",
resize = false,
id = "icon",
widget = wibox.widget.imagebox
{
image = gcolor.recolor_image(icondir .. 'volume-off.svg', Theme_config.volume_osd.icon_color),
valign = 'center',
halign = 'center',
resize = true,
id = 'icon_role',
widget = wibox.widget.imagebox,
},
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
{ -- Volume Bar
{
{
id = "progressbar1",
id = 'progressbar',
color = Theme_config.volume_osd.bar_bg_active,
background_color = Theme_config.volume_osd.bar_bg,
max_value = 100,
value = 50,
forced_height = dpi(6),
shape = function(cr, width, heigth)
gears.shape.rounded_bar(cr, width, heigth, dpi(6))
end,
widget = wibox.widget.progressbar
value = 0,
shape = gshape.rounded_rect,
widget = wibox.widget.progressbar,
},
id = "progressbar_container2",
halign = "center",
valign = "center",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(250),
height = dpi(5),
},
id = "progressbar_container",
width = dpi(240),
heigth = dpi(20),
stragety = "max",
widget = wibox.container.constraint
widget = wibox.container.place,
},
{ -- Volume text
widget = wibox.widget.textbox,
id = 'text_role',
text = '0',
valign = 'center',
halign = 'center',
},
id = "layout1",
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
id = "margin",
margins = dpi(10),
widget = wibox.container.margin
left = dpi(10),
right = dpi(10),
top = dpi(20),
bottom = dpi(20),
widget = wibox.container.margin,
},
forced_width = dpi(300),
forced_height = dpi(80),
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
end,
shape = Theme_config.volume_osd.shape,
widget = wibox.container.background,
},
ontop = true,
stretch = false,
visible = false,
border_color = Theme_config.volume_osd.border_color,
border_width = Theme_config.volume_osd.border_width,
fg = Theme_config.volume_osd.fg,
bg = Theme_config.volume_osd.bg,
widget = wibox.container.background
screen = 1,
placement = function(c) aplacement.bottom(c, { margins = dpi(20) }) end,
}
local volume_container = awful.popup {
widget = ret.w,
ontop = true,
stretch = false,
visible = false,
screen = args.screen,
placement = function(c) awful.placement.bottom_left(c, { margins = dpi(20) }) end,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(14))
end
}
gtable.crush(w, osd)
local hide_volume_osd = gears.timer {
w.timer = gtimer {
timeout = 2,
autostart = true,
callback = function()
volume_container.visible = false
end
w.visible = false
end,
}
capi.awesome.connect_signal(
"audio::get",
function(muted, volume)
audio_helper:connect_signal('output::get', function(_, muted, volume)
volume = tonumber(volume or 0)
if muted then
ret.w:get_children_by_id("icon")[1]
:set_image(gears.color.recolor_image(
icondir .. "volume-mute" .. ".svg", Theme_config.volume_osd.icon_color))
ret.w:get_children_by_id("progressbar1")[1].value = tonumber(0)
w.widget:get_children_by_id('icon_role')[1]:set_image(gcolor.recolor_image(icondir .. 'volume-mute' .. '.svg', Theme_config.volume_osd.icon_color))
w.widget:get_children_by_id('progressbar')[1].value = 0
else
volume = tonumber(volume)
if not volume then
return
end
ret.w:get_children_by_id("progressbar1")[1].value = tonumber(volume)
local icon = icondir .. "volume"
w.widget:get_children_by_id('progressbar')[1].value = volume
local icon = icondir .. 'volume'
if volume < 1 then
icon = icon .. "-mute"
icon = icon .. '-mute'
elseif volume >= 1 and volume < 34 then
icon = icon .. "-low"
icon = icon .. '-low'
elseif volume >= 34 and volume < 67 then
icon = icon .. "-medium"
icon = icon .. '-medium'
elseif volume >= 67 then
icon = icon .. "-high"
end
ret.w:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg",
Theme_config.volume_osd.icon_color))
end
end
)
capi.awesome.connect_signal(
"widget::volume_osd:rerun",
function()
if capi.mouse.screen == args.screen then
volume_container.visible = true
if hide_volume_osd.started then
hide_volume_osd:again()
else
hide_volume_osd:start()
end
end
end
)
icon = icon .. '-high'
end
function osd.mt:__call(...)
return osd.new(...)
w.widget:get_children_by_id('icon_role')[1]:set_image(gcolor.recolor_image(icon .. '.svg', Theme_config.volume_osd.icon_color))
w.widget:get_children_by_id('text_role')[1].text = volume
end
w:run()
end)
return w
end
return setmetatable(osd, osd.mt)
return setmetatable(osd, { __call = function(_, ...) return osd.new(...) end })

View File

@@ -3,23 +3,24 @@
--------------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local awidget = require("awful.widget")
local base = require("wibox.widget.base")
local dpi = require("beautiful").xresources.apply_dpi
local gcolor = require("gears").color
local gfilesystem = require("gears").filesystem
local gtable = require("gears").table
local lgi = require("lgi")
local wibox = require("wibox")
local abutton = require('awful.button')
local awidget = require('awful.widget')
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears').color
local gfilesystem = require('gears').filesystem
local gtable = require('gears').table
local lgi = require('lgi')
local wibox = require('wibox')
-- Own libs
local context_menu = require("src.modules.context_menu")
local context_menu = require('src.modules.context_menu.init')
local hover = require('src.tools.hover')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/bluetooth/'
local capi = {
awesome = awesome
awesome = awesome,
}
local device = { mt = {} }
@@ -33,7 +34,7 @@ function device:layout(_, width, height)
end
function device:fit(context, width, height)
local w, h = 0, 0
local w, h = 0, 0 ---@type number|nil, number|nil
if self._private.widget then
w, h = base.fit_widget(self, context, self._private.widget, width, height)
end
@@ -48,29 +49,14 @@ end
--#endregion
local dbus_proxy = require('dbus_proxy')
--- Connect to a device if not connected else disconnect
function device:toggle_connect()
if not self.device.Paired then
self:toggle_pair()
return
end
if not self.device.Connected then
--TODO: Implement device passcode support, I have no idea how to get the
--TODO: Methods from Agent1 implemented
--[[ self._private.AgentManager1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
path = "/org/bluez",
interface = "org.bluez.AgentManager1"
}
self._private.Agent1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
path = "/org/bluez",
interface = "org.bluez.Agent1",
}
self._private.AgentManager1:RegisterAgent(self._private.Agent1.object_path, "")
self._private.AgentManager1:RequestDefaultAgent(self._private.Agent1.object_path) ]]
self.device:ConnectAsync()
else
self.device:DisconnectAsync()
@@ -79,37 +65,52 @@ end
--- Pair to a device if not paired else unpair
function device:toggle_pair()
if self.device.Paired then
if not self.device.Paired then
self._private.AgentManager1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = 'org.bluez',
path = '/org/bluez',
interface = 'org.bluez.AgentManager1',
}
self._private.Agent1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = 'org.bluez',
path = '/org/bluez',
interface = 'org.bluez.Agent1',
}
self._private.AgentManager1:RegisterAgent(self._private.Agent1.object_path, 'KeyboardDisplay')
self.device:PairAsync()
else
self.device:CancelPairingAsync()
--Remove via adapter
end
end
--- Trust a device if not trusted else untrust
function device:toggle_trusted()
self.device:Set("org.bluez.Device1", "Trusted", lgi.GLib.Variant("b", not self.device.Trusted))
self.device.Trusted = { signature = "b", value = not self.device.Trusted }
self.device:Set('org.bluez.Device1', 'Trusted', lgi.GLib.Variant('b', not self.device.Trusted))
self.device.Trusted = { signature = 'b', value = not self.device.Trusted }
end
---Rename a device alias
---@param newname string New name, if empty the device name will be reset
---@return string name The new or old name depending if the string was empty or not
function device:rename(newname)
self.device:Set("org.bluez.Device1", "Alias", lgi.GLib.Variant("s", newname))
self.device.Alias = { signature = "s", value = newname }
return self.device:Get("org.bluez.Device1", "Alias")
self.device:Set('org.bluez.Device1', 'Alias', lgi.GLib.Variant('s', newname))
self.device.Alias = { signature = 's', value = newname }
return self.device:Get('org.bluez.Device1', 'Alias')
end
function device.new(args)
args = args or {}
local icon = device.Icon or "bluetooth-on"
local icon = device.Icon or 'bluetooth-on'
local inputbox = awidget.inputbox {
text = args.device.Alias or args.device.Name,
halign = "left",
valign = "center",
halign = 'left',
valign = 'center',
}
local ret = base.make_widget_from_value(wibox.widget {
@@ -119,78 +120,80 @@ function device.new(args)
{
{
image = gcolor.recolor_image(
icondir .. icon .. ".svg", Theme_config.bluetooth_controller.icon_color),
icondir .. icon .. '.svg', Theme_config.bluetooth_controller.icon_color),
resize = false,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
strategy = "exact",
strategy = 'exact',
width = dpi(24),
height = dpi(24),
widget = wibox.container.constraint
widget = wibox.container.constraint,
},
{
inputbox,
widget = wibox.container.constraint,
strategy = "exact",
strategy = 'exact',
width = dpi(300),
id = "const"
id = 'const',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
{ -- Spacing
forced_width = dpi(10),
widget = wibox.container.background
widget = wibox.container.background,
},
{
{
{
{
{
id = "con",
id = 'con',
resize = false,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
strategy = "exact",
strategy = 'exact',
width = dpi(24),
height = dpi(24),
widget = wibox.container.constraint
widget = wibox.container.constraint,
},
margins = dpi(2),
widget = wibox.container.margin
widget = wibox.container.margin,
},
shape = Theme_config.bluetooth_controller.icon_shape,
bg = Theme_config.bluetooth_controller.con_button_color,
widget = wibox.container.background
widget = wibox.container.background,
},
margin = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.bluetooth_controller.device_bg,
fg = Theme_config.bluetooth_controller.device_fg,
border_color = Theme_config.bluetooth_controller.device_border_color,
border_width = Theme_config.bluetooth_controller.device_border_width,
id = "background",
id = 'background',
shape = Theme_config.bluetooth_controller.device_shape,
widget = wibox.container.background
widget = wibox.container.background,
})
assert(ret, 'Failed to create widget')
gtable.crush(ret, device, true)
ret.device = args.device or {}
-- Set the image of the connection button depending on the connection state
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(ret.device.Connected and icondir .. "link.svg" or
icondir .. "link-off.svg",
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(ret.device.Connected and icondir .. 'link.svg' or
icondir .. 'link-off.svg',
Theme_config.bluetooth_controller.icon_color_dark)
local cm = context_menu {
@@ -201,78 +204,82 @@ function device.new(args)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
}, spacing = dpi(10),
entries = {
{ -- Connect/Disconnect a device
name = ret.device.Connected and "Disconnect" or "Connect",
icon = gcolor.recolor_image(ret.device.Connected and icondir .. "bluetooth-off.svg" or
icondir .. "bluetooth-on.svg",
name = ret.device.Connected and 'Disconnect' or 'Connect',
icon = gcolor.recolor_image(ret.device.Connected and icondir .. 'bluetooth-off.svg' or
icondir .. 'bluetooth-on.svg',
Theme_config.bluetooth_controller.icon_color),
callback = function()
ret:toggle_connect()
end,
id = "connected"
id = 'connected',
},
{ -- Pair/Unpair a device
name = "Pair",
icon = gcolor.recolor_image(ret.device.Paired and icondir .. "link-off.svg" or
icondir .. "link.svg",
name = 'Pair',
icon = gcolor.recolor_image(ret.device.Paired and icondir .. 'link-off.svg' or
icondir .. 'link.svg',
Theme_config.bluetooth_controller.icon_color),
callback = function()
ret:toggle_pair()
end
end,
},
{ -- Trust/Untrust a device
name = ret.device.Trusted and "Untrust" or "Trust",
icon = gcolor.recolor_image(ret.device.Trusted and icondir .. "untrusted.svg" or icondir .. "trusted.svg",
name = ret.device.Trusted and 'Untrust' or 'Trust',
icon = gcolor.recolor_image(ret.device.Trusted and icondir .. 'untrusted.svg' or icondir .. 'trusted.svg',
Theme_config.bluetooth_controller.icon_color),
callback = function()
ret:toggle_trusted()
end,
id = "trusted"
id = 'trusted',
},
{ -- Rename a device
name = "Rename",
icon = gcolor.recolor_image(icondir .. "edit.svg", Theme_config.bluetooth_controller.icon_color),
name = 'Rename',
icon = gcolor.recolor_image(icondir .. 'edit.svg', Theme_config.bluetooth_controller.icon_color),
callback = function()
inputbox:focus()
inputbox:connect_signal("submit", function(text)
inputbox:connect_signal('submit', function(text)
text = text:get_text()
inputbox.markup = ret:rename(text)
end)
end
end,
},
{ -- Remove a device
name = "Remove",
icon = gcolor.recolor_image(icondir .. "delete.svg", Theme_config.bluetooth_controller.icon_color),
name = 'Remove',
icon = gcolor.recolor_image(icondir .. 'delete.svg', Theme_config.bluetooth_controller.icon_color),
callback = function()
args.remove_callback(ret.device)
end
}
}
end,
},
},
}
cm:connect_signal('mouse::leave', function()
cm.visible = false
end)
ret:buttons(gtable.join(
abutton({}, 1, function()
-- Toggle the connection state
@@ -281,19 +288,19 @@ function device.new(args)
abutton({}, 3, function()
-- Show the context menu and update its entrie names
for _, value in ipairs(cm.widget.children) do
value.id = value.id or ""
if value.id:match("connected") then
value:get_children_by_id("text_role")[1].text = ret.device.Connected and "Disconnect" or "Connect"
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Connected and
icondir .. "bluetooth-off.svg" or icondir .. "bluetooth-on.svg",
value.id = value.id or ''
if value.id:match('connected') then
value:get_children_by_id('text_role')[1].text = ret.device.Connected and 'Disconnect' or 'Connect'
value:get_children_by_id('icon_role')[1].image = gcolor.recolor_image(ret.device.Connected and
icondir .. 'bluetooth-off.svg' or icondir .. 'bluetooth-on.svg',
Theme_config.bluetooth_controller.icon_color)
elseif value.id:match("trusted") then
value:get_children_by_id("text_role")[1].text = ret.device.Trusted and "Untrust" or "Trust"
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Trusted and
icondir .. "untrusted.svg" or icondir .. "trusted.svg", Theme_config.bluetooth_controller.icon_color)
elseif value.id:match("paired") then
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Paired and
icondir .. "link-off.svg" or icondir .. "link.svg", Theme_config.bluetooth_controller.icon_color)
elseif value.id:match('trusted') then
value:get_children_by_id('text_role')[1].text = ret.device.Trusted and 'Untrust' or 'Trust'
value:get_children_by_id('icon_role')[1].image = gcolor.recolor_image(ret.device.Trusted and
icondir .. 'untrusted.svg' or icondir .. 'trusted.svg', Theme_config.bluetooth_controller.icon_color)
elseif value.id:match('paired') then
value:get_children_by_id('icon_role')[1].image = gcolor.recolor_image(ret.device.Paired and
icondir .. 'link-off.svg' or icondir .. 'link.svg', Theme_config.bluetooth_controller.icon_color)
end
end
cm:toggle()
@@ -301,13 +308,13 @@ function device.new(args)
))
-- Update the updated device icon
capi.awesome.connect_signal(ret.device.object_path .. "_updated", function(d)
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(d.Connected and icondir .. "link.svg" or
icondir .. "link-off.svg",
capi.awesome.connect_signal(ret.device.object_path .. '_updated', function(d)
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(d.Connected and icondir .. 'link.svg' or
icondir .. 'link-off.svg',
Theme_config.bluetooth_controller.icon_color_dark)
end)
Hover_signal(ret)
hover.bg_hover { widget = ret }
return ret
end

View File

@@ -3,28 +3,29 @@
--------------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local aspawn = require("awful.spawn")
local base = require("wibox.widget.base")
local dbus_proxy = require("src.lib.lua-dbus_proxy.src.dbus_proxy")
local dpi = require("beautiful").xresources.apply_dpi
local gcolor = require("gears").color
local gfilesystem = require("gears").filesystem
local gshape = require("gears").shape
local gtable = require("gears").table
local gtimer = require("gears.timer")
local lgi = require("lgi")
local naughty = require("naughty")
local wibox = require("wibox")
local abutton = require('awful.button')
local aspawn = require('awful.spawn')
local base = require('wibox.widget.base')
local dbus_proxy = require('src.lib.lua-dbus_proxy.src.dbus_proxy')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears').color
local gfilesystem = require('gears').filesystem
local gshape = require('gears').shape
local gtable = require('gears').table
local gtimer = require('gears.timer')
local lgi = require('lgi')
local naughty = require('naughty')
local wibox = require('wibox')
-- Third party libs
local rubato = require("src.lib.rubato")
local rubato = require('src.lib.rubato')
local hover = require('src.tools.hover')
-- Own libs
local bt_device = require("src.modules.bluetooth.device")
local dnd_widget = require("awful.widget.toggle_widget")
local bt_device = require('src.modules.bluetooth.device')
local dnd_widget = require('awful.widget.toggle_widget')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/bluetooth/'
local capi = {
awesome = awesome,
@@ -61,13 +62,13 @@ end
---Get the list of paired devices
---@return table devices table of paired devices
function bluetooth:get_paired_devices()
return self:get_children_by_id("connected_device_list")[1].children
return self:get_children_by_id('connected_device_list')[1].children
end
---Get the list of discovered devices
---@return table devices table of discovered devices
function bluetooth:get_discovered_devices()
return self:get_children_by_id("discovered_device_list")[1].children
return self:get_children_by_id('discovered_device_list')[1].children
end
--- Remove a device by first disconnecting it async then removing it
@@ -81,8 +82,8 @@ end
function bluetooth:add_device(device, object_path)
-- Get a reference to both lists
local plist = self:get_children_by_id("connected_device_list")[1]
local dlist = self:get_children_by_id("discovered_device_list")[1]
local plist = self:get_children_by_id('connected_device_list')[1]
local dlist = self:get_children_by_id('discovered_device_list')[1]
-- For the first list check if the device already exists and if its connection state changed
-- if it changed then remove it from the current list and put it into the other one
@@ -117,6 +118,7 @@ function bluetooth:add_device(device, object_path)
self:remove_device_information(device)
end,
})
self:emit_signal('device::added_connected')
else
dlist:add(bt_device {
device = device,
@@ -125,22 +127,25 @@ function bluetooth:add_device(device, object_path)
self:remove_device_information(device)
end,
})
self:emit_signal('device::added_discovered')
end
end
---Remove a device from any list
---@param object_path string the object path of the device
function bluetooth:remove_device(object_path)
local plist = self:get_children_by_id("connected_device_list")[1]
local dlist = self:get_children_by_id("discovered_device_list")[1]
local plist = self:get_children_by_id('connected_device_list')[1]
local dlist = self:get_children_by_id('discovered_device_list')[1]
for _, d in ipairs(dlist.children) do
if d.device.object_path == object_path then
dlist:remove_widgets(d)
self:emit_signal('device::removed_discovered')
end
end
for _, d in ipairs(plist.children) do
if d.device.object_path == object_path then
if d.device.object_path == object_path and (not d.device.Paired) then
plist:remove_widgets(d)
self:emit_signal('device::removed_connected')
end
end
end
@@ -159,42 +164,42 @@ end
function bluetooth:toggle()
local powered = self._private.Adapter1.Powered
self._private.Adapter1:Set("org.bluez.Adapter1", "Powered", lgi.GLib.Variant("b", not powered))
self._private.Adapter1:Set('org.bluez.Adapter1', 'Powered', lgi.GLib.Variant('b', not powered))
self._private.Adapter1.Powered = {
signature = "b",
value = not powered
signature = 'b',
value = not powered,
}
end
--- Open blueman-manager
function bluetooth:open_settings()
aspawn("blueman-manager")
aspawn('blueman-manager')
end
---Get a new device proxy and connect a PropertyChanged signal to it and
---add the device to the list
---@param object_path string the object path of the device
function bluetooth:get_device_info(object_path)
if (not object_path) or (not object_path:match("/org/bluez/hci0/dev")) then return end
if (not object_path) or (not object_path:match('/org/bluez/hci0/dev')) then return end
-- New Device1 proxy
local Device1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
interface = "org.bluez.Device1",
path = object_path
name = 'org.bluez',
interface = 'org.bluez.Device1',
path = object_path,
}
-- New Properties proxy for the object_path
local Device1Properties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
interface = "org.freedesktop.DBus.Properties",
path = object_path
name = 'org.bluez',
interface = 'org.freedesktop.DBus.Properties',
path = object_path,
}
-- Just return if the Device1 has no name, this usually means random devices with just a mac address
if (not Device1.Name) or (Device1.Name == "") then return end
if (not Device1.Name) or (Device1.Name == '') then return end
-- For some reason it notifies twice or thrice
local just_notified = false
@@ -205,29 +210,29 @@ function bluetooth:get_device_info(object_path)
single_shot = true,
callback = function()
just_notified = false
end
end,
}
-- Connect the PropertyChanged signal to update the device when a property changes and send a notification
Device1Properties:connect_signal(function(_, _, changed_props)
if changed_props["Connected"] ~= nil then
if changed_props['Connected'] ~= nil then
if not just_notified then
naughty.notification({
app_icon = icondir .. "bluetooth-on.svg",
app_name = "Bluetooth",
naughty.notification {
app_icon = icondir .. 'bluetooth-on.svg',
app_name = 'Bluetooth',
title = Device1.Name,
icon = gcolor.recolor_image(icondir .. Device1.Icon .. ".svg", Theme_config.bluetooth_controller.icon_color),
icon = icondir .. Device1.Icon .. '.svg',
timeout = 5,
message = "Device " ..
Device1.Name .. " is now " .. (changed_props["Connected"] and "connected" or "disconnected"),
category = Device1.Connected and "device.added" or "device.removed",
})
message = 'Device ' ..
Device1.Name .. ' is now ' .. (changed_props['Connected'] and 'connected' or 'disconnected'),
category = Device1.Connected and 'device.added' or 'device.removed',
}
just_notified = true
notify_timer:start()
end
end
capi.awesome.emit_signal(object_path .. "_updated", Device1)
end, "PropertiesChanged")
capi.awesome.emit_signal(object_path .. '_updated', Device1)
end, 'PropertiesChanged')
self:add_device(Device1, object_path)
end
@@ -236,13 +241,12 @@ end
---@param powered boolean the powered state of the adapter
local function send_state_notification(powered)
naughty.notification {
app_icon = gcolor.recolor_image(icondir .. "bluetooth-on.svg", Theme_config.bluetooth_controller.icon_color),
app_name = "Bluetooth",
title = "Bluetooth",
message = powered and "Enabled" or "Disabled",
icon = gcolor.recolor_image(powered and icondir .. "bluetooth-on.svg" or icondir .. "bluetooth-off.svg",
Theme_config.bluetooth_controller.icon_color),
category = powered and "device.added" or "device.removed",
app_icon = icondir .. 'bluetooth-on.svg',
app_name = 'Bluetooth',
title = 'Bluetooth',
message = powered and 'Enabled' or 'Disabled',
icon = powered and icondir .. 'bluetooth-on.svg' or icondir .. 'bluetooth-off.svg',
category = powered and 'device.added' or 'device.removed',
}
end
@@ -250,7 +254,7 @@ function bluetooth.new(args)
args = args or {}
-- For some reason the first widget isn't read so the first container is a duplicate
local ret = base.make_widget_from_value({
local ret = base.make_widget_from_value {
{
{
{
@@ -258,128 +262,132 @@ function bluetooth.new(args)
{
{
resize = false,
image = gcolor.recolor_image(icondir .. "menu-down.svg",
image = gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.bluetooth_controller.connected_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "connected_icon"
valign = 'center',
halign = 'center',
id = 'connected_icon',
},
{
{
text = "Paired Devices",
valign = "center",
halign = "center",
text = 'Paired Devices',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
bg = Theme_config.bluetooth_controller.connected_bg,
fg = Theme_config.bluetooth_controller.connected_fg,
shape = Theme_config.bluetooth_controller.connected_shape,
widget = wibox.container.background,
id = "connected_bg"
id = 'connected_bg',
},
id = "connected_margin",
widget = wibox.container.margin
id = 'connected_margin',
widget = wibox.container.margin,
},
{
{
{
{
step = dpi(50),
spacing = dpi(10),
layout = require("src.lib.overflow_widget.overflow").vertical,
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
id = "connected_device_list"
id = 'connected_device_list',
},
id = "margin",
id = 'margin',
margins = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
},
border_color = Theme_config.bluetooth_controller.con_device_border_color,
border_width = Theme_config.bluetooth_controller.con_device_border_width,
shape = Theme_config.bluetooth_controller.con_device_shape,
widget = wibox.container.background,
forced_height = 0,
id = "connected_list",
},
widget = wibox.container.constraint,
strategy = 'exact',
height = 0,
id = 'connected_list',
},
{
{
{
{
resize = false,
image = gcolor.recolor_image(icondir .. "menu-down.svg",
image = gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.bluetooth_controller.discovered_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "discovered_icon",
valign = 'center',
halign = 'center',
id = 'discovered_icon',
},
{
{
text = "Nearby Devices",
valign = "center",
halign = "center",
text = 'Nearby Devices',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
id = "discovered_bg",
id = 'discovered_bg',
bg = Theme_config.bluetooth_controller.discovered_bg,
fg = Theme_config.bluetooth_controller.discovered_fg,
shape = Theme_config.bluetooth_controller.discovered_shape,
widget = wibox.container.background
widget = wibox.container.background,
},
id = "discovered_margin",
id = 'discovered_margin',
top = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
},
{
{
{
id = "discovered_device_list",
id = 'discovered_device_list',
spacing = dpi(10),
step = dpi(50),
layout = require("src.lib.overflow_widget.overflow").vertical,
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
},
margins = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
},
border_color = Theme_config.bluetooth_controller.con_device_border_color,
border_width = Theme_config.bluetooth_controller.con_device_border_width,
shape = Theme_config.bluetooth_controller.con_device_shape,
widget = wibox.container.background,
forced_height = 0,
id = "discovered_list",
id = 'discovered_list',
},
{
{ -- action buttons
{
dnd_widget {
color = Theme_config.bluetooth_controller.power_bg,
size = dpi(40)
size = dpi(40),
},
id = "dnd",
id = 'dnd',
widget = wibox.container.place,
valign = "center",
halign = "center"
valign = 'center',
halign = 'center',
},
nil,
{ -- refresh
{
{
image = gcolor.recolor_image(icondir .. "refresh.svg",
image = gcolor.recolor_image(icondir .. 'refresh.svg',
Theme_config.bluetooth_controller.refresh_icon_color),
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
widget = wibox.container.margin,
@@ -387,28 +395,30 @@ function bluetooth.new(args)
},
shape = Theme_config.bluetooth_controller.refresh_shape,
bg = Theme_config.bluetooth_controller.refresh_bg,
id = "scan",
widget = wibox.container.background
id = 'scan',
widget = wibox.container.background,
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.margin,
top = dpi(10),
},
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
margins = dpi(15),
widget = wibox.container.margin,
},
margins = dpi(15),
widget = wibox.container.margin,
})
}
assert(type(ret) == 'table', 'bluetooth_controller: ret is not a table')
-- Get a reference to the dnd button
local dnd = ret:get_children_by_id("dnd")[1]:get_widget()
local dnd = ret:get_children_by_id('dnd')[1]:get_widget()
-- Toggle bluetooth on or off
dnd:connect_signal("dnd::toggle", function(enable)
dnd:connect_signal('dnd::toggle', function()
ret:toggle()
end)
@@ -418,36 +428,38 @@ function bluetooth.new(args)
-- Create a proxy for the freedesktop ObjectManager
ret._private.ObjectManager = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
interface = "org.freedesktop.DBus.ObjectManager",
path = "/"
name = 'org.bluez',
interface = 'org.freedesktop.DBus.ObjectManager',
path = '/',
}
-- Create a proxy for the bluez Adapter1 interface
ret._private.Adapter1 = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
interface = "org.bluez.Adapter1",
path = "/org/bluez/hci0"
name = 'org.bluez',
interface = 'org.bluez.Adapter1',
path = '/org/bluez/hci0',
}
if not ret._private.Adapter1.Powered then return end
-- Create a proxy for the bluez Adapter1 Properties interface
ret._private.Adapter1Properties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.bluez",
interface = "org.freedesktop.DBus.Properties",
path = "/org/bluez/hci0"
name = 'org.bluez',
interface = 'org.freedesktop.DBus.Properties',
path = '/org/bluez/hci0',
}
-- Connect to the ObjectManager's InterfacesAdded signal
ret._private.ObjectManager:connect_signal(function(_, interface)
ret:get_device_info(interface)
end, "InterfacesAdded")
end, 'InterfacesAdded')
-- Connect to the ObjectManager's InterfacesRemoved signal
ret._private.ObjectManager:connect_signal(function(_, interface)
ret:remove_device(interface)
end, "InterfacesRemoved")
end, 'InterfacesRemoved')
-- Connect to the Adapter1's PropertiesChanged signal
ret._private.Adapter1Properties:connect_signal(function(_, _, data)
@@ -459,9 +471,9 @@ function bluetooth.new(args)
else
dnd:set_disabled()
end
ret:emit_signal("bluetooth::status", data.Powered)
ret:emit_signal('bluetooth::status', data.Powered)
end
end, "PropertiesChanged")
end, 'PropertiesChanged')
gtimer.delayed_call(function()
for path, _ in pairs(ret._private.ObjectManager:GetManagedObjects()) do
@@ -473,100 +485,160 @@ function bluetooth.new(args)
else
dnd:set_disabled()
end
ret:emit_signal("bluetooth::status", ret._private.Adapter1.Powered)
ret:emit_signal('bluetooth::status', ret._private.Adapter1.Powered)
send_state_notification(ret._private.Adapter1.Powered)
end)
--#endregion
--#region Dropdown logic
local connected_margin = ret:get_children_by_id("connected_margin")[1]
local connected_list = ret:get_children_by_id("connected_list")[1]
local connected_icon = ret:get_children_by_id("connected_icon")[1]
local connected_margin = ret:get_children_by_id('connected_margin')[1]
local connected_list = ret:get_children_by_id('connected_list')[1]
local connected_icon = ret:get_children_by_id('connected_icon')[1]
connected_margin:connect_signal(
"button::press",
function()
local rubato_timer = rubato.timed {
local connected_animation = rubato.timed {
duration = 0.2,
pos = connected_list.forced_height,
easing = rubato.linear,
pos = connected_list.height,
clamp_position = true,
subscribed = function(v)
connected_list.forced_height = v
end
connected_list.height = v
end,
}
if connected_list.forced_height == 0 then
ret:connect_signal('device::added_connected', function(device)
if device.Connected then
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
rubato_timer.target = dpi(size)
end
if size > 0 then
connected_animation.target = dpi(size)
connected_margin.connected_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
connected_icon:set_image(gcolor.recolor_image(icondir .. "menu-up.svg",
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.connected_icon_color))
end
end
end)
ret:connect_signal('device::removed_connected', function(device)
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
connected_animation.target = dpi(size)
connected_margin.connected_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.connected_icon_color))
end
end)
connected_margin:connect_signal('button::press', function()
if connected_list.height == 0 then
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
connected_animation.target = dpi(size)
connected_margin.connected_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.connected_icon_color))
end
else
rubato_timer.target = 0
connected_animation.target = 0
connected_margin.connected_bg.shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 4)
end
connected_icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg",
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.bluetooth_controller.connected_icon_color))
end
end
)
end)
local discovered_margin = ret:get_children_by_id("discovered_margin")[1]
local discovered_list = ret:get_children_by_id("discovered_list")[1]
local discovered_bg = ret:get_children_by_id("discovered_bg")[1]
local discovered_icon = ret:get_children_by_id("discovered_icon")[1]
local discovered_margin = ret:get_children_by_id('discovered_margin')[1]
local discovered_list = ret:get_children_by_id('discovered_list')[1]
local discovered_bg = ret:get_children_by_id('discovered_bg')[1]
local discovered_icon = ret:get_children_by_id('discovered_icon')[1]
discovered_margin:connect_signal(
"button::press",
function()
local rubato_timer = rubato.timed {
local discovered_animation = rubato.timed {
duration = 0.2,
pos = discovered_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
discovered_list.forced_height = v
end
end,
}
ret:connect_signal('device::added_discovered', function(device)
if not device.Connected then
local size = (#ret:get_discovered_devices() * 60)
if size > 210 then
size = 210
end
if size > 0 then
discovered_animation.target = dpi(size)
discovered_margin.discovered_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
discovered_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.discovered_icon_color))
end
end
end)
ret:connect_signal('device::removed_discovered', function(device)
local size = (#ret:get_discovered_devices() * 60)
if size > 210 then
size = 210
end
if size > 0 then
discovered_animation.target = dpi(size)
discovered_margin.discovered_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
discovered_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.discovered_icon_color))
end
end)
discovered_margin:connect_signal('button::press', function()
if discovered_list.forced_height == 0 then
local size = (#ret:get_discovered_devices() * 60)
if size > 210 then
size = 210
end
if size > 0 then
rubato_timer.target = dpi(size)
discovered_animation.target = dpi(size)
discovered_margin.discovered_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
discovered_icon:set_image(gcolor.recolor_image(icondir .. "menu-up.svg",
discovered_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.discovered_icon_color))
end
else
rubato_timer.target = 0
discovered_animation.target = 0
discovered_bg.shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 4)
end
discovered_icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg",
discovered_icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.bluetooth_controller.discovered_icon_color))
end
end
)
end)
--#endregion
-- Add buttons to the scan button
ret:get_children_by_id("scan")[1]:buttons({
ret:get_children_by_id('scan')[1]:buttons {
abutton({}, 1, function()
ret:scan()
end)
})
end),
}
Hover_signal(ret:get_children_by_id("scan")[1])
hover.bg_hover { widget = ret:get_children_by_id('scan')[1] }
hover.bg_hover { widget = connected_margin.connected_bg }
hover.bg_hover { widget = discovered_bg }
return ret
end

View File

@@ -3,17 +3,17 @@
---------------------------------------
-- Awesome Libs
local aplacement = require("awful.placement")
local apopup = require("awful.popup")
local dpi = require("beautiful").xresources.apply_dpi
local gcolor = require("gears.color")
local gfilesystem = require("gears.filesystem")
local gtable = require("gears.table")
local gshape = require("gears.shape")
local gtimer = require("gears.timer")
local wibox = require("wibox")
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local gtimer = require('gears.timer')
local wibox = require('wibox')
local backlight_helper = require("src.tools.helpers.backlight")
local backlight_helper = require('src.tools.helpers.backlight')
local capi = {
awesome = awesome,
@@ -21,125 +21,119 @@ local capi = {
}
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/brightness/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/brightness/'
local brightness_osd = { mt = {} }
-- Hide the brightness_osd after 3 seconds
function brightness_osd:hide()
self.timer:stop(false)
end
-- Rerun the timer
function brightness_osd:rerun()
function brightness_osd:run()
self.visible = true
self.timer:again(true)
if self.timer.started then
self.timer:again()
else
self.timer:start()
end
-- Show the brightness_osd for 3 seconds
function brightness_osd:show()
self.visible = true
self.timer:start(true)
end
function brightness_osd.new(args)
args = args or {}
local osd = apopup {
local w = apopup {
widget = {
{
{
{ -- Brightness Icon
image = gcolor.recolor_image(icondir .. "brightness-high.svg", Theme_config.brightness_osd.icon_color),
valign = "center",
halign = "center",
resize = false,
id = "icon",
{
image = gcolor.recolor_image(icondir .. 'volume-off.svg', Theme_config.brightness_ods.icon_color),
valign = 'center',
halign = 'center',
resize = true,
id = 'icon_role',
widget = wibox.widget.imagebox
},
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact'
},
{ -- Brightness Bar
{
{
id = "progressbar1",
color = Theme_config.brightness_osd.bar_bg_active,
background_color = Theme_config.brightness_osd.bar_bg,
id = 'progressbar',
color = Theme_config.brightness_ods.bar_bg_active,
background_color = Theme_config.brightness_ods.bar_bg,
max_value = 100,
value = 0,
forced_height = dpi(6),
shape = function(cr, width, height)
gshape.rounded_bar(cr, width, height, dpi(6))
end,
shape = gshape.rounded_rect,
widget = wibox.widget.progressbar
},
id = "progressbar_container2",
halign = "center",
valign = "center",
widget = wibox.container.constraint,
width = dpi(250),
height = dpi(5),
},
widget = wibox.container.place
},
id = "progressbar_container",
width = dpi(240),
heigth = dpi(20),
stragety = "max",
widget = wibox.container.constraint
{ -- Brightness text
widget = wibox.widget.textbox,
id = 'text_role',
text = '0',
valign = 'center',
halign = 'center'
},
id = "layout1",
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
},
id = "margin",
margins = dpi(10),
left = dpi(10),
right = dpi(10),
top = dpi(20),
bottom = dpi(20),
widget = wibox.container.margin
},
forced_width = dpi(300),
forced_height = dpi(80),
border_color = Theme_config.brightness_osd.border_color,
border_width = Theme_config.brightness_osd.border_width,
fg = Theme_config.brightness_osd.fg,
bg = Theme_config.brightness_osd.bg,
shape = Theme_config.brightness_ods.shape,
widget = wibox.container.background
},
ontop = true,
stretch = false,
visible = false,
screen = args.screen,
placement = function(c) aplacement.bottom_left(c, { margins = dpi(20) }) end,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(14))
border_color = Theme_config.brightness_ods.border_color,
border_width = Theme_config.brightness_ods.border_width,
fg = Theme_config.brightness_ods.fg,
bg = Theme_config.brightness_ods.bg,
screen = 1,
placement = function(c) aplacement.bottom(c, { margins = dpi(20) }) end,
}
gtable.crush(w, brightness_osd, true)
w.timer = gtimer {
timeout = 2,
autostart = true,
callback = function()
w.visible = false
end
}
gtable.crush(osd, brightness_osd, true)
backlight_helper:connect_signal('brightness_changed', function()
backlight_helper:brightness_get_async(function(brightness)
brightness = brightness / (backlight_helper.brightness_max or 24000) * 100
w.widget:get_children_by_id('progressbar')[1].value = brightness
-- Called when the brightness changes, updates the brightness osd and icon
capi.awesome.connect_signal("brightness::changed", function(brightness)
if not capi.mouse.screen == args.screen then return end
assert(type(brightness) == "number", "brightness must be a number")
brightness = (brightness - 0) / ((backlight_helper.brightness_max or 24000) - 0) * 100
osd.widget:get_children_by_id("progressbar1")[1].value = brightness
local icon = icondir .. "brightness"
local icon = icondir .. 'brightness'
if brightness >= 0 and brightness < 34 then
icon = icon .. "-low.svg"
icon = icon .. '-low.svg'
elseif brightness >= 34 and brightness < 67 then
icon = icon .. "-medium.svg"
icon = icon .. '-medium.svg'
elseif brightness >= 67 then
icon = icon .. "-high.svg"
icon = icon .. '-high.svg'
end
osd:rerun(true)
osd.widget:get_children_by_id("icon")[1]:set_image(gcolor.recolor_image(icon,
Theme_config.brightness_osd.icon_color))
w.widget:get_children_by_id('icon')[1]:set_image(gcolor.recolor_image(icon, Theme_config.brightness_osd.icon_color))
w.widget:get_children_by_id('text_role')[1].text = brightness
w:run()
end)
end)
-- osd timer
osd.timer = gtimer {
timeout = 3,
single_shot = true,
callback = function()
osd.visible = false
end
}
return w
end
function brightness_osd.mt:__call(...)

File diff suppressed because it is too large Load Diff

View File

@@ -1,23 +1,21 @@
-- 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 gfilesystem = require("gears").filesystem
local wibox = require("wibox")
local base = require("wibox.widget.base")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears.table')
local gcolor = require('gears.color')
local gfilesystem = require('gears').filesystem
local wibox = require('wibox')
local base = require('wibox.widget.base')
local capi = {
awesome = awesome,
mouse = mouse,
}
local ical_parser = require("src.tools.ical_parser")()
local task_info = require("src.modules.calendar.task_info")
local ical_parser = require('src.tools.ical_parser')()
local task_info = require('src.modules.calendar.task_info')
local hover = require('src.tools.hover')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/calendar/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/calendar/'
local calendar = { mt = {} }
calendar.tasks = {}
@@ -27,36 +25,36 @@ calendar._private = {}
-- Month lookup table
calendar._private.months = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
'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"
'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
day = tonumber(os.date('%d')) or 1,
month = tonumber(os.date('%m')) or 1,
year = tonumber(os.date('%Y')) or 1970,
}
--#region base widget functions
@@ -67,7 +65,7 @@ function calendar:layout(_, width, height)
end
function calendar:fit(context, width, height)
local w, h = 0, 0
local w, h = 0, 0 ---@type number|nil, number|nil
if self._private.widget then
w, h = base.fit_widget(self, context, self._private.widget, width, height)
end
@@ -102,7 +100,7 @@ function calendar:get_last_day_in_month(month, year)
[9] = 30,
[10] = 31,
[11] = 30,
[12] = 31
[12] = 31,
}
if (month == 2) and (math.floor(year % 4) == 0) then
@@ -136,10 +134,10 @@ function calendar:weekday_for_day(day, month, year)
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)
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
@@ -181,7 +179,7 @@ function calendar:get_tasks()
day = start_date.d,
hour = start_date.hour or 0,
min = start_date.min or 0,
sec = start_date.sec or 0
sec = start_date.sec or 0,
},
date_end = {
year = end_date.y,
@@ -189,7 +187,7 @@ function calendar:get_tasks()
day = end_date.d,
hour = end_date.hour or 0,
min = end_date.min or 0,
sec = end_date.sec or 0
sec = end_date.sec or 0,
},
summary = sum,
location = loc,
@@ -219,12 +217,12 @@ function calendar:get_tasks()
day = start_time.day,
hour = start_time.hour,
min = start_time.min,
sec = start_time.sec
sec = start_time.sec,
}
end
-- Get repeat cases
if event.RRULE then
if event.RRULE.FREQ == "DAILY" then
if event.RRULE.FREQ == 'DAILY' then
local year_counter, month_counter, day_counter = start_time.year, start_time.month,
start_time.day
while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or
@@ -235,14 +233,14 @@ function calendar:get_tasks()
d = day_counter,
hour = start_time.hour,
min = start_time.min,
sec = start_time.sec
sec = start_time.sec,
}, {
y = year_counter,
m = month_counter,
d = day_counter,
hour = end_time.hour,
min = end_time.min,
sec = end_time.sec
sec = end_time.sec,
}, event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ)
day_counter = day_counter + 1
@@ -255,14 +253,14 @@ function calendar:get_tasks()
end
end
end
elseif event.RRULE.FREQ == "WEEKLY" then
elseif event.RRULE.FREQ == 'WEEKLY' then
local year_counter, month_counter, day_counter = start_time.year, start_time.month,
start_time.day
while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or
(day_counter <= event.RRULE.UNTIL.day) do
task_factory({ y = year_counter, m = month_counter, d = day_counter, hour = start_time.hour,
min = start_time.min, sec = start_time.sec }, { y = year_counter, m = month_counter,
d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec },
min = start_time.min, sec = start_time.sec, }, { y = year_counter, m = month_counter,
d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec, },
event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ)
day_counter = day_counter + 7
local month_length = calendar:get_last_day_in_month(month_counter, year_counter)
@@ -275,14 +273,14 @@ function calendar:get_tasks()
end
end
end
elseif event.RRULE.FREQ == "MONTHLY" then
elseif event.RRULE.FREQ == 'MONTHLY' then
local year_counter, month_counter, day_counter = start_time.year, start_time.month,
start_time.day
while (year_counter < event.RRULE.UNTIL.year) or (month_counter < event.RRULE.UNTIL.month) or
(day_counter <= event.RRULE.UNTIL.day) do
task_factory({ y = year_counter, m = month_counter, d = day_counter, hour = start_time.hour,
min = start_time.min, sec = start_time.sec }, { y = year_counter, m = month_counter,
d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec },
min = start_time.min, sec = start_time.sec, }, { y = year_counter, m = month_counter,
d = day_counter, hour = end_time.hour, min = end_time.min, sec = end_time.sec, },
event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ)
month_counter = month_counter + 1
if month_counter > 12 then
@@ -290,27 +288,27 @@ function calendar:get_tasks()
year_counter = year_counter + 1
end
end
elseif event.RRULE.FREQ == "YEARLY" 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
day = start_time.day,
}
end
for i = start_time.year, end_time.year, 1 do
task_factory({ y = i, m = start_time.month, d = start_time.day, hour = start_time.hour,
min = start_time.min, sec = start_time.sec }, { y = i, m = end_time.month, d = end_time.day,
hour = end_time.hour, min = end_time.min, sec = end_time.sec }, event.SUMMARY,
min = start_time.min, sec = start_time.sec, }, { y = i, m = end_time.month, d = end_time.day,
hour = end_time.hour, min = end_time.min, sec = end_time.sec, }, event.SUMMARY,
event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ)
end
end
-- If RRULE is empty we just add a single day event
else
task_factory({ y = start_time.year, m = start_time.month, d = start_time.day, hour = start_time.hour,
min = start_time.min, sec = start_time.sec }, { y = end_time.year, m = end_time.month,
d = end_time.day, hour = end_time.hour, min = end_time.min, sec = end_time.sec },
min = start_time.min, sec = start_time.sec, }, { y = end_time.year, m = end_time.month,
d = end_time.day, hour = end_time.hour, min = end_time.min, sec = end_time.sec, },
event.SUMMARY, event.LOCATION, event.DESCRIPTION, event.UID, event.RRULE.FREQ)
end
if event.VALARM then
@@ -323,7 +321,7 @@ function calendar:get_tasks()
table.insert(self.tasks, tasks)
table.insert(self.calendars, {
tasks = self.tasks,
color = cal.color
color = cal.color,
})
end
end
@@ -344,19 +342,19 @@ function calendar:create_calendar_weeks_widget()
{
{
text = i,
id = "num",
align = "center",
valign = "top",
id = 'num',
align = 'center',
valign = 'top',
widget = wibox.widget.textbox,
},
id = "background",
id = 'background',
fg = Theme_config.calendar.day.fg_unfocus,
widget = wibox.container.background,
},
strategy = "exact",
strategy = 'exact',
height = dpi(120),
width = dpi(40),
widget = wibox.container.constraint
widget = wibox.container.constraint,
})
end
end
@@ -369,8 +367,8 @@ function calendar:create_weekdays_widget()
self._private.weekdays:add(wibox.widget {
{
text = self._private.weeks[i],
align = "center",
valign = "center",
align = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
bg = Theme_config.calendar.weekdays.bg,
@@ -404,10 +402,10 @@ function calendar:create_calendar_widget()
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,
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
step = dpi(50),
spacing = dpi(2)
spacing = dpi(2),
}
local function task_factory(task, bg)
@@ -415,19 +413,19 @@ function calendar:create_calendar_widget()
{
{
text = task.summary,
align = "left",
halign = "center",
font = "JetBrainsMono Nerd Font, bold 10",
widget = wibox.widget.textbox
align = 'left',
halign = 'center',
font = 'JetBrainsMono Nerd Font, bold 10',
widget = wibox.widget.textbox,
},
margins = dpi(2),
widget = wibox.container.margin
widget = wibox.container.margin,
},
fg = Theme_config.calendar.task.fg,
bg = bg,
shape = Theme_config.calendar.task.shape,
forced_height = dpi(20),
widget = wibox.container.background
widget = wibox.container.background,
}
end
@@ -442,7 +440,7 @@ function calendar:create_calendar_widget()
(
task.date_start.year == self.date.year and task.date_start.month == self.date.month and
task.date_start.day < self.date.day) then
tw = task_factory(task, cal.color .. "55")
tw = task_factory(task, cal.color .. '55')
else
tw = task_factory(task, cal.color)
end
@@ -466,10 +464,10 @@ function calendar:create_calendar_widget()
widget = ti,
ontop = true,
visible = false,
bg = "#00000000",
bg = '#00000000',
x = capi.mouse.coords().x,
y = capi.mouse.coords().y,
screen = self.screen
screen = capi.mouse.screen,
}
tw:buttons(
@@ -482,11 +480,11 @@ function calendar:create_calendar_widget()
)
)
tw:connect_signal("mouse::leave", function()
tw:connect_signal('mouse::leave', function()
task_popup.visible = false
end)
Hover_signal(tw)
hover.bg_hover { widget = tw }
table.insert(tasks_layout, tw)
end
@@ -514,8 +512,8 @@ function calendar:create_calendar_widget()
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"))
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
@@ -531,39 +529,39 @@ function calendar:create_calendar_widget()
{
{ -- Day
widget = wibox.widget.textbox,
align = "center",
valign = "center",
align = 'center',
valign = 'center',
text = math.floor(i),
id = "day_text",
id = 'day_text',
},
widget = wibox.container.margin,
margins = dpi(2),
},
id = "day_bg",
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",
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 = 'day_tasks',
},
id = "tasks",
id = 'tasks',
spacing = dpi(4),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
id = "day_bg",
id = 'day_bg',
widget = wibox.container.margin,
top = dpi(4)
top = dpi(4),
},
id = "background",
id = 'background',
widget = wibox.container.background,
bg = Theme_config.calendar.day.bg_unfocus,
fg = Theme_config.calendar.day.fg_unfocus,
@@ -571,11 +569,11 @@ function calendar:create_calendar_widget()
border_width = Theme_config.calendar.day.border_width,
shape = Theme_config.calendar.day.shape,
},
id = "day",
id = 'day',
widget = wibox.container.constraint,
width = dpi(100),
height = dpi(120),
strategy = "exact"
strategy = 'exact',
}
self._private.calendar_matrix:add_widget_at(day, 1, column)
@@ -592,8 +590,8 @@ function calendar:create_calendar_widget()
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"))
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
@@ -608,37 +606,37 @@ function calendar:create_calendar_widget()
{
{ -- Day
widget = wibox.widget.textbox,
align = "center",
valign = "center",
align = 'center',
valign = 'center',
text = math.floor(i),
id = "day_text",
id = 'day_text',
},
widget = wibox.container.margin,
margins = dpi(2),
},
id = "day_bg",
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",
valign = 'center',
halign = 'center',
},
{
get_tasks_for_day(math.floor(i), self.date.month, self.date.year),
widget = wibox.container.margin,
margins = dpi(4)
margins = dpi(4),
},
id = "tasks",
id = 'tasks',
spacing = dpi(4),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
top = dpi(4)
top = dpi(4),
},
id = "background",
id = 'background',
widget = wibox.container.background,
bg = Theme_config.calendar.day.bg,
fg = Theme_config.calendar.day.fg,
@@ -649,7 +647,7 @@ function calendar:create_calendar_widget()
widget = wibox.container.constraint,
width = dpi(100),
height = dpi(120),
strategy = "exact"
strategy = 'exact',
}
self._private.calendar_matrix:add_widget_at(day, row, col)
@@ -674,8 +672,8 @@ function calendar:create_calendar_widget()
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"))
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
@@ -689,37 +687,37 @@ function calendar:create_calendar_widget()
{
{ -- Day
widget = wibox.widget.textbox,
align = "center",
valign = "center",
align = 'center',
valign = 'center',
text = math.floor(i),
id = "day_text",
id = 'day_text',
},
widget = wibox.container.margin,
margins = dpi(2),
},
id = "day_bg",
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",
valign = 'center',
halign = 'center',
},
{
get_tasks_for_day(math.floor(i), next_month, year),
widget = wibox.container.margin,
margins = dpi(4)
margins = dpi(4),
},
id = "tasks",
id = 'tasks',
spacing = dpi(4),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
top = dpi(4)
top = dpi(4),
},
id = "background",
id = 'background',
widget = wibox.container.background,
bg = Theme_config.calendar.day.bg_unfocus,
fg = Theme_config.calendar.day.fg_unfocus,
@@ -730,7 +728,7 @@ function calendar:create_calendar_widget()
widget = wibox.container.constraint,
width = dpi(100),
height = dpi(120),
strategy = "exact"
strategy = 'exact',
}
self._private.calendar_matrix:add_widget_at(day, months_t[self.date.month].weeks,
months_t[self.date.month].last_day + i)
@@ -754,44 +752,44 @@ function calendar.new(args)
{
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"
image = gcolor.recolor_image(icondir .. 'add_ical.svg', Theme_config.calendar.add_ical.fg_focus),
halign = 'center',
valign = 'center',
},
id = "add_ical",
id = 'add_ical',
shape = Theme_config.calendar.add_ical.shape,
bg = Theme_config.calendar.add_ical.bg,
widget = wibox.container.background
widget = wibox.container.background,
},
widget = wibox.container.margin,
margins = dpi(4)
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"
image = gcolor.recolor_image(icondir .. 'add_task.svg', Theme_config.calendar.add_task.fg),
halign = 'center',
valign = 'center',
},
id = "add_task",
id = 'add_task',
shape = Theme_config.calendar.add_task.shape,
bg = Theme_config.calendar.add_task.bg,
widget = wibox.container.background
widget = wibox.container.background,
},
widget = wibox.container.margin,
margins = dpi(4)
margins = dpi(4),
},
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.constraint,
strategy = "exact",
height = dpi(75)
strategy = 'exact',
height = dpi(75),
},
ret._private.calendar_weeks_widget,
id = "weekdaysnum",
layout = wibox.layout.fixed.vertical
id = 'weekdaysnum',
layout = wibox.layout.fixed.vertical,
},
{
{
@@ -800,88 +798,88 @@ function calendar.new(args)
{ -- Prev arrow
widget = wibox.widget.imagebox,
resize = true,
image = icondir .. "chevron-left.svg",
valign = "center",
halign = "center",
id = "prev_month",
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"
id = 'month',
valign = 'center',
align = 'center',
},
widget = wibox.container.constraint,
strategy = "exact",
width = dpi(150)
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",
image = icondir .. 'chevron-right.svg',
valign = 'center',
halign = 'center',
id = 'next_month',
},
layout = wibox.layout.fixed.horizontal
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"
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"
id = 'year',
valign = 'center',
align = 'center',
},
widget = wibox.container.constraint,
strategy = "exact",
width = dpi(150)
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"
image = icondir .. 'chevron-right.svg',
valign = 'center',
halign = 'center',
id = 'next_year',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.constraint,
height = dpi(40),
strategy = "exact"
strategy = 'exact',
},
{ -- Weekdays
ret._private.weekdays,
widget = wibox.container.background
widget = wibox.container.background,
},
ret._private.calendar_matrix,
id = "calendar",
id = 'calendar',
spacing = dpi(5),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
id = "lay1",
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",
border_strategy = 'inner',
fg = Theme_config.calendar.fg,
shape = Theme_config.calendar.shape,
})
@@ -893,13 +891,13 @@ function calendar.new(args)
ret:create_weekdays_widget()
ret:create_calendar_weeks_widget()
ret:get_widget():get_children_by_id("add_ical")[1]:buttons(gtable.join(
ret:get_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) or (path_to_file == "") then return end
path_to_file = string.gsub(path_to_file, '\n', '')
if (not path_to_file) or (path_to_file == '') then return end
ical_parser:add_calendar(path_to_file)
ret:get_tasks()
ret:create_calendar_widget()
@@ -908,7 +906,7 @@ function calendar.new(args)
end)
))
ret:get_widget():get_children_by_id("add_task")[1]:buttons(gtable.join(
ret:get_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'",
@@ -919,54 +917,57 @@ function calendar.new(args)
end)
))
ret:get_widget():get_children_by_id("prev_month")[1]:buttons(gtable.join(
ret:get_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
ret:get_widget():get_children_by_id("month")[1].text = ret._private.months[ret.date.month]
ret:get_widget():get_children_by_id("year")[1].text = ret.date.year
ret:get_widget():get_children_by_id('month')[1].text = ret._private.months[ret.date.month]
ret:get_widget():get_children_by_id('year')[1].text = ret.date.year
ret:create_calendar_weeks_widget()
ret:create_calendar_widget()
end)
))
ret:get_widget():get_children_by_id("next_month")[1]:buttons(gtable.join(
ret:get_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
ret:get_widget():get_children_by_id("month")[1].text = ret._private.months[ret.date.month]
ret:get_widget():get_children_by_id("year")[1].text = ret.date.year
ret:get_widget():get_children_by_id('month')[1].text = ret._private.months[ret.date.month]
ret:get_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
ret:get_widget():get_children_by_id("prev_year")[1]:buttons(gtable.join(
ret:get_widget():get_children_by_id('prev_year')[1]:buttons(gtable.join(
awful.button({}, 1, function()
ret.date.year = ret.date.year - 1
ret:get_widget():get_children_by_id("year")[1].text = ret.date.year
ret:get_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
ret:get_widget():get_children_by_id("next_year")[1]:buttons(gtable.join(
ret:get_widget():get_children_by_id('next_year')[1]:buttons(gtable.join(
awful.button({}, 1, function()
ret.date.year = ret.date.year + 1
ret:get_widget():get_children_by_id("year")[1].text = ret.date.year
ret:get_widget():get_children_by_id('year')[1].text = ret.date.year
ret:create_calendar_weeks_widget()
ret:create_calendar_widget()
end)
))
hover.bg_hover { widget = ret:get_widget():get_children_by_id('add_ical')[1] }
hover.bg_hover { widget = ret:get_widget():get_children_by_id('add_task')[1] }
return ret
end

View File

@@ -1,18 +1,16 @@
-- 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 gfilesystem = require("gears").filesystem
local wibox = require("wibox")
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 gfilesystem = require('gears').filesystem
local wibox = require('wibox')
local capi = {
mouse = mouse,
}
local hover = require('src.tools.hover')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/calendar/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/calendar/'
local task_info = { mt = {} }
task_info._private = {}
@@ -23,11 +21,11 @@ function task_info.new(args)
local ret = gobject {}
gtable.crush(ret, task_info, true)
args.color = args.color or "#ffffff"
args.color = args.color or '#ffffff'
local date_long_written = os.date("%A, %d. %B %Y", os.time(args.date_start))
local date_long_written = os.date('%A, %d. %B %Y', os.time(args.date_start))
local from_to = os.date("%H:%M", os.time(args.date_start)) .. " - " .. os.date("%H:%M", os.time(args.date_end))
local from_to = os.date('%H:%M', os.time(args.date_start)) .. ' - ' .. os.date('%H:%M', os.time(args.date_end))
local task_info_widget = wibox.widget {
{
@@ -45,89 +43,89 @@ function task_info.new(args)
{
{ -- Summary
widget = wibox.widget.textbox,
text = args.summary:sub(1, -2) or "NO SUMMARY",
valign = "center",
halign = "left",
id = "summary",
text = args.summary:sub(1, -2) or 'NO SUMMARY',
valign = 'center',
halign = 'left',
id = 'summary',
},
{ -- Date long
widget = wibox.widget.textbox,
text = date_long_written or "01.12.1970",
valign = "center",
halign = "right",
id = "date_long",
text = date_long_written or '01.12.1970',
valign = 'center',
halign = 'right',
id = 'date_long',
},
{ -- From - To
widget = wibox.widget.textbox,
text = from_to or "",
valign = "center",
halign = "left",
id = "from_to",
text = from_to or '',
valign = 'center',
halign = 'left',
id = 'from_to',
},
{ -- Repeat information
widget = wibox.widget.textbox,
text = args.freq or "0",
valign = "center",
halign = "left",
id = "repeat_info",
text = args.freq or '0',
valign = 'center',
halign = 'left',
id = 'repeat_info',
}, -- Year
{
widget = wibox.widget.textbox,
text = args.date_start.year or "1970",
valign = "center",
halign = "left",
id = "year",
text = args.date_start.year or '1970',
valign = 'center',
halign = 'left',
id = 'year',
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical,
},
spacing = dpi(20),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin,
left = dpi(9)
left = dpi(9),
},
{ -- Location
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. "location.svg", args.color),
image = gcolor.recolor_image(icondir .. 'location.svg', args.color),
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
},
{
widget = wibox.widget.textbox,
text = args.location:sub(1, -2) or "F303",
valign = "center",
halign = "left",
id = "location",
text = args.location:sub(1, -2) or 'F303',
valign = 'center',
halign = 'left',
id = 'location',
},
spacing = dpi(10),
id = "location_container",
layout = wibox.layout.fixed.horizontal
id = 'location_container',
layout = wibox.layout.fixed.horizontal,
},
{ -- Alarm
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. "alarm.svg", args.color),
image = gcolor.recolor_image(icondir .. 'alarm.svg', args.color),
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
},
{
widget = wibox.widget.textbox,
text = args.alarm or "NO ALARM",
valign = "center",
halign = "left",
id = "alarm",
text = args.alarm or 'NO ALARM',
valign = 'center',
halign = 'left',
id = 'alarm',
},
spacing = dpi(10),
id = "alarm_container",
layout = wibox.layout.fixed.horizontal
id = 'alarm_container',
layout = wibox.layout.fixed.horizontal,
},
id = "task_detail",
id = 'task_detail',
spacing = dpi(15),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
left = dpi(6),
@@ -141,6 +139,8 @@ function task_info.new(args)
widget = wibox.container.background,
}
hover.bg_hover { widget = task_info_widget }
ret.widget = task_info_widget
return ret.widget

View File

@@ -2,32 +2,33 @@
-- This is the brightness_osd module --
---------------------------------------
-- Awesome Libs
local awful = require("awful")
local awful = require('awful')
local abutton = awful.button
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears.table")
local base = require("wibox.widget.base")
local wibox = require("wibox")
local gfilesystem = require("gears.filesystem")
local gobject = require("gears.object")
local gcolor = require("gears.color")
local gtimer = require("gears.timer")
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears.table')
local base = require('wibox.widget.base')
local wibox = require('wibox')
local gfilesystem = require('gears.filesystem')
local gcolor = require('gears.color')
local gtimer = require('gears.timer')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
mouse = mouse
mouse = mouse,
}
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/context_menu/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/context_menu/'
local context_menu = {
mt = {}
mt = {},
}
function context_menu:layout(_, width, height)
if self._private.widget then
return {
base.place_widget_at(self._private.widget, 0, 0, width, height)
base.place_widget_at(self._private.widget, 0, 0, width, height),
}
end
end
@@ -45,7 +46,7 @@ context_menu.set_widget = base.set_widget_common
function context_menu:make_entries(wtemplate, entries, spacing)
local menu_entries = {
layout = wibox.layout.fixed.vertical,
spacing = spacing
spacing = spacing,
}
if not wtemplate then
@@ -53,8 +54,7 @@ function context_menu:make_entries(wtemplate, entries, spacing)
end
for key, entry in pairs(entries) do
-- TODO: Figure out how to make a new widget from etemplate
local menu_entry = wibox.widget {
local menu_entry = base.make_widget_from_value {
{
{
{
@@ -62,72 +62,74 @@ function context_menu:make_entries(wtemplate, entries, spacing)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role"
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
nil,
{
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "arrow_role"
valign = 'center',
halign = 'center',
id = 'arrow_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.desktop.context_menu.entry_bg,
fg = Theme_config.desktop.context_menu.entry_fg,
widget = wibox.container.background
widget = wibox.container.background,
}
Hover_signal(menu_entry)
assert(type(menu_entry) == 'table', 'Entry must be a table')
menu_entry:get_children_by_id("icon_role")[1].image = entry.icon
menu_entry:get_children_by_id("text_role")[1].text = entry.name
hover.bg_hover { widget = menu_entry }
menu_entry:get_children_by_id('icon_role')[1].image = entry.icon
menu_entry:get_children_by_id('text_role')[1].text = entry.name
if entry.submenu then
menu_entry:get_children_by_id("arrow_role")[1].image =
gcolor.recolor_image(icondir .. "entry.svg", Theme_config.desktop.context_menu.entry_fg)
menu_entry:get_children_by_id('arrow_role')[1].image =
gcolor.recolor_image(icondir .. 'entry.svg', Theme_config.desktop.context_menu.entry_fg)
end
gtable.crush(menu_entry, entry, true)
menu_entry:buttons(gtable.join {
abutton({
abutton {
modifiers = {},
button = 1,
on_release = function()
if not entry.submenu then
entry.callback()
end
capi.awesome.emit_signal("submenu::close")
capi.awesome.emit_signal("cm::hide")
end
})
capi.awesome.emit_signal('submenu::close')
capi.awesome.emit_signal('cm::hide')
end,
},
})
if entry.submenu then
@@ -139,7 +141,7 @@ function context_menu:make_entries(wtemplate, entries, spacing)
border_width = Theme_config.desktop.context_menu.border_width,
border_color = Theme_config.desktop.context_menu.border_color,
shape = Theme_config.desktop.context_menu.shape,
visible = false
visible = false,
}
local hide_timer = gtimer {
@@ -148,25 +150,25 @@ function context_menu:make_entries(wtemplate, entries, spacing)
single_shot = true,
callback = function()
menu_entry.popup.visible = false
end
end,
}
menu_entry:connect_signal("mouse::enter", function()
menu_entry:connect_signal('mouse::enter', function()
-- place widget right of parent
menu_entry.popup:move_next_to(capi.mouse.current_widget_geometry)
hide_timer:stop()
menu_entry.popup.visible = true
end)
menu_entry.popup:connect_signal("mouse::leave", function()
menu_entry.popup:connect_signal('mouse::leave', function()
hide_timer:again()
end)
menu_entry.popup:connect_signal("mouse::enter", function()
menu_entry.popup:connect_signal('mouse::enter', function()
hide_timer:stop()
end)
menu_entry:connect_signal("mouse::leave", function()
menu_entry:connect_signal('mouse::leave', function()
hide_timer:again()
end)
capi.awesome.connect_signal("submenu::close", function()
capi.awesome.connect_signal('submenu::close', function()
menu_entry.popup.visible = false
end)
end
@@ -176,8 +178,11 @@ function context_menu:make_entries(wtemplate, entries, spacing)
end
function context_menu:toggle()
self.x = capi.mouse.coords().x
self.y = capi.mouse.coords().y
self.x = capi.mouse.coords().x - dpi(5)
self.y = capi.mouse.coords().y - dpi(5)
if self.y + self.height > capi.mouse.screen.geometry.height then
self.y = self.y - self.height + dpi(10)
end
self.visible = not self.visible
end
@@ -190,8 +195,10 @@ function context_menu.new(args)
gtable.crush(ret, context_menu, true)
local entries = ret:make_entries(args.widget_template, args.entries, args.spacing)
ret = awful.popup {
widget = ret:make_entries(args.widget_template, args.entries, args.spacing),
widget = entries,
bg = Theme_config.desktop.context_menu.bg,
fg = Theme_config.desktop.context_menu.fg,
ontop = true,
@@ -200,11 +207,11 @@ function context_menu.new(args)
shape = Theme_config.desktop.context_menu.shape,
visible = false,
x = capi.mouse.coords().x + 10,
y = capi.mouse.coords().y - 10
y = capi.mouse.coords().y - 10,
}
-- I literally have no clue how to do it better, it doesn't really matter anyways
capi.awesome.connect_signal("cm::hide", function()
capi.awesome.connect_signal('cm::hide', function()
ret.visible = false
end)

View File

@@ -2,10 +2,10 @@
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local capi = {
awesome = awesome,
@@ -17,7 +17,7 @@ return function(s, widgets)
local function prepare_widgets(w)
local layout = {
forced_height = dpi(50),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
}
for i, widget in pairs(w) do
if i == 1 then
@@ -28,7 +28,7 @@ return function(s, widgets)
right = dpi(6),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
elseif i == #w then
table.insert(layout,
@@ -38,7 +38,7 @@ return function(s, widgets)
right = dpi(6),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
else
table.insert(layout,
@@ -48,28 +48,28 @@ return function(s, widgets)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
end
end
return layout
end
local top_center = awful.popup {
local top_center = apopup {
screen = s,
widget = prepare_widgets(widgets),
ontop = false,
bg = Theme_config.center_bar.bg,
visible = true,
maximum_width = dpi(500),
placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end
placement = function(c) aplacement.top(c, { margins = dpi(10) }) end,
}
top_center:struts {
top = dpi(55)
top = dpi(55),
}
capi.client.connect_signal("manage", function(c)
capi.client.connect_signal('manage', function(c)
if #s.selected_tag:clients() < 1 then
top_center.visible = false
else
@@ -77,7 +77,7 @@ return function(s, widgets)
end
end)
capi.client.connect_signal("unmanage", function(c)
capi.client.connect_signal('unmanage', function(c)
if #s.selected_tag:clients() < 1 then
top_center.visible = false
else
@@ -85,7 +85,7 @@ return function(s, widgets)
end
end)
capi.client.connect_signal("property::selected", function(c)
capi.client.connect_signal('property::selected', function(c)
if #s.selected_tag:clients() < 1 then
top_center.visible = false
else
@@ -93,7 +93,7 @@ return function(s, widgets)
end
end)
capi.awesome.connect_signal("refresh", function(c)
capi.awesome.connect_signal('refresh', function(c)
if #s.selected_tag:clients() < 1 then
top_center.visible = false
else

View File

@@ -2,116 +2,170 @@
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local Gio = require("lgi").Gio
local gears = require("gears")
local wibox = require("wibox")
local lgi = require('lgi')
local Gio = lgi.Gio
local abutton = require('awful.button')
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local wibox = require('wibox')
local gcolor = require('gears.color')
local awidget = require('awful.widget')
local aplacement = require('awful.placement')
local gtimer = require('gears.timer')
local amenu = require('awful.menu')
-- Local libs
local config = require('src.tools.config')
local context_menu = require('src.modules.context_menu.init')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
client = client,
mouse = mouse,
screen = screen,
}
local json = require("src.lib.json-lua.json-lua")
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/'
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/context_menu/"
local cm = require("src.modules.context_menu.init")
return function(screen)
local cm_open = false
local dock_element_ammount = 0
---Creates a new program widget for the dock
---@param program string | function The name of the .desktop file
---@param size number The size of the widget
---@return widox.widget | nil The widget or nil if the program is not found
local function create_dock_element(program, size)
local dock_element = wibox.widget {
{
{
{
{
resize = true,
widget = wibox.widget.imagebox,
image = program.icon or "",
valign = "center",
halign = "center",
id = "icon",
},
id = "icon_container",
strategy = "exact",
width = dpi(size),
height = dpi(size),
widget = wibox.container.constraint
},
margins = dpi(5),
widget = wibox.container.margin,
id = "margin"
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(10))
end,
bg = Theme_config.dock.element_bg,
fg = "#000000",
widget = wibox.container.background,
id = "background"
},
top = dpi(5),
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin
local elements = {
['pinned'] = {},
['applauncher_starter'] = {},
['running'] = {},
}
Hover_signal(dock_element.background, Theme_config.dock.element_focused_bg .. "dd")
local instances = {}
local DAI = Gio.DesktopAppInfo.new_from_filename(program.desktop_file)
if not DAI then return end
local action_entries = {}
for _, action in ipairs(program.actions) do
table.insert(action_entries, {
name = Gio.DesktopAppInfo.get_action_name(DAI, action) or "",
icon = gears.color.recolor_image(action.icon or icondir .. "entry.svg", Theme_config.dock.cm_icon),
callback = function()
Gio.DesktopAppInfo.launch_action(DAI, action)
local dock = { mt = {} }
--[[ Json format of dock.json, running apps won't be saved
[
{
"applauncher_starter": {
{
"name": "Application Launcher",
"icon": "/usr/share/icons/Papirus/48x48/apps/xfce4-appfinder.svg",
}
},
"pinned": [
{
"name": "firefox",
"icon": "/usr/share/icons/Papirus/48x48/apps/firefox.svg",
"exec": "firefox",
"desktop_file": "/usr/share/applications/firefox.desktop"
},
{
"name": "discord",
"icon": "/usr/share/icons/Papirus/48x48/apps/discord.svg",
"exec": "discord",
"desktop_file": "/usr/share/applications/discord.desktop"
}
],
}
]
]]
function dock:toggle()
self.popup.visible = not self.popup.visible
end
function dock:write_elements_to_file_async(callback)
--create a local copy of the elements["pinned"] table and only set the desktop_file key from its children
local elements_copy = { pinned = {} }
for _, element in ipairs(elements['pinned']) do
table.insert(elements_copy['pinned'], { desktop_file = element.desktop_file })
end
config.write_json(gfilesystem.get_configuration_dir() .. 'src/config/dock_' .. self.screen.index .. '.json', elements_copy['pinned'], callback)
end
---Read the content of dock.json and get the content as a table
---@param callback function Called after the elements have been set, no values are passed
function dock:read_elements_from_file_async(callback)
local data = config.read_json(gfilesystem.get_configuration_dir() .. 'src/config/dock_' .. self.screen.index .. '.json')
-- Make sure to not set the running key to nil on accident
for _, v in ipairs(data) do
local w = self:get_element_widget(v.desktop_file)
table.insert(elements['pinned'], w)
end
if callback then
callback()
end
end
---Creates a pinned widget for the dock and adds it into the elements table
---@param desktop_file string .desktop file path
---@return nil
function dock:get_element_widget(desktop_file)
if not desktop_file then return end
local GDesktopAppInfo = Gio.DesktopAppInfo.new_from_filename(desktop_file)
local icon = Get_gicon_path(nil, GDesktopAppInfo.get_string(GDesktopAppInfo, 'Icon')) or
Get_gicon_path(nil, Gio.DesktopAppInfo.get_string(GDesktopAppInfo, 'X-AppImage-Old-Icon')) or ''
local widget = wibox.widget {
{
{
{
{
widget = wibox.widget.imagebox,
image = icon,
valign = 'center',
halign = 'center',
resize = true,
id = 'icon_role',
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size,
height = User_config.dock_icon_size,
},
widget = wibox.container.margin,
margins = dpi(5),
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size + dpi(10), -- + margins
height = User_config.dock_icon_size + dpi(10),
strategy = 'exact',
},
bg = Theme_config.dock.element.bg,
shape = Theme_config.dock.element.shape,
widget = wibox.container.background,
}
local action_entries = {}
for _, action in ipairs(Gio.DesktopAppInfo.list_actions(GDesktopAppInfo)) do
table.insert(action_entries, {
name = Gio.DesktopAppInfo.get_action_name(GDesktopAppInfo, action) or '',
icon = Get_gicon_path(nil, GDesktopAppInfo.get_string(GDesktopAppInfo, 'Icon')) or
Get_gicon_path(nil, Gio.DesktopAppInfo.get_string(GDesktopAppInfo, 'X-AppImage-Old-Icon')) or
gcolor.recolor_image(icondir .. 'entry.svg', Theme_config.dock.cm_icon),
callback = function()
Gio.DesktopAppInfo.launch_action(GDesktopAppInfo, action)
end,
})
end
table.insert(action_entries, {
name = "Remove from Dock",
icon = gears.color.recolor_image(icondir .. "entry.svg", Theme_config.dock.cm_icon),
name = 'Remove from Dock',
icon = gcolor.recolor_image(icondir .. 'context_menu/entry.svg', Theme_config.dock.cm_icon),
callback = function()
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
return
end
local dock = json:decode(data:read("a"))
data:close()
for i, v in ipairs(dock) do
if v.desktop_file == program.desktop_file then
if type(dock) == "table" then
table.remove(dock, i)
local data = config.read_json(gfilesystem.get_configuration_dir() .. 'src/config/dock_' .. self.screen.index .. '.json')
for i, v in ipairs(data) do
if v.desktop_file == desktop_file then
if type(data) == 'table' then
table.remove(data, i)
end
break
end
end
data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "w")
if not data then
return
end
data:write(json:encode(dock))
data:close()
capi.awesome.emit_signal("dock::changed")
end
config.write_json(gfilesystem.get_configuration_dir() .. 'src/config/dock_' .. self.screen.index .. '.json', data)
self:remove_element_widget(widget)
end,
})
local context_menu = cm {
widget.cm = context_menu {
widget_template = wibox.widget {
{
{
@@ -119,217 +173,174 @@ return function(screen)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
},
}, spacing = dpi(10),
entries = action_entries,
spacing = dpi(10),
}
dock_element:buttons(gears.table.join(
awful.button({
modifiers = {},
button = 1,
on_release = function()
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(program.exec, nil, 0))
end
}),
awful.button({
modifiers = {},
button = 3,
on_release = function()
if not context_menu then
return
end
-- add offset so mouse is above widget, this is so the mouse::leave event triggers always
context_menu:toggle()
end
})
))
widget.cm:connect_signal('mouse::leave', function()
widget.cm.visible = false
self.cm_open = widget.cm.visible
end)
capi.awesome.connect_signal(
"context_menu::hide",
function()
cm_open = false
capi.awesome.emit_signal("dock::check_for_dock_hide")
end
)
awful.tooltip {
objects = { dock_element },
text = program.name,
mode = "outside",
preferred_alignments = "middle",
margins = dpi(10)
hover.bg_hover {
widget = widget,
overlay = 12,
press_overlay = 24,
}
dock_element_ammount = dock_element_ammount + 1
return dock_element
local exec = Gio.DesktopAppInfo.get_string(GDesktopAppInfo, 'Exec')
widget:buttons(gtable.join {
abutton({}, 1, function()
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(exec, nil, 0))
end),
abutton({}, 3, function()
widget.cm:toggle()
self.cm_open = widget.cm.visible
end),
})
table.insert(elements['pinned'], widget)
self:emit_signal('dock::element_added', widget)
end
--- Indicators under the elements to indicate various open states
local function create_incicator_widget()
local container = { layout = wibox.layout.flex.horizontal }
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
---Removes a given widget from the dock
---@param widget wibox.widget The widget to remove
function dock:remove_element_widget(widget)
if not widget then return end
for k, v in pairs(elements['pinned']) do
if v == widget then
table.remove(elements['pinned'], k)
self:emit_signal('dock::element_removed', widget)
return
end
end
end
local prog = json:decode(data:read("a"))
data:close()
for _, pr in ipairs(prog) do
local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) }
local col = Theme_config.dock.indicator_bg
for _, c in ipairs(capi.client.get()) do
local icon_name = string.lower(pr.icon)
if not c or not c.valid then return end
local cls = c.class or ""
local class = string.lower(cls)
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 == capi.client.focus then
col = Theme_config.dock.indicator_focused_bg
elseif c.urgent then
col = Theme_config.dock.indicator_urgent_bg
elseif c.maximized then
col = Theme_config.dock.indicator_maximized_bg
elseif c.minimized then
col = Theme_config.dock.indicator_minimized_bg
elseif c.fullscreen then
col = Theme_config.dock.indicator_fullscreen_bg
else
col = Theme_config.dock.indicator_bg
---Pins an element to the dock by adding it to the pinned table, then writes the table to the file
---emits the signal `dock::pin_element` then successfully added to the table
---@param args {desktop_file: string} The path to the .desktop file
function dock:pin_element(args)
if not args then return end
local e = args.desktop_file
assert(e, 'No desktop file provided')
self:emit_signal('dock::pin_element', e)
self:write_elements_to_file_async()
end
table.insert(indicators, wibox.widget {
widget = wibox.container.background,
shape = gears.shape.rounded_rect,
forced_height = dpi(3),
bg = col,
forced_width = dpi(5),
})
end
end
table.insert(container, wibox.widget {
indicators,
forced_height = dpi(5),
forced_width = dpi(User_config.dock_icon_size),
left = dpi(5),
right = dpi(5),
function dock:add_start_element()
local widget = wibox.widget {
{
{
{
{
widget = wibox.widget.imagebox,
image = gfilesystem.get_configuration_dir() .. 'src/assets/CT.svg',
valign = 'center',
halign = 'center',
resize = true,
id = 'icon_role',
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size,
height = User_config.dock_icon_size,
},
widget = wibox.container.margin,
margins = dpi(5),
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size + dpi(10), -- + margins
height = User_config.dock_icon_size + dpi(10),
strategy = 'exact',
},
bg = Theme_config.dock.element.bg,
shape = Theme_config.dock.element.shape,
widget = wibox.container.background,
}
hover.bg_hover {
widget = widget,
overlay = 12,
press_overlay = 24,
}
widget:buttons(gtable.join {
abutton({}, 1, function()
capi.awesome.emit_signal('application_launcher::show')
end),
})
end
return wibox.widget {
container,
bottom = dpi(5),
widget = wibox.container.margin,
}
return widget
end
--- The container bar where the elements/program widgets sit in
local dock = awful.popup {
widget = wibox.container.background,
ontop = true,
bg = Theme_config.dock.bg,
visible = true,
screen = screen,
type = "dock",
height = dpi(User_config.dock_icon_size + 10),
placement = function(c) awful.placement.bottom(c, { margins = dpi(10) }) end
}
---Unpins an element from the dock by removing it from the pinned table, then writes the table to the file
---emits the signal `dock::unpin_element` then successfully removed from the table
---@param args {desktop_file: string} The path to the .desktop file
function dock:unpin_element(args)
if not args then return end
--- A fakedock to send a signal when the mouse is over it
local fakedock = awful.popup {
widget = wibox.container.background,
ontop = true,
bg = '#00000000',
visible = true,
screen = screen,
type = "dock",
id = "fakedock",
height = dpi(10),
placement = function(c) awful.placement.bottom(c) end,
}
--- List of all elements/program widgets
local dock_elements = { layout = wibox.layout.fixed.horizontal }
--- This function creates a list with all dock elements/program widgets
---@return table|nil string list of widgets
local function get_dock_elements()
dock_element_ammount = 0
dock_elements = { layout = wibox.layout.fixed.horizontal }
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
return
for index, value in ipairs(elements['pinned']) do
if value == args.desktop_file then
table.remove(elements['pinned'], index)
break;
end
local dock_data = json:decode(data:read("a"))
data:close()
for _, program in ipairs(dock_data) do
table.insert(dock_elements, create_dock_element(program, User_config.dock_icon_size))
end
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
self:emit_signal('dock::unpin_element', args.desktop_file)
self:write_elements_to_file_async()
end
get_dock_elements()
--- Function to get an empty list with the same ammount as dock_element
local function get_fake_elements()
local fake_elements = { layout = wibox.layout.fixed.horizontal }
for i = 0, dock_element_ammount, 1 do
fake_elements[i] = wibox.widget {
bg = '00000000',
forced_width = User_config.dock_icon_size + dpi(20),
forced_height = dpi(10),
id = "fake",
widget = wibox.container.background
}
end
return fake_elements
function dock:get_all_elements()
return elements
end
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
function dock:get_applauncher_starter_element()
return elements['applauncher_starter']
end
---Check if the dock needs to be hidden, I also put the topbar check here since it shares that logic
---@param s screen The screen to check for hide
local function check_for_dock_hide(s)
local clients_on_tag = s.selected_tag:clients()
function dock:get_pinned_elements()
return elements['pinned']
end
function dock:get_running_elements()
return elements['running']
end
function dock:get_dock_for_screen(screen)
return instances[screen]
end
local function check_for_dock_hide(self, a_popup)
if self.cm_open then return end
local clients_on_tag = self.screen.selected_tag:clients()
-- If there is no client on the current tag show the dock
if #clients_on_tag < 1 then
dock.visible = true
self.visible = true
return
end
@@ -338,18 +349,16 @@ return function(screen)
if client.maximized or client.fullscreen then
dock.visible = false
if client.fullscreen then
fakedock.visible = false
capi.awesome.emit_signal("notification_center_activation::toggle", s, false)
a_popup.visible = false
capi.awesome.emit_signal('notification_center_activation::toggle', self.screen, false)
end
elseif not client.fullscreen then
fakedock.visible = true
capi.awesome.emit_signal("notification_center_activation::toggle", s, true)
a_popup.visible = true
capi.awesome.emit_signal('notification_center_activation::toggle', self.screen, true)
end
end
if s == capi.mouse.screen then
if self.screen == capi.mouse.screen then
local minimized = false
for _, c in ipairs(clients_on_tag) do
if c.minimized then
@@ -358,162 +367,229 @@ return function(screen)
minimized = false
local y = c:geometry().y
local h = c.height
if (y + h) >= s.geometry.height - User_config.dock_icon_size - 35 then
dock.visible = false
if (y + h) >= self.screen.geometry.height - User_config.dock_icon_size - 35 then
self.visible = false
return
else
dock.visible = true
self.visible = true
end
end
end
if minimized then
dock.visible = true
self.visible = true
end
else
dock.visible = false
self.visible = false
end
end
function dock:activation_area()
local activation = apopup {
widget = {
width = self.screen.geometry.width / 4,
height = 1,
strategy = 'exact',
widget = wibox.container.constraint,
},
ontop = true,
bg = gcolor.transparent,
visible = false,
screen = self.screen,
type = 'dock',
placement = function(c) aplacement.bottom(c) end,
}
-- Call the function every second to check if the dock needs to be hidden
local dock_intelligent_hide = gears.timer {
local dock_hide = gtimer {
timeout = 1,
autostart = true,
call_now = true,
callback = function()
check_for_dock_hide(screen)
end
check_for_dock_hide(self, activation)
end,
}
--- Hover function to show the dock
fakedock:connect_signal(
"mouse::enter",
function()
if #screen.clients < 1 then
dock.visible = true
dock_intelligent_hide:stop()
activation:connect_signal('mouse::enter', function()
if #self.screen.clients < 1 then
self.visible = true
dock_hide:stop()
return
end
for _, c in ipairs(screen.clients) do
for _, c in ipairs(self.screen.clients) do
if not c.fullscreen then
dock.visible = true
dock_intelligent_hide:stop()
self.visible = true
dock_hide:stop()
end
end
end
)
end)
capi.client.connect_signal(
"manage",
function()
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
self:connect_signal('mouse::enter', function()
dock_hide:stop()
end)
capi.client.connect_signal(
"property::minimized",
function()
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
capi.client.connect_signal(
"unmanage",
function()
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
capi.client.connect_signal(
"focus",
function()
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
capi.awesome.connect_signal(
"dock::changed",
function()
get_dock_elements()
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
capi.awesome.connect_signal(
"dock::check_for_dock_hide",
function()
dock_intelligent_hide:again()
end
)
dock:connect_signal(
"mouse::enter",
function()
dock_intelligent_hide:stop()
end
)
dock:connect_signal(
"mouse::leave",
function()
if cm_open then
self:connect_signal('mouse::leave', function()
--[[ if cm_open then
return
end ]]
check_for_dock_hide(self, activation)
dock_hide:again()
end)
end
check_for_dock_hide(screen)
dock_intelligent_hide:again()
end
)
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
function dock.new(args)
args = args or {}
local w = apopup {
widget = {
{
{
spacing = dpi(5),
id = 'applauncher_starter',
layout = wibox.layout.fixed.horizontal,
},
wibox.widget.separator {
forced_width = dpi(2),
forced_height = dpi(20),
thickness = dpi(2),
color = Theme_config.dock.element.border,
},
{
spacing = dpi(5),
id = 'pinned',
layout = wibox.layout.fixed.horizontal,
},
{
id = 'running',
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
spacing = dpi(10),
id = 'elements',
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin,
margins = dpi(5),
},
ontop = true,
visible = true,
placement = function(c) aplacement.bottom(c, { margins = dpi(10) }) end,
bg = Theme_config.dock.bg,
screen = args.screen,
}
gtable.crush(w, dock)
instances[args.screen] = w
w:activation_area()
w.task_list = awidget.tasklist {
screen = args.screen,
layout = wibox.layout.fixed.horizontal,
filter = awidget.tasklist.filter.alltags,
update_function = function(widget, _, _, _, clients)
widget:reset()
if #clients == 0 then
return widget
end
widget:add {
{
widget = wibox.widget.separator,
forced_height = dpi(20),
forced_width = dpi(2),
thickness = dpi(2),
color = Theme_config.dock.element.border,
},
widget = wibox.container.margin,
right = dpi(5),
}
for _, client in ipairs(clients) do
local element = wibox.widget {
{
{
{
{
widget = wibox.widget.imagebox,
image = client.icon,
valign = 'center',
halign = 'center',
resize = true,
id = 'icon_role',
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size,
height = User_config.dock_icon_size,
},
widget = wibox.container.margin,
margins = dpi(5),
},
widget = wibox.container.constraint,
width = User_config.dock_icon_size + dpi(10), -- + margins
height = User_config.dock_icon_size + dpi(10),
strategy = 'exact',
},
bg = Theme_config.dock.element.bg,
shape = Theme_config.dock.element.shape,
widget = wibox.container.background,
}
hover.bg_hover {
widget = element,
overlay = 12,
press_overlay = 24,
}
element:buttons(gtable.join(
abutton({}, 1, function(c)
if c == client.focus then
c.minimized = true
else
c:emit_signal('request::activate', 'tasklist', { raise = true })
end
end),
abutton({}, 3, function()
amenu.client_list { theme = { width = dpi(250) } }
end)
))
widget:add(element)
widget:set_spacing(dpi(5))
end
return widget
end,
}
w.widget.elements.applauncher_starter:add(w:add_start_element())
w.widget.elements.running:add(w.task_list)
w:connect_signal('dock::element_added', function(_, widget)
w.widget.elements.pinned:add(widget)
end)
w:connect_signal('dock::element_removed', function(_, widget)
w.widget.elements.pinned:remove_widgets(widget)
end)
w:connect_signal('dock::pin_element', function(_, element)
w:get_element_widget(element)
end)
capi.awesome.connect_signal('dock::pin_element', function(args)
w:pin_element(args)
end)
w:connect_signal('dock::unpin_element', function(_, widget)
w:remove_element_widget(widget)
end)
w:read_elements_from_file_async()
return w
end
return setmetatable(dock, { __call = function(_, ...) return dock.new(...) end })

View File

@@ -10,42 +10,42 @@ return function(s)
local widget_table = {}
if widgets then
for _, widget in ipairs(widgets) do
if widget == "Audio" then
table.insert(widget_table, require("src.widgets.audio")(s))
elseif widget == "Battery" then
table.insert(widget_table, require("src.widgets.battery")(User_config.battery_kind))
elseif widget == "Bluetooth" then
table.insert(widget_table, require("src.widgets.bluetooth")(s))
elseif widget == "Clock" then
table.insert(widget_table, require("src.widgets.clock")())
elseif widget == "Cpu Frequency" then
table.insert(widget_table, require("src.widgets.cpu_info")("freq"))
elseif widget == "Cpu Temperature" then
table.insert(widget_table, require("src.widgets.cpu_info")("temp"))
elseif widget == "Cpu Usage" then
table.insert(widget_table, require("src.widgets.cpu_info")("usage"))
elseif widget == "Date" then
table.insert(widget_table, require("src.widgets.date")(s))
elseif widget == "Gpu Temperature" then
table.insert(widget_table, require("src.widgets.gpu_info")("temp"))
elseif widget == "Gpu Usage" then
table.insert(widget_table, require("src.widgets.gpu_info")("usage"))
elseif widget == "Keyboard Layout" then
table.insert(widget_table, require("src.widgets.kblayout")(s))
elseif widget == "Tiling Layout" then
table.insert(widget_table, require("src.widgets.layout_list")())
elseif widget == "Network" then
table.insert(widget_table, require("src.widgets.network") { screen = s })
elseif widget == "Power Button" then
table.insert(widget_table, require("src.widgets.power")())
elseif widget == "Ram Usage" then
table.insert(widget_table, require("src.widgets.ram_info")())
elseif widget == "Systray" then
table.insert(widget_table, require("src.widgets.systray")(s))
elseif widget == "Taglist" then
table.insert(widget_table, require("src.widgets.taglist")(s))
elseif widget == "Tasklist" then
table.insert(widget_table, require("src.widgets.tasklist")(s))
if widget == 'Audio' then
table.insert(widget_table, require('src.widgets.audio')(s))
elseif widget == 'Battery' then
table.insert(widget_table, require('src.widgets.battery')(User_config.battery_kind))
elseif widget == 'Bluetooth' then
table.insert(widget_table, require('src.widgets.bluetooth')(s))
elseif widget == 'Clock' then
table.insert(widget_table, require('src.widgets.clock')())
elseif widget == 'Cpu Frequency' then
table.insert(widget_table, require('src.widgets.cpu_info')('freq'))
elseif widget == 'Cpu Temperature' then
table.insert(widget_table, require('src.widgets.cpu_info')('temp'))
elseif widget == 'Cpu Usage' then
table.insert(widget_table, require('src.widgets.cpu_info')('usage'))
elseif widget == 'Date' then
table.insert(widget_table, require('src.widgets.date')(s))
elseif widget == 'Gpu Temperature' then
table.insert(widget_table, require('src.widgets.gpu_info')('temp'))
elseif widget == 'Gpu Usage' then
table.insert(widget_table, require('src.widgets.gpu_info')('usage'))
elseif widget == 'Keyboard Layout' then
table.insert(widget_table, require('src.widgets.kblayout')(s))
elseif widget == 'Tiling Layout' then
table.insert(widget_table, require('src.widgets.layout_list')())
elseif widget == 'Network' then
table.insert(widget_table, require('src.widgets.network') { screen = s })
elseif widget == 'Power Button' then
table.insert(widget_table, require('src.widgets.power')())
elseif widget == 'Ram Usage' then
table.insert(widget_table, require('src.widgets.ram_info')())
elseif widget == 'Systray' then
table.insert(widget_table, require('src.widgets.systray')())
elseif widget == 'Taglist' then
table.insert(widget_table, require('src.widgets.taglist')(s))
elseif widget == 'Tasklist' then
table.insert(widget_table, require('src.widgets.tasklist')(s))
end
end
end
@@ -56,16 +56,16 @@ return function(s)
for index, screen in ipairs(User_config.crylia_bar) do
if index == s.index then
if screen.left_bar then
require("src.modules.crylia_bar.left_bar")(s, get_widgets(screen.left_bar))
require('src.modules.crylia_bar.left_bar')(s, get_widgets(screen.left_bar))
end
if screen.center_bar then
require("src.modules.crylia_bar.center_bar")(s, get_widgets(screen.center_bar))
require('src.modules.crylia_bar.center_bar')(s, get_widgets(screen.center_bar))
end
if screen.right_bar then
require("src.modules.crylia_bar.right_bar")(s, get_widgets(screen.right_bar))
require('src.modules.crylia_bar.right_bar')(s, get_widgets(screen.right_bar))
end
end
end
end
require("src.modules.crylia_bar.dock")(s)
require('src.modules.crylia_bar.dock') { screen = s }
end

View File

@@ -2,16 +2,15 @@
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local wibox = require("wibox")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
return function(s, w)
local function prepare_widgets(widgets)
local layout = {
forced_height = dpi(50),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
}
for i, widget in pairs(widgets) do
if i == 1 then
@@ -22,7 +21,7 @@ return function(s, w)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
elseif i == #widgets then
table.insert(layout,
@@ -32,7 +31,7 @@ return function(s, w)
right = dpi(6),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
else
table.insert(layout,
@@ -42,7 +41,7 @@ return function(s, w)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
end
end
@@ -56,11 +55,11 @@ return function(s, w)
bg = Theme_config.left_bar.bg,
visible = true,
maximum_width = dpi(650),
placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end
placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end,
}
top_left:struts {
top = dpi(55)
top = dpi(55),
}
Global_config.top_struts = dpi(55)

View File

@@ -2,16 +2,15 @@
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local wibox = require("wibox")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
return function(s, w)
local function prepare_widgets(widgets)
local layout = {
forced_height = dpi(50),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
}
for i, widget in pairs(widgets) do
if i == 1 then
@@ -22,7 +21,7 @@ return function(s, w)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
elseif i == #widgets then
table.insert(layout,
@@ -32,7 +31,7 @@ return function(s, w)
right = dpi(6),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
else
table.insert(layout,
@@ -42,7 +41,7 @@ return function(s, w)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
end
end
@@ -55,11 +54,11 @@ return function(s, w)
bg = Theme_config.right_bar.bg,
visible = true,
screen = s,
placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end
placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end,
}
top_right:struts {
top = dpi(55)
top = dpi(55),
}
Global_config.top_struts = top_right

View File

@@ -1,9 +1,9 @@
--------------------------------------------------------------------------------------------------------------
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
local wibox = require("wibox")
local dpi = require("beautiful").xresources.apply_dpi
local gshape = require("gears.shape")
local wibox = require('wibox')
local dpi = require('beautiful').xresources.apply_dpi
local gshape = require('gears.shape')
return function(s)
---Lookup function to return the widget from its easy name string
@@ -13,42 +13,42 @@ return function(s)
local widget_table = {}
if widgets then
for _, widget in ipairs(widgets) do
if widget == "Audio" then
table.insert(widget_table, require("src.widgets.audio")(s))
elseif widget == "Battery" then
table.insert(widget_table, require("src.widgets.battery")(User_config.battery_kind))
elseif widget == "Bluetooth" then
table.insert(widget_table, require("src.widgets.bluetooth")())
elseif widget == "Clock" then
table.insert(widget_table, require("src.widgets.clock")())
elseif widget == "Cpu Frequency" then
table.insert(widget_table, require("src.widgets.cpu_info")("freq", User_config.cpu_frequency))
elseif widget == "Cpu Temperature" then
table.insert(widget_table, require("src.widgets.cpu_info")("temp"))
elseif widget == "Cpu Usage" then
table.insert(widget_table, require("src.widgets.cpu_info")("usage"))
elseif widget == "Date" then
table.insert(widget_table, require("src.widgets.date")())
elseif widget == "Gpu Temperature" then
table.insert(widget_table, require("src.widgets.gpu_info")("temp"))
elseif widget == "Gpu Usage" then
table.insert(widget_table, require("src.widgets.gpu_info")("usage"))
elseif widget == "Keyboard Layout" then
table.insert(widget_table, require("src.widgets.kblayout")(s))
elseif widget == "Tiling Layout" then
table.insert(widget_table, require("src.widgets.layout_list")())
elseif widget == "Network" then
table.insert(widget_table, require("src.widgets.network")())
elseif widget == "Power Button" then
table.insert(widget_table, require("src.widgets.power")())
elseif widget == "Ram Usage" then
table.insert(widget_table, require("src.widgets.ram_info")())
elseif widget == "Systray" then
table.insert(widget_table, require("src.widgets.systray")(s))
elseif widget == "Taglist" then
table.insert(widget_table, require("src.widgets.taglist")(s))
elseif widget == "Tasklist" then
table.insert(widget_table, require("src.widgets.tasklist")(s))
if widget == 'Audio' then
table.insert(widget_table, require('src.widgets.audio')(s))
elseif widget == 'Battery' then
table.insert(widget_table, require('src.widgets.battery')(User_config.battery_kind))
elseif widget == 'Bluetooth' then
table.insert(widget_table, require('src.widgets.bluetooth')())
elseif widget == 'Clock' then
table.insert(widget_table, require('src.widgets.clock')())
elseif widget == 'Cpu Frequency' then
table.insert(widget_table, require('src.widgets.cpu_info')('freq', User_config.cpu_frequency))
elseif widget == 'Cpu Temperature' then
table.insert(widget_table, require('src.widgets.cpu_info')('temp'))
elseif widget == 'Cpu Usage' then
table.insert(widget_table, require('src.widgets.cpu_info')('usage'))
elseif widget == 'Date' then
table.insert(widget_table, require('src.widgets.date')())
elseif widget == 'Gpu Temperature' then
table.insert(widget_table, require('src.widgets.gpu_info')('temp'))
elseif widget == 'Gpu Usage' then
table.insert(widget_table, require('src.widgets.gpu_info')('usage'))
elseif widget == 'Keyboard Layout' then
table.insert(widget_table, require('src.widgets.kblayout')(s))
elseif widget == 'Tiling Layout' then
table.insert(widget_table, require('src.widgets.layout_list')())
elseif widget == 'Network' then
table.insert(widget_table, require('src.widgets.network')())
elseif widget == 'Power Button' then
table.insert(widget_table, require('src.widgets.power')())
elseif widget == 'Ram Usage' then
table.insert(widget_table, require('src.widgets.ram_info')())
elseif widget == 'Systray' then
table.insert(widget_table, require('src.widgets.systray')())
elseif widget == 'Taglist' then
table.insert(widget_table, require('src.widgets.taglist')(s))
elseif widget == 'Tasklist' then
table.insert(widget_table, require('src.widgets.tasklist')(s))
end
end
end
@@ -61,7 +61,7 @@ return function(s)
local function prepare_widgets(widgets)
local layout = {
forced_height = dpi(50),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
}
for i, widget in pairs(widgets) do
if i == 1 then
@@ -72,7 +72,7 @@ return function(s)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
elseif i == #widgets then
table.insert(layout,
@@ -82,7 +82,7 @@ return function(s)
right = dpi(6),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
else
table.insert(layout,
@@ -92,7 +92,7 @@ return function(s)
right = dpi(3),
top = dpi(6),
bottom = dpi(6),
widget = wibox.container.margin
widget = wibox.container.margin,
})
end
end
@@ -109,17 +109,17 @@ return function(s)
visible = true,
x = 0,
y = 1035,
type = "desktop",
type = 'desktop',
height = dpi(55),
width = 1920,
bg = "#212121",
bg = '#212121',
shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, 8)
end,
}
w:struts {
bottom = dpi(55)
bottom = dpi(55),
}
Global_config.bottom_struts = dpi(55)

View File

@@ -1,52 +0,0 @@
local base = require("wibox.widget.base")
local awful = require("awful")
local gtable = require("gears.table")
local gfilesystem = require("gears.filesystem")
local gcolor = require("gears.color")
local wibox = require("wibox")
local dpi = require("beautiful").xresources.apply_dpi
local gobject = require("gears.object")
local cm = require("src.modules.context_menu.init")
local capi = {
awesome = awesome
}
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/"
local context_menu = { mt = {} }
context_menu._private = {}
function context_menu:toggle()
self._private.popup.x = mouse.coords().x - 10
self._private.popup.y = mouse.coords().y - 10
self._private.popup.visible = not self._private.popup.visible
end
function context_menu.new(args)
args = args or {}
local ret = gobject {}
gtable.crush(ret, context_menu, true)
capi.awesome.connect_signal("context_menu:show", function()
ret:toggle()
mousegrabber.run(function()
if mouse.current_wibox ~= ret._private.popup then
ret:toggle()
return false
end
return true
end, nil)
end)
return ret
end
function context_menu.mt:__call(...)
return context_menu.new(...)
end
return setmetatable(context_menu, context_menu.mt)

View File

@@ -1,33 +1,30 @@
local base = require("wibox.widget.base")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears.table")
local gshape = require("gears.shape")
local grid = require("wibox.layout.grid")
local wibox = require("wibox")
local abutton = require("awful.button")
local awful = require("awful")
local gcolor = require("gears.color")
local json = require("src.lib.json-lua.json-lua")
local gfilesystem = require("gears.filesystem")
local Gio = require("lgi").Gio
local Gio = require('lgi').Gio
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local grid = require('wibox.layout.grid')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local wibox = require('wibox')
local element = require("src.modules.desktop.element")
local cm = require("src.modules.context_menu.init")
local config = require('src.tools.config')
local element = require('src.modules.desktop.element')
local cm = require('src.modules.context_menu.init')
local capi = {
mouse = mouse,
awesome = awesome,
screen = screen,
}
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/desktop/'
local desktop = { mt = {} }
function desktop:save_layout()
local layout = {}
local dir = gfilesystem.get_configuration_dir() .. "src/config/files/desktop/icons/"
local dir = gfilesystem.get_configuration_dir() .. 'src/config/files/desktop/icons/'
if not gfilesystem.dir_readable(dir) then
gfilesystem.make_directories(dir)
end
@@ -40,54 +37,45 @@ function desktop:save_layout()
col = pos.col,
widget = {
icon = widget.icon,
label = widget:get_children_by_id("text_role")[1].text,
label = widget.label,
exec = widget.exec,
icon_size = widget.icon_size
}
icon_size = widget.icon_size,
},
}
end
dir = gfilesystem.get_configuration_dir() .. "src/config"
dir = gfilesystem.get_configuration_dir() .. 'src/config/desktop.json'
gfilesystem.make_directories(dir)
if not gfilesystem.file_readable(dir .. "/desktop.json") then
os.execute("touch " .. dir .. "/desktop.json")
end
local handler = io.open(dir .. "/desktop.json", "w")
if not handler then return end
handler:write(json:encode(layout))
handler:close()
config.write_json(dir, layout)
end
function desktop:load_layout()
local dir = gfilesystem.get_configuration_dir() .. "src/config"
if not gfilesystem.file_readable(dir .. "/desktop.json") then
return
end
local handler = io.open(dir .. "/desktop.json", "r")
if not handler then return end
local dir = gfilesystem.get_configuration_dir() .. 'src/config/desktop.json'
if not gfilesystem.file_readable(dir) then return end
local layout = json:decode(handler:read("*all"))
handler:close()
if not layout then return end
for i, value in pairs(layout) do
local data = config.read_json(dir)
if not data then return end
for _, value in pairs(data) do
self:add_element(value.widget, { x = value.row, y = value.col })
end
end
function desktop:get_element_at(x, y)
return self.widget.mrgn.grid:get_widgets_at(x, y)[1]
local w = self.widget.mrgn.grid:get_widgets_at(x, y)
return w and w[1] or nil
end
function desktop:add_desktop_file(app_info)
self:add_element({
self:add_element {
icon = app_info.icon,
label = app_info.label,
exec = app_info.exec,
icon_size = dpi(96),
icon_size = dpi(48),
desktop_file = app_info.desktop_file,
parent = self.widget.mrgn.grid,
})
width = self.widget_width,
height = self.widget_height,
}
end
--[[
@@ -98,18 +86,17 @@ function desktop:remove_element(e)
end
function desktop:get_grid_index_at(y, x)
local col, row = 1, 1
local margin_x, margin_y = dpi(10), dpi(10)
local screen_width, screen_height = self.args.screen.geometry.width - margin_x * 2, self.args.screen.geometry.height - dpi(75) - dpi(95) - margin_y * 2
local cell_width, cell_height = screen_width / 20, screen_height / 11
local width = dpi(96) * 1.75 * (4 / 3)
local height = dpi(96) * 1.75
local spacing = dpi(10)
local col = math.floor((x - margin_x) / cell_width) + 1
col = math.min(col, 20)
col = math.max(col, 1)
while width * col + spacing * (col - 1) < x do
col = col + 1
end
while height * row + spacing * (row - 1) < y do
row = row + 1
end
local row = math.floor((y - margin_y) / cell_height) + 1
row = math.min(row, 11)
row = math.max(row, 1)
return col, row
end
@@ -133,7 +120,9 @@ function desktop:add_element(args, pos)
exec = args.exec,
icon_size = args.icon_size,
desktop_file = args.desktop_file,
parent = args.parent
parent = args.parent,
width = self.widget_width,
height = self.widget_height,
}
local cm_popup = cm {
@@ -144,106 +133,98 @@ function desktop:add_element(args, pos)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
},
spacing = dpi(10),
entries = {
{
name = "Open with",
icon = gcolor.recolor_image(icondir .. "launch.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Open with',
icon = gcolor.recolor_image(icondir .. 'launch.svg', Theme_config.desktop.context_menu.icon_color),
submenu = {
--!TODO: Fetch programs and add them as entries
}
},
},
{
name = "Copy",
icon = gcolor.recolor_image(icondir .. "copy.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Copy',
icon = gcolor.recolor_image(icondir .. 'copy.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
end
end,
},
{
name = "Cut",
icon = gcolor.recolor_image(icondir .. "cut.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Cut',
icon = gcolor.recolor_image(icondir .. 'cut.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
end
end,
},
{
name = "Rename",
icon = gcolor.recolor_image(icondir .. "edit.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Rename',
icon = gcolor.recolor_image(icondir .. 'edit.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
end
end,
},
{
name = "Remove",
icon = gcolor.recolor_image(icondir .. "delete.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Remove',
icon = gcolor.recolor_image(icondir .. 'delete.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
self:remove_element(e)
self:save_layout()
end
end,
},
{
name = "Actions",
icon = gcolor.recolor_image(icondir .. "dots-vertical.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Actions',
icon = gcolor.recolor_image(icondir .. 'dots-vertical.svg', Theme_config.desktop.context_menu.icon_color),
submenu = {
-- TODO: fetch actions from desktop file
}
},
},
},
}
}
cm_popup:connect_signal("mouse::leave", function()
cm_popup:connect_signal('mouse::leave', function()
cm_popup.visible = false
end)
local cols = math.floor(self.args.screen.geometry.width / (args.icon_size * 1.75 * (4 / 3)))
local rows = math.floor((self.args.screen.geometry.height - 75 + 95) / (args.icon_size * 1.75))
print(cols, rows)
-- While the mouse is down, remove the element from the grid and add it to manual then move it
-- until the mouse is released and then add it back to the grid.
e:connect_signal("button::press", function(_, _, _, b)
local start_pos = mouse.coords()
e:connect_signal('button::press', function(_, _, _, b)
if not mousegrabber.isrunning() then
local width = (self.args.screen.geometry.width - 20 - ((cols - 1) * 10)) / cols
local height = (self.args.screen.geometry.height - 170 - 20) / rows
local dnd_widget = element {
icon = args.icon,
label = args.label,
on_click = args.on_click,
exec = args.exec,
icon_size = args.icon_size,
desktop_file = args.desktop_file,
parent = args.parent,
width = width,
height = height,
width = self.widget_width,
height = self.widget_height,
}
dnd_widget.visible = false
dnd_widget:get_children_by_id("icon_role")[1].opacity = 0.6
local xp, yp = capi.mouse.coords()
dnd_widget.point = { x = xp, y = yp }
dnd_widget:get_children_by_id('icon_role')[1].opacity = 0.6
local start_pos = capi.mouse.coords()
dnd_widget.point = { x = math.floor(start_pos.x - self.args.screen.geometry.x), y = math.floor(start_pos.y - self.args.screen.geometry.y) }
local old_pos = self.widget.mrgn.grid:get_widget_position(e)
self.widget.manual:add(dnd_widget)
mousegrabber.run(function(m)
@@ -254,22 +235,29 @@ function desktop:add_element(args, pos)
m.buttons[1] then
self:remove_element(e)
dnd_widget.visible = true
dnd_widget.bg = gcolor("#0ffff088")
dnd_widget.border_color = gcolor("#0ffff0")
self.widget.manual:move_widget(dnd_widget, { x = m.x - dnd_widget.width / 2, y = m.y - dnd_widget.height / 2 })
dnd_widget.bg = gcolor('#0ffff088')
dnd_widget.border_color = gcolor('#0ffff0')
self.widget.manual:move_widget(dnd_widget, {
x = (m.x - dnd_widget.width / 2) - self.args.screen.geometry.x,
y = (m.y - dnd_widget.height / 2) - self.args.screen.geometry.y,
})
end
if not m.buttons[1] then
if b == 1 then
dnd_widget.bg = gcolor("#0ffff088")
dnd_widget.border_color = gcolor("#0ffff0")
dnd_widget.bg = gcolor('#0ffff088')
dnd_widget.border_color = gcolor('#0ffff0')
if dnd_widget.visible then
dnd_widget.visible = false
local np_x, np_y = self:get_grid_index_at(m.y, m.x)
if not self.widget.mrgn.grid:get_widgets_at(np_y, np_x) then
self.widget.mrgn.grid:add_widget_at(e, np_y, np_x)
local newp_x, newp_y = self:get_grid_index_at(
(m.y - dnd_widget.height / 2) - self.args.screen.geometry.y,
(m.x - dnd_widget.width / 2) - self.args.screen.geometry.x
)
if not self.widget.mrgn.grid:get_widgets_at(newp_y, newp_x) then
self.widget.mrgn.grid:add_widget_at(e, newp_y, newp_x)
self:save_layout()
else
self.widget.mrgn.grid:add_widget_at(e, old_pos.row, old_pos.col)
@@ -286,7 +274,7 @@ function desktop:add_element(args, pos)
end
return m.buttons[1]
end, "left_ptr")
end, 'left_ptr')
end
end)
@@ -299,62 +287,83 @@ function desktop:draw_selector()
if not mousegrabber.isrunning() then
local selector = wibox.widget {
widget = wibox.container.background,
bg = gcolor("#0ffff088"),
border_color = gcolor("#0ffff0"),
bg = gcolor('#0ffff088'),
border_color = gcolor('#0ffff0'),
border_width = dpi(2),
forced_width = 0,
forced_height = 0,
x = start_pos.x,
y = start_pos.y,
x = start_pos.x - self.args.screen.geometry.x,
y = start_pos.y - self.args.screen.geometry.y,
visible = true,
shape = function(cr, w, h)
gshape.rounded_rect(cr, w, h, dpi(10))
end
end,
}
selector.point = { x = start_pos.x, y = start_pos.y }
selector.point = { x = start_pos.x - self.args.screen.geometry.x, y = start_pos.y - self.args.screen.geometry.y }
self.widget.manual:add(selector)
mousegrabber.run(function(m)
if m.buttons[1] then
selector.visible = true
end
if not m.buttons[1] then
print("stop")
mousegrabber.stop()
selector.visible = false
self.widget.manual:reset()
end
selector.forced_width = selector.forced_width + ((start_pos.x - m.x) * -1)
selector.forced_height = selector.forced_width + ((start_pos.y - m.y) * -1)
print(selector.forced_width, selector.forced_height)
local dx = m.x - start_pos.x
local dy = m.y - start_pos.y
local gx, gy = self:get_grid_index_at(math.abs(dy), math.abs(dx))
selector.forced_width = math.abs(dx)
selector.forced_height = math.abs(dy)
--if the mouse is moving to the left, move the widget to the left
if dx < 0 then
selector.x = start_pos.x - self.args.screen.geometry.x + dx
selector.point.x = start_pos.x - self.args.screen.geometry.x + dx
gx, gy = self:get_grid_index_at(selector.point.y, selector.point.x)
end
--if the mouse is moving up, move the widget up
if dy < 0 then
selector.y = start_pos.y - self.args.screen.geometry.y + dy
selector.point.y = start_pos.y - self.args.screen.geometry.y + dy
gx, gy = self:get_grid_index_at(selector.point.y, selector.point.x)
end
-- check if a widget is inside the selector
local w = self:get_element_at(gx, gy)
if w then
w.bg = gcolor('#0ffff088')
w.border_color = gcolor('#0ffff0')
end
return m.buttons[1]
end, "left_ptr")
end, 'left_ptr')
end
end
function desktop:add_xdg()
self:add_element({
icon = "/usr/share/icons/Papirus-Dark/96x96/places/user-trash.svg",
label = "Papierkorb",
exec = "nautilus trash:/",
icon_size = 96,
})
self:add_element {
icon = '/usr/share/icons/Papirus-Dark/96x96/places/user-trash.svg',
label = 'Papierkorb',
exec = 'nautilus trash:/',
icon_size = dpi(48),
}
self:add_element({
icon = "/usr/share/icons/Papirus-Dark/96x96/places/user-home.svg",
label = "Persönlicher Ordner",
exec = "nautilus file:/home/crylia",
icon_size = 96,
})
self:add_element {
icon = '/usr/share/icons/Papirus-Dark/96x96/places/user-home.svg',
label = 'Persönlicher Ordner',
exec = 'nautilus file:/home/crylia',
icon_size = dpi(48),
}
end
function desktop.new(args)
args = args or {}
local icon_size = args.icon_size or dpi(96)
args.icon_size = dpi(48)
local rows = 20
local cols = 11
local h_spacing = dpi(10)
local v_spacing = dpi(20)
local cols = math.floor(args.screen.geometry.width / (icon_size * 1.75 * (4 / 3)))
local rows = math.floor((args.screen.geometry.height - 75 + 95) / (icon_size * 1.75))
--[[
The wibox has a stacked layout with a manual layout over a grid.
@@ -368,10 +377,10 @@ function desktop.new(args)
local w = wibox {
ontop = false,
visible = true,
type = "desktop",
type = 'desktop',
input_passthrough = false,
x = 0,
y = 0,
x = args.screen.geometry.x,
y = args.screen.geometry.y,
bg = gcolor.transparent,
width = args.screen.geometry.width,
height = args.screen.geometry.height,
@@ -381,26 +390,27 @@ function desktop.new(args)
{
layout = grid,
homogeneous = true,
spacing = 10,
expand = true,
orientation = "horizontal",
forced_num_cols = cols,
forced_num_rows = rows,
id = "grid",
horizontal_spacing = h_spacing,
vertical_spacing = v_spacing,
expand = false,
orientation = 'horizontal',
forced_num_cols = rows,
forced_num_rows = cols,
id = 'grid',
},
widget = wibox.container.margin,
left = dpi(10),
right = dpi(10),
top = dpi(75),
bottom = dpi(95),
id = "mrgn"
id = 'mrgn',
},
{
layout = wibox.layout.manual,
id = "manual",
id = 'manual',
},
layout = wibox.layout.stack,
}
},
}
w.args = args
@@ -413,158 +423,158 @@ function desktop.new(args)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
},
spacing = dpi(10),
entries = {
{
name = "Create new",
icon = gcolor.recolor_image(icondir .. "file_add.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Create new',
icon = gcolor.recolor_image(icondir .. 'file_add.svg', Theme_config.desktop.context_menu.icon_color),
submenu = {
{
name = "Folder",
icon = gcolor.recolor_image(icondir .. "folder.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Folder',
icon = gcolor.recolor_image(icondir .. 'folder.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
--create a new folder and if it exists add a number to the end
local folder_name = "New folder"
local folder_path = os.getenv("HOME") .. "/Desktop/" .. folder_name
local folder_name = 'New folder'
local folder_path = os.getenv('HOME') .. '/Desktop/' .. folder_name
local i = 1
while gfilesystem.dir_readable(folder_path) do
folder_name = "New folder " .. "(" .. i .. ")"
folder_path = os.getenv("HOME") .. "/Desktop/" .. folder_name
folder_name = 'New folder ' .. '(' .. i .. ')'
folder_path = os.getenv('HOME') .. '/Desktop/' .. folder_name
i = i + 1
end
gfilesystem.make_directories(folder_path)
w:add_element({
icon = "/usr/share/icons/Papirus-Dark/24x24/places/folder.svg",
w:add_element {
icon = '/usr/share/icons/Papirus-Dark/24x24/places/folder.svg',
label = folder_name,
exec = "nautilus file:\"" .. folder_path .. "\"",
icon_size = icon_size,
})
end
exec = 'nautilus file:\"' .. folder_path .. '\"',
icon_size = dpi(48),
}
end,
},
{
name = "File",
icon = gcolor.recolor_image(icondir .. "file.svg", Theme_config.desktop.context_menu.icon_color),
name = 'File',
icon = gcolor.recolor_image(icondir .. 'file.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
--create new text file and if it exists add a number to the end
local file_name = "New file.txt"
local file_path = os.getenv("HOME") .. "/Desktop/" .. file_name
local file_name = 'New file.txt'
local file_path = os.getenv('HOME') .. '/Desktop/' .. file_name
local i = 1
while gfilesystem.file_readable(file_path) do
file_name = "New file " .. "(" .. i .. ")"
file_path = os.getenv("HOME") .. "/Desktop/" .. file_name
file_name = 'New file ' .. '(' .. i .. ')'
file_path = os.getenv('HOME') .. '/Desktop/' .. file_name
i = i + 1
end
awful.spawn.with_shell("touch " .. file_path)
w:add_element({
icon = "/usr/share/icons/Papirus-Dark/24x24/mimetypes/text-plain.svg",
awful.spawn.with_shell('touch ' .. file_path)
w:add_element {
icon = '/usr/share/icons/Papirus-Dark/24x24/mimetypes/text-plain.svg',
label = file_name,
exec = "xdg-open " .. file_path,
icon_size = icon_size,
})
end
}
exec = 'xdg-open ' .. file_path,
icon_size = dpi(48),
}
end,
},
},
},
{
name = "Terminal",
icon = gcolor.recolor_image(icondir .. "terminal.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Terminal',
icon = gcolor.recolor_image(icondir .. 'terminal.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.terminal)
end
end,
},
{
name = "Web Browser",
icon = gcolor.recolor_image(icondir .. "web_browser.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Web Browser',
icon = gcolor.recolor_image(icondir .. 'web_browser.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.web_browser)
end
end,
},
{
name = "File Manager",
icon = gcolor.recolor_image(icondir .. "file_manager.svg", Theme_config.desktop.context_menu.icon_color),
name = 'File Manager',
icon = gcolor.recolor_image(icondir .. 'file_manager.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.file_manager)
end
end,
},
{
name = "Text Editor",
icon = gcolor.recolor_image(icondir .. "text_editor.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Text Editor',
icon = gcolor.recolor_image(icondir .. 'text_editor.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.text_editor)
end
end,
},
{
name = "Music Player",
icon = gcolor.recolor_image(icondir .. "music_player.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Music Player',
icon = gcolor.recolor_image(icondir .. 'music_player.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.music_player)
end
end,
},
{
name = "Applications",
icon = gcolor.recolor_image(icondir .. "application.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Applications',
icon = gcolor.recolor_image(icondir .. 'application.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
end
end,
},
{
name = "GTK Settings",
icon = gcolor.recolor_image(icondir .. "gtk_settings.svg", Theme_config.desktop.context_menu.icon_color),
name = 'GTK Settings',
icon = gcolor.recolor_image(icondir .. 'gtk_settings.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.gtk_settings)
end
end,
},
{
name = "Energy Settings",
icon = gcolor.recolor_image(icondir .. "energy_settings.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Energy Settings',
icon = gcolor.recolor_image(icondir .. 'energy_settings.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.energy_manager)
end
end,
},
{
name = "Screen Settings",
icon = gcolor.recolor_image(icondir .. "screen_settings.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Screen Settings',
icon = gcolor.recolor_image(icondir .. 'screen_settings.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
awful.spawn(User_config.screen_settings)
end
end,
},
{
name = "Reload Awesome",
icon = gcolor.recolor_image(icondir .. "refresh.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Reload Awesome',
icon = gcolor.recolor_image(icondir .. 'refresh.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
capi.awesome.restart()
end
end,
},
{
name = "Quit",
icon = gcolor.recolor_image(icondir .. "quit.svg", Theme_config.desktop.context_menu.icon_color),
name = 'Quit',
icon = gcolor.recolor_image(icondir .. 'quit.svg', Theme_config.desktop.context_menu.icon_color),
callback = function()
capi.awesome.quit()
end
end,
},
--cm_awesome
}
},
}
w.widget.manual:buttons(gtable.join(
@@ -583,9 +593,12 @@ function desktop.new(args)
gtable.crush(w, desktop, true)
w.widget_width = (args.screen.geometry.width - 20 - ((h_spacing - 1) * rows)) / rows
w.widget_height = (args.screen.geometry.height - 170 - ((v_spacing - 1) * cols)) / cols
w:load_layout()
capi.awesome.connect_signal("desktop::add_to_desktop", function(args2)
capi.awesome.connect_signal('desktop::add_to_desktop', function(args2)
w:add_desktop_file(args2)
end)

View File

@@ -1,17 +1,11 @@
local base = require("wibox.widget.base")
local wibox = require("wibox")
local gtable = require("gears.table")
local dpi = require("beautiful").xresources.apply_dpi
local gshape = require("gears.shape")
local gfilesystem = require("gears.filesystem")
local gcolor = require("gears.color")
local abutton = require("awful.button")
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/desktop/"
local capi = {
mouse = mouse
}
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local lgi = require('lgi')
local cairo = lgi.cairo
local wibox = require('wibox')
local element = { mt = {} }
@@ -34,30 +28,174 @@ function element:get_widget()
end
function element:on_hover()
self:connect_signal("mouse::enter", function()
self.bg = "#0ffff033"
self.border_color = "#0ffff099"
self:connect_signal('mouse::enter', function()
self.bg = '#0ffff033'
self.border_color = '#0ffff099'
end)
--[[ self:connect_signal("mouse::leave", function()
self:connect_signal('mouse::leave', function()
self.bg = gcolor.transparent
self.border_color = gcolor.transparent
end) ]]
self:connect_signal("button::press", function()
self.bg = "#0ffff088"
self.border_color = "#0ffff0dd"
end)
self:connect_signal("button::release", function()
self.bg = "#0ffff033"
self.border_color = "#0ffff099"
self:connect_signal('button::press', function()
self.bg = '#0ffff088'
self.border_color = '#0ffff0dd'
end)
self:connect_signal('button::release', function()
self.bg = '#0ffff033'
self.border_color = '#0ffff099'
end)
end
---Get the cairo extents for any text with its give size and font
---@param font string A font
---@param font_size number Font size
---@param text string Text to get the extent for
---@param args table Additional arguments
---@return userdata cairo.Extent
local function cairo_text_extents(font, font_size, text, args)
local surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 0, 0)
local cr = cairo.Context(surface)
cr:select_font_face(font, cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
cr:set_font_size(font_size)
cr:set_antialias(cairo.Antialias.BEST)
return cr:text_extents(text)
end
local function split_string(str, max_width)
local line1 = ''
local line2 = ''
local line1_width = 0
local line2_width = 0
local font = 'JetBrainsMono Nerd Font'
local font_size = dpi(16)
local font_args = { cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD }
for word in str:gmatch('%S+') do
local word_width = cairo_text_extents(font, font_size, word, font_args).width
if line1_width + word_width < max_width then
line1 = line1 .. word .. ' '
line1_width = line1_width + word_width
else
line2 = line2 .. word .. ' '
line2_width = line2_width + word_width
end
end
return line1, line2
end
---This function takes any text and uses cairo to draw an outline and a shadow
---It also wraps the text correctly if max_width would be violated. It only uses two lines for wraping
---the rest is cut off.
---@param text string Text to be changed
---@param max_width number max width the text won't go over
---@return cairo.Surface cairo_surface manupulated text as a cairo surface
---@return table `width`,`height` The surface dimensions
local function outlined_text(text, max_width)
local font = 'JetBrainsMono Nerd Font'
local font_size = dpi(16)
local spacing = dpi(5)
local margin = dpi(5)
max_width = max_width - (margin * 2)
local shadow_offset_x, shadow_offset_y = 1, 1
local font_args = { cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD }
-- Get the dimensions from the text
local extents = cairo_text_extents(font, font_size, text, font_args)
-- if its bigger it needs special treatment
if extents.width > max_width then
local line1, line2 = split_string(text, max_width)
-- Get the dimensions for both lines
local extents1 = cairo_text_extents(font, font_size, line1, font_args)
local extents2 = cairo_text_extents(font, font_size, line2, font_args)
-- The surface width will be the biggest of the two lines
local s_width = extents1.width
if extents1.width < extents2.width then
s_width = extents2.width
end
-- Create a new surface based on the widest line, and both line's height + the spacing between them and the shadow offset
local surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, s_width + shadow_offset_x, extents1.height + extents2.height + spacing + (shadow_offset_y * 3))
local cr = cairo.Context(surface)
-- Create the font with best antialias
cr:select_font_face(font, cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
cr:set_font_size(font_size)
cr:set_antialias(cairo.Antialias.BEST)
-- To center both lines get the surface center then substract half the line width
local text_x = s_width / 2 - ((extents1.width) / 2)
local text_x2 = s_width / 2 - ((extents2.width) / 2)
-- This makes the first text to be blow the main text
cr:set_operator(cairo.Operator.OVER)
-- Draw the text shadow
cr:move_to(text_x + shadow_offset_x, -extents1.y_bearing + shadow_offset_y)
cr:set_source_rgba(0, 0, 0, 0.5)
cr:show_text(line1)
cr:set_operator(cairo.Operator.OVER)
-- Draw the second shadow
cr:move_to(text_x2 + shadow_offset_x, extents1.height + extents2.height + spacing + shadow_offset_y)
cr:set_source_rgba(0, 0, 0, 0.5)
cr:show_text(line2)
-- Draw the first and second line
cr:move_to(text_x, -extents1.y_bearing)
cr:set_source_rgb(1, 1, 1)
cr:text_path(line1)
cr:move_to(text_x2, extents1.height + extents2.height + spacing)
cr:text_path(line2)
-- Color it and set the stroke
cr:fill_preserve()
cr:set_source_rgb(0, 0, 0)
cr:set_line_width(0.1)
cr:stroke()
return surface, { width = extents.width, height = extents1.height + extents2.height + spacing }
else
-- The size is the dimension from above the if
local surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, extents.width, extents.height + shadow_offset_y)
local cr = cairo.Context(surface)
-- Set the font, then draw the text and its stroke
cr:select_font_face(font, cairo.FontSlant.NORMAL, cairo.FontWeight.BOLD)
cr:set_font_size(font_size)
-- This makes the first text to be blow the main text
cr:set_operator(cairo.Operator.OVER)
-- Draw the text shadow
cr:move_to(-extents.x_bearing + shadow_offset_x, -extents.y_bearing + shadow_offset_y)
cr:set_source_rgba(0, 0, 0, 0.5)
cr:show_text(text)
cr:move_to(-extents.x_bearing, -extents.y_bearing)
cr:set_source_rgb(1, 1, 1)
cr:text_path(text)
cr:fill_preserve()
cr:set_source_rgb(0, 0, 0)
cr:set_line_width(0.1)
cr:stroke()
return surface, { width = extents.width, height = extents.height }
end
end
function element.new(args)
args = args or {}
local text_img, size = outlined_text(args.label, args.width)
local w = base.make_widget_from_value(wibox.widget {
{
{
@@ -66,31 +204,34 @@ function element.new(args)
image = args.icon,
resize = true,
clip_shape = gshape.rounded_rect,
valign = "center",
halign = "center",
id = "icon_role",
widget = wibox.widget.imagebox
valign = 'top',
halign = 'center',
id = 'icon_role',
forced_width = args.icon_size,
forced_height = args.icon_size,
widget = wibox.widget.imagebox,
},
strategy = "exact",
height = args.icon_size,
width = args.icon_size,
widget = wibox.container.constraint
widget = wibox.container.margin,
top = dpi(5),
left = dpi(20),
right = dpi(20),
bottom = dpi(5),
},
{
text = args.label,
id = "text_role",
valign = "center",
halign = "center",
widget = wibox.widget.textbox
image = text_img,
resize = false,
valign = 'bottom',
halign = 'center',
widget = wibox.widget.imagebox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.align.vertical,
},
valign = 'center',
halign = 'center',
widget = wibox.container.place,
valign = "center",
halign = "center"
},
fg = "#ffffff",
fg = '#ffffff',
bg = gcolor.transparent,
border_color = gcolor.transparent,
border_width = dpi(2),
@@ -102,9 +243,12 @@ function element.new(args)
exec = args.exec,
icon_size = args.icon_size,
icon = args.icon,
widget = wibox.container.background
label = args.label,
widget = wibox.container.background,
})
assert(w, 'No widget returned')
gtable.crush(w, element, true)
w:on_hover()

View File

@@ -2,27 +2,45 @@
-- This is the statusbar, every widget, module and so on is combined to all the stuff you see on the screen --
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local awful = require('awful')
awful.screen.connect_for_each_screen(function(s)
-- Create 9 tags
awful.layout.append_default_layouts(User_config.layouts)
awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, User_config.layouts[1])
awful.tag({ '1', '2', '3', '4', '5', '6', '7', '8', '9' }, s, User_config.layouts[1])
require("src.modules.desktop.desktop") { screen = s }
require("src.modules.powermenu.powermenu")(s)
require("src.modules.audio.volume_osd") { screen = s }
--require("src.modules.audio.volume_controller") { screen = s }
require("src.modules.brightness.brightness_osd") { screen = s }
require("src.modules.crylia_bar.init")(s)
--require("src.modules.crylia_wibox.init")(s)
require("src.modules.notification-center.init")(s)
require("src.modules.window_switcher.init")(s)
require("src.modules.application_launcher.init") { screen = s }
--require("src.modules.network_controller.init") { screen = s }
require('src.modules.desktop.desktop') { screen = s }
require('src.modules.crylia_bar.init')(s)
--require('src.modules.crylia_wibox.init')(s)
require('src.modules.notification-center.init') { screen = s }
--require('src.modules.window_switcher.init')(s)
require('src.modules.application_launcher.init') { screen = s }
end)
do
require("src.lib.nice") { titlebar_font = User_config.font.bold,
titlebar_items = { left = { "icon" }, right = { "minimize", "maximize", "close" } } }
end
local ip = require('src.modules.inputbox.new') {
text = 'inputboxtest',
cursor_pos = 4,
highlight = {
start_pos = 1,
end_pos = 4,
},
text_hint = 'Input Some Text',
}
awful.popup {
widget = ip.widget,
bg = '#212121',
visible = true,
screen = 1,
placement = awful.placement.centered,
}
--[[ require('src.modules.inputbox.init') {
text = 'inputboxtest',
cursor_pos = 4,
highlight = {
start_pos = 5,
end_pos = 8,
},
}
]]

View File

@@ -0,0 +1,796 @@
---------------------------------------------------------------------------
-- This widget can be used to type text and get the text from it.
--@DOC_wibox_widget_defaults_inputbox_EXAMPLE@
--
-- @author Rene Kievits
-- @copyright 2022, Rene Kievits
-- @module awful.widget.inputbox
---------------------------------------------------------------------------
local setmetatable = setmetatable
local beautiful = require('beautiful')
local gtable = require('gears.table')
local base = require('wibox.widget.base')
local gstring = require('gears.string')
local akeygrabber = require('awful.keygrabber')
local akey = require('awful.key')
local textbox = require('wibox.widget.textbox')
local imagebox = require('wibox.widget.imagebox')
local cairo = require('lgi').cairo
local apopup = require('awful.popup')
local aplacement = require('awful.placement')
local gsurface = require('gears.surface')
local wibox = require('wibox')
local abutton = require('awful.button')
local capi = {
selection = selection,
mousegrabber = mousegrabber,
mouse = mouse,
}
local inputbox = { mt = {} }
--- Formats the text with a cursor and highlights if set.
--[[ local function text_with_cursor(text, cursor_pos, self)
local char, spacer, text_start, text_end
local cursor_fg = beautiful.inputbox_cursor_fg or '#313131'
local cursor_bg = beautiful.inputbox_cursor_bg or '#0dccfc'
local placeholder_text = self.hint_text or ''
local placeholder_fg = beautiful.inputbox_placeholder_fg or '#777777'
local highlight_bg = beautiful.inputbox_highlight_bg or '#35ffe4'
local highlight_fg = beautiful.inputbox_highlight_fg or '#000000'
if text == '' then
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. '</span>'
end
local offset = 0
if text:sub(cursor_pos - 1, cursor_pos - 1) == -1 then
offset = 1
end
if #text < cursor_pos then
char = ' '
spacer = ''
text_start = gstring.xml_escape(text)
text_end = ''
else
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
spacer = ' '
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
text_end = gstring.xml_escape(text:sub(cursor_pos + offset + 1))
end
if self._private.highlight and self._private.highlight.start_pos and self._private.highlight.end_pos then
-- split the text into 3 parts based on the highlight and cursor position
local text_start_highlight = gstring.xml_escape(text:sub(1, self._private.highlight.start_pos - 1))
local text_highlighted = gstring.xml_escape(text:sub(self._private.highlight.start_pos,
self._private.highlight.end_pos))
local text_end_highlight = gstring.xml_escape(text:sub(self._private.highlight.end_pos + 1))
return text_start_highlight ..
"<span foreground='" .. highlight_fg .. "' background='" .. highlight_bg .. "'>" ..
text_highlighted .. '</span>' .. text_end_highlight
else
return text_start .. "<span background='" .. cursor_bg .. "' foreground='" .. cursor_fg .. "'>" ..
char .. '</span>' .. text_end .. spacer
end
end ]]
local function text_extents(text, font, font_size, args)
local surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
local cr = cairo.Context(surface)
cr:select_font_face(font, args)
cr:set_font_size(font_size)
return cr:text_extents(text)
end
--[[
calculate width/height of the text
create new surface with the calculated width/height
draw a vertical line on the surface as the cursor
the position of the vertical line will be the cursor_pos - text length and the text extend
draw the "text" .. "cursor" .. "rest of the text"
return the surface
mouse_coord holds the coordinates where the user clicked
if its not empty then draw the cursor where the user clicked,
if its on a character then set the cursor to the closest space
if some text is highlighted then draw the text with the highlights
]]
--inputbox.text
--inputbox.cursor_pos <<-- 1 = before the text, 2 = after the first character, 3 = after the second character, etc
--inputbox.highlight <<-- { start_pos, end_pos }
--inputbox.mouse_coord <<-- { x, y } (Will be saved after the user clicked, it will only be overwritten when the user clicks again)
function inputbox:draw_text_surface(x, override_cursor)
-- x can be 0 for the first time its drawn with a default cursor position
x = x or 0
--Colors need to be in rgba 0-1 format, table.unpack is used to unpack the table into function arguments
local fg, fg_highlight, bg_highlight, fg_cursor = { 1, 1, 1 }, { 1, 1, 1 }, { 0.1, 1, 1, 0.5 }, { 1, 1, 1 }
-- Main text_entent mainly to align everything to this one (it knows the highest and lowest point of the text)
local text_extent = text_extents(self:get_text(), self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
--The offset if so the user has some space to click on the left and right side of the text
local start_offset = 4
local end_offset = 4
local surface = cairo.ImageSurface(cairo.Format.ARGB32, text_extent.width + start_offset + end_offset, text_extent.height)
local cr = cairo.Context(surface)
--Split the text initially into 2 or 3 parts (most likely split again later)
local text = self:get_text()
local text_start, text_end, text_highlight
if self._private.highlight.start_pos ~= self._private.highlight.end_pos then
text_start = text:sub(1, self._private.highlight.start_pos - 1)
text_highlight = text:sub(self._private.highlight.start_pos, self._private.highlight.end_pos)
text_end = text:sub(self._private.highlight.end_pos + 1)
else
text_start = text:sub(1, self._private.cursor_pos - 1)
text_end = text:sub(self._private.cursor_pos)
end
--Figure out the cursor position based on the mouse coordinates
if override_cursor then
local cursor_pos = 1
for i = 1, #text, 1 do
-- Not sure if I need new context's to check the character width but I got inconsistent results without it
local ccr = cairo.Context(surface)
ccr:select_font_face(self.font, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
ccr:set_font_size(self.font_size)
local ext_c = ccr:text_extents(text:sub(1, i))
if ext_c.width >= x then
local cccr = cairo.Context(surface)
cccr:select_font_face(self.font, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
cccr:set_font_size(self.font_size)
if math.abs(cccr:text_extents(text:sub(1, i - 1)).width - x) <= math.abs(ext_c.width - x) then
cursor_pos = i
else
cursor_pos = i + 1
end
break
else
cursor_pos = #text + 1
end
end
self._private.cursor_pos = cursor_pos
end
-- Text extents for the start and highlight without any splitting (less calculating, text_end is not needed)
local text_start_extents = text_extents(text_start, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
local text_highlight_extents = text_extents(text_highlight, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
cr:select_font_face(self.font, cairo.FontSlant.NORMAL, cairo.FontWeight.REGULAR)
cr:set_font_size(self.font_size)
--[[
The following code is a bit of a mess because I have to check if the cursor is inside the highlighted text,
the text_start or text_end and then split either of them again to draw the cursor between.
]]
if (self._private.cursor_pos > 1) and text_highlight then
-- If the cursor is inside the highlighted text
if (self._private.highlight.start_pos <= self._private.cursor_pos) and (self._private.highlight.end_pos >= self._private.cursor_pos) then
-- Draw the text_start
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset, -text_extent.y_bearing)
cr:show_text(text_start)
-- split the text_highlight at the cursor_pos
local text_highlight_start = text_highlight:sub(1, self._private.cursor_pos - self._private.highlight.start_pos)
local text_highlight_end = text_highlight:sub(self._private.cursor_pos - self._private.highlight.start_pos + 1)
-- The text_highlight_start extents are needed for the cursor position and the text_highlight_end position
local text_highlight_start_extents = text_extents(text_highlight_start, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
-- Draw the first highlighted part(text_highlight_start)
cr:set_source_rgb(table.unpack(fg_highlight))
cr:move_to(start_offset + text_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_highlight_start)
-- Draw the cursor
cr:set_source_rgb(table.unpack(fg_cursor))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_start_extents.x_advance, text_extent.y_bearing)
cr:line_to(start_offset + text_start_extents.x_advance + text_highlight_start_extents.x_advance, text_extent.height)
cr:stroke()
-- Draw the second highlighted part(text_highlight_end)
cr:set_source_rgb(table.unpack(fg_highlight))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_highlight_end)
-- Draw the text_end
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_end)
-- Draw the background highlight
cr:set_source_rgba(table.unpack(bg_highlight))
cr:rectangle(start_offset + text_start_extents.x_advance, text_extent.y_advance, text_highlight_extents.width, text_extent.height)
cr:fill()
elseif self._private.cursor_pos < self._private.highlight.start_pos then -- If its inside the text_start
-- Split the text_start at the cursor_pos
local text_start_start = text_start:sub(1, self._private.cursor_pos - 1)
local text_start_end = text_start:sub(self._private.cursor_pos)
-- The text_start_start extents is needed for the cursor position and the text_start_end position
local text_start_start_extents = text_extents(text_start_start, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
-- Draw the first part of the text_start(text_start_start)
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset, -text_extent.y_bearing)
cr:show_text(text_start_start)
-- Draw the cursor
cr:set_source_rgb(table.unpack(fg_cursor))
cr:move_to(start_offset + text_start_start_extents.x_advance, text_extent.y_bearing)
cr:line_to(start_offset + text_start_start_extents.x_advance, text_extent.height)
cr:stroke()
-- Draw the second part of the text_start(text_start_end)
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_start_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_start_end)
-- Draw the text_highlight
cr:set_source_rgb(table.unpack(fg_highlight))
cr:move_to(start_offset + text_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_highlight)
-- Draw the text_end
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_end)
-- Draw the highlight background
cr:set_source_rgba(table.unpack(bg_highlight))
cr:rectangle(start_offset + text_start_extents.x_advance, text_extent.y_advance, text_highlight_extents.width, text_extent.height)
cr:fill()
elseif self._private.cursor_pos > self._private.highlight.end_pos then -- If its inside the text_end
-- Draw the text start
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset, -text_extent.y_bearing)
cr:show_text(text_start)
-- Draw the text highlight
cr:set_source_rgb(table.unpack(fg_highlight))
cr:move_to(start_offset + text_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_highlight)
--split the text_end at the cursor_pos
local text_end_start = text_end:sub(1, self._private.cursor_pos - self._private.highlight.end_pos - 1)
local text_end_end = text_end:sub(self._private.cursor_pos - self._private.highlight.end_pos)
-- Text end_start extents needed for the cursor position and the text_end_end
local text_end_start_extents = text_extents(text_end_start, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
-- Draw the first part of the text_end (text_end_start)
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_end_start)
-- Draw the cursor
cr:set_source_rgb(table.unpack(fg_cursor))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance + text_end_start_extents.x_advance, text_extent.y_bearing)
cr:line_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance + text_end_start_extents.x_advance, text_extent.height)
cr:stroke()
-- Draw the second part of the text_end (text_end_end)
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_start_extents.x_advance + text_highlight_extents.x_advance + text_end_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_end_end)
-- Draw the highlight background
cr:set_source_rgba(table.unpack(bg_highlight))
cr:rectangle(start_offset + text_start_extents.x_advance, text_extent.y_advance, text_highlight_extents.width, text_extent.height)
cr:fill()
end
else -- If the cursor is all the way to the left no split is needed
-- text_start
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset, -text_extent.y_bearing)
cr:show_text(text_start)
-- Cursor
cr:set_source_rgb(table.unpack(fg_cursor))
cr:move_to(start_offset + text_start_extents.x_advance, text_extent.y_bearing)
cr:line_to(start_offset + text_start_extents.x_advance, text_extent.height)
cr:stroke()
-- text_highlight
if text_highlight then
cr:set_source_rgb(table.unpack(fg_highlight))
cr:move_to(start_offset + text_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_highlight)
cr:set_source_rgba(table.unpack(bg_highlight))
cr:rectangle(start_offset + text_start_extents.x_advance, text_extent.y_advance, text_highlight_extents.width, text_extent.height)
cr:fill()
end
-- text_end
cr:set_source_rgb(table.unpack(fg))
cr:move_to(start_offset + text_highlight_extents.x_advance + text_start_extents.x_advance, -text_extent.y_bearing)
cr:show_text(text_end)
end
return surface
end
function inputbox:layout(_, width, height)
if self._private.widget then
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
end
end
function inputbox:fit(context, width, height)
local w, h = 0, 0
if self._private.widget then
w, h = base.fit_widget(self, context, self._private.widget, width, height)
end
return w, h
end
inputbox.set_widget = base.set_widget_common
--- Clears the current text
function inputbox:clear()
self:set_text('')
end
function inputbox:get_text()
return self._private.text or ''
end
function inputbox:set_text(text)
self._private.text = text
--self.markup = text_with_cursor(self:get_text(), #self:get_text(), self)
self:emit_signal('property::text', text)
end
--- Stop the keygrabber and mousegrabber
function inputbox:stop()
if (not self.akeygrabber) or (not self.akeygrabber.is_running) then return end
self:emit_signal('stopped')
self.akeygrabber.stop()
end
function inputbox:focus()
if (not self.akeygrabber) or (not self.akeygrabber.is_running) then
akeygrabber.stop()
self:run()
end
self:connect_signal('button::press', function()
if capi.mouse.current_widget ~= self then
self:emit_signal('keygrabber::stop', '')
end
end)
end
--- Init the inputbox and start the keygrabber
function inputbox:run()
if not self._private.text then self._private.text = '' end
-- Init the cursor position, but causes on refocus the cursor to move to the left
local cursor_pos = self._private.cursor_pos or #self:get_text() + 1
-- Init and reset(when refocused) the highlight
self._private.highlight = {}
self.akeygrabber = akeygrabber {
autostart = true,
start_callback = function()
self:emit_signal('started')
end,
stop_callback = function(_, stop_key)
if stop_key == 'Return' then
self:emit_signal('submit', self:get_text(), stop_key)
else
self:emit_signal('stopped', stop_key)
end
end,
stop_key = { 'Escape', 'Return' },
keybindings = {
--lShift, rShift = #50, #62
--lControl, rControl = #37, #105
akey {
modifiers = { 'Shift' },
key = 'Left', -- left
on_press = function()
if cursor_pos > 1 then
local offset = (self._private.text:sub(cursor_pos - 1, cursor_pos - 1):wlen() == -1) and 1 or 0
if not self._private.highlight.start_pos then
self._private.highlight.start_pos = cursor_pos - 1
end
if not self._private.highlight.end_pos then
self._private.highlight.end_pos = cursor_pos
end
if self._private.highlight.start_pos < cursor_pos then
self._private.highlight.end_pos = self._private.highlight.end_pos - 1
else
self._private.highlight.start_pos = self._private.highlight.start_pos
end
cursor_pos = cursor_pos - 1
end
if cursor_pos < 1 then
cursor_pos = 1
elseif cursor_pos > #self._private.text + 1 then
cursor_pos = #self._private.text + 1
end
self._private.cursor_pos = cursor_pos
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Shift', 'Left')
end,
},
akey {
modifiers = { 'Shift' },
key = 'Right', -- right
on_press = function()
if #self._private.text >= cursor_pos then
if not self._private.highlight.end_pos then
self._private.highlight.end_pos = cursor_pos - 1
end
if not self._private.highlight.start_pos then
self._private.highlight.start_pos = cursor_pos
end
if self._private.highlight.end_pos <= cursor_pos then
self._private.highlight.end_pos = self._private.highlight.end_pos + 1
else
self._private.highlight.start_pos = self._private.highlight.start_pos + 1
end
cursor_pos = cursor_pos + 1
if cursor_pos > #self._private.text + 1 then
self._private.highlight = {}
end
end
if cursor_pos < 1 then
cursor_pos = 1
elseif cursor_pos > #self._private.text + 1 then
cursor_pos = #self._private.text + 1
end
self._private.cursor_pos = cursor_pos
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Shift', 'Right')
end,
},
akey {
modifiers = { 'Control' },
key = 'a', -- a
on_press = function()
-- Mark the entire text
self._private.highlight = {
start_pos = 1,
end_pos = #self._private.text,
}
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Control', 'a')
end,
},
akey {
modifiers = { 'Control' },
key = 'v', -- v
on_press = function()
local sel = capi.selection()
if sel then
sel = sel:gsub('\n', '')
if self._private.highlight and self._private.highlight.start_pos and
self._private.highlight.end_pos then
-- insert the text into the selected part
local text_start = self._private.text:sub(1, self._private.highlight.start_pos - 1)
local text_end = self._private.text:sub(self._private.highlight.end_pos + 1)
self:set_text(text_start .. sel .. text_end)
self._private.highlight = {}
cursor_pos = #text_start + #sel + 1
else
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
sel .. self._private.text:sub(cursor_pos))
cursor_pos = cursor_pos + #sel
end
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Control', 'v')
end,
},
akey {
modifiers = { 'Control' },
key = 'c', -- c
on_press = function()
--TODO
end,
},
akey {
modifiers = { 'Control' },
key = 'x', -- x
on_press = function()
--TODO
end,
},
akey {
modifiers = { 'Control' },
key = 'Left', -- left
on_press = function()
-- Find all spaces
local spaces = {}
local t, i = self._private.text, 0
while t:find('%s') do
i = t:find('%s')
table.insert(spaces, i)
t = t:sub(1, i - 1) .. '-' .. t:sub(i + 1)
end
local cp = 1
for _, v in ipairs(spaces) do
if (v < cursor_pos) then
cp = v
end
end
cursor_pos = cp
if cursor_pos < 1 then
cursor_pos = 1
elseif cursor_pos > #self._private.text + 1 then
cursor_pos = #self._private.text + 1
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Control', 'Left')
end,
},
akey {
modifiers = { 'Control' },
key = 'Right', -- right
on_press = function()
local next_space = self._private.text:sub(cursor_pos):find('%s')
if next_space then
cursor_pos = cursor_pos + next_space
else
cursor_pos = #self._private.text + 1
end
if cursor_pos < 1 then
cursor_pos = 1
elseif cursor_pos > #self._private.text + 1 then
cursor_pos = #self._private.text + 1
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', 'Control', 'Right')
end,
},
akey {
modifiers = {},
key = 'BackSpace', --BackSpace
on_press = function()
-- If text is highlighted delete that, else just delete the character to the left
if self._private.highlight and self._private.highlight.start_pos and
self._private.highlight.end_pos then
local text_start = self._private.text:sub(1, self._private.highlight.start_pos - 1)
local text_end = self._private.text:sub(self._private.highlight.end_pos + 1)
self:set_text(text_start .. text_end)
self._private.highlight = {}
cursor_pos = #text_start + 1
else
if cursor_pos > 1 then
local offset = (self._private.text:sub(cursor_pos - 1, cursor_pos - 1):wlen() == -1) and 1 or
0
self:set_text(self._private.text:sub(1, cursor_pos - 2 - offset) ..
self._private.text:sub(cursor_pos))
cursor_pos = cursor_pos - 1 - offset
end
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', nil, 'BackSpace')
end,
},
akey {
modifiers = {},
key = 'Delete', --delete
on_press = function()
-- If text is highlighted delete that, else just delete the character to the right
if self._private.highlight and self._private.highlight.start_pos and
self._private.highlight.end_pos then
local text_start = self._private.text:sub(1, self._private.highlight.start_pos - 1)
local text_end = self._private.text:sub(self._private.highlight.end_pos + 1)
self:set_text(text_start .. text_end)
self._private.highlight = {}
cursor_pos = #text_start + 1
else
if cursor_pos <= #self._private.text then
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
self._private.text:sub(cursor_pos + 1))
end
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', nil, 'Delete')
end,
},
akey {
modifiers = {},
key = 'Left', --left
on_press = function()
-- Move cursor ro the left
if cursor_pos > 1 then
cursor_pos = cursor_pos - 1
end
self._private.highlight = {}
end,
},
akey {
modifiers = {},
key = 'Right', --right
on_press = function()
-- Move cursor to the right
if cursor_pos <= #self._private.text then
cursor_pos = cursor_pos + 1
end
self._private.highlight = {}
end,
},
--self.keybindings
},
keypressed_callback = function(_, modifiers, key)
if modifiers[1] == 'Shift' then
if key:wlen() == 1 then
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
string.upper(key) .. self._private.text:sub(cursor_pos))
cursor_pos = cursor_pos + #key
end
elseif modifiers[1] == 'Mod2' or '' then
if key:wlen() == 1 then
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
key .. self._private.text:sub(cursor_pos))
cursor_pos = cursor_pos + #key
end
end
if cursor_pos < 1 then
cursor_pos = 1
elseif cursor_pos > #self._private.text + 1 then
cursor_pos = #self._private.text + 1
end
self.p.widget:get_children_by_id('text_image')[1].image = self:draw_text_surface()
self:emit_signal('inputbox::key_pressed', modifiers, key)
end,
}
end
--[[
take the text and cursor position and figure out which character is next
if mx is greater than lx then the right character is the next character
if mx is less than lx then the left character is the next character
calculate the delta between mx and lx, if the delta is greater than the next
character increase or decrease the cursor position by 1 (depends if the delta is positive or negative)
and set the lx = mx
return 1 if advanced to the right, -1 if advanced to the left, 0 if not advanced; and the new lx
]]
function inputbox:advanced_by_character(mx, lx)
local delta = mx - lx
local character
if delta < 0 then
character = self._private.text:sub(self._private.cursor_pos + 1, self._private.cursor_pos + 1)
else
character = self._private.text:sub(self._private.cursor_pos - 1, self._private.cursor_pos - 1)
end
--local character = (self._private.text:sub(self._private.cursor_pos + 1, self._private.cursor_pos + 1) and (delta < 0)) or self._private.text:sub(self._private.cursor_pos - 1, self._private.cursor_pos - 1)
if character then
local cr = cairo.Context(cairo.ImageSurface(cairo.Format.ARGB32, 1, 1))
cr:select_font_face(self.font, cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL)
cr:set_font_size(self.font_size)
local extents = cr:text_extents(character)
if math.abs(delta) >= extents.x_advance then
self._private.cursor_pos = self._private.cursor_pos + (((delta > 0) and 1) or -1)
lx = mx
return (((delta > 0) and 1) or -1), lx
end
end
return 0, lx
end
--- Creates a new inputbox widget
-- @tparam table args Arguments for the inputbox widget
-- @tparam string args.text The text to display in the inputbox
-- @tparam[opt=beautiful.fg_normal] string args.fg Text foreground color
-- @tparam[opt=beautiful.border_focus] string args.border_focus_color Border color when focused
-- @tparam[opt=""] string args.placeholder_text placeholder text to be shown when not focused and
-- @tparam[opt=beautiful.inputbox_placeholder_fg] string args.placeholder_fg placeholder text foreground color
-- @tparam[opt=beautiful.inputbox_cursor_bg] string args.cursor_bg Cursor background color
-- @tparam[opt=beautiful.inputbox_cursor_fg] string args.cursor_fg Cursor foreground color
-- @tparam[opt=beautiful.inputbox_highlight_bg] string args.highlight_bg Highlight background color
-- @tparam[opt=beautiful.inputbox_highlight_fg] string args.highlight_fg Highlight foreground color
-- @treturn awful.widget.inputbox The inputbox widget.
-- @constructorfct awful.widget.inputbox
function inputbox.new(args)
args = args or {}
-- directly pass a possible default text(this is not meant to be a hint)
local w = imagebox()
--gtable.crush(w, args)
gtable.crush(w, inputbox, true)
w._private = {}
w._private.text = args.text or ''
w.font_size = 24
w.font = User_config.font.regular
w._private.cursor_pos = args.cursor_pos
w._private.highlight = args.highlight
w.p = apopup {
widget = {
{
image = w:draw_text_surface(),
resize = false,
valign = 'bottom',
halign = 'center',
widget = wibox.widget.imagebox,
id = 'text_image',
},
widget = wibox.container.margin,
margins = 20,
},
bg = '#212121',
visible = true,
screen = 1,
placement = aplacement.centered,
}
w.p.widget:get_children_by_id('text_image')[1]:buttons(gtable.join {
abutton({}, 1, function()
-- Get the mouse coordinates realative to the widget
local x, y = mouse.coords().x - p.x - 20, mouse.coords().y - p.y - 20 -- 20 is the margin on either side
p.widget:get_children_by_id('text_image')[1].image = w:draw_text_surface(x, false)
w.highlight = { start_pos = w.cursor_pos, end_pos = w.cursor_pos }
p.widget:get_children_by_id('text_image')[1].image = w:draw_text_surface(x, false)
if not mousegrabber.isrunning() then
local last_x, advanced, cursor_pos, mx = x, nil, w.cursor_pos, nil
mousegrabber.run(function(m)
mx = m.x - p.x - 20
if (math.abs(mx - x) > 5) then
-- Returns 1 if the mouse has advanced to the right, -1 if it has advanced to the left
advanced, last_x = w:advanced_by_character(mx, last_x)
if advanced == 1 then
print(cursor_pos, w.highlight.start_pos, w.highlight.end_pos)
if cursor_pos <= w.highlight.start_pos then
if w.highlight.end_pos < #w._private.text then
w.highlight.end_pos = w.highlight.end_pos + 1
end
else
w.highlight.start_pos = w.highlight.start_pos + 1
end
p.widget:get_children_by_id('text_image')[1].image = w:draw_text_surface(x, true)
print(w.highlight.start_pos, w.highlight.end_pos)
elseif advanced == -1 then
if cursor_pos >= w.highlight.end_pos then
if w.highlight.start_pos > 1 then
w.highlight.start_pos = w.highlight.start_pos - 1
end
else
w.highlight.end_pos = w.highlight.end_pos - 1
end
p.widget:get_children_by_id('text_image')[1].image = w:draw_text_surface(x, true)
print(w.highlight.start_pos, w.highlight.end_pos)
end
end
return m.buttons[1]
end, 'xterm')
end
w:run()
end),
})
--w.font = args.font or beautiful.font
--w.keybindings = args.keybindings or {}
--w.hint_text = args.hint_text
--w.markup = args.text or text_with_cursor('', 1, w)
return w
end
function inputbox.mt:__call(...)
return inputbox.new(...)
end
return setmetatable(inputbox, inputbox.mt)

View File

@@ -0,0 +1,485 @@
local Pango = require('lgi').Pango
local PangoCairo = require('lgi').PangoCairo
local abutton = require('awful.button')
local akey = require('awful.key')
local akeygrabber = require('awful.keygrabber')
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local base = require('wibox.widget.base')
local beautiful = require('beautiful')
local cairo = require('lgi').cairo
local gobject = require('gears.object')
local gstring = require('gears.string')
local gsurface = require('gears.surface')
local gtable = require('gears.table')
local gtimer = require('gears.timer')
local imagebox = require('wibox.widget.imagebox')
local setmetatable = setmetatable
local textbox = require('wibox.widget.textbox')
local wibox = require('wibox')
local dpi = beautiful.xresources.apply_dpi
local capi = {
selection = selection,
mousegrabber = mousegrabber,
mouse = mouse,
}
local inputbox = {}
local function get_text_extent(text, font, font_size, args)
local surface = cairo.ImageSurface(cairo.Format.ARGB32, 0, 0)
local cr = cairo.Context(surface)
cr:select_font_face(font, args)
cr:set_font_size(font_size)
return cr:text_extents(text)
end
function inputbox.draw_text(self)
local text = self:get_text()
local highlight = self:get_highlight()
local fg_color = { 1, 1, 1 }
local cursor_color = { 1, 1, 1, 1 }
if text == '' then
fg_color = { 0.2, 0.2, 0.2 }
-- Silently change the text, it will be changed back after it is drawn
self._private.layout:set_text(self._private.text_hint)
end
local _, pango_extent = self._private.layout:get_extents()
local surface = cairo.ImageSurface(cairo.Format.ARGB32, (pango_extent.width / Pango.SCALE) + pango_extent.x, (pango_extent.height / Pango.SCALE) + pango_extent.y)
local cr = cairo.Context(surface)
-- Draw highlight
if (highlight.start_pos ~= 0) or (highlight.end_pos ~= 0) then
cr:set_source_rgb(0, 0, 1)
local txt = text:sub(self:get_highlight().start_pos + 1, self:get_highlight().end_pos)
cr:rectangle(
cr:text_extents(text:sub(0, self:get_highlight().start_pos)).x_advance,
pango_extent.y / Pango.SCALE,
cr:text_extents(txt).width,
pango_extent.height / Pango.SCALE
)
cr:fill()
end
-- Draw text
PangoCairo.update_layout(cr, self._private.layout)
cr:set_source_rgba(1, 1, 1, 1)
cr:move_to(0, 0)
PangoCairo.show_layout(cr, self._private.layout)
-- Draw cursor
cr:set_source_rgba(table.unpack(cursor_color))
local cursor = self:get_cursor_pos()
cr:rectangle(
cursor.x / Pango.SCALE,
cursor.y / Pango.SCALE,
2,
cursor.height / Pango.SCALE)
cr:fill()
self.widget:set_image(surface)
return surface
end
function inputbox:start_keygrabber()
self.akeygrabber = akeygrabber {
autostart = true,
stop_key = { 'Escape', 'Return' },
start_callback = function()
end,
stop_callback = function()
end,
keybindings = {
akey {
modifiers = {},
key = 'BackSpace',
on_press = function()
local hl = self:get_highlight()
local text = self:get_text()
local cursor_pos = self:get_cursor_index()
if hl.end_pos ~= hl.start_pos then
self:set_text(text:sub(0, hl.start_pos) .. text:sub(hl.end_pos + 1, #text))
self:set_cursor_pos(hl.start_pos)
self:set_highlight { start_pos = 0, end_pos = 0 }
else
self:set_text(text:sub(1, cursor_pos - 1) .. text:sub(cursor_pos + 1))
self:set_cursor_pos(cursor_pos - 1)
end
end,
},
akey {
modifiers = {},
key = 'Delete',
on_press = function()
local hl = self:get_highlight()
local text = self:get_text()
local cursor_pos = self:get_cursor_index()
if hl.end_pos ~= hl.start_pos then
self:set_text(text:sub(0, hl.start_pos) .. text:sub(hl.end_pos + 1, #text))
self:set_cursor_pos(hl.start_pos)
self:set_highlight { start_pos = 0, end_pos = 0 }
else
self:set_text(text:sub(1, cursor_pos) .. text:sub(cursor_pos + 2, #text))
end
end,
},
akey {
modifiers = {},
key = 'Left',
on_press = function()
self:set_cursor_pos(self:get_cursor_index() - 1)
self:set_highlight { start_pos = 0, end_pos = 0 }
end,
},
akey {
modifiers = {},
key = 'Right',
on_press = function()
self:set_cursor_pos(self:get_cursor_index() + 1)
self:set_highlight { start_pos = 0, end_pos = 0 }
end,
},
akey {
modifiers = {},
key = 'Home',
on_press = function()
self:set_cursor_pos(0)
self:set_highlight { start_pos = 0, end_pos = 0 }
end,
},
akey {
modifiers = {},
key = 'End',
on_press = function()
self:set_cursor_pos(#self:get_text())
self:set_highlight { start_pos = 0, end_pos = 0 }
end,
},
akey {
modifiers = { 'Shift' },
key = 'Left',
on_press = function()
local cursor_pos = self:get_cursor_pos()
local hl = self:get_highlight()
if cursor_pos == hl.start_pos then
self:set_cursor_pos(cursor_pos - 1)
self:set_highlight { start_pos = self:get_cursor_pos(), end_pos = hl.end_pos }
elseif cursor_pos == hl.end_pos then
self:set_cursor_pos(cursor_pos - 1)
self:set_highlight { start_pos = hl.start_pos, end_pos = self:get_cursor_pos() }
else
if (hl.start_pos ~= cursor_pos) and (hl.end_pos ~= cursor_pos) then
self:set_highlight { start_pos = cursor_pos, end_pos = cursor_pos }
hl = self:get_highlight()
self:set_cursor_pos(cursor_pos - 1)
self:set_highlight { start_pos = self:get_cursor_pos(), end_pos = hl.end_pos }
end
end
end,
},
akey {
modifiers = { 'Shift' },
key = 'Right',
on_press = function()
local cursor_pos = self:get_cursor_pos()
local hl = self:get_highlight()
if cursor_pos == hl.end_pos then
self:set_cursor_pos(cursor_pos + 1)
self:set_highlight { start_pos = hl.start_pos, end_pos = self:get_cursor_pos() }
elseif cursor_pos == hl.start_pos then
self:set_cursor_pos(cursor_pos + 1)
self:set_highlight { start_pos = self:get_cursor_pos(), end_pos = hl.end_pos }
else
if (hl.start_pos ~= cursor_pos) and (hl.end_pos ~= cursor_pos) then
self:set_highlight { start_pos = cursor_pos, end_pos = cursor_pos }
hl = self:get_highlight()
self:set_cursor_pos(cursor_pos + 1)
self:set_highlight { start_pos = hl.start_pos, end_pos = self:get_cursor_pos() }
end
end
end,
},
akey {
modifiers = { 'Control' },
key = 'a',
on_press = function()
self:set_highlight { start_pos = 0, end_pos = #self:get_text() }
self:set_cursor_pos(#self:get_text() - 1)
end,
},
akey {
modifiers = { 'Control' },
key = 'c',
on_press = function()
local hl = self:get_highlight()
if hl.start_pos ~= hl.end_pos then
local text = self:get_text():sub(hl.start_pos, hl.end_pos)
--TODO:self:copy_to_clipboard(text)
end
end,
},
akey {
modifiers = { 'Control' },
key = 'v',
on_press = function()
local hl = self:get_highlight()
local selection = capi.selection()
if hl.start_pos ~= hl.end_pos then
self:set_text(self:get_text():sub(1, hl.start_pos) .. selection .. self:get_text():sub(hl.end_pos + 1, #self:get_text()))
self:set_cursor_pos(hl.start_pos + #selection)
self:set_highlight { start_pos = 0, end_pos = 0 }
else
self:set_text(self:get_text():sub(1, self:get_cursor_pos()) .. selection .. self:get_text():sub(self:get_cursor_pos() + 1, #self:get_text()))
self:set_cursor_pos(self:get_cursor_pos() + #selection)
end
end,
},
akey {
modifiers = { 'Control' },
key = 'x',
on_press = function()
--TODO
end,
},
akey {
modifiers = { 'Control' },
key = 'Right',
on_press = function()
end,
},
akey {
modifiers = { 'Control' },
key = 'Left',
on_press = function()
end,
},
},
keypressed_callback = function(_, mod, key)
local text = self:get_text()
local cursor_pos = self:get_cursor_index()
if (mod[1] == 'Mod2' or '') and (key:wlen() == 1) then
self:set_text(text:sub(1, cursor_pos) .. key .. text:sub(cursor_pos + 1, #text))
self:set_cursor_pos(cursor_pos + #key)
elseif (mod[1] == 'Shift') and (key:wlen() == 1) then
self:set_text(text:sub(1, cursor_pos) .. key:upper() .. text:sub(cursor_pos + 1, #text))
self:set_cursor_pos(cursor_pos + #key)
end
end,
}
end
--[[ function inputbox:advanced_by_character(mx, last_x)
local delta = mx - last_x
local character
local text = self:get_text()
local cursor_pos = self:get_cursor_pos()
if delta < 0 then
character = text:sub(cursor_pos + 1, cursor_pos + 1)
else
character = text:sub(cursor_pos - 1, cursor_pos - 1)
end
if character then
local extents = get_text_extent(character, self.font, self.font_size, { cairo.FontSlant.NORMAL, cairo.FontWeight.NORMAL })
if math.abs(delta) >= extents.x_advance then
self:set_cursor_pos(cursor_pos + (((delta > 0) and 1) or -1))
last_x = mx
return (((delta > 0) and 1) or -1), last_x
end
end
return 0, last_x
end ]]
function inputbox:start_mousegrabber(x, y)
--[[ if not mousegrabber.isrunning() then
local last_x, advanced, cursor_pos, mx = x, nil, self:get_cursor_pos(), nil
local hl = self:get_highlight()
self:set_highlight { start_pos = cursor_pos, end_pos = cursor_pos }
local text = self:get_text()
mousegrabber.run(function(m)
mx = m.x
if (math.abs(mx - x) > 5) then
advanced, last_x = self:advanced_by_character(mx, last_x)
if advanced == 1 then
if cursor_pos <= hl.start_pos then
if hl.end_pos < #text then
self:set_highlight { start_pos = hl.start_pos, end_pos = hl.end_pos + 1 }
end
else
self:set_highlight { start_pos = hl.start_pos + 1, end_pos = hl.end_pos }
end
elseif advanced == -1 then
if cursor_pos >= hl.end_pos then
if hl.start_pos > 1 then
self:set_highlight { start_pos = hl.start_pos - 1, end_pos = hl.end_pos }
end
else
self:set_highlight { start_pos = hl.start_pos, end_pos = hl.end_pos - 1 }
end
end
end
hl = self:get_highlight()
return m.buttons[1]
end, 'xterm')
end ]]
if not mousegrabber.isrunning() then
local index, _ = self._private.layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE)
if not index then return end
self:set_cursor_pos(index)
-- Remove highlight, but also prepare its position (same pos = no highlight)
self:set_highlight { start_pos = index, end_pos = index }
local text = self:get_text()
local cursor_pos = self:get_cursor_pos()
local hl = self:get_highlight()
mousegrabber.run(function(m)
index, _ = self._private.layout:xy_to_index(m.x * Pango.SCALE, m.y * Pango.SCALE)
if not index then return end
if math.abs(index - cursor_pos) == 1 then
if cursor_pos <= hl.start_pos then
if hl.end_pos < #text then
self:set_highlight { start_pos = hl.start_pos, end_pos = hl.end_pos + 1 }
end
else
self:set_highlight { start_pos = hl.start_pos + 1, end_pos = hl.end_pos }
end
elseif math.abs(index - cursor_pos) == -1 then
if cursor_pos >= hl.end_pos then
if hl.start_pos > 1 then
self:set_highlight { start_pos = hl.start_pos - 1, end_pos = hl.end_pos }
end
else
self:set_highlight { start_pos = hl.start_pos, end_pos = hl.end_pos - 1 }
end
end
if index ~= cursor_pos then
self:set_cursor_pos(index)
end
return m.buttons[1]
end, 'xterm')
end
end
function inputbox:set_cursor_pos_from_mouse(x, y)
-- When setting the cursor position, trailing is not needed as its handled by the setter
local index, _ = self._private.layout:xy_to_index(x * Pango.SCALE, y * Pango.SCALE)
if not index then return end
self:set_highlight { start_pos = 0, end_pos = 0 }
self:set_cursor_pos(index)
end
function inputbox:get_text()
return self._private.layout:get_text()
end
function inputbox:set_text(text)
if self:get_text() == text then return end
local attributes, parsed = Pango.parse_markup(text, -1, 0)
if not attributes then return parsed.message or tostring(parsed) end
self._private.layout:set_text(parsed, string.len(parsed))
self._private.layout:set_attributes(attributes)
self.draw_text(self)
end
function inputbox:get_cursor_pos()
return self._private.layout:get_cursor_pos(self._private.cursor_pos.index)
end
function inputbox:get_cursor_index()
return self._private.cursor_pos.index
end
function inputbox:set_cursor_pos(cursor_pos)
-- moving only moved one character set, to move it multiple times we need to loop as long as the difference to the new cursor isn't 0
if not cursor_pos or (cursor_pos < 0) or (cursor_pos >= #self:get_text()) then return end
while (cursor_pos - self._private.cursor_pos.index) ~= 0 do
self._private.cursor_pos.index, self._private.cursor_pos.trailing = self._private.layout:move_cursor_visually(
true, self._private.cursor_pos.index,
self._private.cursor_pos.trailing,
cursor_pos - self._private.cursor_pos.index
)
end
self.draw_text(self)
end
function inputbox:get_highlight()
return self._private.highlight
end
function inputbox:set_highlight(highlight)
self._private.highlight = highlight
self.draw_text(self)
end
function inputbox:focus()
end
function inputbox:unfocus()
end
function inputbox.new(args)
local ret = gobject { enable_properties = true }
args.text = args.text .. '\n'
gtable.crush(ret, inputbox)
ret._private = {}
ret._private.context = PangoCairo.font_map_get_default():create_context()
ret._private.layout = Pango.Layout.new(ret._private.context)
ret.font_size = 24
ret.font = 'JetBrainsMono Nerd Font, ' .. 24
ret._private.layout:set_font_description(Pango.FontDescription.from_string('JetBrainsMono Nerd Font 16'))
ret._private.text_hint = args.text_hint or ''
ret._private.cursor_pos = {
index = args.cursor_pos or 0,
trailing = 0,
}
ret._private.highlight = args.highlight or {
start_pos = 0,
end_pos = 0,
}
ret.widget = imagebox(nil, false)
ret.widget:connect_signal('button::press', function(_, x, y, button)
if button == 1 then
ret:set_cursor_pos_from_mouse(x, y)
--ret:start_mousegrabber(x, y)
ret:start_keygrabber()
end
end)
ret:set_text(args.text or '')
--ret:set_cursor_pos(ret._private.cursor_pos)
ret:set_highlight(ret._private.highlight)
return ret
end
return setmetatable(inputbox, {
__call = function(_, ...)
return inputbox.new(...)
end,
})

View File

@@ -3,44 +3,45 @@
------------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local awidget = require("awful.widget")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears").table
local gfilesystem = require("gears").filesystem
local gcolor = require("gears").color
local lgi = require("lgi")
local wibox = require("wibox")
local base = require("wibox.widget.base")
local abutton = require('awful.button')
local awidget = require('awful.widget')
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears').table
local gfilesystem = require('gears').filesystem
local gcolor = require('gears').color
local lgi = require('lgi')
local wibox = require('wibox')
local base = require('wibox.widget.base')
local NM = lgi.NM
-- Third party libs
local dbus_proxy = require("src.lib.lua-dbus_proxy.src.dbus_proxy")
local dbus_proxy = require('src.lib.lua-dbus_proxy.src.dbus_proxy')
-- Own libs
local ap_form = require("src.modules.network_controller.ap_form")
local cm = require("src.modules.context_menu.init")
local ap_form = require('src.modules.network_controller.ap_form')
local cm = require('src.modules.context_menu.init')
local hover = require('src.tools.hover')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
local access_point = { mt = {} }
local function flags_to_security(flags, wpa_flags, rsn_flags)
local str = ""
local str = ''
if flags == 1 and wpa_flags == 0 and rsn_flags == 0 then
str = str .. " WEP"
str = str .. ' WEP'
end
if wpa_flags ~= 0 then
str = str .. " WPA1"
str = str .. ' WPA1'
end
if not rsn_flags ~= 0 then
str = str .. " WPA2"
str = str .. ' WPA2'
end
if wpa_flags == 512 or rsn_flags == 512 then
str = str .. " 802.1X"
str = str .. ' 802.1X'
end
return (str:gsub("^%s", ""))
return (str:gsub('^%s', ''))
end
function access_point:get_access_point_connections(ssid)
@@ -50,9 +51,9 @@ function access_point:get_access_point_connections(ssid)
for _, connection_path in ipairs(connections) do
local NetworkManagerSettingsConnection = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Settings.Connection",
path = connection_path
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Settings.Connection',
path = connection_path,
}
if NetworkManagerSettingsConnection.Filename:find(ssid) then
@@ -66,39 +67,39 @@ end
function access_point:create_profile(ap, password, auto_connect)
local s_wsec = {}
local security = flags_to_security(ap.Flags, ap.WpaFlags, ap.RsnFlags)
if security ~= "" then
if security:match("WPA") then
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "wpa-psk")
s_wsec["auth-alg"] = lgi.GLib.Variant("s", "open")
s_wsec["psk"] = lgi.GLib.Variant("s", password)
if security ~= '' then
if security:match('WPA') then
s_wsec['key-mgmt'] = lgi.GLib.Variant('s', 'wpa-psk')
s_wsec['auth-alg'] = lgi.GLib.Variant('s', 'open')
s_wsec['psk'] = lgi.GLib.Variant('s', password)
else
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "None")
s_wsec["wep-key-type"] = lgi.GLib.Variant("s", NM.WepKeyType.PASSPHRASE)
s_wsec["wep-key0"] = lgi.GLib.Variant("s", password)
s_wsec['key-mgmt'] = lgi.GLib.Variant('s', 'None')
s_wsec['wep-key-type'] = lgi.GLib.Variant('s', NM.WepKeyType.PASSPHRASE)
s_wsec['wep-key0'] = lgi.GLib.Variant('s', password)
end
end
return {
["connection"] = {
['connection'] = {
-- ["interface-name"] = lgi.GLib.Variant("s", ap.device_interface),
["uuid"] = lgi.GLib.Variant("s", string.gsub('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', '[xy]', function(c)
['uuid'] = lgi.GLib.Variant('s', string.gsub('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', '[xy]', function(c)
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
return string.format('%x', v)
end)),
["id"] = lgi.GLib.Variant("s", NM.utils_ssid_to_utf8(ap.Ssid)),
["type"] = lgi.GLib.Variant("s", "802-11-wireless"),
["autoconnect"] = lgi.GLib.Variant("b", auto_connect),
['id'] = lgi.GLib.Variant('s', NM.utils_ssid_to_utf8(ap.Ssid)),
['type'] = lgi.GLib.Variant('s', '802-11-wireless'),
['autoconnect'] = lgi.GLib.Variant('b', auto_connect),
},
["ipv4"] = {
["method"] = lgi.GLib.Variant("s", "auto")
['ipv4'] = {
['method'] = lgi.GLib.Variant('s', 'auto'),
},
["ipv6"] = {
["method"] = lgi.GLib.Variant("s", "auto"),
['ipv6'] = {
['method'] = lgi.GLib.Variant('s', 'auto'),
},
["802-11-wireless"] = {
["mode"] = lgi.GLib.Variant("s", "infrastructure"),
['802-11-wireless'] = {
['mode'] = lgi.GLib.Variant('s', 'infrastructure'),
},
["802-11-wireless-security"] = s_wsec
['802-11-wireless-security'] = s_wsec,
}
end
@@ -113,26 +114,25 @@ function access_point:connect(ap, password, auto_connect)
if #connections == 0 then
self.NetworkManager:AddAndActivateConnectionAsync(function(proxy, context, success, fail)
if fail ~= nil then
print("Error: " .. tostring(fail), tostring(fail.code))
self:emit_signal("NetworkManager::failed", tostring(fail), tostring(fail.code))
self:emit_signal('NetworkManager::failed', tostring(fail), tostring(fail.code))
return
end
self:emit_signal("NetworkManager::connected", success)
end, { call_id = "my-id" }, profile, self.NetworkManagerDevice.object_path,
self:emit_signal('NetworkManager::connected', success)
end, { call_id = 'my-id' }, profile, self.NetworkManagerDevice.object_path,
self.NetworkManagerAccessPoint.object_path)
--88ALYLNxo9Kk*RwRxMfN
else
connections[1]:Update(profile)
self.NetworkManager:ActivateConnectionAsync(function(proxy, context, success, failure)
if failure then
self:emit_signal("NM::AccessPointFailed", tostring(failure))
self:emit_signal('NM::AccessPointFailed', tostring(failure))
return
end
self:emit_signal("NM::AccessPointConnected", NM.utils_ssid_to_utf8(ap.Ssid))
self:emit_signal('NM::AccessPointConnected', NM.utils_ssid_to_utf8(ap.Ssid))
end,
{ call_id = "my-id" }, connections[1].object_path, self.NetworkManagerDevice.object_path,
{ call_id = 'my-id' }, connections[1].object_path, self.NetworkManagerDevice.object_path,
self.NetworkManagerAccessPoint.object_path)
end
end
@@ -156,9 +156,9 @@ function access_point.new(args)
local ssid_text = awidget.inputbox {
text = NM.utils_ssid_to_utf8(args.NetworkManagerAccessPoint.Ssid) or
args.NetworkManagerAccessPoint.hw_address or "Unknown",
halign = "left",
valign = "center",
args.NetworkManagerAccessPoint.hw_address or 'Unknown',
halign = 'left',
valign = 'center',
}
local ret = base.make_widget_from_value(wibox.widget {
@@ -168,84 +168,86 @@ function access_point.new(args)
{
{
image = gcolor.recolor_image(
icondir .. "wifi-strength-" .. math.floor(args.NetworkManagerAccessPoint.Strength / 25) + 1 .. ".svg",
icondir .. 'wifi-strength-' .. math.floor(args.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
Theme_config.network_manager.access_point.icon_color),
id = "icon",
id = 'icon',
resize = true,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
forced_width = dpi(24),
forced_height = dpi(24),
widget = wibox.widget.imagebox
widget = wibox.widget.imagebox,
},
id = "icon_container",
strategy = "max",
id = 'icon_container',
strategy = 'max',
width = dpi(24),
height = dpi(24),
widget = wibox.container.constraint
widget = wibox.container.constraint,
},
{
{
ssid_text,
widget = wibox.container.constraint,
strategy = "exact",
strategy = 'exact',
width = dpi(300),
id = "alias"
id = 'alias',
},
width = dpi(260),
height = dpi(40),
strategy = "max",
widget = wibox.container.constraint
strategy = 'max',
widget = wibox.container.constraint,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
{ -- Spacing
forced_width = dpi(10),
widget = wibox.container.background
widget = wibox.container.background,
},
{
{
{
{
id = "con",
id = 'con',
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
forced_width = dpi(24),
forced_height = dpi(24),
widget = wibox.widget.imagebox
widget = wibox.widget.imagebox,
},
id = "place",
strategy = "max",
id = 'place',
strategy = 'max',
width = dpi(24),
height = dpi(24),
widget = wibox.container.constraint
widget = wibox.container.constraint,
},
id = "margin",
id = 'margin',
margins = dpi(2),
widget = wibox.container.margin
widget = wibox.container.margin,
},
id = "margin0",
id = 'margin0',
margin = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
id = "device_layout",
layout = wibox.layout.align.horizontal
id = 'device_layout',
layout = wibox.layout.align.horizontal,
},
id = "device_margin",
id = 'device_margin',
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.network_manager.access_point.bg,
fg = Theme_config.network_manager.access_point.fg,
border_color = Theme_config.network_manager.access_point.border_color,
border_width = Theme_config.network_manager.access_point.border_width,
id = "background",
id = 'background',
shape = Theme_config.network_manager.access_point.device_shape,
widget = wibox.container.background
widget = wibox.container.background,
})
assert(type(ret) == 'table', 'access_point:ret is not a table')
gtable.crush(ret, access_point, true)
ret.NetworkManagerAccessPoint = args.NetworkManagerAccessPoint
@@ -256,49 +258,49 @@ function access_point.new(args)
ret.NetworkManagerAccessPointProperties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.DBus.Properties",
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.DBus.Properties',
path = ret.NetworkManagerAccessPoint.object_path,
}
-- Update the access point strength
ret.NetworkManagerAccessPointProperties:connect_signal(function(_, properties, data)
if data.Strength then
awesome.emit_signal("NM::AccessPointStrength", data.Strength)
awesome.emit_signal('NM::AccessPointStrength', data.Strength)
if ret.is_ap_active(ret.NetworkManagerAccessPoint.object_path) then
ret:get_children_by_id("icon")[1].image = gcolor.recolor_image(
icondir .. "wifi-strength-" .. math.floor(data.Strength / 25) + 1 .. ".svg",
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
icondir .. 'wifi-strength-' .. math.floor(data.Strength / 25) + 1 .. '.svg',
Theme_config.network_manager.access_point.icon_color2)
else
ret:get_children_by_id("icon")[1].image = gcolor.recolor_image(
icondir .. "wifi-strength-" .. math.floor(data.Strength / 25) + 1 .. ".svg",
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
icondir .. 'wifi-strength-' .. math.floor(data.Strength / 25) + 1 .. '.svg',
Theme_config.network_manager.access_point.icon_color)
end
end
end, "PropertiesChanged")
end, 'PropertiesChanged')
if ret:is_ap_active(ret.NetworkManagerAccessPoint) then
ret.bg = Theme_config.network_manager.access_point.fg
ret.fg = Theme_config.network_manager.access_point.bg
ret:get_children_by_id("icon")[1].image = gcolor.recolor_image(
icondir .. "wifi-strength-" .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. ".svg",
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
icondir .. 'wifi-strength-' .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
Theme_config.network_manager.access_point.icon_color2)
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(
icondir .. "link.svg", Theme_config.network_manager.access_point.icon_color2)
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(
icondir .. 'link.svg', Theme_config.network_manager.access_point.icon_color2)
else
ret.bg = Theme_config.network_manager.access_point.bg
ret.fg = Theme_config.network_manager.access_point.fg
ret:get_children_by_id("icon")[1].image = gcolor.recolor_image(
icondir .. "wifi-strength-" .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. ".svg",
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
icondir .. 'wifi-strength-' .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
Theme_config.network_manager.access_point.icon_color)
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(
icondir .. "link.svg", Theme_config.network_manager.access_point.icon_color)
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(
icondir .. 'link.svg', Theme_config.network_manager.access_point.icon_color)
end
ret.ap_form = ap_form {
screen = args.screen,
NetworkManagerAccessPoint = args.NetworkManagerAccessPoint,
ap = ret
ap = ret,
}
ret.cm = cm {
@@ -309,40 +311,40 @@ function access_point.new(args)
{
widget = wibox.widget.imagebox,
resize = true,
valign = "center",
halign = "center",
id = "icon_role",
valign = 'center',
halign = 'center',
id = 'icon_role',
},
widget = wibox.container.constraint,
stragety = "exact",
stragety = 'exact',
width = dpi(24),
height = dpi(24),
id = "const"
id = 'const',
},
{
widget = wibox.widget.textbox,
valign = "center",
halign = "left",
id = "text_role"
valign = 'center',
halign = 'left',
id = 'text_role',
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.background,
}, spacing = dpi(10),
entries = {
{ -- Connect/Disconnect a device
name = "ret.device.Connected" and "Disconnect" or "Connect",
icon = gcolor.recolor_image("ret.device.Connected" and icondir .. "link-off.svg" or
icondir .. "link.svg",
name = 'ret.device.Connected' and 'Disconnect' or 'Connect',
icon = gcolor.recolor_image('ret.device.Connected' and icondir .. 'link-off.svg' or
icondir .. 'link.svg',
Theme_config.network_manager.access_point.icon_color),
callback = function()
ret:toggle_connection(ret.NetworkManagerAccessPoint)
end,
id = "connected"
}
}
id = 'connected',
},
},
}
ret:buttons(gtable.join(
@@ -362,7 +364,7 @@ function access_point.new(args)
)
))
Hover_signal(ret)
hover.bg_hover { widget = ret }
return ret
end

View File

@@ -1,21 +1,23 @@
local abutton = require("awful.button")
local aplacement = require("awful.placement")
local apopup = require("awful.popup")
local awidget = require("awful.widget")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears.table")
local gcolor = require("gears.color")
local gshape = require("gears.shape")
local gfilesystem = require("gears.filesystem")
local NM = require("lgi").NM
local wibox = require("wibox")
local abutton = require('awful.button')
local aplacement = require('awful.placement')
local apopup = require('awful.popup')
local awidget = require('awful.widget')
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears.table')
local gcolor = require('gears.color')
local gshape = require('gears.shape')
local gfilesystem = require('gears.filesystem')
local NM = require('lgi').NM
local wibox = require('wibox')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network/"
local hover = require('src.tools.hover')
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
local capi = {
awesome = awesome,
mouse = mouse,
mousegrabber = mousegrabber
mousegrabber = mousegrabber,
}
local ap_form = { mt = {} }
@@ -28,7 +30,7 @@ function ap_form.new(args)
args = args or {}
args.screen = args.screen
local password = awidget.inputbox { hint_text = "Password..." }
local password = awidget.inputbox { hint_text = 'Password...' }
local ret = apopup {
widget = {
@@ -40,31 +42,31 @@ function ap_form.new(args)
{
widget = wibox.widget.textbox,
text = NM.utils_ssid_to_utf8(args.NetworkManagerAccessPoint.Ssid),
font = User_config.font.specify .. ",extra bold 16",
halign = "center",
valign = "center",
font = User_config.font.specify .. ',extra bold 16',
halign = 'center',
valign = 'center',
},
widget = wibox.container.margin,
margins = dpi(5)
margins = dpi(5),
},
{ -- Close button
{
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. "close.svg", Theme_config.network_manager.form.icon_fg),
image = gcolor.recolor_image(icondir .. 'close.svg', Theme_config.network_manager.form.icon_fg),
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
},
widget = wibox.container.margin,
margins = dpi(5),
},
widget = wibox.container.background,
shape = Theme_config.network_manager.form.close_icon_shape,
id = "close_button",
bg = Theme_config.network_manager.form.close_bg
id = 'close_button',
bg = Theme_config.network_manager.form.close_bg,
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.background,
bg = Theme_config.network_manager.form.header_bg,
@@ -73,9 +75,9 @@ function ap_form.new(args)
{ -- Form
{ -- Password
widget = wibox.widget.textbox,
text = "Password",
halign = "center",
valign = "center"
text = 'Password',
halign = 'center',
valign = 'center',
},
{
widget = wibox.container.margin,
@@ -89,25 +91,25 @@ function ap_form.new(args)
password,
widget = wibox.container.margin,
margins = 5,
id = "marg"
id = 'marg',
},
widget = wibox.container.constraint,
strategy = "exact",
strategy = 'exact',
width = 400,
height = 50,
id = "const"
id = 'const',
},
widget = wibox.container.background,
bg = "#212121",
fg = "#F0F0F0",
border_color = "#414141",
bg = '#212121',
fg = '#F0F0F0',
border_color = '#414141',
border_width = 2,
shape = gshape.rounded_rect,
forced_width = 300,
forced_height = 50,
id = "password_container"
id = 'password_container',
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
{ -- Actions
{ -- Auto connect
@@ -121,26 +123,26 @@ function ap_form.new(args)
check_color = Theme_config.network_manager.form.checkbox_bg,
border_color = Theme_config.network_manager.form.checkbox_bg,
border_width = 2,
id = "checkbox",
widget = wibox.widget.checkbox
id = 'checkbox',
widget = wibox.widget.checkbox,
},
widget = wibox.container.constraint,
strategy = "exact",
strategy = 'exact',
width = dpi(30),
height = dpi(30)
height = dpi(30),
},
widget = wibox.container.place,
halign = "center",
valign = "center"
halign = 'center',
valign = 'center',
},
{
widget = wibox.widget.textbox,
text = "Auto connect",
halign = "center",
valign = "center"
text = 'Auto connect',
halign = 'center',
valign = 'center',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
nil,
{ -- Connect
@@ -148,9 +150,9 @@ function ap_form.new(args)
{
{
widget = wibox.widget.textbox,
text = "Connect",
halign = "center",
valign = "center"
text = 'Connect',
halign = 'center',
valign = 'center',
},
widget = wibox.container.margin,
margins = dpi(10),
@@ -159,18 +161,18 @@ function ap_form.new(args)
bg = Theme_config.network_manager.form.button_bg,
fg = Theme_config.network_manager.form.button_fg,
shape = Theme_config.network_manager.form.button_shape,
id = "connect_button",
id = 'connect_button',
},
widget = wibox.container.margin,
margins = dpi(10),
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
spacing = dpi(20),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
margins = dpi(10)
margins = dpi(10),
},
placement = aplacement.centered,
ontop = true,
@@ -182,55 +184,55 @@ function ap_form.new(args)
shape = Theme_config.network_manager.form.shape,
border_color = Theme_config.network_manager.form.border_color,
border_width = Theme_config.network_manager.form.border_width,
type = "dialog",
type = 'dialog',
screen = args.screen,
}
local password_container = ret.widget:get_children_by_id("password_container")[1]
local password_container = ret.widget:get_children_by_id('password_container')[1]
gtable.crush(ret, ap_form, true)
-- Focus the searchbar when its left clicked
password_container:buttons(gtable.join {
abutton({}, 1, function()
password:focus()
end)
end),
})
--#region Hover signals to change the cursor to a text cursor
local old_cursor, old_wibox
password_container:connect_signal("mouse::enter", function()
password_container:connect_signal('mouse::enter', function()
local wid = capi.mouse.current_wibox
if wid then
old_cursor, old_wibox = wid.cursor, wid
wid.cursor = "xterm"
wid.cursor = 'xterm'
end
end)
password_container:connect_signal("mouse::leave", function()
password_container:connect_signal('mouse::leave', function()
old_wibox.cursor = old_cursor
old_wibox = nil
end)
--#endregion
gtable.crush(ret, ap_form, true)
local checkbox = ret.widget:get_children_by_id("checkbox")[1]
checkbox:connect_signal("button::press", function()
local checkbox = ret.widget:get_children_by_id('checkbox')[1]
checkbox:connect_signal('button::press', function()
checkbox.checked = not checkbox.checked
end)
local close_button = ret.widget:get_children_by_id("close_button")[1]
close_button:connect_signal("button::press", function()
local close_button = ret.widget:get_children_by_id('close_button')[1]
close_button:connect_signal('button::press', function()
ret:popup_toggle()
end)
Hover_signal(close_button)
hover.bg_hover { widget = close_button }
local connect_button = ret.widget:get_children_by_id("connect_button")[1]
connect_button:connect_signal("button::press", function()
local connect_button = ret.widget:get_children_by_id('connect_button')[1]
connect_button:connect_signal('button::press', function()
password:stop()
args.ap:connect(args.NetworkManagerAccessPoint, password:get_text(),
ret.widget:get_children_by_id("checkbox")[1].checked)
ret.widget:get_children_by_id('checkbox')[1].checked)
ret:popup_toggle()
end)
Hover_signal(connect_button)
hover.bg_hover { widget = connect_button }
return ret
end

View File

@@ -3,28 +3,29 @@
------------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local base = require("wibox.widget.base")
local dbus_proxy = require("src.lib.lua-dbus_proxy.src.dbus_proxy")
local dpi = require("beautiful").xresources.apply_dpi
local gcolor = require("gears.color")
local gfilesystem = require("gears.filesystem")
local gshape = require("gears.shape")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local lgi = require("lgi")
local abutton = require('awful.button')
local base = require('wibox.widget.base')
local dbus_proxy = require('src.lib.lua-dbus_proxy.src.dbus_proxy')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gshape = require('gears.shape')
local gtable = require('gears.table')
local gtimer = require('gears.timer')
local lgi = require('lgi')
local NM = lgi.NM
local naughty = require("naughty")
local wibox = require("wibox")
local naughty = require('naughty')
local wibox = require('wibox')
-- Third party libs
local rubato = require("src.lib.rubato")
local rubato = require('src.lib.rubato')
local hover = require('src.tools.hover')
-- Local libs
local access_point = require("src.modules.network_controller.access_point")
local dnd_widget = require("awful.widget.toggle_widget")
local access_point = require('src.modules.network_controller.access_point')
local dnd_widget = require('awful.widget.toggle_widget')
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
local network = { mt = {} }
@@ -41,7 +42,7 @@ network.NMState = {
network.DeviceType = {
ETHERNET = 1,
WIFI = 2
WIFI = 2,
}
network.DeviceState = {
@@ -57,7 +58,7 @@ network.DeviceState = {
SECONDARIES = 90,
ACTIVATED = 100,
DEACTIVATING = 110,
FAILED = 120
FAILED = 120,
}
---Get the wifi and or ethernet proxy and connect to their PropertiesChanged signal
@@ -73,9 +74,9 @@ function network:get_active_device()
--Create a new proxy for every device
local NetworkManagerDevice = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device",
path = path
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Device',
path = path,
}
--Check if the device is either a wifi or ethernet device, and if its activated
@@ -87,92 +88,87 @@ function network:get_active_device()
--New wifi proxy to check the bitrate
self._private.NetworkManagerDeviceWireless = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device.Wireless",
path = path
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Device.Wireless',
path = path,
}
-- Watch PropertiesChanged and update the bitrate
local NetworkManagerDeviceWirelessProperties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.DBus.Properties",
path = self._private.NetworkManagerDeviceWireless.object_path
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.DBus.Properties',
path = self._private.NetworkManagerDeviceWireless.object_path,
}
NetworkManagerDeviceWirelessProperties:connect_signal(function(_, properties, data)
if data.Bitrate then
self:emit_signal("NM::Bitrate", data.Bitrate)
self:emit_signal('NM::Bitrate', data.Bitrate)
end
end, "PropertiesChanged")
end, 'PropertiesChanged')
-- Watch the StateChanged signal, update and notify when a new AP is connected
self._private.NetworkManagerDevice:connect_signal(function(proxy, new_state)
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.AccessPoint",
path = self._private.NetworkManagerDeviceWireless.ActiveAccessPoint
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.AccessPoint',
path = self._private.NetworkManagerDeviceWireless.ActiveAccessPoint,
}
if new_state == network.DeviceState.ACTIVATED then
local ssid = NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid)
self:emit_signal("NM::AccessPointConnected", ssid, NetworkManagerAccessPoint.Strength)
self:emit_signal('NM::AccessPointConnected', ssid, NetworkManagerAccessPoint.Strength)
end
end, "StateChanged")
end, 'StateChanged')
elseif (NetworkManagerDevice.DeviceType == network.DeviceType.ETHERNET) and
(NetworkManagerDevice.State == network.DeviceState.ACTIVATED) then
-- Create a new ethernet device and set it as the active device
self._private.NetworkManagerDevice = NetworkManagerDevice
self._private.NetworkManagerDeviceWired = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device.Wired",
path = path
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Device.Wired',
path = path,
}
local NetworkManagerDeviceWiredProperties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.DBus.Properties",
path = self._private.NetworkManagerDeviceWired.object_path
}
-- Watch the PropertiesChanged signal and update the speed and carrier
NetworkManagerDeviceWiredProperties:connect_signal(function(_, properties, data)
if data.Speed then
print(data.Speed)
self:emit_signal("NM::Speed", data.Speed)
elseif data.Carrier then
print(data.Carrier)
self:emit_signal("NM::Carrier", data.Carrier)
if self._private.NetworkManagerDevice.State == network.DeviceState.ACTIVATED then
awesome.emit_signal('NM::EthernetStatus', true, self._private.NetworkManagerDeviceWired.Speed)
end
end, "PropertiesChanged")
-- Connect to the StateChanged signal and notify when the wired connection is ready
self._private.NetworkManagerDevice:connect_signal(function(proxy, new_state)
self._private.NetworkManagerDevice:connect_signal(function(_, new_state)
if new_state == network.DeviceState.ACTIVATED then
self:emit_signal("NM::EthernetActive")
print("Ethernet active")
awesome.emit_signal('NM::EthernetStatus', true, self._private.NetworkManagerDeviceWired.Speed)
elseif new_state == network.DeviceState.DISCONNECTED then
awesome.emit_signal('NM::EthernetStatus', false)
end
end, "StateChanged")
end, 'StateChanged')
end
end
end
function network:get_active_ap_ssid()
local d = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Device.Wireless',
path = self._private.NetworkManagerDeviceWireless.ActiveAccessPoint,
}
return NM.utils_ssid_to_utf8(d.Ssid)
end
---Scan for access points and create a widget for each one.
function network:scan_access_points()
if not self._private.NetworkManagerDeviceWireless then return end
local ap_list = self:get_children_by_id("wifi_ap_list")[1]
local ap_list = self:get_children_by_id('wifi_ap_list')[1]
ap_list:reset()
local ap_table = {}
self._private.NetworkManagerDeviceWireless:RequestScanAsync(function(_, _, _, failure)
if failure then
naughty.notification {
app_icon = icondir .. "ethernet.svg",
app_name = "Network Manager",
title = "Error: Scan failed!",
message = "Failed to scan for access points.\n" .. failure,
icon = gcolor.recolor_image(icondir .. "ethernet.svg", Theme_config.network.icon_color),
app_icon = icondir .. 'ethernet.svg',
app_name = 'Network Manager',
title = 'Error: Scan failed!',
message = 'Failed to scan for access points.\n' .. failure,
icon = gcolor.recolor_image(icondir .. 'ethernet.svg', Theme_config.network.icon_color),
timeout = 5,
}
return
@@ -183,9 +179,9 @@ function network:scan_access_points()
-- Create a new proxy for every ap
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.AccessPoint",
path = ap
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.AccessPoint',
path = ap,
}
-- We are only interested in those with a ssid
@@ -216,17 +212,17 @@ function network:scan_access_points()
NetworkManagerDevice = self._private.NetworkManagerDevice,
NetworkManagerSettings = self._private.NetworkManagerSettings,
NetworkManager = self._private.NetworkManager,
NetworkManagerDeviceWireless = self._private.NetworkManagerDeviceWireless
NetworkManagerDeviceWireless = self._private.NetworkManagerDeviceWireless,
})
end
end, { call_id = "my-id" }, {})
end, { call_id = 'my-id' }, {})
end
---Toggles networking on or off
function network:toggle_wifi()
local enable = not self._private.NetworkManager.WirelessEnabled
self._private.NetworkManager:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable))
self._private.NetworkManager.WirelessEnabled = { signature = "b", value = enable }
self._private.NetworkManager:Set('org.freedesktop.NetworkManager', 'WirelessEnabled', lgi.GLib.Variant('b', enable))
self._private.NetworkManager.WirelessEnabled = { signature = 'b', value = enable }
end
function network.new(args)
@@ -242,54 +238,54 @@ function network.new(args)
{
{
resize = false,
image = gcolor.recolor_image(icondir .. "menu-down.svg",
image = gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.network_manager.wifi_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "icon"
valign = 'center',
halign = 'center',
id = 'icon',
},
id = "center",
halign = "center",
valign = "center",
id = 'center',
halign = 'center',
valign = 'center',
widget = wibox.container.place,
},
{
{
text = "Wifi Networks",
text = 'Wifi Networks',
widget = wibox.widget.textbox,
id = "ap_name"
id = 'ap_name',
},
margins = dpi(5),
widget = wibox.container.margin
widget = wibox.container.margin,
},
id = "wifi",
layout = wibox.layout.fixed.horizontal
id = 'wifi',
layout = wibox.layout.fixed.horizontal,
},
id = "wifi_bg",
id = 'wifi_bg',
bg = Theme_config.network_manager.wifi_bg,
fg = Theme_config.network_manager.wifi_fg,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(4))
end,
widget = wibox.container.background
widget = wibox.container.background,
},
id = "wifi_margin",
widget = wibox.container.margin
id = 'wifi_margin',
widget = wibox.container.margin,
},
{
id = "wifi_list",
id = 'wifi_list',
{
{
step = dpi(50),
spacing = dpi(10),
layout = require("src.lib.overflow_widget.overflow").vertical,
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
id = "wifi_ap_list"
id = 'wifi_ap_list',
},
id = "margin",
id = 'margin',
margins = dpi(10),
widget = wibox.container.margin
widget = wibox.container.margin,
},
border_color = Theme_config.network_manager.ap_border_color,
border_width = Theme_config.network_manager.ap_border_width,
@@ -297,35 +293,35 @@ function network.new(args)
gshape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4))
end,
widget = wibox.container.background,
forced_height = 0
forced_height = 0,
},
{
{ -- action buttons
{
dnd_widget {
color = Theme_config.network_manager.power_icon_color,
size = dpi(40)
size = dpi(40),
},
id = "dnd",
id = 'dnd',
widget = wibox.container.place,
valign = "center",
halign = "center"
valign = 'center',
halign = 'center',
},
nil,
{ -- refresh
{
{
image = gcolor.recolor_image(icondir .. "refresh.svg",
image = gcolor.recolor_image(icondir .. 'refresh.svg',
Theme_config.network_manager.refresh_icon_color),
resize = false,
valign = "center",
halign = "center",
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
id = "icon"
id = 'icon',
},
widget = wibox.container.margin,
margins = dpi(5),
id = "center",
id = 'center',
},
border_width = dpi(2),
border_color = Theme_config.network_manager.border_color,
@@ -334,20 +330,20 @@ function network.new(args)
end,
bg = Theme_config.network_manager.refresh_bg,
widget = wibox.container.background,
id = "refresh"
id = 'refresh',
},
layout = wibox.layout.align.horizontal
layout = wibox.layout.align.horizontal,
},
widget = wibox.container.margin,
top = dpi(10),
id = "action_buttons"
id = 'action_buttons',
},
id = "layout1",
layout = wibox.layout.fixed.vertical
id = 'layout1',
layout = wibox.layout.fixed.vertical,
},
id = "margin",
id = 'margin',
margins = dpi(15),
widget = wibox.container.margin
widget = wibox.container.margin,
},
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
@@ -355,17 +351,19 @@ function network.new(args)
border_color = Theme_config.network_manager.border_color,
border_width = Theme_config.network_manager.border_width,
bg = Theme_config.network_manager.bg,
id = "background",
widget = wibox.container.background
id = 'background',
widget = wibox.container.background,
},
width = dpi(400),
strategy = "exact",
widget = wibox.container.constraint
strategy = 'exact',
widget = wibox.container.constraint,
})
local dnd = ret:get_children_by_id("dnd")[1]:get_widget()
assert(type(ret) == 'table', 'NetworkManager is not running')
dnd:connect_signal("dnd::toggle", function(enable)
local dnd = ret:get_children_by_id('dnd')[1]:get_widget()
dnd:connect_signal('dnd::toggle', function(enable)
ret:toggle_wifi()
end)
@@ -375,23 +373,23 @@ function network.new(args)
ret._private.NetworkManager = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager",
path = "/org/freedesktop/NetworkManager",
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager',
path = '/org/freedesktop/NetworkManager',
}
ret._private.NetworkManagerSettings = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Settings",
path = "/org/freedesktop/NetworkManager/Settings",
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.NetworkManager.Settings',
path = '/org/freedesktop/NetworkManager/Settings',
}
ret._private.NetworkManagerProperties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.DBus.Properties",
path = "/org/freedesktop/NetworkManager",
name = 'org.freedesktop.NetworkManager',
interface = 'org.freedesktop.DBus.Properties',
path = '/org/freedesktop/NetworkManager',
}
ret._private.NetworkManagerProperties:connect_signal(function(_, properties, data)
@@ -404,7 +402,7 @@ function network.new(args)
dnd:set_disabled()
end
ret:emit_signal("NetworkManager::status", ret._private.WirelessEnabled)
ret:emit_signal('NetworkManager::status', ret._private.WirelessEnabled)
if data.WirelessEnabled then
gtimer {
@@ -414,11 +412,11 @@ function network.new(args)
single_shot = true,
callback = function()
ret:scan_access_points()
end
end,
}
end
end
end, "PropertiesChanged")
end, 'PropertiesChanged')
ret:get_active_device()
@@ -433,9 +431,9 @@ function network.new(args)
--#endregion
--#region Dropdown logic
local wifi_margin = ret:get_children_by_id("wifi_margin")[1]
local wifi_list = ret:get_children_by_id("wifi_list")[1]
local wifi = ret:get_children_by_id("wifi")[1].center
local wifi_margin = ret:get_children_by_id('wifi_margin')[1]
local wifi_list = ret:get_children_by_id('wifi_list')[1]
local wifi = ret:get_children_by_id('wifi')[1].center
local rubato_timer = rubato.timed {
duration = 0.2,
@@ -443,14 +441,14 @@ function network.new(args)
easing = rubato.linear,
subscribed = function(v)
wifi_list.forced_height = v
end
end,
}
wifi_margin:buttons(gtable.join(
abutton({}, 1, nil,
function()
if wifi_list.forced_height == 0 then
if not ret:get_children_by_id("wifi_ap_list")[1].children then
if not ret:get_children_by_id('wifi_ap_list')[1].children then
return
end
local size = (5 * 49) + 1
@@ -461,30 +459,29 @@ function network.new(args)
wifi_margin.wifi_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-up.svg",
wifi.icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.network_manager.wifi_icon_color))
else
rubato_timer.target = 0
wifi_margin.wifi_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, true, true, dpi(4))
end
wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg",
wifi.icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
Theme_config.network_manager.wifi_icon_color))
end
end
)
))
hover.bg_hover { widget = wifi_margin.wifi_bg }
--#endregion
local refresh_button = ret:get_children_by_id("refresh")[1]
local refresh_button = ret:get_children_by_id('refresh')[1]
refresh_button:buttons(gtable.join(
abutton({}, 1, nil,
function()
abutton({}, 1, nil, function()
ret:scan_access_points()
end
)
end)
))
Hover_signal(refresh_button)
hover.bg_hover { widget = refresh_button }
return ret
end

View File

@@ -3,286 +3,303 @@
-------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local dnd_widget = require("awful.widget.toggle_widget")
local dpi = require('beautiful').xresources.apply_dpi
local gfilesystem = require('gears.filesystem')
local base = require('wibox.widget.base')
local wibox = require('wibox')
local apopup = require('awful.popup')
local aplacement = require('awful.placement')
local gshape = require('gears.shape')
local gcolor = require('gears.color')
local capi = {
awesome = awesome,
}
-- Own Libs
local dnd_widget = require('awful.widget.toggle_widget')
local notification_list = require('src.modules.notification-center.widgets.notification_list')()
local weather_widget = require('src.modules.notification-center.widgets.weather')()
local profile_widget = require('src.modules.notification-center.widgets.profile')()
local status_bars = require('src.modules.notification-center.widgets.status_bars')()
local music_widget = require('src.modules.notification-center.widgets.song_info')()
local hover = require('src.tools.hover')
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/notifications/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/notifications/'
return function(s)
local dnd = dnd_widget({
text = "Do not disturb",
color = Theme_config.notification_center.dnd_color,
fg = Theme_config.notification_center.dnd_fg,
size = dpi(40)
})
dnd:get_widget():connect_signal("dnd::toggle", function(enabled)
User_config.dnd = enabled
end)
--#region Activation area
local activation_area = awful.popup {
bg = '#00000000',
widget = wibox.container.background,
ontop = true,
screen = s,
type = 'dock',
placement = function(c)
awful.placement.top(c)
end,
local capi = {
client = client,
}
activation_area:setup({
widget = wibox.container.background,
forced_height = dpi(1),
forced_width = dpi(300),
bg = '#00000000',
layout = wibox.layout.fixed.horizontal
})
local instance = nil
capi.awesome.connect_signal(
"notification_center_activation::toggle",
function(screen, hide)
if screen == s then
activation_area.visible = hide
local info_center = {}
function info_center:toggle()
if self.container.visible then
self.container.visible = false
else
self.container.visible = true
end
end
)
--#endregion
function info_center.new(args)
args = args or {}
--#region Widgets
local nl = require("src.modules.notification-center.notification_list").notification_list
local music_widget = require("src.modules.notification-center.song_info")()
local time_date = require("src.modules.notification-center.time_date")()
local weather_widget = require("src.modules.notification-center.weather")()
local profile_widget = require("src.modules.notification-center.profile")()
local status_bars_widget = require("src.modules.notification-center.status_bars")()
--#endregion
--#region Notification buttons
local clear_all_widget = wibox.widget { -- Clear all button
local w = base.make_widget_from_value {
{
{
{
text = "Clear",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "clearall"
{
{
{ -- Time
halign = 'center',
valign = 'center',
format = "<span foreground='#18FFFF' font='JetBrainsMono Nerd Font, Bold 46'><b>%H:%M</b></span>",
widget = wibox.widget.textclock,
},
id = "background4",
fg = Theme_config.notification_center.clear_all_button.fg,
bg = Theme_config.notification_center.clear_all_button.bg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 12)
end,
forced_width = dpi(80),
forced_height = dpi(40),
widget = wibox.container.background
{ -- Date and Day
{ -- Date
halign = 'left',
valign = 'bottom',
format = "<span foreground='#69F0AE' font='JetBrainsMono Nerd Font, Regular 18'><b>%d</b></span><span foreground='#18FFFF' font='JetBrainsMono Nerd Font, Regular 18'><b> %b %Y</b></span>",
widget = wibox.widget.textclock,
},
id = "margin3",
margins = dpi(10),
widget = wibox.container.margin
{ -- Day
halign = 'left',
valign = 'top',
format = "<span foreground='#69F0AE' font='JetBrainsMono Nerd Font, Bold 20'><b>%A</b></span>",
widget = wibox.widget.textclock,
},
layout = wibox.layout.flex.vertical,
},
spacing = dpi(20),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
valign = "bottom",
halign = "right",
}
local no_notification_widget = wibox.widget {
{
{
valign = "center",
halign = "center",
resize = true,
forced_height = dpi(200),
forced_width = dpi(200),
image = icondir .. "megamind.svg",
widget = wibox.widget.imagebox,
id = "icon"
},
margins = dpi(20),
widget = wibox.container.margin,
},
{
id = "txt",
markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notifications?</span>",
valign = "center",
halign = "center",
widget = wibox.widget.textbox
},
id = "lay",
layout = wibox.layout.fixed.vertical
},
valign = "center",
halign = "center",
widget = wibox.container.place
}
--#endregion
--#region Notification center
local notification_center = awful.popup {
{
{
bg = Theme_config.notification_center.spacing_line.color,
widget = wibox.container.background,
bg = Theme_config.notification_center.bg,
border_color = Theme_config.notification_center.border_color,
border_width = Theme_config.notification_center.border_width,
placement = function(c)
awful.placement.top(c, { margins = dpi(10) })
end,
ontop = true,
screen = s,
visible = false,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
end,
}
local function notification_center_setup()
notification_center:setup({
widget = notification_center,
-- Custom widgets
{
time_date,
require("src.modules.notification-center.spacingline_widget")(),
},
widget = wibox.container.constraint,
height = dpi(2),
strategy = 'exact',
},
left = dpi(60),
right = dpi(60),
widget = wibox.container.margin,
},
{
{
weather_widget,
{
profile_widget,
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
status_bars_widget,
status_bars,
music_widget,
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
-- Notification list
{
{
{
nl,
notification_list,
height = dpi(680),
strategy = "max",
widget = wibox.container.constraint
},
{
no_notification_widget,
strategy = "max",
height = dpi(400),
widget = wibox.container.constraint
strategy = 'max',
widget = wibox.container.constraint,
},
{
{
dnd,
{
{
{
valign = 'center',
halign = 'center',
resize = true,
image = icondir .. 'megamind.svg',
widget = wibox.widget.imagebox,
id = 'no_notification_icon',
},
widget = wibox.container.constraint,
height = dpi(200),
width = dpi(200),
strategy = 'exact',
},
{
markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notifications?</span>",
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'no_notification_text',
},
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.place,
},
strategy = 'max',
height = dpi(400),
widget = wibox.container.constraint,
},
{
{
dnd_widget {
text = 'Do not disturb',
color = Theme_config.notification_center.dnd_color,
fg = Theme_config.notification_center.dnd_fg,
size = dpi(40),
},
id = 'dnd',
widget = wibox.container.place,
valign = "center",
halign = "center"
},
nil,
clear_all_widget,
layout = wibox.layout.align.horizontal
},
id = "layout5",
layout = wibox.layout.align.vertical
},
id = "margin6",
margins = dpi(20),
widget = wibox.container.margin
},
id = "yes",
spacing_widget = {
{ -- Clear all button
{
bg = Theme_config.notification_center.spacing_color,
widget = wibox.container.background
{
{
{
text = 'Clear',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'clear',
},
top = dpi(40),
bottom = dpi(40),
widget = wibox.container.margin
fg = Theme_config.notification_center.clear_all_button.fg,
bg = Theme_config.notification_center.clear_all_button.bg,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 12)
end,
id = 'clear_all_bg',
widget = wibox.container.background,
},
spacing = dpi(1),
forced_height = dpi(800),
forced_width = dpi(1000),
layout = wibox.layout.flex.horizontal
})
end
widget = wibox.container.constraint,
width = dpi(80),
height = dpi(40),
strategy = 'exact',
},
margins = dpi(10),
widget = wibox.container.margin,
},
widget = wibox.container.place,
valign = 'bottom', --? Needed?
halign = 'right', --? Needed?
},
layout = wibox.layout.align.horizontal,
},
layout = wibox.layout.align.vertical,
},
margins = dpi(20),
widget = wibox.container.margin,
},
spacing_widget = {
thickness = dpi(2),
color = Theme_config.notification_center.spacing_color,
span_ratio = 0.9,
widget = wibox.widget.separator,
},
spacing = dpi(2),
layout = wibox.layout.flex.horizontal,
},
widget = wibox.container.constraint,
height = dpi(800),
width = dpi(1000),
strategy = 'exact',
}
--#endregion
hover.bg_hover { widget = w:get_children_by_id('clear_all_bg')[1] }
--#region Signals
-- Toggle notification_center visibility when mouse is over activation_area
activation_area:connect_signal(
"mouse::enter",
function()
notification_center.visible = true
notification_center_setup()
end
)
assert(type(w) == 'table', 'Widget creation failed')
-- Update the notification center popup and check if there are no notifications
capi.awesome.connect_signal(
"notification_center:update::needed",
function()
if #nl == 0 then
notification_list:connect_signal('new_children', function()
if #notification_list.children == 0 then
math.randomseed(os.time())
local prob = math.random(1, 10)
if (prob == 5) or (prob == 6) then
no_notification_widget.lay.icon.image = icondir .. "megamind.svg"
no_notification_widget.lay.txt.markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notifications?</span>"
w:get_children_by_id('no_notification_icon')[1].image = icondir .. 'megamind.svg'
w:get_children_by_id('no_notification_text')[1].markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notifications?</span>"
else
no_notification_widget.lay.icon.image = icondir .. "bell-outline.svg"
no_notification_widget.lay.txt.markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notification</span>"
w:get_children_by_id('no_notification_icon')[1].image = icondir .. 'bell-outline.svg'
w:get_children_by_id('no_notification_text')[1].markup = "<span color='#414141' font='JetBrainsMono Nerd Font, ExtraBold 20'>No Notification</span>"
end
no_notification_widget.visible = true
w:get_children_by_id('no_notification_icon')[1].visible = true
w:get_children_by_id('no_notification_text')[1].visible = true
else
no_notification_widget.visible = false
w:get_children_by_id('no_notification_icon')[1].visible = false
w:get_children_by_id('no_notification_text')[1].visible = false
end
notification_center_setup()
end
)
local function mouse_leave()
notification_center.visible = false
end
capi.awesome.connect_signal("notification_center::block_mouse_events", function()
notification_center:disconnect_signal("mouse::leave", mouse_leave)
end)
capi.awesome.connect_signal("notification_center::unblock_mouse_events", function()
notification_center:connect_signal("mouse::leave", mouse_leave)
w:get_children_by_id('clear')[1]:connect_signal('button::press', function()
notification_list.children = {}
notification_list:emit_signal('new_children')
end)
-- Hide notification_center when mouse leaves it
notification_center:connect_signal(
"mouse::leave",
mouse_leave
)
w:get_children_by_id('dnd')[1]:get_widget():connect_signal('dnd::toggle', function(enabled)
User_config.dnd = enabled
end)
-- Clear all notifications on button press
clear_all_widget:connect_signal(
"button::press",
function()
local size = #nl
for i = 0, size do
nl[i] = nil
end
capi.awesome.emit_signal("notification_center:update::needed")
end
)
w.container = apopup {
widget = w,
bg = Theme_config.notification_center.bg,
border_color = Theme_config.notification_center.border_color,
border_width = Theme_config.notification_center.border_width,
placement = function(c)
aplacement.top(c, { margins = dpi(10) })
end,
ontop = true,
screen = args.screen,
visible = false,
}
Hover_signal(clear_all_widget.margin3.background4)
--#endregion
local activation_area = apopup {
bg = gcolor.transparent,
widget = {
forced_height = dpi(1),
forced_width = dpi(300),
bg = gcolor.transparent,
layout = wibox.layout.fixed.horizontal,
},
ontop = true,
screen = args.screen,
type = 'dock',
placement = function(c)
aplacement.top(c)
end,
}
capi.client.connect_signal('property::fullscreen', function(c)
if c.fullscreen then
activation_area.visible = false
else
activation_area.visible = true
end
end)
activation_area:connect_signal('mouse::enter', function()
w.container.visible = true
end)
w.container:connect_signal('mouse::leave', function()
w.container.visible = false
end)
return w
end
if not instance then
instance = setmetatable(info_center, {
__call = function(self, ...)
self.new(...)
end,
})
end
return instance

View File

@@ -1,268 +0,0 @@
-------------------------------------
-- This is the notification-center --
-------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local naughty = require("naughty")
local capi = {
awesome = awesome,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/notifications/"
local nl = {}
nl.notification_list = { layout = require("src.lib.overflow_widget.overflow").vertical, scrollbar_width = 0,
step = dpi(100), spacing = dpi(20) }
-- @param {table} notification
-- @return {widget} notifications_list
function nl.create_notification(n)
n.time = os.time()
local time_ago_text = "- ago"
local timer_widget = wibox.widget {
{
{
text = time_ago_text,
widget = wibox.widget.textbox,
id = "txt"
},
id = "background",
fg = Theme_config.notification_center.notification_list.timer_fg,
widget = wibox.container.background
},
margins = dpi(10),
widget = wibox.container.margin,
}
gears.timer {
timeout = 1,
autostart = true,
call_now = true,
callback = function()
local time_ago = math.floor(os.time() - n.time)
local timer_text = timer_widget.background.txt
if time_ago < 5 then
timer_text:set_text("now")
elseif time_ago < 60 then
timer_text:set_text(time_ago .. "s ago")
elseif time_ago < 3600 then
timer_text:set_text(math.floor(time_ago / 60) .. "m ago")
elseif time_ago < 86400 then
timer_text:set_text(math.floor(time_ago / 3600) .. "h ago")
else
timer_text:set_text(math.floor(time_ago / 86400) .. "d ago")
end
end
}
local close_widget = wibox.widget {
{
{
{
{
font = User_config.font.specify .. ", 10",
text = "",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
start_angle = 4.71239,
thickness = dpi(2),
min_value = 0,
max_value = 360,
value = 360,
widget = wibox.container.arcchart,
id = "arc_chart"
},
id = "background",
fg = Theme_config.notification_center.notification_list.close_color,
bg = Theme_config.notification_center.notification_list.close_bg,
widget = wibox.container.background
},
strategy = "exact",
width = dpi(20),
height = dpi(20),
widget = wibox.container.constraint,
id = "const"
},
margins = dpi(10),
widget = wibox.container.margin,
}
local timer_close_widget = timer_widget
local notification = wibox.widget {
{
{
{
{
{
{
{
{
{
{
image = gears.color.recolor_image(icondir .. "notification-outline.svg",
Theme_config.notification_center.notification_list.icon),
resize = false,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
},
right = dpi(5),
widget = wibox.container.margin
},
{
markup = n.app_name or 'System Notification',
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
layout = wibox.layout.fixed.horizontal
},
fg = Theme_config.notification_center.notification_list.title_fg,
widget = wibox.container.background
},
margins = dpi(10),
widget = wibox.container.margin
},
nil,
{
timer_widget,
layout = wibox.layout.fixed.horizontal,
id = "arc_app_layout_2"
},
id = "arc_app_layout",
layout = wibox.layout.align.horizontal
},
id = "arc_app_bg",
border_color = Theme_config.notification_center.notification_list.title_border_color,
border_width = Theme_config.notification_center.notification_list.title_border_width,
widget = wibox.container.background
},
{
{
{
{
{
image = n.icon,
resize = true,
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
clip_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, 10)
end
},
width = naughty.config.defaults.icon_size,
height = naughty.config.defaults.icon_size,
strategy = "exact",
widget = wibox.container.constraint
},
halign = "center",
valign = "top",
widget = wibox.container.place
},
id = "margin01",
left = dpi(20),
bottom = dpi(15),
top = dpi(15),
right = dpi(10),
widget = wibox.container.margin
},
{
{
{
markup = n.title,
widget = wibox.widget.textbox,
align = "left"
},
{
markup = n.message,
widget = wibox.widget.textbox,
align = "left"
},
layout = wibox.layout.fixed.vertical
},
left = dpi(10),
bottom = dpi(10),
top = dpi(10),
right = dpi(20),
widget = wibox.container.margin
},
layout = wibox.layout.fixed.horizontal
},
id = "widget_layout",
layout = wibox.layout.fixed.vertical
},
id = "min_size",
strategy = "min",
width = dpi(100),
widget = wibox.container.constraint
},
id = "max_size",
strategy = "max",
width = Theme.notification_max_width or dpi(500),
widget = wibox.container.constraint
},
pk = #nl.notification_list + 1,
bg = Theme_config.notification_center.notification_list.notification_bg,
border_color = Theme_config.notification_center.notification_list.notification_border_color,
border_width = Theme_config.notification_center.notification_list.notification_border_width,
shape = Theme_config.notification_center.notification_list.notification_shape,
widget = wibox.container.background
}
close_widget:connect_signal(
"button::press",
function(_, _, _, button)
if button == 1 then
for i, b in pairs(nl.notification_list) do
if b.pk == notification.pk then
table.remove(nl.notification_list, math.tointeger(i))
capi.awesome.emit_signal("notification_center:update::needed")
break
end
end
end
end
)
Hover_signal(close_widget.const.background)
notification:connect_signal(
"mouse::enter",
function()
notification:get_children_by_id("arc_app_layout_2")[1]:set(1, close_widget)
end
)
notification:connect_signal(
"mouse::leave",
function()
notification:get_children_by_id("arc_app_layout_2")[1]:set(1, timer_close_widget)
end
)
table.insert(nl.notification_list, 1, notification)
end
naughty.connect_signal(
"request::display",
function(n)
nl.create_notification(n)
capi.awesome.emit_signal("notification_center:update::needed")
end
)
return nl

View File

@@ -1,208 +0,0 @@
--------------------------------
-- This is the profile widget --
--------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/profile/"
return function()
local profile_widget = wibox.widget {
{
{
{
{
{
{
image = gears.surface.load_uncached(gears.filesystem.get_configuration_dir() ..
"src/assets/userpfp/crylia.png"),
id = "icon",
valign = "center",
halign = "center",
clip_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
end,
widget = wibox.widget.imagebox
},
strategy = "exact",
widget = wibox.container.constraint
},
id = "icon_margin",
margins = dpi(20),
widget = wibox.container.margin
},
{
{
{
{
{ -- Username
id = "username_prefix",
image = gears.color.recolor_image(icondir .. "user.svg",
Theme_config.notification_center.profile.username_icon_color),
valign = "center",
halign = "left",
resize = false,
widget = wibox.widget.imagebox
},
{ -- Username
id = "username",
valign = "center",
align = "left",
widget = wibox.widget.textbox
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
},
{
{
id = "os_prefix",
image = gears.color.recolor_image(icondir .. "laptop.svg",
Theme_config.notification_center.profile.os_prefix_icon_color),
valign = "center",
halign = "left",
resize = false,
widget = wibox.widget.imagebox
},
{ -- OS
id = "os",
valign = "center",
align = "left",
widget = wibox.widget.textbox
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
},
{
{
id = "kernel_prefix",
image = gears.color.recolor_image(icondir .. "penguin.svg",
Theme_config.notification_center.profile.kernel_icon_color),
valign = "center",
halign = "left",
resize = false,
widget = wibox.widget.imagebox
},
{ -- Kernel
id = "kernel",
valign = "center",
align = "left",
widget = wibox.widget.textbox
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
},
{
{
id = "uptime_prefix",
image = gears.color.recolor_image(icondir .. "clock.svg",
Theme_config.notification_center.profile.uptime_icon_color),
valign = "center",
halign = "left",
resize = false,
widget = wibox.widget.imagebox
},
{ -- Uptime
id = "uptime",
valign = "center",
align = "left",
widget = wibox.widget.textbox
},
spacing = dpi(10),
id = "uptime_layout",
layout = wibox.layout.fixed.horizontal
},
spacing = dpi(5),
id = "info_layout",
layout = wibox.layout.flex.vertical
},
id = "text_margin",
widget = wibox.container.constraint
},
id = "text_container",
bottom = dpi(20),
left = dpi(20),
widget = wibox.container.margin
},
id = "text_container_wrapper",
widget = wibox.layout.fixed.vertical
},
id = "wrapper",
fg = Theme_config.notification_center.profile.fg,
border_color = Theme_config.notification_center.profile.border_color,
border_width = Theme_config.notification_center.profile.border_width,
shape = Theme_config.notification_center.profile.shape,
widget = wibox.container.background
},
id = "const",
strategy = "exact",
width = dpi(250),
height = dpi(350),
widget = wibox.container.constraint
},
top = dpi(20),
left = dpi(10),
right = dpi(20),
bottom = dpi(10),
widget = wibox.container.margin
}
local function get_os_name_pretty()
awful.spawn.easy_async_with_shell(
"cat /etc/os-release | grep -w NAME",
function(stdout)
profile_widget:get_children_by_id("os")[1].text = stdout:match("\"(.+)\"")
end
)
end
-- function to get and set the kernel version
local function get_kernel_version()
awful.spawn.easy_async_with_shell(
"uname -r",
function(stdout)
profile_widget:get_children_by_id("kernel")[1].text = stdout:match("(%d+%.%d+%.%d+)")
end
)
end
--function to get the username and hostname
local function get_user_hostname()
awful.spawn.easy_async_with_shell(
"echo $USER@$(hostname)",
function(stdout)
profile_widget:get_children_by_id("username")[1].text = stdout:gsub("\n", "") or ""
end
)
end
-- function to fetch uptime async
local function get_uptime()
awful.spawn.easy_async_with_shell("uptime -p", function(stdout)
local hours = stdout:match("(%d+) hours") or 0
local minutes = stdout:match("(%d+) minutes") or 0
profile_widget:get_children_by_id("uptime")[1].text = hours .. "h, " .. minutes .. "m"
end)
end
get_os_name_pretty()
get_kernel_version()
get_user_hostname()
gears.timer {
timeout = 60,
autostart = true,
call_now = true,
callback = get_uptime
}
return profile_widget
end

View File

@@ -1,501 +0,0 @@
---------------------------
-- This is the song-info --
---------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local capi = {
awesome = awesome,
mouse = mouse,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/notifications/"
return function(s)
--#region Music control button widgets
local function button_hover_effect(widget, svg, color, color2)
local mouse_enter = function()
widget.image = gears.surface.load_uncached(gears.color.recolor_image(icondir .. svg, color2))
local w = capi.mouse.current_wibox
if w then
w.cursor = "hand1"
end
end
local mouse_leave = function()
widget.image = gears.surface.load_uncached(gears.color.recolor_image(icondir .. svg, color))
capi.mouse.cursor = "left_ptr"
local w = capi.mouse.current_wibox
if w then
w.cursor = "left_ptr"
end
end
widget:disconnect_signal("mouse::enter", mouse_enter)
widget:connect_signal("mouse::enter", mouse_enter)
widget:disconnect_signal("mouse::leave", mouse_leave)
widget:connect_signal("mouse::leave", mouse_leave)
end
local shuffle_button = wibox.widget {
resize = false,
image = gears.color.recolor_image(icondir .. "shuffle.svg",
Theme_config.notification_center.song_info.shuffle_disabled),
valign = "center",
halign = "center",
widget = wibox.widget.imagebox,
}
local function suffle_handler()
awful.spawn.easy_async_with_shell(
"playerctl shuffle",
function(stdout)
if stdout:match("On") then
awful.spawn.with_shell("playerctl shuffle off")
shuffle_button.image = gears.color.recolor_image(icondir .. "shuffle.svg",
Theme_config.notification_center.song_info.shuffle_disabled)
else
awful.spawn.with_shell("playerctl shuffle on")
shuffle_button.image = gears.color.recolor_image(icondir .. "shuffle.svg",
Theme_config.notification_center.song_info.shuffle_enabled)
end
end
)
end
local function update_shuffle()
awful.spawn.easy_async_with_shell(
"playerctl shuffle",
function(stdout)
if stdout:match("On") then
shuffle_button.image = gears.color.recolor_image(icondir .. "shuffle.svg",
Theme_config.notification_center.song_info.shuffle_enabled)
else
shuffle_button.image = gears.color.recolor_image(icondir .. "shuffle.svg",
Theme_config.notification_center.song_info.shuffle_disabled)
end
end
)
end
update_shuffle()
local repeat_button = wibox.widget {
resize = false,
image = gears.color.recolor_image(icondir .. "repeat.svg", Theme_config.notification_center.song_info.repeat_disabled),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "imagebox"
}
-- On first time load set the correct loop
local function update_loop()
awful.spawn.easy_async_with_shell(
"playerctl loop",
function(stdout)
local loop_mode = stdout:gsub("\n", "")
if loop_mode == "Track" then
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat-once.svg"),
Theme_config.notification_center.song_info.repeat_single)
elseif loop_mode == "None" then
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat.svg"),
Theme_config.notification_center.song_info.repeat_disabled)
elseif loop_mode == "Playlist" then
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat.svg"),
Theme_config.notification_center.song_info.repeat_all)
end
end
)
end
update_loop()
-- Activate shuffle when button is clicked
shuffle_button:buttons(gears.table.join(
awful.button({}, 1, suffle_handler)))
local prev_button = wibox.widget {
resize = false,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "skip-prev.svg", Theme_config.notification_center.song_info.prev_enabled),
widget = wibox.widget.imagebox
}
-- Activate previous song when button is clicked
prev_button:buttons(gears.table.join(
awful.button({}, 1, function()
awful.spawn.easy_async_with_shell(
"playerctl previous && sleep 1",
function()
update_loop()
end
)
end)
))
local pause_play_button = wibox.widget {
resize = false,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "play-pause.svg",
Theme_config.notification_center.song_info.play_enabled),
widget = wibox.widget.imagebox
}
-- Activate play/pause when button is clicked
pause_play_button:buttons(gears.table.join(
awful.button({}, 1, function()
awful.spawn.with_shell("playerctl play-pause")
end)
))
local next_button = wibox.widget {
resize = false,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "skip-next.svg", Theme_config.notification_center.song_info.next_enabled),
widget = wibox.widget.imagebox
}
-- Activate next song when button is clicked
next_button:buttons(gears.table.join(
awful.button({}, 1, function()
awful.spawn.easy_async_with_shell(
"playerctl next && sleep 1",
function()
update_loop()
end
)
end)
))
--- This function updates the repeat button svg and changes the mode on click
local function loop_handler()
awful.spawn.easy_async_with_shell(
"playerctl loop",
function(stdout)
local loop_mode = stdout:gsub("\n", "")
if loop_mode == "None" then
awful.spawn.with_shell("playerctl loop playlist")
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat.svg"),
Theme_config.notification_center.song_info.repeat_all)
elseif loop_mode == "Playlist" then
awful.spawn.with_shell("playerctl loop track")
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat-once.svg"),
Theme_config.notification_center.song_info.repeat_single)
elseif loop_mode == "Track" then
awful.spawn.with_shell("playerctl loop none")
repeat_button.image = gears.color.recolor_image(gears.surface.load_uncached(icondir .. "repeat.svg"),
Theme_config.notification_center.song_info.repeat_disabled)
end
end
)
end
repeat_button:buttons(gears.table.join(awful.button({}, 1, loop_handler)))
button_hover_effect(prev_button, "skip-prev.svg", Theme_config.notification_center.song_info.prev_enabled,
Theme_config.notification_center.song_info.prev_hover)
button_hover_effect(pause_play_button, "play-pause.svg", Theme_config.notification_center.song_info.play_enabled,
Theme_config.notification_center.song_info.play_hover)
button_hover_effect(next_button, "skip-next.svg", Theme_config.notification_center.song_info.next_enabled,
Theme_config.notification_center.song_info.next_hover)
--#endregion
-- Main music widget
local music_widget = wibox.widget {
{
{
{
{
{
{ -- Album art
{
image = icondir .. "default_image.svg",
resize = true,
clip_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(8))
end,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox,
id = "imagebox"
},
width = dpi(80),
height = dpi(80),
strategy = "exact",
widget = wibox.container.constraint,
id = "const"
},
{
{
{
{
{ --Title
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "textbox4"
},
fg = Theme_config.notification_center.song_info.title_fg,
id = "textbox5",
widget = wibox.container.background
},
id = "textbox_const",
strategy = "max",
width = dpi(400),
widget = wibox.container.constraint
},
halign = "center",
valign = "center",
id = "textbox_container4",
widget = wibox.container.place
},
{
{
{
{ --Artist
halign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "textbox3"
},
fg = Theme_config.notification_center.song_info.artist_fg,
id = "background",
widget = wibox.container.background
},
strategy = "max",
width = dpi(400),
widget = wibox.container.constraint
},
halign = "center",
valign = "center",
id = "artist_container",
widget = wibox.container.place
},
{ --Buttons
{
{
shuffle_button,
prev_button,
pause_play_button,
next_button,
repeat_button,
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
id = "layout5"
},
halign = "center",
widget = wibox.container.place,
id = "place2"
},
widget = wibox.container.margin,
id = "margin6"
},
layout = wibox.layout.flex.vertical,
id = "layout4"
},
fill_space = true,
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
id = "layout3"
},
widget = wibox.container.margin,
id = "margin5"
},
{ --Song Duration
{
{
{
markup = "0:00",
widget = wibox.widget.textbox,
id = "textbox2"
},
fg = Theme_config.notification_center.song_info.duration_fg,
widget = wibox.container.background,
id = "background3"
},
right = dpi(10),
widget = wibox.container.margin,
id = "margin4"
},
{ -- Progressbar
{
color = Theme_config.notification_center.song_info.progress_color,
background_color = Theme_config.notification_center.song_info.progress_background_color,
max_value = 100,
value = 50,
forced_height = dpi(5),
shape = function(cr, width)
gears.shape.rounded_bar(cr, width, dpi(5))
end,
widget = wibox.widget.progressbar,
id = "progressbar1"
},
valign = "center",
halign = "center",
widget = wibox.container.place,
id = "place1"
},
{
{
{
text = "00:00",
widget = wibox.widget.textbox,
id = "text1"
},
id = "background2",
fg = Theme_config.notification_center.song_info.duration_fg,
widget = wibox.container.background
},
id = "margin3",
left = dpi(10),
widget = wibox.container.margin
},
id = "layout2",
layout = wibox.layout.align.horizontal
},
id = "layout1",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
},
id = "margin2",
widget = wibox.container.margin,
margins = dpi(10)
},
id = "background1",
border_color = Theme_config.notification_center.song_info.border_color,
border_width = Theme_config.notification_center.song_info.border_width,
shape = Theme_config.notification_center.song_info.shape,
widget = wibox.container.background
},
id = "margin1",
widget = wibox.container.margin,
top = dpi(10),
bottom = dpi(20),
left = dpi(20),
right = dpi(20)
}
-- Used to check if the music changed and if everthing should be updated
local trackid = ""
local artist = ""
local title = ""
-- Function to get spotify title, artist, album, album_art, length and track_id
local function get_spotify_metadata(skip_check)
skip_check = skip_check or false
awful.spawn.easy_async_with_shell(
"playerctl metadata",
function(stdout)
-- Only fetch info if the track changed or if the title/artist is empty
if skip_check or (not stdout:match(trackid)) or (not stdout:match(artist)) or (not stdout:match(title)) then
-- Get the song title
awful.spawn.easy_async_with_shell(
"playerctl metadata xesam:title",
function(stdout2)
local tit = stdout2:gsub("\n", "")
title = tit
music_widget:get_children_by_id("textbox4")[1].text = tit
end
)
-- Get the song artist
awful.spawn.easy_async_with_shell(
"playerctl metadata xesam:artist",
function(stdout2)
local art = stdout2:gsub("\n", "")
artist = art
music_widget:get_children_by_id("textbox3")[1].text = art
end
)
-- Get the song album image
awful.spawn.easy_async_with_shell(
"playerctl metadata mpris:artUrl",
function(album_art)
local url = album_art:gsub("\n", "")
awful.spawn.easy_async_with_shell(
-- TODO: curl does not stdout and is returns before it finished. This causes the image to sometimes not show correctly.
-- !Find a better solution than sleep 0.1
-- Maybe cache the image? Not sure if that would be a waste of space or not.
"curl -s " .. url .. " -o /tmp/album_art.jpg && echo /tmp/album_art.jpg && sleep 0.5",
function()
music_widget:get_children_by_id("imagebox")[1].image = gears.surface.load_uncached("/tmp/album_art.jpg")
or icondir .. "default_image.svg"
end
)
end
)
-- Get the length of the song
awful.spawn.easy_async_with_shell(
"playerctl metadata mpris:length",
function(stdout2)
local length = stdout2:gsub("\n", "")
if length ~= "" then
local length_formated = string.format("%02d:%02d", math.floor((tonumber(length) or 1) / 60000000) or 0,
(math.floor((tonumber(length) or 1) / 1000000) % 60) or 0)
music_widget:get_children_by_id("progressbar1")[1].max_value = tonumber(math.floor(tonumber(length) /
1000000))
music_widget:get_children_by_id("text1")[1].markup = string.format("<span foreground='%s' font='JetBrainsMono Nerd Font, Bold 14'>%s</span>"
, Theme_config.notification_center.song_info.duration_fg, length_formated)
end
end
)
end
awful.spawn.easy_async_with_shell(
"playerctl metadata mpris:trackid",
function(stdout2)
trackid = stdout2:gsub("\n", "")
end
)
-- Update track id
trackid, artist, title = stdout, music_widget:get_children_by_id("textbox3")[1].text,
music_widget:get_children_by_id("textbox4")[1].text
end
)
-- Always update the current song progression
awful.spawn.easy_async_with_shell(
"playerctl position",
function(stdout)
local time = stdout:gsub("\n", "")
if time ~= "" then
local time_formated = string.format("%02d:%02d", math.floor((tonumber(time) or 1) / 60),
math.floor(tonumber(time) or 1) % 60)
music_widget:get_children_by_id("textbox2")[1].markup = string.format("<span foreground='%s' font='JetBrainsMono Nerd Font, Bold 14'>%s</span>"
, Theme_config.notification_center.song_info.duration_fg, time_formated)
music_widget:get_children_by_id("progressbar1")[1].value = tonumber(time)
end
end
)
end
-- Call every second, if performance is bad, set the timer to a higher value
gears.timer {
timeout = 1,
autostart = true,
call_now = true,
callback = function()
--!Rewrite entire playerctl module for better performance
--get_spotify_metadata()
end
}
-- get_spotify_metadata() on awesome reload
capi.awesome.connect_signal("startup", function()
get_spotify_metadata(true)
end)
return music_widget
end

View File

@@ -1,22 +0,0 @@
------------------------------------------------
-- This is the spacing widget under the clock --
------------------------------------------------
-- Awesome Libs
local dpi = require("beautiful").xresources.apply_dpi
local wibox = require("wibox")
return function()
return wibox.widget {
{
forced_height = dpi(2),
bg = Theme_config.notification_center.spacing_line.color,
widget = wibox.container.background
},
left = dpi(80),
right = dpi(80),
widget = wibox.container.margin
}
end

View File

@@ -1,840 +0,0 @@
------------------------------------
-- This is the status_bars widget --
------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local rubato = require("src.lib.rubato")
local capi = {
awesome = awesome,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/"
--- Signal bars widget for the notification-center
---@diagnostic disable-next-line: undefined-doc-name
---@return wibox.widget
return function()
---Creates a layout with bar widgets based on the given table
---@param widget_table table
---@return table
local function create_bar_layout(widget_table)
local bar_layout = { layout = wibox.layout.flex.horizontal, spacing = dpi(10) }
for _, widget in pairs(widget_table) do
local w
if widget == "cpu_usage" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.cpu_usage_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
image = gears.color.recolor_image(icondir .. "cpu/cpu.svg",
Theme_config.notification_center.status_bar.cpu_usage_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox,
id = "icon1",
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "cpu_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::cpu_usage",
function(cpu_usage)
tooltip.text = "CPU Usage: " .. cpu_usage .. "%"
rubato_timer.target = cpu_usage
end
)
elseif widget == "cpu_temp" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.cpu_temp_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "cpu/thermometer.svg",
Theme_config.notification_center.status_bar.cpu_temp_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "cpu_temp_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::cpu_temp",
function(cpu_temp)
local temp_icon
if cpu_temp < 50 then
temp_icon = icondir .. "cpu/thermometer-low.svg"
elseif cpu_temp >= 50 and cpu_temp < 80 then
temp_icon = icondir .. "cpu/thermometer.svg"
elseif cpu_temp >= 80 then
temp_icon = icondir .. "cpu/thermometer-high.svg"
end
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(temp_icon,
Theme_config.notification_center.status_bar.cpu_temp_color)
tooltip.text = "CPU Temp: " .. cpu_temp .. "°C"
rubato_timer.target = cpu_temp
end
)
elseif widget == "ram_usage" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.ram_usage_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
image = gears.color.recolor_image(icondir .. "cpu/ram.svg",
Theme_config.notification_center.status_bar.ram_usage_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "ram_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::ram_widget",
function(MemTotal, _, MemAvailable)
if not MemTotal or not MemAvailable then
return
end
local ram_usage = math.floor(((MemTotal - MemAvailable) / MemTotal * 100) + 0.5)
tooltip.text = "RAM Usage: " .. ram_usage .. "%"
rubato_timer.target = ram_usage
end
)
elseif widget == "gpu_usage" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.gpu_usage_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
image = gears.color.recolor_image(icondir .. "cpu/gpu.svg",
Theme_config.notification_center.status_bar.gpu_usage_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "gpu_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::gpu_usage",
function(gpu_usage)
if not gpu_usage then return end
tooltip.text = "GPU Usage: " .. gpu_usage .. "%"
rubato_timer.target = tonumber(gpu_usage)
end
)
elseif widget == "gpu_temp" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.gpu_temp_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "cpu/thermometer.svg",
Theme_config.notification_center.status_bar.gpu_temp_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "gpu_temp_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::gpu_temp",
function(gpu_temp)
local temp_icon
local temp_num = tonumber(gpu_temp) or "NaN"
if temp_num then
if temp_num < 50 then
temp_icon = icondir .. "cpu/thermometer-low.svg"
elseif temp_num >= 50 and temp_num < 80 then
temp_icon = icondir .. "cpu/thermometer.svg"
elseif temp_num >= 80 then
temp_icon = icondir .. "cpu/thermometer-high.svg"
end
else
temp_num = "NaN"
temp_icon = icondir .. "cpu/thermometer-low.svg"
end
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(temp_icon,
Theme_config.notification_center.status_bar.gpu_temp_color)
tooltip.text = "GPU Temp: " .. temp_num .. "°C"
rubato_timer.target = temp_num
end
)
elseif widget == "volume" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.volume_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "audio/volume-high.svg",
Theme_config.notification_center.status_bar.volume_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "volume_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"audio::get",
function(muted, volume)
local icon = icondir .. "audio/volume"
volume = tonumber(volume)
if not volume then
return
end
if muted then
icon = icon .. "-mute"
else
if volume < 1 then
icon = icon .. "-mute"
elseif volume >= 1 and volume < 34 then
icon = icon .. "-low"
elseif volume >= 34 and volume < 67 then
icon = icon .. "-medium"
elseif volume >= 67 then
icon = icon .. "-high"
end
end
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(icon .. ".svg",
Theme_config.notification_center.status_bar.volume_color)
tooltip.text = "Volume: " .. volume .. "%"
rubato_timer.target = volume
end
)
elseif widget == "microphone" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.microphone_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "audio/microphone.svg",
Theme_config.notification_center.status_bar.microphone_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "microphone_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"microphone::get",
function(muted, volume)
if not volume then
return
end
local icon = icondir .. "audio/microphone"
volume = tonumber(volume)
if not volume then
return
end
if muted or (volume < 1) then
icon = icon .. "-off"
end
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(icon .. ".svg",
Theme_config.notification_center.status_bar.microphone_color)
tooltip.text = "Microphone: " .. volume .. "%"
rubato_timer.target = volume
end
)
elseif widget == "backlight" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.backlight_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "brightness/brightness-high.svg",
Theme_config.notification_center.status_bar.backlight_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "brightness_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"brightness::get",
function(brightness)
local icon = icondir .. "brightness"
if brightness >= 0 and brightness < 34 then
icon = icon .. "-low"
elseif brightness >= 34 and brightness < 67 then
icon = icon .. "-medium"
elseif brightness >= 67 then
icon = icon .. "-high"
end
w:get_children_by_id("icon1")[1]:set_image(gears.color.recolor_image(icon .. ".svg",
Theme_config.notification_center.status_bar.backlight_color))
tooltip.text = "Backlight: " .. brightness .. "%"
rubato_timer.target = brightness
end
)
elseif widget == "battery" then
w = wibox.widget {
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.battery_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = "progressbar1",
widget = wibox.widget.progressbar
},
id = "background1",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background2",
forced_height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
forced_width = dpi(24),
direction = "east",
widget = wibox.container.rotate
},
{
{ --Icon
id = "icon1",
image = gears.color.recolor_image(icondir .. "battery/battery.svg",
Theme_config.notification_center.status_bar.battery_color),
halign = "center",
valign = "center",
widget = wibox.widget.imagebox
},
id = "background3",
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint
},
id = "battery_layout",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
}
local bar = w:get_children_by_id("progressbar1")[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end
}
local tooltip = awful.tooltip {
objects = { w },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
}
w:connect_signal("mouse::enter", function()
capi.awesome.emit_signal("notification_center::block_mouse_events")
end)
w:connect_signal("mouse::leave", function()
capi.awesome.emit_signal("notification_center::unblock_mouse_events")
end)
capi.awesome.connect_signal(
"update::battery_widget",
function(battery, battery_icon)
w:get_children_by_id("icon1")[1].image = gears.color.recolor_image(battery_icon,
Theme_config.notification_center.status_bar.battery_color)
tooltip.text = "Battery: " .. battery .. "%"
rubato_timer.target = battery
end
)
end
table.insert(bar_layout, w)
end
return bar_layout
end
local signal_bars = wibox.widget {
{
{
{
{
create_bar_layout(User_config.status_bar_widgets),
width = dpi(480),
strategy = "exact",
widget = wibox.container.constraint
},
halign = "center",
valign = "center",
widget = wibox.container.place
},
magins = dpi(10),
layout = wibox.container.margin
},
forced_height = dpi(120),
forced_width = dpi(500),
border_color = Theme_config.notification_center.status_bar.border_color,
border_width = Theme_config.notification_center.status_bar.border_width,
shape = Theme_config.notification_center.status_bar.shape,
widget = wibox.container.background
},
top = dpi(10),
left = dpi(20),
right = dpi(20),
bottom = dpi(10),
widget = wibox.container.margin
}
return signal_bars
end

View File

@@ -1,65 +0,0 @@
----------------------------------
-- This is the time_date widget --
----------------------------------
-- Awesome Libs
local dpi = require("beautiful").xresources.apply_dpi
local wibox = require("wibox")
return function()
local time_date = wibox.widget {
{
{
{
{ -- Time
{
id = "label",
align = "center",
valign = "center",
format = "<span foreground='#18FFFF' font='JetBrainsMono Nerd Font, Bold 46'><b>%H:%M</b></span>",
widget = wibox.widget.textclock
},
widget = wibox.container.margin
},
{ -- Date and Day
{ -- Date
{
id = "label",
align = "left",
valign = "bottom",
format = "<span foreground='#69F0AE' font='JetBrainsMono Nerd Font, Regular 18'><b>%d</b></span><span foreground='#18FFFF' font='JetBrainsMono Nerd Font, Regular 18'><b> %b %Y</b></span>",
widget = wibox.widget.textclock
},
widget = wibox.container.margin
},
{ -- Day
{
id = "label",
align = "left",
valign = "top",
format = "<span foreground='#69F0AE' font='JetBrainsMono Nerd Font, Bold 20'><b>%A</b></span>",
widget = wibox.widget.textclock
},
widget = wibox.container.margin
},
layout = wibox.layout.flex.vertical
},
spacing = dpi(20),
layout = wibox.layout.fixed.horizontal
},
valign = "center",
halign = "center",
widget = wibox.container.place
},
id = "background",
widget = wibox.container.background
},
id = "margin",
margins = dpi(20),
widget = wibox.container.margin
}
return time_date
end

View File

@@ -1,224 +0,0 @@
--------------------------------
-- This is the weather widget --
--------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local naughty = require("naughty")
local json_lua = require("src.lib.json-lua.json-lua")
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/weather/"
return function()
local api_secrets = {
key = User_config.weather_secrets.key,
city_id = User_config.weather_secrets.city_id,
unit = User_config.weather_secrets.unit
}
local weather_widget = wibox.widget {
{
{
{
{
{
{ -- Icon
valign = "center",
align = "center",
resize = true,
forced_width = dpi(64),
forced_height = dpi(64),
widget = wibox.widget.imagebox,
id = "icon"
},
id = "place2",
valing = "center",
halign = "center",
widget = wibox.container.place
},
{ -- Temperature
text = "0°C",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
font = "JetBrains Mono Bold 24",
id = "temp"
},
{ -- City, Country
text = "City, Country",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "city_country",
},
{
{ -- Description
text = "Description",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "description"
},
fg = Theme_config.notification_center.weather.description_fg,
widget = wibox.container.background
},
{ -- line
forced_height = dpi(4),
forced_width = dpi(10),
bg = Theme_config.notification_center.weather.line_bg,
widget = wibox.container.background,
id = "line"
},
{
{ -- Speed
{
image = gears.color.recolor_image(icondir .. "weather-windy.svg",
Theme_config.notification_center.weather.speed_icon_color),
resize = true,
forced_width = dpi(24),
forced_height = dpi(24),
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
},
{
text = "",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "speed"
},
spacing = dpi(10),
id = "layout3",
layout = wibox.layout.fixed.horizontal
},
id = "place4",
halign = "center",
valign = "center",
widget = wibox.container.place
},
{
{ -- Humidity
{
forced_width = dpi(24),
forced_height = dpi(24),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "humidity.svg",
Theme_config.notification_center.weather.humidity_icon_color),
id = "humidity_icon"
},
{
text = "",
valign = "center",
align = "center",
widget = wibox.widget.textbox,
id = "humidity"
},
spacing = dpi(10),
id = "layoutHum",
layout = wibox.layout.fixed.horizontal
},
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "lyt",
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
},
margins = dpi(20),
widget = wibox.container.margin,
},
id = "center",
halign = "center",
valign = "center",
widget = wibox.container.place
},
id = "background",
border_color = Theme_config.notification_center.weather.border_color,
border_width = Theme_config.notification_center.weather.border_width,
shape = Theme_config.notification_center.weather.shape,
widget = wibox.container.background
},
id = "margin",
top = dpi(20),
left = dpi(20),
right = dpi(10),
bottom = dpi(10),
forced_width = dpi(250),
widget = wibox.container.margin
}
local function fetch_weather_data()
awful.spawn.easy_async_with_shell(
"curl -sf 'http://api.openweathermap.org/data/2.5/weather?id=" ..
api_secrets.city_id .. "&units=" .. api_secrets.unit .. "&appid=" .. api_secrets.key .. "'",
function(stdout)
if not stdout:match('error') then
local weather_metadata = json_lua:decode(stdout)
if weather_metadata then
local temp = weather_metadata.main.temp
local humidity = weather_metadata.main.humidity
local city = weather_metadata.name
local country = weather_metadata.sys.country
local weather_icon = weather_metadata.weather[1].icon
local description = weather_metadata.weather[1].description
local speed = weather_metadata.wind.speed
local icon_table = {
["01d"] = "weather-sunny",
["01n"] = "weather-clear-night",
["02d"] = "weather-partly-cloudy",
["02n"] = "weather-night-partly-cloudy",
["03d"] = "weather-cloudy",
["03n"] = "weather-clouds-night",
["04d"] = "weather-cloudy",
["04n"] = "weather-cloudy",
["09d"] = "weather-rainy",
["09n"] = "weather-rainy",
["10d"] = "weather-partly-rainy",
["10n"] = "weather-partly-rainy",
["11d"] = "weather-pouring",
["11n"] = "weather-pouring",
["13d"] = "weather-snowy",
["13n"] = "weather-snowy",
["50d"] = "weather-fog",
["50n"] = "weather-fog"
}
weather_widget:get_children_by_id("icon")[1].image = icondir .. icon_table[weather_icon] .. ".svg"
weather_widget:get_children_by_id("temp")[1].text = math.floor(temp + 0.5) .. "°C"
weather_widget:get_children_by_id("city_country")[1].text = city .. ", " .. country
weather_widget:get_children_by_id("description")[1].text = description:sub(1, 1):upper() ..
description:sub(2)
weather_widget:get_children_by_id("line")[1].bg = Theme_config.notification_center.weather.line_color
weather_widget:get_children_by_id("speed")[1].text = speed .. " m/s"
weather_widget:get_children_by_id("humidity")[1].text = humidity .. "%"
end
end
end
)
end
fetch_weather_data()
gears.timer {
timeout = 900,
autostart = true,
callback = function()
fetch_weather_data()
end
}
return weather_widget
end

View File

@@ -0,0 +1,71 @@
-------------------------------------
-- This is the notification-center --
-------------------------------------
-- Awesome Libs
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local naughty = require('naughty')
local gtimer = require('gears.timer')
local hover = require('src.tools.hover')
return setmetatable({}, {
__call = function()
local ret = wibox.widget {
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
step = dpi(100),
spacing = dpi(20),
}
--!No, :get_children_by_id() does not work here for some reason, yes I hate it too
--[[ naughty.connect_signal('notification_surface', function(b)
local start_time = os.time()
local w = wibox.template.make_from_value(b)
w = w:get_widget()
assert(type(w) == 'table', 'w is not a wibox.widget.base')
-- Change the clock to a timer how long ago the notification was created
w.children[1].children[1].children[1].children[1].children[1].children[2].children[1].children[1] = wibox.widget {
text = 'now',
font = 'JetBrainsMono Nerd Font, Bold 12',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
}
hover.bg_hover { widget = w.children[1].children[1].children[1].children[1].children[1].children[2].children[1].children[2].children[1].children[1] }
w.children[1].children[1].children[1].children[1].children[1].children[2].children[1].children[2]:connect_signal('button::press', function()
ret:remove_widgets(w)
ret:emit_signal('new_children')
end)
gtimer {
timeout = 1,
autostart = true,
call_now = true,
callback = function()
local time_ago = math.floor(os.time() - start_time)
local timer_text = w.children[1].children[1].children[1].children[1].children[1].children[2].children[1].children[1]
if time_ago < 5 then
timer_text:set_text('now')
elseif time_ago < 60 then
timer_text:set_text(time_ago .. 's ago')
elseif time_ago < 3600 then
timer_text:set_text(math.floor(time_ago / 60) .. 'm ago')
elseif time_ago < 86400 then
timer_text:set_text(math.floor(time_ago / 3600) .. 'h ago')
else
timer_text:set_text(math.floor(time_ago / 86400) .. 'd ago')
end
end,
}
ret:add(w)
ret:emit_signal('new_children')
end) ]]
return ret
end,
})

View File

@@ -0,0 +1,174 @@
--------------------------------
-- This is the profile widget --
--------------------------------
-- Awesome Libs
local aspawn = require('awful.spawn')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gshape = require('gears.shape')
local gsurface = require('gears.surface')
local gtimer = require('gears.timer')
local wibox = require('wibox')
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/profile/'
local instance = nil
if not instance then
instance = setmetatable({}, { __call = function()
local w = wibox.widget {
{
{
{
{
{
{
---@diagnostic disable-next-line: param-type-mismatch
image = gsurface.load_uncached(gfilesystem.get_configuration_dir() .. 'src/assets/userpfp/userpfp.png'),
valign = 'center',
halign = 'center',
clip_shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(12))
end,
widget = wibox.widget.imagebox,
},
strategy = 'exact',
widget = wibox.container.constraint,
},
margins = dpi(20),
widget = wibox.container.margin,
},
{
{
{
{ -- Username
image = gcolor.recolor_image(icondir .. 'user.svg',
Theme_config.notification_center.profile.username_icon_color),
valign = 'center',
halign = 'left',
resize = false,
widget = wibox.widget.imagebox,
},
{ -- Username
id = 'username',
valign = 'center',
halign = 'left',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
{
{
image = gcolor.recolor_image(icondir .. 'laptop.svg',
Theme_config.notification_center.profile.os_prefix_icon_color),
valign = 'center',
halign = 'left',
resize = false,
widget = wibox.widget.imagebox,
},
{ -- OS
id = 'os',
valign = 'center',
halign = 'left',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
{
{
image = gcolor.recolor_image(icondir .. 'penguin.svg',
Theme_config.notification_center.profile.kernel_icon_color),
valign = 'center',
halign = 'left',
resize = false,
widget = wibox.widget.imagebox,
},
{ -- Kernel
id = 'kernel',
valign = 'center',
halign = 'left',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
{
{
image = gcolor.recolor_image(icondir .. 'clock.svg',
Theme_config.notification_center.profile.uptime_icon_color),
valign = 'center',
halign = 'left',
resize = false,
widget = wibox.widget.imagebox,
},
{ -- Uptime
id = 'uptime',
valign = 'center',
halign = 'left',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
spacing = dpi(5),
layout = wibox.layout.flex.vertical,
},
bottom = dpi(20),
left = dpi(20),
widget = wibox.container.margin,
},
widget = wibox.layout.fixed.vertical,
},
fg = Theme_config.notification_center.profile.fg,
border_color = Theme_config.notification_center.profile.border_color,
border_width = Theme_config.notification_center.profile.border_width,
shape = Theme_config.notification_center.profile.shape,
widget = wibox.container.background,
},
strategy = 'exact',
width = dpi(250),
height = dpi(350),
widget = wibox.container.constraint,
},
top = dpi(20),
left = dpi(10),
right = dpi(20),
bottom = dpi(10),
widget = wibox.container.margin,
}
aspawn.easy_async_with_shell('cat /etc/os-release | grep -w NAME', function(stdout)
w:get_children_by_id('os')[1].text = stdout:match('\"(.+)\"')
end)
aspawn.easy_async_with_shell('uname -r', function(stdout)
w:get_children_by_id('kernel')[1].text = stdout:match('(%d+%.%d+%.%d+)')
end)
aspawn.easy_async_with_shell('echo $USER@$(hostname)', function(stdout)
w:get_children_by_id('username')[1].text = stdout:gsub('\n', '') or ''
end)
gtimer {
timeout = 60,
autostart = true,
call_now = true,
callback = function()
aspawn.easy_async_with_shell('uptime -p', function(stdout)
local hours = stdout:match('(%d+) hours') or 0
local minutes = stdout:match('(%d+) minutes') or 0
w:get_children_by_id('uptime')[1].text = hours .. 'h, ' .. minutes .. 'm'
end)
end,
}
return w
end, })
end
return instance

View File

@@ -0,0 +1,241 @@
---------------------------
-- This is the song-info --
---------------------------
-- Awesome Libs
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local gcolor = require('gears.color')
local gshape = require('gears.shape')
local base = require('wibox.widget.base')
local abutton = require('awful.button')
local mh = require('src.tools.helpers.playerctl')
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/notifications/'
local music_player = {}
return setmetatable({}, { __call = function()
local w = base.make_widget_from_value {
{
{
{
{
{ -- Album art
{
image = icondir .. 'default_image.svg',
resize = true,
clip_shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
id = 'album_art',
},
width = dpi(80),
height = dpi(80),
strategy = 'exact',
widget = wibox.container.constraint,
},
{
{
{
{
{ --Title
valign = 'center',
halign = 'center',
text = 'Unknown Title',
id = 'title',
widget = wibox.widget.textbox,
},
fg = Theme_config.notification_center.song_info.title_fg,
widget = wibox.container.background,
},
strategy = 'max',
width = dpi(400),
widget = wibox.container.constraint,
},
widget = wibox.container.place,
},
{
{
{
{ --Artist
halign = 'center',
valign = 'center',
id = 'artist',
text = 'Unknown Artist',
widget = wibox.widget.textbox,
},
fg = Theme_config.notification_center.song_info.artist_fg,
widget = wibox.container.background,
},
strategy = 'max',
width = dpi(400),
widget = wibox.container.constraint,
},
widget = wibox.container.place,
},
{ --Buttons
{
{
resize = false,
image = gcolor.recolor_image(icondir .. 'shuffle.svg',
Theme_config.notification_center.song_info.shuffle_disabled),
valign = 'center',
halign = 'center',
id = 'shuffle',
widget = wibox.widget.imagebox,
},
{
resize = false,
valign = 'center',
halign = 'center',
id = 'prev',
image = gcolor.recolor_image(icondir .. 'skip-prev.svg', Theme_config.notification_center.song_info.prev_enabled),
widget = wibox.widget.imagebox,
},
{
resize = false,
valign = 'center',
halign = 'center',
id = 'play_pause',
image = gcolor.recolor_image(icondir .. 'play-pause.svg',
Theme_config.notification_center.song_info.play_enabled),
widget = wibox.widget.imagebox,
},
{
resize = false,
valign = 'center',
halign = 'center',
id = 'next',
image = gcolor.recolor_image(icondir .. 'skip-next.svg', Theme_config.notification_center.song_info.next_enabled),
widget = wibox.widget.imagebox,
},
{
resize = false,
image = gcolor.recolor_image(icondir .. 'repeat.svg', Theme_config.notification_center.song_info.repeat_disabled),
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
id = 'repeat',
},
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
layout = wibox.layout.flex.vertical,
},
fill_space = true,
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
{ --Song Duration
{
{
{
widget = wibox.widget.textbox,
id = 'position',
text = '00:00',
valign = 'center',
halign = 'center',
},
fg = Theme_config.notification_center.song_info.duration_fg,
widget = wibox.container.background,
},
right = dpi(10),
widget = wibox.container.margin,
},
{ -- Progressbar
{
color = Theme_config.notification_center.song_info.progress_color,
background_color = Theme_config.notification_center.song_info.progress_background_color,
max_value = 100,
value = 0,
id = 'progress',
forced_height = dpi(5),
shape = function(cr, width)
gshape.rounded_bar(cr, width, dpi(5))
end,
widget = wibox.widget.progressbar,
},
widget = wibox.container.place,
},
{
{
{
widget = wibox.widget.textbox,
id = 'length',
text = '00:00',
valign = 'center',
halign = 'center',
},
fg = Theme_config.notification_center.song_info.duration_fg,
widget = wibox.container.background,
},
left = dpi(10),
widget = wibox.container.margin,
},
layout = wibox.layout.align.horizontal,
},
widget = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
margins = dpi(10),
},
border_color = Theme_config.notification_center.song_info.border_color,
border_width = Theme_config.notification_center.song_info.border_width,
shape = Theme_config.notification_center.song_info.shape,
widget = wibox.container.background,
},
widget = wibox.container.margin,
top = dpi(10),
bottom = dpi(20),
left = dpi(20),
right = dpi(20),
}
assert(type(w) == 'table', 'Widget must be a table')
gtable.crush(w, music_player, true)
local music_handler = mh(w)
--#region Buttons
w:get_children_by_id('play_pause')[1]:buttons(gtable.join(
abutton({}, 1, function()
music_handler:play_pause()
end)
))
w:get_children_by_id('next')[1]:buttons(gtable.join(
abutton({}, 1, function()
music_handler:next()
end)
))
w:get_children_by_id('prev')[1]:buttons(gtable.join(
abutton({}, 1, function()
music_handler:prev()
end)
))
w:get_children_by_id('repeat')[1]:buttons(gtable.join(
abutton({}, 1, function()
music_handler:set_loop_status()
end)
))
w:get_children_by_id('shuffle')[1]:buttons(gtable.join(
abutton({}, 1, function()
music_handler:set_shuffle()
end)
))
--#endregion
return w
end, })

View File

@@ -0,0 +1,266 @@
------------------------------------
-- This is the status_bars widget --
------------------------------------
-- Awesome Libs
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gears = require('gears')
local wibox = require('wibox')
local base = require('wibox.widget.base')
local gfilesystem = require('gears.filesystem')
local rubato = require('src.lib.rubato')
-- Own Libs
local audio = require('src.tools.helpers.audio')
local backlight = require('src.tools.helpers.backlight')
--local battery = require('src.tools.helpers.battery')
local cpu_usage = require('src.tools.helpers.cpu_usage')
local cpu_temp = require('src.tools.helpers.cpu_temp')
local ram = require('src.tools.helpers.ram')
local gpu_usage = require('src.tools.helpers.gpu_usage')
local gpu_temp = require('src.tools.helpers.gpu_temp')
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/'
return setmetatable({}, { __call = function()
---Creates a layout with bar widgets based on the given table
---@param widget_table table
---@return table
local function create_bar_layout(widget_table)
local bar_layout = { layout = wibox.layout.flex.horizontal, spacing = dpi(10) }
for _, widget in pairs(widget_table) do
local w = base.make_widget_from_value {
{
{
{
{ --Bar
color = Theme_config.notification_center.status_bar.cpu_usage_color,
background_color = Theme_config.notification_center.status_bar.bar_bg_color,
max_value = 100,
value = 0,
forced_height = dpi(8),
shape = function(cr)
gears.shape.rounded_bar(cr, dpi(58), dpi(8))
end,
id = 'progress_role',
widget = wibox.widget.progressbar,
},
halign = 'center',
valign = 'center',
widget = wibox.container.place,
},
direction = 'east',
widget = wibox.container.rotate,
},
widget = wibox.container.constraint,
height = dpi(58), --120 Base size - (10+10) margin - (4+4) Border - 24 Icon - 10 spacing = 58
width = dpi(24),
strategy = 'exact',
},
{
{ --Icon
id = 'image_role',
halign = 'center',
valign = 'center',
widget = wibox.widget.imagebox,
},
height = dpi(24),
width = dpi(24),
widget = wibox.container.constraint,
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical,
}
assert(type(w) == 'table', 'Widget creation failed')
local bar = w:get_children_by_id('progress_role')[1]
local rubato_timer = rubato.timed {
duration = 1,
pos = bar.value,
easing = rubato.linear,
subscribed = function(v)
bar.value = v
end,
}
local tooltip = awful.tooltip {
objects = { w },
mode = 'inside',
preferred_alignments = 'middle',
margins = dpi(10),
}
if widget == 'cpu_usage' then
cpu_usage:connect_signal('update::cpu_usage', function(_, v)
tooltip.text = 'CPU Usage: ' .. v .. '%'
rubato_timer.target = v
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(icondir .. 'cpu/cpu.svg',
Theme_config.notification_center.status_bar.cpu_usage_color)
end)
elseif widget == 'cpu_temp' then
cpu_temp:connect_signal('update::cpu_temp', function(_, v)
local temp_icon
if v < 50 then
temp_icon = icondir .. 'cpu/thermometer-low.svg'
elseif v >= 50 and v < 80 then
temp_icon = icondir .. 'cpu/thermometer.svg'
elseif v >= 80 then
temp_icon = icondir .. 'cpu/thermometer-high.svg'
end
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(temp_icon,
Theme_config.notification_center.status_bar.cpu_temp_color)
tooltip.text = 'CPU Temp: ' .. v .. '°C'
rubato_timer.target = v
end)
elseif widget == 'ram_usage' then
ram:connect_signal('update::ram_widget', function(_, MemTotal, _, MemAvailable)
if not MemTotal or not MemAvailable then return end
local ram_usage = math.floor(((MemTotal - MemAvailable) / MemTotal * 100) + 0.5)
tooltip.text = 'RAM Usage: ' .. ram_usage .. '%'
rubato_timer.target = ram_usage
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(icondir .. 'cpu/ram.svg',
Theme_config.notification_center.status_bar.ram_usage_color)
end)
elseif widget == 'gpu_usage' then
gpu_usage:connect_signal('update::gpu_usage', function(_, v)
if not v then return end
tooltip.text = 'GPU Usage: ' .. v .. '%'
rubato_timer.target = tonumber(v)
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(icondir .. 'cpu/gpu.svg',
Theme_config.notification_center.status_bar.gpu_usage_color)
end)
elseif widget == 'gpu_temp' then
gpu_temp:connect_signal('update::gpu_temp', function(_, v)
local temp_icon, temp_num
if v then
temp_num = tonumber(v)
if temp_num < 50 then
temp_icon = icondir .. 'cpu/thermometer-low.svg'
elseif temp_num >= 50 and temp_num < 80 then
temp_icon = icondir .. 'cpu/thermometer.svg'
elseif temp_num >= 80 then
temp_icon = icondir .. 'cpu/thermometer-high.svg'
end
else
temp_num = 'NaN'
temp_icon = icondir .. 'cpu/thermometer-low.svg'
end
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(temp_icon,
Theme_config.notification_center.status_bar.gpu_temp_color)
tooltip.text = 'GPU Temp: ' .. temp_num .. '°C'
rubato_timer.target = temp_num
end)
elseif widget == 'volume' then
audio:connect_signal('sink::get', function(_, muted, volume)
local icon = icondir .. 'audio/volume'
volume = tonumber(volume)
if not volume then
return
end
if muted then
icon = icon .. '-mute'
else
if volume < 1 then
icon = icon .. '-mute'
elseif volume >= 1 and volume < 34 then
icon = icon .. '-low'
elseif volume >= 34 and volume < 67 then
icon = icon .. '-medium'
elseif volume >= 67 then
icon = icon .. '-high'
end
end
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(icon .. '.svg',
Theme_config.notification_center.status_bar.volume_color)
tooltip.text = 'Volume: ' .. volume .. '%'
rubato_timer.target = volume
end)
elseif widget == 'microphone' then
audio:connect_signal('source::get', function(_, muted, volume)
if not volume then
return
end
local icon = icondir .. 'audio/microphone'
volume = tonumber(volume)
if not volume then
return
end
if muted or (volume < 1) then
icon = icon .. '-off'
end
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(icon .. '.svg',
Theme_config.notification_center.status_bar.microphone_color)
tooltip.text = 'Microphone: ' .. volume .. '%'
rubato_timer.target = volume
end)
elseif widget == 'backlight' then
backlight:connect_signal('brightness::get', function(_, v)
local icon = icondir .. 'brightness'
if v >= 0 and v < 34 then
icon = icon .. '-low'
elseif v >= 34 and v < 67 then
icon = icon .. '-medium'
elseif v >= 67 then
icon = icon .. '-high'
end
w:get_children_by_id('image_role')[1]:set_image(gears.color.recolor_image(icon .. '.svg',
Theme_config.notification_center.status_bar.backlight_color))
tooltip.text = 'Backlight: ' .. v .. '%'
rubato_timer.target = v
end)
elseif widget == 'battery' then
--[[ battery:connect_signal('update::battery_widget', function(battery, battery_icon)
w:get_children_by_id('image_role')[1].image = gears.color.recolor_image(battery_icon,
Theme_config.notification_center.status_bar.battery_color)
tooltip.text = 'Battery: ' .. battery .. '%'
rubato_timer.target = battery
end) ]]
end
table.insert(bar_layout, w)
end
return bar_layout
end
return wibox.widget {
{
{
{
{
{
create_bar_layout(User_config.status_bar_widgets),
width = dpi(480),
strategy = 'exact',
widget = wibox.container.constraint,
},
widget = wibox.container.place,
},
magins = dpi(10),
layout = wibox.container.margin,
},
border_color = Theme_config.notification_center.status_bar.border_color,
border_width = Theme_config.notification_center.status_bar.border_width,
shape = Theme_config.notification_center.status_bar.shape,
widget = wibox.container.background,
},
widget = wibox.container.constraint,
height = dpi(120),
width = dpi(500),
strategy = 'exact',
},
top = dpi(10),
left = dpi(20),
right = dpi(20),
bottom = dpi(10),
widget = wibox.container.margin,
}
end, })

View File

@@ -0,0 +1,203 @@
--------------------------------
-- This is the weather widget --
--------------------------------
-- Awesome Libs
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local gfilesystem = require('gears.filesystem')
local gtimer = require('gears.timer')
local aspawn = require('awful.spawn')
local gcolor = require('gears.color')
local json_lua = require('src.lib.json-lua.json-lua')
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/weather/'
local instance = nil
local icon_table = {
['01d'] = 'weather-sunny',
['01n'] = 'weather-clear-night',
['02d'] = 'weather-partly-cloudy',
['02n'] = 'weather-night-partly-cloudy',
['03d'] = 'weather-cloudy',
['03n'] = 'weather-clouds-night',
['04d'] = 'weather-cloudy',
['04n'] = 'weather-cloudy',
['09d'] = 'weather-rainy',
['09n'] = 'weather-rainy',
['10d'] = 'weather-partly-rainy',
['10n'] = 'weather-partly-rainy',
['11d'] = 'weather-pouring',
['11n'] = 'weather-pouring',
['13d'] = 'weather-snowy',
['13n'] = 'weather-snowy',
['50d'] = 'weather-fog',
['50n'] = 'weather-fog',
}
if not instance then
instance = setmetatable({}, { __call = function()
local w = wibox.widget {
{
{
{
{
{
{
{ -- Icon
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
id = 'icon',
},
widget = wibox.container.constraint,
width = dpi(64),
height = dpi(64),
strategy = 'exact',
},
{ -- Temperature
text = 'NaN°C',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
font = 'JetBrains Mono Bold 24',
id = 'temp',
},
{ -- City, Country
text = 'City, Country',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'city_country',
},
{
{ -- Description
text = 'NaN',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'description',
},
fg = Theme_config.notification_center.weather.description_fg,
widget = wibox.container.background,
},
{ -- line
{
bg = Theme_config.notification_center.weather.line_color,
widget = wibox.container.background,
},
widget = wibox.container.constraint,
height = dpi(2),
width = dpi(10),
strategy = 'exact',
},
{
{ -- Speed
{
image = gcolor.recolor_image(icondir .. 'weather-windy.svg',
Theme_config.notification_center.weather.speed_icon_color),
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
widget = wibox.container.constraint,
width = dpi(24),
height = dpi(24),
strategy = 'exact',
},
{
text = 'NaN m/s',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'speed',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
{
{ -- Humidity
{
{
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icondir .. 'humidity.svg',
Theme_config.notification_center.weather.humidity_icon_color),
},
widget = wibox.container.constraint,
width = dpi(24),
height = dpi(24),
strategy = 'exact',
},
{
text = 'NaN%',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'humidity',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical,
},
margins = dpi(20),
widget = wibox.container.margin,
},
widget = wibox.container.place,
},
border_color = Theme_config.notification_center.weather.border_color,
border_width = Theme_config.notification_center.weather.border_width,
shape = Theme_config.notification_center.weather.shape,
widget = wibox.container.background,
},
top = dpi(20),
left = dpi(20),
right = dpi(10),
bottom = dpi(10),
widget = wibox.container.margin,
},
widget = wibox.container.constraint,
width = dpi(250),
strategy = 'exact',
}
gtimer {
timeout = 900,
autostart = true,
call_now = true,
callback = function()
aspawn.easy_async_with_shell("curl -sf 'http://api.openweathermap.org/data/2.5/weather?id=" ..
User_config.weather_secrets.city_id .. '&units=' .. User_config.weather_secrets.unit .. '&appid=' .. User_config.weather_secrets.key .. "'",
function(stdout)
if not stdout:match('error') then
local weather_metadata = json_lua:decode(stdout)
if weather_metadata then
w:get_children_by_id('icon')[1].image = icondir .. icon_table[weather_metadata.weather[1].icon] .. '.svg'
w:get_children_by_id('temp')[1].text = math.floor(weather_metadata.main.temp + 0.5) .. '°C'
w:get_children_by_id('city_country')[1].text = weather_metadata.name .. ', ' .. weather_metadata.sys.country
w:get_children_by_id('description')[1].text = weather_metadata.weather[1].description:sub(1, 1):upper() ..
weather_metadata.weather[1].description:sub(2)
w:get_children_by_id('speed')[1].text = weather_metadata.wind.speed .. ' m/s'
w:get_children_by_id('humidity')[1].text = weather_metadata.main.humidity .. '%'
end
end
end
)
end,
}
return w
end, })
end
return instance

View File

@@ -0,0 +1,214 @@
--------------------------------
-- This is the network widget --
--------------------------------
-- Awesome Libs
local abutton = require('awful.button')
local akey = require('awful.key')
local akeygrabber = require('awful.keygrabber')
local aspawn = require('awful.spawn')
local dpi = require('beautiful').xresources.apply_dpi
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local wibox = require('wibox')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
screen = screen,
}
-- Icon directory path
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/powermenu/'
local instance = nil
local powermenu = {}
local function get_button(type)
local icon, name, bg_color, command
if type == 'shutdown' then
icon = icondir .. 'shutdown.svg'
name = 'Shutdown'
bg_color = Theme_config.powermenu.shutdown_button_bg
command = 'shutdown now'
elseif type == 'reboot' then
icon = icondir .. 'reboot.svg'
name = 'Reboot'
bg_color = Theme_config.powermenu.reboot_button_bg
command = 'reboot'
elseif type == 'logout' then
icon = icondir .. 'logout.svg'
name = 'Logout'
bg_color = Theme_config.powermenu.logout_button_bg
command = 'awesome-client "awesome.quit()"'
elseif type == 'lock' then
icon = icondir .. 'lock.svg'
name = 'Lock'
bg_color = Theme_config.powermenu.lock_button_bg
command = 'dm-tool lock'
elseif type == 'suspend' then
icon = icondir .. 'suspend.svg'
name = 'Suspend'
bg_color = Theme_config.powermenu.suspend_button_bg
command = 'systemctl suspend'
end
local widget = wibox.widget {
{
{
{
{
{
image = icon,
resize = true,
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
{
text = name,
font = 'JetBrains Mono Bold 30',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
},
widget = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
margins = dpi(10),
widget = wibox.container.margin,
},
fg = Theme_config.powermenu.button_fg,
bg = bg_color,
shape = Theme_config.powermenu.button_shape,
widget = wibox.container.background,
id = 'background',
},
height = dpi(70),
strategy = 'exact',
widget = wibox.container.constraint,
}
hover.bg_hover { widget = widget.background, overlay = 12, press_overlay = 24 }
widget:buttons(gtable.join(
abutton({}, 1, function()
aspawn(command)
end)
))
return widget
end
function powermenu:toggle()
self.keygrabber:start()
self.visible = not self.visible
end
function powermenu.new()
local w = wibox {
widget = {
{
{
{
{
image = icondir .. 'defaultpfp.svg',
resize = true,
clip_shape = Theme_config.powermenu.profile_picture_shape,
valign = 'center',
halign = 'center',
id = 'icon_role',
widget = wibox.widget.imagebox,
},
widget = wibox.container.constraint,
width = dpi(200),
height = dpi(200),
strategy = 'exact',
},
{
halign = 'center',
valign = 'center',
font = 'JetBrains Mono Bold 30',
id = 'text_role',
widget = wibox.widget.textbox,
},
spacing = dpi(50),
layout = wibox.layout.fixed.vertical,
},
{
{
get_button('shutdown'),
get_button('reboot'),
get_button('logout'),
get_button('lock'),
get_button('suspend'),
spacing = dpi(30),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
spacing = dpi(50),
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.place,
},
screen = capi.screen.primary,
type = 'splash',
visible = false,
ontop = true,
bg = Theme_config.powermenu.container_bg,
height = capi.screen.primary.geometry.height,
width = capi.screen.primary.geometry.width,
x = capi.screen.primary.geometry.x,
y = capi.screen.primary.geometry.y,
}
gtable.crush(w, powermenu, true)
w:buttons { gtable.join(
abutton({}, 3, function()
w:toggle()
w.keygrabber:stop()
end)
), }
w.keygrabber = akeygrabber {
autostart = false,
stop_event = 'release',
stop_key = 'Escape',
keybindings = {
akey {
modifiers = {},
key = 'Escape',
on_press = function()
w:toggle()
end,
},
},
}
-- Get the profile script from /var/lib/AccountsService/icons/${USER}
-- and copy it to the assets folder
-- TODO: If the user doesnt have AccountsService look into $HOME/.faces
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/pfp.sh 'userPfp'", function(stdout)
if stdout then
w:get_children_by_id('icon_role')[1].image = stdout:gsub('\n', '')
else
w:get_children_by_id('icon_role')[1].image = icondir .. 'defaultpfp.svg'
end
end)
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/pfp.sh 'userName' '" .. User_config.namestyle .. "'", function(stdout)
w:get_children_by_id('text_role')[1].text = stdout:gsub('\n', '')
end)
return w
end
if instance == nil then
instance = powermenu.new()
end
return instance

View File

@@ -1,249 +0,0 @@
--------------------------------
-- This is the network widget --
--------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local capi = {
awesome = awesome,
mouse = mouse,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/powermenu/"
return function(s)
-- Profile picture imagebox
local profile_picture = wibox.widget {
image = icondir .. "defaultpfp.svg",
resize = true,
forced_height = dpi(200),
clip_shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(30))
end,
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
}
-- Username textbox
local profile_name = wibox.widget {
align = 'center',
valign = 'center',
text = " ",
font = "JetBrains Mono Bold 30",
widget = wibox.widget.textbox
}
-- Get the profile script from /var/lib/AccountsService/icons/${USER}
-- and copy it to the assets folder
-- TODO: If the user doesnt have AccountsService look into $HOME/.faces
local update_profile_picture = function()
awful.spawn.easy_async_with_shell(
"./.config/awesome/src/scripts/pfp.sh 'userPfp'",
function(stdout)
if stdout then
profile_picture:set_image(stdout:gsub("\n", ""))
else
profile_picture:set_image(icondir .. "defaultpfp.svg")
end
end
)
end
update_profile_picture()
-- Get the full username(if set) and the username + hostname
local update_user_name = function()
awful.spawn.easy_async_with_shell(
"./.config/awesome/src/scripts/pfp.sh 'userName' '" .. User_config.namestyle .. "'",
function(stdout)
if stdout:gsub("\n", "") == "Rick Astley" then
profile_picture:set_image(gears.filesystem.get_configuration_dir() .. "src/assets/userpfp/" .. "rickastley.jpg")
end
profile_name:set_text(stdout)
end
)
end
update_user_name()
-- Universal Button widget
local button = function(name, icon, bg_color, callback)
local item = wibox.widget {
{
{
{
{
-- TODO: using gears.color to recolor a SVG will make it look super low res
-- currently I recolor it in the .svg file directly, but later implement
-- a better way to recolor a SVG
image = icon,
resize = true,
forced_height = dpi(30),
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
},
{
text = name,
font = "JetBrains Mono Bold 30",
widget = wibox.widget.textbox
},
widget = wibox.layout.fixed.horizontal
},
margins = dpi(10),
widget = wibox.container.margin
},
fg = Theme_config.powermenu.button_fg,
bg = bg_color,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(10))
end,
widget = wibox.container.background,
id = 'background'
},
layout = wibox.layout.align.vertical
}
item:connect_signal(
"button::release",
function()
callback()
end
)
return item
end
-- Create the power menu actions
local suspend_command = function()
awful.spawn("systemctl suspend")
capi.awesome.emit_signal("module::powermenu:hide")
end
local logout_command = function()
capi.awesome.quit()
end
local lock_command = function()
awful.spawn("dm-tool lock")
capi.awesome.emit_signal("module::powermenu:hide")
end
local shutdown_command = function()
awful.spawn("shutdown now")
capi.awesome.emit_signal("module::powermenu:hide")
end
local reboot_command = function()
awful.spawn("reboot")
capi.awesome.emit_signal("module::powermenu:hide")
end
-- Create the buttons with their command and name etc
local shutdown_button = button("Shutdown", icondir .. "shutdown.svg", Theme_config.powermenu.shutdown_button_bg,
shutdown_command)
local reboot_button = button("Reboot", icondir .. "reboot.svg", Theme_config.powermenu.reboot_button_bg, reboot_command)
local suspend_button = button("Suspend", icondir .. "suspend.svg", Theme_config.powermenu.suspend_button_bg,
suspend_command)
local logout_button = button("Logout", icondir .. "logout.svg", Theme_config.powermenu.logout_button_bg, logout_command)
local lock_button = button("Lock", icondir .. "lock.svg", Theme_config.powermenu.lock_button_bg, lock_command)
-- Signals to change color on hover
Hover_signal(shutdown_button.background)
Hover_signal(reboot_button.background)
Hover_signal(suspend_button.background)
Hover_signal(logout_button.background)
Hover_signal(lock_button.background)
-- The powermenu widget
local powermenu = wibox.widget {
{
{
profile_picture,
profile_name,
spacing = dpi(50),
layout = wibox.layout.fixed.vertical
},
{
{
shutdown_button,
reboot_button,
logout_button,
lock_button,
suspend_button,
spacing = dpi(30),
layout = wibox.layout.fixed.horizontal
},
halign = "center",
valign = "center",
widget = wibox.container.place
},
layout = wibox.layout.fixed.vertical
},
halign = "center",
valign = "center",
widget = wibox.container.place
}
-- Container for the widget, covers the entire screen
local powermenu_container = wibox {
widget = powermenu,
screen = s,
type = "splash",
visible = false,
ontop = true,
bg = Theme_config.powermenu.container_bg,
height = s.geometry.height,
width = s.geometry.width,
x = s.geometry.x,
y = s.geometry.y
}
-- Close on rightclick
powermenu_container:buttons(
gears.table.join(
awful.button(
{},
3,
function()
capi.awesome.emit_signal("module::powermenu:hide")
end
)
)
)
-- Close on Escape
local powermenu_keygrabber = awful.keygrabber {
autostart = false,
stop_event = 'release',
keypressed_callback = function(self, mod, key, command)
if key == 'Escape' then
capi.awesome.emit_signal("module::powermenu:hide")
end
end
}
-- Signals
capi.awesome.connect_signal(
"module::powermenu:show",
function()
if s == capi.mouse.screen then
powermenu_container.visible = true
powermenu_keygrabber:start()
end
end
)
capi.awesome.connect_signal(
"module::powermenu:hide",
function()
powermenu_keygrabber:stop()
powermenu_container.visible = false
end
)
end

View File

@@ -3,13 +3,13 @@
---------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gears = require('gears')
local wibox = require('wibox')
local color = require("src.lib.color")
local rubato = require("src.lib.rubato")
local color = require('src.lib.color')
local rubato = require('src.lib.rubato')
local capi = {
awesome = awesome,
@@ -21,13 +21,13 @@ return function()
local elements = wibox.widget {
layout = wibox.layout.fixed.horizontal,
spacing = dpi(20),
id = "switcher"
id = 'switcher',
}
local selected = 0
local function create_elements(fn)
fn = fn or ""
fn = fn or ''
elements:reset()
@@ -53,44 +53,43 @@ return function()
{
{ -- Icon
{
id = "icon",
id = 'icon',
--!ADD FALLBACK ICON!--
image = Get_icon(client.class, client.name) or client.icon,
--image = gears.surface(client.content),
valign = "center",
halign = "center",
widget = wibox.widget.imagebox
image = gears.surface(client.icon),
valign = 'center',
halign = 'center',
widget = wibox.widget.imagebox,
},
width = dpi(100),
height = dpi(100),
id = "icon_const",
strategy = "exact",
widget = wibox.container.constraint
id = 'icon_const',
strategy = 'exact',
widget = wibox.container.constraint,
},
{
{
text = client.name,
id = "label",
widget = wibox.widget.textbox
id = 'label',
widget = wibox.widget.textbox,
},
id = "place",
valign = "center",
halign = "center",
widget = wibox.container.place
id = 'place',
valign = 'center',
halign = 'center',
widget = wibox.container.place,
},
id = "layout1",
id = 'layout1',
spacing = dpi(10),
layout = wibox.layout.fixed.vertical
layout = wibox.layout.fixed.vertical,
},
id = "box",
id = 'box',
width = dpi(150),
height = dpi(150),
strategy = "exact",
widget = wibox.container.constraint
strategy = 'exact',
widget = wibox.container.constraint,
},
id = "margin",
id = 'margin',
margins = dpi(20),
widget = wibox.container.margin
widget = wibox.container.margin,
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
@@ -99,13 +98,13 @@ return function()
border_width = Theme_config.window_switcher.border_width,
bg = Theme_config.window_switcher.bg,
fg = Theme_config.window_switcher.element_fg,
widget = wibox.container.background
widget = wibox.container.background,
}
elements:add(window_element)
end
if fn == "next" then
if fn == 'next' then
if selected >= #clients_sorted then
selected = 1
else
@@ -153,15 +152,15 @@ return function()
end
local function update_bg()
element:set_bg("#" .. color.utils.rgba_to_hex { r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos })
element:set_bg('#' .. color.utils.rgba_to_hex { r_timed_bg.pos, g_timed_bg.pos, b_timed_bg.pos })
end
local function update_fg()
element:set_fg("#" .. color.utils.rgba_to_hex { r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos })
element:set_fg('#' .. color.utils.rgba_to_hex { r_timed_fg.pos, g_timed_fg.pos, b_timed_fg.pos })
end
local function update_border()
element.border_color = "#" ..
element.border_color = '#' ..
color.utils.rgba_to_hex { r_timed_border.pos, g_timed_border.pos, b_timed_border.pos }
end
@@ -202,7 +201,7 @@ return function()
set_bg(Theme_config.window_switcher.bg)
end
end
elseif fn == "raise" then
elseif fn == 'raise' then
local c = clients_sorted[selected]
if not c:isvisible() and c.first_tag then
c.first_tag:view_only()
@@ -219,35 +218,35 @@ return function()
elements = create_elements()
capi.awesome.connect_signal(
"window_switcher::select_next",
'window_switcher::select_next',
function()
elements = create_elements("next")
elements = create_elements('next')
end
)
capi.awesome.connect_signal(
"window_switcher::raise",
'window_switcher::raise',
function()
elements = create_elements("raise")
elements = create_elements('raise')
end
)
capi.client.connect_signal(
"manage",
'manage',
function()
elements = create_elements()
end
)
capi.client.connect_signal(
"unmanage",
'unmanage',
function()
elements = create_elements()
end
)
capi.awesome.connect_signal(
"window_switcher::update",
'window_switcher::update',
function()
elements = create_elements()
end

View File

@@ -1,27 +0,0 @@
#!/bin/bash
SINK=$(LC_ALL=C pactl get-default-source)
case $1 in
"volume")
echo $(LC_ALL=C pactl get-source-volume $SINK | awk '{print $5}')
;;
"mute")
echo $(LC_ALL=C pactl get-source-mute $SINK)
;;
"toggle_mute")
$(LC_ALL=C pactl set-source-mute $SINK toggle)
;;
"set_volume")
$(LC_ALL=C pactl set-source-volume $SINK $2)
;;
"set_source")
$(LC_ALL=C pactl set-default-source $2)
;;
esac

View File

@@ -23,8 +23,8 @@ case $1 in
else
if [[ -f "$iconPath" ]];
then
cp "$iconPath" "$userIconPath$USER.png"
printf "$userIconPath$USER.png"
cp "$iconPath" $userIconPath"userpfp.png"
printf $userIconPath"userpfp.png"
exit;
fi
fi

View File

@@ -1,16 +0,0 @@
#!/bin/bash
case $1 in
"volume")
echo $(LC_ALL=C pactl get-sink-volume @DEFAULT_SINK@ | awk '{print $5}')
;;
"mute")
echo $(LC_ALL=C pactl get-sink-mute @DEFAULT_SINK@)
;;
"set_sink")
$(LC_ALL=C pactl set-default-sink $2)
;;
esac

View File

@@ -5,7 +5,6 @@
return {
['White'] = '#ffffff',
['Black'] = '#000000',
['Grey50'] = '#fafafa',
['Grey100'] = '#f5f5f5',
['Grey200'] = '#eeeeee',
@@ -16,7 +15,6 @@ return {
['Grey700'] = '#616161',
['Grey800'] = '#424242',
['Grey900'] = '#212121',
['Red50'] = '#ffebee',
['Red100'] = '#ffcdd2',
['Red200'] = '#ef9a9a',
@@ -31,7 +29,6 @@ return {
['RedA200'] = '#ff5252',
['RedA400'] = '#ff1744',
['RedA700'] = '#d50000',
['Pink50'] = '#fce4ec',
['Pink100'] = '#f8bbd0',
['Pink200'] = '#f48fb1',
@@ -46,7 +43,6 @@ return {
['PinkA200'] = '#ff4081',
['PinkA400'] = '#f50057',
['PinkA700'] = '#c51162',
['Blue50'] = '#e3f2fd',
['Blue100'] = '#bbdefb',
['Blue200'] = '#90caf9',
@@ -61,7 +57,6 @@ return {
['BlueA200'] = '#448aff',
['BlueA400'] = '#2979ff',
['BlueA700'] = '#2962ff',
['Yellow50'] = '#fffde7',
['Yellow100'] = '#fff9c4',
['Yellow200'] = '#fff59d',
@@ -76,7 +71,6 @@ return {
['YellowA200'] = '#ffff00',
['YellowA400'] = '#ffea00',
['YellowA700'] = '#ffd600',
['Teal50'] = '#e0f2f1',
['Teal100'] = '#b2dfdb',
['Teal200'] = '#80cbc4',
@@ -91,7 +85,6 @@ return {
['TealA200'] = '#64ffda',
['TealA400'] = '#1de9b6',
['TealA700'] = '#00bfa5',
['Green50'] = '#e8f5e9',
['Green100'] = '#c8e6c9',
['Green200'] = '#a5d6a7',
@@ -106,7 +99,6 @@ return {
['GreenA200'] = '#69f0ae',
['GreenA400'] = '#00e676',
['GreenA700'] = '#00c853',
['Orange50'] = '#fff3e0',
['Orange100'] = '#ffe0b2',
['Orange200'] = '#ffcc80',
@@ -121,7 +113,6 @@ return {
['OrangeA200'] = '#ffab40',
['OrangeA400'] = '#ff9100',
['OrangeA700'] = '#ff6d00',
['DeepOrange50'] = '#fbe9e7',
['DeepOrange100'] = '#ffccbc',
['DeepOrange200'] = '#ffab91',
@@ -136,7 +127,6 @@ return {
['DeepOrangeA200'] = '#ff6e40',
['DeepOrangeA400'] = '#ff3d00',
['DeepOrangeA700'] = '#dd2c00',
['Purple50'] = '#F3E5F5',
['Purple100'] = '#E1BEE7',
['Purple200'] = '#CE93D8',
@@ -151,7 +141,6 @@ return {
['PurpleA200'] = '#E040FB',
['PurpleA500'] = '#D500F9',
['PurpleA700'] = '#AA00FF',
['DeepPurple50'] = '#EDE7F6',
['DeepPurple100'] = '#D1C4E9',
['DeepPurple200'] = '#B39DDB',
@@ -166,7 +155,6 @@ return {
['DeepPurpleA200'] = '#7C4DFF',
['DeepPurpleA400'] = '#651FFF',
['DeepPurpleA700'] = '#6200EA',
['LightBlue50'] = '#E1F5FE',
['LightBlue100'] = '#B3E5FC',
['LightBlue200'] = '#81D4FA',
@@ -181,7 +169,6 @@ return {
['LightBlueA200'] = '#40C4FF',
['LightBlueA400'] = '#00B0FF',
['LightBlueA700'] = '#0091EA',
['Cyan50'] = '#E0F7FA',
['Cyan100'] = '#B2EBF2',
['Cyan200'] = '#80DEEA',
@@ -196,8 +183,6 @@ return {
['CyanA200'] = '#18FFFF',
['CyanA400'] = '#00E5FF',
['CyanA700'] = '#00B8D4',
['BlueGrey50'] = '#ECEFF1',
['BlueGrey100'] = '#CFD8DC',
['BlueGrey200'] = '#B0BEC5',
@@ -207,5 +192,5 @@ return {
['BlueGrey600'] = '#546E7A',
['BlueGrey700'] = '#455A64',
['BlueGrey800'] = '#37474F',
['BlueGrey900'] = '#263238'
['BlueGrey900'] = '#263238',
}

View File

@@ -6,16 +6,20 @@
-- ╚██████╗██║ ██║ ██║ ███████╗██║██║ ██║ --
-- ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚══════╝╚═╝╚═╝ ╚═╝ --
--------------------------------------------------
local beautiful = require("beautiful")
local gears = require("gears")
local beautiful = require('beautiful')
local gwallpaper = require('gears.wallpaper')
local gfilesystem = require('gears.filesystem')
local capi = {
awesome = awesome,
screen = screen,
}
Theme_path = gears.filesystem.get_configuration_dir() .. "/src/theme/"
Theme_path = gfilesystem.get_configuration_dir() .. '/src/theme/'
Theme = {}
awesome.set_preferred_icon_size(128)
-- Default font, change it in user_config, not here.
Theme.font = User_config.font.bold
@@ -51,17 +55,17 @@ Theme.hotkeys_label_fg = Theme_config.hotkeys.label_fg
-- Wallpaper
beautiful.wallpaper = User_config.wallpaper
capi.screen.connect_signal(
'request::wallpaper',
function(s)
capi.screen.connect_signal('request::wallpaper', function(s)
if beautiful.wallpaper then
if type(beautiful.wallpaper) == 'string' then
gears.wallpaper.maximized(beautiful.wallpaper, s)
gwallpaper.maximized(beautiful.wallpaper, s)
else
beautiful.wallpaper(s)
end
end
end
)
end)
beautiful.init(Theme)
-- Load titlebar
require('src.core.titlebar')()

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +1,9 @@
-------------------------------------------
-- Uservariables are stored in this file --
-------------------------------------------
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local home = os.getenv("HOME")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local home = os.getenv('HOME')
-- If you want different default programs, wallpaper path or modkey; edit this file.
User_config = {
@@ -17,10 +17,13 @@ User_config = {
Flatpak application: flatpak run com.example.App
]] --
autostart = {
"picom",
"/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1",
"setxkbmap -option caps:swapescape",
"/home/crylia/.screenlayout/double.sh"
'nm-applet',
'protonvpn-cli ks --off',
'picom',
'/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1',
'setxkbmap -option caps:swapescape',
'/home/crylia/.screenlayout/double.sh',
'gnome-keyring-daemon --start --components=secrets',
},
--[[
@@ -43,7 +46,7 @@ User_config = {
"MEDIA_PLAYER"
More information at: https://lazka.github.io/pgi-docs/UPowerGlib-1.0/enums.html#UPowerGlib.DeviceKind.KEYBOARD
]] --
battery_kind = "LINE_POWER",
battery_kind = 'LINE_POWER',
--[[
If your battery is not found you can specify its path here.
@@ -61,6 +64,8 @@ User_config = {
]]
brightness_step = 2,
clock_mode = 'average',
--[[
DnD or 'Do not Disturb' will prevent notifications from poping up.
This is just a default value, you can toggle it in the notification-center, but it won't be saved.
@@ -78,12 +83,12 @@ User_config = {
This is the program that will be started when clicking on the battery widget
If you don't want any just leave it as nil
]] --
energy_manager = "xfce4-power-manager-settings",
energy_manager = 'xfce4-power-manager-settings',
--[[
Your filemanager. Will be opened with <super> + <e>
]] --
file_manager = "nautilus",
file_manager = 'nemo',
--[[
The font that will be used on all widgets/modules etc.
@@ -98,19 +103,19 @@ User_config = {
}
]]
font = {
regular = "JetBrainsMono Nerd Font, " .. dpi(16),
bold = "JetBrainsMono Nerd Font, bold " .. dpi(16),
extrabold = "JetBrainsMono Nerd Font, ExtraBold " .. dpi(16),
specify = "JetBrainsMono Nerd Font"
regular = 'JetBrainsMono Nerd Font, ' .. dpi(16),
bold = 'JetBrainsMono Nerd Font, bold ' .. dpi(16),
extrabold = 'JetBrainsMono Nerd Font, ExtraBold ' .. dpi(16),
specify = 'JetBrainsMono Nerd Font',
},
gtk_settings = "lxappearance",
gtk_settings = 'lxappearance',
--[[
The icon theme name must be exactly as the folder is called
The folder can be in any $XDG_DATA_DIRS/icons/[icon_theme_name]
]] --
icon_theme = "Papirus-Dark",
icon_theme = 'Papirus-Dark',
-- List every Keyboard layout you use here comma seperated. (run localectl list-keymaps to list all averiable keymaps)
--[[
@@ -119,28 +124,15 @@ User_config = {
Example:
kblayout = { "de", "ru", "us" }
]] --
kblayout = { "de", "ru" },
kblayout = { 'de', 'ru' },
--[[
This is a list of every layout you can use.
Remove every that you don't want to use.
]] --
layouts = {
awful.layout.suit.tile,
awful.layout.suit.tile.left,
awful.layout.suit.tile.bottom,
awful.layout.suit.tile.top,
awful.layout.suit.floating,
awful.layout.suit.fair,
awful.layout.suit.fair.horizontal,
awful.layout.suit.corner.nw,
awful.layout.suit.corner.ne,
awful.layout.suit.corner.sw,
awful.layout.suit.corner.se,
awful.layout.suit.magnifier,
awful.layout.suit.max,
awful.layout.suit.max.fullscreen,
awful.layout.suit.spiral.dwindle,
awful.layout.suit.floating,
},
--[[
@@ -153,9 +145,9 @@ User_config = {
"mod4" <-- for the super/windows key
"mod5" <-- for the shift key
]] --
modkey = "Mod4",
modkey = 'Mod4',
music_player = "flatpak run com.spotify.Client",
music_player = 'spotify',
--[[
This is the naming sheme used for the powermenu and maybe some other places in the future.
@@ -164,7 +156,7 @@ User_config = {
"fullname" <-- Will display "Firstname Surname"
"?" <-- Will display "?"
]] --
namestyle = "userhost",
namestyle = 'userhost',
--[[
This is used to identify your network adapters.
@@ -174,16 +166,16 @@ User_config = {
ethernet = "eno1"
]] --
network = {
wlan = "wlo1",
ethernet = "eno1"
wlan = 'wlo1',
ethernet = 'eno1',
},
screen_settings = "arandr",
screen_settings = 'arandr',
--[[
This is the program that will be executed when hitting the print key.
]] --
screenshot_program = "flameshot gui",
screenshot_program = 'flameshot gui',
--[[
These are the status bar widgets which are to be found in the notification-center.
@@ -199,13 +191,13 @@ User_config = {
"backlight"
]] --
status_bar_widgets = {
"cpu_usage",
"cpu_temp",
"ram_usage",
"microphone",
"volume",
"gpu_temp",
"gpu_usage",
'cpu_usage',
'cpu_temp',
'ram_usage',
'microphone',
'volume',
'gpu_temp',
'gpu_usage',
},
--[[
@@ -217,9 +209,9 @@ User_config = {
--[[
This is the default terminal, Alacritty is the default.
]] --
terminal = "kitty",
terminal = 'kitty',
text_editor = "code",
text_editor = 'code',
--[[
Add every client that should get no titlebar.
@@ -233,7 +225,7 @@ User_config = {
}
]] --
titlebar_exception = {
"protonvpn"
'protonvpn',
},
--[[
@@ -241,13 +233,19 @@ User_config = {
Example:
titlebar_position = "top"
]] --
titlebar_position = "top",
titlebar_position = 'left',
titlebar_items = {
left_and_bottom = { 'icon' },
--middle = "title",
right_and_top = { 'close', 'maximize', 'minimize' },
},
--[[
This is the path to your wallpaper.
home is $HOME, you can also use an absolute path.
]] --
wallpaper = home .. "/Bilder/Hintergründe/784194.jpg",
wallpaper = home .. '/Bilder/Hintergründe/784194.jpg',
--[[
This is the weather widget.
@@ -258,12 +256,12 @@ User_config = {
unit = "metric" or "imperial"
]]
weather_secrets = {
key = "e71b00168ca7219563dde4514a425b14",
city_id = "2864118",
unit = "metric"
key = 'e71b00168ca7219563dde4514a425b14',
city_id = '2864118',
unit = 'metric',
},
web_browser = "firefox",
web_browser = 'firefox',
--[[
You can configure your bar's here, if you leave it empty the bar will not be shown.
@@ -293,65 +291,64 @@ User_config = {
crylia_bar = {
[1] = {
left_bar = {
"Tiling Layout",
"Systray",
"Taglist"
'Tiling Layout',
'Systray',
'Taglist',
},
center_bar = {
"Tasklist"
'Tasklist',
},
right_bar = {
"Cpu Frequency",
"Cpu Temperature",
"Cpu Usage",
"Audio",
"Keyboard Layout",
"Date",
"Clock",
"Power Button"
}
'Bluetooth',
'Network',
'Cpu Frequency',
'Cpu Usage',
'Cpu Temperature',
'Audio',
'Keyboard Layout',
'Date',
'Clock',
'Power Button',
},
--[[ [2] = {
},
[2] = {
left_bar = {
"Tiling Layout",
"Systray",
"Taglist"
'Tiling Layout',
'Taglist',
},
center_bar = {
"Tasklist"
'Tasklist',
},
right_bar = {
"Gpu Temperature",
"Gpu Usage",
"Ram",
"Audio",
"Keyboard Layout",
"Date",
"Clock",
"Power Button"
}
}]]
'Gpu Temperature',
'Gpu Usage',
'Ram Usage',
'Audio',
'Date',
'Clock',
},
},
},
crylia_wibox = {
[1] = {
left_bar = {
"Tiling Layout",
"Taglist"
'Tiling Layout',
'Taglist',
},
center_bar = {
"Tasklist"
'Tasklist',
},
right_bar = {
"Systray",
"Battery",
"Bluetooth",
"Audio",
"Network",
"Keyboard Layout",
"Date",
"Clock",
}
}
}
'Systray',
'Battery',
'Bluetooth',
'Audio',
'Network',
'Keyboard Layout',
'Date',
'Clock',
},
},
},
}

View File

@@ -1,20 +1,19 @@
local awful = require("awful")
local Gio = require("lgi").Gio
local gears = require("gears")
local Gio = require('lgi').Gio
local aspawn = require('awful.spawn')
local gfilesystem = require('gears.filesystem')
return function(table)
for _, t in ipairs(table) do
awful.spawn(t);
aspawn(t);
end
local path = gears.filesystem.get_xdg_config_home() .. "autostart/"
local handler = io.popen("ls " .. path)
local path = gfilesystem.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))
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(Gio.DesktopAppInfo.get_string(app, 'Exec'), nil, 0))
end
end
end

View File

@@ -0,0 +1,87 @@
local lgi = require('lgi')
local GLib = lgi.GLib
local Gio = lgi.Gio
local gobject = require('gears.object')
local gtable = require('gears.table')
local gfilesystem = require('gears.filesystem')
local aspawn = require('awful.spawn')
local json = require('src.lib.json-lua.json-lua')
local config = {}
local instance
---Takes a file path and puts the content into the callback
---@param path string file path, caller has to make sure it exists
---@return string|nil file_content
config.read = function(path)
local handler = io.open(path, 'r')
if not handler then error('Invalid path') return end
local content = handler:read('*all')
handler:close()
return content
end
---Writes a string to a file
---@param path string file path, caller has to make sure it exists
---@param content string content to write
config.write = function(path, content)
local handler = io.open(path, 'w')
if not handler then error('Invalid path') return end
handler:write(content)
handler:close()
end
config.read_json = function(path)
local handler = io.open(path, 'r')
if not handler then error('Invalid path') return end
local content = handler:read('*all')
handler:close()
local json_content = json:decode(content) or {}
assert(type(json_content) == 'table', 'json is not a table')
return json_content
end
config.write_json = function(path, content)
local json_content = json:encode(content)
assert(type(json_content) == 'string', 'json is not a string')
local handler = io.open(path, 'w')
if not handler then error('Invalid path') return end
handler:write(json_content)
handler:close()
end
local function new()
local ret = gobject {}
gtable.crush(ret, config, true)
-- Create config files if they don't exist
for _, file in pairs { 'floating.json', 'dock.json', 'desktop.json', 'applications.json' } do
if not gfilesystem.file_readable(gfilesystem.get_configuration_dir() .. 'src/config/' .. file) then
aspawn('touch ' .. gfilesystem.get_configuration_dir() .. 'src/config/' .. file)
end
end
-- Create config directories if they don't exist
for _, dir in pairs { 'files/desktop/icons' } do
if not gfilesystem.dir_readable(gfilesystem.get_configuration_dir() .. 'src/config/' .. dir) then
gfilesystem.make_directories(gfilesystem.get_configuration_dir() .. 'src/config/' .. dir)
end
end
return ret
end
if not instance then
instance = new()
end
return instance

View File

@@ -1,84 +1,23 @@
-- Libraries
local lgi = require("lgi")
local Gtk = lgi.require("Gtk", "3.0")
local Gio = lgi.Gio
local gears = require("gears")
local GLib = require("lgi").GLib
-- Get all .desktop files as gobjects
local app_info = Gio.AppInfo
local app_list = app_info.get_all()
local lgi = require('lgi')
local Gtk = lgi.require('Gtk', '3.0')
-- Init a new Gtk theme from the users string
local gtk_theme = Gtk.IconTheme.new()
Gtk.IconTheme.set_custom_theme(gtk_theme, User_config.icon_theme)
local gtk_theme = Gtk.IconTheme.get_default()
---Gets the icon path from an AppInfo gicon.
---@param app Gio.AppInfo
---@param app Gio.AppInfo|nil
---@param icon_string string|nil
---@return string|nil path
function Get_gicon_path(app)
if not app then return end
local icon_info = gtk_theme:lookup_by_gicon(app, 64, 0)
if icon_info then
local path = icon_info:get_filename()
if path then
return path
end
end
return ""
function Get_gicon_path(app, icon_string)
if (not app) and (not icon_string) then return end
if icon_string then
return gtk_theme:lookup_icon(icon_string, 64, 0):get_filename() or ''
end
---Takes a class and name string and tries to match it to an icon.
---@param class string
---@param name string
---@return string | nil icon_path
function Get_icon(class, name)
class = string.lower(class or "")
name = string.lower(name or "")
for _, app in ipairs(app_list) do
local desktop_app_info = Gio.DesktopAppInfo.new(app_info.get_id(app))
local icon_string = Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon")
if icon_string then
icon_string = string.lower(icon_string)
if icon_string == class or icon_string == name then
return Get_gicon_path(app_info.get_icon(app))
elseif icon_string:match(class) then
return Get_gicon_path(app_info.get_icon(app))
end
end
local icon_info = gtk_theme:lookup_by_gicon(app, 64, 0)
if icon_info then
return icon_info:get_filename()
end
return nil
end
---Will return every $XDG_DATA_DIRS
---@return table
local function get_paths()
local dirs = {}
local dir
for _, value in ipairs(GLib.get_system_data_dirs()) do
dir = GLib.build_filenamev({ value, "applications" })
if gears.filesystem.dir_readable(dir) then table.insert(dirs, dir) end
end
dir = GLib.build_filenamev({ GLib.get_user_data_dir(), "applications" })
if gears.filesystem.dir_readable(dir) then table.insert(dirs, dir) end
return dirs
end
---Returns every .desktop file into a table
---@param file string .desktop files
---@return string | nil path
function Get_desktop_values(file)
if not file or file == "" then
return
end
for _, dir in ipairs(get_paths()) do
if gears.filesystem.file_readable(dir .. "/" .. file, "r") then
return dir .. "/" .. file
end
end
end

View File

@@ -1,61 +1,108 @@
local aspawn = require("awful.spawn")
local aspawn = require('awful.spawn')
local gobject = require('gears.object')
local gtable = require('gears.table')
local capi = {
awesome = awesome,
}
local audio = {}
local instance = nil
function audio.set_sink_volume(volume)
aspawn('pactl set-sink-volume @DEFAULT_SINK@ ' .. volume .. '%')
end
function audio.set_source_volume(volume)
aspawn('pactl set-source-volume @DEFAULT_SOURCE@ ' .. volume .. '%')
end
function audio.sink_volume_up()
aspawn('pactl set-sink-volume @DEFAULT_SINK@ +2%')
end
function audio.source_volume_up()
aspawn('pactl set-source-volume @DEFAULT_SOURCE@ +2%')
end
function audio.sink_volume_down()
aspawn('pactl set-sink-volume @DEFAULT_SINK@ -2%')
end
function audio.source_volume_down()
aspawn('pactl set-source-volume @DEFAULT_SOURCE@ -2%')
end
function audio.sink_toggle_mute()
aspawn('pactl set-sink-mute @DEFAULT_SINK@ toggle')
end
function audio.source_toggle_mute()
aspawn('pactl set-source-mute @DEFAULT_SOURCE@ toggle')
end
local function new()
local self = gobject {}
gtable.crush(self, audio, true)
aspawn.with_line_callback([[bash -c "LC_ALL=C pactl subscribe"]], {
stdout = function(line)
-- Volume changed
if line:match("on sink") or line:match("on source") then
capi.awesome.emit_signal("audio::volume_changed")
capi.awesome.emit_signal("microphone::volume_changed")
if line:match('on sink') or line:match('on source') then
self:emit_signal('sink::volume_changed')
self:emit_signal('source::volume_changed')
end
-- Device added/removed
if line:match("on server") then
capi.awesome.emit_signal("audio::device_changed")
capi.awesome.emit_signal("microphone::device_changed")
if line:match('on server') then
self:emit_signal('sink::device_changed')
self:emit_signal('source::device_changed')
end
end,
output_done = function()
aspawn.with_shell("pkill pactl && pkill grep")
end
aspawn.with_shell('pkill pactl && pkill grep')
end,
})
capi.awesome.connect_signal("audio::volume_changed", function()
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/vol.sh mute", function(stdout)
if stdout == "" or stdout == nil then
self:connect_signal('sink::volume_changed', function()
aspawn.easy_async_with_shell([[LC_ALL=C pactl get-sink-mute @DEFAULT_SINK@]], function(stdout)
if stdout == '' or stdout == nil then
return
end
local muted = false
if stdout:match("yes") then
if stdout:match('yes') then
muted = true
end
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/vol.sh volume", function(stdout2)
if stdout == "" or stdout == nil then
aspawn.easy_async_with_shell([[LC_ALL=C pactl get-sink-volume @DEFAULT_SINK@ | awk '{print $5}']], function(stdout2)
if stdout == '' or stdout == nil then
return
end
capi.awesome.emit_signal("audio::get", muted, stdout2:gsub("%%", ""):gsub("\n", "") or 0)
self:emit_signal('sink::get', muted, stdout2:gsub('%%', ''):gsub('\n', '') or 0)
end)
end)
end)
capi.awesome.connect_signal("microphone::volume_changed", function()
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/mic.sh mute", function(stdout)
self:connect_signal('source::volume_changed', function()
aspawn.easy_async_with_shell([[LC_ALL=C pactl get-source-mute @DEFAULT_SOURCE@]], function(stdout)
local muted = false
if stdout:match("yes") then
if stdout:match('yes') then
muted = true
end
aspawn.easy_async_with_shell("./.config/awesome/src/scripts/mic.sh volume", function(stdout2)
if stdout2 == nil or stdout2 == "awful" then
aspawn.easy_async_with_shell([[LC_ALL=C pactl get-source-volume @DEFAULT_SOURCE@ | awk '{print $5}']], function(stdout2)
if stdout2 == nil or stdout2 == 'awful' then
return
end
capi.awesome.emit_signal("microphone::get", muted, stdout2:gsub("%%", ""):gsub("\n", "") or 0)
self:emit_signal('source::get', muted, stdout2:gsub('%%', ''):gsub('\n', '') or 0)
end)
end)
end)
capi.awesome.emit_signal("audio::volume_changed")
capi.awesome.emit_signal("microphone::volume_changed")
capi.awesome.emit_signal("audio::device_changed")
capi.awesome.emit_signal("microphone::device_changed")
self:emit_signal('sink::volume_changed')
self:emit_signal('source::volume_changed')
self:emit_signal('sink::device_changed')
self:emit_signal('source::device_changed')
return self
end
if not instance then
instance = new()
end
return instance

View File

@@ -1,57 +1,41 @@
local aspawn = require("awful.spawn")
local capi = {
awesome = awesome,
}
local aspawn = require('awful.spawn')
local gobject = require('gears.object')
local gtable = require('gears.table')
local backlight = {}
backlight.device = ""
local instance = nil
backlight.max_brightness = 1
function backlight.brightness_get_async(callback)
aspawn.easy_async_with_shell('brightnessctl get', function(stdout)
callback(tonumber(stdout:gsub('\n', '')))
end)
end
function backlight:brightness_increase()
aspawn('brightnessctl set +2%')
self:emit_signal('brightness_changed')
end
function backlight:brightness_decrease()
aspawn('brightnessctl set -2%')
self:emit_signal('brightness_changed')
end
local function new()
local self = gobject {}
gtable.crush(self, backlight, true)
-- Init the backlight device and get the max brightness
aspawn.easy_async_with_shell("ls /sys/class/backlight/", function(stdout)
backlight.device = stdout:gsub("%s+", "")
aspawn.easy_async_with_shell("cat /sys/class/backlight/" .. backlight.device .. "/max_brightness", function(stdout)
backlight.max_brightness = tonumber(stdout:gsub("\n", "") or 0)
end)
aspawn.easy_async_with_shell('brightnessctl max', function(stdout)
self.max_brightness = tonumber(stdout:gsub('\n', '') or 1)
end)
function backlight.brightness_get()
aspawn.easy_async_with_shell("cat /sys/class/backlight/" .. backlight.device .. "/brightness", function(stdout)
capi.awesome.emit_signal("brightness::get", tonumber(stdout))
end)
return self
end
function backlight.brightness_get_percent()
aspawn.easy_async_with_shell("cat /sys/class/backlight/" .. backlight.device .. "/brightness", function(stdout)
capi.awesome.emit_signal("brightness::get_percent",
math.floor((tonumber(stdout) / backlight.max_brightness * 100) + 0.5))
end)
if not instance then
instance = new()
end
function backlight.brightness_set(value)
if value < 0 or value > (backlight.max_brightness or 24000) then return end
aspawn.with_shell("echo " .. math.floor(value) .. " > /sys/class/backlight/" .. backlight.device .. "/brightness")
end
function backlight.brightness_increase()
aspawn.easy_async_with_shell("cat /sys/class/backlight/" .. backlight.device .. "/brightness", function(stdout)
local new_value = tonumber(stdout:gsub("\n", "") or 0) +
(backlight.max_brightness / 100 * User_config.brightness_step)
backlight.brightness_set(new_value)
capi.awesome.emit_signal("brightness::changed", new_value)
end)
end
function backlight.brightness_decrease()
aspawn.easy_async_with_shell("cat /sys/class/backlight/" .. backlight.device .. "/brightness", function(stdout)
local new_value = tonumber(stdout:gsub("\n", "") or 0) -
(backlight.max_brightness / 100 * User_config.brightness_step)
backlight.brightness_set(new_value)
capi.awesome.emit_signal("brightness::changed", new_value)
end)
end
return backlight
return instance

View File

@@ -1,30 +1,34 @@
local awful = require("awful")
local watch = awful.widget.watch
local gobject = require('gears.object')
local watch = require('awful.widget.watch')
local capi = {
awesome = awesome,
}
local instance = nil
watch(
[[ bash -c "cat /proc/cpuinfo | grep "MHz" | awk '{print int($4)}'" ]],
3,
function(_, stdout)
local function new()
local self = gobject {}
watch("bash -c \"cat /proc/cpuinfo | grep 'MHz' | awk '{print int($4)}'\"", 2, function(_, stdout)
local cpu_freq = {}
for value in stdout:gmatch("%d+") do
for value in stdout:gmatch('%d+') do
table.insert(cpu_freq, value)
end
local average = 0
if User_config.clock_mode == "average" then
if User_config.clock_mode == 'average' then
for i = 1, #cpu_freq do
average = average + cpu_freq[i]
end
average = math.floor(average / #cpu_freq)
capi.awesome.emit_signal("update::cpu_freq_average", average)
average = math.floor((average / #cpu_freq) + 0.5)
self:emit_signal('update::cpu_freq_average', average)
elseif User_config.clock_mode then
capi.awesome.emit_signal("update::cpu_freq_core", cpu_freq[User_config.clock_mode])
self:emit_signal('update::cpu_freq_core', cpu_freq[User_config.clock_mode])
end
end)
return self
end
)
if not instance then
instance = new()
end
return instance

View File

@@ -1,32 +1,29 @@
local awful = require("awful")
local watch = awful.widget.watch
local aspawn = require('awful.spawn')
local awatch = require('awful.widget.watch')
local gobject = require('gears.object')
local capi = {
awesome = awesome,
}
local instance = nil
watch(
[[ bash -c "sensors | grep 'Package id 0:' | awk '{print $4}'" ]],
3,
function(_, stdout)
local temp = tonumber(stdout:match("%d+"))
if not temp or temp == "" then
awful.spawn.easy_async_with_shell(
"paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp)",
function(stdout2)
if (not stdout2) or stdout:match("\n") then return end
temp = math.floor((tonumber(stdout2:match("x86_pkg_temp(.%d+)")) / 1000) + 0.5)
capi.awesome.emit_signal(
"update::cpu_temp",
temp
)
end
)
local function new()
local self = gobject {}
awatch([[ bash -c "sensors | grep 'Package id 0:' | awk '{print $4}'" ]], 2, function(_, stdout)
local temp = tonumber(stdout:match('%d+'))
if not temp or temp == '' then
aspawn.easy_async_with_shell('paste <(cat /sys/class/thermal/thermal_zone*/type) <(cat /sys/class/thermal/thermal_zone*/temp)', function(stdout2)
if (not stdout2) or stdout:match('\n') then return end
temp = math.floor((tonumber(stdout2:match('x86_pkg_temp(.%d+)')) / 1000) + 0.5)
self:emit_signal('update::cpu_temp', temp)
end)
else
capi.awesome.emit_signal(
"update::cpu_temp",
temp
)
self:emit_signal('update::cpu_temp', temp)
end
end)
return self
end
)
if not instance then
instance = new()
end
return instance

View File

@@ -1,32 +1,43 @@
local awful = require("awful")
local watch = awful.widget.watch
local aspawn = require('awful.spawn')
local gobject = require('gears.object')
local gtimer = require('gears.timer')
local capi = {
awesome = awesome,
}
local instance = nil
--!Find a better way that doesn't need manual GC since it has a huge performance impact
local function new()
local self = gobject {}
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)
gtimer {
timeout = 2,
autostart = true,
call_now = true,
callback = function()
aspawn.easy_async_with_shell([[ cat "/proc/stat" | grep '^cpu ' ]], function(stdout)
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")
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
local diff_idle = idle - idle_prev
local diff_total = total - total_prev
local diff_usage = math.floor(((1000 * (diff_total - diff_idle) / diff_total + 5) / 10) + 0.5)
local diff_usage = math.floor(((1000 * (diff_total - (idle - idle_prev)) / diff_total + 5) / 10) + 0.5)
capi.awesome.emit_signal("update::cpu_usage", diff_usage)
self:emit_signal('update::cpu_usage', diff_usage)
total_prev = total
idle_prev = idle
collectgarbage("collect")
end)
end
)
}
return self
end
if not instance then
instance = new()
end
return instance

View File

@@ -1,15 +1,19 @@
local awful = require("awful")
local watch = awful.widget.watch
local awatch = require('awful.widget.watch')
local gobject = require('gears.object')
local capi = {
awesome = awesome,
}
local instance = nil
watch(
[[ bash -c "nvidia-smi -q -d TEMPERATURE | grep 'GPU Current Temp' | awk '{print $5}'"]],
3,
function(_, stdout)
if not stdout:gsub("\n", "") then return end
capi.awesome.emit_signal("update::gpu_temp", stdout:match("%d+"):gsub("\n", ""))
local function new()
local self = gobject {}
awatch([[ bash -c "nvidia-smi -q -d TEMPERATURE | grep 'GPU Current Temp' | awk '{print $5}' | head -n 1"]], 3, function(_, stdout)
stdout = stdout:match('%d+')
if not stdout then return end
self:emit_signal('update::gpu_temp', stdout)
end)
return self
end
)
if not instance then
instance = new()
end
return instance

View File

@@ -1,16 +1,19 @@
local awful = require("awful")
local watch = awful.widget.watch
local awatch = require('awful.widget.watch')
local gobject = require('gears.object')
local capi = {
awesome = awesome,
}
local instance
watch(
[[ bash -c "nvidia-smi -q -d UTILIZATION | grep Gpu | awk '{print $3}'"]],
3,
function(_, stdout)
stdout = stdout:match("%d+")
local function new()
local self = gobject {}
awatch([[ bash -c "nvidia-smi -q -d UTILIZATION | grep Gpu | awk '{print $3}'"]], 3, function(_, stdout)
stdout = stdout:match('%d+')
if not stdout then return end
capi.awesome.emit_signal("update::gpu_usage", stdout)
self:emit_signal('update::gpu_usage', stdout)
end)
return self
end
)
if not instance then
instance = new()
end
return instance

View File

@@ -0,0 +1,48 @@
-- Awesome libs
local gobject = require('gears.object')
local gtable = require('gears.table')
local aspawn = require('awful.spawn')
local instance = nil
local kb_helper = {}
function kb_helper:cycle_layout()
self:get_layout_async(function(layout)
local index = gtable.hasitem(self.layout_list, layout)
if index then
if index == #self.layout_list then
self:set_layout(self.layout_list[1])
else
self:set_layout(self.layout_list[index + 1])
end
else
self:set_layout(self.layout_list[1])
end
end)
end
function kb_helper:set_layout(keymap)
aspawn('setxkbmap ' .. keymap)
self:emit_signal('KB::layout_changed', keymap)
end
function kb_helper:get_layout_async(callback)
aspawn.easy_async_with_shell([[ setxkbmap -query | grep layout | awk '{print $2}' ]], function(stdout)
callback(stdout:gsub('\n', ''))
end)
end
local function new()
local self = gobject {}
gtable.crush(self, kb_helper, true)
self.layout_list = User_config.kblayout
return self
end
if not instance then
instance = new()
end
return instance

View File

@@ -1,349 +1,213 @@
-- 99.9% Stolen from bling
local Playerctl = require('lgi').Playerctl
local http_request = require('http.request')
local Cairo = require('lgi').cairo
local Gdk = require('lgi').Gdk
local GdkPixbuf = require('lgi').GdkPixbuf
local gfilesystem = require('gears.filesystem')
local gtimer = require('gears.timer')
local gcolor = require('gears.color')
local gtable = require('gears.table')
local gobject = require("gears.object")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local gstring = require("gears.string")
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/notifications/'
local capi = {
awesome = awesome
Gdk.init {}
local instance = nil
local music_player = {}
--#region Audio control mappings
function music_player:next() self.player:next() end
function music_player:prev() self.player:previous() end
function music_player:play_pause() self.player:play_pause() end
function music_player:play() self.player:play() end
function music_player:pause() self.player:pause() end
--TODO: Needs validation
function music_player:get_length()
local length = self.player:print_metadata_prop('mpris:length') or 0
return tonumber(length) / 1000000
end
function music_player:set_shuffle()
self.player:set_shuffle(not self.player.shuffle)
end
-- None, Track, Playlist, loops trough them if not specified
function music_player:set_loop_status(state)
if state then
self.player:set_loop_status(state)
return
end
if self.player.loop_status == 'NONE' then
self.player:set_loop_status('PLAYLIST')
elseif self.player.loop_status == 'PLAYLIST' then
self.player:set_loop_status('TRACK')
elseif self.player.loop_status == 'TRACK' then
self.player:set_loop_status('NONE')
end
end
--#endregion
--#region Metadata getter and setter
function music_player:get_artist() return self.player:get_artist() end
function music_player:get_title() return self.player:get_title() end
function music_player:get_album() return self.player:get_album() end
function music_player:get_position() return (self.player:get_position() / 1000000) end
function music_player:set_position() return self.player:set_position() end
function music_player:get_art(url)
url = url or self.player:print_metadata_prop('mpris:artUrl')
if url and url:match('^https?://') then
local scheme = http_request.new_from_uri(url)
if not scheme then return end
local headers, stream = assert(scheme:go())
if not (stream or headers) then return end
local body = assert(stream:get_body_as_string())
if headers:get ':status' ~= '200' then
error(body)
end
local loader = GdkPixbuf.PixbufLoader()
loader:write(body)
loader:close()
local image = loader:get_pixbuf()
local surface = Cairo.ImageSurface.create(Cairo.Format.ARGB32, image:get_width(), image:get_height())
local cr = Cairo.Context(surface)
-- Render the image onto the surface
Gdk.cairo_set_source_pixbuf(cr, image, 0, 0)
cr:paint()
body = nil
loader = nil
image = nil
collectgarbage()
return surface
elseif url and url:match('^file://') then
return url:gsub('%%(%x%x)', function(h) return string.char(tonumber(h, 16)) end):gsub('^file://', '')
end
return icondir .. 'default_image.svg'
end
--#endregion
local priority_players = {
'vlc',
'spotify',
}
local playerctl = { mt = {} }
playerctl._private = {}
function music_player:player_gets_priority(name)
-- If for some reason there is no player, manage the new one
if not name then return true end
function playerctl:play_pause(player)
player = player or self._private.manager.players[1]
if player then
player:play_pause()
end
for _, n in ipairs(priority_players) do
if name.name:lower():match(n) then return true 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
capi.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)
capi.awesome.emit_signal("playerctl::playback_status", true, player.player_name)
else
self:emit_signal("playerctl::playback_status", false, player.player_name)
capi.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
-- If the currently managed player is playing, don't change it
if self.player.playback_status == 'PLAYING' then return false end
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
local function start_manage(self, w, name)
if not self._private.pos_timer.started then
self._private.pos_timer:start()
end
end
end
if not self:player_gets_priority(name) then return end
self.player = Playerctl.Player.new_from_name(name)
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
self.playermanager:manage_player(self.player)
if player_a == player_b then
return 0
end
if not self.player.player_name then return 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 {
local function on_metadata(_, metadata)
if not metadata then return end
w:get_children_by_id('title')[1].text = metadata.value['xesam:title'] or 'Unknown Title'
w:get_children_by_id('artist')[1].text = metadata.value['xesam:artist'] and metadata.value['xesam:artist'][1] or 'Unknown Artist'
local length = (metadata.value['mpris:length'] or 0) / 1000000
w:get_children_by_id('length')[1].text = string.format('%02d:%02d', math.floor(length / 60), math.floor(length % 60))
w:get_children_by_id('progress')[1].max_value = length
w:get_children_by_id('album_art')[1].image = self:get_art(metadata.value['mpris:artUrl'])
self.gtimer = gtimer {
timeout = 1,
autostart = true,
callback = function()
pos_callback(self)
end
local position = self:get_position()
w:get_children_by_id('position')[1].text = string.format('%02d:%02d', math.floor(position / 60), math.floor(position % 60))
w:get_children_by_id('progress')[1].value = position
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
self.player.on_metadata = on_metadata
on_metadata(nil, self.player.metadata)
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
local function on_loop_status(_, status)
if status == 'TRACK' then
w:get_children_by_id('repeat')[1].image = gcolor.recolor_image(icondir .. 'repeat-once.svg',
Theme_config.notification_center.song_info.repeat_all)
elseif status == 'PLAYLIST' then
w:get_children_by_id('repeat')[1].image = gcolor.recolor_image(icondir .. 'repeat.svg',
Theme_config.notification_center.song_info.repeat_all)
else
w:get_children_by_id('repeat')[1].image = gcolor.recolor_image(icondir .. 'repeat.svg',
Theme_config.notification_center.song_info.repeat_disabled)
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")
capi.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)
self.player.on_loop_status = on_loop_status
on_loop_status(nil, self.player.loop_status)
local function on_shuffle(_, status)
if status then
w:get_children_by_id('shuffle')[1].image = gcolor.recolor_image(icondir .. 'shuffle.svg',
Theme_config.notification_center.song_info.shuffle_enabled)
else
w:get_children_by_id('shuffle')[1].image = gcolor.recolor_image(icondir .. 'shuffle.svg',
Theme_config.notification_center.song_info.shuffle_disabled)
end
end
self.player.on_shuffle = on_shuffle
on_shuffle(nil, self.player.shuffle)
end
function playerctl.new(args)
args = args or {}
if not instance then
instance = setmetatable(music_player, { __call = function(_, w)
if not w then return end
local ret = gobject {}
gtable.crush(ret, playerctl, true)
local ret = {}
ret.update_on_activity = true
ret.interval = 1
gtable.crush(ret, music_player)
ret.playermanager = Playerctl.PlayerManager()
ret.player = Playerctl.Player()
ret._private = {}
if ret.player.player_name then
start_manage(ret, w, Playerctl:list_players()[1])
end
ret._private.Playerctl = require("lgi").Playerctl
ret._private.manager = nil
ret.playermanager.on_name_appeared = function(_, name)
start_manage(ret, w, name)
end
gtimer.delayed_call(function()
start_manager(ret)
end)
ret.playermanager.on_name_vanished = function()
start_manage(ret, w, Playerctl:list_players()[1])
end
return ret
end, })
end
function playerctl.mt:__call(...)
return playerctl.new(...)
end
return setmetatable(playerctl, playerctl.mt)
return instance

View File

@@ -0,0 +1,35 @@
package.cpath = package.cpath .. ';./?.so'
local gobject = require('gears.object')
local gtable = require('gears.table')
local pulseaudio = require('lua_libpulse_glib')
local p = {}
function p.new()
local ret = gobject {}
ret._private = {}
gtable.crush(ret, p, true)
local pa = pulseaudio.new()
local ctx = pa:context('My Test App')
if not ctx then return end
ctx:connect(nil, function(state)
if state == 4 then
print('Connection is ready')
ctx:get_sinks(function(sinks)
print(sinks)
end)
end
end)
return ret
end
return setmetatable(p, { __call = function(_, ...) return p.new() end })

View File

@@ -1,15 +1,18 @@
local awful = require("awful")
local watch = awful.widget.watch
local awatch = require('awful.widget.watch')
local gobject = require('gears.object')
local capi = {
awesome = awesome,
}
local instance = nil
watch(
[[ bash -c "cat /proc/meminfo| grep Mem | awk '{print $2}'" ]],
3,
function(_, stdout)
local MemTotal, MemFree, MemAvailable = stdout:match("(%d+)\n(%d+)\n(%d+)\n")
capi.awesome.emit_signal("update::ram_widget", MemTotal, MemFree, MemAvailable)
local function new()
local self = gobject {}
awatch([[ bash -c "cat /proc/meminfo| grep Mem | awk '{print $2}'" ]], 3, function(_, stdout)
local MemTotal, MemFree, MemAvailable = stdout:match('(%d+)\n(%d+)\n(%d+)\n')
self:emit_signal('update::ram_widget', MemTotal, MemFree, MemAvailable)
end)
return self
end
)
if not instance then
instance = new()
end
return instance

319
awesome/src/tools/hover.lua Normal file
View File

@@ -0,0 +1,319 @@
local gcolor = require('gears.color')
local rubato = require('src.lib.rubato')
local capi = {
mouse = mouse,
}
local function hex_to_rgba(hex)
return tonumber(hex:sub(2, 3), 16) / 255,
tonumber(hex:sub(4, 5), 16) / 255,
tonumber(hex:sub(6, 7), 16) / 255,
((tonumber(hex:sub(8, 9), 16) or 255) / 255)
end
local function rgba_to_hex(r, g, b, a)
return string.format('%02x%02x%02x%02x', r * 255, g * 255, b * 255, a * 255)
end
local function overlay_color(col, overlay, opacity)
if tonumber(col:sub(1, 2), 16) < 128 and tonumber(col:sub(3, 4), 16) < 128 and tonumber(col:sub(5, 6), 16) < 128 then
overlay = 'ffffff'
else
overlay = '000000'
end
return math.floor((tonumber(overlay:sub(1, 2), 16) * opacity / 100) + tonumber(col:sub(1, 2), 16) * (1 - opacity / 100)),
math.floor((tonumber(overlay:sub(3, 4), 16) * opacity / 100) + tonumber(col:sub(3, 4), 16) * (1 - opacity / 100)),
math.floor((tonumber(overlay:sub(5, 6), 16) * opacity / 100) + tonumber(col:sub(5, 6), 16) * (1 - opacity / 100)),
math.floor((tonumber(overlay:sub(7, 8), 16) or 255 * opacity / 100) + tonumber(col:sub(7, 8), 16) * (1 - opacity / 100))
end
local function bg_hover(args)
--[[ args = args or {}
local old_cursor, old_wibox
local _, r, g, b, a = args.widget.bg:get_rgba()
local animation = {
r = rubato.timed {
duration = 0.3 or args.duration,
easing = rubato.easing.linear,
pos = r * 255,
rate = 24,
clamp_position = true,
},
g = rubato.timed {
duration = 0.3 or args.duration,
easing = rubato.easing.linear,
pos = g * 255,
rate = 24,
clamp_position = true,
},
b = rubato.timed {
duration = 0.3 or args.duration,
easing = rubato.easing.linear,
pos = b * 255,
rate = 24,
clamp_position = true,
},
a = rubato.timed {
duration = 0.3 or args.duration,
easing = rubato.easing.linear,
pos = a * 255,
rate = 24,
clamp_position = true,
},
}
local function set_bg()
args.widget._private.background = gcolor(string.format('#%02x%02x%02x%02x', math.floor(animation.r.pos + 0.5), math.floor(animation.g.pos + 0.5), math.floor(animation.b.pos + 0.5), math.floor(animation.a.pos + 0.5)))
args.widget:emit_signal('widget::redraw_needed')
end
animation.r:subscribe(set_bg)
animation.g:subscribe(set_bg)
animation.b:subscribe(set_bg)
animation.a:subscribe(set_bg)
args.widget:connect_signal('mouse::enter', function()
if animation.r.running or animation.g.running or animation.b.running or animation.a.running then
args.widget._private.background = gcolor(string.format('#%02x%02x%02x%02x', math.floor(animation.r.target + 0.5), math.floor(animation.g.target + 0.5), math.floor(animation.b.target + 0.5),
math.floor(animation.a.target + 0.5)))
args.widget:emit_signal('widget::redraw_needed')
end
_, r, g, b, a = args.widget.bg:get_rgba()
animation.r.pos = r * 255
animation.g.pos = g * 255
animation.b.pos = b * 255
animation.a.pos = a * 255
local w = capi.mouse.current_wibox
if w then
old_cursor, old_wibox = w.cursor, w
w.cursor = 'hand1' or args.cursor
end
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 4)
end)
args.widget:connect_signal('mouse::leave', function()
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
animation.r.target, animation.g.target, animation.b.target, animation.a.target = r * 255, g * 255, b * 255, a * 255
end)
args.widget:connect_signal('button::press', function()
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.press_overlay or 12)
end)
args.widget:connect_signal('button::release', function()
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 4)
end)
args.widget:connect_signal('property::bg', function(_, newbg)
r, g, b, a = hex_to_rgba(newbg)
end) ]]
end
--[[ local function fg_hover(args)
args = args or {}
local old_cursor, old_wibox
local _, r, g, b, a = args.widget.fg:get_rgba()
local animation = {
r = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = r * 255,
rate = 24,
clamp_position = true,
},
g = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = g * 255,
rate = 24,
clamp_position = true,
},
b = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = b * 255,
rate = 24,
clamp_position = true,
},
a = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = a * 255,
rate = 24,
clamp_position = true,
},
}
local function set_fg()
args.widget:set_fg(string.format('#%02x%02x%02x%02x', math.floor(animation.r.pos + 0.5), math.floor(animation.g.pos + 0.5), math.floor(animation.b.pos + 0.5), math.floor(animation.a.pos + 0.5)))
end
animation.r:subscribe(set_fg)
animation.g:subscribe(set_fg)
animation.b:subscribe(set_fg)
animation.a:subscribe(set_fg)
args.widget:connect_signal('mouse::enter', function()
if animation.r.running or animation.g.running or animation.b.running or animation.a.running then
args.widget:set_fg(string.format('#%02x%02x%02x%02x', math.floor(animation.r.target + 0.5), math.floor(animation.g.target + 0.5), math.floor(animation.b.target + 0.5), math.floor(animation.a.target + 0.5)))
end
_, r, g, b, a = args.widget.fg:get_rgba()
animation.r.pos = r * 255
animation.g.pos = g * 255
animation.b.pos = b * 255
animation.a.pos = a * 255
local w = capi.mouse.current_wibox
if w then
old_cursor, old_wibox = w.cursor, w
w.cursor = 'hand1' or args.cursor
end
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 4)
end)
args.widget:connect_signal('mouse::leave', function()
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
animation.r.target = r * 255
animation.g.target = g * 255
animation.b.target = b * 255
animation.a.target = a * 255
end)
args.widget:connect_signal('button::press', function()
_, r, g, b, a = args.widget.fg:get_rgba()
args.widget:set_fg(string.format('#%02x%02x%02x%02x', math.floor(r + 0.5), math.floor(g + 0.5), math.floor(b + 0.5), math.floor(a + 0.5)))
animation.r.pos = r * 255
animation.g.pos = g * 255
animation.b.pos = b * 255
animation.a.pos = a * 255
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 12)
end)
args.widget:connect_signal('button::release', function()
animation.r.target = r * 255
animation.g.target = g * 255
animation.b.target = b * 255
animation.a.target = a * 255
end)
end ]]
--[[ local function border_hover(args)
args = args or {}
local old_cursor, old_wibox
local r, g, b, a = hex_to_rgba(args.widget.border_color)
local animation = {
r = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = r * 255,
rate = 24,
clamp_position = true,
},
g = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = g * 255,
rate = 24,
clamp_position = true,
},
b = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = b * 255,
rate = 24,
clamp_position = true,
},
a = rubato.timed {
duration = 0.2 or args.duration,
easing = rubato.easing.linear,
pos = a * 255,
rate = 24,
clamp_position = true,
},
}
local function set_border()
args.widget.border_color = string.format('#%02x%02x%02x%02x', math.floor(animation.r.pos + 0.5), math.floor(animation.g.pos + 0.5), math.floor(animation.b.pos + 0.5), math.floor(animation.a.pos + 0.5))
end
animation.r:subscribe(set_border)
animation.g:subscribe(set_border)
animation.b:subscribe(set_border)
animation.a:subscribe(set_border)
args.widget:connect_signal('mouse::enter', function()
if animation.r.running or animation.g.running or animation.b.running or animation.a.running then
args.widget.border_color = string.format('#%02x%02x%02x%02x', math.floor(animation.r.target + 0.5), math.floor(animation.g.target + 0.5), math.floor(animation.b.target + 0.5), math.floor(animation.a.target + 0.5))
end
r, g, b, a = hex_to_rgba(args.widget.border_color)
animation.r.pos = r * 255
animation.g.pos = g * 255
animation.b.pos = b * 255
animation.a.pos = a * 255
local w = capi.mouse.current_wibox
if w then
old_cursor, old_wibox = w.cursor, w
w.cursor = 'hand1' or args.cursor
end
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 4)
end)
args.widget:connect_signal('mouse::leave', function()
if old_wibox then
old_wibox.cursor = old_cursor
old_wibox = nil
end
animation.r.target = r * 255
animation.g.target = g * 255
animation.b.target = b * 255
animation.a.target = a * 255
end)
args.widget:connect_signal('button::press', function()
r, g, b, a = hex_to_rgba(args.widget.border_color)
args.widget.border_color = string.format('#%02x%02x%02x%02x', math.floor(r + 0.5), math.floor(g + 0.5), math.floor(b + 0.5), math.floor(a + 0.5))
animation.r.pos = r * 255
animation.g.pos = g * 255
animation.b.pos = b * 255
animation.a.pos = a * 255
animation.r.target, animation.g.target, animation.b.target, animation.a.target = overlay_color(rgba_to_hex(r, g, b, a), args.overlay_color or 'ffffff', args.overlay or 12)
end)
args.widget:connect_signal('button::release', function()
animation.r.target = r * 255
animation.g.target = g * 255
animation.b.target = b * 255
animation.a.target = a * 255
end)
end ]]
return {
bg_hover = bg_hover,
--fg_hover = fg_hover,
--border_hover = border_hover,
}

View File

@@ -2,98 +2,118 @@
-- This is the audio widget --
------------------------------
-- Awesome Libs
local abutton = require('awful.button')
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local wibox = require('wibox')
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
-- Local libs
local audio_controller = require('src.modules.audio.audio_controller')
local audio_helper = require('src.tools.helpers.audio')
local hover = require('src.tools.hover')
require("src.tools.helpers.audio")
local capi = {
awesome = awesome,
}
local capi = { mouse = mouse }
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/audio/'
-- Returns the audio widget
return function(s)
return setmetatable({}, { __call = function(_, screen)
local audio_widget = wibox.widget {
local ac_popup = apopup {
widget = audio_controller,
ontop = true,
visible = false,
screen = screen,
border_color = Theme_config.bluetooth_controller.container_border_color,
border_width = Theme_config.bluetooth_controller.container_border_width,
bg = Theme_config.bluetooth_controller.container_bg,
}
local w = wibox.widget {
{
{
{
{
{
id = "icon",
id = 'icon',
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
valign = 'center',
halign = 'center',
resize = true,
},
id = "icon_layout",
widget = wibox.container.place
width = dpi(25),
height = dpi(25),
strategy = 'exact',
widget = wibox.container.constraint,
},
top = dpi(2),
widget = wibox.container.margin,
id = "icon_margin"
{
id = 'label',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
id = 'audio_layout',
layout = wibox.layout.fixed.horizontal,
},
id = "audio_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
id = 'container',
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.audio.bg,
fg = Theme_config.audio.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
shape = Theme_config.audio.shape,
widget = wibox.container.background,
buttons = { gtable.join(
abutton({}, 1, function()
local geo = capi.mouse.coords()
ac_popup.y = dpi(65)
ac_popup.x = geo.x - ac_popup.width / 2
ac_popup.visible = not ac_popup.visible
end)
), },
}
capi.awesome.connect_signal("audio::get", function(muted, volume)
if muted then
audio_widget.container.audio_layout.label.visible = false
audio_widget.container.audio_layout.icon_margin.icon_layout.icon:set_image(
gears.color.recolor_image(icondir .. "volume-mute" .. ".svg", Theme_config.audio.fg))
else
audio_widget.container:set_right(10)
local icon = icondir .. "volume"
audio_widget.container.audio_layout.spacing = dpi(5)
audio_widget.container.audio_layout.label.visible = true
hover.bg_hover { widget = w }
local audio_label = w:get_children_by_id('label')[1]
local audio_icon = w:get_children_by_id('icon')[1]
local audio_spacing = w:get_children_by_id('audio_layout')[1]
audio_helper:connect_signal('sink::get', function(_, muted, volume)
volume = tonumber(volume)
if not volume then
return
end
assert(type(volume) == 'number' and type(muted) == 'boolean', 'Invalid arguments')
if w.volume == volume and w.muted == muted then return end
w.volume = volume
w.muted = muted
if muted then
audio_label.visible = false
audio_icon:set_image(gcolor.recolor_image(icondir .. 'volume-mute' .. '.svg', Theme_config.audio.fg))
else
if not volume then return end
w.container:set_right(10)
audio_spacing.spacing = dpi(5)
audio_label.visible = true
local icon = icondir .. 'volume'
if volume < 1 then
icon = icon .. "-mute"
audio_widget.container.audio_layout.spacing = dpi(0)
audio_widget.container.audio_layout.label.visible = false
icon = icon .. '-mute'
audio_spacing.spacing = 0
audio_label.visible = false
elseif volume >= 1 and volume < 34 then
icon = icon .. "-low"
icon = icon .. '-low'
elseif volume >= 34 and volume < 67 then
icon = icon .. "-medium"
icon = icon .. '-medium'
elseif volume >= 67 then
icon = icon .. "-high"
icon = icon .. '-high'
end
audio_widget.container.audio_layout.label:set_text(volume .. "%")
audio_widget.container.audio_layout.icon_margin.icon_layout.icon:set_image(
gears.color.recolor_image(icon .. ".svg", Theme_config.audio.fg))
audio_label:set_text(volume .. '%')
audio_icon:set_image(gcolor.recolor_image(icon .. '.svg', Theme_config.audio.fg))
end
end)
-- Signals
Hover_signal(audio_widget)
return audio_widget
end
return w
end, })

View File

@@ -3,20 +3,23 @@
--------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local lgi = require("lgi")
local naughty = require("naughty")
local upower_glib = lgi.require("UPowerGlib")
local wibox = require("wibox")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gears = require('gears')
local lgi = require('lgi')
local naughty = require('naughty')
local upower_glib = lgi.require('UPowerGlib')
local wibox = require('wibox')
-- Local libs
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/battery/"
local icondir = gears.filesystem.get_configuration_dir() .. 'src/assets/icons/battery/'
---Returns the battery widget
---@return wibox.widget
@@ -29,46 +32,46 @@ return function(battery_kind)
{
{
{
id = "icon",
image = gears.color.recolor_image(icondir .. "battery-unknown.svg", Theme_config.battery.fg),
id = 'icon',
image = gears.color.recolor_image(icondir .. 'battery-unknown.svg', Theme_config.battery.fg),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
valign = 'center',
halign = 'center',
resize = false,
},
id = "icon_layout",
widget = wibox.container.place
id = 'icon_layout',
widget = wibox.container.place,
},
id = "icon_margin",
id = 'icon_margin',
top = dpi(2),
widget = wibox.container.margin
widget = wibox.container.margin,
},
spacing = dpi(10),
{
visible = false,
align = 'center',
valign = 'center',
id = "label",
widget = wibox.widget.textbox
id = 'label',
widget = wibox.widget.textbox,
},
id = "battery_layout",
layout = wibox.layout.fixed.horizontal
id = 'battery_layout',
layout = wibox.layout.fixed.horizontal,
},
id = "container",
id = 'container',
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.battery.bg,
fg = Theme_config.battery.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
widget = wibox.container.background,
}
-- Color change on mouse over
Hover_signal(battery_widget)
hover.bg_hover { widget = battery_widget }
-- Open an energy manager on click
battery_widget:connect_signal(
@@ -105,9 +108,9 @@ return function(battery_kind)
local tooltip = awful.tooltip {
objects = { battery_widget },
mode = "inside",
preferred_alignments = "middle",
margins = dpi(10)
mode = 'inside',
preferred_alignments = 'middle',
margins = dpi(10),
}
---Sets the battery information for the widget
@@ -125,50 +128,50 @@ return function(battery_kind)
battery_time = device.time_to_full
end
local battery_string = math.floor(battery_time / 3600) .. "h, " .. math.floor((battery_time / 60) % 60) .. "m"
local battery_string = math.floor(battery_time / 3600) .. 'h, ' .. math.floor((battery_time / 60) % 60) .. 'm'
if battery_temp == 0.0 then
battery_temp = "NaN"
battery_temp = 'NaN'
else
battery_temp = math.floor(battery_temp + 0.5) .. "°C"
battery_temp = math.floor(battery_temp + 0.5) .. '°C'
end
if not battery_percentage then
return
end
battery_widget:get_children_by_id("battery_layout")[1].spacing = dpi(5)
battery_widget:get_children_by_id("label")[1].visible = true
battery_widget:get_children_by_id("label")[1].text = battery_percentage .. '%'
battery_widget:get_children_by_id('battery_layout')[1].spacing = dpi(5)
battery_widget:get_children_by_id('label')[1].visible = true
battery_widget:get_children_by_id('label')[1].text = battery_percentage .. '%'
tooltip.markup = "<span foreground='#64ffda'>Battery Status:</span> <span foreground='#90caf9'>"
.. battery_status .. "</span>\n<span foreground='#64ffda'>Remaining time:</span> <span foreground='#90caf9'>"
.. battery_string .. "</span>\n<span foreground='#64ffda'>Temperature:</span> <span foreground='#90caf9'>"
.. battery_temp .. "</span>"
.. battery_temp .. '</span>'
local icon = 'battery'
if battery_status == 'fully-charged' or battery_status == 'charging' and battery_percentage == 100 then
icon = icon .. '-' .. 'charging.svg'
naughty.notification {
title = "Battery notification",
message = "Battery is fully charged",
title = 'Battery notification',
message = 'Battery is fully charged',
icon = icondir .. icon,
timeout = 5
timeout = 5,
}
battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir
battery_widget:get_children_by_id('icon')[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir
.. icon, Theme_config.battery.fg))
return
elseif battery_percentage > 0 and battery_percentage < 10 and battery_status == 'discharging' then
icon = icon .. '-' .. 'alert.svg'
naughty.notification {
title = "Battery warning",
message = "Battery is running low!\n" .. battery_percentage .. "% left",
urgency = "critical",
title = 'Battery warning',
message = 'Battery is running low!\n' .. battery_percentage .. '% left',
urgency = 'critical',
icon = icondir .. icon,
timeout = 60
timeout = 60,
}
battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir
battery_widget:get_children_by_id('icon')[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir
.. icon, Theme_config.battery.fg))
return
end
@@ -195,9 +198,9 @@ return function(battery_kind)
icon = icon .. '-' .. battery_status .. '-' .. '90'
end
battery_widget:get_children_by_id("icon")[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir ..
battery_widget:get_children_by_id('icon')[1].image = gears.surface.load_uncached(gears.color.recolor_image(icondir ..
icon .. '.svg', Theme_config.battery.fg))
capi.awesome.emit_signal("update::battery_widget", battery_percentage, icondir .. icon .. ".svg")
capi.awesome.emit_signal('update::battery_widget', battery_percentage, icondir .. icon .. '.svg')
end
@@ -208,12 +211,12 @@ return function(battery_kind)
---Will report to the bluetooth widget.
---@param path string device path /org/freedesktop/...
local function attach_to_device(path)
local device_path = User_config.battery_path or path or ""
local device_path = User_config.battery_path or path or ''
battery_widget.device = get_device_from_path(device_path) or upower_glib.Client():get_display_device()
battery_widget.device.on_notify = function(device)
battery_widget:emit_signal("upower::update", device)
battery_widget:emit_signal('upower::update', device)
end
-- Check which device kind the user wants to display
@@ -223,7 +226,7 @@ return function(battery_kind)
end
-- The delayed call will fire every time awesome finishes its main event loop
gears.timer.delayed_call(battery_widget.emit_signal, battery_widget, "upower::update", battery_widget.device)
gears.timer.delayed_call(battery_widget.emit_signal, battery_widget, 'upower::update', battery_widget.device)
end
for _, device in ipairs(get_device_path()) do
@@ -231,7 +234,7 @@ return function(battery_kind)
end
battery_widget:connect_signal(
"upower::update",
'upower::update',
function(_, device)
if upower_glib.DeviceKind[battery_widget.device.kind] == battery_kind then
set_battery(device)

View File

@@ -3,21 +3,22 @@
----------------------------------
-- Awesome libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local awful = require('awful')
local dpi = require('beautiful').xresources.apply_dpi
local gears = require('gears')
local wibox = require('wibox')
-- Own libs
local bt_module = require("src.modules.bluetooth.init")
local bt_module = require('src.modules.bluetooth.init')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
mouse = mouse
mouse = mouse,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
local icondir = gears.filesystem.get_configuration_dir() .. 'src/assets/icons/bluetooth/'
-- Returns the bluetooth widget
return function(s)
@@ -29,29 +30,31 @@ return function(s)
{
{
{
id = "icon",
image = gears.color.recolor_image(icondir .. "bluetooth-off.svg", Theme_config.bluetooth.fg),
id = 'icon',
image = gears.color.recolor_image(icondir .. 'bluetooth-off.svg', Theme_config.bluetooth.fg),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
valign = 'center',
halign = 'center',
resize = false,
},
id = "icon_layout",
widget = wibox.container.place
id = 'icon_layout',
widget = wibox.container.place,
},
id = "icon_margin",
id = 'icon_margin',
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.bluetooth.bg,
fg = Theme_config.bluetooth.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
widget = wibox.container.background,
}
hover.bg_hover { widget = bluetooth_widget }
-- If bt_widget is nil then there is no bluetooth adapter and there shouldn't be done
-- anything besides returning the widget without any logic behind
if not bt_widget then
@@ -67,27 +70,24 @@ return function(s)
screen = s,
border_color = Theme_config.bluetooth_controller.container_border_color,
border_width = Theme_config.bluetooth_controller.container_border_width,
bg = Theme_config.bluetooth_controller.container_bg
bg = Theme_config.bluetooth_controller.container_bg,
}
-- When the status changes update the icon
bt_widget:connect_signal("bluetooth::status", function(status)
bluetooth_widget:get_children_by_id("icon")[1].image = gears.color.recolor_image(status._private.Adapter1.Powered and
icondir .. "bluetooth-on.svg" or icondir .. "bluetooth-off.svg", Theme_config.bluetooth.fg)
bt_widget:connect_signal('bluetooth::status', function(status)
bluetooth_widget:get_children_by_id('icon')[1].image = gears.color.recolor_image(status._private.Adapter1.Powered and
icondir .. 'bluetooth-on.svg' or icondir .. 'bluetooth-off.svg', Theme_config.bluetooth.fg)
end)
-- Hover signal to change color when mouse is over
Hover_signal(bluetooth_widget)
-- On left click toggle the bluetooth container else toggle the bluetooth on/off
bluetooth_widget:connect_signal("button::press", function(_, _, _, key)
bluetooth_widget:connect_signal('button::press', function(_, _, _, key)
if key == 1 then
local geo = capi.mouse.current_wibox:geometry()
bluetooth_container.x = geo.x
bluetooth_container.y = geo.y + dpi(55)
bluetooth_container.visible = not bluetooth_container.visible
else
capi.awesome.emit_signal("toggle_bluetooth")
capi.awesome.emit_signal('toggle_bluetooth')
end
end)

View File

@@ -3,62 +3,55 @@
------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local wibox = require('wibox')
-- Local libs
local hover = require('src.tools.hover')
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/clock/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/clock/'
-- Returns the clock widget
return function()
return setmetatable({}, { __call = function()
local clock_widget = wibox.widget {
{
{
{
{
{
id = "icon",
image = gears.color.recolor_image(icondir .. "clock.svg", Theme_config.clock.fg),
image = gcolor.recolor_image(icondir .. 'clock.svg', Theme_config.clock.fg),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
valign = 'center',
halign = 'center',
resize = true,
},
id = "icon_layout",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
id = "icon_margin",
top = dpi(2),
widget = wibox.container.margin
{
halign = 'center',
valign = 'center',
format = '%H:%M',
widget = wibox.widget.textclock,
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
format = "%H:%M",
widget = wibox.widget.textclock
layout = wibox.layout.fixed.horizontal,
},
id = "clock_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.clock.bg,
fg = Theme_config.clock.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
shape = Theme_config.clock.shape,
widget = wibox.container.background,
}
Hover_signal(clock_widget)
hover.bg_hover { widget = clock_widget }
return clock_widget
end
end, })

View File

@@ -3,217 +3,234 @@
---------------------------------
-- Awesome Libs
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local wibox = require('wibox')
local color = require("src.lib.color")
local rubato = require("src.lib.rubato")
-- Third Party Libs
local color = require('src.lib.color')
local rubato = require('src.lib.rubato')
local hover = require('src.tools.hover')
require("src.tools.helpers.cpu_freq")
require("src.tools.helpers.cpu_temp")
require("src.tools.helpers.cpu_usage")
local icon_dir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/cpu/'
local capi = {
awesome = awesome,
}
local cpu_info = {}
local icon_dir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/cpu/"
local function cpu_temp_new()
local cpu_temp_helper = require('src.tools.helpers.cpu_temp')
--TODO: Add tooltip with more CPU and per core information
return function(widget)
local cpu_usage_widget = wibox.widget {
local w = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
id = "icon",
id = 'icon_role',
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icon_dir .. "cpu.svg", Theme_config.cpu_usage.fg),
resize = false
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icon_dir .. 'thermometer.svg', Theme_config.cpu_temp.fg),
resize = true,
},
id = "icon_layout",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
top = dpi(2),
{
id = 'text_role',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
id = "icon_margin"
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
id = "cpu_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
},
bg = Theme_config.cpu_usage.bg,
fg = Theme_config.cpu_usage.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
local cpu_temp = wibox.widget {
{
{
{
{
{
id = "icon",
image = gears.color.recolor_image(icon_dir .. "thermometer.svg", Theme_config.cpu_temp.fg),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
},
id = "icon_layout",
widget = wibox.container.place
},
top = dpi(2),
widget = wibox.container.margin,
id = "icon_margin"
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
id = "cpu_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
},
bg = Theme_config.cpu_temp.bg_low,
bg = Theme_config.cpu_temp.bg,
fg = Theme_config.cpu_temp.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
shape = Theme_config.cpu_temp.shape,
widget = wibox.container.background,
})
local cpu_clock = wibox.widget {
{
{
{
{
{
id = "icon",
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icon_dir .. "cpu.svg", Theme_config.cpu_freq.fg),
resize = false
},
id = "icon_layout",
widget = wibox.container.place
},
top = dpi(2),
widget = wibox.container.margin,
id = "icon_margin"
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
id = "cpu_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
},
bg = Theme_config.cpu_freq.bg,
fg = Theme_config.cpu_freq.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
assert(w, 'Failed to create widget')
capi.awesome.connect_signal("update::cpu_usage", function(usage)
cpu_usage_widget.container.cpu_layout.label.text = usage .. "%"
end)
gtable.crush(w, cpu_info, true)
local r_timed_cpu_bg = rubato.timed { duration = 2.5 }
local g_timed_cpu_bg = rubato.timed { duration = 2.5 }
local b_timed_cpu_bg = rubato.timed { duration = 2.5 }
local r = rubato.timed { duration = 2.5 }
local g = rubato.timed { duration = 2.5 }
local b = rubato.timed { duration = 2.5 }
r_timed_cpu_bg.pos, g_timed_cpu_bg.pos, b_timed_cpu_bg.pos = color.utils.hex_to_rgba(Theme_config.cpu_temp.bg_low)
r.pos, g.pos, b.pos = color.utils.hex_to_rgba(Theme_config.cpu_temp.bg_low)
-- Subscribable function to have rubato set the bg/fg color
local function update_bg()
cpu_temp:set_bg("#" .. color.utils.rgba_to_hex { r_timed_cpu_bg.pos, g_timed_cpu_bg.pos, b_timed_cpu_bg.pos })
w:set_bg('#' .. color.utils.rgba_to_hex { r.pos, g.pos, b.pos })
end
r_timed_cpu_bg:subscribe(update_bg)
g_timed_cpu_bg:subscribe(update_bg)
b_timed_cpu_bg:subscribe(update_bg)
r:subscribe(update_bg)
g:subscribe(update_bg)
b:subscribe(update_bg)
-- Both functions to set a color, if called they take a new color
local function set_bg(newbg)
r_timed_cpu_bg.target, g_timed_cpu_bg.target, b_timed_cpu_bg.target = color.utils.hex_to_rgba(newbg)
r.target, g.target, b.target = color.utils.hex_to_rgba(newbg)
end
capi.awesome.connect_signal("update::cpu_temp", function(temp)
cpu_temp_helper:connect_signal('update::cpu_temp', function(_, temp)
local temp_icon
local temp_color
if temp < 50 then
temp_color = Theme_config.cpu_temp.bg_low
temp_icon = icon_dir .. "thermometer-low.svg"
temp_icon = icon_dir .. 'thermometer-low.svg'
elseif temp >= 50 and temp < 80 then
temp_color = Theme_config.cpu_temp.bg_mid
temp_icon = icon_dir .. "thermometer.svg"
temp_icon = icon_dir .. 'thermometer.svg'
elseif temp >= 80 then
temp_color = Theme_config.cpu_temp.bg_high
temp_icon = icon_dir .. "thermometer-high.svg"
temp_icon = icon_dir .. 'thermometer-high.svg'
end
cpu_temp.container.cpu_layout.icon_margin.icon_layout.icon:set_image(temp_icon)
w:get_children_by_id('icon_role')[1].image = temp_icon
set_bg(temp_color)
cpu_temp.container.cpu_layout.label.text = math.floor(temp) .. "°C"
capi.awesome.emit_signal("update::cpu_temp_widget", temp, temp_icon)
w:get_children_by_id('text_role')[1].text = math.floor(temp) .. '°C'
end)
capi.awesome.connect_signal("update::cpu_freq_average", function(average)
cpu_clock.container.cpu_layout.label.text = average .. "Mhz"
end)
capi.awesome.connect_signal("update::cpu_freq_core", function(freq)
cpu_clock.container.cpu_layout.label.text = freq .. "Mhz"
end)
Hover_signal(cpu_temp)
Hover_signal(cpu_usage_widget)
Hover_signal(cpu_clock)
if widget == "usage" then
return cpu_usage_widget
elseif widget == "temp" then
return cpu_temp
elseif widget == "freq" then
return cpu_clock
return w
end
local function cpu_usage_new()
local cpu_usage_helper = require('src.tools.helpers.cpu_usage')
local w = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
id = 'icon_role',
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icon_dir .. 'cpu.svg', Theme_config.cpu_usage.fg),
resize = true,
},
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
{
id = 'text_role',
text = '0%',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
},
bg = Theme_config.cpu_usage.bg,
fg = Theme_config.cpu_usage.fg,
shape = Theme_config.cpu_usage.shape,
widget = wibox.container.background,
})
assert(w, 'failed to create widget')
hover.bg_hover { widget = w }
gtable.crush(w, cpu_info, true)
cpu_usage_helper:connect_signal('update::cpu_usage', function(_, usage)
w:get_children_by_id('text_role')[1].text = usage .. '%'
end)
return w
end
local function cpu_freq_new()
local cpu_freq_helper = require('src.tools.helpers.cpu_freq')
local w = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
id = 'icon_role',
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icon_dir .. 'cpu.svg', Theme_config.cpu_freq.fg),
resize = true,
},
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
{
id = 'text_role',
text = '0Mhz',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
},
bg = Theme_config.cpu_freq.bg,
fg = Theme_config.cpu_freq.fg,
shape = Theme_config.cpu_freq.shape,
widget = wibox.container.background,
})
assert(w, 'failed to create widget')
hover.bg_hover { widget = w }
gtable.crush(w, cpu_info, true)
cpu_freq_helper:connect_signal('update::cpu_freq_average', function(_, average)
w:get_children_by_id('text_role')[1].text = average .. 'Mhz'
end)
cpu_freq_helper:connect_signal('update::cpu_freq_core', function(_, freq)
w:get_children_by_id('text_role')[1].text = freq .. 'Mhz'
end)
return w
end
return setmetatable(cpu_info, { __call = function(_, widget)
if widget == 'temp' then
return cpu_temp_new()
elseif widget == 'usage' then
return cpu_usage_new()
elseif widget == 'freq' then
return cpu_freq_new()
else
return nil
end
end, })

View File

@@ -3,83 +3,81 @@
-----------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local apopup = require('awful.popup')
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local abutton = require('awful.button')
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local gcolor = require('gears.color')
-- Local libs
local cal = require('src.modules.calendar.init') {}
local hover = require('src.tools.hover')
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/date/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/date/'
local capi = { mouse = mouse }
-- Returns the date widget
return function(s)
local cal = require("src.modules.calendar.init") { screen = s }
return setmetatable({}, { __call = function(_, screen)
local date_widget = wibox.widget {
{
{
{
{
{
id = "icon",
image = gears.color.recolor_image(icondir .. "calendar.svg", Theme_config.date.fg),
image = gcolor.recolor_image(icondir .. 'calendar.svg', Theme_config.date.fg),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
resize = false
valign = 'center',
halign = 'center',
resize = true,
},
id = "icon_layout",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
id = "icon_margin",
top = dpi(2),
widget = wibox.container.margin
{
halign = 'center',
valign = 'center',
format = '%a, %b %d',
widget = wibox.widget.textclock,
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
format = "%a, %b %d",
widget = wibox.widget.textclock
layout = wibox.layout.fixed.horizontal,
},
id = "date_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.date.bg,
fg = Theme_config.date.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
shape = Theme_config.date.shape,
widget = wibox.container.background,
}
local calendar_popup = awful.popup {
local calendar_popup = apopup {
widget = cal:get_widget(),
screen = s,
screen = screen,
ontop = true,
bg = "#00000000",
visible = false,
}
-- Signals
Hover_signal(date_widget)
hover.bg_hover { widget = date_widget }
date_widget:buttons {
gears.table.join(
awful.button({}, 1, function()
local geo = mouse.current_wibox:geometry()
calendar_popup.x = geo.x
calendar_popup.y = geo.y + dpi(55)
date_widget:buttons { gtable.join(
abutton({}, 1, function()
local geo = capi.mouse.coords()
calendar_popup.y = dpi(65)
if geo.x + (calendar_popup.width / 2) > capi.mouse.screen.geometry.width then
calendar_popup.x = capi.mouse.screen.geometry.x + capi.mouse.screen.geometry.width - calendar_popup.width
else
calendar_popup.x = geo.x - (calendar_popup.width / 2)
end
calendar_popup.visible = not calendar_popup.visible
end)
)
}
), }
return date_widget
end
end, })

View File

@@ -3,179 +3,173 @@
---------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local wibox = require('wibox')
local color = require("src.lib.color")
local rubato = require("src.lib.rubato")
-- Third Party Libs
local color = require('src.lib.color')
local rubato = require('src.lib.rubato')
local hover = require('src.tools.hover')
require("src.tools.helpers.gpu_temp")
require("src.tools.helpers.gpu_usage")
local icon_dir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/cpu/'
local capi = {
awesome = awesome,
}
local gpu_info = {}
local icon_dir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/cpu/"
local function gpu_temp_new()
local gpu_temp_helper = require('src.tools.helpers.gpu_temp')
return function(widget)
local gpu_usage_widget = wibox.widget {
local w = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
id = "icon",
id = 'icon_role',
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icon_dir .. "gpu.svg", Theme_config.gpu_usage.fg),
resize = false
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icon_dir .. 'gpu.svg', Theme_config.gpu_temp.fg),
resize = true,
},
id = "icon_layout",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
top = dpi(2),
{
id = 'text_role',
text = '0°C',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
id = "icon_margin"
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
id = "gpu_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
},
bg = Theme_config.gpu_usage.bg,
fg = Theme_config.gpu_usage.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
local gpu_temp_widget = wibox.widget {
{
{
{
{
{
id = "icon",
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icon_dir .. "gpu.svg", Theme_config.gpu_temp.fg),
resize = false
},
id = "icon_layout",
widget = wibox.container.place
},
top = dpi(2),
widget = wibox.container.margin,
id = "icon_margin"
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
},
id = "gpu_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
},
bg = Theme_config.gpu_temp.bg_low,
bg = Theme_config.gpu_temp.bg,
fg = Theme_config.gpu_temp.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
shape = Theme_config.gpu_temp.shape,
widget = wibox.container.background,
})
Hover_signal(gpu_temp_widget)
Hover_signal(gpu_usage_widget)
assert(w, 'Widget not created')
-- GPU Utilization
capi.awesome.connect_signal(
"update::gpu_usage",
function(stdout)
gpu_usage_widget.container.gpu_layout.label.text = stdout:gsub("\n", "") .. "%"
end
)
local r = rubato.timed { duration = 2.5 }
local g = rubato.timed { duration = 2.5 }
local b = rubato.timed { duration = 2.5 }
local r_timed_gpu_bg = rubato.timed { duration = 2.5 }
local g_timed_gpu_bg = rubato.timed { duration = 2.5 }
local b_timed_gpu_bg = rubato.timed { duration = 2.5 }
r_timed_gpu_bg.pos, g_timed_gpu_bg.pos, b_timed_gpu_bg.pos = color.utils.hex_to_rgba(Theme_config.cpu_temp.bg_low)
r.pos, g.pos, b.pos = color.utils.hex_to_rgba(Theme_config.cpu_temp.bg_low)
-- Subscribable function to have rubato set the bg/fg color
local function update_bg()
gpu_temp_widget:set_bg("#" ..
color.utils.rgba_to_hex { math.max(0, r_timed_gpu_bg.pos), math.max(0, g_timed_gpu_bg.pos),
math.max(0, b_timed_gpu_bg.pos) })
w:set_bg('#' .. color.utils.rgba_to_hex { math.max(0, r.pos), math.max(0, g.pos),
math.max(0, b.pos), })
end
r_timed_gpu_bg:subscribe(update_bg)
g_timed_gpu_bg:subscribe(update_bg)
b_timed_gpu_bg:subscribe(update_bg)
r:subscribe(update_bg)
g:subscribe(update_bg)
b:subscribe(update_bg)
-- Both functions to set a color, if called they take a new color
local function set_bg(newbg)
r_timed_gpu_bg.target, g_timed_gpu_bg.target, b_timed_gpu_bg.target = color.utils.hex_to_rgba(newbg)
r.target, g.target, b.target = color.utils.hex_to_rgba(newbg)
end
-- GPU Temperature
capi.awesome.connect_signal(
"update::gpu_temp",
function(stdout)
gpu_temp_helper:connect_signal('update::gpu_temp', function(_, stdout)
local temp_icon
local temp_color
local temp_num = tonumber(stdout) or "N/A"
local temp_num = tonumber(stdout) or 0
if temp_num then
if temp_num < 50 then
temp_color = Theme_config.gpu_temp.bg_low
temp_icon = icon_dir .. "thermometer-low.svg"
temp_icon = icon_dir .. 'thermometer-low.svg'
elseif temp_num >= 50 and temp_num < 80 then
temp_color = Theme_config.gpu_temp.bg_mid
temp_icon = icon_dir .. "thermometer.svg"
temp_icon = icon_dir .. 'thermometer.svg'
elseif temp_num >= 80 then
temp_color = Theme_config.gpu_temp.bg_high
temp_icon = icon_dir .. "thermometer-high.svg"
temp_icon = icon_dir .. 'thermometer-high.svg'
end
else
temp_num = "N/A"
temp_color = Theme_config.gpu_temp.bg_low
temp_icon = icon_dir .. "thermometer-low.svg"
temp_icon = icon_dir .. 'thermometer-low.svg'
end
gpu_temp_widget.container.gpu_layout.icon_margin.icon_layout.icon:set_image(temp_icon)
w:get_children_by_id('icon_role')[1]:set_image(temp_icon)
set_bg(temp_color)
gpu_temp_widget.container.gpu_layout.label.text = tostring(temp_num) .. "°C"
end
)
w:get_children_by_id('text_role')[1].text = tostring(temp_num) .. '°C'
end)
if widget == "usage" then
return gpu_usage_widget
elseif widget == "temp" then
return gpu_temp_widget
return w
end
local function gpu_usage_new()
local gpu_usage_helper = require('src.tools.helpers.gpu_usage')
local w = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
id = 'icon_role',
widget = wibox.widget.imagebox,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icon_dir .. 'gpu.svg', Theme_config.gpu_usage.fg),
resize = true,
},
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
{
id = 'text_role',
text = '0%',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal,
},
widget = wibox.container.place,
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
},
bg = Theme_config.gpu_usage.bg,
fg = Theme_config.gpu_usage.fg,
shape = Theme_config.gpu_usage.shape,
widget = wibox.container.background,
})
assert(w, 'Widget not created')
hover.bg_hover { widget = w }
gpu_usage_helper:connect_signal('update::gpu_usage', function(_, stdout)
w:get_children_by_id('text_role')[1].text = stdout:gsub('\n', '') .. '%'
end)
return w
end
return setmetatable(gpu_info, { __call = function(_, widget)
if widget == 'usage' then
return gpu_usage_new()
elseif widget == 'temp' then
return gpu_temp_new()
end
end, })

View File

@@ -3,395 +3,278 @@
------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local dpi = require('beautiful').xresources.apply_dpi
local wibox = require('wibox')
local gcolor = require('gears.color')
local gfilesystem = require('gears.filesystem')
local gtable = require('gears.table')
local abutton = require('awful.button')
local apopup = require('awful.popup')
-- Local libs
local kb_helper = require('src.tools.helpers.kb_helper')
local hover = require('src.tools.hover')
local capi = {
awesome = awesome,
mousegrabber = mousegrabber,
mouse = mouse,
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/kblayout/"
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/kblayout/'
return function(s)
local kb_layout_popup
local function create_kb_layout_list()
local widget = wibox.widget {
{
{
id = 'list',
layout = wibox.layout.fixed.vertical,
spacing = dpi(10),
},
widget = wibox.container.margin,
margins = dpi(10),
},
widget = wibox.container.background,
bg = Theme_config.kblayout.bg_container,
}
local list = widget:get_children_by_id('list')[1]
for _, keymap in pairs(User_config.kblayout) do
-- TODO: Add more, too lazy rn
local xkeyboard_country_code = {
['af'] = { 'أفغانيش(Afghanistan)', 'AFG' }, -- Afghanistan
['al'] = { 'Shqip(Albania)', 'ALB' }, -- Albania
['am'] = { 'Hայերեն(Armenia)', 'ARM' }, -- Armenia
['ara'] = { 'عربي(Arab)', 'ARB' }, -- Arabic
['at'] = { 'Österreichisch (Austria)', 'AUT' }, -- Austria
['az'] = { 'Azərbaycan(Azerbaijan)', 'AZE' }, -- Azerbaijan
['ba'] = { 'Bosanski(Bosnia and Herzegovina)', 'BIH' }, -- Bosnia and Herzegovina
['bd'] = { '', 'BGD' }, -- Bangladesh
['be'] = { '', 'BEL' }, -- Belgium
['bg'] = { '', 'BGR' }, -- Bulgaria
['br'] = { '', 'BRA' }, -- Brazil
['bt'] = { '', 'BTN' }, -- Bhutan
['bw'] = { '', 'BWA' }, -- Botswana
['by'] = { '', 'BLR' }, -- Belarus
['ca'] = { '', 'CAN' }, -- Canada
['cd'] = { '', 'COD' }, -- Congo
['ch'] = { '', 'CHE' }, -- Switzerland
['cm'] = { '', 'CMR' }, -- Cameroon
['cn'] = { '', 'CHN' }, -- China
['cz'] = { '', 'CZE' }, -- Czechia
['de'] = { 'Deutsch (Germany)', 'GER' }, -- Germany
['dk'] = { '', 'DNK' }, -- Denmark
['ee'] = { '', 'EST' }, -- Estonia
['es'] = { '', 'ESP' }, -- Spain
['et'] = { '', 'ETH' }, -- Ethiopia
['eu'] = { '?', '?' }, -- EurKey
['fi'] = { '', 'FIN' }, -- Finland
['fo'] = { '', 'FRO' }, -- Faroe Islands
['fr'] = { '', 'FRA' }, -- France
['gb'] = { "English (Bri'ish)", 'ENG' }, -- United Kingdom
['ge'] = { '', 'GEO' }, -- Georgia
['gh'] = { '', 'GHA' }, -- Ghana
['gn'] = { '', 'GIN' }, -- Guinea
['gr'] = { '', 'GRC' }, -- Greece
['hr'] = { '', 'HRV' }, -- Croatia
['hu'] = { '', 'HUN' }, -- Hungary
['ie'] = { '', 'IRL' }, -- Ireland
['il'] = { '', 'ISR' }, -- Israel
['in'] = { '', 'IND' }, -- India
['iq'] = { '', 'IRQ' }, -- Iraq
['ir'] = { '', 'IRN' }, -- Iran
['is'] = { '', 'ISL' }, -- Iceland
['it'] = { '', 'ITA' }, -- Italy
['jp'] = { '', 'JPN' }, -- Japan
['ke'] = { '', 'KEN' }, -- Kenya
['kg'] = { '', 'KGZ' }, -- Kyrgyzstan
['kh'] = { '', 'KHM' }, -- Cambodia
['kr'] = { '', 'KOR' }, -- Korea
['kz'] = { '', 'KAZ' }, -- Kazakhstan
['la'] = { '', 'LAO' }, -- Laos
['latm'] = { '?', '?' }, -- Latin America
['latn'] = { '?', '?' }, -- Latin
['lk'] = { '', 'LKA' }, -- Sri Lanka
['lt'] = { '', 'LTU' }, -- Lithuania
['lv'] = { '', 'LVA' }, -- Latvia
['ma'] = { '', 'MAR' }, -- Morocco
['mao'] = { '?', '?' }, -- Maori
['me'] = { '', 'MNE' }, -- Montenegro
['mk'] = { '', 'MKD' }, -- Macedonia
['ml'] = { '', 'MLI' }, -- Mali
['mm'] = { '', 'MMR' }, -- Myanmar
['mn'] = { '', 'MNG' }, -- Mongolia
['mt'] = { '', 'MLT' }, -- Malta
['mv'] = { '', 'MDV' }, -- Maldives
['ng'] = { '', 'NGA' }, -- Nigeria
['nl'] = { '', 'NLD' }, -- Netherlands
['no'] = { '', 'NOR' }, -- Norway
['np'] = { '', 'NRL' }, -- Nepal
['ph'] = { '', 'PHL' }, -- Philippines
['pk'] = { '', 'PAK' }, -- Pakistan
['pl'] = { '', 'POL' }, -- Poland
['pt'] = { '', 'PRT' }, -- Portugal
['ro'] = { '', 'ROU' }, -- Romania
['rs'] = { '', 'SRB' }, -- Serbia
['ru'] = { 'Русский (Russia)', 'RUS' }, -- Russia
['se'] = { '', 'SWE' }, -- Sweden
['si'] = { '', 'SVN' }, -- Slovenia
['sk'] = { '', 'SVK' }, -- Slovakia
['sn'] = { '', 'SEN' }, -- Senegal
['sy'] = { '', 'SYR' }, -- Syria
['th'] = { '', 'THA' }, -- Thailand
['tj'] = { '', 'TJK' }, -- Tajikistan
['tm'] = { '', 'TKM' }, -- Turkmenistan
['tr'] = { '', 'TUR' }, -- Turkey
['tw'] = { '', 'TWN' }, -- Taiwan
['tz'] = { '', 'TZA' }, -- Tanzania
['ua'] = { '', 'UKR' }, -- Ukraine
['us'] = { 'English (United States)', 'USA' }, -- USA
['uz'] = { '', 'UZB' }, -- Uzbekistan
['vn'] = { '', 'VNM' }, -- Vietnam
['za'] = { '', 'ZAF' }, -- South Africa
}
local longname, shortname = table.unpack(xkeyboard_country_code[keymap])
local kb_layout_item = wibox.widget {
{
{
{
id = 'shortname',
markup = '<span foreground="' .. Theme_config.kblayout.item.fg_short .. '">' .. shortname .. '</span>',
widget = wibox.widget.textbox,
valign = 'center',
halign = 'center',
},
{
id = 'longname',
markup = '<span foreground="' .. Theme_config.kblayout.item.fg_long .. '">' .. longname .. '</span>',
widget = wibox.widget.textbox,
font = User_config.font.bold,
},
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
},
margins = dpi(10),
widget = wibox.container.margin,
},
id = 'hover',
shape = Theme_config.kblayout.item.shape,
border_width = Theme_config.kblayout.item.border_width,
border_color = Theme_config.kblayout.item.border_color,
bg = Theme_config.kblayout.item.bg,
widget = wibox.container.background,
}
kb_helper:connect_signal('KB::layout_changed', function(_, k)
if keymap == k then
kb_layout_item.bg = Theme_config.kblayout.item.bg_selected
kb_layout_item.border_color = Theme_config.kblayout.item.bg_selected
kb_layout_item:get_children_by_id('shortname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_selected .. '">' .. shortname .. '</span>'
kb_layout_item:get_children_by_id('longname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_selected .. '">' .. longname .. '</span>'
else
kb_layout_item.bg = Theme_config.kblayout.item.bg
kb_layout_item.border_color = Theme_config.kblayout.item.border_color
kb_layout_item:get_children_by_id('shortname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_short .. '">' .. shortname .. '</span>'
kb_layout_item:get_children_by_id('longname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_long .. '">' .. longname .. '</span>'
end
end)
kb_helper:get_layout_async(function(k)
if keymap == k then
kb_layout_item.bg = Theme_config.kblayout.item.bg_selected
kb_layout_item.border_color = Theme_config.kblayout.item.bg_selected
kb_layout_item:get_children_by_id('shortname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_selected .. '">' .. shortname .. '</span>'
kb_layout_item:get_children_by_id('longname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_selected .. '">' .. longname .. '</span>'
else
kb_layout_item.bg = Theme_config.kblayout.item.bg
kb_layout_item.border_color = Theme_config.kblayout.item.border_color
kb_layout_item:get_children_by_id('shortname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_short .. '">' .. shortname .. '</span>'
kb_layout_item:get_children_by_id('longname')[1].markup = '<span foreground="' .. Theme_config.kblayout.item.fg_long .. '">' .. longname .. '</span>'
end
end)
hover.bg_hover { widget = kb_layout_item }
kb_layout_item:buttons { gtable.join(
abutton({}, 1, function()
kb_helper:set_layout(keymap)
--kb_layout_popup.visible = not kb_layout_popup.visible
end)
), }
list:add(kb_layout_item)
end
return widget
end
return setmetatable({}, { __call = function(_, screen)
local kblayout_widget = wibox.widget {
{
{
{
{
{
id = "icon",
widget = wibox.widget.imagebox,
resize = false,
valign = "center",
halign = "center",
image = gears.color.recolor_image(icondir .. "keyboard.svg", Theme_config.kblayout.fg)
resize = true,
valign = 'center',
halign = 'center',
image = gcolor.recolor_image(icondir .. 'keyboard.svg', Theme_config.kblayout.fg),
},
id = "icon_layout",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(24),
height = dpi(24),
strategy = 'exact',
},
top = dpi(2),
widget = wibox.container.margin,
id = "icon_margin"
{
id = 'text_role',
halign = 'center',
valign = 'center',
widget = wibox.widget.textbox,
},
spacing = dpi(10),
{
id = "label",
align = "center",
valign = "center",
widget = wibox.widget.textbox
layout = wibox.layout.fixed.horizontal,
},
id = "kblayout_layout",
layout = wibox.layout.fixed.horizontal
},
id = "container",
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
bg = Theme_config.kblayout.bg,
fg = Theme_config.kblayout.fg,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(6))
end,
widget = wibox.container.background
}
local function get_kblayout()
awful.spawn.easy_async_with_shell(
[[ setxkbmap -query | grep layout | awk '{print $2}' ]],
function(stdout)
local layout = stdout:gsub("\n", "")
kblayout_widget.container.kblayout_layout.label.text = layout
capi.awesome.emit_signal("update::background:kblayout")
end
)
end
local function create_kb_layout_item(keymap)
-- TODO: Add more, too lazy rn
local longname, shortname
local xkeyboard_country_code = {
{ "af", "أفغانيش(Afghanistan)", "AFG" }, -- Afghanistan
{ "al", "Shqip(Albania)", "ALB" }, -- Albania
{ "am", "Hայերեն(Armenia)", "ARM" }, -- Armenia
{ "ara", "عربي(Arab)", "ARB" }, -- Arabic
{ "at", "Österreichisch (Austria)", "AUT" }, -- Austria
{ "az", "Azərbaycan(Azerbaijan)", "AZE" }, -- Azerbaijan
{ "ba", "Bosanski(Bosnia and Herzegovina)", "BIH" }, -- Bosnia and Herzegovina
{ "bd", "", "BGD" }, -- Bangladesh
{ "be", "", "BEL" }, -- Belgium
{ "bg", "", "BGR" }, -- Bulgaria
{ "br", "", "BRA" }, -- Brazil
{ "bt", "", "BTN" }, -- Bhutan
{ "bw", "", "BWA" }, -- Botswana
{ "by", "", "BLR" }, -- Belarus
{ "ca", "", "CAN" }, -- Canada
{ "cd", "", "COD" }, -- Congo
{ "ch", "", "CHE" }, -- Switzerland
{ "cm", "", "CMR" }, -- Cameroon
{ "cn", "", "CHN" }, -- China
{ "cz", "", "CZE" }, -- Czechia
{ "de", "Deutsch (Germany)", "GER" }, -- Germany
{ "dk", "", "DNK" }, -- Denmark
{ "ee", "", "EST" }, -- Estonia
{ "es", "", "ESP" }, -- Spain
{ "et", "", "ETH" }, -- Ethiopia
{ "eu", "?", "?" }, -- EurKey
{ "fi", "", "FIN" }, -- Finland
{ "fo", "", "FRO" }, -- Faroe Islands
{ "fr", "", "FRA" }, -- France
{ "gb", "English (Bri'ish)", "ENG" }, -- United Kingdom
{ "ge", "", "GEO" }, -- Georgia
{ "gh", "", "GHA" }, -- Ghana
{ "gn", "", "GIN" }, -- Guinea
{ "gr", "", "GRC" }, -- Greece
{ "hr", "", "HRV" }, -- Croatia
{ "hu", "", "HUN" }, -- Hungary
{ "ie", "", "IRL" }, -- Ireland
{ "il", "", "ISR" }, -- Israel
{ "in", "", "IND" }, -- India
{ "iq", "", "IRQ" }, -- Iraq
{ "ir", "", "IRN" }, -- Iran
{ "is", "", "ISL" }, -- Iceland
{ "it", "", "ITA" }, -- Italy
{ "jp", "", "JPN" }, -- Japan
{ "ke", "", "KEN" }, -- Kenya
{ "kg", "", "KGZ" }, -- Kyrgyzstan
{ "kh", "", "KHM" }, -- Cambodia
{ "kr", "", "KOR" }, -- Korea
{ "kz", "", "KAZ" }, -- Kazakhstan
{ "la", "", "LAO" }, -- Laos
{ "latam", "?", "?" }, -- Latin America
{ "latin", "?", "?" }, -- Latin
{ "lk", "", "LKA" }, -- Sri Lanka
{ "lt", "", "LTU" }, -- Lithuania
{ "lv", "", "LVA" }, -- Latvia
{ "ma", "", "MAR" }, -- Morocco
{ "mao", "?", "?" }, -- Maori
{ "me", "", "MNE" }, -- Montenegro
{ "mk", "", "MKD" }, -- Macedonia
{ "ml", "", "MLI" }, -- Mali
{ "mm", "", "MMR" }, -- Myanmar
{ "mn", "", "MNG" }, -- Mongolia
{ "mt", "", "MLT" }, -- Malta
{ "mv", "", "MDV" }, -- Maldives
{ "ng", "", "NGA" }, -- Nigeria
{ "nl", "", "NLD" }, -- Netherlands
{ "no", "", "NOR" }, -- Norway
{ "np", "", "NRL" }, -- Nepal
{ "ph", "", "PHL" }, -- Philippines
{ "pk", "", "PAK" }, -- Pakistan
{ "pl", "", "POL" }, -- Poland
{ "pt", "", "PRT" }, -- Portugal
{ "ro", "", "ROU" }, -- Romania
{ "rs", "", "SRB" }, -- Serbia
{ "ru", "Русский (Russia)", "RUS" }, -- Russia
{ "se", "", "SWE" }, -- Sweden
{ "si", "", "SVN" }, -- Slovenia
{ "sk", "", "SVK" }, -- Slovakia
{ "sn", "", "SEN" }, -- Senegal
{ "sy", "", "SYR" }, -- Syria
{ "th", "", "THA" }, -- Thailand
{ "tj", "", "TJK" }, -- Tajikistan
{ "tm", "", "TKM" }, -- Turkmenistan
{ "tr", "", "TUR" }, -- Turkey
{ "tw", "", "TWN" }, -- Taiwan
{ "tz", "", "TZA" }, -- Tanzania
{ "ua", "", "UKR" }, -- Ukraine
{ "us", "English (United States)", "USA" }, -- USA
{ "uz", "", "UZB" }, -- Uzbekistan
{ "vn", "", "VNM" }, -- Vietnam
{ "za", "", "ZAF" } -- South Africa
}
for _, c in ipairs(xkeyboard_country_code) do
if c[1] == keymap then
longname = c[2]
shortname = c[3]
end
end
local kb_layout_item = wibox.widget {
{
{
-- Short name e.g. GER, ENG, RUS
{
{
text = shortname,
widget = wibox.widget.textbox,
font = User_config.font.extrabold,
id = "shortname"
},
fg = Theme_config.kblayout.item.fg_short,
shape = Theme_config.kblayout.shape,
widget = wibox.container.background,
id = "background2"
},
{
{
text = longname,
widget = wibox.widget.textbox,
font = User_config.font.bold,
id = "longname",
},
fg = Theme_config.kblayout.item.fg_long,
widget = wibox.container.background,
id = "background1"
},
spacing = dpi(15),
layout = wibox.layout.fixed.horizontal,
id = "container"
},
margins = dpi(10),
widget = wibox.container.margin,
id = "margin"
},
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(8))
end,
bg = Theme_config.kblayout.item.bg,
widget = wibox.container.background,
id = "background",
keymap = keymap
}
Hover_signal(kb_layout_item)
hover.bg_hover { widget = kblayout_widget }
capi.awesome.connect_signal(
"update::background:kblayout",
function()
awful.spawn.easy_async_with_shell(
[[ setxkbmap -query | grep layout | awk '{print $2}' ]],
function(stdout)
local layout = stdout:gsub("\n", "")
if kb_layout_item.keymap == layout then
kb_layout_item.bg = Theme_config.kblayout.item.bg_selected
kb_layout_item:get_children_by_id("background2")[1].fg = Theme_config.kblayout.item.fg_selected
kb_layout_item:get_children_by_id("background1")[1].fg = Theme_config.kblayout.item.fg_selected
else
kb_layout_item.bg = Theme_config.kblayout.item.bg
kb_layout_item:get_children_by_id("background2")[1].fg = Theme_config.kblayout.item.fg_short
kb_layout_item:get_children_by_id("background1")[1].fg = Theme_config.kblayout.item.fg_long
end
end
)
end
)
get_kblayout()
kb_helper:get_layout_async(function(stdout)
kblayout_widget:get_children_by_id('text_role')[1].text = stdout:gsub('\n', '')
end)
kb_layout_item:connect_signal(
"button::press",
function()
awful.spawn.easy_async_with_shell(
"setxkbmap " .. keymap,
function()
capi.awesome.emit_signal("kblayout::hide:kbmenu")
capi.mousegrabber.stop()
get_kblayout()
end
)
end
)
return kb_layout_item
end
kb_helper:connect_signal('KB::layout_changed', function(_, k)
kblayout_widget:get_children_by_id('text_role')[1].text = k
end)
local function get_kblist()
local kb_layout_items = {
layout = wibox.layout.fixed.vertical,
spacing = dpi(10)
}
for i, keymap in pairs(User_config.kblayout) do
kb_layout_items[i] = create_kb_layout_item(keymap)
end
local cont = {
{
kb_layout_items,
margins = dpi(10),
widget = wibox.container.margin
},
layout = wibox.layout.fixed.vertical,
}
return cont
end
local kb_menu_widget = awful.popup {
screen = s,
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
end,
widget = wibox.container.background,
bg = Theme_config.kblayout.bg_container,
border_width = dpi(4),
border_color = Theme_config.kblayout.border_color_container,
width = dpi(100),
max_height = dpi(600),
visible = false,
kb_layout_popup = apopup {
widget = create_kb_layout_list(),
border_color = Theme_config.kblayout.border_color,
border_width = Theme_config.kblayout.border_width,
screen = screen,
ontop = true,
placement = function(c) awful.placement.align(c,
{ position = "top_right", margins = { right = dpi(255), top = dpi(60) } })
end
visible = false,
bg = Theme_config.kblayout.bg_container,
}
kb_menu_widget:connect_signal(
"mouse::leave",
function()
capi.mousegrabber.run(
function()
kblayout_widget.bg = Theme_config.kblayout.bg
capi.awesome.emit_signal("kblayout::hide:kbmenu")
capi.mousegrabber.stop()
return true
end,
"arrow"
)
end
)
kblayout_widget:buttons { gtable.join(
abutton({}, 1, function()
local geo = capi.mouse.coords()
kb_layout_popup.y = dpi(65)
kb_layout_popup.x = geo.x - kb_layout_popup.width / 2
kb_layout_popup.visible = not kb_layout_popup.visible
end)
), }
kb_menu_widget:connect_signal(
"mouse::enter",
function()
mousegrabber.stop()
end
)
kb_menu_widget:setup(
get_kblist()
)
local function toggle_kb_layout()
awful.spawn.easy_async_with_shell(
"setxkbmap -query | grep layout: | awk '{print $2}'",
function(stdout)
for j, n in ipairs(User_config.kblayout) do
if stdout:match(n) then
if j == #User_config.kblayout then
awful.spawn.easy_async_with_shell(
"setxkbmap " .. User_config.kblayout[1],
function()
get_kblayout()
end
)
else
awful.spawn.easy_async_with_shell(
"setxkbmap " .. User_config.kblayout[j + 1],
function()
get_kblayout()
end
)
end
end
end
end
)
end
capi.awesome.connect_signal(
"kblayout::toggle",
function()
toggle_kb_layout()
end
)
-- Signals
Hover_signal(kblayout_widget)
local kblayout_keygrabber = awful.keygrabber {
autostart = false,
stop_event = 'release',
keypressed_callback = function(self, mod, key, command)
capi.awesome.emit_signal("kblayout::hide:kbmenu")
capi.mousegrabber.stop()
end
}
kblayout_widget:connect_signal(
"button::press",
function()
capi.mousegrabber.stop()
if kb_menu_widget.visible then
kb_menu_widget.visible = false
kblayout_keygrabber:stop()
else
kb_menu_widget.visible = true
kblayout_keygrabber:start()
end
end
)
capi.awesome.connect_signal(
"kblayout::hide:kbmenu",
function()
kb_menu_widget.visible = false
kblayout_keygrabber:stop()
end
)
get_kblayout()
kb_menu_widget.visible = false
return kblayout_widget
end
end, })

View File

@@ -3,32 +3,35 @@
----------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local alayout = require("awful.layout")
local awidget = require("awful.widget")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears.table")
local wibox = require("wibox")
local abutton = require('awful.button')
local alayout = require('awful.layout')
local awidget = require('awful.widget')
local dpi = require('beautiful').xresources.apply_dpi
local gtable = require('gears.table')
local wibox = require('wibox')
-- Local libs
local hover = require('src.tools.hover')
--#region Layout icons
local layout_path = Theme_path .. "../assets/layout/"
local layout_path = Theme_path .. '../assets/layout/'
Theme.layout_cornerne = layout_path .. "cornerne.png"
Theme.layout_cornernw = layout_path .. "cornernw.png"
Theme.layout_cornerse = layout_path .. "cornerse.png"
Theme.layout_cornersw = layout_path .. "cornersw.png"
Theme.layout_dwindle = layout_path .. "dwindle.png"
Theme.layout_fairh = layout_path .. "fairh.png"
Theme.layout_fairv = layout_path .. "fairv.png"
Theme.layout_floating = layout_path .. "floating.png"
Theme.layout_fullscreen = layout_path .. "fullscreen.png"
Theme.layout_magnifier = layout_path .. "magnifier.png"
Theme.layout_max = layout_path .. "max.png"
Theme.layout_spiral = layout_path .. "spiral.png"
Theme.layout_tile = layout_path .. "tile.png"
Theme.layout_tilebottom = layout_path .. "tilebottom.png"
Theme.layout_tileleft = layout_path .. "tileleft.png"
Theme.layout_tiletop = layout_path .. "tiletop.png"
Theme.layout_cornerne = layout_path .. 'cornerne.png'
Theme.layout_cornernw = layout_path .. 'cornernw.png'
Theme.layout_cornerse = layout_path .. 'cornerse.png'
Theme.layout_cornersw = layout_path .. 'cornersw.png'
Theme.layout_dwindle = layout_path .. 'dwindle.png'
Theme.layout_fairh = layout_path .. 'fairh.png'
Theme.layout_fairv = layout_path .. 'fairv.png'
Theme.layout_floating = layout_path .. 'floating.png'
Theme.layout_fullscreen = layout_path .. 'fullscreen.png'
Theme.layout_magnifier = layout_path .. 'magnifier.png'
Theme.layout_max = layout_path .. 'max.png'
Theme.layout_spiral = layout_path .. 'spiral.png'
Theme.layout_tile = layout_path .. 'tile.png'
Theme.layout_tilebottom = layout_path .. 'tilebottom.png'
Theme.layout_tileleft = layout_path .. 'tileleft.png'
Theme.layout_tiletop = layout_path .. 'tiletop.png'
--#endregion
-- Returns the layoutbox widget
@@ -39,22 +42,21 @@ return function()
{
awidget.layoutbox(),
widget = wibox.container.place,
halign = "center",
valign = "center"
},
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
},
widget = wibox.container.constraint,
width = dpi(40)
strategy = 'exact',
width = dpi(40),
},
bg = Theme_config.layout_list.bg,
shape = Theme_config.layout_list.shape,
widget = wibox.container.background
widget = wibox.container.background,
}
Hover_signal(layout)
hover.bg_hover { widget = layout }
layout:buttons(gtable.join(
abutton({}, 1, function()

View File

@@ -3,15 +3,14 @@
--------------------------------
-- Awesome Libs
local abutton = require("awful.button")
local apopup = require("awful.popup")
local atooltip = require("awful.tooltip")
local base = require("wibox.widget.base")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local gtable = require("gears.table")
local naughty = require("naughty")
local wibox = require("wibox")
local abutton = require('awful.button')
local apopup = require('awful.popup')
local atooltip = require('awful.tooltip')
local base = require('wibox.widget.base')
local dpi = require('beautiful').xresources.apply_dpi
local gears = require('gears')
local gtable = require('gears.table')
local wibox = require('wibox')
local capi = {
awesome = awesome,
@@ -19,51 +18,79 @@ local capi = {
}
-- Icon directory path
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/network/"
local icondir = gears.filesystem.get_configuration_dir() .. 'src/assets/icons/network/'
local nm_widget = require("src.modules.network_controller.init")
local nm_widget = require('src.modules.network_controller.init')
local hover = require('src.tools.hover')
local network = { mt = {} }
function network.new(args)
args = args or {}
local w = base.make_widget_from_value({
local w = base.make_widget_from_value {
{
{
{
{
id = 'wifi_icon',
image = gears.color.recolor_image(icondir .. "no-internet" .. ".svg", Theme_config.network.fg),
image = gears.color.recolor_image(icondir .. 'no-internet.svg', Theme_config.network.fg),
widget = wibox.widget.imagebox,
resize = false
resize = false,
},
{
id = "wifi_strength",
id = 'wifi_strength',
visible = true,
widget = wibox.widget.textbox
widget = wibox.widget.textbox,
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
layout = wibox.layout.fixed.horizontal,
},
left = dpi(8),
right = dpi(8),
widget = wibox.container.margin
widget = wibox.container.margin,
},
widget = wibox.container.place,
halign = "center",
valign = "center"
halign = 'center',
valign = 'center',
},
bg = Theme_config.network.bg,
fg = Theme_config.network.fg,
shape = Theme_config.network.shape,
widget = wibox.container.background
})
widget = wibox.container.background,
}
Hover_signal(w)
assert(w, 'Failed to create widget')
hover.bg_hover { widget = w }
gtable.crush(w, network, true)
capi.awesome.connect_signal('NM::AccessPointStrength', function(strength)
strength = math.floor(strength)
w:get_children_by_id('wifi_strength')[1].text = strength .. '%'
w:get_children_by_id('wifi_icon')[1].image = gears.color.recolor_image(icondir ..
'wifi-strength-' .. math.floor(strength / 25) + 1 .. '.svg', Theme_config.network.fg)
end)
capi.awesome.connect_signal('NM::EthernetStatus', function(connected, speed)
local tt = atooltip {
objects = { w },
mode = 'outside',
preferred_alignments = 'middle',
margins = dpi(10),
}
if connected then
w:get_children_by_id('wifi_icon')[1].image = gears.color.recolor_image(icondir .. 'ethernet.svg',
Theme_config.network.fg)
tt.text = 'Connected via Ethernet at ' .. math.floor(speed or 0) .. '/Mbps'
else
w:get_children_by_id('wifi_icon')[1].image = gears.color.recolor_image(icondir .. 'no-internet.svg',
Theme_config.network.fg)
tt.text = 'No connection found'
end
end)
local nm = nm_widget { screen = args.screen }
local network_controler_popup = apopup {
@@ -82,25 +109,6 @@ function network.new(args)
end)
))
awesome.connect_signal("NM::AccessPointStrength", function(strength)
strength = math.floor(strength)
w:get_children_by_id("wifi_strength")[1].text = strength .. "%"
w:get_children_by_id("wifi_icon")[1].image = gears.color.recolor_image(icondir ..
"wifi-strength-" .. math.floor(strength / 25) + 1 .. ".svg", Theme_config.network.fg)
end)
nm:connect_signal("NM::Bitrate", function(_, bitrate)
print(bitrate)
end)
atooltip {
objects = { w },
mode = "outside",
preferred_alignments = "middle",
margins = dpi(10),
text = "Connected to " .. "" .. " with " .. "" .. " signal strength"
}
return w
end

Some files were not shown because too many files have changed in this diff Show More