diff options
Diffstat (limited to '.config/awesome')
22 files changed, 559 insertions, 277 deletions
diff --git a/.config/awesome/misc/autostart.lua b/.config/awesome/misc/autostart.lua index de79c65..85b91c0 100644 --- a/.config/awesome/misc/autostart.lua +++ b/.config/awesome/misc/autostart.lua @@ -1,7 +1,7 @@ local awful = require "awful" local qpersistent = require "quarrel.persistent" -if qpersistent.is_restart() then +if qpersistent.is_restart() or awesome.release == "somewm" then return end diff --git a/.config/awesome/misc/cfg.lua b/.config/awesome/misc/cfg.lua index f62612f..a05f911 100644 --- a/.config/awesome/misc/cfg.lua +++ b/.config/awesome/misc/cfg.lua @@ -1,7 +1,6 @@ local awful = require "awful" local cfg = { - terminal = "wezterm", tags = { -- home { diff --git a/.config/awesome/misc/init.lua b/.config/awesome/misc/init.lua index 069046a..d3c36b2 100644 --- a/.config/awesome/misc/init.lua +++ b/.config/awesome/misc/init.lua @@ -1,3 +1,3 @@ require "misc.keys" require "misc.rules" --- require "misc.autostart" +require "misc.autostart" diff --git a/.config/awesome/misc/keys.lua b/.config/awesome/misc/keys.lua index b7dc4c4..9a5e481 100644 --- a/.config/awesome/misc/keys.lua +++ b/.config/awesome/misc/keys.lua @@ -2,7 +2,10 @@ local awful = require "awful" local backlight = require "services.backlight" local beautiful = require "beautiful" local cfg = require "misc.cfg" -local fresnel = require "ui.fresnel" +local fresnel = { show = function() end} +if awesome.release ~= "somewm" then + fresnel = require "ui.fresnel" +end local gtable = require "gears.table" local gtimer = require "gears.timer" local insightful = require "ui.insightful" @@ -13,6 +16,7 @@ local playerctl = require "services.playerctl" local powermenu = require "ui.powermenu" local qbind = require "quarrel.bind" local dnd = require "services.dnd" +-- local osd = require "ui.osd" local recording = { false, "" } @@ -30,6 +34,17 @@ client.connect_signal("request::default_mousebindings", function() }, qbind { mods = qbind.mods.M, + triggers = qbind.btns.middle, + press = function(c) + c:activate { + context = "mouse_click", + } + end, + group = "client", + desc = "raise client", + }, + qbind { + mods = qbind.mods.M, triggers = qbind.btns.left, press = function(c) c:activate { @@ -115,6 +130,15 @@ awful.keyboard.append_global_keybindings { group = "awesome", desc = "toggle insightful", }, + -- qbind { + -- mods = qbind.mods.M, + -- triggers = "u", + -- press = function() + -- osd:toggle() + -- end, + -- group = "awesome", + -- desc = "toggle osd", + -- }, qbind { mods = qbind.mods.M, triggers = "space", @@ -229,7 +253,7 @@ awful.keyboard.append_global_keybindings { mods = qbind.mods.M, triggers = "Return", press = function() - awful.spawn(cfg.terminal) + awful.spawn("xdg-terminal-exec") end, group = "launcher", desc = "launch terminal", @@ -293,7 +317,7 @@ awful.keyboard.append_global_keybindings { else recording[1] = true recording[2] = os.getenv "HOME" .. "/Videos/" .. os.date "%Y%m%d_%H%M%S" .. ".mp4" - awful.spawn("giph --format mp4 --framerate 30 " .. recording[2]) + awful.spawn("giph -a --format mp4 --framerate 30 " .. recording[2]) naughty.notification { app_name = "Giph", title = "Recording started", diff --git a/.config/awesome/misc/rules.lua b/.config/awesome/misc/rules.lua index 18b11f1..3f59929 100644 --- a/.config/awesome/misc/rules.lua +++ b/.config/awesome/misc/rules.lua @@ -54,6 +54,18 @@ ruled.client.connect_signal("request::rules", function() }, { + id = "dragon-drop", + rule = { + class = "Dragon-drop" + }, + properties = { + ontop = true, + sticky = true, + floating = true + } + }, + + { id = "browser_tag", rule_any = { instance = { "Navigator" }, diff --git a/.config/awesome/prismite.lua b/.config/awesome/prismite.lua index b9423e8..610ab9b 100644 --- a/.config/awesome/prismite.lua +++ b/.config/awesome/prismite.lua @@ -25,6 +25,10 @@ theme.border_normal = qcolor.palette.border() theme.border_focus = qcolor.palette.border() theme.border_marked = qcolor.palette.border() +theme.snap_bg = qcolor.palette.yellow() +theme.snap_border_width = qui.BORDER_WIDTH * 2 +theme.snap_shape = qui.shape + theme.notification_icon_size = dpi(32) theme.notification_border_width = qui.BORDER_WIDTH theme.notification_border_color = theme.border_normal diff --git a/.config/awesome/quarrel/native/Cargo.toml b/.config/awesome/quarrel/native/Cargo.toml index 1b98681..8d1bd80 100644 --- a/.config/awesome/quarrel/native/Cargo.toml +++ b/.config/awesome/quarrel/native/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "qnative" version = "0.1.0" -edition = "2021" +edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/.config/awesome/quarrel/native/src/lenses/application.rs b/.config/awesome/quarrel/native/src/lenses/application.rs index 38a7762..cc12e82 100644 --- a/.config/awesome/quarrel/native/src/lenses/application.rs +++ b/.config/awesome/quarrel/native/src/lenses/application.rs @@ -3,13 +3,13 @@ use std::{ fs::read_dir, path::PathBuf, sync::{ + Arc, + OnceLock, + RwLock, atomic::{ AtomicBool, Ordering, }, - Arc, - OnceLock, - RwLock, }, }; @@ -20,7 +20,10 @@ use rayon::prelude::*; use url::Url; use crate::lenses::{ - Cache, Entries, Entry, Lense + Cache, + Entries, + Entry, + Lense, }; static APPS_DIR: &'static str = "/usr/share/applications"; @@ -34,6 +37,7 @@ pub struct Application { impl Lense for Application { const NAME: &str = "Application"; + const PREFIX: Option<&'static str> = None; fn init() -> Arc<Self> { let this = Arc::new(Application::default()); @@ -94,7 +98,7 @@ impl Lense for Application { // self.should_interrupt.load(Ordering::Relaxed) } - fn entries(&self, _: &Lua, _: String) -> Result<Entries, anyhow::Error> { + fn entries(&self, _: &Lua, _: &str) -> Result<Entries, anyhow::Error> { let entries = read_dir(APPS_DIR)? .map(|result| result.map(|e| e.path())) .collect::<Result<Vec<_>, std::io::Error>>()?; diff --git a/.config/awesome/quarrel/native/src/lenses/calculator.rs b/.config/awesome/quarrel/native/src/lenses/calculator.rs index 36f9805..a483d10 100644 --- a/.config/awesome/quarrel/native/src/lenses/calculator.rs +++ b/.config/awesome/quarrel/native/src/lenses/calculator.rs @@ -1,22 +1,25 @@ use std::sync::{ + Arc, + LazyLock, + Mutex, atomic::{ AtomicBool, Ordering, }, - Arc, - LazyLock, - Mutex, }; use fend_core::{ - evaluate_with_interrupt, Context, Interrupt, + evaluate_with_interrupt, }; use mlua::prelude::*; use crate::lenses::{ - Cache, Entries, Entry, Lense + Cache, + Entries, + Entry, + Lense, }; static CTX: LazyLock<Mutex<Context>> = LazyLock::new(|| { @@ -32,6 +35,7 @@ pub struct Calculator { impl Lense for Calculator { const NAME: &str = "Calculator"; + const PREFIX: Option<&'static str> = Some("#"); fn init() -> std::sync::Arc<Self> { Arc::new(Calculator::default()) @@ -55,18 +59,14 @@ impl Lense for Calculator { self.should_interrupt.load(Ordering::Relaxed) } - fn entries(&self, _: &Lua, input: String) -> Result<Entries, anyhow::Error> { + fn entries(&self, _: &Lua, input: &str) -> Result<Entries, anyhow::Error> { let result = match evaluate_with_interrupt( input.trim(), &mut CTX.lock().expect("Failed to acquire Fend context lock"), self, ) { - Ok(result) => { - result.get_main_result().to_string() - } - Err(err) => { - err - } + Ok(result) => result.get_main_result().to_string(), + Err(err) => err, }; Ok(if result.is_empty() { @@ -77,11 +77,10 @@ impl Lense for Calculator { exec: None, }) }) - } #[inline] - fn filter(&self, entries: Entries, _: String) -> Entries { + fn filter(&self, entries: Entries, _: &str) -> Entries { entries } } diff --git a/.config/awesome/quarrel/native/src/lenses/mod.rs b/.config/awesome/quarrel/native/src/lenses/mod.rs index bb7f727..0b7864e 100644 --- a/.config/awesome/quarrel/native/src/lenses/mod.rs +++ b/.config/awesome/quarrel/native/src/lenses/mod.rs @@ -5,8 +5,8 @@ use std::sync::Arc; use itertools::Itertools; use mlua::{ - prelude::*, LuaSerdeExt, + prelude::*, }; use rayon::iter::FromParallelIterator; use serde::{ @@ -18,7 +18,7 @@ use serde::{ pub enum Entries { Multiple(Vec<Entry>), Single(Entry), - None + None, } impl FromIterator<Entry> for Entries { @@ -32,7 +32,7 @@ impl FromIterator<Entry> for Entries { let mut vec = Vec::from([first, second]); vec.extend(iter); Self::Multiple(vec) - }, + } } } } @@ -44,8 +44,8 @@ impl From<Vec<Entry>> for Entries { 1 => { let entry = entries.into_iter().exactly_one().unwrap(); Self::Single(entry) - }, - _ => Self::Multiple(entries) + } + _ => Self::Multiple(entries), } } } @@ -55,7 +55,7 @@ impl IntoLua for Entries { match self { Entries::Multiple(entries) => entries.into_lua(lua), Entries::Single(entry) => entry.into_lua(lua), - Entries::None => Ok(LuaValue::Nil) + Entries::None => Ok(LuaValue::Nil), } } } @@ -89,6 +89,7 @@ pub struct _Lense<T: Lense>(pub Arc<T>); pub trait Lense { const NAME: &'static str; + const PREFIX: Option<&'static str>; fn init() -> Arc<Self>; @@ -98,51 +99,70 @@ pub trait Lense { fn set_interrupt(&self, interrupt: bool); fn get_interrupt(&self) -> bool; - fn entries(&self, lua: &Lua, input: String) -> Result<Entries, anyhow::Error>; - fn filter(&self, entries: Entries, input: String) -> Entries { - let entry_contains = |entry: &Entry| { - entry.message.to_lowercase().contains(&input.to_lowercase()) - }; + fn entries(&self, lua: &Lua, input: &str) -> Result<Entries, anyhow::Error>; + fn filter(&self, entries: Entries, input: &str) -> Entries { + let entry_contains = + |entry: &Entry| entry.message.to_lowercase().contains(&input.to_lowercase()); match entries { - Entries::Multiple(entries) => entries.into_iter() - .filter(entry_contains) - .collect(), - Entries::Single(entry) => if entry_contains(&entry) { Entries::Single(entry) } else { Entries::None } - Entries::None => Entries::None + Entries::Multiple(entries) => entries.into_iter().filter(entry_contains).collect(), + Entries::Single(entry) => { + if entry_contains(&entry) { + Entries::Single(entry) + } else { + Entries::None + } + } + Entries::None => Entries::None, } } } impl<T: Lense + 'static> LuaUserData for _Lense<T> { fn add_fields<F: LuaUserDataFields<Self>>(fields: &mut F) { - fields.add_field_method_get("stale", |_, this| { - Ok(matches!(this.0.get_cache(), Cache::Stale)) + fields.add_field_method_get("stale", |_, Self(this)| { + Ok(matches!(this.get_cache(), Cache::Stale)) }); fields.add_field("name", T::NAME); } fn add_methods<M: LuaUserDataMethods<Self>>(methods: &mut M) { - methods.add_method_mut("query", |lua, this, input: String| { - this.0.set_interrupt(false); // reset interrupt so that we can use the lense again - return Ok(match this.0.get_cache() { - Cache::Valid(entries) => this.0.filter(entries.clone(), input), - Cache::Stale => { - let entries = this.0.entries(lua, input.clone()).map_err(LuaError::external)?; - let mut entries = this.0.filter(entries, input); - match entries { - Entries::Multiple(ref mut entries) => entries.sort_by(|a, b| a.message.cmp(&b.message)), - _ => {} - } - this.0.set_cache(Cache::Valid(entries.clone())); - entries + methods.add_method_mut("query", |lua, Self(this), input: String| { + if T::PREFIX.is_some_and(|prefix| input.starts_with(prefix)) || T::PREFIX.is_none() { + let input = if let Some(prefix) = T::PREFIX { + input.trim_start_matches(prefix) + } else { + &input } - }); + .trim(); + + this.set_interrupt(false); // reset interrupt so that we can use the lense again + + return Ok(match this.get_cache() { + Cache::Valid(entries) => this.filter(entries.clone(), input), + Cache::Stale => { + let entries = this.entries(lua, input).map_err(LuaError::external)?; + let mut entries = this.filter(entries, input); + match entries { + Entries::Multiple(ref mut entries) => { + entries.sort_by(|a, b| a.message.cmp(&b.message)) + } + _ => {} + } + this.set_cache(Cache::Valid(entries.clone())); + entries + } + }); + } else { + return Ok(Entries::None); + } }); - methods.add_method_mut("mark_stale", |_, this, _: ()| { - Ok(this.0.set_cache(Cache::Stale)) + methods.add_method_mut("mark_stale", |_, Self(this), _: ()| { + Ok(this.set_cache(Cache::Stale)) + }); + methods.add_method_mut("interrupt", |_, Self(this), _: ()| { + Ok(this.set_interrupt(true)) }); - methods.add_method_mut("interrupt", |_, this, _: ()| Ok(this.0.set_interrupt(true))); } } diff --git a/.config/awesome/quarrel/native/src/net/mod.rs b/.config/awesome/quarrel/native/src/net/mod.rs index 383e800..728e6ec 100644 --- a/.config/awesome/quarrel/native/src/net/mod.rs +++ b/.config/awesome/quarrel/native/src/net/mod.rs @@ -20,21 +20,21 @@ use nix::{ ioctl_read_bad, libc::IF_NAMESIZE, sys::socket::{ - socket as open_socket, AddressFamily, SockFlag, SockType, + socket as open_socket, }, unistd::close, }; use wireless::{ + IW_ESSID_MAX_SIZE, IfConf, IfConfData, IwPoint, IwReq, IwReqData, IwReqName, - IW_ESSID_MAX_SIZE, SIOCGIFCONF, SIOCGIWESSID, }; diff --git a/.config/awesome/quarrel/native/src/net/wireless.rs b/.config/awesome/quarrel/native/src/net/wireless.rs index d3999db..3500751 100644 --- a/.config/awesome/quarrel/native/src/net/wireless.rs +++ b/.config/awesome/quarrel/native/src/net/wireless.rs @@ -7,11 +7,11 @@ use std::ffi::{ use nix::libc::{ __s16, __s32, - __u16, __u8, + __u16, + IF_NAMESIZE, ifreq as IfReq, sockaddr as SockAddr, - IF_NAMESIZE, }; pub static SIOCGIFCONF: c_int = 0x8912; diff --git a/.config/awesome/quarrel/ui/init.lua b/.config/awesome/quarrel/ui/init.lua index 5e68b1d..7ba6a58 100644 --- a/.config/awesome/quarrel/ui/init.lua +++ b/.config/awesome/quarrel/ui/init.lua @@ -4,7 +4,9 @@ local gshape = require "gears.shape" local gtable = require "gears.table" local qbind = require "quarrel.bind" local qcolor = require "quarrel.color" +local qdelegate = require "quarrel.delegate" local wibox = require "wibox" +local cairo = require("lgi").cairo --- Clip Cairo context ---@param cr cairo_surface Cairo surface @@ -199,4 +201,89 @@ function M.hoverable(widget, cursor) return widget end +---@param wibox wibox +function M.animateable_shape(wibox) + local old_apply_shape = wibox._apply_shape + + wibox:disconnect_signal("property::geometry", old_apply_shape) + wibox:disconnect_signal("property::border_width", old_apply_shape) + + function wibox:set_shape_width(value) + self._shape_width = value + self:emit_signal("property::shape_width") + end + + function wibox:get_shape_width(value) + return self._shape_width + end + + function wibox:set_shape_height(value) + self._shape_height = value + self:emit_signal("property::shape_height") + end + + function wibox:get_shape_height(value) + return self._shape_height + end + + -- override to allow us to override shape + wibox._apply_shape = qdelegate(function(env, self) + local shape = self._shape + + if not shape then + self.shape_bounding = nil + self.shape_clip = nil + return + end + + local geo = self:geometry() + local bw = self.border_width + + if self.shape_width then + geo.width = self.shape_width + end + + if self.shape_height then + geo.height = self.shape_height + end + + -- First handle the bounding shape (things including the border) + local img = cairo.ImageSurface(cairo.Format.A1, geo.width + 2*bw, geo.height + 2*bw) + local cr = cairo.Context(img) + + -- We just draw the shape in its full size + shape(cr, geo.width + 2*bw, geo.height + 2*bw) + cr:set_operator(cairo.Operator.SOURCE) + cr:fill() + self.shape_bounding = img._native + img:finish() + + -- Now handle the clip shape (things excluding the border) + img = cairo.ImageSurface(cairo.Format.A1, geo.width, geo.height) + cr = cairo.Context(img) + + -- We give the shape the same arguments as for the bounding shape and draw + -- it in its full size (the translate is to compensate for the smaller + -- surface) + cr:translate(-bw, -bw) + shape(cr, geo.width + 2*bw, geo.height + 2*bw) + cr:set_operator(cairo.Operator.SOURCE) + cr:fill_preserve() + -- Now we remove an area of width 'bw' again around the shape (We use 2*bw + -- since half of that is on the outside and only half on the inside) + cr:set_source_rgba(0, 0, 0, 0) + cr:set_line_width(2*bw) + cr:stroke() + self.shape_clip = img._native + img:finish() + end, old_apply_shape) + + wibox:connect_signal("property::geometry", wibox._apply_shape) + wibox:connect_signal("property::border_width", wibox._apply_shape) + wibox:connect_signal("property::shape_width", wibox._apply_shape) + wibox:connect_signal("property::shape_height", wibox._apply_shape) + + return wibox +end + return M diff --git a/.config/awesome/services/mpris/consts.lua b/.config/awesome/services/mpris/consts.lua new file mode 100644 index 0000000..e86e50e --- /dev/null +++ b/.config/awesome/services/mpris/consts.lua @@ -0,0 +1,13 @@ +local M = {} + +M.EXCLUDED_PLAYERS = {} + +M.TRACKED_METADATA = { + length = "mpris:length", + album = "xesam:album", + title = "xesam:title", + artist = "xesam:artist", + art = "mpris:artUrl", +} + +return M diff --git a/.config/awesome/services/mpris/init.lua b/.config/awesome/services/mpris/init.lua index 3659a3a..1c907e7 100644 --- a/.config/awesome/services/mpris/init.lua +++ b/.config/awesome/services/mpris/init.lua @@ -1,100 +1,132 @@ local gobject = require "gears.object" local playerctl = require "services.mpris.playerctl" local qpersistent = require "quarrel.persistent" +local playerctl = require("lgi").Playerctl ---@class ServiceMpris : gears.object ----@field inner Playerctl ---@field index number the index of the currently active player -local M = {} +---@field manager lgi.Playerctl.PlayerManager +local M = { object = {} } ----@param self ServiceMpris ----@param player Playerctl.data -local function update_player(self, player) - self:emit_signal("player::metadata", player) - self:emit_signal("player::position", player) - -- handle_position(nil, player) +---@class WrappedPlayer : gears.object +---@field inner lgi.Playerctl.Player +---@field _position_timer gears.timer + +---@param self WrappedPlayer +function M.object:_update_position(by_user) + self:emit_signal("property::position", by_user) end ----@param diff_player Playerctl.data -local function recalculate_active_player(diff_player, vanished) - if type(diff_player) ~= "table" then - return +---@param self WrappedPlayer +function M.object:_update_position_timer() + if self.inner.playback_status == "PLAYING" then + self._position_timer:again() + else + self._position_timer:stop() end - -- if #layout.children == 0 then - -- M.active_player_index = 1 - -- update_player() - -- return - -- end +end - local active_player = players[M.active_player_index] - if not active_player then -- we're recovering from a state with no players - update_player(diff_player) - return - end +---@param self WrappedPlayer +---@param value boolean +function M.object:set_shuffle(value) + self.inner:set_shuffle(value) +end - if diff_player.instance == active_player.instance and vanished then -- active player vanished; fall back to previous player - M.previous_player() - else -- non-active player appeared/vanished; try to find active player - for i, p in ipairs(playerctl:list()) do - if p.instance == active_player.instance then - M.active_player_index = i - update_player(p) - return - end - end +---@param self WrappedPlayer +---@param value number +function M.object:set_volume(value) + self.inner:set_volume(value) +end - gdebug.print_warning( - "failed to find active player:\n " .. gdebug.dump_return(active_player, nil, 2):gsub("\n", "\n ") - ) - M.active_player_index = 1 - update_player(playerctl:list()[M.active_player_index]) - end +---@param self WrappedPlayer +---@param value integer +function M.object:set_position(value) + self.inner:set_position(value) +end + +---@param self WrappedPlayer +---@param value lgi.Playerctl.LoopStatus +function M.object:set_loop_status(value) + self.inner:set_loop_status(value) +end + +---@param self WrappedPlayer +function M.object:play_pause() + self.inner:play_pause() +end + +---@param self WrappedPlayer +function M.object:play() + self.inner:play() +end + +---@param self WrappedPlayer +function M.object:pause() + self.inner:pause() end -function M:next_player() - local players = self.inner:list() +---@param self WrappedPlayer +function M.object:stop() + self.inner:stop() +end - if #players == 0 then - return - elseif self.index + 1 > #players then - self.index = 1 +---@param self WrappedPlayer +function M.object:previous() + self.inner:previous() +end + +---@param self WrappedPlayer +function M.object:next() + self.inner:next() +end + +---@param self Playerctl +---@param player_a lgi.Playerctl.Player +---@param player_b lgi.Playerctl.Player +---@return sign +local function compare_players(self, player_a, player_b) + if player_a.player_name < player_b.player_name then + return -1 + elseif player_a.player_name > player_b.player_name then + return 1 else - self.index = self.index + 1 + return 0 end +end + +local function manage_player(self, full_name) + local player = playerctl.Player.new_from_name(full_name) - -- update_player(playerctl:list()[M.active_player_index]) - local player = players[self.index] - self:emit_signal("player::metadata", player) - self:emit_signal("player::position", player) + function player.on_metadata(p, metadata) + + end end -function M:previous_player() - local players = self.inner:list() - if #players == 0 then - return - elseif self.index - 1 < #players then - self.index = #players - else - self.index = self.index - 1 +local function init_manager(self) + self.manager = playerctl.PlayerManager() + self.manager:set_sort_func(function(a, b) + local player_a = playerctl.Player(a) + local player_b = playerctl.Player(b) + return compare_players(self, player_a, player_b) + end) + + function self.manager.on_name_appeared(_, full_name) + + end + + function self.manager.on_player_appeared() + end +end + +local function new() + local self = gobject {} + + init_manager(self) - local player = players[self.index] - self:emit_signal("player::metadata", player) - self:emit_signal("player::position", player) + return self end -M.inner = playerctl.new { - players = {}, - metadata = { - album = "xesam:album", - title = "xesam:title", - artist = "xesam:artist", - art = "mpris:artUrl", - }, -} +local instance = new() -local instance = gobject { class = M } -instance:connect_signal("property::index", function(self, index) - qpersistent.store("active_player_index", self.index) -end) return instance diff --git a/.config/awesome/services/osd.lua b/.config/awesome/services/osd.lua index c4fa3e7..1851016 100644 --- a/.config/awesome/services/osd.lua +++ b/.config/awesome/services/osd.lua @@ -1,7 +1,25 @@ +local gobject = require "gears.object" local battery = require "services.battery" local osd = require "ui.osd" local phosphor = require "assets.phosphor" +local inner = false + +local M = gobject { + class = { + set_dnd = function(self, value) + inner = value + self:emit_signal("dnd", inner) + end, + get_dnd = function() + return inner + end + }, + enable_properties = true, +} + +return M + -- battery:connect_signal("icon", function (self, icon, _) -- osd.notify(icon, self.level, 100) -- end) diff --git a/.config/awesome/services/wifi.lua b/.config/awesome/services/wifi.lua new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/.config/awesome/services/wifi.lua diff --git a/.config/awesome/ui/fresnel/init.lua b/.config/awesome/ui/fresnel/init.lua index dc8e333..613bc9c 100644 --- a/.config/awesome/ui/fresnel/init.lua +++ b/.config/awesome/ui/fresnel/init.lua @@ -1,7 +1,5 @@ local text_input = require "ui.fresnel.text_input" local awful = require "awful" -local qdebug = require "quarrel.debug" -local cfg = require "misc.cfg" local gshape = require "gears.shape" local gtable = require "gears.table" local qanim = require "quarrel.animation" @@ -152,7 +150,7 @@ function fresnel:_exec_entry(entry) local exec = entry.exec if type(exec) ~= "userdata" and type(exec) ~= "nil" then if exec[2] then - awful.spawn(cfg.terminal .. " -e /bin/sh -c " .. exec[1] .. " 1>/dev/null 2>&1") + awful.spawn.with_shell("xdg-terminal-exec /bin/sh -c '" .. exec[1]:gsub("'", [[\']]) .. "' 1>/dev/null 2>&1") else awful.spawn.with_shell(exec[1] .. " 1>/dev/null 2>&1") end @@ -318,17 +316,17 @@ fresnel._w_status = wibox.widget { widget = wibox.widget.textbox, text = "0/0", } -fresnel._w_popup = qui.popup { +fresnel._w_popup = qui.animateable_shape(qui.popup { -- visible = false, ontop = true, placement = false, - shape = function(cr, w) - gshape.partially_rounded_rect(cr, w, 0, false, false, true, true, qui.BORDER_RADIUS) + shape = function(cr, w, h) + gshape.partially_rounded_rect(cr, w, h, false, false, true, true, qui.BORDER_RADIUS) end, x = width / 2, + y = -qui.BORDER_WIDTH, minimum_width = width, maximum_width = width, - -- maximum_height = max_height, widget = { qui.styled { widget = wibox.container.background, @@ -373,7 +371,7 @@ fresnel._w_popup = qui.popup { }, layout = wibox.layout.align.vertical, }, -} +}) function fresnel:show() self._prev_scroll_amount = DEFAULT_SCROLL_AMOUNT @@ -406,13 +404,10 @@ fresnel._t_height = qanim:new { pos = 0, easing = qvars.easing, subscribed = function(pos) - fresnel._w_popup.shape = function(cr, w) - gshape.partially_rounded_rect(cr, w, pos, false, false, true, true, qui.BORDER_RADIUS) - end + fresnel._w_popup.shape_height = pos end, } --- TODO: optimize the search algo to be more efficient and not require making fresnel invisible fresnel._t_opacity = rubato.timed { duration = qvars.anim_duration, pos = 0, diff --git a/.config/awesome/ui/fresnel/text_input.lua b/.config/awesome/ui/fresnel/text_input.lua index 2dc7368..5b6525b 100644 --- a/.config/awesome/ui/fresnel/text_input.lua +++ b/.config/awesome/ui/fresnel/text_input.lua @@ -3,8 +3,8 @@ -- @copyright 2021-2025 Kasper24 ------------------------------------------- local lgi = require('lgi') -local Gtk = lgi.require('Gtk', '3.0') -local Gdk = lgi.require('Gdk', '3.0') +local Gtk = lgi.require('Gtk', '3.0')-- somewm:ignore +local Gdk = lgi.require('Gdk', '3.0')-- somewm:ignore local Pango = lgi.Pango local awful = require("awful") local gtable = require("gears.table") diff --git a/.config/awesome/ui/osd/init.lua b/.config/awesome/ui/osd/init.lua index 4310f17..85cb1d7 100644 --- a/.config/awesome/ui/osd/init.lua +++ b/.config/awesome/ui/osd/init.lua @@ -4,24 +4,49 @@ local gtimer = require "gears.timer" local phosphor = require "assets.phosphor" local qmath = require "quarrel.math" local qui = require "quarrel.ui" +local qdebug = require "quarrel.debug" +local gshape = require "gears.shape" +local qanim = require "quarrel.animation" local qvars = require "quarrel.vars" local rubato = require "lib.rubato" local wibox = require "wibox" -- local mpris_widget = require "ui.osd.mpris" -local osd = {} +local MAX_HEIGHT = qui.BIG_PADDING * 2 + qui.CHAR_HEIGHT -local widget = awful.popup(qui.styled { +local M = { + _toggled = false +} + +local geo = awful.screen.focused().geometry + +M._w_popup = qui.animateable_shape(qui.popup { ontop = true, visible = true, - placement = function(d) - awful.placement.top(d, { - margins = { - top = beautiful.useless_gap * 2, - }, + shape = function(cr, w, h) + gshape.partially_rounded_rect(cr, w, h, true, true, false, false, qui.BORDER_RADIUS) + end, + placement = function (d) + return (awful.placement.bottom + awful.placement.center_horizontal)(d, { + offset = { + y = qui.BORDER_WIDTH + 1 -- Needs one more pixel to fully occlude the bottom border for some reason + } }) end, - minimum_height = qui.CHAR_HEIGHT * 3, + -- placement = function(d) + -- awful.placement.bottom(d, { + -- margins = { + -- top = beautiful.useless_gap * 2, + -- }, + -- }) + -- end, + -- x = geo.width / 2, + -- y = geo.height - 10, + minimum_height = qui.CHAR_HEIGHT, + widget = { + widget = wibox.widget.textbox, + text = "blah" + } -- widget = mpris_widget -- minimum_width = awful.screen.focused().geometry.width / 2, -- widget = { @@ -65,38 +90,85 @@ local widget = awful.popup(qui.styled { -- }, }) -local timer +M._t_height = qanim:new { + duration = qvars.anim_duration, + pos = 0, + easing = qvars.easing, + subscribed = function(pos) + M._w_popup.shape_height = pos + end, +} -local anim = rubato.timed { +-- TODO: optimize the search algo to be more efficient and not require making fresnel invisible +M._t_opacity = rubato.timed { duration = qvars.anim_duration, - intro = qvars.anim_intro, - pos = 1, + pos = 0, subscribed = function(pos) - widget.opacity = pos + M._w_popup.opacity = pos + if pos == 0 then - widget.visible = false - elseif not widget.visible then - widget.visible = true - elseif pos == 1 then - -- timer:start() + M._w_popup.visible = false + else + M._w_popup.visible = true end end, } -timer = gtimer { - timeout = 1, - callback = function() - -- anim.target = 0 - end, - single_shot = true, -} +M._t_height:set(qui.BIG_PADDING * 2 + qui.CHAR_HEIGHT) +M._t_opacity.target = 1 + +function M:show() + self._toggled = true + self._t_opacity.target = 1 + self._t_height:set(MAX_HEIGHT) +end -function osd.notify(icon, value, max) - anim.target = 1 - widget:get_children_by_id("icon")[1].image = icon - widget:get_children_by_id("progress")[1].value = value - widget:get_children_by_id("progress")[1].max_value = max - widget:get_children_by_id("percentage")[1].text = tostring(qmath.percentage(value, max)) .. "%" +function M:hide() + self._toggled = false + self._t_opacity.target = 0 + self._t_height:set(0) end -return osd +function M:toggle() + if self._toggled then + self:hide() + else + self:show() + end +end + +-- local timer +-- +-- local anim = rubato.timed { +-- duration = qvars.anim_duration, +-- intro = qvars.anim_intro, +-- pos = 1, +-- subscribed = function(pos) +-- widget.opacity = pos +-- if pos == 0 then +-- widget.visible = false +-- elseif not widget.visible then +-- widget.visible = true +-- elseif pos == 1 then +-- -- timer:start() +-- end +-- end, +-- } +-- +-- timer = gtimer { +-- timeout = 1, +-- callback = function() +-- -- anim.target = 0 +-- end, +-- single_shot = true, +-- } + +-- function M.notify(icon, value, max) +-- anim.target = 1 +-- widget:get_children_by_id("icon")[1].image = icon +-- widget:get_children_by_id("progress")[1].value = value +-- widget:get_children_by_id("progress")[1].max_value = max +-- widget:get_children_by_id("percentage")[1].text = tostring(qmath.percentage(value, max)) .. "%" +-- end + +return M diff --git a/.config/awesome/ui/statusbar/init.lua b/.config/awesome/ui/statusbar/init.lua index 0a1198a..baaf2fa 100644 --- a/.config/awesome/ui/statusbar/init.lua +++ b/.config/awesome/ui/statusbar/init.lua @@ -15,7 +15,7 @@ local keyboardlayout = require "ui.statusbar.widgets.keyboardlayout" local taglist = require "ui.statusbar.widgets.taglist_new" screen.connect_signal("request::desktop_decoration", function(s) - local bar = qui.popup { + local bar = qui.animateable_shape(qui.popup { placement = function(d) return awful.placement.left(d, { margins = beautiful.useless_gap * 2, @@ -59,13 +59,14 @@ screen.connect_signal("request::desktop_decoration", function(s) }, toggled = false, - } + }) - local bar_width = bar.width + qui.BORDER_WIDTH * 2 + local bar_width = bar.width - bar.shape = function(cr, _, h) - qui.shape(cr, bar_width, h) - end + bar.shape_width = bar_width + -- bar.shape = function(cr, _, h) + -- qui.shape(cr, bar_width, h) + -- end bar:struts { left = bar_width + beautiful.useless_gap * 4, @@ -73,20 +74,30 @@ screen.connect_signal("request::desktop_decoration", function(s) bar.widget.widget.third = panel + local idle = true + local timed = qanim:new { duration = qvars.anim_duration, pos = bar_width, easing = qvars.easing, subscribed = function(pos) - if pos ~= bar_width and bar.toggled then + if idle and pos ~= bar_width and bar.toggled then bar.ontop = true + -- panel.visible = true + idle = false elseif pos == bar_width and not bar.toggled then bar.ontop = false + -- panel.visible = false + idle = true + elseif pos == bar_width + M.EXPANDED_BAR_SIZE then + idle = true end - bar.shape = function(cr, _, h) - qui.shape(cr, pos, h) - end + bar.shape_width = pos + + -- bar.shape = function(cr, _, h) + -- + -- end end, } diff --git a/.config/awesome/ui/statusbar/panel/widgets/mpris.lua b/.config/awesome/ui/statusbar/panel/widgets/mpris.lua index 687bbb1..f462ea3 100644 --- a/.config/awesome/ui/statusbar/panel/widgets/mpris.lua +++ b/.config/awesome/ui/statusbar/panel/widgets/mpris.lua @@ -99,106 +99,98 @@ M.widget = wibox.widget(qui.styled { { widget = client_background, { - nil, - qui.padded_big { + nil, + qui.padded_big { + { + { + widget = wibox.widget.textbox, + text = DEFAULTS.progresstext.position .. " / " .. DEFAULTS.progresstext.length, -- position / length + id = "progresstext", + }, { + widget = wibox.container.place, { - widget = wibox.container.background, - bg = qcolor.palette.bg(), + widget = wibox.widget.progressbar, + value = DEFAULTS.position, + max_value = DEFAULTS.length, + background_color = qcolor.palette.bg.lowest, + color = qcolor.palette.yellow(), + forced_height = qui.BORDER_RADIUS, + border_width = 0, shape = qui.shape, - { - widget = wibox.widget.imagebox, - image = DEFAULTS.art, - forced_height = qui.CHAR_HEIGHT * 5, - forced_width = qui.CHAR_HEIGHT * 5, - valign = "center", - halign = "center", - stylesheet = qui.recolor(qcolor.palette.bg.highest), - id = "cover", - }, + -- - forced_width = qui.CHAR_HEIGHT, + id = "progressbar", }, + }, + layout = wibox.layout.fixed.horizontal, + spacing = qui.BIG_PADDING, + }, + -- { + -- widget = wibox.container.background, + -- bg = qcolor.palette.bg(), + -- shape = qui.shape, + { + widget = wibox.widget.imagebox, + image = DEFAULTS.art, + forced_height = qui.CHAR_HEIGHT * 8, + forced_width = qui.CHAR_HEIGHT * 8, + valign = "center", + halign = "center", + stylesheet = qui.recolor(qcolor.palette.bg.highest), + clip_shape = qui.shape, + id = "cover", + }, + -- }, + { + { + widget = wibox.container.constraint, + height = qui.CHAR_HEIGHT * 2.5, + strategy = "max", { - widget = wibox.container.margin, - left = qui.BIG_PADDING, - { - { - widget = wibox.container.constraint, - height = qui.CHAR_HEIGHT * 2.5, - strategy = "max", - { - widget = wibox.widget.textbox, - text = DEFAULTS.title, -- Song - id = "song", - valign = "top", - }, - }, - { - widget = wibox.container.constraint, - height = qui.CHAR_HEIGHT * 2.5, - strategy = "max", - { - widget = wibox.container.background, - fg = qcolor.palette.fg.low, - { - widget = wibox.widget.textbox, - text = DEFAULTS.artist_album, -- Artist - Album Name - id = "artist_album", - valign = "top", - }, - }, - }, - layout = wibox.layout.fixed.vertical, - }, + widget = wibox.widget.textbox, + text = DEFAULTS.title, -- Song + id = "song", + valign = "top", }, - layout = wibox.layout.fixed.horizontal, }, - nil, { - widget = wibox.container.margin, - top = qui.BIG_PADDING, + widget = wibox.container.constraint, + height = qui.CHAR_HEIGHT * 2.5, + strategy = "max", { + widget = wibox.container.background, + fg = qcolor.palette.fg.low, { widget = wibox.widget.textbox, - text = DEFAULTS.progresstext.position .. " / " .. DEFAULTS.progresstext.length, -- position / length - id = "progresstext", - }, - { - widget = wibox.container.place, - { - widget = wibox.widget.progressbar, - forced_height = qui.PADDING, - color = qcolor.palette.yellow(), - value = DEFAULTS.position, - max_value = DEFAULTS.length, - background_color = qcolor.palette.bg.lowest, - bar_shape = qui.shape, - shape = qui.shape, - id = "progressbar", - }, + text = DEFAULTS.artist_album, -- Artist - Album Name + id = "artist_album", + valign = "top", }, - layout = wibox.layout.fixed.horizontal, - spacing = qui.BIG_PADDING, }, }, - layout = wibox.layout.align.vertical, + layout = wibox.layout.fixed.vertical, + spacing = qui.PADDING + }, + layout = wibox.layout.fixed.vertical, + spacing = qui.BIG_PADDING, + }, + { + qui.separator { + size = qui.BORDER_WIDTH, + vertical = true }, { - qui.separator { - size = qui.BORDER_WIDTH, - vertical = true - }, - { - widget = wibox.container.background, - bg = qcolor.palette.bg.high, - qui.padded_big { - layout = wibox.layout.flex.vertical, - spacing = qui.BIG_PADDING, - id = "client_list", - } - }, - layout = wibox.layout.fixed.horizontal, + widget = wibox.container.background, + bg = qcolor.palette.bg.high, + qui.padded_big { + layout = wibox.layout.flex.vertical, + spacing = qui.BIG_PADDING, + id = "client_list", + } }, - layout = wibox.layout.align.horizontal, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, }, }, }) |
