Big changes

This commit is contained in:
2022-04-14 00:35:06 +03:00
parent 5b218de55a
commit 9136f7ef3d
96 changed files with 1780 additions and 671 deletions

View File

@@ -1,8 +1,7 @@
# Configuration for Alacritty, the GPU enhanced terminal emulator.
background_opacity: 0.95
window:
opacity: 0.85
padding:
x: 8
y: 8

View File

@@ -1,18 +1,17 @@
local gears = require("gears")
local awful = require("awful")
local hotkeys_popup = require("awful.hotkeys_popup")
-- local hotkeys_popup = require("awful.hotkeys_popup")
require "bindings.mod"
require "config.apps"
require "config"
globalkeys =
gears.table.join(
awful.key(
{modkey},
"s",
hotkeys_popup.show_help,
{description = "show help", group = "awesome"}
),
-- awful.key(
-- {modkey},
-- "s",
-- hotkeys_popup.show_help,
-- {description = "show help", group = "awesome"}
-- ),
awful.key(
{modkey, "Control"},
"r",
@@ -297,6 +296,22 @@ globalkeys =
"Escape",
awful.tag.history.restore,
{description = "go back", group = "tag"}
),
awful.key(
{modkey},
".",
function()
awful.spawn("/usr/bin/emoji-picker")
end,
{description = "emoji picker", group = "launcher"}
),
awful.key(
{modkey, "Control"},
"w",
function()
toggle_window_buffers(awful.screen.focused())
end,
{description = "set workarea height to 200", group = "screen"}
)
)

View File

@@ -1,2 +1,4 @@
modkey = "Mod4"
require "bindings.global"
require "bindings.client"

View File

@@ -1 +0,0 @@
modkey = "Mod4"

View File

@@ -1,3 +0,0 @@
terminal = "alacritty"
editor = os.getenv("EDITOR") or "nano"
editor_cmd = terminal .. " -e " .. editor

View File

@@ -1 +1,3 @@
require "config.apps"
terminal = "alacritty"
editor = os.getenv("EDITOR") or "nano"
editor_cmd = terminal .. " -e " .. editor

View File

@@ -0,0 +1,63 @@
package = "bling"
version = "dev-1"
source = {
url = "git://github.com/BlingCorp/bling",
branch = "master",
}
description = {
summary = "Utilities for the AwesomeWM",
detailed = [[
This module extends the Awesome window manager with alternative layouts,
flash focus, tabbing, a simple tiling wallpaper generator, a declarative
wallpaper setter, window swallowing and a playerctl signal.
]],
homepage = "https://github.com/BlingCorp/bling",
license = "MIT",
}
dependencies = {
"lua >= 5.1",
}
build = {
type = "builtin",
modules = {
["bling"] = "init.lua",
["bling.helpers"] = "helpers/init.lua",
["bling.helpers.client"] = "helpers/client.lua",
["bling.helpers.color"] = "helpers/color.lua",
["bling.helpers.filesystem"] = "helpers/filesystem.lua",
["bling.helpers.shape"] = "helpers/shape.lua",
["bling.helpers.time"] = "helpers/time.lua",
["bling.layout"] = "layout/init.lua",
["bling.layout.centered"] = "layout/centered.lua",
["bling.layout.deck"] = "layout/deck.lua",
["bling.layout.equalarea"] = "layout/equalarea.lua",
["bling.layout.horizontal"] = "layout/horizontal.lua",
["bling.layout.mstab"] = "layout/mstab.lua",
["bling.layout.vertical"] = "layout/vertical.lua",
["bling.module"] = "module/init.lua",
["bling.module.flash_focus"] = "module/flash_focus.lua",
["bling.module.scratchpad"] = "module/scratchpad.lua",
["bling.module.tabbed"] = "module/tabbed.lua",
["bling.module.tiled_wallpaper"] = "module/tiled_wallpaper.lua",
["bling.module.wallpaper"] = "module/wallpaper.lua",
["bling.module.window_swallowing"] = "module/window_swallowing.lua",
["bling.signal"] = "signal/init.lua",
["bling.signal.playerctl"] = "signal/playerctl/init.lua",
["bling.signal.playerctl.playerctl_cli"] = "signal/playerctl/playerctl_cli.lua",
["bling.signal.playerctl.playerctl_lib"] = "signal/playerctl/playerctl_lib.lua",
["bling.widget"] = "widget/init.lua",
["bling.widget.tabbar.boxes"] = "widget/tabbar/boxes.lua",
["bling.widget.tabbar.default"] = "widget/tabbar/default.lua",
["bling.widget.tabbar.modern"] = "widget/tabbar/modern.lua",
["bling.widget.tabbed_misc"] = "widget/tabbed_misc/init.lua",
["bling.widget.tabbed_misc.custom_tasklist"] = "widget/tabbed_misc/custom_tasklist.lua",
["bling.widget.tabbed_misc.titlebar_indicator"] = "widget/tabbed_misc/titlebar_indicator.lua",
["bling.widget.tag_preview"] = "widget/tag_preview.lua",
["bling.widget.task_preview"] = "widget/task_preview.lua",
["bling.widget.window_switcher"] = "widget/window_switcher.lua",
},
}

View File

@@ -1,4 +1,6 @@
local Gio = require("lgi").Gio
local awful = require("awful")
local string = string
local _filesystem = {}
@@ -50,4 +52,11 @@ function _filesystem.list_directory_files(path, exts, recursive)
return files
end
function _filesystem.save_image_async_curl(url, filepath, callback)
awful.spawn.with_line_callback(string.format("curl -L -s %s -o %s", url, filepath),
{
exit=callback
})
end
return _filesystem

View File

@@ -1,7 +1,11 @@
--[[
Bling
Layouts, widgets and utilities for Awesome WM
--]]
return {
layout = require(... .. ".layout"),
--module = require(... .. ".module"),
--helpers = require(... .. ".helpers"),
--signal = require(... .. ".signal"),
--widget = require(... .. ".widget"),
module = require(... .. ".module"),
helpers = require(... .. ".helpers"),
signal = require(... .. ".signal"),
widget = require(... .. ".widget"),
}

View File

@@ -8,37 +8,27 @@ mylayout.name = "centered"
function mylayout.arrange(p)
local area = p.workarea
local t = p.tag or screen[p.screen].selected_tag
local mwfact = t.master_width_factor
local nmaster = math.min(t.master_count, #p.clients)
local nslaves = #p.clients - nmaster
local master_area_width = area.width * mwfact
local slave_area_width = area.width - master_area_width
local master_area_x = area.x + 0.5 * slave_area_width
local master_area_width = area.width * t.master_width_factor
if t.master_count == 0 then master_area_width = 0 end
local slave_width = 0.5 * (area.width - master_area_width)
local master_area_x = area.x + slave_width
local number_of_left_sided_slaves = math.floor(nslaves / 2)
local number_of_right_sided_slaves = nslaves - number_of_left_sided_slaves
local left_iterator = 0
local right_iterator = 0
-- Special case: no maters -> rrelapse into awesomes fair layout
if t.master_count == 0 then
awful.layout.suit.fair.arrange(p)
return
end
-- Special case: one slave -> relapse into awesomes masterstack tile layout
if nslaves == 1 then
awful.layout.suit.tile.right.arrange(p)
return
end
-- Special case: no slaves -> fullscreen master area
if nslaves < 1 then
master_area_width = area.width
-- Special case: few slaves -> make masters take more space - unless requested otherwise!
if nslaves < 2 and t.master_fill_policy ~= "master_width_factor" then
master_area_x = area.x
if nslaves == 1 then
slave_width = area.width - master_area_width
else
master_area_width = area.width
end
end
-- iterate through masters
for idx = 1, nmaster do
local c = p.clients[idx]
@@ -52,8 +42,14 @@ function mylayout.arrange(p)
p.geometries[c] = g
end
-- iterate through slaves
for idx = 1, nslaves do -- idx=nmaster+1,#p.clients do
local number_of_left_sided_slaves = math.floor(nslaves / 2)
local number_of_right_sided_slaves = nslaves - number_of_left_sided_slaves
local left_iterator = 0
local right_iterator = 0
for idx = 1, nslaves do
local c = p.clients[idx + nmaster]
local g
if idx % 2 == 0 then
@@ -62,17 +58,17 @@ function mylayout.arrange(p)
y = area.y
+ left_iterator
* (area.height / number_of_left_sided_slaves),
width = slave_area_width / 2,
width = slave_width,
height = area.height / number_of_left_sided_slaves,
}
left_iterator = left_iterator + 1
else
g = {
x = area.x + master_area_width + slave_area_width / 2,
x = master_area_x + master_area_width,
y = area.y
+ right_iterator
* (area.height / number_of_right_sided_slaves),
width = slave_area_width / 2,
width = slave_width,
height = area.height / number_of_right_sided_slaves,
}
right_iterator = right_iterator + 1

View File

@@ -20,7 +20,7 @@ end
local function get_icon(icon_raw)
if icon_raw ~= nil then
return gears.color.recolor_image(icon_raw, "#e6e6e6")
return gears.color.recolor_image(icon_raw, beautiful.fg_focus)
else
return nil
end

View File

@@ -5,7 +5,7 @@ local op = beautiful.flash_focus_start_opacity or 0.6
local stp = beautiful.flash_focus_step or 0.01
local flashfocus = function(c)
if c then
if c and #c.screen.clients > 1 then
c.opacity = op
local q = op
local g = gears.timer({

View File

@@ -293,10 +293,10 @@ function Scratchpad:turn_on()
animate_turn_on(self, anim_y, "y")
end
self:emit_signal("inital_apply", c1)
self.client.disconnect_signal("manage", inital_apply)
client.disconnect_signal("manage", inital_apply)
end
end
self.client.connect_signal("manage", inital_apply)
client.connect_signal("manage", inital_apply)
end
end
end

View File

@@ -53,36 +53,37 @@ function apply(wallpaper_object, args)
args.offset = args.offset or { x = 0, y = 0 }
args.scale = args.scale or 1
local positions = {
["centered"] = function()
["centered"] = function(s)
gears.wallpaper.centered(
wallpaper_object,
args.screen,
s,
args.background,
args.scale
)
end,
["tiled"] = function()
gears.wallpaper.tiled(wallpaper_object, args.screen, args.offset)
["tiled"] = function(s)
gears.wallpaper.tiled(wallpaper_object, s, args.offset)
end,
["maximized"] = function()
["maximized"] = function(s)
gears.wallpaper.maximized(
wallpaper_object,
args.screen,
s,
args.ignore_aspect,
args.offset
)
end,
["fit"] = function()
gears.wallpaper.fit(wallpaper_object, args.screen, args.background)
["fit"] = function(s)
gears.wallpaper.fit(wallpaper_object, s, args.background)
end,
}
local call_func = nil
if
type(wallpaper_object) == "string"
and gears.filesystem.file_readable(wallpaper_object)
then
-- path of an image file, we use a position function
local p = args.position or "centered"
positions[p]()
call_func = positions[p]
elseif type(wallpaper_object) == "function" then
-- function
wallpaper_object(args)
@@ -91,10 +92,13 @@ function apply(wallpaper_object, args)
and args.position
then
-- if the user sets a position function, wallpaper_object should be a cairo surface
positions[args.position]()
call_func = positions[args.position]
else
gears.wallpaper.set(wallpaper_object)
end
if call_func then
call_func(args.screen)
end
end
--- Converts `args.wallpaper` to a list of `wallpaper_objects` readable by `apply` function).
@@ -154,7 +158,15 @@ local simple_index = 0
function setters.simple(args)
local wallpapers = prepare_list(args)
simple_index = (simple_index % #wallpapers) + 1
apply(wallpapers[simple_index], args)
if type(args.screen) == 'table' then
for _,v in ipairs(args.screen) do
args.screen = v
apply(wallpapers[simple_index], args)
args.screen = nil
end
else
apply(wallpapers[simple_index], args)
end
end
--- Set a random wallpaper from a list.
@@ -164,7 +176,15 @@ end
-- @see prepare_list
function setters.random(args)
local wallpapers = prepare_list(args)
apply(wallpapers[math.random(#wallpapers)], args)
if type(args.screen) == 'table' then
for _,v in ipairs(args.screen) do
args.screen = v
apply(wallpapers[math.random(#wallpapers)], args)
args.screen = nil
end
else
apply(wallpapers[math.random(#wallpapers)], args)
end
end
local simple_schedule_object = nil
@@ -310,7 +330,10 @@ function setup(args)
config.set_function = config.set_function
or (config.wallpaper and setters.simple or setters.awesome_wallpaper)
local function set_wallpaper(s)
config.screen = s or config.screen
if type(config.screen) ~= 'table' then
if config.screen and s and config.screen ~= s then return end
config.screen = s or config.screen
end
config.set_function(config)
end
@@ -324,7 +347,7 @@ function setup(args)
end,
})
end
if awesome.version == "v4.3" then
if awesome.version == "v4.3" or awesome.version == "4.3" then
awful.screen.connect_for_each_screen(set_wallpaper)
else
screen.connect_signal("request::wallpaper", set_wallpaper)

View File

@@ -11,53 +11,93 @@ local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local window_swallowing_activated = false
-- you might want to add or remove applications here
local dont_swallow_classname_list = beautiful.dont_swallow_classname_list
local parent_filter_list = beautiful.parent_filter_list
or beautiful.dont_swallow_classname_list
or { "firefox", "Gimp", "Google-chrome" }
local activate_dont_swallow_filter = beautiful.dont_swallow_filter_activated
or true
local child_filter_list = beautiful.child_filter_list
or beautiful.dont_swallow_classname_list or { }
-- checks if client classname matches with any entry of the dont-swallow-list
local function check_if_swallow(c)
if not activate_dont_swallow_filter then
return true
end
for _, classname in ipairs(dont_swallow_classname_list) do
if classname == c.class then
return false
-- for boolean values the or chain way to set the values breaks with 2 vars
-- and always defaults to true so i had to do this to se the right value...
local swallowing_filter = true
local filter_vars = { beautiful.swallowing_filter, beautiful.dont_swallow_filter_activated }
for _, var in pairs(filter_vars) do
swallowing_filter = var
end
-- check if element exist in table
-- returns true if it is
local function is_in_table(element, table)
local res = false
for _, value in pairs(table) do
if element:match(value) then
res = true
break
end
end
return true
return res
end
-- if the swallowing filter is active checks the child and parent classes
-- against their filters
local function check_swallow(parent, child)
local res = true
if swallowing_filter then
local prnt = not is_in_table(parent, parent_filter_list)
local chld = not is_in_table(child, child_filter_list)
res = ( prnt and chld )
end
return res
end
-- async function to get the parent's pid
-- recieves a child process pid and a callback function
-- parent_pid in format "init(1)---ancestorA(pidA)---ancestorB(pidB)...---process(pid)"
function get_parent_pid(child_ppid, callback)
local ppid_cmd = string.format("pstree -A -p -s %s", child_ppid)
awful.spawn.easy_async(ppid_cmd, function(stdout, stderr, reason, exit_code)
-- primitive error checking
if stderr and stderr ~= "" then
callback(stderr)
return
end
local ppid = stdout
callback(nil, ppid)
end)
end
-- the function that will be connected to / disconnected from the spawn client signal
local function manage_clientspawn(c)
-- get the last focused window to check if it is a parent window
local parent_client = awful.client.focus.history.get(c.screen, 1)
if not parent_client then
return
elseif parent_client.type == "dialog" or parent_client.type == "splash" then
return
end
-- io.popen is normally discouraged. Should probably be changed
local handle = io.popen(
[[pstree -T -p -a -s ]]
.. tostring(c.pid)
.. [[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']]
)
local parent_pid = handle:read("*a")
handle:close()
get_parent_pid(c.pid, function(err, ppid)
if err then
return
end
parent_pid = ppid
if
(tostring(parent_pid) == tostring(parent_client.pid))
and check_if_swallow(c)
-- will search for "(parent_client.pid)" inside the parent_pid string
( tostring(parent_pid):find("("..tostring(parent_client.pid)..")") )
and check_swallow(parent_client.class, c.class)
then
c:connect_signal("unmanage", function()
helpers.client.turn_on(parent_client)
helpers.client.sync(parent_client, c)
if parent_client then
helpers.client.turn_on(parent_client)
helpers.client.sync(parent_client, c)
end
end)
helpers.client.sync(c, parent_client)
helpers.client.turn_off(parent_client)
end
end)
end
-- without the following functions that module would be autoloaded by require("bling")

View File

@@ -1 +1,3 @@
return { playerctl = require(... .. ".playerctl") }
return {
playerctl = require(... .. ".playerctl"),
}

View File

@@ -1,4 +1,7 @@
local awful = require("awful")
local gtimer = require("gears.timer")
local beautiful = require("beautiful")
local naughty = require("naughty")
-- Use CLI backend as default as it is supported on most if not all systems
local backend_config = beautiful.playerctl_backend or "playerctl_cli"
@@ -7,13 +10,37 @@ local backends = {
playerctl_lib = require(... .. ".playerctl_lib"),
}
local backend = nil
local function enable_wrapper(args)
local open = naughty.action { name = "Open" }
open:connect_signal("invoked", function()
awful.spawn("xdg-open https://blingcorp.github.io/bling/#/signals/pctl")
end)
gtimer.delayed_call(function()
naughty.notify({
title = "Bling Error",
text = "Global signals are deprecated! Please take a look at the playerctl documentation.",
app_name = "Bling Error",
app_icon = "system-error",
actions = { open }
})
end)
backend_config = (args and args.backend) or backend_config
backends[backend_config].enable(args)
backend = backends[backend_config](args)
return backend
end
local function disable_wrapper()
backends[backend_config].disable()
backend:disable()
end
return { enable = enable_wrapper, disable = disable_wrapper }
return {
lib = backends.playerctl_lib,
cli = backends.playerctl_cli,
enable = enable_wrapper,
disable = disable_wrapper
}

View File

@@ -1,151 +1,348 @@
-- Playerctl signals
--
-- Provides:
-- bling::playerctl::status
-- playing (boolean)
-- bling::playerctl::title_artist_album
-- metadata
-- title (string)
-- artist (string)
-- artist (string)
-- album_path (string)
-- bling::playerctl::position
-- album (string)
-- player_name (string)
-- position
-- interval_sec (number)
-- length_sec (number)
-- bling::playerctl::no_players
--
-- playback_status
-- playing (boolean)
-- volume
-- volume (number)
-- loop_status
-- loop_status (string)
-- shuffle
-- shuffle (bool)
-- no_players
-- (No parameters)
local awful = require("awful")
local gobject = require("gears.object")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local gstring = require("gears.string")
local beautiful = require("beautiful")
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local setmetatable = setmetatable
local tonumber = tonumber
local ipairs = ipairs
local type = type
local capi = { awesome = awesome }
local interval = beautiful.playerctl_position_update_interval or 1
local playerctl = { mt = {} }
local function emit_player_status()
local status_cmd = "playerctl status -F"
-- Follow status
awful.spawn.easy_async({
"pkill",
"--full",
"--uid",
os.getenv("USER"),
"^playerctl status",
}, function()
awful.spawn.with_line_callback(status_cmd, {
stdout = function(line)
local playing = false
if line:find("Playing") then
playing = true
else
playing = false
end
awesome.emit_signal("bling::playerctl::status", playing)
end,
})
collectgarbage("collect")
end)
function playerctl:disable()
self._private.metadata_timer:stop()
self._private.metadata_timer = nil
awful.spawn.with_shell("killall playerctl")
end
local function emit_player_info()
local art_script = [[
sh -c '
function playerctl:pause(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " pause")
else
awful.spawn.with_shell(self._private.cmd .. "pause")
end
end
tmp_dir="$XDG_CACHE_HOME/awesome/"
function playerctl:play(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " play")
else
awful.spawn.with_shell(self._private.cmd .. "play")
end
end
if [ -z ${XDG_CACHE_HOME} ]; then
tmp_dir="$HOME/.cache/awesome/"
fi
function playerctl:stop(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " stop")
else
awful.spawn.with_shell(self._private.cmd .. "stop")
end
end
tmp_cover_path=${tmp_dir}"cover.png"
function playerctl:play_pause(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " play-pause")
else
awful.spawn.with_shell(self._private.cmd .. "play-pause")
end
end
if [ ! -d $tmp_dir ]; then
mkdir -p $tmp_dir
fi
function playerctl:previous(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " previous")
else
awful.spawn.with_shell(self._private.cmd .. "previous")
end
end
link="$(playerctl metadata mpris:artUrl)"
function playerctl:next(player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " next")
else
awful.spawn.with_shell(self._private.cmd .. "next")
end
end
curl -s "$link" --output $tmp_cover_path
function playerctl:set_loop_status(loop_status, player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " loop " .. loop_status)
else
awful.spawn.with_shell(self._private.cmd .. "loop " .. loop_status)
end
end
echo "$tmp_cover_path"
']]
function playerctl:cycle_loop_status(player)
local function set_loop_status(loop_status)
if loop_status == "None" then
self:set_loop_status("Track")
elseif loop_status == "Track" then
self:set_loop_status("Playlist")
elseif loop_status == "Playlist" then
self:set_loop_status("None")
end
end
-- Command that lists artist and title in a format to find and follow
local song_follow_cmd =
"playerctl metadata --format 'artist_{{artist}}title_{{title}}' -F"
if player ~= nil then
awful.spawn.easy_async_with_shell("playerctl --player=" .. player .. " loop", function(stdout)
set_loop_status(stdout)
end)
else
set_loop_status(self._private.loop_status)
end
end
-- Progress Cmds
local prog_cmd = "playerctl position"
local length_cmd = "playerctl metadata mpris:length"
function playerctl:set_position(position, player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " position " .. position)
else
awful.spawn.with_shell(self._private.cmd .. "position " .. position)
end
end
awful.widget.watch(prog_cmd, interval, function(_, interval)
function playerctl:set_shuffle(shuffle, player)
shuffle = shuffle and "on" or "off"
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " shuffle " .. shuffle)
else
awful.spawn.with_shell(self._private.cmd .. "shuffle " .. shuffle)
end
end
function playerctl:cycle_shuffle(player)
if player ~= nil then
awful.spawn.easy_async_with_shell("playerctl --player=" .. player .. " shuffle", function(stdout)
local shuffle = stdout == "on" and true or false
self:set_shuffle(not self._private.shuffle)
end)
else
self:set_shuffle(not self._private.shuffle)
end
end
function playerctl:set_volume(volume, player)
if player ~= nil then
awful.spawn.with_shell("playerctl --player=" .. player .. " volume " .. volume)
else
awful.spawn.with_shell(self._private.cmd .. "volume " .. volume)
end
end
local function emit_player_metadata(self)
local metadata_cmd = self._private.cmd .. "metadata --format 'title_{{title}}artist_{{artist}}art_url_{{mpris:artUrl}}player_name_{{playerName}}album_{{album}}' -F"
awful.spawn.with_line_callback(metadata_cmd, {
stdout = function(line)
local title = gstring.xml_escape(line:match('title_(.*)artist_')) or ""
local artist = gstring.xml_escape(line:match('artist_(.*)art_url_')) or ""
local art_url = line:match('art_url_(.*)player_name_') or ""
local player_name = line:match('player_name_(.*)album_') or ""
local album = gstring.xml_escape(line:match('album_(.*)')) or ""
art_url = art_url:gsub('%\n', '')
if player_name == "spotify" then
art_url = art_url:gsub("open.spotify.com", "i.scdn.co")
end
if self._private.metadata_timer
and self._private.metadata_timer.started
then
self._private.metadata_timer:stop()
end
self._private.metadata_timer = gtimer {
timeout = self.debounce_delay,
autostart = true,
single_shot = true,
callback = function()
if title and title ~= "" then
if art_url ~= "" then
local art_path = os.tmpname()
helpers.filesystem.save_image_async_curl(art_url, art_path, function()
self:emit_signal("metadata", title, artist, art_path, album, player_name)
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, art_path)
end)
else
self:emit_signal("metadata", title, artist, "", album, player_name)
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, "")
end
else
self:emit_signal("no_players")
capi.awesome.emit_signal("bling::playerctl::no_players")
end
end
}
collectgarbage("collect")
end,
})
end
local function emit_player_position(self)
local position_cmd = self._private.cmd .. "position"
local length_cmd = self._private.cmd .. "metadata mpris:length"
awful.widget.watch(position_cmd, self.interval, function(_, interval)
awful.spawn.easy_async_with_shell(length_cmd, function(length)
local length_sec = tonumber(length) -- in microseconds
local interval_sec = tonumber(interval) -- in seconds
if length_sec and interval_sec then
if interval_sec >= 0 and length_sec > 0 then
awesome.emit_signal(
"bling::playerctl::position",
interval_sec,
length_sec / 1000000
)
self:emit_signal("position", interval_sec, length_sec / 1000000)
capi.awesome.emit_signal("bling::playerctl::position", interval_sec, length_sec / 1000000)
end
end
end)
collectgarbage("collect")
end)
-- Follow title
awful.spawn.easy_async({
"pkill",
"--full",
"--uid",
os.getenv("USER"),
"^playerctl metadata",
}, function()
awful.spawn.with_line_callback(song_follow_cmd, {
stdout = function(line)
local album_path = ""
awful.spawn.easy_async_with_shell(art_script, function(out)
-- Get album path
album_path = out:gsub("%\n", "")
-- Get title and artist
local artist = line:match("artist_(.*)title_")
local title = line:match("title_(.*)")
-- If the title is nil or empty then the players stopped
if title and title ~= "" then
awesome.emit_signal(
"bling::playerctl::title_artist_album",
title,
artist,
album_path
)
else
awesome.emit_signal("bling::playerctl::no_players")
end
end)
collectgarbage("collect")
end,
})
collectgarbage("collect")
end)
end
-- Emit info
-- emit_player_status()
-- emit_player_info()
local function emit_player_playback_status(self)
local status_cmd = self._private.cmd .. "status -F"
local enable = function(args)
interval = (args and args.interval) or interval
emit_player_status()
emit_player_info()
awful.spawn.with_line_callback(status_cmd, {
stdout = function(line)
if line:find("Playing") then
self:emit_signal("playback_status", true)
capi.awesome.emit_signal("bling::playerctl::status", true)
else
self:emit_signal("playback_status", false)
capi.awesome.emit_signal("bling::playerctl::status", false)
end
end,
})
end
local disable = function()
awful.spawn.with_shell(
"pkill --full --uid " .. os.getenv("USER") .. " '^playerctl status -F'"
)
local function emit_player_volume(self)
local volume_cmd = self._private.cmd .. "volume -F"
awful.spawn.with_shell(
"pkill --full --uid "
.. os.getenv("USER")
.. " '^playerctl metadata --format'"
)
awful.spawn.with_line_callback(volume_cmd, {
stdout = function(line)
self:emit_signal("volume", tonumber(line))
end,
})
end
return { enable = enable, disable = disable }
local function emit_player_loop_status(self)
local loop_status_cmd = self._private.cmd .. "loop -F"
awful.spawn.with_line_callback(loop_status_cmd, {
stdout = function(line)
self._private.loop_status = line
self:emit_signal("loop_status", line:lower())
end,
})
end
local function emit_player_shuffle(self)
local shuffle_cmd = self._private.cmd .. "shuffle -F"
awful.spawn.with_line_callback(shuffle_cmd, {
stdout = function(line)
if line:find("On") then
self._private.shuffle = true
self:emit_signal("shuffle", true)
else
self._private.shuffle = false
self:emit_signal("shuffle", false)
end
end,
})
end
local function parse_args(self, args)
if args.player then
self._private.cmd = self._private.cmd .. "--player="
if type(args.player) == "string" then
self._private.cmd = self._private.cmd .. args.player .. " "
elseif type(args.player) == "table" then
for index, player in ipairs(args.player) do
self._private.cmd = self._private.cmd .. player
if index < #args.player then
self._private.cmd = self._private.cmd .. ","
else
self._private.cmd = self._private.cmd .. " "
end
end
end
end
if args.ignore then
self._private.cmd = self._private.cmd .. "--ignore-player="
if type(args.ignore) == "string" then
self._private.cmd = self._private.cmd .. args.ignore .. " "
elseif type(args.ignore) == "table" then
for index, player in ipairs(args.ignore) do
self._private.cmd = self._private.cmd .. player
if index < #args.ignore then
self._private.cmd = self._private.cmd .. ","
else
self._private.cmd = self._private.cmd .. " "
end
end
end
end
end
local function new(args)
args = args or {}
local ret = gobject{}
gtable.crush(ret, playerctl, true)
ret.interval = args.interval or beautiful.playerctl_position_update_interval or 1
ret.debounce_delay = args.debounce_delay or beautiful.playerctl_debounce_delay or 0.35
ret._private = {}
ret._private.metadata_timer = nil
ret._private.cmd = "playerctl "
parse_args(ret, args)
emit_player_metadata(ret)
emit_player_position(ret)
emit_player_playback_status(ret)
emit_player_volume(ret)
emit_player_loop_status(ret)
emit_player_shuffle(ret)
return ret
end
function playerctl.mt:__call(...)
return new(...)
end
-- On startup instead of on playerctl object init to make it
-- possible to have more than one of these running
awful.spawn.with_shell("killall playerctl")
return setmetatable(playerctl, playerctl.mt)

View File

@@ -1,88 +1,209 @@
-- Playerctl signals
--
-- Provides:
-- bling::playerctl::status
-- playing (boolean)
-- player_name (string)
-- bling::playerctl::title_artist_album
-- metadata
-- title (string)
-- artist (string)
-- album_path (string)
-- album (string)
-- new (bool)
-- player_name (string)
-- bling::playerctl::position
-- position
-- interval_sec (number)
-- length_sec (number)
-- player_name (string)
-- bling::playerctl::no_players
-- playback_status
-- playing (boolean)
-- player_name (string)
-- seeked
-- position (number)
-- player_name (string)
-- volume
-- volume (number)
-- player_name (string)
-- loop_status
-- loop_status (string)
-- player_name (string)
-- shuffle
-- shuffle (boolean)
-- player_name (string)
-- exit
-- player_name (string)
-- no_players
-- (No parameters)
local gears = require("gears")
local awful = require("awful")
local gobject = require("gears.object")
local gtable = require("gears.table")
local gtimer = require("gears.timer")
local gstring = require("gears.string")
local beautiful = require("beautiful")
local Playerctl = nil
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
local setmetatable = setmetatable
local ipairs = ipairs
local pairs = pairs
local type = type
local capi = { awesome = awesome }
local manager = nil
local metadata_timer = nil
local position_timer = nil
local playerctl = { mt = {} }
local ignore = {}
local priority = {}
local update_on_activity = true
local interval = 1
function playerctl:disable()
-- Restore default settings
self.ignore = {}
self.priority = {}
self.update_on_activity = true
self.interval = 1
self.debounce_delay = 0.35
-- Track position callback
local last_position = -1
local last_length = -1
local function position_cb()
local player = manager.players[1]
-- Reset timers
self._private.manager = nil
self._private.metadata_timer:stop()
self._private.metadata_timer = nil
self._private.position_timer:stop()
self._private.position_timer = nil
-- Reset default values
self._private.last_position = -1
self._private.last_length = -1
self._private.last_player = nil
self._private.last_title = ""
self._private.last_artist = ""
self._private.last_artUrl = ""
end
function playerctl:pause(player)
player = player or self._private.manager.players[1]
if player then
local position = player:get_position() / 1000000
local length = (player.metadata.value["mpris:length"] or 0) / 1000000
if position ~= last_position or length ~= last_length then
awesome.emit_signal(
"bling::playerctl::position",
position,
length,
player.player_name
)
last_position = position
last_length = length
player:pause()
end
end
function playerctl:play(player)
player = player or self._private.manager.players[1]
if player then
player:play()
end
end
function playerctl:stop(player)
player = player or self._private.manager.players[1]
if player then
player:stop()
end
end
function playerctl:play_pause(player)
player = player or self._private.manager.players[1]
if player then
player:play_pause()
end
end
function playerctl:previous(player)
player = player or self._private.manager.players[1]
if player then
player:previous()
end
end
function playerctl:next(player)
player = player or self._private.manager.players[1]
if player then
player:next()
end
end
function playerctl:set_loop_status(loop_status, player)
player = player or self._private.manager.players[1]
if player then
player:set_loop_status(loop_status)
end
end
function playerctl:cycle_loop_status(player)
player = player or self._private.manager.players[1]
if player then
if player.loop_status == "NONE" then
player:set_loop_status("TRACK")
elseif player.loop_status == "TRACK" then
player:set_loop_status("PLAYLIST")
elseif player.loop_status == "PLAYLIST" then
player:set_loop_status("NONE")
end
end
end
local function get_album_art(url)
return awful.util.shell
.. [[ -c '
tmp_dir="$XDG_CACHE_HOME/awesome/"
if [ -z "$XDG_CACHE_HOME" ]; then
tmp_dir="$HOME/.cache/awesome/"
fi
tmp_cover_path="${tmp_dir}cover.png"
if [ ! -d "$tmp_dir" ]; then
mkdir -p $tmp_dir
fi
curl -s ']]
.. url
.. [[' --output $tmp_cover_path
echo "$tmp_cover_path"
']]
function playerctl:set_position(position, player)
player = player or self._private.manager.players[1]
if player then
player:set_position(position * 1000000)
end
end
-- Metadata callback for title, artist, and album art
local last_player = nil
local last_title = ""
local last_artist = ""
local last_artUrl = ""
local function metadata_cb(player, metadata)
if update_on_activity then
manager:move_player_to_top(player)
function playerctl:set_shuffle(shuffle, player)
player = player or self._private.manager.players[1]
if player then
player:set_shuffle(shuffle)
end
end
function playerctl:cycle_shuffle(player)
player = player or self._private.manager.players[1]
if player then
player:set_shuffle(not player.shuffle)
end
end
function playerctl:set_volume(volume, player)
player = player or self._private.manager.players[1]
if player then
player:set_volume(volume)
end
end
function playerctl:get_manager()
return self._private.manager
end
function playerctl:get_active_player()
return self._private.manager.players[1]
end
function playerctl:get_player_of_name(name)
for _, player in ipairs(self._private.manager.players[1]) do
if player.name == name then
return player
end
end
return nil
end
local function emit_metadata_signal(self, title, artist, artUrl, album, new, player_name)
title = gstring.xml_escape(title)
artist = gstring.xml_escape(artist)
album = gstring.xml_escape(album)
-- Spotify client doesn't report its art URL's correctly...
if player_name == "spotify" then
artUrl = artUrl:gsub("open.spotify.com", "i.scdn.co")
end
if artUrl ~= "" then
local art_path = os.tmpname()
helpers.filesystem.save_image_async_curl(artUrl, art_path, function()
self:emit_signal("metadata", title, artist, art_path, album, new, player_name)
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, art_path, player_name)
end)
else
capi.awesome.emit_signal("bling::playerctl::title_artist_album", title, artist, "", player_name)
self:emit_signal("metadata", title, artist, "", album, new, player_name)
end
end
local function metadata_cb(self, player, metadata)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
local data = metadata.value
@@ -93,101 +214,136 @@ local function metadata_cb(player, metadata)
artist = artist .. ", " .. data["xesam:artist"][i]
end
local artUrl = data["mpris:artUrl"] or ""
-- Spotify client doesn't report its art URL's correctly...
if player.player_name == "spotify" then
artUrl = artUrl:gsub("open.spotify.com", "i.scdn.co")
end
local album = data["xesam:album"] or ""
if player == self._private.manager.players[1] then
self._private.active_player = player
if player == manager.players[1] then
-- Callback can be called even though values we care about haven't
-- changed, so check to see if they have
if
player ~= last_player
or title ~= last_title
or artist ~= last_artist
or artUrl ~= last_artUrl
player ~= self._private.last_player
or title ~= self._private.last_title
or artist ~= self._private.last_artist
or artUrl ~= self._private.last_artUrl
then
if title == "" and artist == "" and artUrl == "" then
return
if (title == "" and artist == "" and artUrl == "") then return end
if self._private.metadata_timer ~= nil and self._private.metadata_timer.started then
self._private.metadata_timer:stop()
end
if metadata_timer ~= nil then
if metadata_timer.started then
metadata_timer:stop()
end
end
metadata_timer = gears.timer({
timeout = 0.3,
self._private.metadata_timer = gtimer {
timeout = self.debounce_delay,
autostart = true,
single_shot = true,
callback = function()
if artUrl ~= "" then
awful.spawn.with_line_callback(get_album_art(artUrl), {
stdout = function(line)
awesome.emit_signal(
"bling::playerctl::title_artist_album",
title,
artist,
line,
player.player_name
)
end,
})
else
awesome.emit_signal(
"bling::playerctl::title_artist_album",
title,
artist,
"",
player.player_name
)
end
end,
})
emit_metadata_signal(self, title, artist, artUrl, album, true, player.player_name)
end
}
-- Re-sync with position timer when track changes
position_timer:again()
last_player = player
last_title = title
last_artist = artist
last_artUrl = artUrl
self._private.position_timer:again()
self._private.last_player = player
self._private.last_title = title
self._private.last_artist = artist
self._private.last_artUrl = artUrl
end
end
end
-- Playback status callback
-- Reported as PLAYING, PAUSED, or STOPPED
local function playback_status_cb(player, status)
if update_on_activity then
manager:move_player_to_top(player)
local function position_cb(self)
local player = self._private.manager.players[1]
if player then
local position = player:get_position() / 1000000
local length = (player.metadata.value["mpris:length"] or 0) / 1000000
if position ~= self._private.last_position or length ~= self._private.last_length then
capi.awesome.emit_signal("bling::playerctl::position", position, length, player.player_name)
self:emit_signal("position", position, length, player.player_name)
self._private.last_position = position
self._private.last_length = length
end
end
end
local function playback_status_cb(self, player, status)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
if player == manager.players[1] then
if player == self._private.manager.players[1] then
self._private.active_player = player
-- Reported as PLAYING, PAUSED, or STOPPED
if status == "PLAYING" then
awesome.emit_signal(
"bling::playerctl::status",
true,
player.player_name
)
self:emit_signal("playback_status", true, player.player_name)
capi.awesome.emit_signal("bling::playerctl::status", true, player.player_name)
else
awesome.emit_signal(
"bling::playerctl::status",
false,
player.player_name
)
self:emit_signal("playback_status", false, player.player_name)
capi.awesome.emit_signal("bling::playerctl::status", false, player.player_name)
end
end
end
local function seeked_cb(self, player, position)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
if player == self._private.manager.players[1] then
self._private.active_player = player
self:emit_signal("seeked", position / 1000000, player.player_name)
end
end
local function volume_cb(self, player, volume)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
if player == self._private.manager.players[1] then
self._private.active_player = player
self:emit_signal("volume", volume, player.player_name)
end
end
local function loop_status_cb(self, player, loop_status)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
if player == self._private.manager.players[1] then
self._private.active_player = player
self:emit_signal("loop_status", loop_status:lower(), player.player_name)
end
end
local function shuffle_cb(self, player, shuffle)
if self.update_on_activity then
self._private.manager:move_player_to_top(player)
end
if player == self._private.manager.players[1] then
self._private.active_player = player
self:emit_signal("shuffle", shuffle, player.player_name)
end
end
local function exit_cb(self, player)
if player == self._private.manager.players[1] then
self:emit_signal("exit", player.player_name)
end
end
-- Determine if player should be managed
local function name_is_selected(name)
if ignore[name.name] then
local function name_is_selected(self, name)
if self.ignore[name.name] then
return false
end
if #priority > 0 then
for _, arg in pairs(priority) do
if #self.priority > 0 then
for _, arg in pairs(self.priority) do
if arg == name.name or arg == "%any" then
return true
end
@@ -199,23 +355,42 @@ local function name_is_selected(name)
end
-- Create new player and connect it to callbacks
local function init_player(name)
if name_is_selected(name) then
local player = Playerctl.Player.new_from_name(name)
manager:manage_player(player)
player.on_playback_status = playback_status_cb
player.on_metadata = metadata_cb
local function init_player(self, name)
if name_is_selected(self, name) then
local player = self._private.lgi_Playerctl.Player.new_from_name(name)
self._private.manager:manage_player(player)
player.on_metadata = function(player, metadata)
metadata_cb(self, player, metadata)
end
player.on_playback_status = function(player, playback_status)
playback_status_cb(self, player, playback_status)
end
player.on_seeked = function(player, position)
seeked_cb(self, player, position)
end
player.on_volume = function(player, volume)
volume_cb(self, player, volume)
end
player.on_loop_status = function(player, loop_status)
loop_status_cb(self, player, loop_status)
end
player.on_shuffle = function(player, shuffle_status)
shuffle_cb(self, player, shuffle_status)
end
player.on_exit = function(player, shuffle_status)
exit_cb(self, player)
end
-- Start position timer if its not already running
if not position_timer.started then
position_timer:again()
if not self._private.position_timer.started then
self._private.position_timer:again()
end
end
end
-- Determine if a player name comes before or after another according to the
-- priority order
local function player_compare_name(name_a, name_b)
local function player_compare_name(self, name_a, name_b)
local any_index = math.huge
local a_match_index = nil
local b_match_index = nil
@@ -224,7 +399,7 @@ local function player_compare_name(name_a, name_b)
return 0
end
for index, name in ipairs(priority) do
for index, name in ipairs(self.priority) do
if name == "%any" then
any_index = (any_index == math.huge) and index or any_index
elseif name == name_a then
@@ -248,103 +423,138 @@ local function player_compare_name(name_a, name_b)
end
-- Sorting function used by manager if a priority order is specified
local function player_compare(a, b)
local player_a = Playerctl.Player(a)
local player_b = Playerctl.Player(b)
return player_compare_name(player_a.player_name, player_b.player_name)
local function player_compare(self, a, b)
local player_a = self._private.lgi_Playerctl.Player(a)
local player_b = self._private.lgi_Playerctl.Player(b)
return player_compare_name(self, player_a.player_name, player_b.player_name)
end
local function start_manager()
manager = Playerctl.PlayerManager()
if #priority > 0 then
manager:set_sort_func(player_compare)
local function get_current_player_info(self, player)
local title = player:get_title() or ""
local artist = player:get_artist() or ""
local artUrl = player:print_metadata_prop("mpris:artUrl") or ""
local album = player:get_album() or ""
emit_metadata_signal(self, title, artist, artUrl, album, false, player.player_name)
playback_status_cb(self, player, player.playback_status)
volume_cb(self, player, player.volume)
loop_status_cb(self, player, player.loop_status)
shuffle_cb(self, player, player.shuffle)
end
local function start_manager(self)
self._private.manager = self._private.lgi_Playerctl.PlayerManager()
if #self.priority > 0 then
self._private.manager:set_sort_func(function(a, b)
return player_compare(self, a, b)
end)
end
-- Timer to update track position at specified interval
position_timer = gears.timer({
timeout = interval,
callback = position_cb,
})
self._private.position_timer = gtimer {
timeout = self.interval,
callback = function()
position_cb(self)
end,
}
-- Manage existing players on startup
for _, name in ipairs(manager.player_names) do
init_player(name)
for _, name in ipairs(self._private.manager.player_names) do
init_player(self, name)
end
if self._private.manager.players[1] then
get_current_player_info(self, self._private.manager.players[1])
end
local _self = self
-- Callback to manage new players
function manager:on_name_appeared(name)
init_player(name)
function self._private.manager:on_name_appeared(name)
init_player(_self, name)
end
-- Callback to check if all players have exited
function manager:on_name_vanished(name)
if #manager.players == 0 then
metadata_timer:stop()
position_timer:stop()
awesome.emit_signal("bling::playerctl::no_players")
function self._private.manager:on_player_appeared(player)
if player == self.players[1] then
_self._private.active_player = player
end
end
function self._private.manager:on_player_vanished(player)
if #self.players == 0 then
_self._private.metadata_timer:stop()
_self._private.position_timer:stop()
_self:emit_signal("no_players")
capi.awesome.emit_signal("bling::playerctl::no_players")
elseif player == _self._private.active_player then
_self._private.active_player = self.players[1]
get_current_player_info(_self, self.players[1])
end
end
end
-- Parse arguments
local function parse_args(args)
if args then
update_on_activity = args.update_on_activity or update_on_activity
interval = args.interval or interval
if type(args.ignore) == "string" then
ignore[args.ignore] = true
elseif type(args.ignore) == "table" then
for _, name in pairs(args.ignore) do
ignore[name] = true
end
local function parse_args(self, args)
self.ignore = {}
if type(args.ignore) == "string" then
self.ignore[args.ignore] = true
elseif type(args.ignore) == "table" then
for _, name in pairs(args.ignore) do
self.ignore[name] = true
end
end
if type(args.player) == "string" then
priority[1] = args.player
elseif type(args.player) == "table" then
priority = args.player
end
self.priority = {}
if type(args.player) == "string" then
self.priority[1] = args.player
elseif type(args.player) == "table" then
self.priority = args.player
end
end
local function playerctl_enable(args)
local function new(args)
args = args or {}
local ret = gobject{}
gtable.crush(ret, playerctl, true)
-- Grab settings from beautiful variables if not set explicitly
args.ignore = args.ignore or beautiful.playerctl_ignore
args.player = args.player or beautiful.playerctl_player
args.update_on_activity = args.update_on_activity
or beautiful.playerctl_update_on_activity
args.interval = args.interval
or beautiful.playerctl_position_update_interval
parse_args(args)
ret.update_on_activity = args.update_on_activity or
beautiful.playerctl_update_on_activity or true
ret.interval = args.interval or beautiful.playerctl_position_update_interval or 1
ret.debounce_delay = args.debounce_delay or beautiful.playerctl_debounce_delay or 0.35
parse_args(ret, args)
ret._private = {}
-- Metadata callback for title, artist, and album art
ret._private.last_player = nil
ret._private.last_title = ""
ret._private.last_artist = ""
ret._private.last_artUrl = ""
-- Track position callback
ret._private.last_position = -1
ret._private.last_length = -1
-- Grab playerctl library
Playerctl = require("lgi").Playerctl
ret._private.lgi_Playerctl = require("lgi").Playerctl
ret._private.manager = nil
ret._private.metadata_timer = nil
ret._private.position_timer = nil
-- Ensure main event loop has started before starting player manager
gears.timer.delayed_call(start_manager)
gtimer.delayed_call(function()
start_manager(ret)
end)
return ret
end
local function playerctl_disable()
-- Remove manager and timer
manager = nil
metadata_timer:stop()
metadata_timer = nil
position_timer:stop()
position_timer = nil
-- Restore default settings
ignore = {}
priority = {}
update_on_activity = true
interval = 1
-- Reset default values
last_position = -1
last_length = -1
last_player = nil
last_title = ""
last_artist = ""
last_artUrl = ""
function playerctl.mt:__call(...)
return new(...)
end
return { enable = playerctl_enable, disable = playerctl_disable }
return setmetatable(playerctl, playerctl.mt)

View File

@@ -0,0 +1,105 @@
--[[ Bling theme variables template
This file has all theme variables of the bling module.
Every variable has a small comment on what it does.
You might just want to copy that whole part into your theme.lua and start adjusting from there.
--]]
-- LuaFormatter off
-- window swallowing
theme.dont_swallow_classname_list = { "firefox", "Gimp" } -- list of class names that should not be swallowed
theme.dont_swallow_filter_activated = true -- whether the filter above should be active
-- flash focus
theme.flash_focus_start_opacity = 0.6 -- the starting opacity
theme.flash_focus_step = 0.01 -- the step of animation
-- playerctl signal
theme.playerctl_backend = "playerctl_cli" -- backend to use
theme.playerctl_ignore = {} -- list of players to be ignored
theme.playerctl_player = {} -- list of players to be used in priority order
theme.playerctl_update_on_activity = true -- whether to prioritize the most recently active players or not
theme.playerctl_position_update_interval = 1 -- the update interval for fetching the position from playerctl
-- tabbed
theme.tabbed_spawn_in_tab = false -- whether a new client should spawn into the focused tabbing container
-- tabbar general
theme.tabbar_disable = false -- disable the tab bar entirely
theme.tabbar_ontop = false
theme.tabbar_radius = 0 -- border radius of the tabbar
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
theme.tabbar_font = "Sans 11" -- font of the tabbar
theme.tabbar_size = 40 -- size of the tabbar
theme.tabbar_position = "top" -- position of the tabbar
theme.tabbar_bg_normal = "#000000" -- background color of the focused client on the tabbar
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
-- mstab
theme.mstab_bar_disable = false -- disable the tabbar
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
theme.mstab_dont_resize_slaves = false -- whether the tabbed stack windows should be smaller than the
-- currently focused stack window (set it to true if you use
-- transparent terminals. False if you use shadows on solid ones
theme.mstab_bar_padding = "default" -- how much padding there should be between clients and your tabbar
-- by default it will adjust based on your useless gaps.
-- If you want a custom value. Set it to the number of pixels (int)
theme.mstab_border_radius = 0 -- border radius of the tabbar
theme.mstab_bar_height = 40 -- height of the tabbar
theme.mstab_tabbar_position = "top" -- position of the tabbar (mstab currently does not support left,right)
theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
-- defaults to the tabbar_style so only change if you want a
-- different style for mstab and tabbed
-- the following variables are currently only for the "modern" tabbar style
theme.tabbar_color_close = "#f9929b" -- changes the color of the close button
theme.tabbar_color_min = "#fbdf90" -- changes the color of the minimize button
theme.tabbar_color_float = "#ccaced" -- changes the color of the float button
-- tag preview widget
theme.tag_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
theme.tag_preview_client_border_radius = 0 -- Border radius of each client in the widget (With AA)
theme.tag_preview_client_opacity = 0.5 -- Opacity of each client
theme.tag_preview_client_bg = "#000000" -- The bg color of each client
theme.tag_preview_client_border_color = "#ffffff" -- The border color of each client
theme.tag_preview_client_border_width = 3 -- The border width of each client
theme.tag_preview_widget_bg = "#000000" -- The bg color of the widget
theme.tag_preview_widget_border_color = "#ffffff" -- The border color of the widget
theme.tag_preview_widget_border_width = 3 -- The border width of the widget
theme.tag_preview_widget_margin = 0 -- The margin of the widget
-- task preview widget
theme.task_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
theme.task_preview_widget_bg = "#000000" -- The bg color of the widget
theme.task_preview_widget_border_color = "#ffffff" -- The border color of the widget
theme.task_preview_widget_border_width = 3 -- The border width of the widget
theme.task_preview_widget_margin = 0 -- The margin of the widget
-- window switcher
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
theme.window_switcher_clients_spacing = 20 -- The space between each client item
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
theme.window_switcher_client_width = 150 -- The width of one client widget
theme.window_switcher_client_height = 250 -- The height of one client widget
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
theme.window_switcher_name_forced_width = 200 -- The width of one title
theme.window_switcher_name_font = "Sans 11" -- The font of all titles
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
theme.window_switcher_icon_width = 40 -- The width of one icon
-- LuaFormatter on

View File

@@ -281,8 +281,8 @@ local function search(self, text)
text = text:gsub( "%W", "" )
-- Check if there's a match by the app name or app command
if string.find(entry.name, case_insensitive_pattern(text)) ~= nil or
self.search_commands and string.find(entry.commandline, case_insensitive_pattern(text)) ~= nil
if string.find(entry.name:lower(), text:lower(), 1, true) ~= nil or
self.search_commands and string.find(entry.commandline, text:lower(), 1, true) ~= nil
then
table.insert(self._private.matched_entries, {
name = entry.name,
@@ -498,7 +498,6 @@ local function scroll_right(self)
local rows, columns = self._private.grid:get_dimension()
local pos = self._private.grid:get_widget_position(self._private.active_widget)
local is_less_than_max_column = pos.col < columns
local is_less_than_max_page = self._private.current_page < self._private.pages_count
-- Check if we can scroll down the app list
if is_less_than_max_column then
@@ -773,6 +772,7 @@ local function new(args)
args.icon_theme = args.icon_theme or nil
args.icons_size = args.icons_size or nil
args.type = args.type or "dock"
args.show_on_focused_screen = args.show_on_focused_screen == nil and true or args.show_on_focused_screen
args.screen = args.screen or capi.screen.primary
args.placement = args.placement or awful.placement.centered
@@ -919,7 +919,7 @@ local function new(args)
}
ret._private.widget = awful.popup
{
type = "dock",
type = args.type,
visible = false,
ontop = true,
placement = ret.placement,

View File

@@ -1,4 +1,5 @@
local beautiful = require("beautiful")
local awful = require("awful")
local shapes = require("extras.nice.shapes")
@@ -8,12 +9,77 @@ function update_titlebars(c, init)
-- Rounded Corners
if not c.fullscreen and not c.maximized then
c.shape = shapes.rounded_rect {
tl = 9,
tr = 9,
bl = 9,
br = 9
tl = beautiful.corner_radius,
tr = beautiful.corner_radius,
bl = beautiful.corner_radius,
br = beautiful.corner_radius
}
else
c.shape = nil
end
end
function toggle_window_buffers(s)
if not s.top then
s.left = awful.wibar({
screen = s,
position = "left",
opacity = 0.0,
input_passthrough = true,
})
s.right = awful.wibar({
screen = s,
position = "right",
opacity = 0.0,
input_passthrough = true,
})
s.top = awful.wibar({
screen = s,
position = "top",
opacity = 0.0,
input_passthrough = true,
})
s.bottom = awful.wibar({
screen = s,
position = "bottom",
opacity = 0.0,
input_passthrough = true,
})
end
-- Three states: off, small borders, large borders
s.buffer_state = s.buffer_state or "off"
if s.buffer_state == "off" then
s.buffer_state = "small"
s.left.visible = true
s.right.visible = true
s.top.visible = true
s.bottom.visible = true
s.left.width = 50
s.right.width = 50
s.top.height = 50
s.bottom.height = 50
elseif s.buffer_state == "small" then
s.buffer_state = "large"
s.left.visible = true
s.right.visible = true
s.top.visible = true
s.bottom.visible = true
s.left.width = 200
s.right.width = 200
s.top.height = 50
s.bottom.height = 350
elseif s.buffer_state == "large" then
s.buffer_state = "off"
s.left.visible = false
s.right.visible = false
s.top.visible = false
s.bottom.visible = false
end
end

View File

@@ -2,7 +2,7 @@ local awful = require("awful")
local beautiful = require("beautiful")
awful.rules.rules = {
-- All clients will match this rule.
-- All clients
{
rule = {},
properties = {
@@ -15,7 +15,7 @@ awful.rules.rules = {
placement = awful.placement.no_overlap + awful.placement.no_offscreen + awful.placement.centered
}
},
-- Floating clients.
-- Floating clients
{
rule_any = {
instance = {
@@ -42,7 +42,7 @@ awful.rules.rules = {
},
properties = {floating = true},
},
-- Fullscreen clients.
-- Fullscreen clients
{
rule_any = {
name = {
@@ -53,6 +53,18 @@ awful.rules.rules = {
fullscreen = true
}
},
-- Ontop clients
{
rule_any = {
class = {
"qalculate-gtk",
"Qalculate-gtk",
},
},
properties = {
ontop = true
}
},
-- Anbox floating window size
{
rule_any = {
@@ -62,8 +74,8 @@ awful.rules.rules = {
},
properties = {
floating = true,
height = 1280,
width = 800,
height = 800,
width = 480,
},
},
-- Music Visualizer

View File

@@ -1 +1,12 @@
require "screen.wibar"
local awful = require("awful")
require "screen.wibar"
awful.screen.connect_for_each_screen(
function(s)
set_wallpaper(s)
awful.tag({"1", "2", "3", "4", "5", "6", "7", "8", "9"}, s, awful.layout.layouts[1])
wibar = wibar_builder(s)
end
)

View File

@@ -3,166 +3,36 @@ local awful = require("awful")
local wibox = require("wibox")
local beautiful = require("beautiful")
beautiful.bg_systray = "#2e3440"
beautiful.tasklist_bg_normal = "#2e3440"
beautiful.tasklist_bg_focus = "#4c566a"
beautiful.tasklist_bg_urgent = "#bf616a"
beautiful.tasklist_bg_minimize = "#5e81ac"
require "screen.wibar.widgets"
mykeyboardlayout = awful.widget.keyboardlayout()
mytextclock = wibox.widget.textclock()
mysystray = wibox.widget.systray()
function wibar_builder(s)
local w = awful.wibar({
screen = s,
position = "top",
bg = beautiful.bg_systray,
height = 26,
})
local taglist_buttons =
gears.table.join(
awful.button(
{},
1,
function(t)
t:view_only()
end
),
awful.button(
{modkey},
1,
function(t)
if client.focus then
client.focus:move_to_tag(t)
end
end
),
awful.button({}, 3, awful.tag.viewtoggle),
awful.button(
{modkey},
3,
function(t)
if client.focus then
client.focus:toggle_tag(t)
end
end
),
awful.button(
{},
4,
function(t)
awful.tag.viewnext(t.screen)
end
),
awful.button(
{},
5,
function(t)
awful.tag.viewprev(t.screen)
end
)
)
local taglist = taglist(s)
local tasklist = tasklist(s)
local layoutbox = layoutbox(s)
local tasklist_buttons =
gears.table.join(
awful.button(
{},
1,
function(c)
if c == client.focus then
c.minimized = true
else
c:emit_signal("request::activate", "tasklist", {raise = true})
end
end
),
awful.button(
{},
4,
function()
awful.client.focus.byidx(1)
end
),
awful.button(
{},
5,
function()
awful.client.focus.byidx(-1)
end
)
)
awful.screen.connect_for_each_screen(
function(s)
-- Wallpaper
set_wallpaper(s)
-- Tags
awful.tag({"1", "2", "3", "4", "5", "6", "7", "8", "9"}, s, awful.layout.layouts[1])
s.mytaglist = awful.widget.taglist {
screen = s,
filter = awful.widget.taglist.filter.all,
buttons = taglist_buttons
w:setup{
expand = "none",
layout = wibox.layout.align.horizontal,
{
layout = wibox.layout.fixed.horizontal,
taglist,
},
tasklist,
{
layout = wibox.layout.fixed.horizontal,
systray,
keyboardlayout,
clock,
layoutbox,
}
}
-- Layout Box
s.mylayoutbox = awful.widget.layoutbox(s)
s.mylayoutbox:buttons(
gears.table.join(
awful.button(
{},
1,
function()
awful.layout.inc(1)
end
),
awful.button(
{},
3,
function()
awful.layout.inc(-1)
end
),
awful.button(
{},
4,
function()
awful.layout.inc(1)
end
),
awful.button(
{},
5,
function()
awful.layout.inc(-1)
end
)
)
)
-- Create a tasklist widget
s.mytasklist = awful.widget.tasklist {
screen = s,
filter = awful.widget.tasklist.filter.currenttags,
buttons = tasklist_buttons,
}
-- Wibar initialization
s.mywibox = awful.wibar({
position = "top",
screen = s,
bg = "#2e3440"
})
s.mywibox:setup {
layout = wibox.layout.align.horizontal,
{
layout = wibox.layout.fixed.horizontal,
s.mytaglist,
},
s.mytasklist,
{
layout = wibox.layout.fixed.horizontal,
mysystray,
mykeyboardlayout,
mytextclock,
s.mylayoutbox,
}
}
end
)
return w
end

View File

@@ -0,0 +1,28 @@
local gears = require("gears")
local awful = require("awful")
local wibox = require("wibox")
function layoutbox(s)
lb = awful.widget.layoutbox(s)
lb:buttons(
gears.table.join(
awful.button(
{},
1,
function()
awful.layout.inc(1)
end
),
awful.button(
{},
3,
function()
awful.layout.inc(-1)
end
)
)
)
return lb
end

View File

@@ -0,0 +1,69 @@
local awful = require("awful")
local gears = require("gears")
local wibox = require("wibox")
local beautiful = require("beautiful")
local taglist_buttons =
gears.table.join(
awful.button(
{},
1,
function(t)
t:view_only()
end
),
awful.button(
{modkey},
1,
function(t)
if client.focus then
client.focus:move_to_tag(t)
end
end
),
awful.button({}, 3, awful.tag.viewtoggle),
awful.button(
{modkey},
3,
function(t)
if client.focus then
client.focus:toggle_tag(t)
end
end
)
)
function taglist(s)
return awful.widget.taglist {
screen = s,
filter = awful.widget.taglist.filter.all, --.noempty,
buttons = taglist_buttons,
widget_template = {
{
{
id = 'index_role',
widget = wibox.widget.textbox,
},
margins = 2,
widget = wibox.container.margin,
},
id = 'background_role',
widget = wibox.container.background,
create_callback = function(self, c3, index, objects)
self:get_children_by_id('index_role')[1].markup = '<span> '..index..' </span>'
self:connect_signal('mouse::enter', function()
if self.bg ~= beautiful.taglist_bg_focus then
self.backup = self.bg
self.has_backup = true
end
self.bg = beautiful.taglist_bg_focus
end)
self:connect_signal('mouse::leave', function()
if self.has_backup then self.bg = self.backup end
end)
end,
},
}
end

View File

@@ -0,0 +1,85 @@
local gears = require("gears")
local awful = require("awful")
local wibox = require("wibox")
local beautiful = require("beautiful")
local tasklist_buttons =
gears.table.join(
awful.button(
{},
1,
function(c)
if c == client.focus then
c.minimized = true
else
c:emit_signal("request::activate", "tasklist", {raise = true})
end
end
)
)
function tasklist(s)
return awful.widget.tasklist {
screen = s,
filter = awful.widget.tasklist.filter.currenttags,
buttons = tasklist_buttons,
style = {
--disable_task_name = true
},
layout = {
spacing = 5,
spacing_widget = {
valign = 'center',
halign = 'center',
widget = wibox.container.place,
},
layout = wibox.layout.fixed.horizontal
},
widget_template = {
{
{
{
{
id = 'icon_role',
widget = wibox.widget.imagebox,
},
top = 2,
bottom = 2,
right = 3,
widget = wibox.container.margin,
},
{
id = 'text_role',
widget = wibox.widget.textbox,
},
layout = wibox.layout.fixed.horizontal,
},
left = 8,
right = 10,
widget = wibox.container.margin
},
id = 'background_role',
widget = wibox.container.background,
create_callback = function(self, c3, index, objects)
self:connect_signal('mouse::enter', function()
if self.bg ~= beautiful.tasklist_bg_focus then
self.backup = self.bg
self.has_backup = true
end
self.bg = beautiful.tasklist_bg_focus
-- Raise client
c3:emit_signal(
"request::activate",
"tasklist", {
raise = true
}
)
end)
self:connect_signal('mouse::leave', function()
if self.has_backup then self.bg = self.backup end
end)
end,
},
}
end

View File

@@ -0,0 +1,16 @@
local gears = require("gears")
local awful = require("awful")
local wibox = require("wibox")
local beautiful = require("beautiful")
keyboardlayout = awful.widget.keyboardlayout()
clock = wibox.widget.textclock()
clock.format = "<span foreground='"..beautiful.fg_normal.."'>".." %A %B %d, %H:%M ".."</span>"
systray = wibox.widget.systray()
systray:set_base_size(26)
require "screen.wibar.taglist"
require "screen.wibar.layoutbox"
require "screen.wibar.tasklist"

View File

@@ -3,14 +3,11 @@
theme=$(grep -o -P '(?<=local theme = ").*(?=")' /home/nick/.config/awesome/theme/init.lua)
case $theme in
"nordic_firewatch")
new_theme="nordic_moon"
;;
"nordic_moon")
new_theme="nordic_legion"
;;
"nordic_legion")
new_theme="nordic_firewatch"
new_theme="abstract_office"
;;
"abstract_office")
new_theme="nordic_legion"
;;
*)
esac
@@ -18,41 +15,5 @@ esac
# Replace the theme in the init.lua file
sed -i "s/local theme = .*$/local theme = \"$new_theme\"/" /home/nick/.config/awesome/theme/init.lua
# Configure glava
case $new_theme in
"nordic_firewatch")
sed -i 's/#request mod .*/#request mod bars/g' /home/nick/.config/glava/rc.glsl
sed -i 's/#request setgeometry .*/#request setgeometry 0 0 2560 750/g' /home/nick/.config/glava/rc.glsl
;;
"nordic_moon")
sed -i 's/#request mod .*/#request mod radial/g' /home/nick/.config/glava/rc.glsl
sed -i 's/#request setgeometry .*/#request setgeometry 0 0 2560 1600/g' /home/nick/.config/glava/rc.glsl
;;
"nordic_legion")
sed -i 's/#request mod .*/#request mod bars/g' /home/nick/.config/glava/rc.glsl
sed -i 's/#request setgeometry .*/#request setgeometry 0 0 2560 1600/g' /home/nick/.config/glava/rc.glsl
;;
*)
esac
# Restart glava if it's running
if pgrep glava > /dev/null; then
killall glava
glava --desktop &>/dev/null & disown
fi
# Restart awesome
echo 'awesome.restart()' | awesome-client
# Configure conky
case $new_theme in
"nordic_firewatch")
pkill conky
;;
"nordic_moon")
pkill conky
;;
"nordic_legion")
;;
*)
esac

View File

@@ -22,6 +22,24 @@ client.connect_signal(
end
)
client.connect_signal(
"unmanage",
function(_)
local focus_timer = timer({ timeout = 0.05 })
focus_timer:connect_signal(
"timeout",
function()
local c = awful.mouse.client_under_pointer()
if c ~= nil and not c.below then
client.focus = c
c:raise()
end
focus_timer:stop()
end)
focus_timer:start()
end
)
-- Enable sloppy focus, so that focus follows mouse.
client.connect_signal(
"mouse::enter",
@@ -75,7 +93,6 @@ client.connect_signal(
update_titlebars
)
-- Automatically unminimize windows
client.connect_signal(
"property::minimized",
function(c)
@@ -85,14 +102,15 @@ client.connect_signal(
end
)
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
screen.connect_signal("property::geometry", set_wallpaper)
screen.connect_signal(
"property::geometry",
set_wallpaper
)
tag.connect_signal(
"property::selected",
function (t)
local selected = tostring(t.selected) == "false"
if selected then
function(t)
if not t.selected then
local focus_timer = timer({ timeout = 0.05 })
focus_timer:connect_signal(
"timeout",

View File

@@ -0,0 +1,133 @@
---------------------------
-- Default awesome theme --
---------------------------
local gears = require("gears")
local theme_assets = require("beautiful.theme_assets")
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi
local gfs = require("gears.filesystem")
local themes_path = gfs.get_themes_dir()
local theme = {}
theme.font = "Sans Serif 11"
theme.icon_font = "Font Awesome 6 Free"
theme.icon_size = 11
theme.bg_normal = "#151821"
theme.bg_dark = "#000000"
theme.bg_focus = "#1f2430"
theme.bg_urgent = "#ed8274"
theme.fg_normal = "#ffffff"
theme.fg_focus = "#e4e4e4"
theme.fg_urgent = "#ffffff"
theme.fg_minimize = "#ffffff"
theme.taglist_bg_empty = theme.bg_normal
theme.taglist_bg_occupied = "#ffffff1a"
theme.taglist_bg_urgent = "#e91e6399"
theme.taglist_bg_focus = theme.bg_focus
theme.tasklist_bg_normal = theme.bg_normal
theme.tasklist_bg_focus = theme.bg_focus
theme.tasklist_bg_urgent = theme.bg_urgent
theme.tasklist_fg_focus = theme.fg_focus
theme.tasklist_fg_urgent = theme.fg_urgent
theme.tasklist_fg_normal = theme.fg_normal
theme.useless_gap = dpi(7)
theme.gap_single_client = true
theme.border_width = dpi(0)
theme.corner_radius = dpi(10)
theme.transparency = 85
-- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile]
-- tasklist_[bg|fg]_[focus|urgent]
-- titlebar_[bg|fg]_[normal|focus]
-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color]
-- mouse_finder_[color|timeout|animate_timeout|radius|factor]
-- prompt_[fg|bg|fg_cursor|bg_cursor|font]
-- hotkeys_[bg|fg|border_width|border_color|shape|opacity|modifiers_fg|label_bg|label_fg|group_margin|font|description_font]
-- notification_font
-- notification_[bg|fg]
-- notification_[width|height|margin]
-- notification_[border_color|border_width|shape|opacity]
theme.menu_height = dpi(15)
theme.menu_width = dpi(100)
-- menu_[bg|fg]_[normal|focus]
-- menu_[border_color|border_width]
-- Image recoloring
local function get_icon(icon_raw)
if icon_raw ~= nil then
return gears.color.recolor_image(icon_raw, theme.fg_focus)
else
return nil
end
end
-- Define the image to load
theme.titlebar_close_button_normal = get_icon(themes_path.."default/titlebar/close_normal.png")
theme.titlebar_close_button_focus = get_icon(themes_path.."default/titlebar/close_focus.png")
theme.titlebar_minimize_button_normal = get_icon(themes_path.."default/titlebar/minimize_normal.png")
theme.titlebar_minimize_button_focus = get_icon(themes_path.."default/titlebar/minimize_focus.png")
theme.titlebar_ontop_button_normal_inactive = get_icon(themes_path.."default/titlebar/ontop_normal_inactive.png")
theme.titlebar_ontop_button_focus_inactive = get_icon(themes_path.."default/titlebar/ontop_focus_inactive.png")
theme.titlebar_ontop_button_normal_active = get_icon(themes_path.."default/titlebar/ontop_normal_active.png")
theme.titlebar_ontop_button_focus_active = get_icon(themes_path.."default/titlebar/ontop_focus_active.png")
theme.titlebar_sticky_button_normal_inactive = get_icon(themes_path.."default/titlebar/sticky_normal_inactive.png")
theme.titlebar_sticky_button_focus_inactive = get_icon(themes_path.."default/titlebar/sticky_focus_inactive.png")
theme.titlebar_sticky_button_normal_active = get_icon(themes_path.."default/titlebar/sticky_normal_active.png")
theme.titlebar_sticky_button_focus_active = get_icon(themes_path.."default/titlebar/sticky_focus_active.png")
theme.titlebar_floating_button_normal_inactive = get_icon(themes_path.."default/titlebar/floating_normal_inactive.png")
theme.titlebar_floating_button_focus_inactive = get_icon(themes_path.."default/titlebar/floating_focus_inactive.png")
theme.titlebar_floating_button_normal_active = get_icon(themes_path.."default/titlebar/floating_normal_active.png")
theme.titlebar_floating_button_focus_active = get_icon(themes_path.."default/titlebar/floating_focus_active.png")
theme.titlebar_maximized_button_normal_inactive = get_icon(themes_path.."default/titlebar/maximized_normal_inactive.png")
theme.titlebar_maximized_button_focus_inactive = get_icon(themes_path.."default/titlebar/maximized_focus_inactive.png")
theme.titlebar_maximized_button_normal_active = get_icon(themes_path.."default/titlebar/maximized_normal_active.png")
theme.titlebar_maximized_button_focus_active = get_icon(themes_path.."default/titlebar/maximized_focus_active.png")
theme.wallpaper = get_icon(themes_path.."default/background.png")
-- You can use your own layout icons like this:
theme.layout_fairh = get_icon(themes_path.."default/layouts/fairhw.png")
theme.layout_fairv = get_icon(themes_path.."default/layouts/fairvw.png")
theme.layout_floating = get_icon(themes_path.."default/layouts/floatingw.png")
theme.layout_magnifier = get_icon(themes_path.."default/layouts/magnifierw.png")
theme.layout_max = get_icon(themes_path.."default/layouts/maxw.png")
theme.layout_fullscreen = get_icon(themes_path.."default/layouts/fullscreenw.png")
theme.layout_tilebottom = get_icon(themes_path.."default/layouts/tilebottomw.png")
theme.layout_tileleft = get_icon(themes_path.."default/layouts/tileleftw.png")
theme.layout_tile = get_icon(themes_path.."default/layouts/tilew.png")
theme.layout_tiletop = get_icon(themes_path.."default/layouts/tiletopw.png")
theme.layout_spiral = get_icon(themes_path.."default/layouts/spiralw.png")
theme.layout_dwindle = get_icon(themes_path.."default/layouts/dwindlew.png")
theme.layout_cornernw = get_icon(themes_path.."default/layouts/cornernww.png")
theme.layout_cornerne = get_icon(themes_path.."default/layouts/cornernew.png")
theme.layout_cornersw = get_icon(themes_path.."default/layouts/cornersww.png")
theme.layout_cornerse = get_icon(themes_path.."default/layouts/cornersew.png")
-- Generate Awesome icon:
theme.awesome_icon = theme_assets.awesome_icon(
theme.menu_height, theme.bg_focus, theme.fg_focus
)
-- Define the icon theme for application icons. If not set then the icons
-- from /usr/share/icons and /usr/share/icons/hicolor will be used.
theme.icon_theme = "Tela-blue-dark"
return theme

View File

@@ -3,20 +3,9 @@ local beautiful = require("beautiful")
local awful = require("awful")
local wibox = require("wibox")
beautiful.init(gears.filesystem.get_configuration_dir() .. "theme/default/theme.lua")
beautiful.font = "Ubuntu Sans 11"
beautiful.useless_gap = 7
beautiful.gap_single_client = true
local theme = "nordic_legion"
beautiful.wallpaper = "/home/nick/Pictures/wallpapers/" .. theme .. "/wallpaper.png"
local cutout = "/home/nick/Pictures/wallpapers/" .. theme .. "/cutout.png"
function set_wallpaper(s)
-- Wallpaper
if beautiful.wallpaper then
local wallpaper = beautiful.wallpaper
-- If wallpaper is a function, call it with the screen
if type(wallpaper) == "function" then
wallpaper = wallpaper(s)
end
@@ -24,6 +13,53 @@ function set_wallpaper(s)
end
end
local function set_transparency(t)
-- Percentage xx/100
awful.spawn("sed -i 's/[0-9]*:class_g/" .. t .. ":class_g/g' /home/nick/.config/picom/picom.conf", false)
-- Integer 0.xx/1.00
awful.spawn("sed -i 's/opacity: [0-9]*.[0-9]*/opacity: " .. t/100 .. "/g' /home/nick/.config/alacritty/alacritty.yml", false)
-- Binary xx/255
awful.spawn("sed -i 's/\"glassit.alpha\": [0-9]*/\"glassit.alpha\": " .. math.floor((t/100)*255 + 0.5) .. "/g' /home/nick/.config/Code/User/settings.json", false)
end
local theme = "abstract_office"
-- Cleanup running theme applications
awful.spawn("pkill conky", false)
-- Per-theme settings
if theme == "nordic_legion" then
beautiful.init(gears.filesystem.get_configuration_dir() .. "theme/nordic_legion/theme.lua")
beautiful.font = "Ubuntu Sans 11"
beautiful.useless_gap = 7
beautiful.gap_single_client = true
beautiful.wallpaper = "/home/nick/Pictures/wallpapers/nordic_legion/wallpaper.png"
-- Launch Conky
awful.spawn.with_shell("killall conky; conky -c /home/nick/.config/conky/conky_left.conf &>/dev/null & disown; conky -c /home/nick/.config/conky/conky_right.conf &>/dev/null & disown", false)
-- Configure Glava
awful.spawn("sed -i 's/#request mod .*/#request mod bars/g' /home/nick/.config/glava/rc.glsl", false)
awful.spawn("sed -i 's/#request setgeometry .*/#request setgeometry 0 0 2560 1600/g' /home/nick/.config/glava/rc.glsl", false)
elseif theme == "abstract_office" then
beautiful.init(gears.filesystem.get_configuration_dir() .. "theme/abstract_office/theme.lua")
beautiful.wallpaper = "/home/nick/Pictures/wallpapers/abstract_office/Cage.jpg"
-- Configure Glava
awful.spawn("sed -i 's/#request mod .*/#request mod bars/g' /home/nick/.config/glava/rc.glsl", false)
awful.spawn("sed -i 's/#request setgeometry .*/#request setgeometry 0 0 2560 1600/g' /home/nick/.config/glava/rc.glsl", false)
end
-- Update external configs
awful.spawn("sed -i 's/corner-radius = [0-9]*/corner-radius = " .. beautiful.corner_radius .. "/g' /home/nick/.config/picom/picom.conf", false)
set_transparency(beautiful.transparency)
-- Restart Glava if it's running
awful.spawn.with_shell("if pgrep glava; then killall glava; glava --desktop &>/dev/null & disown; fi", false)
local bling = require("extras.bling")
awful.layout.layouts = {
@@ -36,28 +72,3 @@ awful.layout.layouts = {
awful.layout.suit.corner.nw,
awful.layout.suit.floating
}
-- Wallpaper cutout
local imgbox = wibox({
type = "desktop",
width = 2560,
height = 1600,
x = 0,
y = 0,
visible = true,
focusable = false,
opacity = 1,
bg = "#00000000",
})
imgbox:setup{
layout = wibox.layout.fixed.vertical,
{
widget = wibox.widget.imagebox,
image = cutout,
}
}
-- Launch conky if theme is nordic_legion
if theme == "nordic_legion" then
awful.spawn.with_shell("killall conky; conky -c /home/nick/.config/conky/conky_left.conf; conky -c /home/nick/.config/conky/conky_right.conf")
end

View File

@@ -0,0 +1,137 @@
---------------------------
-- Default awesome theme --
---------------------------
local gears = require("gears")
local theme_assets = require("beautiful.theme_assets")
local xresources = require("beautiful.xresources")
local dpi = xresources.apply_dpi
local gfs = require("gears.filesystem")
local themes_path = gfs.get_themes_dir()
local theme = {}
theme.font = "Sans Serif 11"
theme.icon_font = "Font Awesome 6 Free"
theme.icon_size = 11
theme.bg_normal = "#2e3440"
theme.bg_focus = "#535d6c"
theme.bg_urgent = "#ff0000"
theme.bg_minimize = "#444444"
theme.tasklist_bg_normal = theme.bg_normal
theme.tasklist_bg_focus = "#4c566a"
theme.tasklist_bg_urgent = "#bf616a"
theme.tasklist_bg_minimize = "#5e81ac"
theme.fg_normal = "#ffffff"
theme.fg_focus = "#ffffff"
theme.fg_urgent = "#ffffff"
theme.fg_minimize = "#ffffff"
theme.useless_gap = dpi(7)
theme.gap_single_client = true
theme.border_width = dpi(1)
theme.border_normal = "#000000"
theme.border_focus = "#535d6c"
theme.border_marked = "#91231c"
theme.corner_radius = dpi(10)
theme.transparency = 95
-- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile]
-- tasklist_[bg|fg]_[focus|urgent]
-- titlebar_[bg|fg]_[normal|focus]
-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color]
-- mouse_finder_[color|timeout|animate_timeout|radius|factor]
-- prompt_[fg|bg|fg_cursor|bg_cursor|font]
-- hotkeys_[bg|fg|border_width|border_color|shape|opacity|modifiers_fg|label_bg|label_fg|group_margin|font|description_font]
-- Generate taglist squares:
local taglist_square_size = dpi(4)
theme.taglist_squares_sel = theme_assets.taglist_squares_sel(
taglist_square_size, theme.fg_normal
)
theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel(
taglist_square_size, theme.fg_normal
)
-- notification_font
-- notification_[bg|fg]
-- notification_[width|height|margin]
-- notification_[border_color|border_width|shape|opacity]
theme.menu_height = dpi(15)
theme.menu_width = dpi(100)
-- menu_[bg|fg]_[normal|focus]
-- menu_[border_color|border_width]
-- Image recoloring
local function get_icon(icon_raw)
if icon_raw ~= nil then
return gears.color.recolor_image(icon_raw, theme.fg_focus)
else
return nil
end
end
-- Define the image to load
theme.titlebar_close_button_normal = get_icon(themes_path.."default/titlebar/close_normal.png")
theme.titlebar_close_button_focus = get_icon(themes_path.."default/titlebar/close_focus.png")
theme.titlebar_minimize_button_normal = get_icon(themes_path.."default/titlebar/minimize_normal.png")
theme.titlebar_minimize_button_focus = get_icon(themes_path.."default/titlebar/minimize_focus.png")
theme.titlebar_ontop_button_normal_inactive = get_icon(themes_path.."default/titlebar/ontop_normal_inactive.png")
theme.titlebar_ontop_button_focus_inactive = get_icon(themes_path.."default/titlebar/ontop_focus_inactive.png")
theme.titlebar_ontop_button_normal_active = get_icon(themes_path.."default/titlebar/ontop_normal_active.png")
theme.titlebar_ontop_button_focus_active = get_icon(themes_path.."default/titlebar/ontop_focus_active.png")
theme.titlebar_sticky_button_normal_inactive = get_icon(themes_path.."default/titlebar/sticky_normal_inactive.png")
theme.titlebar_sticky_button_focus_inactive = get_icon(themes_path.."default/titlebar/sticky_focus_inactive.png")
theme.titlebar_sticky_button_normal_active = get_icon(themes_path.."default/titlebar/sticky_normal_active.png")
theme.titlebar_sticky_button_focus_active = get_icon(themes_path.."default/titlebar/sticky_focus_active.png")
theme.titlebar_floating_button_normal_inactive = get_icon(themes_path.."default/titlebar/floating_normal_inactive.png")
theme.titlebar_floating_button_focus_inactive = get_icon(themes_path.."default/titlebar/floating_focus_inactive.png")
theme.titlebar_floating_button_normal_active = get_icon(themes_path.."default/titlebar/floating_normal_active.png")
theme.titlebar_floating_button_focus_active = get_icon(themes_path.."default/titlebar/floating_focus_active.png")
theme.titlebar_maximized_button_normal_inactive = get_icon(themes_path.."default/titlebar/maximized_normal_inactive.png")
theme.titlebar_maximized_button_focus_inactive = get_icon(themes_path.."default/titlebar/maximized_focus_inactive.png")
theme.titlebar_maximized_button_normal_active = get_icon(themes_path.."default/titlebar/maximized_normal_active.png")
theme.titlebar_maximized_button_focus_active = get_icon(themes_path.."default/titlebar/maximized_focus_active.png")
theme.wallpaper = get_icon(themes_path.."default/background.png")
-- You can use your own layout icons like this:
theme.layout_fairh = get_icon(themes_path.."default/layouts/fairhw.png")
theme.layout_fairv = get_icon(themes_path.."default/layouts/fairvw.png")
theme.layout_floating = get_icon(themes_path.."default/layouts/floatingw.png")
theme.layout_magnifier = get_icon(themes_path.."default/layouts/magnifierw.png")
theme.layout_max = get_icon(themes_path.."default/layouts/maxw.png")
theme.layout_fullscreen = get_icon(themes_path.."default/layouts/fullscreenw.png")
theme.layout_tilebottom = get_icon(themes_path.."default/layouts/tilebottomw.png")
theme.layout_tileleft = get_icon(themes_path.."default/layouts/tileleftw.png")
theme.layout_tile = get_icon(themes_path.."default/layouts/tilew.png")
theme.layout_tiletop = get_icon(themes_path.."default/layouts/tiletopw.png")
theme.layout_spiral = get_icon(themes_path.."default/layouts/spiralw.png")
theme.layout_dwindle = get_icon(themes_path.."default/layouts/dwindlew.png")
theme.layout_cornernw = get_icon(themes_path.."default/layouts/cornernww.png")
theme.layout_cornerne = get_icon(themes_path.."default/layouts/cornernew.png")
theme.layout_cornersw = get_icon(themes_path.."default/layouts/cornersww.png")
theme.layout_cornerse = get_icon(themes_path.."default/layouts/cornersew.png")
-- Generate Awesome icon:
theme.awesome_icon = theme_assets.awesome_icon(
theme.menu_height, theme.bg_focus, theme.fg_focus
)
-- Define the icon theme for application icons. If not set then the icons
-- from /usr/share/icons and /usr/share/icons/hicolor will be used.
theme.icon_theme = "Tela-blue-dark"
return theme

View File

@@ -4,7 +4,7 @@ glx-no-stencil = true;
glx-no-rebind-pixmap = true;
unredir-if-possible = true;
corner-radius = 9;
corner-radius = 10;
rounded-corners-exclude = [
"window_type = 'dock'",
"window_type = 'desktop'"
@@ -37,10 +37,11 @@ blur-background-exclude = [
];
blur-kern = "3x3box";
blur-method = "dual_kawase";
blur-strength = 5;
blur-strength = 10;
opacity-rule = [
"95:class_g = 'thunar'",
"95:class_g = 'Thunar'",
"85:class_g = 'thunar'",
"85:class_g = 'Thunar'",
"70:name = 'GLava'",
];
fading = true;

1
.zshrc
View File

@@ -113,6 +113,7 @@ alias fetch='neofetch'
alias tor='sudo /usr/bin/tor'
alias ssh='TERM=xterm-256color ssh'
alias proton-call-ge='proton-call -c /usr/share/steam/compatibilitytools.d/proton-ge-custom -r'
alias sync-timezone='timedatectl set-timezone "$(curl --fail https://ipapi.co/timezone)" && timedatectl'
# To customize prompt, run `p10k configure` or edit ~/.p10k.zsh.
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 685 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 481 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 224 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 342 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 246 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 176 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 569 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 263 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 239 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

0
wallpapers/astronaut/cutout.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 471 KiB

After

Width:  |  Height:  |  Size: 471 KiB

0
wallpapers/astronaut/wallpaper.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.9 MiB

After

Width:  |  Height:  |  Size: 1.9 MiB

0
wallpapers/astronaut/wallpaper.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.7 MiB

After

Width:  |  Height:  |  Size: 1.7 MiB

0
wallpapers/lock_screen_1.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 432 KiB

After

Width:  |  Height:  |  Size: 432 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 189 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 464 KiB

0
wallpapers/nordic_legion/cutout.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 229 KiB

0
wallpapers/nordic_legion/wallpaper.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 217 KiB

After

Width:  |  Height:  |  Size: 217 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 964 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 949 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 KiB