add new context_menu and rework dock, programs can now be added to the dock my right clicking any program in the application launcher an choosing Add to Dock

This commit is contained in:
Rene
2022-08-15 15:18:51 +02:00
parent 9cea2f98cc
commit 268cb29a6b
22 changed files with 507 additions and 167 deletions

View File

@@ -9,6 +9,12 @@ local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
local json = require("src.lib.json-lua.json-lua")
local cm = require("src.modules.context_menu")
local icondir = awful.util.getdir("config") .. "src/assets/icons/context_menu/"
return function()
local application_grid = wibox.widget {
@@ -34,7 +40,6 @@ return function()
---@return table widgets Unsorted widget table
local function get_applications_from_file()
local list = {}
--for _, file in ipairs(desktop_files) do
local app_info = Gio.AppInfo
local apps = app_info.get_all()
for _, app in ipairs(apps) do
@@ -83,8 +88,9 @@ return function()
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_string(desktop_app_info, "Cathegory") 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),
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,
@@ -95,18 +101,84 @@ return function()
widget = wibox.container.background
}
local context_menu = cm({
entries = {
{
name = "Execute as sudo",
icon = gears.color.recolor_image(icondir .. "launch.svg", Theme_config.context_menu.icon_color),
callback = function()
awesome.emit_signal("application_launcher::show")
awful.spawn("/home/crylia/.config/awesome/src/scripts/start_as_admin.sh " .. app_widget.exec)
end
},
{
name = "Pin to dock",
icon = gears.color.recolor_image(icondir .. "pin.svg", Theme_config.context_menu.icon_color),
callback = function()
local handler = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not handler then
return
end
local dock_table = json:decode(handler:read("a")) or {}
handler:close()
---@diagnostic disable-next-line: param-type-mismatch
table.insert(dock_table, {
name = app_widget.name or "",
icon = Get_gicon_path(app_info.get_icon(app)) 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("/home/crylia/.config/awesome/src/config/dock.json", "w")
if not handler then
return
end
handler:write(dock_encoded)
handler:close()
awesome.emit_signal("dock::changed")
end
},
{
name = "Add to desktop",
icon = gears.color.recolor_image(icondir .. "desktop.svg", Theme_config.context_menu.icon_color),
callback = function()
awesome.emit_signal("application_launcher::show")
--!TODO: Add to desktop
end
}
}
})
-- Execute command on left click and hide launcher
app_widget:buttons(
gears.table.join(
awful.button(
{},
1,
nil,
function()
awful.spawn.with_shell(app_widget.exec)
awful.button({
modifiers = {},
button = 1,
on_release = function()
Gio.AppInfo.launch_uris_async(app)
awesome.emit_signal("application_launcher::show")
end
)
}),
awful.button({
modifiers = {},
button = 3,
on_release = function()
if not context_menu then
return
end
-- add offset so mouse is above widget, this is so the mouse::leave event triggers always
context_menu.x = mouse.coords().x - 10
context_menu.y = mouse.coords().y - 10
context_menu.visible = not context_menu.visible
end
})
)
)
Hover_signal(app_widget)
@@ -220,15 +292,7 @@ return function()
awesome.emit_signal("searchbar::stop")
local selected_widget = application_grid:get_widgets_at(curser.y, curser.x)[1]
if selected_widget.terminal then
awful.spawn(User_config.terminal ..
" -e " ..
selected_widget.exec:gsub("%%F", ""):gsub("%%u", ""):gsub("%%U", ""):gsub("%%f", ""):gsub("%%i", ""):gsub("%%c"
, ""):gsub("%%k", ""))
else
awful.spawn.with_shell(selected_widget.exec:gsub("%%F", ""):gsub("%%u", ""):gsub("%%U", ""):gsub("%%f", ""):gsub("%%i"
, ""):gsub("%%c", ""):gsub("%%k", ""))
end
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0))
end
)

View File

@@ -62,6 +62,9 @@ return function(s)
function()
if mouse.screen == s then
application_container.visible = not application_container.visible
if application_container.visible == false then
awesome.emit_signal("searchbar::stop")
end
end
if application_container.visible then
awesome.emit_signal("searchbar::start")

View File

@@ -243,7 +243,6 @@ return function()
searchbar.s_background.fg = Theme_config.application_launcher.searchbar.fg
search_text:set_markup(promt_text_with_cursor("", 1))
end
end
)

View File

@@ -0,0 +1,112 @@
---------------------------------------
-- This is the brightness_osd module --
---------------------------------------
-- Awesome Libs
local awful = require("awful")
local dpi = require("beautiful").xresources.apply_dpi
local gears = require("gears")
local wibox = require("wibox")
return function(args)
if not args then
return
end
local function get_entries()
local menu_entries = { layout = wibox.layout.fixed.vertical, spacing = dpi(10) }
if args.entries then
for _, entry in ipairs(args.entries) do
local menu_entry = wibox.widget {
{
{
{
{ -- Icon
widget = wibox.widget.imagebox,
image = gears.color.recolor_image(entry.icon, Theme_config.context_menu.entry.icon_color),
valign = "center",
halign = "center",
resize = true,
icon = entry.icon,
id = "icon"
},
widget = wibox.container.constraint,
stragety = "exact",
width = dpi(24),
height = dpi(24),
id = "const"
},
{ -- Text
widget = wibox.widget.textbox,
text = entry.name,
id = "name"
},
id = "lay",
spacing = dpi(5),
layout = wibox.layout.fixed.horizontal
},
margins = dpi(10),
widget = wibox.container.margin,
id = "mar"
},
bg = Theme_config.context_menu.entry.bg,
fg = Theme_config.context_menu.entry.fg,
shape = Theme_config.context_menu.entry.shape,
border_width = Theme_config.context_menu.entry.border_width,
border_color = Theme_config.context_menu.entry.border_color,
widget = wibox.container.background,
id = "menu_entry"
}
menu_entry:buttons(gears.table.join(
awful.button({
modifiers = {},
button = 1,
on_release = function()
awesome.emit_signal("context_menu::hide")
entry.callback()
end
})
))
Hover_signal(menu_entry, nil, Theme_config.context_menu.entry.hover_fg,
Theme_config.context_menu.entry.hover_border, Theme_config.context_menu.entry.icon_color,
Theme_config.context_menu.entry.icon_color_hover)
table.insert(menu_entries, menu_entry)
end
end
return menu_entries
end
local menu = awful.popup {
widget = {
get_entries(),
margins = dpi(10),
widget = wibox.container.margin
},
bg = Theme_config.context_menu.bg,
fg = Theme_config.context_menu.fg,
border_width = Theme_config.context_menu.border_width,
border_color = Theme_config.context_menu.border_color,
shape = Theme_config.context_menu.shape,
x = mouse.coords().x,
y = mouse.coords().y,
visible = false,
ontop = true,
placement = awful.placement.no_offscreen,
}
menu:connect_signal("mouse::leave", function()
awesome.emit_signal("context_menu::hide")
end)
awesome.connect_signal(
"context_menu::hide",
function()
menu.visible = false
end
)
return menu
end

View File

@@ -3,30 +3,29 @@
--------------------------------------------------------------------------------------------------------------
-- Awesome Libs
local awful = require("awful")
local async = require("async")
local dpi = require("beautiful").xresources.apply_dpi
local Gio = require("lgi").Gio
local gears = require("gears")
local wibox = require("wibox")
return function(screen, programs)
local json = require("src.lib.json-lua.json-lua")
local icondir = awful.util.getdir("config") .. "src/assets/icons/context_menu/"
local cm = require("src.modules.context_menu")
return function(screen)
local cm_open = false
local dock_element_ammount = 0
---Creates a new program widget for the dock
---@param program string | nil The name of the .desktop file
---@param program string | function The name of the .desktop file
---@param size number The size of the widget
---@return widox.widget | nil The widget or nil if the program is not found
local function create_dock_element(program, size)
if not program then
return
end
local desktop_app_info = Gio.DesktopAppInfo.new_from_filename(program)
if not desktop_app_info then
return
end
local gicon = Gio.Icon.new_for_string(Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon"))
if not gicon then
return
end
local dock_element = wibox.widget {
{
@@ -35,7 +34,7 @@ return function(screen, programs)
{
resize = true,
widget = wibox.widget.imagebox,
image = Get_gicon_path(gicon) or "",
image = program.icon or "",
valign = "center",
halign = "center",
id = "icon",
@@ -64,36 +63,153 @@ return function(screen, programs)
widget = wibox.container.margin
}
for _, c in ipairs(client.get()) do
if string.lower(c.class):match(Get_gicon_path(gicon) or "") and c == client.focus then
dock_element.background.bg = Theme_config.dock.element_focused_bg
end
end
Hover_signal(dock_element.background, Theme_config.dock.element_focused_bg .. "dd")
dock_element:connect_signal(
"button::press",
function(_, _, _, button)
if button == 1 then
awful.spawn(Gio.DesktopAppInfo.get_string(desktop_app_info, "Exec"):gsub("%%F", ""):gsub("%%u", ""):gsub("%%U"
, ""):gsub("%%f", ""):gsub("%%i", ""):gsub("%%c"
, ""):gsub("%%k", ""))
local DAI = Gio.DesktopAppInfo.new_from_filename(program.desktop_file)
local action_entries = {}
for _, action in ipairs(program.actions) do
table.insert(action_entries, {
name = Gio.DesktopAppInfo.get_action_name(DAI, action) or "",
icon = action.icon or icondir .. "entry.svg",
callback = function()
Gio.DesktopAppInfo.launch_action(DAI, action)
end
})
end
table.insert(action_entries, {
name = "Remove from Dock",
icon = icondir .. "entry.svg",
callback = function()
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
return
end
local dock = json:decode(data:read("a"))
data:close()
for i, v in ipairs(dock) do
if v.desktop_file == program.desktop_file then
if type(dock) == "table" then
table.remove(dock, i)
end
break
end
end
data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "w")
if not data then
return
end
data:write(json:encode(dock))
data:close()
awesome.emit_signal("dock::changed")
end
})
local context_menu = cm({
entries = action_entries
})
dock_element:buttons(gears.table.join(
awful.button({
modifiers = {},
button = 1,
on_release = function()
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(program.exec, nil, 0))
end
}),
awful.button({
modifiers = {},
button = 3,
on_release = function()
if not context_menu then
return
end
-- add offset so mouse is above widget, this is so the mouse::leave event triggers always
context_menu.x = mouse.coords().x - 10
context_menu.y = mouse.coords().y + 10 - context_menu.height
context_menu.visible = not context_menu.visible
cm_open = context_menu.visible
end
})
))
awesome.connect_signal(
"context_menu::hide",
function()
cm_open = false
awesome.emit_signal("dock::check_for_dock_hide")
end
)
awful.tooltip {
objects = { dock_element },
text = Gio.DesktopAppInfo.get_string(desktop_app_info, "Name"),
text = program.name,
mode = "outside",
preferred_alignments = "middle",
margins = dpi(10)
}
dock_element_ammount = dock_element_ammount + 1
return dock_element
end
--- Indicators under the elements to indicate various open states
local function create_incicator_widget()
local container = { layout = wibox.layout.flex.horizontal }
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
return
end
local prog = json:decode(data:read("a"))
for _, pr in ipairs(prog) do
local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) }
local col = Theme_config.dock.indicator_bg
for _, c in ipairs(client.get()) do
local icon_name = pr.icon
if icon_name:match(string.lower(c.class or c.name)) or c.class:match(string.lower(icon_name)) or
c.name:match(string.lower(icon_name)) then
if c == client.focus then
col = Theme_config.dock.indicator_focused_bg
elseif c.urgent then
col = Theme_config.dock.indicator_urgent_bg
elseif c.maximized then
col = Theme_config.dock.indicator_maximized_bg
elseif c.minimized then
col = Theme_config.dock.indicator_minimized_bg
elseif c.fullscreen then
col = Theme_config.dock.indicator_fullscreen_bg
else
col = Theme_config.dock.indicator_bg
end
table.insert(indicators, wibox.widget {
widget = wibox.container.background,
shape = gears.shape.rounded_rect,
forced_height = dpi(3),
bg = col,
forced_width = dpi(5),
})
end
end
table.insert(container, wibox.widget {
indicators,
forced_height = dpi(5),
forced_width = dpi(User_config.dock_icon_size),
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
})
end
return wibox.widget {
container,
bottom = dpi(5),
widget = wibox.container.margin,
}
end
--- The container bar where the elements/program widgets sit in
local dock = awful.popup {
widget = wibox.container.background,
@@ -122,27 +238,37 @@ return function(screen, programs)
placement = function(c) awful.placement.bottom(c) end,
}
--- List of all elements/program widgets
local dock_elements = { layout = wibox.layout.fixed.horizontal }
--- This function creates a list with all dock elements/program widgets
---@param pr table A list of .desktop files
---@return table string list of widgets
local function get_dock_elements(pr)
local dock_elements = { layout = wibox.layout.fixed.horizontal }
---@return table|nil string list of widgets
local function get_dock_elements()
dock_element_ammount = 0
dock_elements = { layout = wibox.layout.fixed.horizontal }
for i, p in ipairs(pr) do
dock_elements[i] = create_dock_element(Get_desktop_values(p), User_config.dock_icon_size)
local data = io.open("/home/crylia/.config/awesome/src/config/dock.json", "r")
if not data then
return
end
return dock_elements
local dock_data = json:decode(data:read("a"))
for _, program in ipairs(dock_data) do
table.insert(dock_elements, create_dock_element(program, User_config.dock_icon_size))
end
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
end
--- List of all elements/program widgets
local dock_elements = get_dock_elements(programs)
get_dock_elements()
--- Function to get an empty list with the same ammount as dock_element
local function get_fake_elements(amount)
local function get_fake_elements()
local fake_elements = { layout = wibox.layout.fixed.horizontal }
for i = 0, amount, 1 do
for i = 0, dock_element_ammount, 1 do
fake_elements[i] = wibox.widget {
bg = '00000000',
forced_width = User_config.dock_icon_size + dpi(20),
@@ -154,64 +280,8 @@ return function(screen, programs)
return fake_elements
end
--- Indicators under the elements to indicate various open states
local function create_incicator_widget(prog)
local container = { layout = wibox.layout.flex.horizontal }
local clients = client.get()
for index, pr in ipairs(prog) do
local desktop_app_info = Gio.DesktopAppInfo.new_from_filename(Get_desktop_values(pr))
if desktop_app_info then
local gicon = Gio.Icon.new_for_string(Gio.DesktopAppInfo.get_string(desktop_app_info, "Icon"))
if gicon then
local indicators = { layout = wibox.layout.flex.horizontal, spacing = dpi(5) }
local col = Theme_config.dock.indicator_bg
for i, c in ipairs(clients) do
local icon_name = Get_gicon_path(gicon) or ""
if icon_name:match(string.lower(c.class or c.name)) or c.class:match(string.lower(icon_name)) or
c.name:match(string.lower(icon_name)) then
if c == client.focus then
col = Theme_config.dock.indicator_focused_bg
elseif c.urgent then
col = Theme_config.dock.indicator_urgent_bg
elseif c.maximized then
col = Theme_config.dock.indicator_maximized_bg
elseif c.minimized then
col = Theme_config.dock.indicator_minimized_bg
elseif c.fullscreen then
col = Theme_config.dock.indicator_fullscreen_bg
else
col = Theme_config.dock.indicator_bg
end
indicators[i] = wibox.widget {
widget = wibox.container.background,
shape = gears.shape.rounded_rect,
forced_height = dpi(3),
bg = col,
forced_width = dpi(5),
}
end
end
container[index] = wibox.widget {
indicators,
forced_height = dpi(5),
forced_width = dpi(User_config.dock_icon_size),
left = dpi(5),
right = dpi(5),
widget = wibox.container.margin,
}
end
end
end
return wibox.widget {
container,
bottom = dpi(5),
widget = wibox.container.margin,
}
end
fakedock:setup {
get_fake_elements(#programs),
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
@@ -302,7 +372,12 @@ return function(screen, programs)
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(programs),
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
@@ -314,7 +389,12 @@ return function(screen, programs)
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(programs),
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
@@ -326,7 +406,12 @@ return function(screen, programs)
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(programs),
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
@@ -338,9 +423,38 @@ return function(screen, programs)
check_for_dock_hide(screen)
dock:setup {
dock_elements,
create_incicator_widget(programs),
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
awesome.connect_signal(
"dock::changed",
function()
get_dock_elements()
dock:setup {
dock_elements,
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
fakedock:setup {
get_fake_elements(),
type = 'dock',
layout = wibox.layout.fixed.vertical
}
end
)
awesome.connect_signal(
"dock::check_for_dock_hide",
function()
dock_intelligent_hide:again()
end
)
@@ -354,13 +468,16 @@ return function(screen, programs)
dock:connect_signal(
"mouse::leave",
function()
if cm_open then
return
end
check_for_dock_hide(screen)
dock_intelligent_hide:again()
end
)
dock:setup {
dock_elements,
create_incicator_widget(programs),
create_incicator_widget(),
layout = wibox.layout.fixed.vertical
}
end

View File

@@ -67,5 +67,5 @@ return function(s)
end
end
end
require("src.modules.crylia_bar.dock")(s, User_config.dock_programs)
require("src.modules.crylia_bar.dock")(s)
end

View File

@@ -48,6 +48,7 @@ return function()
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