major update of awesome config
add new icons, switch over to using stylesheets instead of gears.color.recolor_image, add a music widget to the panel, optimize services in common.lua, fix the application lense filtering and increase the update rate of services in common.lua Signed-off-by: delta <darkussdelta@gmail.com>
1
.config/awesome/assets/phosphor/browser-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V88H40V56Z"></path></svg>
|
After Width: | Height: | Size: 234 B |
1
.config/awesome/assets/phosphor/code-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM92.8,145.6a8,8,0,1,1-9.6,12.8l-32-24a8,8,0,0,1,0-12.8l32-24a8,8,0,0,1,9.6,12.8L69.33,128Zm58.89-71.4-32,112a8,8,0,1,1-15.38-4.4l32-112a8,8,0,0,1,15.38,4.4Zm53.11,60.2-32,24a8,8,0,0,1-9.6-12.8L186.67,128,163.2,110.4a8,8,0,1,1,9.6-12.8l32,24a8,8,0,0,1,0,12.8Z"></path></svg>
|
After Width: | Height: | Size: 477 B |
1
.config/awesome/assets/phosphor/discord-logo-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M247.51,174.39,218,58a16.08,16.08,0,0,0-13-11.88l-36.06-5.92a16.22,16.22,0,0,0-18.26,11.88l-.21.85a4,4,0,0,0,3.27,4.93,155.62,155.62,0,0,1,24.41,5.62,8.2,8.2,0,0,1,5.62,9.7,8,8,0,0,1-10.19,5.64,155.4,155.4,0,0,0-90.8-.1,8.22,8.22,0,0,1-10.28-4.81,8,8,0,0,1,5.08-10.33,156.85,156.85,0,0,1,24.72-5.72,4,4,0,0,0,3.27-4.93l-.21-.85A16.21,16.21,0,0,0,87.08,40.21L51,46.13A16.08,16.08,0,0,0,38,58L8.49,174.39a15.94,15.94,0,0,0,9.06,18.51l67,29.71a16.17,16.17,0,0,0,21.71-9.1l3.49-9.45a4,4,0,0,0-3.27-5.35,158.13,158.13,0,0,1-28.63-6.2,8.2,8.2,0,0,1-5.61-9.67,8,8,0,0,1,10.2-5.66,155.59,155.59,0,0,0,91.12,0,8,8,0,0,1,10.19,5.65,8.19,8.19,0,0,1-5.61,9.68,157.84,157.84,0,0,1-28.62,6.2,4,4,0,0,0-3.27,5.35l3.49,9.45a16.18,16.18,0,0,0,21.71,9.1l67-29.71A15.94,15.94,0,0,0,247.51,174.39ZM92,152a12,12,0,1,1,12-12A12,12,0,0,1,92,152Zm72,0a12,12,0,1,1,12-12A12,12,0,0,1,164,152Z"></path></svg>
|
After Width: | Height: | Size: 990 B |
1
.config/awesome/assets/phosphor/game-controller-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M247.44,173.75a.68.68,0,0,0,0-.14L231.05,89.44c0-.06,0-.12,0-.18A60.08,60.08,0,0,0,172,40H83.89a59.88,59.88,0,0,0-59,49.52L8.58,173.61a.68.68,0,0,0,0,.14,36,36,0,0,0,60.9,31.71l.35-.37L109.52,160h37l39.71,45.09c.11.13.23.25.35.37A36.08,36.08,0,0,0,212,216a36,36,0,0,0,35.43-42.25ZM104,112H96v8a8,8,0,0,1-16,0v-8H72a8,8,0,0,1,0-16h8V88a8,8,0,0,1,16,0v8h8a8,8,0,0,1,0,16Zm40-8a8,8,0,0,1,8-8h24a8,8,0,0,1,0,16H152A8,8,0,0,1,144,104Zm84.37,87.47a19.84,19.84,0,0,1-12.9,8.23A20.09,20.09,0,0,1,198,194.31L167.8,160H172a60,60,0,0,0,51-28.38l8.74,45A19.82,19.82,0,0,1,228.37,191.47Z"></path></svg>
|
After Width: | Height: | Size: 698 B |
1
.config/awesome/assets/phosphor/grid-four-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M216,56v60a4,4,0,0,1-4,4H136V44a4,4,0,0,1,4-4h60A16,16,0,0,1,216,56ZM116,40H56A16,16,0,0,0,40,56v60a4,4,0,0,0,4,4h76V44A4,4,0,0,0,116,40Zm96,96H136v76a4,4,0,0,0,4,4h60a16,16,0,0,0,16-16V140A4,4,0,0,0,212,136ZM40,140v60a16,16,0,0,0,16,16h60a4,4,0,0,0,4-4V136H44A4,4,0,0,0,40,140Z"></path></svg>
|
After Width: | Height: | Size: 402 B |
1
.config/awesome/assets/phosphor/house-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M224,115.55V208a16,16,0,0,1-16,16H168a16,16,0,0,1-16-16V168a8,8,0,0,0-8-8H112a8,8,0,0,0-8,8v40a16,16,0,0,1-16,16H48a16,16,0,0,1-16-16V115.55a16,16,0,0,1,5.17-11.78l80-75.48.11-.11a16,16,0,0,1,21.53,0,1.14,1.14,0,0,0,.11.11l80,75.48A16,16,0,0,1,224,115.55Z"></path></svg>
|
After Width: | Height: | Size: 379 B |
|
@ -1,5 +1,4 @@
|
|||
local gfs = require "gears.filesystem"
|
||||
local gsurface = require "gears.surface"
|
||||
local qfs = require "quarrel.fs"
|
||||
|
||||
local icons = {}
|
||||
|
@ -7,7 +6,7 @@ local phosphor_dir = gfs.get_configuration_dir() .. "assets/phosphor/"
|
|||
|
||||
for _, icon in ipairs(qfs.ls_files(phosphor_dir)) do
|
||||
if icon:match(".+%.(.+)") == "svg" then
|
||||
icons[icon:match("(.+)%..+"):gsub("-", "_")] = gsurface.load_uncached(phosphor_dir .. icon)
|
||||
icons[icon:match("(.+)%..+"):gsub("-", "_")] = phosphor_dir .. icon
|
||||
end
|
||||
end
|
||||
|
||||
|
|
1
.config/awesome/assets/phosphor/music-notes-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M212.92,25.71a7.89,7.89,0,0,0-6.86-1.46l-128,32A8,8,0,0,0,72,64V174.1A36,36,0,1,0,88,204V110.25l112-28V142.1A36,36,0,1,0,216,172V32A8,8,0,0,0,212.92,25.71Z"></path></svg>
|
After Width: | Height: | Size: 279 B |
1
.config/awesome/assets/phosphor/pause-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M216,48V208a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V48a16,16,0,0,1,16-16h40A16,16,0,0,1,216,48ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Z"></path></svg>
|
After Width: | Height: | Size: 311 B |
1
.config/awesome/assets/phosphor/play-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z"></path></svg>
|
After Width: | Height: | Size: 314 B |
1
.config/awesome/assets/phosphor/skip-back-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M208,47.88V208.12a16,16,0,0,1-24.43,13.43L64,146.77V216a8,8,0,0,1-16,0V40a8,8,0,0,1,16,0v69.23L183.57,34.45A15.95,15.95,0,0,1,208,47.88Z"></path></svg>
|
After Width: | Height: | Size: 260 B |
1
.config/awesome/assets/phosphor/skip-forward-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M208,40V216a8,8,0,0,1-16,0V146.77L72.43,221.55A15.95,15.95,0,0,1,48,208.12V47.88A15.95,15.95,0,0,1,72.43,34.45L192,109.23V40a8,8,0,0,1,16,0Z"></path></svg>
|
After Width: | Height: | Size: 264 B |
1
.config/awesome/assets/phosphor/spotify-logo-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm31.07,145.74a8,8,0,0,1-10.81,3.33,42.79,42.79,0,0,0-40.52,0,8,8,0,0,1-7.48-14.14,59.33,59.33,0,0,1,55.48,0A8,8,0,0,1,159.07,169.74Zm16-28a8,8,0,0,1-10.82,3.3,77.07,77.07,0,0,0-72.48,0,8,8,0,0,1-7.52-14.12,93,93,0,0,1,87.52,0A8,8,0,0,1,175.06,141.76Zm16-28a8,8,0,0,1-10.83,3.29,110.62,110.62,0,0,0-104.46,0,8,8,0,0,1-7.54-14.12,126.67,126.67,0,0,1,119.54,0A8,8,0,0,1,191.06,113.76Z"></path></svg>
|
After Width: | Height: | Size: 562 B |
1
.config/awesome/assets/phosphor/vinyl-record-fill.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" fill="#000000" viewBox="0 0 256 256"><path d="M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM72,128a8,8,0,0,1-16,0,72.08,72.08,0,0,1,72-72,8,8,0,0,1,0,16A56.06,56.06,0,0,0,72,128Zm32,0a24,24,0,1,1,24,24A24,24,0,0,1,104,128Zm24,72a8,8,0,0,1,0-16,56.06,56.06,0,0,0,56-56,8,8,0,0,1,16,0A72.08,72.08,0,0,1,128,200Z"></path></svg>
|
After Width: | Height: | Size: 399 B |
|
@ -11,9 +11,9 @@ local programs = {
|
|||
"wezterm start --class code_term",
|
||||
"firefox",
|
||||
"discord",
|
||||
"env LD_PRELOAD=/usr/lib/spotify-adblock.so spotify"
|
||||
"LD_PRELOAD=/usr/lib/spotify-adblock.so spotify"
|
||||
}
|
||||
|
||||
for _, program in ipairs(programs) do
|
||||
awful.spawn(program)
|
||||
awful.spawn.with_shell(program .. " 1>/dev/null 2>&1")
|
||||
end
|
||||
|
|
|
@ -1,6 +1,38 @@
|
|||
local c = {
|
||||
titlebars_enabled = false,
|
||||
terminal = "wezterm"
|
||||
local awful = require "awful"
|
||||
local phosphor = require "assets.phosphor"
|
||||
|
||||
local cfg = {
|
||||
terminal = "wezterm",
|
||||
tags = {
|
||||
{
|
||||
layout = awful.layout.suit.floating,
|
||||
selected = true,
|
||||
icon = phosphor.house_fill
|
||||
},
|
||||
{
|
||||
layout = awful.layout.suit.floating,
|
||||
icon = phosphor.browser_fill
|
||||
},
|
||||
{
|
||||
layout = awful.layout.suit.tile.left,
|
||||
master_width_factor = 0.7,
|
||||
icon = phosphor.discord_logo_fill
|
||||
},
|
||||
{
|
||||
layout = awful.layout.suit.tile.top,
|
||||
master_width_factor = 0.2,
|
||||
icon = phosphor.spotify_logo_fill
|
||||
},
|
||||
{
|
||||
layout = awful.layout.suit.tile.right,
|
||||
master_width_factor = 0.7,
|
||||
icon = phosphor.code_fill
|
||||
},
|
||||
{
|
||||
layout = awful.layout.suit.floating,
|
||||
icon = phosphor.game_controller_fill
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
return cfg
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
local awful = require "awful"
|
||||
local beautiful = require "beautiful"
|
||||
local cfg = require "misc.cfg"
|
||||
local fresnel = require "ui.fresnel"
|
||||
local gtimer = require "gears.timer"
|
||||
local insightful = require "ui.insightful"
|
||||
local naughty = require "naughty"
|
||||
local playerctl = require "services.playerctl"
|
||||
local qbind = require "quarrel.bind"
|
||||
local qvars = require "quarrel.vars"
|
||||
local playerctl = require "services.playerctl"
|
||||
|
||||
local recording = { false, "" }
|
||||
|
||||
|
@ -120,7 +121,6 @@ awful.keyboard.append_global_keybindings {
|
|||
},
|
||||
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = "XF86AudioMute",
|
||||
press = function()
|
||||
awful.spawn("wpctl set-mute @DEFAULT_SINK@ toggle")
|
||||
|
@ -129,7 +129,6 @@ awful.keyboard.append_global_keybindings {
|
|||
desc = "mute"
|
||||
},
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = {
|
||||
{ "XF86AudioRaiseVolume", true },
|
||||
{ "XF86AudioLowerVolume", false }
|
||||
|
@ -145,7 +144,6 @@ awful.keyboard.append_global_keybindings {
|
|||
desc = "increase/decrease volume"
|
||||
},
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = {
|
||||
{ "XF86AudioNext", true },
|
||||
{ "XF86AudioPrev", false }
|
||||
|
@ -161,7 +159,6 @@ awful.keyboard.append_global_keybindings {
|
|||
desc = "previous/next song"
|
||||
},
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = "XF86AudioPlay",
|
||||
press = function()
|
||||
playerctl:play_pause()
|
||||
|
@ -171,7 +168,6 @@ awful.keyboard.append_global_keybindings {
|
|||
},
|
||||
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = {
|
||||
{ "XF86MonBrightnessUp", true },
|
||||
{ "XF86MonBrightnessDown", false }
|
||||
|
@ -198,7 +194,6 @@ awful.keyboard.append_global_keybindings {
|
|||
},
|
||||
|
||||
qbind:new {
|
||||
mods = {},
|
||||
triggers = "Print",
|
||||
press = function()
|
||||
local date = os.date("%Y%m%d_%H%M%S")
|
||||
|
@ -283,5 +278,15 @@ awful.keyboard.append_global_keybindings {
|
|||
press = awful.tag.viewnext,
|
||||
group = "tag",
|
||||
desc = "switch to next"
|
||||
},
|
||||
qbind:new {
|
||||
mods = qvars.mods.MC,
|
||||
triggers = "x",
|
||||
press = function()
|
||||
local tag = awful.screen.focused().selected_tag
|
||||
tag.master_width_factor = cfg.tags[tonumber(tag.name)].master_width_factor or beautiful.master_width_factor
|
||||
end,
|
||||
group = "tag",
|
||||
desc = "reset master width"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
local awful = require "awful"
|
||||
local gtable = require "gears.table"
|
||||
local insightful = require "ui.insightful"
|
||||
local qstore = require "quarrel.store"
|
||||
|
||||
local qbind = {}
|
||||
|
||||
qstore.bindings = {}
|
||||
|
||||
local function get_binding_function(trigger)
|
||||
if type(trigger) == "number" and trigger <= 5 and trigger > 0 then
|
||||
return "button"
|
||||
|
@ -37,7 +39,7 @@ local function translate_binding(binding, trigger, multiple)
|
|||
end
|
||||
|
||||
function qbind:new(binding)
|
||||
if not binding.hidden then table.insert(insightful._bindings, binding) end
|
||||
if not binding.hidden then table.insert(qstore.bindings, binding) end
|
||||
binding.mods = binding.mods or {}
|
||||
|
||||
local awful_bindings = {}
|
||||
|
|
|
@ -9,12 +9,14 @@ edition = "2021"
|
|||
freedesktop_entry_parser = "1.3.0"
|
||||
cpc = "1.9.1"
|
||||
mlua = { version = "0.8.7", features = [ "module", "lua54", "serialize" ] }
|
||||
palette = { version = "0.6.1", default-features = false, features = [ "std" ] }
|
||||
rayon = "1.6.1"
|
||||
serde = { version = "1.0.152", features = [ "derive" ] }
|
||||
url = "2.3.1"
|
||||
rodio = "0.17.1"
|
||||
nix = "0.26.2"
|
||||
chrono = "0.4.24"
|
||||
itertools = "0.10.5"
|
||||
html-escape = "0.2.13"
|
||||
|
||||
[lib]
|
||||
crate-type = ["cdylib"]
|
||||
|
|
|
@ -13,10 +13,6 @@ use crate::lenses::entry::{
|
|||
Entry,
|
||||
};
|
||||
|
||||
fn contains_ignore_ascii_case(a: &str, b: &str) -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn parse_entry(entry: &fd::Entry, path: &PathBuf) -> Result<Entry, ()> {
|
||||
let section = entry.section("Desktop Entry");
|
||||
let name = section.attr("Name").ok_or(())?.to_string();
|
||||
|
@ -84,7 +80,7 @@ pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
|
|||
Ok(entries_to_lua_table(
|
||||
parsed_entries
|
||||
.into_iter()
|
||||
.filter(|entry| entry.message.to_lowercase().contains(&input))
|
||||
.filter(|entry| entry.message.to_lowercase().contains(&input.to_lowercase()))
|
||||
.collect(),
|
||||
lua,
|
||||
))
|
||||
|
|
|
@ -2,6 +2,7 @@ mod lenses;
|
|||
mod net;
|
||||
|
||||
use mlua::prelude::*;
|
||||
use html_escape::decode_html_entities_to_string;
|
||||
|
||||
#[mlua::lua_module]
|
||||
fn qnative(lua: &Lua) -> LuaResult<LuaTable> {
|
||||
|
@ -12,6 +13,11 @@ fn qnative(lua: &Lua) -> LuaResult<LuaTable> {
|
|||
let exports = lua.create_table()?;
|
||||
exports.set("lenses", lenses)?;
|
||||
exports.set("get_essid", lua.create_function(net::get_first_essid)?)?;
|
||||
exports.set("decode_html", lua.create_function(|_: &Lua, string: String| {
|
||||
let mut output = String::new();
|
||||
decode_html_entities_to_string(string, &mut output);
|
||||
Ok(output)
|
||||
})?)?;
|
||||
|
||||
Ok(exports)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ use std::{
|
|||
},
|
||||
mem::size_of,
|
||||
os::fd::RawFd,
|
||||
str,
|
||||
};
|
||||
|
||||
use mlua::prelude::*;
|
||||
|
@ -23,7 +22,7 @@ use nix::{
|
|||
SockFlag,
|
||||
SockType,
|
||||
},
|
||||
unistd::close
|
||||
unistd::close,
|
||||
};
|
||||
use wireless::{
|
||||
IfConf,
|
||||
|
@ -59,6 +58,7 @@ pub fn get_first_essid(_: &Lua, _: ()) -> LuaResult<String> {
|
|||
if_req = if_conf.data.ifc_req;
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
for _ in 0..if_conf.ifc_len / size_of::<IfConf>() as c_int {
|
||||
if let Ok(essid) = get_essid(socket, unsafe { *if_req }.ifr_name) {
|
||||
close(socket).map_err(LuaError::external)?;
|
||||
|
@ -90,9 +90,7 @@ fn get_essid(socket: RawFd, if_name: [c_char; IF_NAMESIZE]) -> LuaResult<String>
|
|||
ioctl_get_essid(socket, &mut wrq).map_err(LuaError::external)?;
|
||||
}
|
||||
|
||||
Ok(str::from_utf8(essid.as_slice())
|
||||
.map_err(LuaError::external)?
|
||||
.to_owned())
|
||||
String::from_utf8(essid.to_vec()).map_err(LuaError::external)
|
||||
}
|
||||
|
||||
fn get_first_socket() -> LuaResult<RawFd> {
|
||||
|
|
75
.config/awesome/quarrel/native/src/time.rs
Normal file
|
@ -0,0 +1,75 @@
|
|||
use chrono::prelude::*;
|
||||
use mlua::{
|
||||
prelude::*,
|
||||
LuaSerdeExt,
|
||||
};
|
||||
|
||||
// Taken from https://github.com/chronotope/chrono/issues/69#issuecomment-1510506428
|
||||
trait NaiveDateExt {
|
||||
fn days_in_month(&self) -> u32;
|
||||
fn days_in_year(&self) -> u32;
|
||||
fn is_leap_year(&self) -> bool;
|
||||
}
|
||||
|
||||
impl NaiveDateExt for NaiveDate {
|
||||
fn days_in_month(&self) -> u32 {
|
||||
let month = self.month();
|
||||
match month {
|
||||
1 | 3 | 5 | 7 | 8 | 10 | 12 => 31,
|
||||
4 | 6 | 9 | 11 => 30,
|
||||
2 => {
|
||||
if self.is_leap_year() {
|
||||
29
|
||||
} else {
|
||||
28
|
||||
}
|
||||
}
|
||||
_ => panic!("Invalid month: {}", month),
|
||||
}
|
||||
}
|
||||
|
||||
fn days_in_year(&self) -> u32 {
|
||||
if self.is_leap_year() {
|
||||
366
|
||||
} else {
|
||||
365
|
||||
}
|
||||
}
|
||||
|
||||
fn is_leap_year(&self) -> bool {
|
||||
let year = self.year();
|
||||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
}
|
||||
|
||||
struct Day {
|
||||
day: u32,
|
||||
ce: bool,
|
||||
weekday: Weekday,
|
||||
}
|
||||
|
||||
pub fn get_calendar_table(lua: &Lua, (year, month, day): (i32, u32, u32)) -> LuaResult<LuaTable> {
|
||||
let date =
|
||||
NaiveDate::from_ymd_opt(year, month, day).ok_or(LuaError::external("invalid date"))?;
|
||||
let days: Vec<Day> = (1..=date.days_in_month())
|
||||
.map(|day| NaiveDate::from_ymd_opt(date.year(), date.month(), day).unwrap())
|
||||
.map(|date| {
|
||||
let (ce, year) = date.year_ce();
|
||||
Day {
|
||||
day: date.day(),
|
||||
ce,
|
||||
weekday: date.weekday(),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let calendar: Vec<Vec<Day>> = vec![vec![], vec![], vec![], vec![], vec![], vec![], vec![]];
|
||||
|
||||
if days[1].weekday != Weekday::Mon {
|
||||
get_calendar_table(lua)
|
||||
}
|
||||
|
||||
if days.last().unwrap().weekday != Weekday::Sun {}
|
||||
|
||||
Ok(lua.create_table()?)
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
local gtimer = require "gears.timer"
|
||||
|
||||
local qservice = {}
|
||||
|
||||
function qservice.register(name, service, icon)
|
||||
gtimer {
|
||||
timeout = 1,
|
||||
call_now = true,
|
||||
autostart = true,
|
||||
callback = function()
|
||||
local service_result = table.pack(service())
|
||||
awesome.emit_signal("services::" .. name, table.unpack(service_result))
|
||||
awesome.emit_signal("services::" .. name .. "::icon", icon(table.unpack(service_result)))
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
return qservice
|
3
.config/awesome/quarrel/store.lua
Normal file
|
@ -0,0 +1,3 @@
|
|||
local qstore = {}
|
||||
|
||||
return qstore
|
|
@ -1,5 +1,6 @@
|
|||
local awful = require "awful"
|
||||
local gears = require "gears"
|
||||
local gtable = require "gears.table"
|
||||
local qbind = require "quarrel.bind"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
|
@ -17,12 +18,8 @@ function qui.font(factor)
|
|||
return qvars.text_font .. " " .. qvars.font_size * (factor or 1)
|
||||
end
|
||||
|
||||
function qui.symbol_font(factor)
|
||||
return qvars.symbol_font .. " " .. qvars.font_size * (factor or 1)
|
||||
end
|
||||
|
||||
function qui.styled(target)
|
||||
return gears.table.crush({
|
||||
return gtable.crush({
|
||||
bg = qvars.colors.bg,
|
||||
border_color = qvars.colors.bright.black,
|
||||
border_width = qvars.border_width,
|
||||
|
@ -30,14 +27,14 @@ function qui.styled(target)
|
|||
}, target)
|
||||
end
|
||||
|
||||
function qui.popup(args)
|
||||
args.widget = {
|
||||
function qui.popup(target)
|
||||
target.widget = {
|
||||
widget = wibox.container.margin,
|
||||
margins = qvars.big_padding,
|
||||
args.widget
|
||||
target.widget
|
||||
}
|
||||
|
||||
return awful.popup(qui.styled(args))
|
||||
return awful.popup(qui.styled(target))
|
||||
end
|
||||
|
||||
function qui.tooltip(objects, callback)
|
||||
|
@ -49,4 +46,78 @@ function qui.tooltip(objects, callback)
|
|||
})
|
||||
end
|
||||
|
||||
function qui.recolor(color)
|
||||
return "svg{fill:" .. color .. "}"
|
||||
end
|
||||
|
||||
function qui.icon(image, color, target)
|
||||
local widget = {
|
||||
widget = wibox.widget.imagebox,
|
||||
image = image,
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height,
|
||||
stylesheet = qui.recolor(color or qvars.colors.fg)
|
||||
}
|
||||
if target then
|
||||
return gtable.crush(widget, target)
|
||||
else
|
||||
return widget
|
||||
end
|
||||
end
|
||||
|
||||
function qui.button(args)
|
||||
args.press = args.press or function(_) end
|
||||
local widget = wibox.widget(gtable.crush({
|
||||
widget = wibox.widget.imagebox,
|
||||
image = args.image,
|
||||
forced_height = qvars.char_height,
|
||||
forced_width = qvars.char_height,
|
||||
stylesheet = qui.recolor(qvars.colors.fg),
|
||||
press = args.press
|
||||
}, args.widget or {}))
|
||||
|
||||
widget.buttons = {
|
||||
qbind:new {
|
||||
triggers = qvars.btns.left,
|
||||
press = function()
|
||||
widget:press()
|
||||
end,
|
||||
hidden = true
|
||||
}
|
||||
}
|
||||
|
||||
return widget
|
||||
end
|
||||
|
||||
function qui.toggle(args)
|
||||
args.press = args.press or function(_) end
|
||||
local widget = qui.button({
|
||||
widget = gtable.crush({
|
||||
toggled = false,
|
||||
silent_press = function(self, state)
|
||||
if state then
|
||||
self.toggled = state
|
||||
else
|
||||
self.toggled = not self.toggled
|
||||
end
|
||||
|
||||
if self.toggled then
|
||||
self.image = args.on
|
||||
else
|
||||
self.image = args.off
|
||||
end
|
||||
end,
|
||||
}, args.widget or {}),
|
||||
image = args.off,
|
||||
press = function(self)
|
||||
if not args.manual then
|
||||
self:silent_press()
|
||||
end
|
||||
args.press(self)
|
||||
end
|
||||
})
|
||||
|
||||
return widget
|
||||
end
|
||||
|
||||
return qui
|
||||
|
|
|
@ -22,7 +22,6 @@ qvars.padding = dpi(4)
|
|||
qvars.big_padding = dpi(8)
|
||||
|
||||
qvars.text_font = "Fira Code Nerd Font Mono Medium"
|
||||
qvars.symbol_font = "Symbols Nerd Font:style=1000-em"
|
||||
qvars.font_size = 8
|
||||
qvars.font = qvars.text_font .. " " .. qvars.font_size
|
||||
|
||||
|
@ -35,7 +34,6 @@ qvars.char_height = char_height
|
|||
qvars.char_width = char_width
|
||||
|
||||
qvars.bar_size = dpi(24) + qvars.big_padding * 2
|
||||
-- qvars.expanded_bar_size = qvars.bar_size * 6
|
||||
qvars.element_size = dpi(12)
|
||||
qvars.expanded_bar_size = qvars.big_padding + (qvars.big_padding * 2 + qvars.element_size * 4) * 3 + qvars.padding * 2
|
||||
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
pcall(require, "luarocks.loader")
|
||||
-- --
|
||||
-- ___ ___ ___ ___ ___ ___ ___ ___ --
|
||||
-- /\ \ /\ \ /\ \ /\ \ /\__\ /\ \ /\ \ /\ \ --
|
||||
-- /::\ \ /::\ \ _\:\ \ /::\ \ /::L_L_ _\:\ \ \:\ \ /::\ \ --
|
||||
-- /::\:\__\ /::\:\__\ /\/::\__\ /\:\:\__\ /:/L:\__\ /\/::\__\ /::\__\ /::\:\__\ --
|
||||
-- \/\::/ / \;:::/ / \::/\/__/ \:\:\/__/ \/_/:/ / \::/\/__/ /:/\/__/ \:\:\/ / --
|
||||
-- \/__/ |:\/__/ \:\__\ \::/ / /:/ / \:\__\ \/__/ \:\/ / --
|
||||
-- \|__| \/__/ \/__/ \/__/ \/__/ \/__/ --
|
||||
-- --
|
||||
---=-=-=-=-=-=-=-=-=-=-=-= A colourful and comfy AWM theme =-=-=-=-=-=-=-=-=-=-=-=---
|
||||
|
||||
-- ___ ___ ___ ___ ___ ___ ___ ___
|
||||
-- /\ \ /\ \ /\ \ /\ \ /\__\ /\ \ /\ \ /\ \
|
||||
-- /::\ \ /::\ \ _\:\ \ /::\ \ /::L_L_ _\:\ \ \:\ \ /::\ \
|
||||
-- /::\:\__\ /::\:\__\ /\/::\__\ /\:\:\__\ /:/L:\__\ /\/::\__\ /::\__\ /::\:\__\
|
||||
-- \/\::/ / \;:::/ / \::/\/__/ \:\:\/__/ \/_/:/ / \::/\/__/ /:/\/__/ \:\:\/ /
|
||||
-- \/__/ |:\/__/ \:\__\ \::/ / /:/ / \:\__\ \/__/ \:\/ /
|
||||
-- \|__| \/__/ \/__/ \/__/ \/__/ \/__/
|
||||
--
|
||||
--=-=-=-=-=-=-=-=-=-=-=-= A colorful and comfy AWM theme =-=-=-=-=-=-=-=-=-=-=-=--
|
||||
pcall(require, "luarocks.loader")
|
||||
|
||||
require("beautiful").init(require("gears.filesystem").get_configuration_dir() .. "/prismite.lua")
|
||||
|
||||
|
|
|
@ -1,24 +1,51 @@
|
|||
local qfs = require "quarrel.fs"
|
||||
local gfs = require "gears.filesystem"
|
||||
local qservice = require "quarrel.service"
|
||||
local qjson = require "quarrel.json"
|
||||
local qnative = require "quarrel.native"
|
||||
local gcolor = require "gears.color"
|
||||
local qmath = require "quarrel.math"
|
||||
local gtimer = require "gears.timer"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qfs = require "quarrel.fs"
|
||||
local qjson = require "quarrel.json"
|
||||
local qmath = require "quarrel.math"
|
||||
local qnative = require "quarrel.native"
|
||||
local qstore = require "quarrel.store"
|
||||
local qvars = require "quarrel.vars"
|
||||
|
||||
local q = require "quarrel"
|
||||
|
||||
local function register(name, service, icon)
|
||||
gtimer {
|
||||
timeout = 0.5,
|
||||
call_now = true,
|
||||
autostart = true,
|
||||
callback = function()
|
||||
local service_result = table.pack(service())
|
||||
awesome.emit_signal("services::" .. name, table.unpack(service_result))
|
||||
awesome.emit_signal("services::" .. name .. "::icon", icon(table.unpack(service_result)))
|
||||
end
|
||||
}
|
||||
end
|
||||
|
||||
local function read(file, format)
|
||||
local content = file:read(format or "a")
|
||||
file:seek("set")
|
||||
return content
|
||||
end
|
||||
|
||||
-- create file in case it's not there yet
|
||||
if not gfs.file_readable("/tmp/wp_audio_status") then
|
||||
assert(io.open("/tmp/wp_audio_status", "w")):write("{}"):close()
|
||||
end
|
||||
qstore.audio_file = assert(io.open("/tmp/wp_audio_status", "r"))
|
||||
qstore.battery_capacity_file = assert(io.open("/sys/class/power_supply/BAT0/capacity", "r"))
|
||||
qstore.battery_status_file = assert(io.open("/sys/class/power_supply/BAT0/status", "r"))
|
||||
qstore.brightness_file = assert(io.open("/sys/class/backlight/amdgpu_bl0/actual_brightness", "r"))
|
||||
qstore.wifi_file = assert(io.open("/proc/net/wireless", "r"))
|
||||
|
||||
-- follows the format `service = { provider, icon_provider }`
|
||||
local services = {
|
||||
audio = {
|
||||
-- volume, muted
|
||||
function()
|
||||
if not gfs.file_readable("/tmp/wp_audio_status") then
|
||||
awesome.emit_signal("services::audio", -1, false)
|
||||
return
|
||||
end
|
||||
local audio_status = qjson.decode(qfs.read("/tmp/wp_audio_status"))
|
||||
local default_sink = audio_status["alsa_output.usb-046d_G435_Wireless_Gaming_Headset_V001008005.1-01.analog-stereo"]
|
||||
local audio_status = qjson.decode(read(qstore.audio_file))
|
||||
local default_sink = audio_status["G435 Wireless Gaming Headset Analog Stereo"]
|
||||
|
||||
if not default_sink then
|
||||
return nil, false
|
||||
|
@ -28,7 +55,7 @@ local services = {
|
|||
end,
|
||||
function(volume, muted)
|
||||
if muted or not volume then
|
||||
return gcolor.recolor_image(phosphor["speaker_simple_x_fill"], qvars.colors.red)
|
||||
return phosphor.speaker_simple_x_fill, qvars.colors.red
|
||||
end
|
||||
|
||||
local icon_data = qmath.step_value(volume, {
|
||||
|
@ -39,13 +66,13 @@ local services = {
|
|||
{ 100 }
|
||||
})
|
||||
|
||||
gcolor.recolor_image(phosphor["speaker_simple_" .. icon_data .. "_fill"], qvars.colors.fg)
|
||||
return phosphor["speaker_simple_" .. icon_data .. "_fill"], qvars.colors.fg
|
||||
end
|
||||
},
|
||||
battery = {
|
||||
-- capacity, status
|
||||
function()
|
||||
return qfs.read("/sys/class/power_supply/BAT0/capacity", "n"), qfs.read("/sys/class/power_supply/BAT0/status", "l")
|
||||
return read(qstore.battery_capacity_file, "n"), read(qstore.battery_status_file, "l")
|
||||
end,
|
||||
function(capacity, status)
|
||||
local icon_data = status == "Charging" and { "charging", "green" } or qmath.step_value(capacity, {
|
||||
|
@ -57,13 +84,13 @@ local services = {
|
|||
{ 100 }
|
||||
})
|
||||
|
||||
return gcolor.recolor_image(phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
|
||||
return phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]]
|
||||
end
|
||||
},
|
||||
brightness = {
|
||||
-- brightness
|
||||
function()
|
||||
return qfs.read("/sys/class/backlight/amdgpu_bl0/actual_brightness", "n")
|
||||
return read(qstore.brightness_file, "n")
|
||||
end,
|
||||
function(brightness)
|
||||
local icon_data = qmath.step_value(brightness, {
|
||||
|
@ -75,7 +102,7 @@ local services = {
|
|||
{ 255 }
|
||||
})
|
||||
|
||||
return gcolor.recolor_image(phosphor[icon_data .. "_fill"], qvars.colors.fg)
|
||||
return phosphor[icon_data .. "_fill"], qvars.colors.fg
|
||||
end
|
||||
},
|
||||
wifi = {
|
||||
|
@ -83,9 +110,10 @@ local services = {
|
|||
function()
|
||||
local lines = {}
|
||||
|
||||
for line in io.lines("/proc/net/wireless") do
|
||||
for line in qstore.wifi_file:lines() do
|
||||
table.insert(lines, line)
|
||||
end
|
||||
qstore.wifi_file:seek("set")
|
||||
|
||||
if not lines[3] then
|
||||
return nil, 0, false
|
||||
|
@ -97,7 +125,7 @@ local services = {
|
|||
end,
|
||||
function(_, strength, connected)
|
||||
if not connected then
|
||||
return gcolor.recolor_image(phosphor.wifi_x_fill, qvars.colors.red)
|
||||
return phosphor.wifi_x_fill, qvars.colors.red
|
||||
end
|
||||
|
||||
local icon_data = qmath.step_value(strength, {
|
||||
|
@ -108,11 +136,11 @@ local services = {
|
|||
{ 100 }
|
||||
})
|
||||
|
||||
return gcolor.recolor_image(phosphor["wifi_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
|
||||
return phosphor["wifi_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]]
|
||||
end
|
||||
}
|
||||
}
|
||||
|
||||
for name, service in pairs(services) do
|
||||
qservice.register(name, service[1], service[2])
|
||||
register(name, service[1], service[2])
|
||||
end
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require "services.playerctl"
|
||||
require "services.common"
|
||||
require "services.playerctl"
|
||||
|
|
|
@ -1,40 +1,40 @@
|
|||
local playerctl = require "lib.bling.signal.playerctl".lib {
|
||||
player = { "spotify", "ncmpcpp", "%any" }
|
||||
player = { "spotify", "%any" }
|
||||
}
|
||||
|
||||
playerctl:connect_signal("metadata", function(...)
|
||||
playerctl:connect_signal("metadata", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::metadata", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("position", function(...)
|
||||
playerctl:connect_signal("position", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::position", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("playback_status", function(...)
|
||||
playerctl:connect_signal("playback_status", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::playback_status", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("seeked", function(...)
|
||||
playerctl:connect_signal("seeked", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::seeked", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("volume", function(...)
|
||||
playerctl:connect_signal("volume", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::volume", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("loop_status", function(...)
|
||||
playerctl:connect_signal("loop_status", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::loop_status", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("shuffle", function(...)
|
||||
playerctl:connect_signal("shuffle", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::shuffle", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("exit", function(...)
|
||||
playerctl:connect_signal("exit", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::exit", ...)
|
||||
end)
|
||||
|
||||
playerctl:connect_signal("exit", function(...)
|
||||
playerctl:connect_signal("exit", function(_, ...)
|
||||
awesome.emit_signal("services::playerctl::exit", ...)
|
||||
end)
|
||||
|
||||
|
|
|
@ -1,56 +1,11 @@
|
|||
local awful = require "awful"
|
||||
local cfg = require "misc.cfg"
|
||||
local gtable = require "gears.table"
|
||||
|
||||
screen.connect_signal("request::desktop_decoration", function(s)
|
||||
awful.tag.add(
|
||||
"1",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.floating,
|
||||
selected = true
|
||||
}
|
||||
)
|
||||
|
||||
awful.tag.add(
|
||||
"2",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.floating,
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
awful.tag.add(
|
||||
"3",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.tile.left,
|
||||
master_width_factor = 0.7
|
||||
}
|
||||
)
|
||||
|
||||
awful.tag.add(
|
||||
"4",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.tile.top,
|
||||
master_width_factor = 0.2
|
||||
}
|
||||
)
|
||||
|
||||
awful.tag.add(
|
||||
"5",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.tile.right,
|
||||
master_width_factor = 0.7
|
||||
}
|
||||
)
|
||||
|
||||
awful.tag.add(
|
||||
"6",
|
||||
{
|
||||
screen = s,
|
||||
layout = awful.layout.suit.floating,
|
||||
}
|
||||
)
|
||||
for i, tag in ipairs(cfg.tags) do
|
||||
awful.tag.add(tostring(i), gtable.crush({
|
||||
screen = s
|
||||
}, tag))
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -25,7 +25,11 @@ fresnel._selected_index = 1
|
|||
function fresnel:_exec_entry(entry_index)
|
||||
local exec = self._entries_exec[entry_index]
|
||||
if type(exec) ~= "userdata" and type(exec) ~= "nil" then
|
||||
awful.spawn((exec[2] and cfg.terminal .. " -e " or "") .. exec[1])
|
||||
if exec[2] then
|
||||
awful.spawn(cfg.terminal .. " -e /bin/sh -c " .. exec[1] .. " 1>/dev/null 2>&1")
|
||||
else
|
||||
awful.spawn.with_shell(exec[1] .. " 1>/dev/null 2>&1")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
local awful = require "awful"
|
||||
local beautiful = require "beautiful"
|
||||
local gtable = require "gears.table"
|
||||
local qstore = require "quarrel.store"
|
||||
local qtable = require "quarrel.table"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
|
@ -14,7 +14,6 @@ local mouse = " "
|
|||
local insightful = {}
|
||||
|
||||
insightful._toggled = false
|
||||
insightful._bindings = {}
|
||||
insightful._selected_group = ""
|
||||
insightful._selected_group_index = 1
|
||||
|
||||
|
@ -91,7 +90,7 @@ function insightful:_generate()
|
|||
local grouped_binds = {}
|
||||
local layout_container = insightful._widget.widget.layout_container
|
||||
|
||||
for _, keybind in ipairs(self._bindings) do
|
||||
for _, keybind in ipairs(qstore.bindings) do
|
||||
local group = keybind.group or "general"
|
||||
local group_exists = grouped_binds[group] ~= nil
|
||||
|
||||
|
|
|
@ -9,13 +9,10 @@ local qvars = require "quarrel.vars"
|
|||
local rubato = require "lib.rubato"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local battery = require "ui.statusbar.widgets.battery"
|
||||
local brightness = require "ui.statusbar.widgets.brightness"
|
||||
local clock = require "ui.statusbar.widgets.clock"
|
||||
local displays = require "ui.statusbar.widgets.displays"
|
||||
local keyboardlayout = require "ui.statusbar.widgets.keyboardlayout"
|
||||
local taglist = require "ui.statusbar.widgets.taglist"
|
||||
local volume = require "ui.statusbar.widgets.volume"
|
||||
local wifi = require "ui.statusbar.widgets.wifi"
|
||||
|
||||
screen.connect_signal("request::desktop_decoration", function(s)
|
||||
local expand_button = wibox.widget {
|
||||
|
@ -52,10 +49,10 @@ screen.connect_signal("request::desktop_decoration", function(s)
|
|||
widget = wibox.container.place,
|
||||
valign = "bottom",
|
||||
{
|
||||
brightness,
|
||||
volume,
|
||||
battery,
|
||||
wifi,
|
||||
displays.brightness,
|
||||
displays.audio,
|
||||
displays.battery,
|
||||
displays.wifi,
|
||||
{
|
||||
widget = wibox.container.place,
|
||||
keyboardlayout
|
||||
|
|
|
@ -2,14 +2,11 @@ local qvars = require "quarrel.vars"
|
|||
local wibox = require "wibox"
|
||||
|
||||
local displays = require "ui.statusbar.panel.widgets.displays"
|
||||
local music = require "ui.statusbar.panel.widgets.music"
|
||||
local power_menu = require "ui.statusbar.panel.widgets.power_menu"
|
||||
|
||||
local wifi = require "ui.statusbar.panel.widgets.wifi"
|
||||
|
||||
local panel = wibox.widget {
|
||||
-- widget = wibox.container.constraint,
|
||||
-- width = qvars.expanded_bar_size,
|
||||
-- strategy = "exact",
|
||||
-- {
|
||||
widget = wibox.container.margin,
|
||||
margins = {
|
||||
left = qvars.big_padding
|
||||
|
@ -18,12 +15,18 @@ local panel = wibox.widget {
|
|||
{
|
||||
widget = wibox.container.place,
|
||||
valign = "top",
|
||||
{
|
||||
{
|
||||
displays.battery,
|
||||
displays.volume,
|
||||
displays.audio,
|
||||
displays.brightness,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
spacing = qvars.padding,
|
||||
},
|
||||
wifi,
|
||||
music,
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
spacing = qvars.padding
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -40,7 +43,6 @@ local panel = wibox.widget {
|
|||
},
|
||||
layout = wibox.layout.align.vertical,
|
||||
}
|
||||
-- }
|
||||
}
|
||||
|
||||
return panel
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
local qmath = require "quarrel.math"
|
||||
local qvars = require "quarrel.vars"
|
||||
local qui = require "quarrel.ui"
|
||||
local wibox = require "wibox"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local gcolor = require "gears.color"
|
||||
local qmath = require "quarrel.math"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local function create_display(icon, color)
|
||||
return wibox.widget(qui.styled {
|
||||
|
@ -24,13 +23,7 @@ local function create_display(icon, color)
|
|||
forced_width = qvars.element_size * 4,
|
||||
{
|
||||
widget = wibox.container.place,
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = icon,
|
||||
forced_height = qvars.char_height,
|
||||
forced_width = qvars.char_height,
|
||||
id = "icon"
|
||||
}
|
||||
qui.icon(icon, color, { id = "icon" })
|
||||
},
|
||||
id = "indicator"
|
||||
},
|
||||
|
@ -50,55 +43,40 @@ local function create_display(icon, color)
|
|||
})
|
||||
end
|
||||
|
||||
local d_battery = create_display(gcolor.recolor_image(phosphor.battery_vertical_warning_fill, qvars.colors.fg), qvars.colors.red)
|
||||
|
||||
awesome.connect_signal("services::battery", function(capacity, status)
|
||||
local icon_data = status == "Charging" and { "charging", "green" } or qmath.step_value(capacity, {
|
||||
{ 0, { "empty", "red" } },
|
||||
{ 20, { "low", "red" } },
|
||||
{ 40, { "medium", "yellow" } },
|
||||
{ 60, { "high", "green" } },
|
||||
{ 80, { "full", "green" } },
|
||||
{ 100 }
|
||||
})
|
||||
|
||||
d_battery:get_children_by_id("indicator")[1].color = qvars.colors[icon_data[2]]
|
||||
d_battery:get_children_by_id("indicator")[1].value = capacity
|
||||
d_battery:get_children_by_id("icon")[1].image = gcolor.recolor_image(phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
|
||||
|
||||
d_battery:get_children_by_id("text")[1].text = capacity .. "%"
|
||||
end)
|
||||
|
||||
local d_volume = create_display(gcolor.recolor_image(phosphor.speaker_simple_high_fill, qvars.colors.fg), qvars.colors.fg)
|
||||
|
||||
awesome.connect_signal("services::audio", function(volume, muted)
|
||||
d_volume:get_children_by_id("indicator")[1].value = math.min(volume, 100)
|
||||
d_volume:get_children_by_id("text")[1].text = volume .. "%"
|
||||
|
||||
if muted then
|
||||
d_volume:get_children_by_id("icon")[1].image = gcolor.recolor_image(phosphor["speaker_simple_x_fill"], qvars.colors.red)
|
||||
local d_audio = create_display(phosphor.speaker_simple_high_fill, qvars.colors.fg)
|
||||
awesome.connect_signal("services::audio", function(volume)
|
||||
if not volume then
|
||||
return
|
||||
end
|
||||
|
||||
local icon_data = qmath.step_value(volume, {
|
||||
{ 0, "slash" },
|
||||
{ 25, "none" },
|
||||
{ 50, "low" },
|
||||
{ 75, "high" },
|
||||
{ 100 }
|
||||
})
|
||||
|
||||
d_volume:get_children_by_id("icon")[1].image = gcolor.recolor_image(phosphor["speaker_simple_" .. icon_data .. "_fill"], qvars.colors.fg)
|
||||
d_audio:get_children_by_id("indicator")[1].value = math.min(volume, 100)
|
||||
d_audio:get_children_by_id("text")[1].text = volume .. "%"
|
||||
end)
|
||||
awesome.connect_signal("services::audio::icon", function(icon, color)
|
||||
d_audio:get_children_by_id("indicator")[1].color = color
|
||||
d_audio:get_children_by_id("icon")[1].image = icon
|
||||
d_audio:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
local d_brightness = create_display(gcolor.recolor_image(phosphor.sun_fill, qvars.colors.fg), qvars.colors.fg)
|
||||
local d_battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
|
||||
awesome.connect_signal("services::battery", function(capacity)
|
||||
d_battery:get_children_by_id("indicator")[1].value = capacity
|
||||
d_battery:get_children_by_id("text")[1].text = capacity .. "%"
|
||||
end)
|
||||
awesome.connect_signal("services::battery::icon", function(icon, color)
|
||||
d_battery:get_children_by_id("indicator")[1].color = color
|
||||
d_battery:get_children_by_id("icon")[1].image = icon
|
||||
d_battery:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
local d_brightness = create_display(phosphor.sun_fill, qvars.colors.fg)
|
||||
awesome.connect_signal("services::brightness", function(brightness)
|
||||
brightness = math.floor(qmath.translate_range(brightness, 0, 255, 0, 100))
|
||||
|
||||
d_brightness:get_children_by_id("indicator")[1].value = brightness
|
||||
|
||||
d_brightness:get_children_by_id("text")[1].text = brightness .. "%"
|
||||
end)
|
||||
awesome.connect_signal("services::brightness::icon", function(icon, color)
|
||||
d_brightness:get_children_by_id("icon")[1].image = icon
|
||||
d_brightness:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
return { battery = d_battery, volume = d_volume, brightness = d_brightness }
|
||||
return { audio = d_audio, battery = d_battery, brightness = d_brightness }
|
||||
|
|
706
.config/awesome/ui/statusbar/panel/widgets/imagebox.lua
Normal file
|
@ -0,0 +1,706 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A widget to display an image.
|
||||
--
|
||||
-- The `wibox.widget.imagebox` is part of the Awesome WM's widget system
|
||||
-- (see @{03-declarative-layout.md}).
|
||||
--
|
||||
-- This widget displays an image. The image can be a file,
|
||||
-- a cairo image surface, or an rsvg handle object (see the
|
||||
-- [image property](#image)).
|
||||
--
|
||||
-- Examples using a `wibox.widget.imagebox`:
|
||||
-- ---
|
||||
--
|
||||
-- @DOC_wibox_widget_defaults_imagebox_EXAMPLE@
|
||||
--
|
||||
-- Alternatively, you can declare the `imagebox` widget using the
|
||||
-- declarative pattern (both variants are strictly equivalent):
|
||||
--
|
||||
-- @DOC_wibox_widget_declarative-pattern_imagebox_EXAMPLE@
|
||||
--
|
||||
-- @author Uli Schlachter
|
||||
-- @copyright 2010 Uli Schlachter
|
||||
-- @widgetmod wibox.widget.imagebox
|
||||
-- @supermodule wibox.widget.base
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local lgi = require("lgi")
|
||||
local cairo = lgi.cairo
|
||||
|
||||
local base = require("wibox.widget.base")
|
||||
local surface = require("gears.surface")
|
||||
local gtable = require("gears.table")
|
||||
local gdebug = require("gears.debug")
|
||||
local setmetatable = setmetatable
|
||||
local type = type
|
||||
local math = math
|
||||
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
|
||||
-- Safe load for optional Rsvg module
|
||||
local Rsvg = nil
|
||||
do
|
||||
local success, err = pcall(function() Rsvg = lgi.Rsvg end)
|
||||
if not success then
|
||||
gdebug.print_warning(debug.traceback("Could not load Rsvg: " .. tostring(err)))
|
||||
end
|
||||
end
|
||||
|
||||
local imagebox = { mt = {} }
|
||||
|
||||
local rsvg_handle_cache = setmetatable({}, { __mode = 'k' })
|
||||
|
||||
---Load rsvg handle form image file
|
||||
-- @tparam string file Path to svg file.
|
||||
-- @return Rsvg handle
|
||||
-- @treturn table A table where cached data can be stored.
|
||||
local function load_rsvg_handle(file)
|
||||
if not Rsvg then return end
|
||||
|
||||
local cache = (rsvg_handle_cache[file] or {})["handle"]
|
||||
|
||||
if cache then
|
||||
return cache, rsvg_handle_cache[file]
|
||||
end
|
||||
|
||||
local handle, err
|
||||
|
||||
if file:match("<[?]?xml") or file:match("<svg") then
|
||||
handle, err = Rsvg.Handle.new_from_data(file)
|
||||
else
|
||||
handle, err = Rsvg.Handle.new_from_file(file)
|
||||
end
|
||||
|
||||
if not err then
|
||||
rsvg_handle_cache[file] = rsvg_handle_cache[file] or {}
|
||||
rsvg_handle_cache[file]["handle"] = handle
|
||||
return handle, rsvg_handle_cache[file]
|
||||
end
|
||||
end
|
||||
|
||||
---Apply cairo surface for given imagebox widget
|
||||
local function set_surface(ib, surf)
|
||||
local is_surf_valid = surf.width > 0 and surf.height > 0
|
||||
if not is_surf_valid then return false end
|
||||
|
||||
ib._private.default = { width = surf.width, height = surf.height }
|
||||
ib._private.handle = nil
|
||||
ib._private.image = surf
|
||||
return true
|
||||
end
|
||||
|
||||
---Apply RsvgHandle for given imagebox widget
|
||||
local function set_handle(ib, handle, cache)
|
||||
local dim = handle:get_dimensions()
|
||||
local is_handle_valid = dim.width > 0 and dim.height > 0
|
||||
if not is_handle_valid then return false end
|
||||
|
||||
ib._private.default = { width = dim.width, height = dim.height }
|
||||
ib._private.handle = handle
|
||||
ib._private.cache = cache
|
||||
ib._private.image = nil
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
---Try to load some image object from file then apply it to imagebox.
|
||||
---@tparam table ib Imagebox
|
||||
---@tparam string file Image file name
|
||||
---@tparam function image_loader Function to load image object from file
|
||||
---@tparam function image_setter Function to set image object to imagebox
|
||||
---@treturn boolean True if image was successfully applied
|
||||
local function load_and_apply(ib, file, image_loader, image_setter)
|
||||
local image_applied
|
||||
local object, cache = image_loader(file)
|
||||
|
||||
if object then
|
||||
image_applied = image_setter(ib, object, cache)
|
||||
end
|
||||
return image_applied
|
||||
end
|
||||
|
||||
---Update the cached size depending on the stylesheet and dpi.
|
||||
--
|
||||
-- It's necessary because a single RSVG handle can be used by
|
||||
-- many imageboxes. So DPI and Stylesheet need to be set each time.
|
||||
local function update_dpi(self, ctx)
|
||||
if not self._private.handle then return end
|
||||
|
||||
local dpi = self._private.auto_dpi and
|
||||
ctx.dpi or
|
||||
self._private.dpi or
|
||||
nil
|
||||
|
||||
local need_dpi = dpi and
|
||||
self._private.last_dpi ~= dpi
|
||||
|
||||
local need_style = self._private.handle.set_stylesheet and
|
||||
self._private.stylesheet
|
||||
|
||||
local old_size = self._private.default and self._private.default.width
|
||||
|
||||
if dpi and dpi ~= self._private.cache.dpi then
|
||||
if type(dpi) == "table" then
|
||||
self._private.handle:set_dpi_x_y(dpi.x, dpi.y)
|
||||
else
|
||||
self._private.handle:set_dpi(dpi)
|
||||
end
|
||||
end
|
||||
|
||||
if need_style and self._private.cache.stylesheet ~= self._private.stylesheet then
|
||||
self._private.handle:set_stylesheet(self._private.stylesheet)
|
||||
end
|
||||
|
||||
-- Reload the size.
|
||||
if need_dpi or (need_style and self._private.stylesheet ~= self._private.last_stylesheet) then
|
||||
set_handle(self, self._private.handle, self._private.cache)
|
||||
end
|
||||
|
||||
self._private.last_dpi = dpi
|
||||
self._private.cache.dpi = dpi
|
||||
self._private.last_stylesheet = self._private.stylesheet
|
||||
self._private.cache.stylesheet = self._private.stylesheet
|
||||
|
||||
-- This can happen in the constructor when `dpi` is set after `image`.
|
||||
if old_size and old_size ~= self._private.default.width then
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
end
|
||||
end
|
||||
|
||||
-- Draw an imagebox with the given cairo context in the given geometry.
|
||||
function imagebox:draw(ctx, cr, width, height)
|
||||
if width == 0 or height == 0 or not self._private.default then return end
|
||||
|
||||
-- For valign = "top" and halign = "left"
|
||||
local translate = {
|
||||
x = 0,
|
||||
y = 0,
|
||||
}
|
||||
|
||||
update_dpi(self, ctx)
|
||||
|
||||
local w, h = self._private.default.width, self._private.default.height
|
||||
|
||||
if self._private.resize then
|
||||
-- That's for the "fit" policy.
|
||||
local aspects = {
|
||||
w = width / w,
|
||||
h = height / h
|
||||
}
|
||||
|
||||
local policy = {
|
||||
w = self._private.horizontal_fit_policy or "auto",
|
||||
h = self._private.vertical_fit_policy or "auto"
|
||||
}
|
||||
|
||||
for _, aspect in ipairs {"w", "h"} do
|
||||
if self._private.upscale == false and (w < width and h < height) then
|
||||
aspects[aspect] = 1
|
||||
elseif self._private.downscale == false and (w >= width and h >= height) then
|
||||
aspects[aspect] = 1
|
||||
elseif policy[aspect] == "none" then
|
||||
aspects[aspect] = 1
|
||||
elseif policy[aspect] == "auto" then
|
||||
aspects[aspect] = math.min(width / w, height / h)
|
||||
elseif policy[aspect] == "cover" then
|
||||
aspects[aspect] = math.max(width / w, height / h)
|
||||
end
|
||||
end
|
||||
|
||||
if self._private.halign == "center" then
|
||||
translate.x = math.floor((width - w*aspects.w)/2)
|
||||
elseif self._private.halign == "right" then
|
||||
translate.x = math.floor(width - (w*aspects.w))
|
||||
end
|
||||
|
||||
if self._private.valign == "center" then
|
||||
translate.y = math.floor((height - h*aspects.h)/2)
|
||||
elseif self._private.valign == "bottom" then
|
||||
translate.y = math.floor(height - (h*aspects.h))
|
||||
end
|
||||
|
||||
cr:translate(translate.x, translate.y)
|
||||
|
||||
-- Before using the scale, make sure it is below the threshold.
|
||||
local threshold, max_factor = self._private.max_scaling_factor, math.max(aspects.w, aspects.h)
|
||||
|
||||
if threshold and threshold > 0 and threshold < max_factor then
|
||||
aspects.w = (aspects.w*threshold)/max_factor
|
||||
aspects.h = (aspects.h*threshold)/max_factor
|
||||
end
|
||||
|
||||
-- Set the clip
|
||||
if self._private.clip_shape then
|
||||
cr:clip(self._private.clip_shape(cr, w*aspects.w, h*aspects.h, unpack(self._private.clip_args)))
|
||||
end
|
||||
|
||||
cr:scale(aspects.w, aspects.h)
|
||||
else
|
||||
if self._private.halign == "center" then
|
||||
translate.x = math.floor((width - w)/2)
|
||||
elseif self._private.halign == "right" then
|
||||
translate.x = math.floor(width - w)
|
||||
end
|
||||
|
||||
if self._private.valign == "center" then
|
||||
translate.y = math.floor((height - h)/2)
|
||||
elseif self._private.valign == "bottom" then
|
||||
translate.y = math.floor(height - h)
|
||||
end
|
||||
|
||||
cr:translate(translate.x, translate.y)
|
||||
|
||||
-- Set the clip
|
||||
if self._private.clip_shape then
|
||||
cr:clip(self._private.clip_shape(cr, w, h, unpack(self._private.clip_args)))
|
||||
end
|
||||
end
|
||||
|
||||
if self._private.handle then
|
||||
self._private.handle:render_cairo(cr)
|
||||
else
|
||||
cr:set_source_surface(self._private.image, 0, 0)
|
||||
|
||||
local filter = self._private.scaling_quality
|
||||
|
||||
if filter then
|
||||
cr:get_source():set_filter(cairo.Filter[filter:upper()])
|
||||
end
|
||||
|
||||
cr:paint()
|
||||
end
|
||||
end
|
||||
|
||||
-- Fit the imagebox into the given geometry
|
||||
function imagebox:fit(ctx, width, height)
|
||||
if not self._private.default then return 0, 0 end
|
||||
|
||||
update_dpi(self, ctx)
|
||||
|
||||
local w, h = self._private.default.width, self._private.default.height
|
||||
|
||||
if w <= width and h <= height and self._private.upscale == false then
|
||||
return w, h
|
||||
end
|
||||
|
||||
if (w < width or h < height) and self._private.downscale == false then
|
||||
return w, h
|
||||
end
|
||||
|
||||
if self._private.resize or w > width or h > height then
|
||||
local aspect = math.min(width / w, height / h)
|
||||
return w * aspect, h * aspect
|
||||
end
|
||||
|
||||
return w, h
|
||||
end
|
||||
|
||||
--- The image rendered by the `imagebox`.
|
||||
--
|
||||
-- @property image
|
||||
-- @tparam[opt=nil] image|nil image
|
||||
-- @propemits false false
|
||||
|
||||
--- Set the `imagebox` image.
|
||||
--
|
||||
-- The image can be a file, a cairo image surface, or an rsvg handle object
|
||||
-- (see the [image property](#image)).
|
||||
-- @method set_image
|
||||
-- @hidden
|
||||
-- @tparam image image The image to render.
|
||||
-- @treturn boolean `true` on success, `false` if the image cannot be used.
|
||||
-- @usage my_imagebox:set_image(beautiful.awesome_icon)
|
||||
-- @usage my_imagebox:set_image('/usr/share/icons/theme/my_icon.png')
|
||||
-- @see image
|
||||
function imagebox:set_image(image)
|
||||
local setup_succeed
|
||||
|
||||
-- Keep the original to prevent the cache from being GCed.
|
||||
self._private.original_image = image
|
||||
|
||||
if type(image) == "userdata" and not (Rsvg and Rsvg.Handle:is_type_of(image)) then
|
||||
-- This function is not documented to handle userdata objects, but
|
||||
-- historically it did, and it did by just assuming they refer to a
|
||||
-- cairo surface.
|
||||
image = surface.load(image)
|
||||
end
|
||||
|
||||
if type(image) == "string" then
|
||||
-- try to load rsvg handle from file
|
||||
setup_succeed = load_and_apply(self, image, load_rsvg_handle, set_handle)
|
||||
|
||||
if not setup_succeed then
|
||||
-- rsvg handle failed, try to load cairo surface with pixbuf
|
||||
setup_succeed = load_and_apply(self, image, surface.load, set_surface)
|
||||
end
|
||||
elseif Rsvg and Rsvg.Handle:is_type_of(image) then
|
||||
-- try to apply given rsvg handle
|
||||
rsvg_handle_cache[image] = rsvg_handle_cache[image] or {}
|
||||
setup_succeed = set_handle(self, image, rsvg_handle_cache[image])
|
||||
elseif cairo.Surface:is_type_of(image) then
|
||||
-- try to apply given cairo surface
|
||||
setup_succeed = set_surface(self, image)
|
||||
elseif not image then
|
||||
-- nil as argument mean full imagebox reset
|
||||
setup_succeed = true
|
||||
self._private.handle = nil
|
||||
self._private.image = nil
|
||||
self._private.default = nil
|
||||
end
|
||||
|
||||
if not setup_succeed then return false end
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::image")
|
||||
return true
|
||||
end
|
||||
|
||||
--- Set a clip shape for this imagebox.
|
||||
--
|
||||
-- A clip shape defines an area and dimension to which the content should be
|
||||
-- trimmed.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_clip_shape_EXAMPLE@
|
||||
--
|
||||
-- @property clip_shape
|
||||
-- @tparam[opt=gears.shape.rectangle] shape clip_shape A `gears.shape` compatible shape function.
|
||||
-- @propemits true false
|
||||
-- @see gears.shape
|
||||
|
||||
--- Set a clip shape for this imagebox.
|
||||
--
|
||||
-- A clip shape defines an area and dimensions to which the content should be
|
||||
-- trimmed.
|
||||
--
|
||||
-- Additional parameters will be passed to the clip shape function.
|
||||
--
|
||||
-- @tparam function|gears.shape clip_shape A `gears_shape` compatible shape function.
|
||||
-- @method set_clip_shape
|
||||
-- @hidden
|
||||
-- @see gears.shape
|
||||
-- @see clip_shape
|
||||
function imagebox:set_clip_shape(clip_shape, ...)
|
||||
self._private.clip_shape = clip_shape
|
||||
self._private.clip_args = {...}
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::clip_shape", clip_shape)
|
||||
end
|
||||
|
||||
--- Should the image be resized to fit into the available space?
|
||||
--
|
||||
-- Note that `upscale` and `downscale` can affect the value of `resize`.
|
||||
-- If conflicting values are passed to the constructor, then the result
|
||||
-- is undefined.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_resize_EXAMPLE@
|
||||
-- @property resize
|
||||
-- @propemits true false
|
||||
-- @tparam[opt=true] boolean resize
|
||||
|
||||
--- Allow the image to be upscaled (made bigger).
|
||||
--
|
||||
-- Note that `upscale` and `downscale` can affect the value of `resize`.
|
||||
-- If conflicting values are passed to the constructor, then the result
|
||||
-- is undefined.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_upscale_EXAMPLE@
|
||||
-- @property upscale
|
||||
-- @tparam[opt=self.resize] boolean upscale
|
||||
-- @see downscale
|
||||
-- @see resize
|
||||
|
||||
--- Allow the image to be downscaled (made smaller).
|
||||
--
|
||||
-- Note that `upscale` and `downscale` can affect the value of `resize`.
|
||||
-- If conflicting values are passed to the constructor, then the result
|
||||
-- is undefined.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_downscale_EXAMPLE@
|
||||
-- @property downscale
|
||||
-- @tparam[opt=self.resize] boolean downscale
|
||||
-- @see upscale
|
||||
-- @see resize
|
||||
|
||||
--- Set the SVG CSS stylesheet.
|
||||
--
|
||||
-- If the image is an SVG (vector graphics), this property allows to set
|
||||
-- a CSS stylesheet. It can be used to set colors and much more.
|
||||
--
|
||||
-- Note that this property is a string, not a path. If the stylesheet is
|
||||
-- stored on disk, read the content first.
|
||||
--
|
||||
--@DOC_wibox_widget_imagebox_stylesheet_EXAMPLE@
|
||||
--
|
||||
-- @property stylesheet
|
||||
-- @tparam[opt=""] string stylesheet
|
||||
-- @propemits true false
|
||||
|
||||
--- Set the SVG DPI (dot per inch).
|
||||
--
|
||||
-- Force a specific DPI when rendering the `.svg`. For other file formats,
|
||||
-- this does nothing.
|
||||
--
|
||||
-- It can either be a number of a table containing the `x` and `y` keys.
|
||||
--
|
||||
-- Please note that DPI and `resize` can "fight" each other and end up
|
||||
-- making the image smaller instead of bigger.
|
||||
--
|
||||
--@DOC_wibox_widget_imagebox_dpi_EXAMPLE@
|
||||
--
|
||||
-- @property dpi
|
||||
-- @tparam[opt=96] number|table dpi
|
||||
-- @negativeallowed false
|
||||
-- @propemits true false
|
||||
-- @see auto_dpi
|
||||
|
||||
--- Use the object DPI when rendering the SVG.
|
||||
--
|
||||
-- By default, the SVG are interpreted as-is. When this property is set,
|
||||
-- the screen DPI will be passed to the SVG renderer. Depending on which
|
||||
-- tool was used to create the `.svg`, this may do nothing at all. However,
|
||||
-- for example, if the `.svg` uses `<text>` elements and doesn't have an
|
||||
-- hardcoded stylesheet, the result will differ.
|
||||
--
|
||||
-- @property auto_dpi
|
||||
-- @tparam[opt=false] boolean auto_dpi
|
||||
-- @propemits true false
|
||||
-- @see dpi
|
||||
|
||||
for _, prop in ipairs {"stylesheet", "dpi", "auto_dpi"} do
|
||||
imagebox["set_" .. prop] = function(self, value)
|
||||
-- It will be set in :fit and :draw. The handle is shared
|
||||
-- by multiple imagebox, so it cannot be set just once.
|
||||
self._private[prop] = value
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::" .. prop)
|
||||
end
|
||||
end
|
||||
|
||||
function imagebox:set_resize(allowed)
|
||||
self._private.resize = allowed
|
||||
|
||||
if allowed then
|
||||
self._private.downscale = true
|
||||
self._private.upscale = true
|
||||
self:emit_signal("property::downscale", allowed)
|
||||
self:emit_signal("property::upscale", allowed)
|
||||
end
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::resize", allowed)
|
||||
end
|
||||
|
||||
for _, prop in ipairs {"downscale", "upscale" } do
|
||||
imagebox["set_" .. prop] = function(self, allowed)
|
||||
self._private[prop] = allowed
|
||||
|
||||
if self._private.resize ~= (self._private.upscale or self._private.downscale) then
|
||||
self._private.resize = self._private.upscale or self._private.downscale
|
||||
self:emit_signal("property::resize", self._private.resize)
|
||||
end
|
||||
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("widget::layout_changed")
|
||||
self:emit_signal("property::"..prop, allowed)
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the horizontal fit policy.
|
||||
--
|
||||
-- Here is the result for a 22x32 image:
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_horizontal_fit_policy_EXAMPLE@
|
||||
--
|
||||
-- @property horizontal_fit_policy
|
||||
-- @tparam[opt="auto"] string horizontal_fit_policy
|
||||
-- @propertyvalue "auto" Honor the `resize` variable and preserve the aspect ratio.
|
||||
-- @propertyvalue "none" Do not resize at all.
|
||||
-- @propertyvalue "fit" Resize to the widget width.
|
||||
-- @propertyvalue "cover" Resize to fill widget and preserve the aspect ratio.
|
||||
-- @propemits true false
|
||||
-- @see vertical_fit_policy
|
||||
-- @see resize
|
||||
|
||||
--- Set the vertical fit policy.
|
||||
--
|
||||
-- Here is the result for a 32x22 image:
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_vertical_fit_policy_EXAMPLE@
|
||||
--
|
||||
-- @property vertical_fit_policy
|
||||
-- @tparam[opt="auto"] string vertical_fit_policy
|
||||
-- @propertyvalue "auto" Honor the `resize` variable and preserve the aspect ratio.
|
||||
-- @propertyvalue "none" Do not resize at all.
|
||||
-- @propertyvalue "fit" Resize to the widget height.
|
||||
-- @propertyvalue "cover" Resize to fill widget and preserve the aspect ratio.
|
||||
-- @propemits true false
|
||||
-- @see horizontal_fit_policy
|
||||
-- @see resize
|
||||
|
||||
|
||||
--- The vertical alignment.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_valign_EXAMPLE@
|
||||
--
|
||||
-- @property valign
|
||||
-- @tparam[opt="center"] string valign
|
||||
-- @propertyvalue "top"
|
||||
-- @propertyvalue "center"
|
||||
-- @propertyvalue "bottom"
|
||||
-- @propemits true false
|
||||
-- @see wibox.container.place
|
||||
-- @see halign
|
||||
|
||||
--- The horizontal alignment.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_halign_EXAMPLE@
|
||||
--
|
||||
-- @property halign
|
||||
-- @tparam[opt="center"] string halign
|
||||
-- @propertyvalue "left"
|
||||
-- @propertyvalue "center"
|
||||
-- @propertyvalue "right"
|
||||
-- @propemits true false
|
||||
-- @see wibox.container.place
|
||||
-- @see valign
|
||||
|
||||
--- The maximum scaling factor.
|
||||
--
|
||||
-- If an image is scaled too much, it gets very blurry. This
|
||||
-- property allows to limit the scaling.
|
||||
-- Use the properties `valign` and `halign` to control how the image will be
|
||||
-- aligned.
|
||||
--
|
||||
-- In the example below, the original size is 22x22
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_max_scaling_factor_EXAMPLE@
|
||||
--
|
||||
-- @property max_scaling_factor
|
||||
-- @tparam[opt=0] number max_scaling_factor Use `0` for "no limit".
|
||||
-- @negativeallowed false
|
||||
-- @propemits true false
|
||||
-- @see valign
|
||||
-- @see halign
|
||||
-- @see scaling_quality
|
||||
|
||||
--- Set the scaling aligorithm.
|
||||
--
|
||||
-- Depending on how the image is used, what is the "correct" way to
|
||||
-- scale can change. For example, upscaling a pixel art image should
|
||||
-- not make it blurry. However, scaling up a photo should not make it
|
||||
-- blocky.
|
||||
--
|
||||
--<table class='widget_list' border=1>
|
||||
-- <tr style='font-weight: bold;'>
|
||||
-- <th align='center'>Value</th>
|
||||
-- <th align='center'>Description</th>
|
||||
-- </tr>
|
||||
-- <tr><td>fast</td><td>A high-performance filter</td></tr>
|
||||
-- <tr><td>good</td><td>A reasonable-performance filter</td></tr>
|
||||
-- <tr><td>best</td><td>The highest-quality available</td></tr>
|
||||
-- <tr><td>nearest</td><td>Nearest-neighbor filtering (blocky)</td></tr>
|
||||
-- <tr><td>bilinear</td><td>Linear interpolation in two dimensions</td></tr>
|
||||
--</table>
|
||||
--
|
||||
-- The image used in the example below has a resolution of 32x22 and is
|
||||
-- intentionally blocky to highlight the difference.
|
||||
-- It is zoomed by a factor of 3.
|
||||
--
|
||||
-- @DOC_wibox_widget_imagebox_scaling_quality_EXAMPLE@
|
||||
--
|
||||
-- @property scaling_quality
|
||||
-- @tparam[opt="good"] string scaling_quality
|
||||
-- @propertyvalue "fast" A high-performance filter.
|
||||
-- @propertyvalue "good" A reasonable-performance filter.
|
||||
-- @propertyvalue "best" The highest-quality available.
|
||||
-- @propertyvalue "nearest" Nearest-neighbor filtering (blocky).
|
||||
-- @propertyvalue "bilinear" Linear interpolation in two dimensions.
|
||||
-- @propemits true false
|
||||
-- @see resize
|
||||
-- @see horizontal_fit_policy
|
||||
-- @see vertical_fit_policy
|
||||
-- @see max_scaling_factor
|
||||
|
||||
local defaults = {
|
||||
halign = "left",
|
||||
valign = "top",
|
||||
horizontal_fit_policy = "auto",
|
||||
vertical_fit_policy = "auto",
|
||||
max_scaling_factor = 0,
|
||||
scaling_quality = "good"
|
||||
}
|
||||
|
||||
local function get_default(prop, value)
|
||||
if value == nil then return defaults[prop] end
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
for prop in pairs(defaults) do
|
||||
imagebox["set_"..prop] = function(self, value)
|
||||
if value == self._private[prop] then return end
|
||||
|
||||
self._private[prop] = get_default(prop, value)
|
||||
self:emit_signal("widget::redraw_needed")
|
||||
self:emit_signal("property::"..prop, self._private[prop])
|
||||
end
|
||||
|
||||
imagebox["get_"..prop] = function(self)
|
||||
if self._private[prop] == nil then
|
||||
return defaults[prop]
|
||||
end
|
||||
|
||||
return self._private[prop]
|
||||
end
|
||||
end
|
||||
|
||||
--- Returns a new `wibox.widget.imagebox` instance.
|
||||
--
|
||||
-- This is the constructor of `wibox.widget.imagebox`. It creates a new
|
||||
-- instance of imagebox widget.
|
||||
--
|
||||
-- Alternatively, the declarative layout syntax can handle
|
||||
-- `wibox.widget.imagebox` instanciation.
|
||||
--
|
||||
-- The image can be a file, a cairo image surface, or an rsvg handle object
|
||||
-- (see the [image property](#image)).
|
||||
--
|
||||
-- Any additional arguments will be passed to the clip shape function.
|
||||
-- @tparam[opt] image image The image to display (may be `nil`).
|
||||
-- @tparam[opt] boolean resize_allowed If `false`, the image will be
|
||||
-- clipped, else it will be resized to fit into the available space.
|
||||
-- @tparam[opt] function clip_shape A `gears.shape` compatible function.
|
||||
-- @treturn wibox.widget.imagebox A new `wibox.widget.imagebox` widget instance.
|
||||
-- @constructorfct wibox.widget.imagebox
|
||||
local function new(image, resize_allowed, clip_shape, ...)
|
||||
local ret = base.make_widget(nil, nil, {enable_properties = true})
|
||||
|
||||
gtable.crush(ret, imagebox, true)
|
||||
ret._private.resize = true
|
||||
|
||||
if image then
|
||||
ret:set_image(image)
|
||||
end
|
||||
|
||||
if resize_allowed ~= nil then
|
||||
ret.resize = resize_allowed
|
||||
end
|
||||
|
||||
ret._private.clip_shape = clip_shape
|
||||
ret._private.clip_args = {...}
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function imagebox.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(imagebox, imagebox.mt)
|
||||
|
||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
200
.config/awesome/ui/statusbar/panel/widgets/music.lua
Normal file
|
@ -0,0 +1,200 @@
|
|||
local cairo = require "lgi".cairo
|
||||
local gcolor = require "gears.color"
|
||||
local gsurface = require "gears.surface"
|
||||
local imagebox = require "ui.statusbar.panel.widgets.imagebox"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local playerctl = require "services.playerctl"
|
||||
local qnative = require "quarrel.native"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local default_cover = phosphor.vinyl_record_fill
|
||||
local default_text = "Nothing playing"
|
||||
|
||||
local function faded_cover(cover)
|
||||
local surface = gsurface(cover)
|
||||
local w,h = gsurface.get_size(surface)
|
||||
local cr = cairo.Context(surface)
|
||||
local pattern = gcolor(qvars.colors.bg .. "aa")
|
||||
cr:rectangle(0, 0, w, h)
|
||||
cr:set_source(pattern)
|
||||
cr:fill_preserve()
|
||||
return surface
|
||||
end
|
||||
|
||||
local w_title = wibox.widget {
|
||||
widget = wibox.widget.textbox,
|
||||
text = "Nothing playing",
|
||||
}
|
||||
|
||||
local w_artist = wibox.widget {
|
||||
widget = wibox.container.background,
|
||||
fg = qvars.colors.dim.fg,
|
||||
{
|
||||
widget = wibox.widget.textbox,
|
||||
text = ""
|
||||
}
|
||||
}
|
||||
|
||||
local w_cover = wibox.widget {
|
||||
widget = imagebox,
|
||||
image = default_cover,
|
||||
stylesheet = qui.recolor(qvars.colors.bright.black),
|
||||
forced_height = qvars.char_height * 6 + qvars.big_padding * 2,
|
||||
forced_width = qvars.expanded_bar_size - qvars.big_padding,
|
||||
horizontal_fit_policy = "cover",
|
||||
vertical_fit_policy = "cover",
|
||||
valign = "center",
|
||||
halign = "center"
|
||||
}
|
||||
|
||||
local w_progress_bar = wibox.widget {
|
||||
widget = wibox.widget.progressbar,
|
||||
max_value = 0,
|
||||
value = 0,
|
||||
forced_height = qvars.char_height / 2,
|
||||
forced_width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2) - (qvars.char_height / 1.25 + qvars.padding) * 3,
|
||||
color = qvars.colors.yellow,
|
||||
background_color = qvars.colors.black,
|
||||
shape = qvars.shape,
|
||||
}
|
||||
|
||||
local w_play_pause = qui.toggle {
|
||||
widget = {
|
||||
forced_height = qvars.char_height / 1.25,
|
||||
forced_width = qvars.char_height / 1.25
|
||||
},
|
||||
off = phosphor.play_fill,
|
||||
on = phosphor.pause_fill,
|
||||
manual = true,
|
||||
press = function()
|
||||
playerctl:play_pause()
|
||||
end
|
||||
}
|
||||
|
||||
local w_skip_forward = qui.button {
|
||||
widget = {
|
||||
forced_height = qvars.char_height / 1.25,
|
||||
forced_width = qvars.char_height / 1.25
|
||||
},
|
||||
image = phosphor.skip_forward_fill,
|
||||
press = function()
|
||||
playerctl:next()
|
||||
end
|
||||
}
|
||||
|
||||
local w_skip_back = qui.button {
|
||||
widget = {
|
||||
forced_height = qvars.char_height / 1.25,
|
||||
forced_width = qvars.char_height / 1.25
|
||||
},
|
||||
image = phosphor.skip_back_fill,
|
||||
press = function()
|
||||
playerctl:previous()
|
||||
end
|
||||
}
|
||||
|
||||
local music = wibox.widget(qui.styled {
|
||||
widget = wibox.container.background,
|
||||
{
|
||||
{
|
||||
widget = wibox.container.background,
|
||||
bg = qvars.colors.black
|
||||
},
|
||||
w_cover,
|
||||
{
|
||||
widget = wibox.container.margin,
|
||||
margins = qvars.big_padding,
|
||||
{
|
||||
{
|
||||
{
|
||||
widget = wibox.container.background,
|
||||
bg = qvars.colors.bg,
|
||||
shape = qvars.shape,
|
||||
{
|
||||
widget = wibox.container.margin,
|
||||
margins = qvars.padding,
|
||||
{
|
||||
{
|
||||
widget = wibox.container.constraint,
|
||||
width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
|
||||
height = qvars.char_height,
|
||||
{
|
||||
widget = wibox.container.scroll.horizontal,
|
||||
speed = 50,
|
||||
step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
|
||||
w_title
|
||||
}
|
||||
},
|
||||
{
|
||||
widget = wibox.container.constraint,
|
||||
width = qvars.expanded_bar_size - (qvars.big_padding + qvars.big_padding * 2 + qvars.padding * 2),
|
||||
height = qvars.char_height,
|
||||
{
|
||||
widget = wibox.container.scroll.horizontal,
|
||||
speed = 50,
|
||||
step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth,
|
||||
w_artist
|
||||
}
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical
|
||||
}
|
||||
}
|
||||
},
|
||||
nil,
|
||||
nil,
|
||||
layout = wibox.layout.align.horizontal
|
||||
},
|
||||
nil,
|
||||
{
|
||||
widget = wibox.container.background,
|
||||
bg = qvars.colors.bg,
|
||||
shape = qvars.shape,
|
||||
{
|
||||
widget = wibox.container.margin,
|
||||
margins = qvars.padding,
|
||||
{
|
||||
w_play_pause,
|
||||
w_skip_back,
|
||||
{
|
||||
widget = wibox.container.place,
|
||||
w_progress_bar
|
||||
},
|
||||
w_skip_forward,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
spacing = qvars.padding
|
||||
}
|
||||
}
|
||||
},
|
||||
layout = wibox.layout.align.vertical
|
||||
}
|
||||
},
|
||||
layout = wibox.layout.stack
|
||||
}
|
||||
})
|
||||
|
||||
awesome.connect_signal("services::playerctl::metadata", function(title, artist, album_path)
|
||||
w_title.text = title ~= "" and qnative.decode_html(title) or default_text
|
||||
w_artist.widget.text = qnative.decode_html(artist)
|
||||
w_cover.image = faded_cover(album_path)
|
||||
end)
|
||||
|
||||
awesome.connect_signal("services::playerctl::position", function(position, length)
|
||||
w_progress_bar.value = position
|
||||
w_progress_bar.max_value = length
|
||||
end)
|
||||
|
||||
awesome.connect_signal("services::playerctl::no_players", function()
|
||||
w_title = default_text
|
||||
w_artist = ""
|
||||
w_cover.image = default_cover
|
||||
w_progress_bar.value = 0
|
||||
w_progress_bar.max_value = 0
|
||||
end)
|
||||
|
||||
awesome.connect_signal("services::playerctl::playback_status", function(playing)
|
||||
w_play_pause:silent_press(playing)
|
||||
end)
|
||||
|
||||
return music
|
|
@ -1,7 +1,7 @@
|
|||
local q = require "quarrel"
|
||||
local qbind = require "quarrel.bind"
|
||||
local qvars = require "quarrel.vars"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local power_menu = wibox.widget {
|
||||
|
|
42
.config/awesome/ui/statusbar/panel/widgets/wifi.lua
Normal file
|
@ -0,0 +1,42 @@
|
|||
local phosphor = require "assets.phosphor"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local wifi = wibox.widget(qui.styled {
|
||||
widget = wibox.container.background,
|
||||
{
|
||||
widget = wibox.container.margin,
|
||||
margins = qvars.big_padding,
|
||||
{
|
||||
{
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
qui.icon(phosphor.wifi_x_fill, qvars.colors.red, { id = "icon" })
|
||||
},
|
||||
{
|
||||
widget = wibox.widget.textbox,
|
||||
text = "Disconnected",
|
||||
id = "essid"
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
spacing = qvars.padding
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
awesome.connect_signal("services::wifi", function(essid, _, connected)
|
||||
if connected then
|
||||
wifi:get_children_by_id("essid")[1].text = essid
|
||||
else
|
||||
wifi:get_children_by_id("essid")[1].text = "Disconnected"
|
||||
end
|
||||
end)
|
||||
|
||||
awesome.connect_signal("services::wifi::icon", function(icon, color)
|
||||
wifi:get_children_by_id("icon")[1].image = icon
|
||||
wifi:get_children_by_id("icon")[1].stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
return wifi
|
|
@ -1,32 +0,0 @@
|
|||
local gcolor = require "gears.color"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qmath = require "quarrel.math"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local battery = wibox.widget {
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = gcolor.recolor_image(phosphor.battery_vertical_warning_fill, qvars.colors.red),
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height
|
||||
}
|
||||
}
|
||||
|
||||
awesome.connect_signal("services::battery", function(capacity, status)
|
||||
local icon_data = status == "Charging" and { "charging", "green" } or qmath.step_value(capacity, {
|
||||
{ 0, { "empty", "red" } },
|
||||
{ 20, { "low", "red" } },
|
||||
{ 40, { "medium", "yellow" } },
|
||||
{ 60, { "high", "green" } },
|
||||
{ 80, { "full", "green" } },
|
||||
{ 100 }
|
||||
})
|
||||
|
||||
battery.widget.image = gcolor.recolor_image(phosphor["battery_vertical_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
|
||||
end)
|
||||
|
||||
return battery
|
|
@ -1,32 +0,0 @@
|
|||
local gcolor = require "gears.color"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qmath = require "quarrel.math"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local brightness = wibox.widget {
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = gcolor.recolor_image(phosphor.moon_fill, qvars.colors.fg),
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height
|
||||
}
|
||||
}
|
||||
|
||||
awesome.connect_signal("services::brightness", function(value)
|
||||
local icon_data = qmath.step_value(value, {
|
||||
{ 0, "cloud_moon" },
|
||||
{ 51, "moon" },
|
||||
{ 102, "sun_horizon" },
|
||||
{ 153, "sun_dim" },
|
||||
{ 204, "sun" },
|
||||
{ 255 }
|
||||
})
|
||||
|
||||
brightness.widget.image = gcolor.recolor_image(phosphor[icon_data .. "_fill"], qvars.colors.fg)
|
||||
end)
|
||||
|
||||
return brightness
|
39
.config/awesome/ui/statusbar/widgets/displays.lua
Normal file
|
@ -0,0 +1,39 @@
|
|||
local phosphor = require "assets.phosphor"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local function create_display(icon, color)
|
||||
return wibox.widget {
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
qui.icon(icon, color)
|
||||
}
|
||||
end
|
||||
|
||||
local battery = create_display(phosphor.battery_vertical_warning_fill, qvars.colors.red)
|
||||
awesome.connect_signal("services::battery::icon", function(icon, color)
|
||||
battery.widget.image = icon
|
||||
battery.widget.stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
local brightness = create_display(phosphor.moon_fill, qvars.colors.fg)
|
||||
awesome.connect_signal("services::brightness::icon", function(icon, color)
|
||||
brightness.widget.image = icon
|
||||
brightness.widget.stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
local audio = create_display(phosphor.speaker_simple_slash_fill, qvars.colors.red)
|
||||
awesome.connect_signal("services::audio::icon", function(icon, color)
|
||||
audio.widget.image = icon
|
||||
audio.widget.stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
local wifi = create_display(phosphor.wifi_x_fill, qvars.colors.red)
|
||||
awesome.connect_signal("services::wifi::icon", function(icon, color)
|
||||
wifi.widget.image = icon
|
||||
wifi.widget.stylesheet = qui.recolor(color)
|
||||
end)
|
||||
|
||||
return { audio = audio, battery = battery, brightness = brightness, wifi = wifi }
|
|
@ -1,7 +1,9 @@
|
|||
local awful = require "awful"
|
||||
local gcolor = require "gears.color"
|
||||
local gdebug = require "gears.debug"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qbind = require "quarrel.bind"
|
||||
local qui = require "quarrel.ui"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
|
@ -16,42 +18,33 @@ return awful.widget.taglist {
|
|||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = gcolor.recolor_image(phosphor.circle_bold, qvars.colors.fg),
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height,
|
||||
icon = phosphor.dot_fill
|
||||
},
|
||||
create_callback = function(self, tag)
|
||||
-- self.widget.icon = phosphor[next(tag:clients()) and "circle_fill" or "circle_bold"]
|
||||
self.widget = qui.icon(tag.icon)
|
||||
|
||||
self:connect_signal("mouse::enter", function()
|
||||
if tag.selected then return end
|
||||
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.yellow)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
|
||||
end)
|
||||
|
||||
self:connect_signal("mouse::leave", function()
|
||||
if tag.selected then return end
|
||||
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.fg)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.fg)
|
||||
end)
|
||||
|
||||
if tag.selected then
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.yellow)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
|
||||
return
|
||||
end
|
||||
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.fg)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.fg)
|
||||
end,
|
||||
update_callback = function(self, tag)
|
||||
-- self.widget.icon = phosphor[next(tag:clients()) and "circle_fill" or "circle_bold"]
|
||||
|
||||
if tag.selected then
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.yellow)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.yellow)
|
||||
else
|
||||
self.widget.image = gcolor.recolor_image(self.widget.icon, qvars.colors.fg)
|
||||
self.widget.stylesheet = qui.recolor(qvars.colors.fg)
|
||||
end
|
||||
end
|
||||
},
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
local gcolor = require "gears.color"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qmath = require "quarrel.math"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
|
||||
local volume_widget = wibox.widget {
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = gcolor.recolor_image(phosphor.speaker_simple_slash_fill, qvars.colors.red),
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height
|
||||
}
|
||||
}
|
||||
|
||||
awesome.connect_signal("services::audio", function(volume, muted)
|
||||
if muted then
|
||||
volume_widget.widget.image = gcolor.recolor_image(phosphor["speaker_simple_x_fill"], qvars.colors.red)
|
||||
return
|
||||
end
|
||||
|
||||
local icon_data = qmath.step_value(volume, {
|
||||
{ 0, "slash" },
|
||||
{ 25, "none" },
|
||||
{ 50, "low" },
|
||||
{ 75, "high" },
|
||||
{ 100 }
|
||||
})
|
||||
|
||||
volume_widget.widget.image = gcolor.recolor_image(phosphor["speaker_simple_" .. icon_data .. "_fill"], qvars.colors.fg)
|
||||
end)
|
||||
|
||||
return volume_widget
|
|
@ -1,38 +0,0 @@
|
|||
local gcolor = require "gears.color"
|
||||
local phosphor = require "assets.phosphor"
|
||||
local qmath = require "quarrel.math"
|
||||
local qvars = require "quarrel.vars"
|
||||
local wibox = require "wibox"
|
||||
local q = require "quarrel"
|
||||
local gdebug = require "gears.debug"
|
||||
|
||||
local wifi = wibox.widget {
|
||||
widget = wibox.container.place,
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
image = gcolor.recolor_image(phosphor.wifi_x_fill, qvars.colors.red),
|
||||
forced_width = qvars.char_height,
|
||||
forced_height = qvars.char_height
|
||||
}
|
||||
}
|
||||
|
||||
awesome.connect_signal("services::wifi", function(essid, strength, connected)
|
||||
if not connected then
|
||||
wifi.widget.image = gcolor.recolor_image(phosphor.wifi_x_fill, qvars.colors.red)
|
||||
return
|
||||
end
|
||||
|
||||
local icon_data = qmath.step_value(strength, {
|
||||
{ 0, { "none", "red" } },
|
||||
{ 25, { "low", "yellow" } },
|
||||
{ 50, { "medium", "yellow" } },
|
||||
{ 75, { "high", "green" } },
|
||||
{ 100 }
|
||||
})
|
||||
|
||||
wifi.widget.image = gcolor.recolor_image(phosphor["wifi_" .. icon_data[1] .. "_fill"], qvars.colors[icon_data[2]])
|
||||
end)
|
||||
|
||||
return wifi
|