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

@@ -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
--[[ 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 ''
})
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 "",
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 ""
})
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
},
{ -- Volume Bar
{
{
{ -- Volume Icon
{
id = "progressbar1",
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
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,
},
id = "progressbar_container2",
halign = "center",
valign = "center",
widget = wibox.container.place
widget = wibox.container.constraint,
width = dpi(25),
height = dpi(25),
strategy = 'exact',
},
id = "progressbar_container",
width = dpi(240),
heigth = dpi(20),
stragety = "max",
widget = wibox.container.constraint
{ -- Volume Bar
{
{
id = 'progressbar',
color = Theme_config.volume_osd.bar_bg_active,
background_color = Theme_config.volume_osd.bar_bg,
max_value = 100,
value = 0,
shape = gshape.rounded_rect,
widget = wibox.widget.progressbar,
},
widget = wibox.container.constraint,
width = dpi(250),
height = dpi(5),
},
widget = wibox.container.place,
},
{ -- Volume text
widget = wibox.widget.textbox,
id = 'text_role',
text = '0',
valign = 'center',
halign = 'center',
},
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal,
},
id = "layout1",
spacing = dpi(10),
layout = wibox.layout.fixed.horizontal
left = dpi(10),
right = dpi(10),
top = dpi(20),
bottom = dpi(20),
widget = wibox.container.margin,
},
id = "margin",
margins = dpi(10),
widget = wibox.container.margin
shape = Theme_config.volume_osd.shape,
widget = wibox.container.background,
},
forced_width = dpi(300),
forced_height = dpi(80),
shape = function(cr, width, height)
gears.shape.rounded_rect(cr, width, height, dpi(12))
end,
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)
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)
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"
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
ret.w:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg",
Theme_config.volume_osd.icon_color))
audio_helper:connect_signal('output::get', function(_, muted, volume)
volume = tonumber(volume or 0)
if muted then
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
w.widget:get_children_by_id('progressbar')[1].value = volume
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
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
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
function osd.mt:__call(...)
return osd.new(...)
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,
scrollbar_width = 0,
id = "connected_device_list"
{
step = dpi(50),
spacing = dpi(10),
layout = require('src.lib.overflow_widget.overflow').vertical,
scrollbar_width = 0,
id = 'connected_device_list',
},
id = 'margin',
margins = dpi(10),
widget = wibox.container.margin,
},
id = "margin",
margins = dpi(10),
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,
},
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]
local connected_animation = rubato.timed {
duration = 0.2,
pos = connected_list.height,
clamp_position = true,
subscribed = function(v)
connected_list.height = v
end,
}
ret:connect_signal('device::added_connected', function(device)
if device.Connected then
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
connected_animation.target = dpi(size)
connected_margin:connect_signal(
"button::press",
function()
local rubato_timer = rubato.timed {
duration = 0.2,
pos = connected_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
connected_list.forced_height = v
end
}
if connected_list.forced_height == 0 then
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
rubato_timer.target = dpi(size)
end
if size > 0 then
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_margin.connected_bg.shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, 4)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
connected_icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg",
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.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]
ret:connect_signal('device::removed_connected', function(device)
local size = (#ret:get_paired_devices() * 60)
if size < 210 then
connected_animation.target = dpi(size)
discovered_margin:connect_signal(
"button::press",
function()
local rubato_timer = rubato.timed {
duration = 0.2,
pos = discovered_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
discovered_list.forced_height = v
end
}
connected_margin.connected_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
if discovered_list.forced_height == 0 then
local size = (#ret:get_discovered_devices() * 60)
if size > 210 then
size = 210
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
if size > 0 then
rubato_timer.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))
connected_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
Theme_config.bluetooth_controller.connected_icon_color))
end
else
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',
Theme_config.bluetooth_controller.connected_icon_color))
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_animation = rubato.timed {
duration = 0.2,
pos = discovered_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
discovered_list.forced_height = v
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
else
rubato_timer.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-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
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
else
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',
Theme_config.bluetooth_controller.discovered_icon_color))
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)
end
-- Show the brightness_osd for 3 seconds
function brightness_osd:show()
self.visible = true
self.timer:start(true)
if self.timer.started then
self.timer:again()
else
self.timer:start()
end
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",
widget = wibox.widget.imagebox
{
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.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
},
{ -- 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")
local icon = icondir .. 'brightness'
if brightness >= 0 and brightness < 34 then
icon = icon .. '-low.svg'
elseif brightness >= 34 and brightness < 67 then
icon = icon .. '-medium.svg'
elseif brightness >= 67 then
icon = icon .. '-high.svg'
end
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"
if brightness >= 0 and brightness < 34 then
icon = icon .. "-low.svg"
elseif brightness >= 34 and brightness < 67 then
icon = icon .. "-medium.svg"
elseif brightness >= 67 then
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,124 +21,126 @@ 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 {
{
{
{
{ -- Task detail
{ -- Calendar color
widget = wibox.container.background,
bg = args.color,
forced_width = dpi(10),
shape = function(cr, _, height)
gshape.rounded_rect(cr, dpi(10), height, dpi(8))
end,
{ -- Task detail
{ -- Calendar color
widget = wibox.container.background,
bg = args.color,
forced_width = dpi(10),
shape = function(cr, _, height)
gshape.rounded_rect(cr, dpi(10), height, dpi(8))
end,
},
{
{ -- Summary
widget = wibox.widget.textbox,
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',
},
{ -- From - To
widget = wibox.widget.textbox,
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',
}, -- Year
{
widget = wibox.widget.textbox,
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,
},
widget = wibox.container.margin,
left = dpi(9),
},
{
{ -- Summary
widget = wibox.widget.textbox,
text = args.summary:sub(1, -2) or "NO SUMMARY",
valign = "center",
halign = "left",
id = "summary",
{ -- Location
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. 'location.svg', args.color),
resize = false,
valign = 'center',
halign = 'center',
},
{ -- Date long
widget = wibox.widget.textbox,
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",
},
{ -- Repeat information
widget = wibox.widget.textbox,
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.location:sub(1, -2) or 'F303',
valign = 'center',
halign = 'left',
id = 'location',
},
spacing = dpi(10),
layout = wibox.layout.fixed.vertical,
id = 'location_container',
layout = wibox.layout.fixed.horizontal,
},
spacing = dpi(20),
layout = wibox.layout.fixed.horizontal
{ -- Alarm
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. 'alarm.svg', args.color),
resize = false,
valign = 'center',
halign = 'center',
},
{
widget = wibox.widget.textbox,
text = args.alarm or 'NO ALARM',
valign = 'center',
halign = 'left',
id = 'alarm',
},
spacing = dpi(10),
id = 'alarm_container',
layout = wibox.layout.fixed.horizontal,
},
id = 'task_detail',
spacing = dpi(15),
layout = wibox.layout.fixed.vertical,
},
widget = wibox.container.margin,
left = dpi(9)
},
{ -- Location
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. "location.svg", args.color),
resize = false,
valign = "center",
halign = "center",
},
{
widget = wibox.widget.textbox,
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
},
{ -- Alarm
{
widget = wibox.widget.imagebox,
image = gcolor.recolor_image(icondir .. "alarm.svg", args.color),
resize = false,
valign = "center",
halign = "center",
},
{
widget = wibox.widget.textbox,
text = args.alarm or "NO ALARM",
valign = "center",
halign = "left",
id = "alarm",
},
spacing = dpi(10),
id = "alarm_container",
layout = wibox.layout.fixed.horizontal
},
id = "task_detail",
spacing = dpi(15),
layout = wibox.layout.fixed.vertical
left = dpi(6),
right = dpi(15),
top = dpi(15),
bottom = dpi(15),
},
widget = wibox.container.margin,
left = dpi(6),
right = dpi(15),
top = dpi(15),
bottom = dpi(15),
},
bg = Theme_config.calendar.task_info.bg,
fg = Theme_config.calendar.task_info.fg,
shape = Theme_config.calendar.task_info.shape,
widget = wibox.container.background,
}
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

File diff suppressed because it is too large Load Diff

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
@@ -50,17 +49,17 @@ return function(s, w)
end
local top_left = awful.popup {
screen = s,
widget = prepare_widgets(w),
ontop = false,
bg = Theme_config.left_bar.bg,
visible = true,
maximum_width = dpi(650),
placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end
}
screen = s,
widget = prepare_widgets(w),
ontop = false,
bg = Theme_config.left_bar.bg,
visible = true,
maximum_width = dpi(650),
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)
end
end, "PropertiesChanged")
if self._private.NetworkManagerDevice.State == network.DeviceState.ACTIVATED then
awesome.emit_signal('NM::EthernetStatus', true, self._private.NetworkManagerDeviceWired.Speed)
end
-- 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()
ret:scan_access_points()
end
)
abutton({}, 1, nil, function()
ret:scan_access_points()
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 capi = {
client = client,
}
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)
})
local instance = nil
dnd:get_widget():connect_signal("dnd::toggle", function(enabled)
User_config.dnd = enabled
end)
local info_center = {}
--#region Activation area
function info_center:toggle()
if self.container.visible then
self.container.visible = false
else
self.container.visible = true
end
end
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,
}
function info_center.new(args)
args = args or {}
activation_area:setup({
widget = wibox.container.background,
forced_height = dpi(1),
forced_width = dpi(300),
bg = '#00000000',
layout = wibox.layout.fixed.horizontal
})
capi.awesome.connect_signal(
"notification_center_activation::toggle",
function(screen, hide)
if screen == s then
activation_area.visible = hide
end
end
)
--#endregion
--#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,
},
{ -- 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,
},
{ -- 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,
},
margins = dpi(20),
widget = wibox.container.margin,
},
{
{
{
bg = Theme_config.notification_center.spacing_line.color,
widget = wibox.container.background,
},
widget = wibox.container.constraint,
height = dpi(2),
strategy = 'exact',
},
left = dpi(60),
right = dpi(60),
widget = wibox.container.margin,
},
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
},
id = "margin3",
margins = dpi(10),
widget = wibox.container.margin
},
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"
},
{
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 {
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")(),
{
{
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
{ -- Clear all button
{
{
{
{
text = 'Clear',
valign = 'center',
halign = 'center',
widget = wibox.widget.textbox,
id = 'clear',
},
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,
},
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,
},
id = "layout5",
layout = wibox.layout.align.vertical
layout = wibox.layout.align.vertical,
},
id = "margin6",
margins = dpi(20),
widget = wibox.container.margin
widget = wibox.container.margin,
},
id = "yes",
spacing_widget = {
{
bg = Theme_config.notification_center.spacing_color,
widget = wibox.container.background
},
top = dpi(40),
bottom = dpi(40),
widget = wibox.container.margin
thickness = dpi(2),
color = Theme_config.notification_center.spacing_color,
span_ratio = 0.9,
widget = wibox.widget.separator,
},
spacing = dpi(1),
forced_height = dpi(800),
forced_width = dpi(1000),
layout = wibox.layout.flex.horizontal
})
end
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
math.randomseed(os.time())
local prob = math.random(1, 10)
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>"
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>"
end
no_notification_widget.visible = true
if (prob == 5) or (prob == 6) then
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.visible = false
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
notification_center_setup()
w:get_children_by_id('no_notification_icon')[1].visible = true
w:get_children_by_id('no_notification_text')[1].visible = true
else
w:get_children_by_id('no_notification_icon')[1].visible = false
w:get_children_by_id('no_notification_text')[1].visible = false
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")
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,
}
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)
Hover_signal(clear_all_widget.margin3.background4)
--#endregion
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