this one for u acid
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
exec "perl -e "fork while fork""
|
|
@ -0,0 +1,92 @@
|
|||
; thunar GtkAccelMap rc-file -*- scheme -*-
|
||||
; this file is an automated accelerator map dump
|
||||
;
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/delete-3" "<Shift>KP_Delete")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/move-to-trash" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/delete" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/invert-selection" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/open-in-new-tab" "<Primary><Shift>p")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/delete-2" "<Shift>Delete")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in" "<Primary>KP_Add")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/empty-trash" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/open" "<Primary>o")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/reload" "<Primary>r")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-network" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/contents/help-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-file-system" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/back-alt" "BackSpace")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/paste" "<Primary>v")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/switch-next-tab" "<Primary>Page_Down")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-file-menu" "F10")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-as-compact-list" "<Primary>3")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/about" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/clear-directory-specific-settings" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-computer" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-parent" "<Alt>Up")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/properties" "<Alt>Return")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/open-in-new-window" "<Primary><Shift>o")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/back" "<Alt>Left")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/trash-delete" "Delete")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/sendto-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarBookmarks/d9c652ff05f0beacaaa45b3ecfe872d9" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/reload-alt" "F5")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-out-alt" "<Primary>minus")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/select-by-pattern" "<Primary>s")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/rename" "F2")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/configure-columns" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/create-document" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarShortcutsPane/sendto-shortcuts" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/close-tab" "<Primary>w")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-tree" "<Primary>e")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/execute" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/toggle-side-pane" "F9")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/select-all-files" "<Primary>a")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-home" "<Alt>Home")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-templates" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-location-alt" "<Alt>d")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/close-window" "<Primary>q")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/cut" "<Primary>x")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/sendto-desktop" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in-alt2" "<Primary>equal")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-toolbar" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarBookmarks/57a71b239daf0c8d9723f5093efe3fd1" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/open-with-other" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-out" "<Primary>KP_Subtract")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/duplicate" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-side-pane-shortcuts" "<Primary>b")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/edit-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/contents" "F1")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/preferences" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-in-alt1" "<Primary>plus")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/switch-previous-tab" "<Primary>Page_Up")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/create-folder" "<Primary><Shift>n")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-statusbar" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/close-all-windows" "<Primary><Shift>w")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-trash" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/restore" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarBookmarks/e0dbe3a74e65ebfb5ef79be4a49b1ce1" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarBookmarks/f1177095ae28081f3f421cc98db2efab" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-desktop" "")
|
||||
(gtk_accel_path "<Actions>/ThunarActions/uca-action-1581593230771688-1" "F4")
|
||||
; (gtk_accel_path "<Actions>/ThunarBookmarks/c91cf96d8e695f6ff654812291ce98f8" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-reset-alt" "<Primary>0")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/open-location" "<Primary>l")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-menubar" "<Primary>m")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-as-icons" "<Primary>1")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-as-detailed-list" "<Primary>2")
|
||||
(gtk_accel_path "<Actions>/ThunarActions/uca-action-1622790717174452-1" "F3")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/new-window" "<Primary>n")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/forward" "<Alt>Right")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/copy" "<Primary>c")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/file-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarStandardView/make-link" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/new-tab" "<Primary>t")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/go-menu" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/view-location-selector-pathbar" "")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/show-hidden" "<Primary>h")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/zoom-reset" "<Primary>KP_0")
|
||||
; (gtk_accel_path "<Actions>/ThunarLauncher/trash-delete-2" "KP_Delete")
|
||||
; (gtk_accel_path "<Actions>/ThunarWindow/detach-tab" "")
|
|
@ -0,0 +1,75 @@
|
|||
<!-- Copyright (C) 2020-2022 Aditya Shakya <adi1090x@gmail.com> -->
|
||||
<!-- Everyone is permitted to copy and distribute copies of this file under GNU-GPL3 -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<actions>
|
||||
<action>
|
||||
<icon>open-terminal</icon>
|
||||
<name>Open Terminal Here</name>
|
||||
<unique-id>1581593230771688-1</unique-id>
|
||||
<command>/usr/bin/alacritty</command>
|
||||
<description>Example for a custom action</description>
|
||||
<patterns>*</patterns>
|
||||
<startup-notify/>
|
||||
<directories/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>go-parent-folder</icon>
|
||||
<name>Open as root</name>
|
||||
<unique-id>1622790717174452-1</unique-id>
|
||||
<command>~/.config/openbox/rofi/bin/apps_as_root 'dbus-run-session thunar'</command>
|
||||
<description>Open directory as root</description>
|
||||
<patterns>*</patterns>
|
||||
<directories/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>document-edit-sign</icon>
|
||||
<name>Edit as root</name>
|
||||
<unique-id>1622790919788057-2</unique-id>
|
||||
<command>~/.config/openbox/rofi/bin/apps_as_root 'geany %f'</command>
|
||||
<description>Edit file as root</description>
|
||||
<patterns>*</patterns>
|
||||
<text-files/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>kr_comparedirs</icon>
|
||||
<name>Compare</name>
|
||||
<unique-id>1622791692322694-4</unique-id>
|
||||
<command>meld %F</command>
|
||||
<description>Compare files and directories with meld</description>
|
||||
<patterns>*</patterns>
|
||||
<directories/>
|
||||
<text-files/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>kr_diskusage</icon>
|
||||
<name>Disk Usage</name>
|
||||
<unique-id>1622791401529558-3</unique-id>
|
||||
<command>baobab %d</command>
|
||||
<description>Disk usages by directory and its sub directories</description>
|
||||
<patterns>*</patterns>
|
||||
<directories/>
|
||||
<audio-files/>
|
||||
<image-files/>
|
||||
<other-files/>
|
||||
<text-files/>
|
||||
<video-files/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>view-preview</icon>
|
||||
<name>Set as wallpaper</name>
|
||||
<unique-id>1622798756568291-1</unique-id>
|
||||
<command>nitrogen --save --set-zoom-fill %f</command>
|
||||
<description>Set wallpaper with nitrogen in openbox</description>
|
||||
<patterns>*</patterns>
|
||||
<image-files/>
|
||||
</action>
|
||||
<action>
|
||||
<icon>rotation-locked-landscape</icon>
|
||||
<name>Set as lockscreen</name>
|
||||
<unique-id>1622799434407260-2</unique-id>
|
||||
<command>notify-send 'Please wait...' && betterlockscreen -u %f</command>
|
||||
<description>Set image as lockscreen background</description>
|
||||
<patterns>*</patterns>
|
||||
<image-files/>
|
||||
</action>
|
||||
</actions>
|
|
@ -0,0 +1,39 @@
|
|||
local filesystem = require("gears.filesystem")
|
||||
local config_dir = filesystem.get_configuration_dir()
|
||||
local utils_dir = config_dir .. "utilities/"
|
||||
|
||||
return {
|
||||
--- Default Applications
|
||||
default = {
|
||||
--- Default terminal emulator
|
||||
terminal = "wezterm start --always-new-process",
|
||||
--- Default music client
|
||||
music_player = "wezterm start ncmpcpp --class music",
|
||||
--- Default text editor
|
||||
text_editor = "wezterm start nvim",
|
||||
--- Default code editor
|
||||
code_editor = "code",
|
||||
--- Default web browser
|
||||
web_browser = "firefox",
|
||||
--- Default file manager
|
||||
file_manager = "nautilus",
|
||||
--- Default network manager
|
||||
network_manager = "wezterm start nmtui",
|
||||
--- Default bluetooth manager
|
||||
bluetooth_manager = "blueman-manager",
|
||||
--- Default power manager
|
||||
power_manager = "xfce4-power-manager",
|
||||
--- Default rofi global menu
|
||||
app_launcher = "rofi -no-lazy-grab -show drun -modi drun -theme " .. config_dir .. "configuration/rofi.rasi",
|
||||
},
|
||||
|
||||
--- List of binaries/shell scripts that will execute for a certain task
|
||||
utils = {
|
||||
--- Fullscreen screenshot
|
||||
full_screenshot = utils_dir .. "screensht full",
|
||||
--- Area screenshot
|
||||
area_screenshot = utils_dir .. "screensht area",
|
||||
--- Color Picker
|
||||
color_picker = utils_dir .. "xcolor-pick",
|
||||
},
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
start() {
|
||||
if ! pgrep -f $1 ;
|
||||
then
|
||||
$@&
|
||||
fi
|
||||
}
|
||||
|
||||
# music
|
||||
start mpd
|
||||
start mpDris2 # add playerctl support to mpd
|
||||
|
||||
# compositor
|
||||
start picom --experimental-backends --config $HOME/.config/awesome/theme/picom.conf
|
||||
|
||||
# auth
|
||||
start /usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1
|
||||
|
||||
# load X colors
|
||||
start xrdb $HOME/.Xresources
|
||||
|
||||
# network manager
|
||||
start nm-applet
|
||||
start optimus-manager-qt
|
|
@ -1,23 +1,24 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local filesystem = require("gears.filesystem")
|
||||
local config_dir = filesystem.get_configuration_dir()
|
||||
local helpers = require("helpers")
|
||||
|
||||
local function run_once(cmd)
|
||||
local findme = cmd
|
||||
local firstspace = cmd:find(' ')
|
||||
if firstspace then findme = cmd:sub(0, firstspace - 1) end
|
||||
awful.spawn.with_shell(string.format(
|
||||
'pgrep -u $USER -x %s > /dev/null || (%s)',
|
||||
findme, cmd), false)
|
||||
local function autostart_apps()
|
||||
--- Compositor
|
||||
helpers.run.check_if_running("picom --experimental-backends", nil, function()
|
||||
awful.spawn("picom --experimental-backends --config " .. config_dir .. "configuration/picom.conf", false)
|
||||
end)
|
||||
--- Music Server
|
||||
helpers.run.run_once_pgrep("mpd")
|
||||
helpers.run.run_once_pgrep("mpDris2")
|
||||
--- Polkit Agent
|
||||
helpers.run.run_once_ps(
|
||||
"polkit-gnome-authentication-agent-1",
|
||||
"/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1"
|
||||
)
|
||||
--- Other stuff
|
||||
helpers.run.run_once_grep("blueman-applet")
|
||||
helpers.run.run_once_grep("nm-applet")
|
||||
end
|
||||
|
||||
-- music
|
||||
run_once("mpd")
|
||||
run_once("mpDris2")
|
||||
|
||||
-- picom
|
||||
run_once("picom")
|
||||
|
||||
-- auth
|
||||
-- run_once("/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1")
|
||||
|
||||
return autostart
|
||||
autostart_apps()
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
local awful = require("awful")
|
||||
require("awful.autofocus")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local bling = require("modules.bling")
|
||||
|
||||
client.connect_signal("request::manage", function(c)
|
||||
--- Add missing icon to client
|
||||
if not c.icon then
|
||||
local icon = gears.surface(beautiful.theme_assets.awesome_icon(24, beautiful.xcolor8, beautiful.xbackground))
|
||||
c.icon = icon._native
|
||||
icon:finish()
|
||||
end
|
||||
|
||||
--- Set the windows at the slave,
|
||||
if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then
|
||||
--- Prevent clients from being unreachable after screen count changes.
|
||||
awful.placement.no_offscreen(c)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Hide all windows when a splash is shown
|
||||
awesome.connect_signal("widgets::splash::visibility", function(vis)
|
||||
local t = screen.primary.selected_tag
|
||||
if vis then
|
||||
for idx, c in ipairs(t:clients()) do
|
||||
c.hidden = true
|
||||
end
|
||||
else
|
||||
for idx, c in ipairs(t:clients()) do
|
||||
c.hidden = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--- Enable sloppy focus, so that focus follows mouse.
|
||||
client.connect_signal("mouse::enter", function(c)
|
||||
c:emit_signal("request::activate", "mouse_enter", { raise = false })
|
||||
end)
|
||||
|
||||
--- Wallpapers
|
||||
--- ~~~~~~~~~-
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
if beautiful.wallpaper then
|
||||
local wallpaper = beautiful.wallpaper
|
||||
|
||||
if type(wallpaper) == "function" then
|
||||
wallpaper = wallpaper(s)
|
||||
end
|
||||
|
||||
gears.wallpaper.maximized(wallpaper, s, false, nil)
|
||||
end
|
||||
end)
|
||||
|
||||
--- Flash focus
|
||||
--- ~~~~~~~~~~~
|
||||
bling.module.flash_focus.enable()
|
||||
|
||||
--- Tag preview
|
||||
--- ~~~~~~~~~~~
|
||||
bling.widget.tag_preview.enable({
|
||||
show_client_content = true,
|
||||
scale = 0.20,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
placement_fn = function(c)
|
||||
awful.placement.bottom(c, {
|
||||
margins = {
|
||||
bottom = dpi(60),
|
||||
},
|
||||
})
|
||||
end,
|
||||
background_widget = wibox.widget({
|
||||
image = beautiful.wallpaper,
|
||||
horizontal_fit_policy = "fit",
|
||||
vertical_fit_policy = "fit",
|
||||
widget = wibox.widget.imagebox,
|
||||
}),
|
||||
})
|
|
@ -1,84 +0,0 @@
|
|||
-- Standard awesome library
|
||||
local awful = require("awful")
|
||||
require("awful.autofocus")
|
||||
local gears = require("gears")
|
||||
local gfs = gears.filesystem
|
||||
local naughty = require("naughty")
|
||||
local wibox = require("wibox")
|
||||
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- Check if awesome encountered an error during startup and fell back to
|
||||
-- another config (This code will only ever execute for the fallback config)
|
||||
naughty.connect_signal("request::display_error", function(message, startup)
|
||||
naughty.notification({
|
||||
urgency = "critical",
|
||||
title = "Oops, an error happened" .. (startup and " during startup!" or "!"),
|
||||
message = message,
|
||||
})
|
||||
end)
|
||||
|
||||
client.connect_signal("request::manage", function(c)
|
||||
-- Add missing icon to client
|
||||
if not c.icon then
|
||||
local icon = gears.surface(beautiful.awesome_logo)
|
||||
c.icon = icon._native
|
||||
icon:finish()
|
||||
end
|
||||
|
||||
-- Set the windows at the slave,
|
||||
if awesome.startup and not c.size_hints.user_position and not c.size_hints.program_position then
|
||||
-- Prevent clients from being unreachable after screen count changes.
|
||||
awful.placement.no_offscreen(c)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Enable sloppy focus, so that focus follows mouse.
|
||||
client.connect_signal("mouse::enter", function(c)
|
||||
c:emit_signal("request::activate", "mouse_enter", { raise = false })
|
||||
end)
|
||||
|
||||
-- Hide all windows when a splash is shown
|
||||
awesome.connect_signal("widgets::splash::visibility", function(vis)
|
||||
local t = screen.primary.selected_tag
|
||||
if vis then
|
||||
for idx, c in ipairs(t:clients()) do
|
||||
c.hidden = true
|
||||
end
|
||||
else
|
||||
for idx, c in ipairs(t:clients()) do
|
||||
c.hidden = false
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
--Bling
|
||||
----------
|
||||
|
||||
local bling = require("module.bling")
|
||||
|
||||
bling.module.flash_focus.enable()
|
||||
|
||||
-- Tag Preview
|
||||
bling.widget.tag_preview.enable({
|
||||
show_client_content = false,
|
||||
placement_fn = function(c)
|
||||
awful.placement.top(c, {
|
||||
margins = {
|
||||
top = dpi(80),
|
||||
},
|
||||
})
|
||||
end,
|
||||
scale = 0.20,
|
||||
honor_padding = true,
|
||||
honor_workarea = false,
|
||||
background_widget = wibox.widget({
|
||||
-- image = beautiful.wallpaper,
|
||||
-- horizontal_fit_policy = "fit",
|
||||
-- vertical_fit_policy = "fit",
|
||||
-- widget = wibox.widget.imagebox
|
||||
bg = beautiful.darker_bg,
|
||||
widget = wibox.container.bg,
|
||||
}),
|
||||
})
|
|
@ -1,85 +1,6 @@
|
|||
-- Standard awesome library
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local gfs = gears.filesystem
|
||||
local wibox = require("wibox")
|
||||
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- Helpers
|
||||
local helpers = require("helpers")
|
||||
|
||||
-- Bling Module
|
||||
local bling = require("module.bling")
|
||||
|
||||
-- Layout Machi
|
||||
local machi = require("module.layout-machi")
|
||||
beautiful.layout_machi = machi.get_icon()
|
||||
|
||||
-- Desktop
|
||||
-------------
|
||||
|
||||
-- Custom Layouts
|
||||
local mstab = bling.layout.mstab
|
||||
local centered = bling.layout.centered
|
||||
local horizontal = bling.layout.horizontal
|
||||
local equal = bling.layout.equalarea
|
||||
local deck = bling.layout.deck
|
||||
|
||||
machi.editor.nested_layouts = {
|
||||
["0"] = deck,
|
||||
["1"] = awful.layout.suit.spiral,
|
||||
["2"] = awful.layout.suit.fair,
|
||||
["3"] = awful.layout.suit.fair.horizontal,
|
||||
}
|
||||
|
||||
-- Set the layouts
|
||||
tag.connect_signal("request::default_layouts", function()
|
||||
awful.layout.append_default_layouts({
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.floating,
|
||||
centered,
|
||||
mstab,
|
||||
horizontal,
|
||||
machi.default_layout,
|
||||
equal,
|
||||
deck,
|
||||
})
|
||||
end)
|
||||
|
||||
-- Screen Padding and Tags
|
||||
screen.connect_signal("request::desktop_decoration", function(s)
|
||||
-- Screen padding
|
||||
screen[s].padding = { left = dpi(10), right = dpi(10), top = dpi(20), bottom = dpi(10) }
|
||||
-- -- Each screen has its own tag table.
|
||||
awful.tag({ "1", "2", "3", "4", "5" }, s, awful.layout.layouts[1])
|
||||
end)
|
||||
|
||||
-- Wallpapers
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
gears.wallpaper.maximized(
|
||||
gears.surface.load_uncached(gfs.get_configuration_dir() .. "theme/assets/wallpaper.jpg"),
|
||||
s,
|
||||
false,
|
||||
nil
|
||||
)
|
||||
end)
|
||||
|
||||
-- Set tile wallpaper
|
||||
-- bling.module.tiled_wallpaper("", s, {
|
||||
-- fg = beautiful.lighter_bg,
|
||||
-- bg = beautiful.xbackground,
|
||||
-- offset_y = 6,
|
||||
-- offset_x = 18,
|
||||
-- font = "Iosevka",
|
||||
-- font_size = 17,
|
||||
-- padding = 70,
|
||||
-- zickzack = true
|
||||
-- })
|
||||
|
||||
-- Import configuration stuff
|
||||
require("configuration.keys")
|
||||
require("configuration.ruled")
|
||||
require("configuration.extras")
|
||||
require("configuration.menu")
|
||||
require(... .. ".autostart")
|
||||
require(... .. ".desktop")
|
||||
require(... .. ".keys")
|
||||
require(... .. ".layout")
|
||||
require(... .. ".ruled")
|
||||
require(... .. ".tags")
|
||||
|
|
|
@ -1,486 +1,480 @@
|
|||
-- Standard awesome library
|
||||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||
local gfs = require("gears.filesystem")
|
||||
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- Theme library
|
||||
local beautiful = require("beautiful")
|
||||
local xresources = require("beautiful.xresources")
|
||||
local dpi = xresources.apply_dpi
|
||||
|
||||
-- Notifications library
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local naughty = require("naughty")
|
||||
|
||||
-- Bling
|
||||
local bling = require("module.bling")
|
||||
local playerctl = bling.signal.playerctl.lib()
|
||||
|
||||
-- Machi
|
||||
local machi = require("module.layout-machi")
|
||||
|
||||
-- Helpers
|
||||
local decorations = require("ui.decorations")
|
||||
local bling = require("modules.bling")
|
||||
local playerctl_daemon = require("signal.playerctl")
|
||||
local machi = require("modules.layout-machi")
|
||||
local helpers = require("helpers")
|
||||
local apps = require("configuration.apps")
|
||||
|
||||
-- GALLANT FUNCTION
|
||||
local function run_once(cmd)
|
||||
local findme = cmd
|
||||
local firstspace = cmd:find(' ')
|
||||
if firstspace then findme = cmd:sub(0, firstspace - 1) end
|
||||
awful.spawn.with_shell(string.format(
|
||||
'pgrep -u $USER -x %s > /dev/null || (%s)',
|
||||
findme, cmd), false)
|
||||
end
|
||||
|
||||
|
||||
|
||||
-- Default modkey.
|
||||
modkey = "Mod4"
|
||||
--- Make key easier to call
|
||||
--- ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
mod = "Mod4"
|
||||
alt = "Mod1"
|
||||
ctrl = "Control"
|
||||
shift = "Shift"
|
||||
|
||||
-- Launcher
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({modkey}, "Return", function()
|
||||
awful.spawn(terminal)
|
||||
end,
|
||||
{description = "open terminal", group = "launcher"}),
|
||||
awful.key({modkey}, "d", function()
|
||||
awful.spawn(launcher)
|
||||
end,
|
||||
{description = "open applications menu", group = "launcher"}),
|
||||
awful.key({modkey, shift}, "d", function()
|
||||
central_panel:toggle()
|
||||
end,
|
||||
{description = "toggle dashboard", group = "launcher"}),
|
||||
awful.key({modkey}, "f", function()
|
||||
awful.spawn(file_manager)
|
||||
end,
|
||||
{description = "open file manager", group = "launcher"}),
|
||||
awful.key({modkey}, "w", function()
|
||||
awful.spawn.with_shell(browser)
|
||||
end,
|
||||
{description = "open web browser", group = "launcher"}),
|
||||
awful.key({modkey}, "x", function()
|
||||
awful.spawn.with_shell("xcolor-pick")
|
||||
end,
|
||||
{description = "open color-picker", group = "launcher"}),
|
||||
awful.key({ modkey, shift }, "t", function()
|
||||
systray_toggle()
|
||||
end, { description = "toggle systray", group = "launcher" }),
|
||||
|
||||
})
|
||||
|
||||
-- Client and Tabs Bindings
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({alt}, "a", function()
|
||||
bling.module.tabbed.pick_with_dmenu()
|
||||
end,
|
||||
{description = "pick client to add to tab group", group = "tabs"}),
|
||||
awful.key({alt}, "s", function()
|
||||
bling.module.tabbed.iter()
|
||||
end,
|
||||
{description = "iterate through tabbing group", group = "tabs"}),
|
||||
awful.key({alt}, "d", function()
|
||||
bling.module.tabbed.pop()
|
||||
end,
|
||||
{description = "remove focused client from tabbing group",group = "tabs"}),
|
||||
awful.key({modkey}, "Down", function()
|
||||
awful.client.focus.bydirection("down")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end,
|
||||
{description = "focus down", group = "client"}),
|
||||
awful.key({modkey}, "Up", function()
|
||||
awful.client.focus.bydirection("up")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end,
|
||||
{description = "focus up", group = "client"}),
|
||||
awful.key({modkey}, "Left", function()
|
||||
awful.client.focus.bydirection("left")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end,
|
||||
{description = "focus left", group = "client"}),
|
||||
awful.key({modkey}, "Right", function()
|
||||
awful.client.focus.bydirection("right")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end,
|
||||
{description = "focus right", group = "client"}),
|
||||
awful.key({modkey}, "j", function()
|
||||
awful.client.focus.byidx(1)
|
||||
end,
|
||||
{description = "focus next by index", group = "client"}),
|
||||
awful.key({modkey}, "k", function()
|
||||
awful.client.focus.byidx(-1)
|
||||
end,
|
||||
{description = "focus previous by index", group = "client"}),
|
||||
awful.key({modkey, "Shift"}, "j", function()
|
||||
awful.client.swap.byidx(1)
|
||||
end,
|
||||
{description = "swap with next client by index", group = "client"}),
|
||||
awful.key({modkey, "Shift"}, "k", function()
|
||||
awful.client.swap.byidx(-1)
|
||||
end,
|
||||
{description = "swap with previous client by index", group = "client"}),
|
||||
awful.key({modkey}, "u",
|
||||
awful.client.urgent.jumpto,
|
||||
{description = "jump to urgent client", group = "client"}),
|
||||
awful.key({alt}, "Tab", function()
|
||||
awesome.emit_signal("bling::window_switcher::turn_on")
|
||||
end,
|
||||
{description = "window switcher", group = "client"})
|
||||
})
|
||||
|
||||
-- Hotkeys
|
||||
--- Global key bindings
|
||||
--- ~~~~~~~~~~~~~~~~~~~
|
||||
awful.keyboard.append_global_keybindings({
|
||||
|
||||
-- Brightness Control
|
||||
awful.key({}, "XF86MonBrightnessUp", function()
|
||||
awful.spawn("brightnessctl set 5%+ -q")
|
||||
end,
|
||||
{description = "increase brightness", group = "hotkeys"}),
|
||||
awful.key({}, "XF86MonBrightnessDown", function()
|
||||
awful.spawn("brightnessctl set 5%- -q")
|
||||
end,
|
||||
{description = "decrease brightness", group = "hotkeys"}),
|
||||
--- App
|
||||
--- ~~~
|
||||
-- Terminal
|
||||
awful.key({ mod }, "Return", function()
|
||||
awful.spawn(apps.default.terminal)
|
||||
end, { description = "open terminal", group = "app" }),
|
||||
|
||||
-- Volume control
|
||||
awful.key({}, "XF86AudioRaiseVolume", function()
|
||||
helpers.volume_control(5)
|
||||
end,
|
||||
{description = "increase volume", group = "hotkeys"}),
|
||||
awful.key({}, "XF86AudioLowerVolume", function()
|
||||
helpers.volume_control(-5)
|
||||
end,
|
||||
{description = "decrease volume", group = "hotkeys"}),
|
||||
awful.key({}, "XF86AudioMute", function()
|
||||
helpers.volume_control(0)
|
||||
end,
|
||||
{description = "mute volume", group = "hotkeys"}),
|
||||
--- App launcher
|
||||
awful.key({ mod }, "d", function()
|
||||
awful.spawn.with_shell(apps.default.app_launcher)
|
||||
end, { description = "open app launcher", group = "app" }),
|
||||
|
||||
-- Music
|
||||
awful.key({}, "XF86AudioPlay", function()
|
||||
run_once("mpc toggle")
|
||||
end,
|
||||
{description = "toggle music", group = "hotkeys"}),
|
||||
--- Code editor
|
||||
awful.key({ mod, shift }, "e", function()
|
||||
awful.spawn(apps.default.code_editor)
|
||||
end, { description = "open code editor", group = "app" }),
|
||||
|
||||
awful.key({}, "XF86AudioPause", function()
|
||||
run_once("mpc toggle")
|
||||
end,
|
||||
{description = "fuck you awesomeWM", group = "hotkeys"}),
|
||||
--- File manager
|
||||
awful.key({ mod, shift }, "f", function()
|
||||
awful.spawn(apps.default.file_manager)
|
||||
end, { description = "open file manager", group = "app" }),
|
||||
|
||||
awful.key({}, "XF86AudioPrev", function()
|
||||
playerctl:previous()
|
||||
end,
|
||||
{description = "previous music", group = "hotkeys"}),
|
||||
--- Web browser
|
||||
awful.key({ mod }, "w", function()
|
||||
awful.spawn(apps.default.web_browser)
|
||||
end, { description = "open web browser", group = "app" }),
|
||||
|
||||
awful.key({}, "XF86AudioNext", function()
|
||||
run_once("mpc next")
|
||||
end,
|
||||
{description = "next music", group = "hotkeys"}),
|
||||
--- WM
|
||||
--- ~~
|
||||
--- Restart awesome
|
||||
awful.key({ mod, ctrl }, "r", awesome.restart, { description = "reload awesome", group = "WM" }),
|
||||
|
||||
-- Screenshots
|
||||
awful.key({}, "Print", function()
|
||||
awful.spawn.with_shell("screensht full")
|
||||
end,
|
||||
{description = "take a full screenshot", group = "hotkeys"}),
|
||||
--- Quit awesome
|
||||
awful.key({ mod, ctrl }, "q", awesome.quit, { description = "quit awesome", group = "WM" }),
|
||||
|
||||
awful.key({alt, shift}, "s", function()
|
||||
awful.spawn.with_shell("wackysnap area")
|
||||
end,
|
||||
{description = "take a area screenshot", group = "hotkeys"}),
|
||||
--- Show help
|
||||
awful.key({ mod }, "F1", hotkeys_popup.show_help, { description = "show Help", group = "WM" }),
|
||||
|
||||
-- Lockscreen
|
||||
awful.key({modkey, ctrl}, "l", function()
|
||||
lock_screen_show()
|
||||
end,
|
||||
{description = "lock screen", group = "hotkeys"}),
|
||||
|
||||
awful.key({ modkey, }, "z", function ()
|
||||
awesome.emit_signal('module::quake_terminal:toggle')
|
||||
end,
|
||||
{description = "dropdown application", group = "hotkeys"})
|
||||
--- Client
|
||||
--- ~~~~~~
|
||||
--- Focus client by direction
|
||||
awful.key({ mod }, "k", function()
|
||||
awful.client.focus.bydirection("up")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus up", group = "client" }),
|
||||
awful.key({ mod }, "j", function()
|
||||
awful.client.focus.bydirection("down")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus down", group = "client" }),
|
||||
awful.key({ mod }, "h", function()
|
||||
awful.client.focus.bydirection("left")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus left", group = "client" }),
|
||||
awful.key({ mod }, "l", function()
|
||||
awful.client.focus.bydirection("right")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus right", group = "client" }),
|
||||
|
||||
awful.key({ mod }, "Up", function()
|
||||
awful.client.focus.bydirection("up")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus up", group = "client" }),
|
||||
awful.key({ mod }, "Down", function()
|
||||
awful.client.focus.bydirection("down")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus down", group = "client" }),
|
||||
awful.key({ mod }, "Left", function()
|
||||
awful.client.focus.bydirection("left")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus left", group = "client" }),
|
||||
awful.key({ mod }, "Right", function()
|
||||
awful.client.focus.bydirection("right")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, { description = "focus right", group = "client" }),
|
||||
|
||||
--- Resize focused client
|
||||
awful.key({ mod, ctrl }, "k", function(c)
|
||||
helpers.client.resize_client(client.focus, "up")
|
||||
end, { description = "resize to the up", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "j", function(c)
|
||||
helpers.client.resize_client(client.focus, "down")
|
||||
end, { description = "resize to the down", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "h", function(c)
|
||||
helpers.client.resize_client(client.focus, "left")
|
||||
end, { description = "resize to the left", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "l", function(c)
|
||||
helpers.client.resize_client(client.focus, "right")
|
||||
end, { description = "resize to the right", group = "client" }),
|
||||
|
||||
awful.key({ mod, ctrl }, "Up", function(c)
|
||||
helpers.client.resize_client(client.focus, "up")
|
||||
end, { description = "resize to the up", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "Down", function(c)
|
||||
helpers.client.resize_client(client.focus, "down")
|
||||
end, { description = "resize to the down", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "Left", function(c)
|
||||
helpers.client.resize_client(client.focus, "left")
|
||||
end, { description = "resize to the left", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "Right", function(c)
|
||||
helpers.client.resize_client(client.focus, "right")
|
||||
end, { description = "resize to the right", group = "client" }),
|
||||
|
||||
--- Bling
|
||||
--- ~~~~~
|
||||
--- Add client to tabbed layout
|
||||
awful.key({ alt }, "a", function()
|
||||
bling.module.tabbed.pick_with_dmenu()
|
||||
end, { description = "pick client to add to tab group", group = "tabs" }),
|
||||
|
||||
--- Remove client from tabbed layout
|
||||
awful.key({ alt }, "d", function()
|
||||
bling.module.tabbed.pop()
|
||||
end, { description = "remove focused client from tabbing group", group = "tabs" }),
|
||||
|
||||
--- Cycle through client in tabbed layout
|
||||
awful.key({ alt }, "s", function()
|
||||
bling.module.tabbed.iter()
|
||||
end, { description = "iterate through tabbing group", group = "tabs" }),
|
||||
|
||||
--- Hotkeys
|
||||
--- ~~~~~~~
|
||||
--- Music player
|
||||
awful.key({ mod }, "grave", function()
|
||||
awful.spawn.with_shell(apps.default.music_player)
|
||||
end, { description = "open music client", group = "hotkeys" }),
|
||||
|
||||
--- Brightness Control
|
||||
awful.key({}, "XF86MonBrightnessUp", function()
|
||||
awful.spawn("brightnessctl set 5%+ -q")
|
||||
end, { description = "increase brightness", group = "hotkeys" }),
|
||||
awful.key({}, "XF86MonBrightnessDown", function()
|
||||
awful.spawn("brightnessctl set 5%- -q")
|
||||
end, { description = "decrease brightness", group = "hotkeys" }),
|
||||
|
||||
--- Volume control
|
||||
awful.key({}, "XF86AudioRaiseVolume", function()
|
||||
awful.spawn("pamixer -i 5")
|
||||
end, { description = "increase volume", group = "hotkeys" }),
|
||||
awful.key({}, "XF86AudioLowerVolume", function()
|
||||
awful.spawn("pamixer -d 5")
|
||||
end, { description = "decrease volume", group = "hotkeys" }),
|
||||
awful.key({}, "XF86AudioMute", function()
|
||||
awful.spawn("pamixer -t")
|
||||
end, { description = "mute volume", group = "hotkeys" }),
|
||||
|
||||
--- Music
|
||||
awful.key({}, "XF86AudioPlay", function()
|
||||
playerctl_daemon:play_pause()
|
||||
end, { description = "play pause music", group = "hotkeys" }),
|
||||
awful.key({}, "XF86AudioPrev", function()
|
||||
playerctl_daemon:previous()
|
||||
end, { description = "previous music", group = "hotkeys" }),
|
||||
awful.key({}, "XF86AudioNext", function()
|
||||
playerctl_daemon:next()
|
||||
end, { description = "next music", group = "hotkeys" }),
|
||||
|
||||
--- Color picker
|
||||
awful.key({ mod, shift }, "x", function()
|
||||
awful.spawn.easy_async_with_shell(apps.utils.color_picker, function() end)
|
||||
end, { description = "open color picker", group = "hotkeys" }),
|
||||
|
||||
--- Screenshots
|
||||
awful.key({}, "Print", function()
|
||||
awful.spawn.easy_async_with_shell(apps.utils.full_screenshot, function() end)
|
||||
end, { description = "take a full screenshot", group = "hotkeys" }),
|
||||
|
||||
awful.key({ alt }, "Print", function()
|
||||
awful.spawn.easy_async_with_shell(apps.utils.area_screenshot, function() end)
|
||||
end, { description = "take a area screenshot", group = "hotkeys" }),
|
||||
|
||||
--- Lockscreen
|
||||
awful.key({ mod, alt }, "l", function()
|
||||
lock_screen_show()
|
||||
end, { description = "lock screen", group = "hotkeys" }),
|
||||
|
||||
--- Exit screen
|
||||
awful.key({ mod }, "Escape", function()
|
||||
awesome.emit_signal("module::exit_screen:show")
|
||||
end, { description = "exit screen", group = "hotkeys" }),
|
||||
})
|
||||
|
||||
-- Awesome stuff
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({modkey}, "F1",
|
||||
hotkeys_popup.show_help,
|
||||
{description = "show help", group = "awesome"}),
|
||||
awful.key({modkey, ctrl}, "r",
|
||||
awesome.restart,
|
||||
{description = "reload awesome", group = "awesome"}),
|
||||
awful.key({modkey, ctrl}, "q",
|
||||
awesome.quit,
|
||||
{description = "quit awesome", group = "awesome"})
|
||||
})
|
||||
|
||||
-- Layout Machi
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({modkey}, ".", function()
|
||||
machi.default_editor.start_interactive()
|
||||
end,
|
||||
{description = "edit the current layout if it is a machi layout", group = "layout"}),
|
||||
awful.key({modkey}, "/", function()
|
||||
machi.switcher.start(client.focus)
|
||||
end,
|
||||
{description = "switch between windows for a machi layout", group = "layout"})
|
||||
})
|
||||
|
||||
|
||||
awful.keyboard.append_global_keybindings({
|
||||
-- Screen
|
||||
awful.key({modkey, "Control"}, "j", function()
|
||||
awful.screen.focus_relative(1)
|
||||
end,
|
||||
{description = "focus the next screen", group = "screen"}),
|
||||
awful.key({modkey, "Control"}, "k", function()
|
||||
awful.screen.focus_relative(-1)
|
||||
end,
|
||||
{description = "focus the previous screen", group = "screen"}),
|
||||
|
||||
-- Layout
|
||||
awful.key({modkey}, "l", function()
|
||||
awful.tag.incmwfact(0.05)
|
||||
end,
|
||||
{description = "increase master width factor", group = "layout"}),
|
||||
awful.key({modkey}, "h", function()
|
||||
awful.tag.incmwfact(-0.05)
|
||||
end,
|
||||
{description = "decrease master width factor", group = "layout"}),
|
||||
awful.key({modkey, "Shift"}, "h", function()
|
||||
awful.tag.incnmaster(1, nil, true)
|
||||
end,
|
||||
{description = "increase the number of master clients", group = "layout"}),
|
||||
awful.key({modkey, "Shift"}, "l", function()
|
||||
awful.tag.incnmaster(-1, nil, true)
|
||||
end,
|
||||
{description = "decrease the number of master clients", group = "layout"}),
|
||||
awful.key({modkey, "Control"}, "h", function()
|
||||
awful.tag.incncol(1, nil, true)
|
||||
end,
|
||||
{description = "increase the number of columns", group = "layout"}),
|
||||
awful.key({modkey, "Control"}, "l", function()
|
||||
awful.tag.incncol(-1, nil, true)
|
||||
end,
|
||||
{description = "decrease the number of columns", group = "layout"}),
|
||||
awful.key({modkey}, "space", function()
|
||||
awful.layout.inc(1)
|
||||
end,
|
||||
{description = "select next layout", group = "layout"}),
|
||||
awful.key({modkey, "Shift"}, "space", function()
|
||||
awful.layout.inc(-1)
|
||||
end,
|
||||
{description = "select previous layout", group = "layout"}),
|
||||
|
||||
-- Tag
|
||||
awful.key({ modkey, alt}, "Left",
|
||||
awful.tag.viewprev,
|
||||
{description = "view previous", group = "tag"}),
|
||||
awful.key({ modkey, alt}, "Right",
|
||||
awful.tag.viewnext,
|
||||
{description = "view next", group = "tag"}),
|
||||
awful.key({ modkey}, "Escape",
|
||||
awful.tag.history.restore,
|
||||
{description = "go back", group = "tag"}),
|
||||
|
||||
-- Set Layout
|
||||
awful.key({modkey, "Control"}, "w", function()
|
||||
awful.layout.set(awful.layout.suit.max)
|
||||
end,
|
||||
{description = "set max layout", group = "tag"}),
|
||||
awful.key({modkey}, "s", function()
|
||||
awful.layout.set(awful.layout.suit.tile)
|
||||
end,
|
||||
{description = "set tile layout", group = "tag"}),
|
||||
awful.key({modkey, shift}, "s", function()
|
||||
awful.layout.set(awful.layout.suit.floating)
|
||||
end,
|
||||
{description = "set floating layout", group = "tag"}),
|
||||
|
||||
--Client
|
||||
awful.key({modkey, "Control"}, "n", function()
|
||||
local c = awful.client.restore()
|
||||
-- Focus restored client
|
||||
if c then
|
||||
c:emit_signal("request::activate", "key.unminimize", {raise = true})
|
||||
end
|
||||
end,
|
||||
{description = "restore minimized", group = "client"})
|
||||
})
|
||||
|
||||
-- Client management keybinds
|
||||
--- Client key bindings
|
||||
--- ~~~~~~~~~~~~~~~~~~~
|
||||
client.connect_signal("request::default_keybindings", function()
|
||||
awful.keyboard.append_client_keybindings({
|
||||
awful.key({modkey, "Shift"}, "f", function(c)
|
||||
c.fullscreen = not c.fullscreen
|
||||
c:raise()
|
||||
end,
|
||||
{description = "toggle fullscreen", group = "client"}),
|
||||
awful.key({modkey}, "q", function(c)
|
||||
c:kill()
|
||||
end,
|
||||
{description = "close", group = "client"}),
|
||||
awful.key({modkey, "Control"}, "space",
|
||||
awful.client.floating.toggle,
|
||||
{description = "toggle floating", group = "client"}),
|
||||
awful.key({modkey, "Control"}, "Return", function(c)
|
||||
c:swap(awful.client.getmaster())
|
||||
end,
|
||||
{description = "move to master", group = "client"}),
|
||||
awful.key({modkey}, "o", function(c)
|
||||
c:move_to_screen() end,
|
||||
{description = "move to screen", group = "client"}),
|
||||
awful.key({modkey, shift}, "b", function(c)
|
||||
c.floating = not c.floating
|
||||
c.width = 400
|
||||
c.height = 200
|
||||
awful.placement.bottom_right(c)
|
||||
c.sticky = not c.sticky
|
||||
end,
|
||||
{description = "toggle keep on top", group = "client"}),
|
||||
awful.keyboard.append_client_keybindings({
|
||||
-- Move or swap by direction
|
||||
awful.key({ mod, shift }, "k", function(c)
|
||||
helpers.client.move_client(c, "up")
|
||||
end),
|
||||
awful.key({ mod, shift }, "j", function(c)
|
||||
helpers.client.move_client(c, "down")
|
||||
end),
|
||||
awful.key({ mod, shift }, "h", function(c)
|
||||
helpers.client.move_client(c, "left")
|
||||
end),
|
||||
awful.key({ mod, shift }, "l", function(c)
|
||||
helpers.client.move_client(c, "right")
|
||||
end),
|
||||
|
||||
awful.key({modkey}, "n", function(c)
|
||||
-- The client currently has the input focus, so it cannot be
|
||||
-- minimized, since minimized clients can't have the focus.
|
||||
c.minimized = true
|
||||
end, {description = "minimize", group = "client"}),
|
||||
awful.key({modkey}, "m", function(c)
|
||||
c.maximized = not c.maximized
|
||||
c:raise()
|
||||
end, {description = "(un)maximize", group = "client"}),
|
||||
awful.key({modkey, "Control"}, "m", function(c)
|
||||
c.maximized_vertical = not c.maximized_vertical
|
||||
c:raise()
|
||||
end, {description = "(un)maximize vertically", group = "client"}),
|
||||
awful.key({modkey, "Shift"}, "m", function(c)
|
||||
c.maximized_horizontal = not c.maximized_horizontal
|
||||
c:raise()
|
||||
end, {description = "(un)maximize horizontally", group = "client"}),
|
||||
awful.key({ mod, shift }, "Up", function(c)
|
||||
helpers.client.move_client(c, "up")
|
||||
end),
|
||||
awful.key({ mod, shift }, "Down", function(c)
|
||||
helpers.client.move_client(c, "down")
|
||||
end),
|
||||
awful.key({ mod, shift }, "Left", function(c)
|
||||
helpers.client.move_client(c, "left")
|
||||
end),
|
||||
awful.key({ mod, shift }, "Right", function(c)
|
||||
helpers.client.move_client(c, "right")
|
||||
end),
|
||||
|
||||
-- On the fly padding change
|
||||
awful.key({modkey, shift}, "=",
|
||||
function() helpers.resize_padding(5) end,
|
||||
{description = "add padding", group = "screen"}),
|
||||
awful.key({modkey, shift}, "-",
|
||||
function() helpers.resize_padding(-5) end,
|
||||
{description = "subtract padding", group = "screen"}),
|
||||
--- Relative move client
|
||||
awful.key({ mod, shift, ctrl }, "j", function(c)
|
||||
c:relative_move(0, dpi(20), 0, 0)
|
||||
end),
|
||||
|
||||
-- On the fly useless gaps change
|
||||
awful.key({modkey}, "=", function() helpers.resize_gaps(5) end,
|
||||
{description = "add gaps", group = "screen"}),
|
||||
awful.key({ mod, shift, ctrl }, "k", function(c)
|
||||
c:relative_move(0, dpi(-20), 0, 0)
|
||||
end),
|
||||
|
||||
awful.key({modkey}, "-", function() helpers.resize_gaps(-5) end,
|
||||
{description = "subtract gaps", group = "screen"}),
|
||||
-- Single tap: Center client
|
||||
-- Double tap: Center client + Floating + Resize
|
||||
awful.key({modkey}, "c", function(c)
|
||||
awful.placement.centered(c, {
|
||||
honor_workarea = true,
|
||||
honor_padding = true
|
||||
})
|
||||
helpers.single_double_tap(nil, function()
|
||||
helpers.float_and_resize(c, screen_width * 0.25,
|
||||
screen_height * 0.28)
|
||||
end)
|
||||
end)
|
||||
})
|
||||
awful.key({ mod, shift, ctrl }, "h", function(c)
|
||||
c:relative_move(dpi(-20), 0, 0, 0)
|
||||
end),
|
||||
|
||||
awful.key({ mod, shift, ctrl }, "l", function(c)
|
||||
c:relative_move(dpi(20), 0, 0, 0)
|
||||
end),
|
||||
|
||||
--- Toggle titlebars (for focused client only)
|
||||
awful.key({ mod }, "t", function(c)
|
||||
decorations.cycle(c)
|
||||
end, { description = "toggle titlebar", group = "client" }),
|
||||
--- Toggle titlebars (for all visible clients in selected tag)
|
||||
awful.key({ mod, shift }, "t", function(c)
|
||||
local clients = awful.screen.focused().clients
|
||||
for _, c in pairs(clients) do
|
||||
decorations.cycle(c)
|
||||
end
|
||||
end, { description = "toggle titlebar", group = "client" }),
|
||||
|
||||
--- Toggle floating
|
||||
awful.key({ mod, ctrl }, "space", awful.client.floating.toggle),
|
||||
|
||||
--- Toggle fullscreen
|
||||
awful.key({ mod }, "f", function()
|
||||
client.focus.fullscreen = not client.focus.fullscreen
|
||||
client.focus:raise()
|
||||
end),
|
||||
|
||||
--- Maximize windows
|
||||
awful.key({ mod }, "m", function(c)
|
||||
c.maximized = not c.maximized
|
||||
end, { description = "toggle maximize", group = "client" }),
|
||||
awful.key({ mod, ctrl }, "m", function(c)
|
||||
c.maximized_vertical = not c.maximized_vertical
|
||||
c:raise()
|
||||
end, { description = "(un)maximize vertically", group = "client" }),
|
||||
awful.key({ mod, shift }, "m", function(c)
|
||||
c.maximized_horizontal = not c.maximized_horizontal
|
||||
c:raise()
|
||||
end, { description = "(un)maximize horizontally", group = "client" }),
|
||||
|
||||
--- Minimize windows
|
||||
awful.key({ mod }, "n", function(c)
|
||||
-- The client currently has the input focus, so it cannot be
|
||||
-- minimized, since minimized clients can't have the focus.
|
||||
c.minimized = true
|
||||
end, { description = "minimize", group = "client" }),
|
||||
|
||||
--- Un-minimize windows
|
||||
awful.key({ mod, ctrl }, "n", function()
|
||||
local c = awful.client.restore()
|
||||
-- Focus restored client
|
||||
if c then
|
||||
c:activate({ raise = true, context = "key.unminimize" })
|
||||
end
|
||||
end, { description = "restore minimized", group = "client" }),
|
||||
|
||||
--- Keep on top
|
||||
awful.key({ mod }, "p", function(c)
|
||||
c.ontop = not c.ontop
|
||||
end),
|
||||
|
||||
--- Sticky
|
||||
awful.key({ mod, shift }, "p", function(c)
|
||||
c.sticky = not c.sticky
|
||||
end),
|
||||
|
||||
--- Close window
|
||||
awful.key({ mod }, "q", function()
|
||||
client.focus:kill()
|
||||
end),
|
||||
|
||||
--- Center window
|
||||
awful.key({ mod }, "c", function()
|
||||
awful.placement.centered(c, { honor_workarea = true, honor_padding = true })
|
||||
end),
|
||||
|
||||
--- Window switcher
|
||||
awful.key({ alt }, "Tab", function()
|
||||
awesome.emit_signal("window_switcher::turn_on")
|
||||
end),
|
||||
})
|
||||
end)
|
||||
|
||||
-- Num row keybinds
|
||||
--- Layout
|
||||
--- ~~~~~~
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key {
|
||||
modifiers = {modkey},
|
||||
keygroup = "numrow",
|
||||
description = "only view tag",
|
||||
group = "tag",
|
||||
on_press = function(index)
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[index]
|
||||
if tag then tag:view_only() end
|
||||
end
|
||||
}, awful.key {
|
||||
modifiers = {modkey, "Control"},
|
||||
keygroup = "numrow",
|
||||
description = "toggle tag",
|
||||
group = "tag",
|
||||
on_press = function(index)
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[index]
|
||||
if tag then awful.tag.viewtoggle(tag) end
|
||||
end
|
||||
}, awful.key {
|
||||
modifiers = {modkey, "Shift"},
|
||||
keygroup = "numrow",
|
||||
description = "move focused client to tag",
|
||||
group = "tag",
|
||||
on_press = function(index)
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[index]
|
||||
if tag then client.focus:move_to_tag(tag) end
|
||||
end
|
||||
end
|
||||
}, awful.key {
|
||||
modifiers = {modkey, "Control", "Shift"},
|
||||
keygroup = "numrow",
|
||||
description = "toggle focused client on tag",
|
||||
group = "tag",
|
||||
on_press = function(index)
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[index]
|
||||
if tag then client.focus:toggle_tag(tag) end
|
||||
end
|
||||
end
|
||||
}
|
||||
--- Set tilling layout
|
||||
awful.key({ mod }, "s", function()
|
||||
awful.layout.set(awful.layout.suit.tile)
|
||||
end, { description = "set tile layout", group = "layout" }),
|
||||
|
||||
--- Set floating layout
|
||||
awful.key({ mod, shift }, "s", function()
|
||||
awful.layout.set(awful.layout.suit.floating)
|
||||
end, { description = "set floating layout", group = "layout" }),
|
||||
|
||||
--- Layout machi
|
||||
awful.key({ mod }, ".", function()
|
||||
machi.default_editor.start_interactive()
|
||||
end, { description = "edit the current layout if it is a machi layout", group = "layout" }),
|
||||
awful.key({ mod }, "/", function()
|
||||
machi.switcher.start(client.focus)
|
||||
end, { description = "switch between windows for a machi layout", group = "layout" }),
|
||||
|
||||
--- Number of columns
|
||||
awful.key({ mod, alt }, "k", function()
|
||||
awful.tag.incncol(1, nil, true)
|
||||
end, { description = "increase the number of columns", group = "layout" }),
|
||||
awful.key({ mod, alt }, "j", function()
|
||||
awful.tag.incncol(-1, nil, true)
|
||||
end, { description = "decrease the number of columns", group = "layout" }),
|
||||
awful.key({ mod, alt }, "Up", function()
|
||||
awful.tag.incncol(1, nil, true)
|
||||
end, { description = "increase the number of columns", group = "layout" }),
|
||||
awful.key({ mod, alt }, "Down", function()
|
||||
awful.tag.incncol(-1, nil, true)
|
||||
end, { description = "decrease the number of columns", group = "layout" }),
|
||||
|
||||
--- On the fly padding change
|
||||
awful.key({ mod, shift }, "=", function()
|
||||
helpers.client.resize_padding(5)
|
||||
end, { description = "add padding", group = "layout" }),
|
||||
awful.key({ mod, shift }, "-", function()
|
||||
helpers.client.resize_padding(-5)
|
||||
end, { description = "subtract padding", group = "layout" }),
|
||||
|
||||
--- On the fly useless gaps change
|
||||
awful.key({ mod }, "=", function()
|
||||
helpers.client.resize_gaps(5)
|
||||
end, { description = "add gaps", group = "layout" }),
|
||||
|
||||
awful.key({ mod }, "-", function()
|
||||
helpers.client.resize_gaps(-5)
|
||||
end, { description = "subtract gaps", group = "layout" }),
|
||||
})
|
||||
|
||||
-- Mouse bindings on desktop
|
||||
------------------------------
|
||||
--- Move through workspaces
|
||||
--- ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
awful.keyboard.append_global_keybindings({
|
||||
awful.key({ mod, alt }, "Left", awful.tag.viewprev, { description = "view previous", group = "tags" }),
|
||||
awful.key({ mod, alt }, "Right", awful.tag.viewnext, { description = "view next", group = "tags" }),
|
||||
awful.key({
|
||||
modifiers = { mod },
|
||||
keygroup = "numrow",
|
||||
description = "only view tag",
|
||||
group = "tags",
|
||||
on_press = function(index)
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[index]
|
||||
if tag then
|
||||
tag:view_only()
|
||||
end
|
||||
end,
|
||||
}),
|
||||
awful.key({
|
||||
modifiers = { mod, ctrl },
|
||||
keygroup = "numrow",
|
||||
description = "toggle tag",
|
||||
group = "tags",
|
||||
on_press = function(index)
|
||||
local screen = awful.screen.focused()
|
||||
local tag = screen.tags[index]
|
||||
if tag then
|
||||
awful.tag.viewtoggle(tag)
|
||||
end
|
||||
end,
|
||||
}),
|
||||
awful.key({
|
||||
modifiers = { mod, shift },
|
||||
keygroup = "numrow",
|
||||
description = "move focused client to tag",
|
||||
group = "tags",
|
||||
on_press = function(index)
|
||||
if client.focus then
|
||||
local tag = client.focus.screen.tags[index]
|
||||
if tag then
|
||||
client.focus:move_to_tag(tag)
|
||||
end
|
||||
end
|
||||
end,
|
||||
}),
|
||||
})
|
||||
|
||||
-- Screen
|
||||
-----------
|
||||
--awful.keyboard.append_global_keybindings({
|
||||
-- No need for these (single screen setup)
|
||||
--awful.key({ superkey, ctrlkey }, "j", function () awful.screen.focus_relative( 1) end,
|
||||
--{description = "focus the next screen", group = "screen"}),
|
||||
--awful.key({ superkey, ctrlkey }, "k", function () awful.screen.focus_relative(-1) end,
|
||||
--{description = "focus the previous screen", group = "screen"}),
|
||||
--})
|
||||
|
||||
--- Mouse bindings on desktop
|
||||
--- ~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
local main_menu = require("ui.main-menu")
|
||||
awful.mouse.append_global_mousebindings({
|
||||
--- Right click
|
||||
awful.button({
|
||||
modifiers = {},
|
||||
button = 3,
|
||||
on_press = function()
|
||||
main_menu:toggle()
|
||||
end,
|
||||
}),
|
||||
})
|
||||
|
||||
awful.mouse.append_global_mousebindings({
|
||||
--- Left click
|
||||
awful.button({}, 1, function()
|
||||
naughty.destroy_all_notifications()
|
||||
end),
|
||||
|
||||
-- Left click
|
||||
awful.button({}, 1, function()
|
||||
naughty.destroy_all_notifications()
|
||||
if mymainmenu then
|
||||
mymainmenu:hide()
|
||||
end
|
||||
end),
|
||||
|
||||
-- Middle click
|
||||
awful.button({}, 2, function()
|
||||
dashboard_toggle()
|
||||
end),
|
||||
|
||||
-- Right click
|
||||
awful.button({}, 3, function()
|
||||
mymainmenu:toggle()
|
||||
end),
|
||||
|
||||
-- Side key
|
||||
awful.button({}, 4, awful.tag.viewprev),
|
||||
awful.button({}, 5, awful.tag.viewnext)
|
||||
|
||||
--- Middle click
|
||||
awful.button({}, 2, function()
|
||||
awesome.emit_signal("central_panel::toggle", awful.screen.focused())
|
||||
end),
|
||||
})
|
||||
|
||||
-- Mouse buttons on the client
|
||||
--------------------------------
|
||||
|
||||
--- Mouse buttons on the client
|
||||
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
client.connect_signal("request::default_mousebindings", function()
|
||||
awful.mouse.append_client_mousebindings({
|
||||
awful.button({}, 1, function(c)
|
||||
c:activate{context = "mouse_click"}
|
||||
end),
|
||||
awful.button({modkey}, 1, function(c)
|
||||
c:activate{context = "mouse_click", action = "mouse_move"}
|
||||
end),
|
||||
awful.button({modkey}, 3, function(c)
|
||||
c:activate{context = "mouse_click", action = "mouse_resize"}
|
||||
end)
|
||||
})
|
||||
awful.mouse.append_client_mousebindings({
|
||||
awful.button({}, 1, function(c)
|
||||
c:activate({ context = "mouse_click" })
|
||||
end),
|
||||
awful.button({ mod }, 1, function(c)
|
||||
c:activate({ context = "mouse_click", action = "mouse_move" })
|
||||
end),
|
||||
awful.button({ mod }, 3, function(c)
|
||||
c:activate({ context = "mouse_click", action = "mouse_resize" })
|
||||
end),
|
||||
})
|
||||
end)
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
local awful = require("awful")
|
||||
local beautiful = require("beautiful")
|
||||
local bling = require("modules.bling")
|
||||
local machi = require("modules.layout-machi")
|
||||
beautiful.layout_machi = machi.get_icon()
|
||||
|
||||
--- Custom Layouts
|
||||
local mstab = bling.layout.mstab
|
||||
local centered = bling.layout.centered
|
||||
local horizontal = bling.layout.horizontal
|
||||
local equal = bling.layout.equalarea
|
||||
local deck = bling.layout.deck
|
||||
|
||||
machi.editor.nested_layouts = {
|
||||
["0"] = deck,
|
||||
["1"] = awful.layout.suit.spiral,
|
||||
["2"] = awful.layout.suit.fair,
|
||||
["3"] = awful.layout.suit.fair.horizontal,
|
||||
}
|
||||
|
||||
--- Set the layouts
|
||||
tag.connect_signal("request::default_layouts", function()
|
||||
awful.layout.append_default_layouts({
|
||||
awful.layout.suit.tile,
|
||||
awful.layout.suit.floating,
|
||||
centered,
|
||||
mstab,
|
||||
horizontal,
|
||||
machi.default_layout,
|
||||
equal,
|
||||
deck,
|
||||
})
|
||||
end)
|
|
@ -1,96 +0,0 @@
|
|||
-- Standard Awesome Library
|
||||
local awful = require("awful")
|
||||
local hotkeys_popup = require("awful.hotkeys_popup")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- Helpers
|
||||
local helpers = require("helpers")
|
||||
|
||||
-- Create a launcher widget and a main menu
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
-- Submenu
|
||||
awesomemenu = {
|
||||
{
|
||||
"Hotkeys",
|
||||
function()
|
||||
hotkeys_popup.show_help(nil, awful.screen.focused())
|
||||
end,
|
||||
},
|
||||
{ "Manual", terminal .. " -e man awesome" },
|
||||
{ "Edit Config", editor .. " " .. awesome.conffile },
|
||||
{ "Restart", awesome.restart },
|
||||
{
|
||||
"Quit",
|
||||
function()
|
||||
awesome.quit()
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
-- Powermenu
|
||||
powermenu = {
|
||||
{
|
||||
"Power OFF",
|
||||
function()
|
||||
awful.spawn.with_shell("systemctl poweroff")
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Reboot",
|
||||
function()
|
||||
awful.spawn.with_shell("systemctl reboot")
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Suspend",
|
||||
function()
|
||||
lock_screen_show()
|
||||
awful.spawn.with_shell("systemctl suspend")
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Lock Screen",
|
||||
function()
|
||||
lock_screen_show()
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
-- Mainmenu
|
||||
mymainmenu = awful.menu({
|
||||
items = {
|
||||
{
|
||||
"Terminal",
|
||||
function()
|
||||
awful.spawn.with_shell(terminal)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Code Editor",
|
||||
function()
|
||||
awful.spawn.with_shell(vscode)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"File Manager",
|
||||
function()
|
||||
awful.spawn.with_shell(file_manager)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Web Browser",
|
||||
function()
|
||||
awful.spawn.with_shell(browser)
|
||||
end,
|
||||
},
|
||||
{
|
||||
"Music",
|
||||
function()
|
||||
awful.spawn.with_shell(music_client)
|
||||
end,
|
||||
},
|
||||
{ "AwesomeWM", awesomemenu, beautiful.awesome_logo },
|
||||
{ "Power Menu", powermenu },
|
||||
},
|
||||
})
|
||||
end)
|
|
@ -0,0 +1,135 @@
|
|||
# ░█▀█░▀█▀░█▀▀░█▀█░█▄█░░░░█▀▀░█▀█░█▀█░█▀▀
|
||||
# ░█▀▀░░█░░█░░░█░█░█░█░░░░█░░░█░█░█░█░█▀▀
|
||||
# ░▀░░░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀░░▀▀▀░▀▀▀░▀░▀░▀░░
|
||||
#
|
||||
# rxyhn X compositor configuration
|
||||
|
||||
|
||||
# ░█▀▀░█▀█░█▀▄░█▀█░█▀▀░█▀▄░█▀▀
|
||||
# ░█░░░█░█░█▀▄░█░█░█▀▀░█▀▄░▀▀█
|
||||
# ░▀▀▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀░▀░▀▀▀
|
||||
|
||||
corner-radius = 12;
|
||||
rounded-corners-exclude = [
|
||||
# "class_g ?= 'rofi'",
|
||||
"class_g ?= 'peek'",
|
||||
"window_type *= 'dock'",
|
||||
"window_type = 'menu'",
|
||||
"window_type = 'tooltip'",
|
||||
# "window_type = 'popup_menu'",
|
||||
"window_type = 'dropdown_menu'"
|
||||
];
|
||||
|
||||
|
||||
# ░█▀▀░█░█░█▀█░█▀▄░█▀█░█░█
|
||||
# ░▀▀█░█▀█░█▀█░█░█░█░█░█▄█
|
||||
# ░▀▀▀░▀░▀░▀░▀░▀▀░░▀▀▀░▀░▀
|
||||
|
||||
shadow = true;
|
||||
shadow-radius = 12;
|
||||
shadow-opacity = 0.4;
|
||||
shadow-offset-x = -12;
|
||||
shadow-offset-y = -12;
|
||||
shadow-color = "#000000";
|
||||
xinerama-shadow-crop = true;
|
||||
shadow-ignore-shaped = false;
|
||||
shadow-exclude = [
|
||||
"class_g = 'slop'",
|
||||
"class_g ?= 'peek'",
|
||||
"_NET_WM_WINDOW_TYPE@:a *= 'SPLASH'",
|
||||
# "_NET_WM_WINDOW_TYPE@:a *= 'NOTIFICATION'",
|
||||
# "window_type *= 'menu'",
|
||||
"window_type = 'utility'",
|
||||
"window_type = 'dropdown_menu'",
|
||||
# "window_type = 'popup_menu'"
|
||||
];
|
||||
|
||||
|
||||
# ░█▀▀░█▀█░█▀▄░▀█▀░█▀█░█▀▀
|
||||
# ░█▀▀░█▀█░█░█░░█░░█░█░█░█
|
||||
# ░▀░░░▀░▀░▀▀░░▀▀▀░▀░▀░▀▀▀
|
||||
|
||||
fading = true;
|
||||
fade-in-step = 0.03;
|
||||
fade-out-step = 0.03;
|
||||
fade-delta = 5;
|
||||
|
||||
no-fading-openclose = false
|
||||
no-fading-destroyed-argb = true
|
||||
|
||||
fade-exclude = [
|
||||
"class_g = 'slop'" # maim
|
||||
]
|
||||
|
||||
|
||||
# ░█▀█░█▀█░█▀█░█▀▀░▀█▀░▀█▀░█░█
|
||||
# ░█░█░█▀▀░█▀█░█░░░░█░░░█░░░█░
|
||||
# ░▀▀▀░▀░░░▀░▀░▀▀▀░▀▀▀░░▀░░░▀░
|
||||
|
||||
active-opacity = 1.0;
|
||||
inactive-opacity = 1.0;
|
||||
frame-opacity = 1.0;
|
||||
inactive-dim = 0.0;
|
||||
|
||||
opacity-rule = [];
|
||||
|
||||
focus-exclude = [
|
||||
#"class_g ?= 'rofi'"
|
||||
#'_NET_WM_NAME@:s = "rofi"'
|
||||
"class_g ?= 'slop'",
|
||||
"name = 'rofi'",
|
||||
"class_g ?= 'Steam'",
|
||||
"_NET_WM_WINDOW_TYPE@:a *= 'MENU'",
|
||||
"window_type *= 'menu'",
|
||||
"window_type = 'utility'",
|
||||
"window_type = 'dropdown_menu'",
|
||||
"window_type = 'popup_menu'"
|
||||
];
|
||||
|
||||
|
||||
# ░█▀▄░█░░░█░█░█▀▄░█▀▄░▀█▀░█▀█░█▀▀
|
||||
# ░█▀▄░█░░░█░█░█▀▄░█▀▄░░█░░█░█░█░█
|
||||
# ░▀▀░░▀▀▀░▀▀▀░▀░▀░▀░▀░▀▀▀░▀░▀░▀▀▀
|
||||
|
||||
blur: {
|
||||
method = "dual_kawase";
|
||||
strength = 10;
|
||||
background = false;
|
||||
background-frame = true;
|
||||
background-fixed = true;
|
||||
}
|
||||
|
||||
blur-background-exclude = [
|
||||
# Exclude everything except windows of type "splash"
|
||||
# (Notice the inverse condition)
|
||||
"window_type != 'splash'"
|
||||
];
|
||||
|
||||
|
||||
# ░█▀▀░█▀▀░█▀█░█▀▀░█▀▄░█▀█░█░░░░░█▀▀░█▀▀░▀█▀░▀█▀░▀█▀░█▀█░█▀▀░█▀▀
|
||||
# ░█░█░█▀▀░█░█░█▀▀░█▀▄░█▀█░█░░░░░▀▀█░█▀▀░░█░░░█░░░█░░█░█░█░█░▀▀█
|
||||
# ░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀░▀░▀░▀░▀▀▀░░░▀▀▀░▀▀▀░░▀░░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀
|
||||
|
||||
backend = "glx";
|
||||
glx-no-stencil = false;
|
||||
glx-copy-from-front = false;
|
||||
use-damage = true;
|
||||
vsync = true;
|
||||
detect-rounded-corners = true;
|
||||
detect-client-leader = true;
|
||||
detect-transient = true;
|
||||
unredir-if-possible = true;
|
||||
|
||||
wintypes:
|
||||
{
|
||||
tooltip = { fade = true; full-shadow = true; focus = true; blur-background = false;};
|
||||
menu = { full-shadow = true;};
|
||||
popup_menu = { full-shadow = true;};
|
||||
utility = {full-shadow = true;};
|
||||
toolbar = {full-shadow = true;};
|
||||
normal = {full-shadow = true;};
|
||||
notification = {full-shadow = true;};
|
||||
dialog = {full-shadow = true};
|
||||
dock = {full-shadow = true;};
|
||||
dropdown_menu = { full-shadow = true;};
|
||||
};
|
|
@ -0,0 +1,142 @@
|
|||
configuration {
|
||||
font: "Roboto Medium 10";
|
||||
show-icons: true;
|
||||
icon-theme: "WhiteSur-dark";
|
||||
display-drun: "";
|
||||
drun-display-format: "{icon} {name}";
|
||||
disable-history: false;
|
||||
sidebar-mode: false;
|
||||
click-to-exit: true;
|
||||
location: 6;
|
||||
}
|
||||
|
||||
* {
|
||||
BG: #06111599;
|
||||
BGA: #061115;
|
||||
FG: #D9D7D6ff;
|
||||
UGT: #DF5B61ff;
|
||||
}
|
||||
|
||||
window {
|
||||
transparency: "real";
|
||||
background-color: @BG;
|
||||
text-color: @FG;
|
||||
border-radius: 8px;
|
||||
width: 700px;
|
||||
x-offset: 0;
|
||||
y-offset: -45px;
|
||||
}
|
||||
|
||||
prompt {
|
||||
enabled: true;
|
||||
background-color: @BG;
|
||||
text-color: @FG;
|
||||
}
|
||||
|
||||
textbox-prompt-colon {
|
||||
expand: false;
|
||||
str: "";
|
||||
background-color: @BGA;
|
||||
text-color: @FG;
|
||||
padding: 10px 0px 0px 12px;
|
||||
font: "Material Icons Round 16";
|
||||
}
|
||||
|
||||
entry {
|
||||
background-color: @BGA;
|
||||
text-color: @FG;
|
||||
placeholder-color: @FG;
|
||||
expand: true;
|
||||
horizontal-align: 0;
|
||||
placeholder: "Type here to search";
|
||||
font: "Roboto Bold 12";
|
||||
blink: true;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
inputbar {
|
||||
children: [ textbox-prompt-colon, entry ];
|
||||
spacing: 0px;
|
||||
background-color: @BGA;
|
||||
text-color: @FG;
|
||||
expand: false;
|
||||
border-radius: 8px;
|
||||
position: center;
|
||||
}
|
||||
|
||||
case-indicator {
|
||||
background-color: @BG;
|
||||
text-color: @FG;
|
||||
spacing: 0;
|
||||
}
|
||||
|
||||
|
||||
listview {
|
||||
background-color: #00000000;
|
||||
columns: 5;
|
||||
lines: 5;
|
||||
spacing: 4px;
|
||||
cycle: false;
|
||||
dynamic: true;
|
||||
layout: vertical;
|
||||
}
|
||||
|
||||
mainbox {
|
||||
background-color: @BG;
|
||||
children: [ inputbar, listview ];
|
||||
spacing: 40px;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
element {
|
||||
background-color: #00000000;
|
||||
text-color: @FG;
|
||||
orientation: vertical;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
element-icon {
|
||||
background-color: inherit;
|
||||
text-color: inherit;
|
||||
horizontal-align: 0.5;
|
||||
vertical-align: 0.5;
|
||||
size: 48px;
|
||||
}
|
||||
|
||||
element-text {
|
||||
background-color: inherit;
|
||||
text-color: inherit;
|
||||
expand: true;
|
||||
horizontal-align: 0.5;
|
||||
vertical-align: 0.5;
|
||||
}
|
||||
|
||||
element normal.urgent,
|
||||
element alternate.urgent {
|
||||
background-color: @UGT;
|
||||
text-color: @FG;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
element normal.active,
|
||||
element alternate.active {
|
||||
background-color: @BGA;
|
||||
text-color: @FG;
|
||||
}
|
||||
|
||||
element selected {
|
||||
background-color: @BGA;
|
||||
text-color: @FG;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
element selected.urgent {
|
||||
background-color: @UGT;
|
||||
text-color: @FG;
|
||||
}
|
||||
|
||||
element selected.active {
|
||||
background-color: @BGA;
|
||||
color: @FG;
|
||||
}
|
|
@ -1,39 +1,32 @@
|
|||
-- Standard awesome library
|
||||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
|
||||
-- Theme handling library
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- Notification handling library
|
||||
local naughty = require("naughty")
|
||||
|
||||
-- Ruled
|
||||
local ruled = require("ruled")
|
||||
|
||||
-- Helpers
|
||||
local helpers = require("helpers")
|
||||
|
||||
-- Get screen geometry
|
||||
--- Get screen geometry
|
||||
local screen_width = awful.screen.focused().geometry.width
|
||||
local screen_height = awful.screen.focused().geometry.height
|
||||
|
||||
ruled.client.connect_signal("request::rules", function()
|
||||
-- Global
|
||||
--- Global
|
||||
ruled.client.append_rule({
|
||||
id = "global",
|
||||
rule = {},
|
||||
properties = {
|
||||
focus = awful.client.focus.filter,
|
||||
raise = true,
|
||||
size_hints_honor = false,
|
||||
screen = awful.screen.preferred,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
-- screen = awful.screen.preferred,
|
||||
screen = awful.screen.focused,
|
||||
focus = awful.client.focus.filter,
|
||||
titlebars_enabled = beautiful.titlebar_enabled,
|
||||
placement = awful.placement.no_overlap + awful.placement.no_offscreen,
|
||||
},
|
||||
})
|
||||
|
||||
-- Tasklist order
|
||||
--- Tasklist order
|
||||
ruled.client.append_rule({
|
||||
id = "tasklist_order",
|
||||
rule = {},
|
||||
|
@ -41,20 +34,14 @@ ruled.client.connect_signal("request::rules", function()
|
|||
callback = awful.client.setslave,
|
||||
})
|
||||
|
||||
-- Titlebar rules
|
||||
--- Titlebar rules
|
||||
ruled.client.append_rule({
|
||||
id = "titlebars",
|
||||
rule_any = {
|
||||
class = {
|
||||
"discord",
|
||||
"Spotify",
|
||||
"Org.gnome.Nautilus",
|
||||
},
|
||||
type = {
|
||||
"splash",
|
||||
},
|
||||
name = {
|
||||
"^discord.com is sharing your screen.$", -- Discord (running in browser) screen sharing popup
|
||||
"Peek",
|
||||
},
|
||||
},
|
||||
properties = {
|
||||
|
@ -62,12 +49,12 @@ ruled.client.connect_signal("request::rules", function()
|
|||
},
|
||||
})
|
||||
|
||||
-- Float
|
||||
--- Float
|
||||
ruled.client.append_rule({
|
||||
id = "floating",
|
||||
rule_any = {
|
||||
instance = {
|
||||
"Devtools", -- Firefox devtools
|
||||
"Devtools", --- Firefox devtools
|
||||
},
|
||||
class = {
|
||||
"Lxappearance",
|
||||
|
@ -86,10 +73,10 @@ ruled.client.connect_signal("request::rules", function()
|
|||
"dialog",
|
||||
},
|
||||
},
|
||||
properties = { floating = true, placement = helpers.centered_client_placement },
|
||||
properties = { floating = true, placement = helpers.client.centered_client_placement },
|
||||
})
|
||||
|
||||
-- Centered
|
||||
--- Centered
|
||||
ruled.client.append_rule({
|
||||
id = "centered",
|
||||
rule_any = {
|
||||
|
@ -97,19 +84,35 @@ ruled.client.connect_signal("request::rules", function()
|
|||
"dialog",
|
||||
},
|
||||
class = {
|
||||
-- "discord",
|
||||
--- "discord",
|
||||
},
|
||||
role = {
|
||||
"GtkFileChooserDialog",
|
||||
"conversation",
|
||||
},
|
||||
},
|
||||
properties = { placement = helpers.centered_client_placement },
|
||||
properties = { placement = helpers.client.centered_client_placement },
|
||||
})
|
||||
|
||||
-- Music clients (usually a terminal running ncmpcpp)
|
||||
--- Music clients (usually a terminal running ncmpcpp)
|
||||
ruled.client.append_rule({
|
||||
rule_any = {
|
||||
class = {
|
||||
"music",
|
||||
},
|
||||
instance = {
|
||||
"music",
|
||||
},
|
||||
},
|
||||
properties = {
|
||||
floating = true,
|
||||
width = screen_width * 0.40,
|
||||
height = screen_height * 0.42,
|
||||
placement = helpers.client.centered_client_placement,
|
||||
},
|
||||
})
|
||||
|
||||
-- Image viewers
|
||||
--- Image viewers
|
||||
ruled.client.append_rule({
|
||||
rule_any = {
|
||||
class = {
|
||||
|
@ -126,32 +129,4 @@ ruled.client.connect_signal("request::rules", function()
|
|||
awful.placement.centered(c, { honor_padding = true, honor_workarea = true })
|
||||
end,
|
||||
})
|
||||
|
||||
-- Mpv
|
||||
ruled.client.append_rule({
|
||||
rule = { class = "mpv" },
|
||||
properties = {},
|
||||
callback = function(c)
|
||||
-- make it floating, ontop and move it out of the way if the current tag is maximized
|
||||
if awful.layout.get(awful.screen.focused()) == awful.layout.suit.floating then
|
||||
c.floating = true
|
||||
c.ontop = true
|
||||
c.width = screen_width * 0.30
|
||||
c.height = screen_height * 0.35
|
||||
awful.placement.bottom_right(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
margins = { bottom = beautiful.useless_gap * 2, right = beautiful.useless_gap * 2 },
|
||||
})
|
||||
awful.titlebar.hide(c, beautiful.titlebar_pos)
|
||||
end
|
||||
|
||||
-- restore `ontop` after fullscreen is disabled
|
||||
c:connect_signal("property::fullscreen", function()
|
||||
if not c.fullscreen then
|
||||
c.ontop = true
|
||||
end
|
||||
end)
|
||||
end,
|
||||
})
|
||||
end)
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
local awful = require("awful")
|
||||
|
||||
--- Tags
|
||||
--- ~~~~
|
||||
|
||||
screen.connect_signal("request::desktop_decoration", function(s)
|
||||
--- Each screen has its own tag table.
|
||||
awful.tag({ "1", "2", "3", "4", "5", "6" }, s, awful.layout.layouts[1])
|
||||
end)
|
|
@ -1,678 +0,0 @@
|
|||
-- helpers.lua
|
||||
-- Functions that you use more than once and in different files would
|
||||
-- be nice to define here.
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local xresources = require("beautiful.xresources")
|
||||
local dpi = xresources.apply_dpi
|
||||
local wibox = require("wibox")
|
||||
local naughty = require("naughty")
|
||||
|
||||
local helpers = {}
|
||||
|
||||
function helpers.contains(_table, _c)
|
||||
for _, c in ipairs(_table) do
|
||||
if _c == c then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function helpers.find(rule)
|
||||
local function matcher(c)
|
||||
return awful.rules.match(c, rule)
|
||||
end
|
||||
local clients = client.get()
|
||||
local findex = gears.table.hasitem(clients, client.focus) or 1
|
||||
local start = gears.math.cycle(#clients, findex + 1)
|
||||
|
||||
local matches = {}
|
||||
for c in awful.client.iterate(matcher, start) do
|
||||
matches[#matches + 1] = c
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
-- Adds a maximized mask to a screen
|
||||
function helpers.screen_mask(s, bg)
|
||||
local mask = wibox({
|
||||
visible = false,
|
||||
ontop = true,
|
||||
type = "splash",
|
||||
screen = s,
|
||||
})
|
||||
awful.placement.maximize(mask)
|
||||
mask.bg = bg
|
||||
return mask
|
||||
end
|
||||
|
||||
function helpers.custom_shape(cr, width, height)
|
||||
cr:move_to(0, height / 25)
|
||||
cr:line_to(height / 25, 0)
|
||||
cr:line_to(width, 0)
|
||||
cr:line_to(width, height - height / 25)
|
||||
cr:line_to(width - height / 25, height)
|
||||
cr:line_to(0, height)
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
-- Resize gaps on the fly
|
||||
|
||||
helpers.resize_gaps = function(amt)
|
||||
local t = awful.screen.focused().selected_tag
|
||||
t.gap = t.gap + tonumber(amt)
|
||||
awful.layout.arrange(awful.screen.focused())
|
||||
end
|
||||
|
||||
-- Resize padding on the fly
|
||||
|
||||
helpers.resize_padding = function(amt)
|
||||
local s = awful.screen.focused()
|
||||
local l = s.padding.left
|
||||
local r = s.padding.right
|
||||
local t = s.padding.top
|
||||
local b = s.padding.bottom
|
||||
s.padding = {
|
||||
left = l + amt,
|
||||
right = r + amt,
|
||||
top = t + amt,
|
||||
bottom = b + amt,
|
||||
}
|
||||
awful.layout.arrange(awful.screen.focused())
|
||||
end
|
||||
|
||||
-- Create rounded rectangle shape (in one line)
|
||||
|
||||
helpers.rrect = function(radius)
|
||||
return function(cr, width, height)
|
||||
gears.shape.rounded_rect(cr, width, height, radius)
|
||||
end
|
||||
end
|
||||
|
||||
helpers.squircle = function(rate, delta)
|
||||
return function(cr, width, height)
|
||||
gears.shape.squircle(cr, width, height, rate, delta)
|
||||
end
|
||||
end
|
||||
helpers.psquircle = function(rate, delta, tl, tr, br, bl)
|
||||
return function(cr, width, height)
|
||||
gears.shape.partial_squircle(cr, width, height, tl, tr, br, bl, rate, delta)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create pi
|
||||
|
||||
helpers.pie = function(width, height, start_angle, end_angle, radius)
|
||||
return function(cr)
|
||||
gears.shape.pie(cr, width, height, start_angle, end_angle, radius)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create parallelogram
|
||||
|
||||
helpers.prgram = function(height, base)
|
||||
return function(cr, width)
|
||||
gears.shape.parallelogram(cr, width, height, base)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create partially rounded rect
|
||||
|
||||
helpers.prrect = function(radius, tl, tr, br, bl)
|
||||
return function(cr, width, height)
|
||||
gears.shape.partially_rounded_rect(cr, width, height, tl, tr, br, bl, radius)
|
||||
end
|
||||
end
|
||||
|
||||
-- Create rounded bar
|
||||
|
||||
helpers.rbar = function(width, height)
|
||||
return function(cr)
|
||||
gears.shape.rounded_bar(cr, width, height)
|
||||
end
|
||||
end
|
||||
|
||||
-- Markup helper
|
||||
|
||||
function helpers.colorize_text(txt, fg)
|
||||
return "<span foreground='" .. fg .. "'>" .. txt .. "</span>"
|
||||
end
|
||||
|
||||
function helpers.client_menu_toggle()
|
||||
local instance = nil
|
||||
|
||||
return function()
|
||||
if instance and instance.wibox.visible then
|
||||
instance:hide()
|
||||
instance = nil
|
||||
else
|
||||
instance = awful.menu.clients({ theme = { width = dpi(250) } })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Escapes a string so that it can be displayed inside pango markup
|
||||
-- tags. Modified from:
|
||||
-- https://github.com/kernelsauce/turbo/blob/master/turbo/escape.lua
|
||||
function helpers.pango_escape(s)
|
||||
return (string.gsub(s, "[&<>]", { ["&"] = "&", ["<"] = "<", [">"] = ">" }))
|
||||
end
|
||||
|
||||
function helpers.vertical_pad(height)
|
||||
return wibox.widget({
|
||||
forced_height = height,
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
})
|
||||
end
|
||||
|
||||
function helpers.horizontal_pad(width)
|
||||
return wibox.widget({
|
||||
forced_width = width,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
})
|
||||
end
|
||||
|
||||
-- Maximizes client and also respects gaps
|
||||
function helpers.maximize(c)
|
||||
c.maximized = not c.maximized
|
||||
if c.maximized then
|
||||
awful.placement.maximize(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
margins = beautiful.useless_gap * 2,
|
||||
})
|
||||
end
|
||||
c:raise()
|
||||
end
|
||||
|
||||
function helpers.move_to_edge(c, direction)
|
||||
-- local workarea = awful.screen.focused().workarea
|
||||
-- local client_geometry = c:geometry()
|
||||
if direction == "up" then
|
||||
local old_x = c:geometry().x
|
||||
awful.placement.top(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
})
|
||||
c.x = old_x
|
||||
-- c:geometry({ nil, y = workarea.y + beautiful.screen_margin * 2, nil, nil })
|
||||
elseif direction == "down" then
|
||||
local old_x = c:geometry().x
|
||||
awful.placement.bottom(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
})
|
||||
c.x = old_x
|
||||
-- c:geometry({ nil, y = workarea.height + workarea.y - client_geometry.height - beautiful.screen_margin * 2 - beautiful.border_width * 2, nil, nil })
|
||||
elseif direction == "left" then
|
||||
local old_y = c:geometry().y
|
||||
awful.placement.left(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
})
|
||||
c.y = old_y
|
||||
-- c:geometry({ x = workarea.x + beautiful.screen_margin * 2, nil, nil, nil })
|
||||
elseif direction == "right" then
|
||||
local old_y = c:geometry().y
|
||||
awful.placement.right(c, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
honor_padding = true,
|
||||
})
|
||||
c.y = old_y
|
||||
-- c:geometry({ x = workarea.width + workarea.x - client_geometry.width - beautiful.screen_margin * 2 - beautiful.border_width * 2, nil, nil, nil })
|
||||
end
|
||||
end
|
||||
|
||||
local double_tap_timer = nil
|
||||
function helpers.single_double_tap(single_tap_function, double_tap_function)
|
||||
if double_tap_timer then
|
||||
double_tap_timer:stop()
|
||||
double_tap_timer = nil
|
||||
double_tap_function()
|
||||
-- naughty.notify({text = "We got a double tap"})
|
||||
return
|
||||
end
|
||||
|
||||
double_tap_timer = gears.timer.start_new(0.20, function()
|
||||
double_tap_timer = nil
|
||||
-- naughty.notify({text = "We got a single tap"})
|
||||
if single_tap_function then
|
||||
single_tap_function()
|
||||
end
|
||||
return false
|
||||
end)
|
||||
end
|
||||
|
||||
-- Used as a custom command in rofi to move a window into the current tag
|
||||
-- instead of following it.
|
||||
-- Rofi has access to the X window id of the client.
|
||||
function helpers.rofi_move_client_here(window)
|
||||
local win = function(c)
|
||||
return awful.rules.match(c, { window = window })
|
||||
end
|
||||
|
||||
for c in awful.client.iterate(win) do
|
||||
c.minimized = false
|
||||
c:move_to_tag(mouse.screen.selected_tag)
|
||||
client.focus = c
|
||||
c:raise()
|
||||
end
|
||||
end
|
||||
|
||||
-- Add a hover cursor to a widget by changing the cursor on
|
||||
-- mouse::enter and mouse::leave
|
||||
-- You can find the names of the available cursors by opening any
|
||||
-- cursor theme and looking in the "cursors folder"
|
||||
-- For example: "hand1" is the cursor that appears when hovering over
|
||||
-- links
|
||||
function helpers.add_hover_cursor(w, hover_cursor)
|
||||
local original_cursor = "left_ptr"
|
||||
|
||||
w:connect_signal("mouse::enter", function()
|
||||
local w = _G.mouse.current_wibox
|
||||
if w then
|
||||
w.cursor = hover_cursor
|
||||
end
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
local w = _G.mouse.current_wibox
|
||||
if w then
|
||||
w.cursor = original_cursor
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
-- Tag back and forth:
|
||||
-- If you try to focus the tag you are already at, go back to the previous tag.
|
||||
-- Useful for quick switching after for example checking an incoming chat
|
||||
-- message at tag 2 and coming back to your work at tag 1 with the same
|
||||
-- keypress.
|
||||
-- Also focuses urgent clients if they exist in the tag. This fixes the issue
|
||||
-- (visual mismatch) where after switching to a tag which includes an urgent
|
||||
-- client, the urgent client is unfocused but still covers all other windows
|
||||
-- (even the currently focused window).
|
||||
function helpers.tag_back_and_forth(tag_index)
|
||||
local s = mouse.screen
|
||||
local tag = s.tags[tag_index]
|
||||
if tag then
|
||||
if tag == s.selected_tag then
|
||||
awful.tag.history.restore()
|
||||
else
|
||||
tag:view_only()
|
||||
end
|
||||
|
||||
local urgent_clients = function(c)
|
||||
return awful.rules.match(c, { urgent = true, first_tag = tag })
|
||||
end
|
||||
|
||||
for c in awful.client.iterate(urgent_clients) do
|
||||
client.focus = c
|
||||
c:raise()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Resize DWIM (Do What I Mean)
|
||||
-- Resize client or factor
|
||||
-- Constants --
|
||||
local floating_resize_amount = dpi(20)
|
||||
local tiling_resize_factor = 0.05
|
||||
---------------
|
||||
function helpers.resize_dwim(c, direction)
|
||||
if awful.layout.get(mouse.screen) == awful.layout.suit.floating or (c and c.floating) then
|
||||
if direction == "up" then
|
||||
c:relative_move(0, 0, 0, -floating_resize_amount)
|
||||
elseif direction == "down" then
|
||||
c:relative_move(0, 0, 0, floating_resize_amount)
|
||||
elseif direction == "left" then
|
||||
c:relative_move(0, 0, -floating_resize_amount, 0)
|
||||
elseif direction == "right" then
|
||||
c:relative_move(0, 0, floating_resize_amount, 0)
|
||||
end
|
||||
else
|
||||
if direction == "up" then
|
||||
awful.client.incwfact(-tiling_resize_factor)
|
||||
elseif direction == "down" then
|
||||
awful.client.incwfact(tiling_resize_factor)
|
||||
elseif direction == "left" then
|
||||
awful.tag.incmwfact(-tiling_resize_factor)
|
||||
elseif direction == "right" then
|
||||
awful.tag.incmwfact(tiling_resize_factor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Move client to screen edge, respecting the screen workarea
|
||||
function helpers.move_to_edge(c, direction)
|
||||
local workarea = awful.screen.focused().workarea
|
||||
if direction == "up" then
|
||||
c:geometry({ nil, y = workarea.y + beautiful.useless_gap * 2, nil, nil })
|
||||
elseif direction == "down" then
|
||||
c:geometry({
|
||||
nil,
|
||||
y = workarea.height
|
||||
+ workarea.y
|
||||
- c:geometry().height
|
||||
- beautiful.useless_gap * 2
|
||||
- beautiful.border_width * 2,
|
||||
nil,
|
||||
nil,
|
||||
})
|
||||
elseif direction == "left" then
|
||||
c:geometry({ x = workarea.x + beautiful.useless_gap * 2, nil, nil, nil })
|
||||
elseif direction == "right" then
|
||||
c:geometry({
|
||||
x = workarea.width
|
||||
+ workarea.x
|
||||
- c:geometry().width
|
||||
- beautiful.useless_gap * 2
|
||||
- beautiful.border_width * 2,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Move client DWIM (Do What I Mean)
|
||||
-- Move to edge if the client / layout is floating
|
||||
-- Swap by index if maximized
|
||||
-- Else swap client by direction
|
||||
function helpers.move_client_dwim(c, direction)
|
||||
if c.floating or (awful.layout.get(mouse.screen) == awful.layout.suit.floating) then
|
||||
helpers.move_to_edge(c, direction)
|
||||
elseif awful.layout.get(mouse.screen) == awful.layout.suit.max then
|
||||
if direction == "up" or direction == "left" then
|
||||
awful.client.swap.byidx(-1, c)
|
||||
elseif direction == "down" or direction == "right" then
|
||||
awful.client.swap.byidx(1, c)
|
||||
end
|
||||
else
|
||||
awful.client.swap.bydirection(direction, c, nil)
|
||||
end
|
||||
end
|
||||
|
||||
-- Make client floating and snap to the desired edge
|
||||
function helpers.float_and_edge_snap(c, direction)
|
||||
-- if not c.floating then
|
||||
-- c.floating = true
|
||||
-- end
|
||||
naughty.notify({ text = "double tap" })
|
||||
c.floating = true
|
||||
local workarea = awful.screen.focused().workarea
|
||||
if direction == "up" then
|
||||
local axis = "horizontally"
|
||||
local f = awful.placement.scale + awful.placement.top + (axis and awful.placement["maximize_" .. axis] or nil)
|
||||
local geo = f(client.focus, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
to_percent = 0.5,
|
||||
})
|
||||
elseif direction == "down" then
|
||||
local axis = "horizontally"
|
||||
local f = awful.placement.scale
|
||||
+ awful.placement.bottom
|
||||
+ (axis and awful.placement["maximize_" .. axis] or nil)
|
||||
local geo = f(client.focus, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
to_percent = 0.5,
|
||||
})
|
||||
elseif direction == "left" then
|
||||
local axis = "vertically"
|
||||
local f = awful.placement.scale + awful.placement.left + (axis and awful.placement["maximize_" .. axis] or nil)
|
||||
local geo = f(client.focus, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
to_percent = 0.5,
|
||||
})
|
||||
elseif direction == "right" then
|
||||
local axis = "vertically"
|
||||
local f = awful.placement.scale + awful.placement.right + (axis and awful.placement["maximize_" .. axis] or nil)
|
||||
local geo = f(client.focus, {
|
||||
honor_padding = true,
|
||||
honor_workarea = true,
|
||||
to_percent = 0.5,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Rounds a number to any number of decimals
|
||||
function helpers.round(number, decimals)
|
||||
local power = 10 ^ decimals
|
||||
return math.floor(number * power) / power
|
||||
end
|
||||
|
||||
function helpers.fake_escape()
|
||||
root.fake_input("key_press", "Escape")
|
||||
root.fake_input("key_release", "Escape")
|
||||
end
|
||||
|
||||
function helpers.pad(size)
|
||||
local str = ""
|
||||
for i = 1, size do
|
||||
str = str .. " "
|
||||
end
|
||||
local pad = wibox.widget.textbox(str)
|
||||
return pad
|
||||
end
|
||||
|
||||
function helpers.float_and_resize(c, width, height)
|
||||
c.width = width
|
||||
c.height = height
|
||||
awful.placement.centered(c, { honor_workarea = true, honor_padding = true })
|
||||
awful.client.property.set(c, "floating_geometry", c:geometry())
|
||||
c.floating = true
|
||||
c:raise()
|
||||
end
|
||||
|
||||
function helpers.centered_client_placement(c)
|
||||
return gears.timer.delayed_call(function()
|
||||
awful.placement.centered(c, { honor_padding = true, honor_workarea = true })
|
||||
end)
|
||||
end
|
||||
|
||||
-- Useful for periodically checking the output of a command that
|
||||
-- requires internet access.
|
||||
-- Ensures that `command` will be run EXACTLY once during the desired
|
||||
-- `interval`, even if awesome restarts multiple times during this time.
|
||||
-- Saves output in `output_file` and checks its last modification
|
||||
-- time to determine whether to run the command again or not.
|
||||
-- Passes the output of `command` to `callback` function.
|
||||
function helpers.remote_watch(command, interval, output_file, callback)
|
||||
local run_the_thing = function()
|
||||
-- Pass output to callback AND write it to file
|
||||
awful.spawn.easy_async_with_shell(command .. " | tee " .. output_file, function(out)
|
||||
callback(out)
|
||||
end)
|
||||
end
|
||||
|
||||
local timer
|
||||
timer = gears.timer({
|
||||
timeout = interval,
|
||||
call_now = true,
|
||||
autostart = true,
|
||||
single_shot = false,
|
||||
callback = function()
|
||||
awful.spawn.easy_async_with_shell(
|
||||
"date -r " .. output_file .. " +%s",
|
||||
function(last_update, _, __, exitcode)
|
||||
-- Probably the file does not exist yet (first time
|
||||
-- running after reboot)
|
||||
if exitcode == 1 then
|
||||
run_the_thing()
|
||||
return
|
||||
end
|
||||
|
||||
local diff = os.time() - tonumber(last_update)
|
||||
if diff >= interval then
|
||||
run_the_thing()
|
||||
else
|
||||
-- Pass the date saved in the file since it is fresh enough
|
||||
awful.spawn.easy_async_with_shell("cat " .. output_file, function(out)
|
||||
callback(out)
|
||||
end)
|
||||
|
||||
-- Schedule an update for when the remaining time to complete the interval passes
|
||||
timer:stop()
|
||||
gears.timer.start_new(interval - diff, function()
|
||||
run_the_thing()
|
||||
timer:again()
|
||||
end)
|
||||
end
|
||||
end
|
||||
)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
-- Volume Control
|
||||
function helpers.volume_control(step)
|
||||
local cmd
|
||||
if step == 0 then
|
||||
cmd = "pactl set-sink-mute @DEFAULT_SINK@ toggle"
|
||||
else
|
||||
sign = step > 0 and "+" or ""
|
||||
cmd = "pactl set-sink-mute @DEFAULT_SINK@ 0 && pactl set-sink-volume @DEFAULT_SINK@ "
|
||||
.. sign
|
||||
.. tostring(step)
|
||||
.. "%"
|
||||
end
|
||||
awful.spawn.with_shell(cmd)
|
||||
end
|
||||
|
||||
function helpers.music_control(state)
|
||||
local cmd
|
||||
if state == "toggle" then
|
||||
cmd = "playerctl -p spotify,mpd play-pause"
|
||||
elseif state == "prev" then
|
||||
cmd = "playerctl -p spotify,mpd previous"
|
||||
elseif state == "next" then
|
||||
cmd = "playerctl -p spotify,mpd next"
|
||||
end
|
||||
awful.spawn.with_shell(cmd)
|
||||
end
|
||||
|
||||
function helpers.send_key(c, key)
|
||||
awful.spawn.with_shell("xdotool key --window " .. tostring(c.window) .. " " .. key)
|
||||
end
|
||||
|
||||
function helpers.send_key_sequence(c, seq)
|
||||
awful.spawn.with_shell("xdotool type --delay 5 --window " .. tostring(c.window) .. " " .. seq)
|
||||
end
|
||||
|
||||
local prompt_font = beautiful.prompt_font
|
||||
function helpers.prompt(action, textbox, prompt, callback)
|
||||
if action == "run" then
|
||||
awful.prompt.run({
|
||||
prompt = prompt,
|
||||
textbox = textbox,
|
||||
font = prompt_font,
|
||||
done_callback = callback,
|
||||
exe_callback = awful.spawn,
|
||||
completion_callback = awful.completion.shell,
|
||||
history_path = awful.util.get_cache_dir() .. "/history",
|
||||
})
|
||||
elseif action == "web_search" then
|
||||
awful.prompt.run({
|
||||
prompt = prompt,
|
||||
textbox = textbox,
|
||||
font = prompt_font,
|
||||
history_path = awful.util.get_cache_dir() .. "/history_web",
|
||||
done_callback = callback,
|
||||
exe_callback = function(input)
|
||||
if not input or #input == 0 then
|
||||
return
|
||||
end
|
||||
awful.spawn.with_shell("noglob " .. web_search_cmd .. "'" .. input .. "'")
|
||||
naughty.notify({
|
||||
title = "Searching the web for",
|
||||
text = input,
|
||||
urgency = "low",
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Given a `match` condition, returns an array with clients that match it, or
|
||||
-- just the first found client if `first_only` is true
|
||||
function helpers.find_clients(match, first_only)
|
||||
local matcher = function(c)
|
||||
return awful.rules.match(c, match)
|
||||
end
|
||||
|
||||
if first_only then
|
||||
for c in awful.client.iterate(matcher) do
|
||||
return c
|
||||
end
|
||||
else
|
||||
local clients = {}
|
||||
for c in awful.client.iterate(matcher) do
|
||||
table.insert(clients, c)
|
||||
end
|
||||
return clients
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Given a `match` condition, calls the specified function `f_do` on all the
|
||||
-- clients that match it
|
||||
function helpers.find_clients_and_do(match, f_do)
|
||||
local matcher = function(c)
|
||||
return awful.rules.match(c, match)
|
||||
end
|
||||
|
||||
for c in awful.client.iterate(matcher) do
|
||||
f_do(c)
|
||||
end
|
||||
end
|
||||
|
||||
function helpers.run_or_raise(match, move, spawn_cmd, spawn_args)
|
||||
local matcher = function(c)
|
||||
return awful.rules.match(c, match)
|
||||
end
|
||||
|
||||
-- Find and raise
|
||||
local found = false
|
||||
for c in awful.client.iterate(matcher) do
|
||||
found = true
|
||||
c.minimized = false
|
||||
if move then
|
||||
c:move_to_tag(mouse.screen.selected_tag)
|
||||
client.focus = c
|
||||
else
|
||||
c:jump_to()
|
||||
end
|
||||
break
|
||||
end
|
||||
|
||||
-- Spawn if not found
|
||||
if not found then
|
||||
awful.spawn(spawn_cmd, spawn_args)
|
||||
end
|
||||
end
|
||||
|
||||
-- Run raise or minimize a client (scratchpad style)
|
||||
-- Depends on helpers.run_or_raise
|
||||
-- If it not running, spawn it
|
||||
-- If it is running, focus it
|
||||
-- If it is focused, minimize it
|
||||
function helpers.scratchpad(match, spawn_cmd, spawn_args)
|
||||
local cf = client.focus
|
||||
if cf and awful.rules.match(cf, match) then
|
||||
cf.minimized = true
|
||||
else
|
||||
helpers.run_or_raise(match, true, spawn_cmd, spawn_args)
|
||||
end
|
||||
end
|
||||
|
||||
return helpers
|
|
@ -0,0 +1,116 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local xresources = require("beautiful.xresources")
|
||||
local dpi = xresources.apply_dpi
|
||||
local capi = { client = client, mouse = mouse }
|
||||
|
||||
local _client = {}
|
||||
|
||||
-- Resize client or factor
|
||||
local floating_resize_amount = dpi(20)
|
||||
local tiling_resize_factor = 0.05
|
||||
function _client.resize_client(c, direction)
|
||||
if c and c.floating or awful.layout.get(capi.mouse.screen) == awful.layout.suit.floating then
|
||||
if direction == "up" then
|
||||
c:relative_move(0, 0, 0, -floating_resize_amount)
|
||||
elseif direction == "down" then
|
||||
c:relative_move(0, 0, 0, floating_resize_amount)
|
||||
elseif direction == "left" then
|
||||
c:relative_move(0, 0, -floating_resize_amount, 0)
|
||||
elseif direction == "right" then
|
||||
c:relative_move(0, 0, floating_resize_amount, 0)
|
||||
end
|
||||
elseif awful.layout.get(capi.mouse.screen) ~= awful.layout.suit.floating then
|
||||
if direction == "up" then
|
||||
awful.client.incwfact(-tiling_resize_factor)
|
||||
elseif direction == "down" then
|
||||
awful.client.incwfact(tiling_resize_factor)
|
||||
elseif direction == "left" then
|
||||
awful.tag.incmwfact(-tiling_resize_factor)
|
||||
elseif direction == "right" then
|
||||
awful.tag.incmwfact(tiling_resize_factor)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Move client to screen edge, respecting the screen workarea
|
||||
function _client.move_to_edge(c, direction)
|
||||
local workarea = awful.screen.focused().workarea
|
||||
if direction == "up" then
|
||||
c:geometry({ nil, y = workarea.y + beautiful.useless_gap * 2, nil, nil })
|
||||
elseif direction == "down" then
|
||||
c:geometry({
|
||||
nil,
|
||||
y = workarea.height
|
||||
+ workarea.y
|
||||
- c:geometry().height
|
||||
- beautiful.useless_gap * 2
|
||||
- beautiful.border_width * 2,
|
||||
nil,
|
||||
nil,
|
||||
})
|
||||
elseif direction == "left" then
|
||||
c:geometry({ x = workarea.x + beautiful.useless_gap * 2, nil, nil, nil })
|
||||
elseif direction == "right" then
|
||||
c:geometry({
|
||||
x = workarea.width
|
||||
+ workarea.x
|
||||
- c:geometry().width
|
||||
- beautiful.useless_gap * 2
|
||||
- beautiful.border_width * 2,
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Move client DWIM (Do What I Mean)
|
||||
-- Move to edge if the client / layout is floating
|
||||
-- Swap by index if maximized
|
||||
-- Else swap client by direction
|
||||
function _client.move_client(c, direction)
|
||||
if c.floating or (awful.layout.get(capi.mouse.screen) == awful.layout.suit.floating) then
|
||||
_client.move_to_edge(c, direction)
|
||||
elseif awful.layout.get(capi.mouse.screen) == awful.layout.suit.max then
|
||||
if direction == "up" or direction == "left" then
|
||||
awful.client.swap.byidx(-1, c)
|
||||
elseif direction == "down" or direction == "right" then
|
||||
awful.client.swap.byidx(1, c)
|
||||
end
|
||||
else
|
||||
awful.client.swap.bydirection(direction, c, nil)
|
||||
end
|
||||
end
|
||||
|
||||
function _client.centered_client_placement(c)
|
||||
return gears.timer.delayed_call(function()
|
||||
awful.placement.centered(c, { honor_padding = true, honor_workarea = true })
|
||||
end)
|
||||
end
|
||||
|
||||
-- Resize gaps on the fly
|
||||
_client.resize_gaps = function(amt)
|
||||
local t = awful.screen.focused().selected_tag
|
||||
t.gap = t.gap + tonumber(amt)
|
||||
awful.layout.arrange(awful.screen.focused())
|
||||
end
|
||||
|
||||
-- Resize padding on the fly
|
||||
_client.resize_padding = function(amt)
|
||||
local s = awful.screen.focused()
|
||||
local l = s.padding.left
|
||||
local r = s.padding.right
|
||||
local t = s.padding.top
|
||||
local b = s.padding.bottom
|
||||
s.padding = {
|
||||
left = l + amt,
|
||||
right = r + amt,
|
||||
top = t + amt,
|
||||
bottom = b + amt,
|
||||
}
|
||||
awful.layout.arrange(awful.screen.focused())
|
||||
end
|
||||
|
||||
return _client
|
|
@ -0,0 +1,207 @@
|
|||
local color_libary = require("modules.color")
|
||||
local tonumber = tonumber
|
||||
local string = string
|
||||
local math = math
|
||||
local type = type
|
||||
local floor = math.floor
|
||||
local max = math.max
|
||||
local min = math.min
|
||||
local pow = math.pow
|
||||
local random = math.random
|
||||
local abs = math.abs
|
||||
local format = string.format
|
||||
|
||||
local _color = {}
|
||||
|
||||
local function round(x, p)
|
||||
local power = 10 ^ (p or 0)
|
||||
return (x * power + 0.5 - (x * power + 0.5) % 1) / power
|
||||
end
|
||||
|
||||
-- Returns a value that is clipped to interval edges if it falls outside the interval
|
||||
local function clip(num, min_num, max_num)
|
||||
return max(min(num, max_num), min_num)
|
||||
end
|
||||
|
||||
-- Converts the given hex color to rgba
|
||||
function _color.hex_to_rgb(color)
|
||||
color = color:gsub("#", "")
|
||||
return {
|
||||
r = tonumber("0x" .. color:sub(1, 2)),
|
||||
g = tonumber("0x" .. color:sub(3, 4)),
|
||||
b = tonumber("0x" .. color:sub(5, 6)),
|
||||
a = #color == 8 and tonumber("0x" .. color:sub(7, 8)) or 255,
|
||||
}
|
||||
end
|
||||
|
||||
-- Converts the given rgba color to hex
|
||||
function _color.rgb_to_hex(color)
|
||||
local r = clip(color.r or color[1], 0, 255)
|
||||
local g = clip(color.g or color[2], 0, 255)
|
||||
local b = clip(color.b or color[3], 0, 255)
|
||||
local a = clip(color.a or color[4] or 255, 0, 255)
|
||||
return "#" .. format("%02x%02x%02x%02x", floor(r), floor(g), floor(b), floor(a))
|
||||
end
|
||||
|
||||
-- Converts the given hex color to hsv
|
||||
function _color.hex_to_hsv(color)
|
||||
local color = _color.hex_to_rgb(color)
|
||||
local C_max = max(color.r, color.g, color.b)
|
||||
local C_min = min(color.r, color.g, color.b)
|
||||
local delta = C_max - C_min
|
||||
local H, S, V
|
||||
if delta == 0 then
|
||||
H = 0
|
||||
elseif C_max == color.r then
|
||||
H = 60 * (((color.g - color.b) / delta) % 6)
|
||||
elseif C_max == color.g then
|
||||
H = 60 * (((color.b - color.r) / delta) + 2)
|
||||
elseif C_max == color.b then
|
||||
H = 60 * (((color.r - color.g) / delta) + 4)
|
||||
end
|
||||
if C_max == 0 then
|
||||
S = 0
|
||||
else
|
||||
S = delta / C_max
|
||||
end
|
||||
V = C_max
|
||||
|
||||
return { h = H, s = S * 100, v = V * 100 }
|
||||
end
|
||||
|
||||
--- Try to guess if a color is dark or light.
|
||||
function _color.is_dark(color)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
return color.l <= 0.4
|
||||
end
|
||||
|
||||
--- Check if a color is opaque.
|
||||
function _color.is_opaque(color)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
return color.a == 0
|
||||
end
|
||||
|
||||
-- Calculates the relative luminance of the given color
|
||||
function _color.relative_luminance(color)
|
||||
local function from_sRGB(u)
|
||||
return u <= 0.0031308 and 25 * u / 323 or pow(((200 * u + 11) / 211), 12 / 5)
|
||||
end
|
||||
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
return 0.2126 * from_sRGB(color.r) + 0.7152 * from_sRGB(color.g) + 0.0722 * from_sRGB(color.b)
|
||||
end
|
||||
|
||||
-- Calculates the contrast ratio between the two given colors
|
||||
function _color.contrast_ratio(fg, bg)
|
||||
return (_color.relative_luminance(fg) + 0.05) / (_color.relative_luminance(bg) + 0.05)
|
||||
end
|
||||
|
||||
-- Returns true if the contrast between the two given colors is suitable
|
||||
function _color.is_contrast_acceptable(fg, bg)
|
||||
return _color.contrast_ratio(fg, bg) >= 7 and true
|
||||
end
|
||||
|
||||
-- Returns a bright-ish, saturated-ish, color of random hue
|
||||
function _color.rand_hex(lb_angle, ub_angle)
|
||||
return color_libary.color({
|
||||
h = random(lb_angle or 0, ub_angle or 360),
|
||||
s = 70,
|
||||
v = 90,
|
||||
}).hex
|
||||
end
|
||||
|
||||
-- Rotates the hue of the given hex color by the specified angle (in degrees)
|
||||
function _color.rotate_hue(color, angle)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
angle = clip(angle or 0, 0, 360)
|
||||
color.h = (color.h + angle) % 360
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.button_color(color, amount)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
if _color.is_dark(color.hex) then
|
||||
color = color + string.format("%fl", amount)
|
||||
else
|
||||
color = color - string.format("%fl", amount)
|
||||
end
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.lighten(color, amount)
|
||||
amount = amount or 0
|
||||
|
||||
color = color_libary.color({ hex = color })
|
||||
color.l = color.l + amount
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.darken(color, amount)
|
||||
amount = amount or 0
|
||||
|
||||
color = color_libary.color({ hex = color })
|
||||
color.l = color.l - amount
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
-- Pywal like functions
|
||||
function _color.pywal_blend(color1, color2)
|
||||
color1 = color_libary.color({ hex = color1 })
|
||||
color2 = color_libary.color({ hex = color2 })
|
||||
|
||||
return color_libary.color({
|
||||
r = round(0.5 * color1.r + 0.5 * color2.r),
|
||||
g = round(0.5 * color1.g + 0.5 * color2.g),
|
||||
b = round(0.5 * color1.b + 0.5 * color2.b),
|
||||
}).hex
|
||||
end
|
||||
|
||||
function _color.pywal_saturate_color(color, amount)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
color.s = clip(amount, 0, 1)
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.pywal_alter_brightness(color, amount, sat)
|
||||
sat = sat or 0
|
||||
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
color.l = clip(color.l + amount, 0, 1)
|
||||
color.s = clip(color.s + sat, 0, 1)
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.pywal_lighten(color, amount)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
color.r = round(color.r + (255 - color.r) * amount)
|
||||
color.g = round(color.g + (255 - color.g) * amount)
|
||||
color.b = round(color.b + (255 - color.b) * amount)
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
function _color.pywal_darken(color, amount)
|
||||
color = color_libary.color({ hex = color })
|
||||
|
||||
color.r = round(color.r * (1 - amount))
|
||||
color.g = round(color.g * (1 - amount))
|
||||
color.b = round(color.b * (1 - amount))
|
||||
|
||||
return color.hex
|
||||
end
|
||||
|
||||
return _color
|
|
@ -0,0 +1,426 @@
|
|||
local lgi = require("lgi")
|
||||
local Gio = lgi.Gio
|
||||
local Glib = lgi.GLib
|
||||
local awful = require("awful")
|
||||
local gtimer = require("gears.timer")
|
||||
local tonumber = tonumber
|
||||
local tostring = tostring
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local os = os
|
||||
local capi = { awesome = awesome }
|
||||
|
||||
local _filesystem = {}
|
||||
|
||||
function _filesystem.is_directory_readable_block(path)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
local gfileinfo = gfile:query_info(
|
||||
"standard::type,access::can-read,time::modified",
|
||||
Gio.FileQueryInfoFlags.NONE
|
||||
)
|
||||
return gfileinfo and gfileinfo:get_file_type() == "DIRECTORY" and
|
||||
gfileinfo:get_attribute_boolean("access::can-read")
|
||||
end
|
||||
|
||||
function _filesystem.is_file_readable_block(path)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
local gfileinfo = gfile:query_info(
|
||||
"standard::type,access::can-read,time::modified",
|
||||
Gio.FileQueryInfoFlags.NONE
|
||||
)
|
||||
return gfileinfo and gfileinfo:get_file_type() ~= "DIRECTORY" and
|
||||
gfileinfo:get_attribute_boolean("access::can-read")
|
||||
end
|
||||
|
||||
function _filesystem.read_file_block(path)
|
||||
if _filesystem.is_file_readable_block(path) == false then
|
||||
print("file '" .. path .. "' is not found or not readable...")
|
||||
return nil
|
||||
else
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
local content = gfile:load_contents()
|
||||
if content == nil or content == false then
|
||||
print("Failed reading " .. path)
|
||||
return nil
|
||||
else
|
||||
return content
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _filesystem.query_info(path, callback)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
gfile:query_info_async(
|
||||
"standard::type,access::can-read,time::modified",
|
||||
Gio.FileQueryInfoFlags.NONE, Glib.PRIORITY_DEFAULT,
|
||||
nil,
|
||||
function(_, info_result)
|
||||
local info, error = gfile:query_info_finish(info_result)
|
||||
if info == nil or error ~= nil then
|
||||
callback(nil)
|
||||
print(error)
|
||||
return
|
||||
else
|
||||
callback(info)
|
||||
end
|
||||
end, nil)
|
||||
end
|
||||
|
||||
function _filesystem.is_directory_readable(path, callback)
|
||||
_filesystem.query_info(path, function(info)
|
||||
if info ~= nil then
|
||||
if info:get_file_type() == "DIRECTORY" and
|
||||
info:get_attribute_boolean("access::can-read")
|
||||
then
|
||||
callback(true)
|
||||
else
|
||||
print("directory '" .. path .. "' is not found or not readable...")
|
||||
callback(false)
|
||||
end
|
||||
else
|
||||
print("info for directory '" .. path .. "' could not be retrived")
|
||||
callback(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.is_file_readable(path, callback)
|
||||
_filesystem.query_info(path, function(info)
|
||||
if info ~= nil then
|
||||
if info:get_file_type() ~= "DIRECTORY" and
|
||||
info:get_attribute_boolean("access::can-read")
|
||||
then
|
||||
callback(true)
|
||||
else
|
||||
print("file '" .. path .. "' is not found or not readable...")
|
||||
callback(false)
|
||||
end
|
||||
else
|
||||
print("info for file '" .. path .. "' could not be retrived")
|
||||
callback(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.make_directory(path, callback)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
_filesystem.is_directory_readable(path, function(is_readable)
|
||||
if is_readable then
|
||||
print("directory '" .. path .. "' already exists")
|
||||
callback(true)
|
||||
return
|
||||
else
|
||||
gfile:make_directory_async(Glib.PRIORITY_DEFAULT, nil, function(file, task, c)
|
||||
local result, error = gfile:make_directory_finish(task)
|
||||
if result == false or error ~= nil then
|
||||
print("Failed creating " .. path)
|
||||
callback(false)
|
||||
else
|
||||
print("Successfully created " .. path)
|
||||
callback(true)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.save_file(path, text, callback, is_retry)
|
||||
print("writing to file " .. path)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
_filesystem.is_file_readable(path, function(is_readable)
|
||||
if not is_readable then
|
||||
if is_retry then
|
||||
print("failed creating file "..path)
|
||||
if callback then
|
||||
callback(false)
|
||||
end
|
||||
return
|
||||
end
|
||||
print("making parent directories...")
|
||||
gfile:get_parent():make_directory_with_parents()
|
||||
gfile:create_readwrite_async(Gio.FileCreateFlags.NONE, Glib.PRIORITY_DEFAULT, nil, function(_, create_result)
|
||||
print("file created " .. tostring(gfile:create_readwrite_finish(create_result)))
|
||||
_filesystem.save_file(path, text, callback, true)
|
||||
end, nil)
|
||||
else
|
||||
gfile:open_readwrite_async(Glib.PRIORITY_DEFAULT, nil, function(_, io_stream_result)
|
||||
local io_stream = gfile:open_readwrite_finish(io_stream_result)
|
||||
io_stream:seek(0, Glib.SeekType.SET, nil)
|
||||
local file = io_stream:get_output_stream()
|
||||
file:write_all_async(text, Glib.PRIORITY_DEFAULT, nil, function(_, write_result)
|
||||
local length_written = file:write_all_finish(write_result)
|
||||
print("file written " .. length_written)
|
||||
file:truncate(length_written, nil)
|
||||
file:close_async(Glib.PRIORITY_DEFAULT, nil, function(_, file_close_result)
|
||||
print("output stream closed " .. tostring(file:close_finish(file_close_result)))
|
||||
io_stream:close_async(Glib.PRIORITY_DEFAULT, nil, function(_, stream_close_result)
|
||||
print("file stream closed " .. tostring(io_stream:close_finish(stream_close_result)))
|
||||
if callback then
|
||||
callback(true)
|
||||
end
|
||||
end, nil)
|
||||
end, nil)
|
||||
end, nil)
|
||||
end, nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.read_file(path, callback)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
_filesystem.is_file_readable(path, function(is_readable)
|
||||
if not is_readable then
|
||||
print("file '" .. path .. "' is not found or not readable...")
|
||||
callback(nil)
|
||||
else
|
||||
gfile:load_contents_async(nil, function(file, task, c)
|
||||
local content = gfile:load_contents_finish(task)
|
||||
if content == nil then
|
||||
print("Failed reading " .. path)
|
||||
callback(nil)
|
||||
else
|
||||
callback(content)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.read_file_uri(uri, callback)
|
||||
local gfile = Gio.File.new_for_uri(uri)
|
||||
gfile:load_contents_async(nil, function(file, task, c)
|
||||
local content = gfile:load_contents_finish(task)
|
||||
if content == nil then
|
||||
print("Failed reading " .. uri)
|
||||
callback(nil)
|
||||
else
|
||||
callback(content)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.delete_file(path, callback)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
gfile:delete_async(Glib.PRIORITY_DEFAULT, nil, function(file, task, c)
|
||||
local result, error = gfile:delete_finish(task)
|
||||
if result == false or error ~= nil then
|
||||
print("Failed deleting " .. tostring(error))
|
||||
if callback then
|
||||
callback(false)
|
||||
end
|
||||
else
|
||||
if callback then
|
||||
callback(true)
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.scan(path, callback, recursive)
|
||||
if not path then
|
||||
return
|
||||
end
|
||||
|
||||
local result = {}
|
||||
|
||||
local function enumerator(path)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
gfile:enumerate_children_async(
|
||||
"standard::name,standard::type,access::can-read",
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
0,
|
||||
nil,
|
||||
function(file, task, c)
|
||||
local enum, error = file:enumerate_children_finish(task)
|
||||
if enum == nil or error ~= nil then
|
||||
print("Failed enumrating " .. path .. " " .. tostring(error))
|
||||
callback(nil)
|
||||
return
|
||||
end
|
||||
|
||||
enum:next_files_async(99999, 0, nil, function(file_enum, task2, c)
|
||||
local files, error = file_enum:next_files_finish(task2)
|
||||
if files == nil or error ~= nil then
|
||||
print("Failed enumrating " .. tostring(error))
|
||||
callback(nil)
|
||||
return
|
||||
end
|
||||
|
||||
for _, file in ipairs(files) do
|
||||
local file_child = enum:get_child(file)
|
||||
local file_type = file:get_file_type()
|
||||
local readable = file:get_attribute_boolean("access::can-read")
|
||||
if file_type == "REGULAR" and readable then
|
||||
local path = file_child:get_path()
|
||||
if path ~= nil then
|
||||
table.insert(result, path)
|
||||
end
|
||||
elseif file_type == "DIRECTORY" and recursive then
|
||||
enumerator(file_child:get_path())
|
||||
end
|
||||
end
|
||||
|
||||
enum:close_async(0, nil)
|
||||
callback(result)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
enumerator(path)
|
||||
end
|
||||
|
||||
function _filesystem.scan_with_folders(path, callback)
|
||||
if not path then
|
||||
return
|
||||
end
|
||||
|
||||
local files_table = {}
|
||||
local folders_table = {}
|
||||
|
||||
local function enumerator(path)
|
||||
local gfile = Gio.File.new_for_path(path)
|
||||
gfile:enumerate_children_async(
|
||||
"standard::name,standard::type,access::can-read",
|
||||
Gio.FileQueryInfoFlags.NONE,
|
||||
0,
|
||||
nil,
|
||||
function(file, task, c)
|
||||
local enum, error = file:enumerate_children_finish(task)
|
||||
if enum == nil or error ~= nil then
|
||||
print("Failed enumrating " .. path .. " " .. tostring(error))
|
||||
callback(nil)
|
||||
return
|
||||
end
|
||||
|
||||
enum:next_files_async(99999, 0, nil, function(file_enum, task2, c)
|
||||
local files, error = file_enum:next_files_finish(task2)
|
||||
if files == nil or error ~= nil then
|
||||
print("Failed enumrating " .. tostring(error))
|
||||
callback(nil)
|
||||
return
|
||||
end
|
||||
|
||||
for _, file in ipairs(files) do
|
||||
local file_child = enum:get_child(file)
|
||||
local file_type = file:get_file_type()
|
||||
local readable = file:get_attribute_boolean("access::can-read")
|
||||
if file_type == "REGULAR" and readable then
|
||||
local path = file_child:get_path()
|
||||
if path ~= nil then
|
||||
table.insert(files_table, path)
|
||||
end
|
||||
elseif file_type == "DIRECTORY" then
|
||||
table.insert(folders_table, file_child:get_path())
|
||||
end
|
||||
end
|
||||
|
||||
enum:close_async(0, nil)
|
||||
callback(files_table, folders_table)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
enumerator(path)
|
||||
end
|
||||
|
||||
function _filesystem.save_uri(path, uri, callback)
|
||||
_filesystem.read_file_uri(uri, function(content)
|
||||
if content == nil then
|
||||
print("Failed to download file " .. uri)
|
||||
callback(false)
|
||||
else
|
||||
_filesystem.save_file(path, content, function(result)
|
||||
if result == true then
|
||||
callback(true)
|
||||
else
|
||||
print("Failed to save " .. uri .. " to" .. path)
|
||||
callback(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.remote_watch(path, uri, interval, callback, old_content_callback)
|
||||
local function download()
|
||||
_filesystem.read_file_uri(uri, function(content)
|
||||
callback(content)
|
||||
if content ~= nil and content ~= false then
|
||||
_filesystem.read_file(path, function(old_content)
|
||||
if old_content ~= nil and old_content ~= false then
|
||||
if old_content_callback ~= nil then
|
||||
old_content_callback(old_content)
|
||||
end
|
||||
end
|
||||
|
||||
_filesystem.save_file(path, content)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
_filesystem.read_file(path, function(old_content)
|
||||
if old_content ~= nil and old_content ~= false then
|
||||
if old_content_callback ~= nil then
|
||||
old_content_callback(old_content)
|
||||
end
|
||||
end
|
||||
|
||||
local timer
|
||||
timer = gtimer
|
||||
{
|
||||
timeout = interval,
|
||||
call_now = true,
|
||||
autostart = true,
|
||||
single_shot = false,
|
||||
callback = function()
|
||||
_filesystem.query_info(path, function(info)
|
||||
if info ~= nil then
|
||||
local time = info:get_modification_date_time()
|
||||
local diff = math.ceil(Glib.DateTime.new_now_local():difference(time) / 1000000)
|
||||
if diff >= interval then
|
||||
print("Enough time has passed, redownloading " .. path)
|
||||
download()
|
||||
else
|
||||
_filesystem.read_file(path, function(content)
|
||||
if content == nil or content:gsub("%s+", "") == "" then
|
||||
print("Empty file, Redownloading " .. path)
|
||||
download()
|
||||
else
|
||||
callback(content)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Schedule an update for when the remaining time to complete the interval passes
|
||||
timer:stop()
|
||||
gtimer.start_new(interval - diff, function()
|
||||
print("Finally! redownloading " .. path)
|
||||
download()
|
||||
timer:again()
|
||||
end)
|
||||
end
|
||||
else
|
||||
print(path .. " doesn't exist, downloading " .. uri)
|
||||
download()
|
||||
end
|
||||
end)
|
||||
end
|
||||
}
|
||||
end)
|
||||
end
|
||||
|
||||
function _filesystem.get_awesome_config_dir(sub_folder)
|
||||
return (capi.awesome.conffile:match(".*/") or "./") .. sub_folder .. "/"
|
||||
end
|
||||
|
||||
function _filesystem.get_cache_dir(sub_folder)
|
||||
return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache")
|
||||
.. "/awesome/" .. sub_folder .. "/"
|
||||
end
|
||||
|
||||
function _filesystem.get_xdg_cache_home(sub_folder)
|
||||
return (os.getenv("XDG_CACHE_HOME") or os.getenv("HOME") .. "/.cache")
|
||||
.. "/" .. sub_folder .. "/"
|
||||
end
|
||||
|
||||
return _filesystem
|
|
@ -0,0 +1,8 @@
|
|||
return {
|
||||
client = require(... .. ".client"),
|
||||
color = require(... .. ".color"),
|
||||
filesystem = require(... .. ".filesystem"),
|
||||
misc = require(... .. ".misc"),
|
||||
run = require(... .. ".run"),
|
||||
ui = require(... .. ".ui"),
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
local awful = require("awful")
|
||||
local naughty = require("naughty")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local icons = require("icons")
|
||||
local math = math
|
||||
local os = os
|
||||
local capi = { awesome = awesome, client = client }
|
||||
|
||||
local _misc = {}
|
||||
|
||||
-- Send key
|
||||
function _misc.send_key(c, key)
|
||||
awful.spawn.with_shell("xdotool key --window " .. tostring(c.window) .. " " .. key)
|
||||
end
|
||||
|
||||
--- Converts string representation of date (2020-06-02T11:25:27Z) to date
|
||||
function _misc.parse_date(date_str)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)%Z"
|
||||
local y, m, d, h, min, sec, _ = date_str:match(pattern)
|
||||
|
||||
return os.time({ year = y, month = m, day = d, hour = h, min = min, sec = sec })
|
||||
end
|
||||
|
||||
--- Converts seconds to "time ago" representation, like '1 hour ago'
|
||||
function _misc.to_time_ago(seconds)
|
||||
local days = seconds / 86400
|
||||
if days >= 1 then
|
||||
days = math.floor(days)
|
||||
return days .. (days == 1 and " day" or " days") .. " ago"
|
||||
end
|
||||
|
||||
local hours = (seconds % 86400) / 3600
|
||||
if hours >= 1 then
|
||||
hours = math.floor(hours)
|
||||
return hours .. (hours == 1 and " hour" or " hours") .. " ago"
|
||||
end
|
||||
|
||||
local minutes = ((seconds % 86400) % 3600) / 60
|
||||
if minutes >= 1 then
|
||||
minutes = math.floor(minutes)
|
||||
return minutes .. (minutes == 1 and " minute" or " minutes") .. " ago"
|
||||
end
|
||||
|
||||
return "Now"
|
||||
end
|
||||
|
||||
function _misc.tag_back_and_forth(tag_index)
|
||||
local s = awful.screen.focused()
|
||||
local tag = s.tags[tag_index]
|
||||
if tag then
|
||||
if tag == s.selected_tag then
|
||||
awful.tag.history.restore()
|
||||
else
|
||||
tag:view_only()
|
||||
end
|
||||
|
||||
local urgent_clients = function(c)
|
||||
return awful.rules.match(c, { urgent = true, first_tag = tag })
|
||||
end
|
||||
|
||||
for c in awful.client.iterate(urgent_clients) do
|
||||
capi.client.focus = c
|
||||
c:raise()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _misc.prompt(action, textbox, prompt, callback)
|
||||
if action == "run" then
|
||||
awful.prompt.run({
|
||||
prompt = prompt,
|
||||
-- prompt = "<b>Run: </b>",
|
||||
textbox = textbox,
|
||||
font = beautiful.font_name .. "Regular 12",
|
||||
done_callback = callback,
|
||||
exe_callback = awful.spawn,
|
||||
completion_callback = awful.completion.shell,
|
||||
history_path = awful.util.get_cache_dir() .. "/history",
|
||||
})
|
||||
elseif action == "web_search" then
|
||||
awful.prompt.run({
|
||||
prompt = prompt,
|
||||
-- prompt = '<b>Web search: </b>',
|
||||
textbox = textbox,
|
||||
font = beautiful.font_name .. "Regular 12",
|
||||
history_path = awful.util.get_cache_dir() .. "/history_web",
|
||||
done_callback = callback,
|
||||
exe_callback = function(input)
|
||||
if not input or #input == 0 then
|
||||
return
|
||||
end
|
||||
awful.spawn.with_shell("noglob " .. "xdg-open https://www.google.com/search?q=" .. "'" .. input .. "'")
|
||||
naughty.notify({
|
||||
title = "Searching the web for",
|
||||
text = input,
|
||||
icon = gears.color.recolor_image(icons.web_browser, beautiful.accent),
|
||||
urgency = "low",
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
return _misc
|
|
@ -0,0 +1,50 @@
|
|||
local awful = require("awful")
|
||||
|
||||
local tostring = tostring
|
||||
local string = string
|
||||
local ipairs = ipairs
|
||||
local math = math
|
||||
local os = os
|
||||
|
||||
local _run = {}
|
||||
|
||||
function _run.run_once_pgrep(cmd)
|
||||
local findme = cmd
|
||||
local firstspace = cmd:find(" ")
|
||||
if firstspace then
|
||||
findme = cmd:sub(0, firstspace - 1)
|
||||
end
|
||||
awful.spawn.easy_async_with_shell(string.format("pgrep -u $USER -x %s > /dev/null || (%s)", findme, cmd))
|
||||
end
|
||||
|
||||
function _run.run_once_ps(findme, cmd)
|
||||
awful.spawn.easy_async_with_shell(string.format("ps -C %s|wc -l", findme), function(stdout)
|
||||
if tonumber(stdout) ~= 2 then
|
||||
awful.spawn(cmd, false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _run.run_once_grep(command)
|
||||
awful.spawn.easy_async_with_shell(string.format("ps aux | grep '%s' | grep -v 'grep'", command), function(stdout)
|
||||
if stdout == "" or stdout == nil then
|
||||
awful.spawn(command, false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _run.check_if_running(command, running_callback, not_running_callback)
|
||||
awful.spawn.easy_async_with_shell(string.format("ps aux | grep '%s' | grep -v 'grep'", command), function(stdout)
|
||||
if stdout == "" or stdout == nil then
|
||||
if not_running_callback ~= nil then
|
||||
not_running_callback()
|
||||
end
|
||||
else
|
||||
if running_callback ~= nil then
|
||||
running_callback()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
return _run
|
|
@ -0,0 +1,113 @@
|
|||
local awful = require("awful")
|
||||
local wibox = require("wibox")
|
||||
local gshape = require("gears.shape")
|
||||
local gmatrix = require("gears.matrix")
|
||||
local ipairs = ipairs
|
||||
local table = table
|
||||
local capi = { mouse = mouse }
|
||||
|
||||
local _ui = {}
|
||||
|
||||
function _ui.colorize_text(text, color)
|
||||
return "<span foreground='" .. color .. "'>" .. text .. "</span>"
|
||||
end
|
||||
|
||||
function _ui.add_hover_cursor(w, hover_cursor)
|
||||
local original_cursor = "left_ptr"
|
||||
|
||||
w:connect_signal("mouse::enter", function()
|
||||
local widget = capi.mouse.current_wibox
|
||||
if widget then
|
||||
widget.cursor = hover_cursor
|
||||
end
|
||||
end)
|
||||
|
||||
w:connect_signal("mouse::leave", function()
|
||||
local widget = capi.mouse.current_wibox
|
||||
if widget then
|
||||
widget.cursor = original_cursor
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function _ui.vertical_pad(height)
|
||||
return wibox.widget({
|
||||
forced_height = height,
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
})
|
||||
end
|
||||
|
||||
function _ui.horizontal_pad(width)
|
||||
return wibox.widget({
|
||||
forced_width = width,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
})
|
||||
end
|
||||
|
||||
function _ui.rrect(radius)
|
||||
return function(cr, width, height)
|
||||
gshape.rounded_rect(cr, width, height, radius)
|
||||
end
|
||||
end
|
||||
|
||||
function _ui.pie(width, height, start_angle, end_angle, radius)
|
||||
return function(cr)
|
||||
gshape.pie(cr, width, height, start_angle, end_angle, radius)
|
||||
end
|
||||
end
|
||||
|
||||
function _ui.prgram(height, base)
|
||||
return function(cr, width)
|
||||
gshape.parallelogram(cr, width, height, base)
|
||||
end
|
||||
end
|
||||
|
||||
function _ui.prrect(radius, tl, tr, br, bl)
|
||||
return function(cr, width, height)
|
||||
gshape.partially_rounded_rect(cr, width, height, tl, tr, br, bl, radius)
|
||||
end
|
||||
end
|
||||
|
||||
function _ui.custom_shape(cr, width, height)
|
||||
cr:move_to(0, height / 25)
|
||||
cr:line_to(height / 25, 0)
|
||||
cr:line_to(width, 0)
|
||||
cr:line_to(width, height - height / 25)
|
||||
cr:line_to(width - height / 25, height)
|
||||
cr:line_to(0, height)
|
||||
cr:close_path()
|
||||
end
|
||||
|
||||
local function _get_widget_geometry(_hierarchy, widget)
|
||||
local width, height = _hierarchy:get_size()
|
||||
if _hierarchy:get_widget() == widget then
|
||||
-- Get the extents of this widget in the device space
|
||||
local x, y, w, h = gmatrix.transform_rectangle(_hierarchy:get_matrix_to_device(), 0, 0, width, height)
|
||||
return { x = x, y = y, width = w, height = h, hierarchy = _hierarchy }
|
||||
end
|
||||
|
||||
for _, child in ipairs(_hierarchy:get_children()) do
|
||||
local ret = _get_widget_geometry(child, widget)
|
||||
if ret then
|
||||
return ret
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function _ui.get_widget_geometry(wibox, widget)
|
||||
return _get_widget_geometry(wibox._drawable._widget_hierarchy, widget)
|
||||
end
|
||||
|
||||
function _ui.screen_mask(s, bg)
|
||||
local mask = wibox({
|
||||
visible = false,
|
||||
ontop = true,
|
||||
type = "splash",
|
||||
screen = s,
|
||||
})
|
||||
awful.placement.maximize(mask)
|
||||
mask.bg = bg
|
||||
return mask
|
||||
end
|
||||
|
||||
return _ui
|
|
@ -0,0 +1,114 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
width="520"
|
||||
height="64"
|
||||
id="svg2"
|
||||
sodipodi:docname="Awesome_logo_horizontal3.svg"
|
||||
inkscape:version="0.92.0 r">
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1062"
|
||||
id="namedview42"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1.3100951"
|
||||
inkscape:cx="208.7345"
|
||||
inkscape:cy="-24.8331"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="18"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2" />
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs6" />
|
||||
<path
|
||||
d="M 0,63.999999 V 22 H 43.999999 V 20 H 0 V 0 h 63.999999 v 63.999999 h -20 V 42 H 20 v 2 h 21.999999 v 19.999999 z"
|
||||
id="path10"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5121"
|
||||
d="M 75.999999,0 H 118 v 43.999999 h 2 V 0 h 20 V 63.999999 H 75.999999 c 0.03867,-19.975266 1.21505,-20 22,-20 V 0 l -2,3.13e-4 v 44.03356 l -20,19.966102 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 216,0 v 42 h -44 v 2 h 44 V 64 H 152 V 0 c 19.97527,0.03867 20,1.21505 20,22 h 44 l -3.1e-4,-2 H 171.96613 L 152.00002,0 Z"
|
||||
id="path5123"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5125"
|
||||
d="M 292,63.999999 V 22 h -44 v -2 h 44 V 0 h -64 v 42.011827 l 20,-0.01183 v 0 h 24 v 2.09375 h -44 l -0.009,19.906249 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 324.3125,63.999999 c 0,-43.882671 0.18277,-0.110242 -0.0915,-43.999999 h 0.88388 42.89515 V 0 h -64 c 0,63.768424 -0.009,0.109806 -0.009,63.999996 z"
|
||||
id="path5127"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 380,63.999999 h 42 V 20.000001 h 2 v 43.999998 h 20 V 0 h -64 c 0.0387,19.975267 1.21505,20.000001 22,20.000001 v 43.999998 l -2,-3.13e-4 V 19.966127 L 380,2.4e-5 Z"
|
||||
id="path5129"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5131"
|
||||
d="m 520,0 v 42 h -44 v 2 h 44 V 64 H 456 V 0 c 19.97527,0.03867 20,1.21505 20,22 h 44 l -3.1e-4,-2 H 475.96613 L 456.00002,0 Z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5135"
|
||||
d="m 332.34911,63.999999 c 0,-44.007671 -0.003,-0.02174 -0.003,-43.999999 0,0 30.24668,0 35.65403,0 V 0 h -64 c 0,63.768424 -0.009,0.109806 -0.009,63.999996 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 334.99382,63.999999 c 0,0 -0.003,-0.02174 -0.003,-43.999999 h 32.71653 V 0 h -63.70721 c 0,63.768424 -0.009,0.109806 -0.009,63.999996 z"
|
||||
id="path5137"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5162"
|
||||
d="m 347.67867,0 c 0,43.882671 -0.18277,0.110242 0.0915,43.999999 h -0.88388 -42.89515 v 20 h 64 c 0,-63.768424 0.009,-0.109806 0.009,-63.999996 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
d="m 339.64206,0 c 0,44.007671 0.003,0.02174 0.003,43.999999 0,0 -30.24668,0 -35.65403,0 v 20 h 64 c 0,-63.768424 0.009,-0.109806 0.009,-63.999996 z"
|
||||
id="path5164"
|
||||
style="fill:#535d6c"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#535d6c"
|
||||
id="path5166"
|
||||
d="m 336.99735,0 c 0,0 0.003,0.02174 0.003,43.999999 h -32.71653 v 20 h 63.70721 c 0,-63.768424 0.009,-0.109806 0.009,-63.999996 z"
|
||||
inkscape:connector-curvature="0" />
|
||||
</svg>
|
After Width: | Height: | Size: 4.4 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M96 320h48V192H96V320zM544 192V160c0-35.35-28.65-64-64-64H64C28.65 96 0 124.7 0 160v192c0 35.35 28.65 64 64 64h416c35.35 0 64-28.65 64-64v-32c17.67 0 32-14.33 32-32V224C576 206.3 561.7 192 544 192zM496 352c0 8.822-7.178 16-16 16H64c-8.822 0-16-7.178-16-16V160c0-8.822 7.178-16 16-16h416c8.822 0 16 7.178 16 16V352z"/></svg>
|
After Width: | Height: | Size: 538 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M96 320h352V192H96V320zM544 192V160c0-35.35-28.65-64-64-64H64C28.65 96 0 124.7 0 160v192c0 35.35 28.65 64 64 64h416c35.35 0 64-28.65 64-64v-32c17.67 0 32-14.33 32-32V224C576 206.3 561.7 192 544 192zM496 352c0 8.822-7.178 16-16 16H64c-8.822 0-16-7.178-16-16V160c0-8.822 7.178-16 16-16h416c8.822 0 16 7.178 16 16V352z"/></svg>
|
After Width: | Height: | Size: 539 B |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.0.0-alpha3 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) --><path d="M48 352V160c0-8.822 7.178-16 16-16h106.6L212.9 96H64C28.65 96 0 124.7 0 160v192c0 35.35 28.65 64 64 64h73.87l17.29-48H64C55.18 368 48 360.8 48 352zM544 192V160c0-35.35-28.65-64-64-64h-73.87l-17.29 48H480c8.822 0 16 7.178 16 16v192c0 8.822-7.178 16-16 16h-106.6L331.1 416H480c35.35 0 64-28.65 64-64v-32c17.67 0 32-14.33 32-32V224C576 206.3 561.7 192 544 192zM397.9 246.1C393.1 237.5 385.4 232 376 232h-69.84l60.44-167.9c3.906-10.84-.4687-22.92-10.38-28.78c-9.906-5.844-22.59-3.875-30.25 4.797l-176 200C143.8 247.2 142.3 257.3 146.1 265.9C149.1 274.5 158.6 280 168 280h69.84l-60.44 167.9c-3.906 10.84 .4687 22.92 10.38 28.78C191.6 478.9 195.8 480 200 480c6.688 0 13.31-2.812 18.03-8.141l176-200C400.3 264.8 401.8 254.7 397.9 246.1z"/></svg>
|
After Width: | Height: | Size: 953 B |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M130.22 127.548C130.38 127.558 130.3 127.558 130.22 127.548V127.548ZM481.64 172.898C471.03 147.398 449.56 119.898 432.7 111.168C446.42 138.058 454.37 165.048 457.4 185.168C457.405 185.306 457.422 185.443 457.45 185.578C429.87 116.828 383.098 89.1089 344.9 28.7479C329.908 5.05792 333.976 3.51792 331.82 4.08792L331.7 4.15792C284.99 30.1109 256.365 82.5289 249.12 126.898C232.503 127.771 216.219 131.895 201.19 139.035C199.838 139.649 198.736 140.706 198.066 142.031C197.396 143.356 197.199 144.87 197.506 146.323C197.7 147.162 198.068 147.951 198.586 148.639C199.103 149.327 199.76 149.899 200.512 150.318C201.264 150.737 202.096 150.993 202.954 151.071C203.811 151.148 204.676 151.045 205.491 150.768L206.011 150.558C221.511 143.255 238.408 139.393 255.541 139.238C318.369 138.669 352.698 183.262 363.161 201.528C350.161 192.378 326.811 183.338 304.341 187.248C392.081 231.108 368.541 381.784 246.951 376.448C187.487 373.838 149.881 325.467 146.421 285.648C146.421 285.648 157.671 243.698 227.041 243.698C234.541 243.698 255.971 222.778 256.371 216.698C256.281 214.698 213.836 197.822 197.281 181.518C188.434 172.805 184.229 168.611 180.511 165.458C178.499 163.75 176.392 162.158 174.201 160.688C168.638 141.231 168.399 120.638 173.51 101.058C148.45 112.468 128.96 130.508 114.8 146.428H114.68C105.01 134.178 105.68 93.7779 106.25 85.3479C106.13 84.8179 99.022 89.0159 98.1 89.6579C89.5342 95.7103 81.5528 102.55 74.26 110.088C57.969 126.688 30.128 160.242 18.76 211.318C14.224 231.701 12 255.739 12 263.618C12 398.318 121.21 507.508 255.92 507.508C376.56 507.508 478.939 420.281 496.35 304.888C507.922 228.192 481.64 173.82 481.64 172.898Z"/></svg>
|
After Width: | Height: | Size: 1.8 KiB |
|
@ -0,0 +1,20 @@
|
|||
--- Icons directory
|
||||
local gfs = require("gears.filesystem")
|
||||
local dir = gfs.get_configuration_dir() .. "icons/"
|
||||
|
||||
return {
|
||||
--- notifications
|
||||
notification = dir .. "notification.svg",
|
||||
notification_bell = dir .. "notification_bell.svg",
|
||||
|
||||
--- system UI
|
||||
ram = dir .. "ram.svg",
|
||||
cpu = dir .. "cpu.svg",
|
||||
temp = dir .. "temp.svg",
|
||||
disk = dir .. "disk.svg",
|
||||
battery = dir .. "battery.svg",
|
||||
battery_low = dir .. "battery-low.svg",
|
||||
charging = dir .. "charging.svg",
|
||||
web_browser = dir .. "firefox.svg",
|
||||
awesome_logo = dir .. "awesome-logo.svg",
|
||||
}
|
0
config/awesome/theme/assets/icons/notification.svg → config/awesome/icons/notification.svg
Normal file → Executable file
Before Width: | Height: | Size: 398 B After Width: | Height: | Size: 398 B |
0
config/awesome/theme/assets/icons/notification_bell.svg → config/awesome/icons/notification_bell.svg
Normal file → Executable file
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
@ -1,134 +0,0 @@
|
|||
local Gio = require("lgi").Gio
|
||||
local Gtk = require("lgi").Gtk
|
||||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
local helpers = require("helpers")
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
|
||||
local icon_theme = { mt = {} }
|
||||
|
||||
function icon_theme:get_client_icon_path(client)
|
||||
local function find_icon(class)
|
||||
if self._private.client_icon_cache[class] ~= nil then
|
||||
return self._private.client_icon_cache[class]
|
||||
end
|
||||
|
||||
for _, app in ipairs(Gio.AppInfo.get_all()) do
|
||||
local id = Gio.AppInfo.get_id(app)
|
||||
if id:match(helpers.misc.case_insensitive_pattern(class)) then
|
||||
self._private.client_icon_cache[class] = self:get_gicon_path(Gio.AppInfo.get_icon(app))
|
||||
return self._private.client_icon_cache[class]
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local class = client.class
|
||||
if class == "jetbrains-studio" then
|
||||
class = "android-studio"
|
||||
end
|
||||
|
||||
local icon = self:get_icon_path("gnome-window-manager")
|
||||
|
||||
if class ~= nil then
|
||||
class = class:gsub("[%-]", "%%%0")
|
||||
icon = find_icon(class) or icon
|
||||
|
||||
class = client.class
|
||||
class = class:gsub("[%-]", "")
|
||||
icon = find_icon(class) or icon
|
||||
|
||||
class = client.class
|
||||
class = class:gsub("[%-]", ".")
|
||||
icon = find_icon(class) or icon
|
||||
|
||||
class = client.class
|
||||
class = class:match("(.-)-") or class
|
||||
class = class:match("(.-)%.") or class
|
||||
class = class:match("(.-)%s+") or class
|
||||
class = class:gsub("[%-]", "%%%0")
|
||||
icon = find_icon(class) or icon
|
||||
end
|
||||
|
||||
return icon
|
||||
end
|
||||
|
||||
function icon_theme:choose_icon(icons_names)
|
||||
local icon_info = Gtk.IconTheme.choose_icon(self.gtk_theme, icons_names, self.icon_size, 0);
|
||||
if icon_info then
|
||||
local icon_path = Gtk.IconInfo.get_filename(icon_info)
|
||||
if icon_path then
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
|
||||
function icon_theme:get_gicon_path(gicon)
|
||||
if gicon == nil then
|
||||
return ""
|
||||
end
|
||||
|
||||
if self._private.icon_cache[gicon] ~= nil then
|
||||
return self._private.icon_cache[gicon]
|
||||
end
|
||||
|
||||
local icon_info = Gtk.IconTheme.lookup_by_gicon(self.gtk_theme, gicon, self.icon_size, 0);
|
||||
if icon_info then
|
||||
local icon_path = Gtk.IconInfo.get_filename(icon_info)
|
||||
if icon_path then
|
||||
self._private.icon_cache[gicon] = icon_path
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
function icon_theme:get_icon_path(icon_name)
|
||||
if self._private.icon_cache[icon_name] ~= nil then
|
||||
return self._private.icon_cache[icon_name]
|
||||
end
|
||||
|
||||
local icon_info = Gtk.IconTheme.lookup_icon(self.gtk_theme, icon_name, self.icon_size, 0);
|
||||
if icon_info then
|
||||
local icon_path = Gtk.IconInfo.get_filename(icon_info)
|
||||
if icon_path then
|
||||
self._private.icon_cache[icon_name] = icon_path
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
local function new(theme_name, icon_size)
|
||||
local ret = gobject{}
|
||||
gtable.crush(ret, icon_theme, true)
|
||||
|
||||
ret._private = {}
|
||||
ret._private.client_icon_cache = {}
|
||||
ret._private.icon_cache = {}
|
||||
|
||||
ret.name = theme_name or nil
|
||||
ret.icon_size = icon_size or 48
|
||||
|
||||
if theme_name then
|
||||
ret.gtk_theme = Gtk.IconTheme.new()
|
||||
Gtk.IconTheme.set_custom_theme(ret.gtk_theme, theme_name);
|
||||
else
|
||||
ret.gtk_theme = Gtk.IconTheme.get_default()
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function icon_theme.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(icon_theme, icon_theme.mt)
|
|
@ -1,87 +0,0 @@
|
|||
local gears = require("gears")
|
||||
|
||||
--typesafe function overloader (copied from lua-users.org) {{{
|
||||
--source: http://lua-users.org/wiki/OverloadedFunctions
|
||||
local function overloaded()
|
||||
local fns = {}
|
||||
local mt = {}
|
||||
local function oerror()
|
||||
return error("Invalid argument types to overloaded function")
|
||||
end
|
||||
function mt:__call(...)
|
||||
local arg = {...}
|
||||
local default = self.default
|
||||
local signature = {}
|
||||
for i,arg in ipairs {...} do
|
||||
signature[i] = type(arg)
|
||||
end
|
||||
signature = table.concat(signature, ",")
|
||||
return (fns[signature] or self.default)(...)
|
||||
end
|
||||
function mt:__index(key)
|
||||
local signature = {}
|
||||
local function __newindex(self, key, value)
|
||||
print(key, type(key), value, type(value))
|
||||
signature[#signature+1] = key
|
||||
fns[table.concat(signature, ",")] = value
|
||||
print("bind", table.concat(signature, ", "))
|
||||
end
|
||||
local function __index(self, key)
|
||||
print("I", key, type(key))
|
||||
signature[#signature+1] = key
|
||||
return setmetatable({}, { __index = __index, __newindex = __newindex })
|
||||
end
|
||||
return __index(self, key)
|
||||
end
|
||||
function mt:__newindex(key, value)
|
||||
fns[key] = value
|
||||
end
|
||||
return setmetatable({ default = oerror }, mt)
|
||||
end
|
||||
--}}}
|
||||
|
||||
local function dec_hex(IN)
|
||||
local B,K,OUT,I,D=16,"0123456789ABCDEF","",0
|
||||
while IN>0 do
|
||||
I=I+1
|
||||
IN,D=math.floor(IN/B),(IN%B)+1
|
||||
OUT=string.sub(K,D,D)..OUT
|
||||
end
|
||||
return #OUT == 2 and OUT or "0" .. OUT
|
||||
end
|
||||
|
||||
-- color helpers {{{
|
||||
local color = {}
|
||||
|
||||
color.col_shift = overloaded()
|
||||
color.col_shift.string.number = function(c, s)
|
||||
local r,g,b,o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r*255+s)
|
||||
.. dec_hex(g*255+s)
|
||||
.. dec_hex(b*255+s)
|
||||
.. dec_hex(o*255)
|
||||
end
|
||||
color.col_shift.string.number.number.number = function(c,sr,sg,sb)
|
||||
local r,g,b,o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r*255+sr)
|
||||
.. dec_hex(g*255+sg)
|
||||
.. dec_hex(b*255+sb)
|
||||
.. dec_hex(o*255)
|
||||
end
|
||||
color.col_shift.string.number.number.number.number = function(c,sr,sg,sb,so)
|
||||
local r,g,b,o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r*255+sr)
|
||||
.. dec_hex(g*255+sg)
|
||||
.. dec_hex(b*255+sb)
|
||||
.. dec_hex(o*255+so)
|
||||
end
|
||||
|
||||
color.col_diff = function(f, s)
|
||||
local fr, fg, fb, fo = gears.color.parse_color(f)
|
||||
local sr, sg, sb, so = gears.color.parse_color(s)
|
||||
return sr-fr,sg-fg,sb-fb,so-fo
|
||||
end
|
||||
--}}}
|
||||
return {
|
||||
color = color
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
local gears = require("gears")
|
||||
local dock = require("module.dock")
|
||||
dock.init(screen.primary, 50, 5, gears.shape.rounded_rect)
|
||||
|
||||
require("module.bling")
|
||||
require("module.rubato")
|
||||
require("module.layout-machi")
|
||||
require("module.better-resize")
|
||||
require("module.exit-screen")
|
||||
require("module.tooltip")
|
||||
require("module.savefloats")
|
||||
require("module.window_switcher").enable()
|
|
@ -1,226 +0,0 @@
|
|||
local gears = require("gears")
|
||||
local awful = require("awful")
|
||||
local beautiful = require("beautiful")
|
||||
local wibox = require("wibox")
|
||||
local helpers = require("helpers")
|
||||
|
||||
local function create_boxed_widget(widget_to_be_boxed, width, height, inner_pad)
|
||||
local box_container = wibox.container.background()
|
||||
box_container.bg = beautiful.tooltip_widget_bg
|
||||
box_container.forced_height = height
|
||||
box_container.forced_width = width
|
||||
box_container.shape = helpers.rrect(beautiful.tooltip_box_border_radius)
|
||||
|
||||
local inner = dpi(0)
|
||||
|
||||
if inner_pad then
|
||||
inner = beautiful.tooltip_box_margin
|
||||
end
|
||||
|
||||
local boxed_widget = wibox.widget({
|
||||
-- Add margins
|
||||
{
|
||||
-- Add background color
|
||||
{
|
||||
-- The actual widget goes here
|
||||
widget_to_be_boxed,
|
||||
margins = inner,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
widget = box_container,
|
||||
},
|
||||
margins = beautiful.tooltip_gap / 2,
|
||||
color = "#FF000000",
|
||||
widget = wibox.container.margin,
|
||||
})
|
||||
|
||||
return boxed_widget
|
||||
end
|
||||
|
||||
-- Tooltip widgets
|
||||
---------------------
|
||||
|
||||
awful.screen.connect_for_each_screen(function(s)
|
||||
-- Battery
|
||||
-------------
|
||||
local cute_battery_face = require("ui.widgets.cute-battery-face")
|
||||
|
||||
-- Date
|
||||
----------
|
||||
local date_day = wibox.widget({
|
||||
font = beautiful.font_name .. "bold 10",
|
||||
format = helpers.colorize_text("%A", beautiful.xforeground),
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textclock,
|
||||
})
|
||||
|
||||
local date_month = wibox.widget({
|
||||
font = beautiful.font_name .. "bold 14",
|
||||
format = "%d %B %Y",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
widget = wibox.widget.textclock,
|
||||
})
|
||||
|
||||
local date = wibox.widget({
|
||||
date_day,
|
||||
nil,
|
||||
date_month,
|
||||
layout = wibox.layout.align.vertical,
|
||||
})
|
||||
|
||||
-- Separator
|
||||
---------------
|
||||
local separator = wibox.widget({
|
||||
{
|
||||
bg = beautiful.accent,
|
||||
shape = helpers.rrect(dpi(5)),
|
||||
forced_width = dpi(3),
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
right = dpi(5),
|
||||
widget = wibox.container.margin,
|
||||
})
|
||||
|
||||
-- Analog clock
|
||||
------------------
|
||||
local analog_clock = require("ui.widgets.analog-clock")
|
||||
|
||||
-- Wifi
|
||||
----------
|
||||
local wifi_status_icon = wibox.widget({
|
||||
markup = "",
|
||||
font = beautiful.icon_font_name .. "14",
|
||||
valign = "center",
|
||||
align = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
})
|
||||
|
||||
local wifi = wibox.widget({
|
||||
wifi_status_icon,
|
||||
forced_width = dpi(30),
|
||||
forced_height = dpi(30),
|
||||
bg = beautiful.tooltip_bg,
|
||||
shape = gears.shape.circle,
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
|
||||
local wifi_status = false
|
||||
|
||||
awesome.connect_signal("signal::network", function(status, ssid)
|
||||
wifi_status = status
|
||||
awesome.emit_signal("widget::network")
|
||||
end)
|
||||
|
||||
awesome.connect_signal("widget::network", function()
|
||||
local w, fill_color
|
||||
if wifi_status == true then
|
||||
w = ""
|
||||
fill_color = beautiful.xcolor2
|
||||
else
|
||||
w = ""
|
||||
fill_color = beautiful.xcolor1
|
||||
end
|
||||
|
||||
wifi.shape_border_color = fill_color
|
||||
wifi_status_icon.markup = helpers.colorize_text(w, fill_color)
|
||||
end)
|
||||
|
||||
-- UpTime
|
||||
------------
|
||||
local uptime_label = wibox.widget({
|
||||
font = beautiful.font_name .. "medium 9",
|
||||
markup = helpers.colorize_text("Uptime", beautiful.accent),
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
})
|
||||
|
||||
local uptime_text = wibox.widget({
|
||||
font = beautiful.font_name .. "bold 13",
|
||||
markup = helpers.colorize_text("-", beautiful.accent),
|
||||
valign = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
})
|
||||
|
||||
awesome.connect_signal("signal::uptime", function(uptime_value)
|
||||
uptime_text.markup = uptime_value
|
||||
end)
|
||||
|
||||
local uptime_container = wibox.widget({
|
||||
separator,
|
||||
{
|
||||
uptime_label,
|
||||
nil,
|
||||
uptime_text,
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
{
|
||||
wifi,
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
|
||||
-- Widget
|
||||
------------
|
||||
local uptime_boxed = create_boxed_widget(uptime_container, dpi(170), dpi(50), true)
|
||||
local analog_clock_boxed = create_boxed_widget(analog_clock, dpi(110), dpi(110), true)
|
||||
|
||||
-- Tooltip setup
|
||||
-------------------
|
||||
s.stats_tooltip = wibox({
|
||||
type = "dock",
|
||||
screen = s,
|
||||
height = beautiful.tooltip_height,
|
||||
width = beautiful.tooltip_width,
|
||||
bg = beautiful.transparent,
|
||||
ontop = true,
|
||||
visible = false,
|
||||
})
|
||||
|
||||
awful.placement.top_right(s.stats_tooltip, {
|
||||
margins = {
|
||||
top = beautiful.useless_gap * 16,
|
||||
bottom = beautiful.useless_gap * 6,
|
||||
left = beautiful.useless_gap * 6,
|
||||
right = beautiful.useless_gap * 6,
|
||||
},
|
||||
})
|
||||
|
||||
s.stats_tooltip:setup({
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
date,
|
||||
{
|
||||
analog_clock_boxed,
|
||||
nil,
|
||||
cute_battery_face,
|
||||
expand = "none",
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
{
|
||||
uptime_boxed,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
margins = beautiful.tooltip_gap,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
shape = helpers.rrect(beautiful.tooltip_border_radius),
|
||||
bg = beautiful.tooltip_bg,
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
end)
|
||||
|
||||
function tooltip_toggle()
|
||||
local s = awful.screen.focused()
|
||||
s.stats_tooltip.visible = not s.stats_tooltip.visible
|
||||
end
|
|
@ -0,0 +1,232 @@
|
|||
-------------------------------------------
|
||||
-- @author https://github.com/Kasper24
|
||||
-- @copyright 2021-2022 Kasper24
|
||||
-------------------------------------------
|
||||
|
||||
local GLib = require("lgi").GLib
|
||||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
local subscribable = require("modules.animation.subscribable")
|
||||
local tween = require("modules.animation.tween")
|
||||
local ipairs = ipairs
|
||||
local table = table
|
||||
local pairs = pairs
|
||||
|
||||
local animation_manager = {}
|
||||
animation_manager.easing = {
|
||||
linear = "linear",
|
||||
inQuad = "inQuad",
|
||||
outQuad = "outQuad",
|
||||
inOutQuad = "inOutQuad",
|
||||
outInQuad = "outInQuad",
|
||||
inCubic = "inCubic",
|
||||
outCubic = "outCubic",
|
||||
inOutCubic = "inOutCubic",
|
||||
outInCubic = "outInCubic",
|
||||
inQuart = "inQuart",
|
||||
outQuart = "outQuart",
|
||||
inOutQuart = "inOutQuart",
|
||||
outInQuart = "outInQuart",
|
||||
inQuint = "inQuint",
|
||||
outQuint = "outQuint",
|
||||
inOutQuint = "inOutQuint",
|
||||
outInQuint = "outInQuint",
|
||||
inSine = "inSine",
|
||||
outSine = "outSine",
|
||||
inOutSine = "inOutSine",
|
||||
outInSine = "outInSine",
|
||||
inExpo = "inExpo",
|
||||
outExpo = "outExpo",
|
||||
inOutExpo = "inOutExpo",
|
||||
outInExpo = "outInExpo",
|
||||
inCirc = "inCirc",
|
||||
outCirc = "outCirc",
|
||||
inOutCirc = "inOutCirc",
|
||||
outInCirc = "outInCirc",
|
||||
inElastic = "inElastic",
|
||||
outElastic = "outElastic",
|
||||
inOutElastic = "inOutElastic",
|
||||
outInElastic = "outInElastic",
|
||||
inBack = "inBack",
|
||||
outBack = "outBack",
|
||||
inOutBack = "inOutBack",
|
||||
outInBack = "outInBack",
|
||||
inBounce = "inBounce",
|
||||
outBounce = "outBounce",
|
||||
inOutBounce = "inOutBounce",
|
||||
outInBounce = "outInBounce",
|
||||
}
|
||||
|
||||
local animation = {}
|
||||
|
||||
local instance = nil
|
||||
|
||||
local ANIMATION_FRAME_DELAY = 5
|
||||
|
||||
local function micro_to_milli(micro)
|
||||
return micro / 1000
|
||||
end
|
||||
|
||||
local function second_to_micro(sec)
|
||||
return sec * 1000000
|
||||
end
|
||||
|
||||
local function second_to_milli(sec)
|
||||
return sec * 1000
|
||||
end
|
||||
|
||||
function animation:start(args)
|
||||
args = args or {}
|
||||
|
||||
-- Awestoer/Rubbto compatibility
|
||||
-- I'd rather this always be a table, but Awestoer/Rubbto
|
||||
-- except the :set() method to have 1 number value parameter
|
||||
-- used to set the target
|
||||
local is_table = type(args) == "table"
|
||||
local initial = is_table and (args.pos or self.pos) or self.pos
|
||||
local subject = is_table and (args.subject or self.subject) or self.subject
|
||||
local target = is_table and (args.target or self.target) or args
|
||||
local duration = is_table and (args.duration or self.duration) or self.duration
|
||||
local easing = is_table and (args.easing or self.easing) or self.easing
|
||||
|
||||
duration = self._private.anim_manager._private.instant == true and 0.01 or duration
|
||||
|
||||
if self.tween == nil or self.reset_on_stop == true then
|
||||
self.tween = tween.new({
|
||||
initial = initial,
|
||||
subject = subject,
|
||||
target = target,
|
||||
duration = second_to_micro(duration),
|
||||
easing = easing,
|
||||
})
|
||||
end
|
||||
|
||||
if self._private.anim_manager._private.animations[self.index] == nil then
|
||||
table.insert(self._private.anim_manager._private.animations, self)
|
||||
end
|
||||
|
||||
self.state = true
|
||||
self.last_elapsed = GLib.get_monotonic_time()
|
||||
|
||||
self.started:fire()
|
||||
self:emit_signal("started")
|
||||
end
|
||||
|
||||
function animation:set(args)
|
||||
self:start(args)
|
||||
self:emit_signal("set")
|
||||
end
|
||||
|
||||
function animation:stop()
|
||||
self.state = false
|
||||
self:emit_signal("stopped")
|
||||
end
|
||||
|
||||
function animation:abort(reset)
|
||||
animation:stop(reset)
|
||||
self:emit_signal("aborted")
|
||||
end
|
||||
|
||||
function animation:initial()
|
||||
return self._private.initial
|
||||
end
|
||||
|
||||
function animation_manager:set_instant(value)
|
||||
self._private.instant = value
|
||||
end
|
||||
|
||||
function animation_manager:new(args)
|
||||
args = args or {}
|
||||
|
||||
args.pos = args.pos or 0
|
||||
args.subject = args.subject or nil
|
||||
args.target = args.target or nil
|
||||
args.duration = args.duration or 0
|
||||
args.easing = args.easing or nil
|
||||
args.loop = args.loop or false
|
||||
args.signals = args.signals or {}
|
||||
args.update = args.update or nil
|
||||
args.reset_on_stop = args.reset_on_stop == nil and true or args.reset_on_stop
|
||||
|
||||
-- Awestoer/Rubbto compatibility
|
||||
args.subscribed = args.subscribed or nil
|
||||
local ret = subscribable()
|
||||
ret.started = subscribable()
|
||||
ret.ended = subscribable()
|
||||
if args.subscribed ~= nil then
|
||||
ret:subscribe(args.subscribed)
|
||||
end
|
||||
|
||||
for sig, sigfun in pairs(args.signals) do
|
||||
ret:connect_signal(sig, sigfun)
|
||||
end
|
||||
if args.update ~= nil then
|
||||
ret:connect_signal("update", args.update)
|
||||
end
|
||||
|
||||
gtable.crush(ret, args, true)
|
||||
gtable.crush(ret, animation, true)
|
||||
|
||||
ret._private = {}
|
||||
ret._private.anim_manager = self
|
||||
ret._private.initial = args.pos
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local function new()
|
||||
local ret = gobject({})
|
||||
gtable.crush(ret, animation_manager, true)
|
||||
|
||||
ret._private = {}
|
||||
ret._private.animations = {}
|
||||
ret._private.instant = false
|
||||
|
||||
GLib.timeout_add(GLib.PRIORITY_DEFAULT, ANIMATION_FRAME_DELAY, function()
|
||||
for index, animation in ipairs(ret._private.animations) do
|
||||
if animation.state == true then
|
||||
-- compute delta time
|
||||
local time = GLib.get_monotonic_time()
|
||||
local delta = time - animation.last_elapsed
|
||||
animation.last_elapsed = time
|
||||
|
||||
-- If pos is true, the animation has ended
|
||||
local pos = animation.tween:update(delta)
|
||||
if pos == true then
|
||||
-- Loop the animation, don't end it.
|
||||
-- Useful for widgets like the spinning cicle
|
||||
if animation.loop == true then
|
||||
animation.tween:reset()
|
||||
else
|
||||
-- Snap to end
|
||||
animation.pos = animation.tween.target
|
||||
animation:fire(animation.pos)
|
||||
animation:emit_signal("update", animation.pos)
|
||||
|
||||
animation.state = false
|
||||
animation.ended:fire(pos)
|
||||
table.remove(ret._private.animations, index)
|
||||
animation:emit_signal("ended", animation.pos)
|
||||
end
|
||||
-- Animation in process, keep updating
|
||||
else
|
||||
animation.pos = pos
|
||||
animation:fire(animation.pos)
|
||||
animation:emit_signal("update", animation.pos)
|
||||
end
|
||||
else
|
||||
table.remove(ret._private.animations, index)
|
||||
end
|
||||
end
|
||||
|
||||
-- call again the function after cooldown
|
||||
return true
|
||||
end)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
if not instance then
|
||||
instance = new()
|
||||
end
|
||||
return instance
|
|
@ -0,0 +1,34 @@
|
|||
local gobject = require("gears.object")
|
||||
|
||||
-- Kidna copying awesotre's stores on a surface level for added compatibility
|
||||
local function subscribable(args)
|
||||
local ret = gobject{}
|
||||
local subscribed = {}
|
||||
|
||||
-- Subscrubes a function to the object so that it's called when `fire` is
|
||||
-- Calls subscribe_callback if it exists as well
|
||||
function ret:subscribe(func)
|
||||
local id = tostring(func):gsub("function: ", "")
|
||||
subscribed[id] = func
|
||||
|
||||
if self.subscribe_callback then self.subscribe_callback(func) end
|
||||
end
|
||||
|
||||
-- Unsubscribes a function and calls unsubscribe_callback if it exists
|
||||
function ret:unsubscribe(func)
|
||||
if not func then
|
||||
subscribed = {}
|
||||
else
|
||||
local id = tostring(func):gsub("function: ", "")
|
||||
subscribed[id] = nil
|
||||
end
|
||||
|
||||
if self.unsubscribe_callback then self.unsubscribe_callback(func) end
|
||||
end
|
||||
|
||||
function ret:fire(...) for _, func in pairs(subscribed) do func(...) end end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
return subscribable
|
|
@ -0,0 +1,487 @@
|
|||
-- easing
|
||||
|
||||
-- Adapted from https://github.com/EmmanuelOga/easing. See LICENSE.txt for credits.
|
||||
-- For all easing functions:
|
||||
-- t = time == how much time has to pass for the tweening to complete
|
||||
-- b = begin == starting property value
|
||||
-- c = change == ending - beginning
|
||||
-- d = duration == running time. How much time has passed *right now*
|
||||
|
||||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
|
||||
local tween = {
|
||||
_VERSION = 'tween 2.1.1',
|
||||
_DESCRIPTION = 'tweening for lua',
|
||||
_URL = 'https://github.com/kikito/tween.lua',
|
||||
_LICENSE = [[
|
||||
MIT LICENSE
|
||||
Copyright (c) 2014 Enrique García Cota, Yuichi Tateno, Emmanuel Oga
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
The above copyright notice and this permission notice shall be included
|
||||
in all copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
]]
|
||||
}
|
||||
|
||||
local pow, sin, cos, pi, sqrt, abs, asin = math.pow, math.sin, math.cos, math.pi, math.sqrt, math.abs, math.asin
|
||||
|
||||
-- linear
|
||||
local function linear(t, b, c, d)
|
||||
return c * t / d + b
|
||||
end
|
||||
|
||||
-- quad
|
||||
local function inQuad(t, b, c, d)
|
||||
return c * pow(t / d, 2) + b
|
||||
end
|
||||
local function outQuad(t, b, c, d)
|
||||
t = t / d
|
||||
return -c * t * (t - 2) + b
|
||||
end
|
||||
local function inOutQuad(t, b, c, d)
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * pow(t, 2) + b
|
||||
end
|
||||
return -c / 2 * ((t - 1) * (t - 3) - 1) + b
|
||||
end
|
||||
local function outInQuad(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outQuad(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inQuad((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- cubic
|
||||
local function inCubic (t, b, c, d)
|
||||
return c * pow(t / d, 3) + b
|
||||
end
|
||||
local function outCubic(t, b, c, d)
|
||||
return c * (pow(t / d - 1, 3) + 1) + b
|
||||
end
|
||||
local function inOutCubic(t, b, c, d)
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * t * t * t + b
|
||||
end
|
||||
t = t - 2
|
||||
return c / 2 * (t * t * t + 2) + b
|
||||
end
|
||||
local function outInCubic(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outCubic(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inCubic((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- quart
|
||||
local function inQuart(t, b, c, d)
|
||||
return c * pow(t / d, 4) + b
|
||||
end
|
||||
local function outQuart(t, b, c, d)
|
||||
return -c * (pow(t / d - 1, 4) - 1) + b
|
||||
end
|
||||
local function inOutQuart(t, b, c, d)
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * pow(t, 4) + b
|
||||
end
|
||||
return -c / 2 * (pow(t - 2, 4) - 2) + b
|
||||
end
|
||||
local function outInQuart(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outQuart(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inQuart((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- quint
|
||||
local function inQuint(t, b, c, d)
|
||||
return c * pow(t / d, 5) + b
|
||||
end
|
||||
local function outQuint(t, b, c, d)
|
||||
return c * (pow(t / d - 1, 5) + 1) + b
|
||||
end
|
||||
local function inOutQuint(t, b, c, d)
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * pow(t, 5) + b
|
||||
end
|
||||
return c / 2 * (pow(t - 2, 5) + 2) + b
|
||||
end
|
||||
local function outInQuint(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outQuint(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inQuint((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- sine
|
||||
local function inSine(t, b, c, d)
|
||||
return -c * cos(t / d * (pi / 2)) + c + b
|
||||
end
|
||||
local function outSine(t, b, c, d)
|
||||
return c * sin(t / d * (pi / 2)) + b
|
||||
end
|
||||
local function inOutSine(t, b, c, d)
|
||||
return -c / 2 * (cos(pi * t / d) - 1) + b
|
||||
end
|
||||
local function outInSine(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outSine(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inSine((t * 2) -d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- expo
|
||||
local function inExpo(t, b, c, d)
|
||||
if t == 0 then
|
||||
return b
|
||||
end
|
||||
return c * pow(2, 10 * (t / d - 1)) + b - c * 0.001
|
||||
end
|
||||
local function outExpo(t, b, c, d)
|
||||
if t == d then
|
||||
return b + c
|
||||
end
|
||||
return c * 1.001 * (-pow(2, -10 * t / d) + 1) + b
|
||||
end
|
||||
local function inOutExpo(t, b, c, d)
|
||||
if t == 0 then
|
||||
return b end
|
||||
if t == d then
|
||||
return b + c
|
||||
end
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * pow(2, 10 * (t - 1)) + b - c * 0.0005
|
||||
end
|
||||
return c / 2 * 1.0005 * (-pow(2, -10 * (t - 1)) + 2) + b
|
||||
end
|
||||
local function outInExpo(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outExpo(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inExpo((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- circ
|
||||
local function inCirc(t, b, c, d)
|
||||
return(-c * (sqrt(1 - pow(t / d, 2)) - 1) + b)
|
||||
end
|
||||
local function outCirc(t, b, c, d)
|
||||
return(c * sqrt(1 - pow(t / d - 1, 2)) + b)
|
||||
end
|
||||
local function inOutCirc(t, b, c, d)
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return -c / 2 * (sqrt(1 - t * t) - 1) + b
|
||||
end
|
||||
t = t - 2
|
||||
return c / 2 * (sqrt(1 - t * t) + 1) + b
|
||||
end
|
||||
local function outInCirc(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outCirc(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inCirc((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
-- elastic
|
||||
local function calculatePAS(p,a,c,d)
|
||||
p, a = p or d * 0.3, a or 0
|
||||
if a < abs(c) then
|
||||
return p, c, p / 4
|
||||
end -- p, a, s
|
||||
return p, a, p / (2 * pi) * asin(c/a) -- p,a,s
|
||||
end
|
||||
local function inElastic(t, b, c, d, a, p)
|
||||
local s
|
||||
if t == 0 then
|
||||
return b
|
||||
end
|
||||
t = t / d
|
||||
if t == 1 then
|
||||
return b + c
|
||||
end
|
||||
p,a,s = calculatePAS(p,a,c,d)
|
||||
t = t - 1
|
||||
return -(a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b
|
||||
end
|
||||
local function outElastic(t, b, c, d, a, p)
|
||||
local s
|
||||
if t == 0 then
|
||||
return b
|
||||
end
|
||||
t = t / d
|
||||
if t == 1 then
|
||||
return b + c
|
||||
end
|
||||
p,a,s = calculatePAS(p,a,c,d)
|
||||
return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p) + c + b
|
||||
end
|
||||
local function inOutElastic(t, b, c, d, a, p)
|
||||
local s
|
||||
if t == 0 then
|
||||
return b
|
||||
end
|
||||
t = t / d * 2
|
||||
if t == 2 then return b + c end
|
||||
p,a,s = calculatePAS(p,a,c,d)
|
||||
t = t - 1
|
||||
if t < 0 then
|
||||
return -0.5 * (a * pow(2, 10 * t) * sin((t * d - s) * (2 * pi) / p)) + b
|
||||
end
|
||||
return a * pow(2, -10 * t) * sin((t * d - s) * (2 * pi) / p ) * 0.5 + c + b
|
||||
end
|
||||
local function outInElastic(t, b, c, d, a, p)
|
||||
if t < d / 2 then
|
||||
return outElastic(t * 2, b, c / 2, d, a, p)
|
||||
end
|
||||
return inElastic((t * 2) - d, b + c / 2, c / 2, d, a, p)
|
||||
end
|
||||
|
||||
-- back
|
||||
local function inBack(t, b, c, d, s)
|
||||
s = s or 1.70158
|
||||
t = t / d
|
||||
return c * t * t * ((s + 1) * t - s) + b
|
||||
end
|
||||
local function outBack(t, b, c, d, s)
|
||||
s = s or 1.70158
|
||||
t = t / d - 1
|
||||
return c * (t * t * ((s + 1) * t + s) + 1) + b
|
||||
end
|
||||
local function inOutBack(t, b, c, d, s)
|
||||
s = (s or 1.70158) * 1.525
|
||||
t = t / d * 2
|
||||
if t < 1 then
|
||||
return c / 2 * (t * t * ((s + 1) * t - s)) + b
|
||||
end
|
||||
t = t - 2
|
||||
return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b
|
||||
end
|
||||
local function outInBack(t, b, c, d, s)
|
||||
if t < d / 2 then
|
||||
return outBack(t * 2, b, c / 2, d, s)
|
||||
end
|
||||
return inBack((t * 2) - d, b + c / 2, c / 2, d, s)
|
||||
end
|
||||
|
||||
-- bounce
|
||||
local function outBounce(t, b, c, d)
|
||||
t = t / d
|
||||
if t < 1 / 2.75 then
|
||||
return c * (7.5625 * t * t) + b
|
||||
end
|
||||
if t < 2 / 2.75 then
|
||||
t = t - (1.5 / 2.75)
|
||||
return c * (7.5625 * t * t + 0.75) + b
|
||||
elseif t < 2.5 / 2.75 then
|
||||
t = t - (2.25 / 2.75)
|
||||
return c * (7.5625 * t * t + 0.9375) + b
|
||||
end
|
||||
t = t - (2.625 / 2.75)
|
||||
return c * (7.5625 * t * t + 0.984375) + b
|
||||
end
|
||||
local function inBounce(t, b, c, d)
|
||||
return c - outBounce(d - t, 0, c, d) + b
|
||||
end
|
||||
local function inOutBounce(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return inBounce(t * 2, 0, c, d) * 0.5 + b
|
||||
end
|
||||
return outBounce(t * 2 - d, 0, c, d) * 0.5 + c * .5 + b
|
||||
end
|
||||
local function outInBounce(t, b, c, d)
|
||||
if t < d / 2 then
|
||||
return outBounce(t * 2, b, c / 2, d)
|
||||
end
|
||||
return inBounce((t * 2) - d, b + c / 2, c / 2, d)
|
||||
end
|
||||
|
||||
tween.easing =
|
||||
{
|
||||
linear = linear,
|
||||
inQuad = inQuad, outQuad = outQuad, inOutQuad = inOutQuad, outInQuad = outInQuad,
|
||||
inCubic = inCubic, outCubic = outCubic, inOutCubic = inOutCubic, outInCubic = outInCubic,
|
||||
inQuart = inQuart, outQuart = outQuart, inOutQuart = inOutQuart, outInQuart = outInQuart,
|
||||
inQuint = inQuint, outQuint = outQuint, inOutQuint = inOutQuint, outInQuint = outInQuint,
|
||||
inSine = inSine, outSine = outSine, inOutSine = inOutSine, outInSine = outInSine,
|
||||
inExpo = inExpo, outExpo = outExpo, inOutExpo = inOutExpo, outInExpo = outInExpo,
|
||||
inCirc = inCirc, outCirc = outCirc, inOutCirc = inOutCirc, outInCirc = outInCirc,
|
||||
inElastic = inElastic, outElastic = outElastic, inOutElastic = inOutElastic, outInElastic = outInElastic,
|
||||
inBack = inBack, outBack = outBack, inOutBack = inOutBack, outInBack = outInBack,
|
||||
inBounce = inBounce, outBounce = outBounce, inOutBounce = inOutBounce, outInBounce = outInBounce
|
||||
}
|
||||
|
||||
-- Private interface
|
||||
local function copyTables(destination, keysTable, valuesTable)
|
||||
valuesTable = valuesTable or keysTable
|
||||
local mt = getmetatable(keysTable)
|
||||
if mt and getmetatable(destination) == nil then
|
||||
setmetatable(destination, mt)
|
||||
end
|
||||
|
||||
for k,v in pairs(keysTable) do
|
||||
if type(v) == 'table' then
|
||||
destination[k] = copyTables({}, v, valuesTable[k])
|
||||
else
|
||||
destination[k] = valuesTable[k]
|
||||
end
|
||||
end
|
||||
return destination
|
||||
end
|
||||
|
||||
local function checkSubjectAndTargetRecursively(subject, target, path)
|
||||
path = path or {}
|
||||
local targetType, newPath
|
||||
for k,targetValue in pairs(target) do
|
||||
targetType, newPath = type(targetValue), copyTables({}, path)
|
||||
table.insert(newPath, tostring(k))
|
||||
if targetType == 'number' then
|
||||
assert(type(subject[k]) == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' is missing from subject or isn't a number")
|
||||
elseif targetType == 'table' then
|
||||
checkSubjectAndTargetRecursively(subject[k], targetValue, newPath)
|
||||
else
|
||||
assert(targetType == 'number', "Parameter '" .. table.concat(newPath,'/') .. "' must be a number or table of numbers")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function checkNewParams(initial, duration, subject, target, easing)
|
||||
-- assert(type(initial) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration))
|
||||
-- assert(type(duration) == 'number' and duration > 0, "duration must be a positive number. Was " .. tostring(duration))
|
||||
assert(type(easing)=='function', "easing must be a function. Was " .. tostring(easing))
|
||||
|
||||
if subject and target then
|
||||
local tsubject = type(subject)
|
||||
assert(tsubject == 'table' or tsubject == 'userdata', "subject must be a table or userdata. Was " .. tostring(subject))
|
||||
assert(type(target)== 'table', "target must be a table. Was " .. tostring(target))
|
||||
checkSubjectAndTargetRecursively(subject, target)
|
||||
end
|
||||
end
|
||||
|
||||
local function getEasingFunction(easing)
|
||||
easing = easing or "linear"
|
||||
if type(easing) == 'string' then
|
||||
local name = easing
|
||||
easing = tween.easing[name]
|
||||
if type(easing) ~= 'function' then
|
||||
error("The easing function name '" .. name .. "' is invalid")
|
||||
end
|
||||
end
|
||||
return easing
|
||||
end
|
||||
|
||||
local function performEasingOnSubject(subject, target, initial, clock, duration, easing)
|
||||
local t,b,c,d
|
||||
for k,v in pairs(target) do
|
||||
if type(v) == 'table' then
|
||||
performEasingOnSubject(subject[k], v, initial[k], clock, duration, easing)
|
||||
else
|
||||
t,b,c,d = clock, initial[k], v - initial[k], duration
|
||||
subject[k] = easing(t,b,c,d)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function performEasing(table, initial, target, clock, duration, easing)
|
||||
if type(target) == "table" then
|
||||
local t,b,c,d
|
||||
for k, v in pairs(target) do
|
||||
if type(v) == 'table' then
|
||||
table[k] = {}
|
||||
performEasing(table[k], initial[k], v, clock, duration, easing)
|
||||
else
|
||||
t,b,c,d = clock, initial[k], v - initial[k], duration
|
||||
table[k] = easing(t,b,c,d)
|
||||
end
|
||||
end
|
||||
|
||||
return table
|
||||
else
|
||||
local t, b, c, d = clock, initial, target - initial, duration
|
||||
return easing(t,b,c,d)
|
||||
end
|
||||
end
|
||||
|
||||
-- Public interface
|
||||
local Tween = {}
|
||||
|
||||
function Tween:set(clock)
|
||||
assert(type(clock) == 'number', "clock must be a positive number or 0")
|
||||
|
||||
if self.subject and self.initial == 0 then
|
||||
self.initial = copyTables({}, self.target, self.subject)
|
||||
end
|
||||
|
||||
self.clock = clock
|
||||
|
||||
if self.clock <= 0 then
|
||||
self.clock = 0
|
||||
if self.subject then
|
||||
copyTables(self.subject, self.initial)
|
||||
end
|
||||
elseif self.clock >= self.duration then -- the tween has expired
|
||||
self.clock = self.duration
|
||||
|
||||
if self.subject then
|
||||
copyTables(self.subject, self.target)
|
||||
end
|
||||
else
|
||||
if self.subject then
|
||||
performEasingOnSubject(self.subject, self.target, self.initial, self.clock, self.duration, self.easing)
|
||||
else
|
||||
local pos = {}
|
||||
return performEasing(pos, self.initial, self.target, self.clock, self.duration, self.easing)
|
||||
end
|
||||
end
|
||||
|
||||
return self.clock >= self.duration
|
||||
end
|
||||
|
||||
function Tween:update(dt)
|
||||
assert(type(dt) == 'number', "dt must be a number")
|
||||
return self:set(self.clock + dt)
|
||||
end
|
||||
|
||||
function Tween:reset()
|
||||
return self:set(0)
|
||||
end
|
||||
|
||||
function tween.new(args)
|
||||
args = args or {}
|
||||
|
||||
args.initial = args.initial or 0
|
||||
args.subject = args.subject or nil
|
||||
args.target = args.target or nil
|
||||
args.duration = args.duration or 0
|
||||
args.easing = args.easing or nil
|
||||
|
||||
args.easing = getEasingFunction(args.easing)
|
||||
checkNewParams(args.initial, args.duration, args.subject, args.target, args.easing)
|
||||
|
||||
local ret = gobject{}
|
||||
ret.clock = 0
|
||||
|
||||
gtable.crush(ret, args, true)
|
||||
gtable.crush(ret, Tween, true)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
return tween
|
145
config/awesome/module/dock.lua → config/awesome/modules/awedock/init.lua
Normal file → Executable file
|
@ -1,21 +1,97 @@
|
|||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local rubato = require(tostring(...):match(".*awedock") .. ".rubato")
|
||||
|
||||
local chel = require("module.dock_helpers").color
|
||||
local rubato = require("module.rubato")
|
||||
local function helpers()
|
||||
local function overloaded()
|
||||
local fns = {}
|
||||
local mt = {}
|
||||
local function oerror()
|
||||
return error("Invalid argument types to overloaded function")
|
||||
end
|
||||
function mt:__call(...)
|
||||
local arg = { ... }
|
||||
local default = self.default
|
||||
local signature = {}
|
||||
for i, arg in ipairs({ ... }) do
|
||||
signature[i] = type(arg)
|
||||
end
|
||||
signature = table.concat(signature, ",")
|
||||
return (fns[signature] or self.default)(...)
|
||||
end
|
||||
function mt:__index(key)
|
||||
local signature = {}
|
||||
local function __newindex(self, key, value)
|
||||
print(key, type(key), value, type(value))
|
||||
signature[#signature + 1] = key
|
||||
fns[table.concat(signature, ",")] = value
|
||||
print("bind", table.concat(signature, ", "))
|
||||
end
|
||||
local function __index(self, key)
|
||||
print("I", key, type(key))
|
||||
signature[#signature + 1] = key
|
||||
return setmetatable({}, { __index = __index, __newindex = __newindex })
|
||||
end
|
||||
return __index(self, key)
|
||||
end
|
||||
function mt:__newindex(key, value)
|
||||
fns[key] = value
|
||||
end
|
||||
return setmetatable({ default = oerror }, mt)
|
||||
end
|
||||
--}}}
|
||||
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local function dec_hex(IN)
|
||||
local B, K, OUT, I, D = 16, "0123456789ABCDEF", "", 0
|
||||
while IN > 0 do
|
||||
I = I + 1
|
||||
IN, D = math.floor(IN / B), (IN % B) + 1
|
||||
OUT = string.sub(K, D, D) .. OUT
|
||||
end
|
||||
return #OUT == 2 and OUT or "0" .. OUT
|
||||
end
|
||||
|
||||
local function init(s, h, o, shape, pinneds)
|
||||
--local function init(args)
|
||||
--[[ if args.screen == nil then return end
|
||||
-- local s = args.screen
|
||||
-- local h = args.height or dpi(50)
|
||||
-- local o = args.offset or 0
|
||||
-- local shape = args.shape or gears.shape.rectangle
|
||||
-- local pinneds = args.pinneds or nil]]
|
||||
-- color helpers {{{
|
||||
local color = {}
|
||||
|
||||
color.col_shift = overloaded()
|
||||
color.col_shift.string.number = function(c, s)
|
||||
local r, g, b, o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r * 255 + s) .. dec_hex(g * 255 + s) .. dec_hex(b * 255 + s) .. dec_hex(o * 255)
|
||||
end
|
||||
color.col_shift.string.number.number.number = function(c, sr, sg, sb)
|
||||
local r, g, b, o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255)
|
||||
end
|
||||
color.col_shift.string.number.number.number.number = function(c, sr, sg, sb, so)
|
||||
local r, g, b, o = gears.color.parse_color(c)
|
||||
return "#" .. dec_hex(r * 255 + sr) .. dec_hex(g * 255 + sg) .. dec_hex(b * 255 + sb) .. dec_hex(o * 255 + so)
|
||||
end
|
||||
|
||||
color.col_diff = function(f, s)
|
||||
local fr, fg, fb, fo = gears.color.parse_color(f)
|
||||
local sr, sg, sb, so = gears.color.parse_color(s)
|
||||
return sr - fr, sg - fg, sb - fb, so - fo
|
||||
end
|
||||
--}}}
|
||||
return {
|
||||
color = color,
|
||||
}
|
||||
end
|
||||
|
||||
local chel = helpers().color
|
||||
|
||||
--local function init(s, h, o, shape, pinneds)
|
||||
local function init(args)
|
||||
local s = args.screen
|
||||
local h = args.height or dpi(50)
|
||||
local o = args.offset or 5
|
||||
local inner_shape = args.inner_shape or gears.shape.rectangle
|
||||
local outer_shape = args.outer_shape or gears.shape.rectangle
|
||||
local pinneds = args.pinneds
|
||||
|
||||
-- tasklist creation {{{
|
||||
local tasklist = awful.widget.tasklist({
|
||||
|
@ -29,9 +105,6 @@ local function init(s, h, o, shape, pinneds)
|
|||
end, --sorts clients in order of their tags
|
||||
filter = awful.widget.tasklist.filter.alltags,
|
||||
forced_height = h,
|
||||
style = {
|
||||
shape = shape,
|
||||
},
|
||||
layout = {
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
|
@ -55,8 +128,8 @@ local function init(s, h, o, shape, pinneds)
|
|||
forced_height = h / 10,
|
||||
forced_width = h / 10,
|
||||
id = "status",
|
||||
bg = beautiful.dock_focused_bg,
|
||||
shape = shape,
|
||||
bg = beautiful.dock_unfocused_indicator_bg or "#484E5B",
|
||||
shape = inner_shape,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
widget = wibox.container.place, --so the bg widget doesnt get stretched
|
||||
|
@ -65,8 +138,8 @@ local function init(s, h, o, shape, pinneds)
|
|||
},
|
||||
id = "bg",
|
||||
widget = wibox.container.background,
|
||||
bg = beautiful.dock_bg,
|
||||
shape = shape,
|
||||
bg = beautiful.dock_bg or "#061115",
|
||||
shape = inner_shape,
|
||||
},
|
||||
widget = wibox.container.margin,
|
||||
margins = h / 10,
|
||||
|
@ -81,7 +154,7 @@ local function init(s, h, o, shape, pinneds)
|
|||
rate = 30,
|
||||
pos = p,
|
||||
subscribed = function(pos)
|
||||
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg, pos)
|
||||
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
|
||||
end,
|
||||
})
|
||||
on_hover.target = t
|
||||
|
@ -119,8 +192,8 @@ local function init(s, h, o, shape, pinneds)
|
|||
self:get_children_by_id("status")[1].forced_width = pos
|
||||
end,
|
||||
})
|
||||
local bg_col = beautiful.dock_focused_bg
|
||||
local bg_focus_col = beautiful.dock_accent
|
||||
local bg_col = beautiful.dock_unfocused_indicator_bg or "#484E5B"
|
||||
local bg_focus_col = beautiful.dock_indicator_bg or "#6791C9"
|
||||
local sh_r, sh_g, sh_b, _ = chel.col_diff(bg_col, bg_focus_col)
|
||||
|
||||
local status_c = rubato.timed({
|
||||
|
@ -182,7 +255,7 @@ local function init(s, h, o, shape, pinneds)
|
|||
forced_height = h / 10,
|
||||
forced_width = h / 10,
|
||||
id = "status",
|
||||
shape = shape,
|
||||
shape = inner_shape,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
widget = wibox.container.place, --so the bg widget doesnt get stretched
|
||||
|
@ -191,7 +264,7 @@ local function init(s, h, o, shape, pinneds)
|
|||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
widget = wibox.container.background,
|
||||
shape = shape,
|
||||
shape = inner_shape,
|
||||
id = "bg",
|
||||
buttons = awful.button({}, 1, function()
|
||||
awful.spawn.easy_async(p.start_cmd)
|
||||
|
@ -211,7 +284,7 @@ local function init(s, h, o, shape, pinneds)
|
|||
rate = 30,
|
||||
pos = po,
|
||||
subscribed = function(pos)
|
||||
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg, pos)
|
||||
self:get_children_by_id("bg")[1].bg = chel.col_shift(beautiful.dock_bg or "#061115", pos)
|
||||
end,
|
||||
})
|
||||
on_hover.target = t
|
||||
|
@ -237,24 +310,20 @@ local function init(s, h, o, shape, pinneds)
|
|||
screen = s,
|
||||
x = s.geometry.x + s.geometry.width / 2,
|
||||
y = s.geometry.y + s.geometry.height - (h + o),
|
||||
shape = shape,
|
||||
shape = outer_shape,
|
||||
widget = {
|
||||
{
|
||||
{
|
||||
{
|
||||
pinned_apps,
|
||||
tasklist,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
widget = wibox.container.margin,
|
||||
margin = dpi(5),
|
||||
pinned_apps,
|
||||
tasklist,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
widget = wibox.container.background,
|
||||
bg = beautiful.dock_bg,
|
||||
shape = shape,
|
||||
widget = wibox.container.margin,
|
||||
margin = dpi(5),
|
||||
},
|
||||
widget = wibox.container.place,
|
||||
halign = "center",
|
||||
widget = wibox.container.background,
|
||||
bg = beautiful.dock_bg or "#061115",
|
||||
shape = inner_shape,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -275,7 +344,7 @@ local function init(s, h, o, shape, pinneds)
|
|||
end,
|
||||
})
|
||||
local autohidetimer = gears.timer({
|
||||
timeout = 1,
|
||||
timeout = 2,
|
||||
single_shot = true,
|
||||
callback = function()
|
||||
autohideanim.target = 0
|
0
config/awesome/module/rubato/.editorconfig → config/awesome/modules/awedock/rubato/.editorconfig
Normal file → Executable file
|
@ -0,0 +1 @@
|
|||
tags
|
0
config/awesome/module/rubato/LICENSE → config/awesome/modules/awedock/rubato/LICENSE
Normal file → Executable file
0
config/awesome/module/rubato/README.md → config/awesome/modules/awedock/rubato/README.md
Normal file → Executable file
0
config/awesome/module/rubato/easing.lua → config/awesome/modules/awedock/rubato/easing.lua
Normal file → Executable file
0
config/awesome/module/rubato/images/beautiful.gif → config/awesome/modules/awedock/rubato/images/beautiful.gif
Normal file → Executable file
Before Width: | Height: | Size: 809 KiB After Width: | Height: | Size: 809 KiB |
0
config/awesome/module/rubato/images/connected_graph.png → config/awesome/modules/awedock/rubato/images/connected_graph.png
Normal file → Executable file
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
0
config/awesome/module/rubato/images/disconnected_graph.png → config/awesome/modules/awedock/rubato/images/disconnected_graph.png
Normal file → Executable file
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
0
config/awesome/module/rubato/images/normal_graph.png → config/awesome/modules/awedock/rubato/images/normal_graph.png
Normal file → Executable file
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
0
config/awesome/module/rubato/images/quadratic_easing.gif → config/awesome/modules/awedock/rubato/images/quadratic_easing.gif
Normal file → Executable file
Before Width: | Height: | Size: 248 KiB After Width: | Height: | Size: 248 KiB |
0
config/awesome/module/rubato/images/slope_graph.png → config/awesome/modules/awedock/rubato/images/slope_graph.png
Normal file → Executable file
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
0
config/awesome/module/rubato/images/trapezoid_easing.gif → config/awesome/modules/awedock/rubato/images/trapezoid_easing.gif
Normal file → Executable file
Before Width: | Height: | Size: 97 KiB After Width: | Height: | Size: 97 KiB |
0
config/awesome/module/rubato/images/triangleish.png → config/awesome/modules/awedock/rubato/images/triangleish.png
Normal file → Executable file
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
0
config/awesome/module/rubato/init.lua → config/awesome/modules/awedock/rubato/init.lua
Normal file → Executable file
0
config/awesome/module/rubato/rubato-1.1-1.rockspec → config/awesome/modules/awedock/rubato/rubato-1.1-1.rockspec
Normal file → Executable file
0
config/awesome/module/rubato/subscribable.lua → config/awesome/modules/awedock/rubato/subscribable.lua
Normal file → Executable file
4
config/awesome/module/rubato/timed.lua → config/awesome/modules/awedock/rubato/timed.lua
Normal file → Executable file
|
@ -195,10 +195,10 @@ local function timed(args)
|
|||
timer:stop() --stops itself
|
||||
|
||||
--run subscribed in functions
|
||||
obj:fire(obj.pos, time, dx)
|
||||
obj:fire(obj.pos, obj.duration, dx)
|
||||
|
||||
-- awestore compatibility...
|
||||
if obj.awestore_compat then obj.ended:fire(obj.pos, time, dx) end
|
||||
if obj.awestore_compat then obj.ended:fire(obj.pos, obj.duration, dx) end
|
||||
|
||||
--otherwise it just fires normally
|
||||
else obj:fire(obj.pos, time, dx) end
|
|
@ -0,0 +1 @@
|
|||
doc/
|
|
@ -0,0 +1,84 @@
|
|||
# UPower Battery Widget
|
||||
|
||||
This is my re-implementation of the [awesome-upower-battery][awesome-upower-battery-repository] by [berlam][berlam]. This widget has a lot of potencial for the [Awesome WM][AwesomeWM] and I wanted to hack it a bit for my personal use.
|
||||
|
||||
UPower is an abstraction for power devices. You can use it to access advanced statistics about your power devices.
|
||||
UPowerGlib is a Glib interface to access data exposed by UPower.
|
||||
The Awesome WM uses LGI as an interpolation layer for Glib with Lua. So, you can access the UPowerGlib interface directly from your lua code.
|
||||
|
||||
Thanks to this, we can write battery widget relaying on realtime data pushed from the UPower daemon itself. So the battery widget as no charge on the system (no need to pull data every X seconds) and provides more accurate data to the user.
|
||||
|
||||
## Usage
|
||||
|
||||
When creating an instance of this widget, you can specify the `widget_template` you want to use and how the widget updates. It gives you the control on how the widget should display the battery status.
|
||||
|
||||
You can generate the API documentation with [ldoc][ldoc].
|
||||
|
||||
```sh
|
||||
ldoc -c config.ld init.lua
|
||||
```
|
||||
|
||||
Here is an example of implementation using a [`wibox.widget.textbox`][awesome-api-wibox.widget.textbox] widget to display the battery percentage:
|
||||
|
||||
```lua
|
||||
-- Load the module:
|
||||
local battery_widget = require 'battery_widget'
|
||||
|
||||
-- Create the battery widget:
|
||||
local my_battery_widget = battery_widget {
|
||||
screen = screen,
|
||||
use_display_device = true,
|
||||
widget_template = wibox.widget.textbox
|
||||
}
|
||||
|
||||
-- When UPower updates the battery status, the widget is notified
|
||||
-- and calls a signal you need to connect to:
|
||||
my_battery_widget:connect_signal('upower::update', function (widget, device)
|
||||
widget.text = string.format('%3d', device.percentage) .. '%'
|
||||
end)
|
||||
```
|
||||
|
||||
### Using different devices
|
||||
|
||||
With the parameter `use_display_device = true`, the battery widget will automatically monitor the _display device_.
|
||||
|
||||
If you want to manually set which device to monitor, you can use the `device_path` parameter.
|
||||
|
||||
```lua
|
||||
local my_battery_widget = battery_widget{
|
||||
screen = s,
|
||||
device_path = '/org/freedesktop/UPower/devices/battery_BAT0',
|
||||
widget_template = wibox.widget.textbox
|
||||
}
|
||||
```
|
||||
|
||||
You can check the API documentation to read more about statics function to help you to identify your devices.
|
||||
|
||||
### Battery widget not appearing
|
||||
|
||||
When creating a new instance of `battery_widget`, the widget will not be shown. The widget waits an update from UPower to call the "upower::update" signal and use your attached callback to update (and draw) the widget.
|
||||
|
||||
You can however use one of the following method to force the widget to be drawn at its creation:
|
||||
|
||||
* Use the parameter `instant_update` to explicitly ask the battery_widget to call the "upower::update" signal at the next Awesome WM cycle.
|
||||
* Use the parameter `create_callback` to use your own code to initialize the widget. (This callback await the same arguments than the "upower::update" signal)
|
||||
|
||||
You can read more about these parameters in the API documentation.
|
||||
|
||||
## Dependencies
|
||||
|
||||
* [Awesome WM][AwesomeWM]
|
||||
* [UPower][UPower]
|
||||
* [UPowerGlib][UPowerGlib]
|
||||
|
||||
## Acknowledgment
|
||||
|
||||
Thanks a lot to [berlam][berlam] for the initial code and the idea to use the UPowerGlib interface 🚀.
|
||||
|
||||
[awesome-upower-battery-repository]: https://github.com/berlam/awesome-upower-battery
|
||||
[berlam]: https://github.com/berlam
|
||||
[AwesomeWM]: https://awesomewm.org/
|
||||
[awesome-api-wibox.widget.textbox]: https://awesomewm.org/apidoc/widgets/wibox.widget.textbox.html
|
||||
[UPower]: https://upower.freedesktop.org/
|
||||
[UPowerGlib]: https://lazka.github.io/pgi-docs/UPowerGlib-1.0/index.html
|
||||
[ldoc]: https://stevedonovan.github.io/ldoc/
|
|
@ -0,0 +1,24 @@
|
|||
-- Configuration file for ldoc
|
||||
|
||||
project = 'battery_widget'
|
||||
title = 'Awesome WM - Battery Widget'
|
||||
|
||||
all = false
|
||||
dir = 'doc'
|
||||
format='markdown'
|
||||
pretty = 'lua'
|
||||
prettify_files = true
|
||||
backtick_references = true
|
||||
merge = true
|
||||
use_markdown_titles = true
|
||||
wrap = true
|
||||
sort_modules = true
|
||||
not_luadoc = true
|
||||
|
||||
|
||||
-- Define some new ldoc tags from the AwesomeWM doc
|
||||
new_type("staticfct", "Static functions", false, "Parameters")
|
||||
new_type("constructorfct", "Constructor", false, "Parameters")
|
||||
new_type("method", "Object methods", false, "Parameters")
|
||||
new_type("property", "Object properties", false, "Type")
|
||||
new_type("signal", "Signals", false, "Arguments")
|
|
@ -0,0 +1,140 @@
|
|||
---------------------------------------------------------------------------
|
||||
-- A battery widget based on the UPower deamon.
|
||||
--
|
||||
-- @author Aire-One
|
||||
-- @copyright 2020 Aire-One
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local upower = require('lgi').require('UPowerGlib')
|
||||
|
||||
local gtable = require 'gears.table'
|
||||
local gtimer = require 'gears.timer'
|
||||
local wbase = require 'wibox.widget.base'
|
||||
|
||||
local setmetatable = setmetatable -- luacheck: ignore setmetatable
|
||||
|
||||
local battery_widget = {}
|
||||
local mt = {}
|
||||
|
||||
|
||||
--- Helper to get the path of all connected power devices.
|
||||
-- @treturn table The list of all power devices path.
|
||||
-- @staticfct battery_widget.list_devices
|
||||
function battery_widget.list_devices()
|
||||
local ret = {}
|
||||
local devices = upower.Client():get_devices()
|
||||
|
||||
for _,d in ipairs(devices) do
|
||||
table.insert(ret, d:get_object_path())
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
--- Helper function to get a device instance from its path.
|
||||
-- @tparam string path The path of the device to get.
|
||||
-- @treturn UPowerGlib.Device|nil The device if it was found, `nil` otherwise.
|
||||
-- @staticfct battery_widget.get_device
|
||||
function battery_widget.get_device(path)
|
||||
local devices = upower.Client():get_devices()
|
||||
|
||||
for _,d in ipairs(devices) do
|
||||
if d:get_object_path() == path then
|
||||
return d
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Helper function to easily get the default BAT0 device path without.
|
||||
-- @treturn string The BAT0 device path.
|
||||
-- @staticfct battery_widget.get_BAT0_device_path
|
||||
function battery_widget.get_BAT0_device_path()
|
||||
local bat0_path = '/org/freedesktop/UPower/devices/battery_BAT0'
|
||||
return bat0_path
|
||||
end
|
||||
|
||||
--- Helper function to convert seconds into a human readable clock string.
|
||||
--
|
||||
-- This translates the given seconds parameter into a human readable string
|
||||
-- following the notation `HH:MM` (where HH is the number of hours and MM the
|
||||
-- number of minutes).
|
||||
-- @tparam number seconds The umber of seconds to translate.
|
||||
-- @treturn string The human readable generated clock string.
|
||||
-- @staticfct battery_widget.to_clock
|
||||
function battery_widget.to_clock(seconds)
|
||||
if seconds <= 0 then
|
||||
return '00:00';
|
||||
else
|
||||
local hours = string.format('%02.f', math.floor(seconds/3600));
|
||||
local mins = string.format('%02.f', math.floor(seconds/60 - hours*60));
|
||||
return hours .. ':' .. mins
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Gives the default widget to use if user didn't specify one.
|
||||
-- The default widget used is an `empty_widget` instance.
|
||||
-- @treturn widget The default widget to use.
|
||||
local function default_template ()
|
||||
return wbase.empty_widget()
|
||||
end
|
||||
|
||||
|
||||
--- The device monitored by the widget.
|
||||
-- @property device
|
||||
-- @tparam UPowerGlib.Device device
|
||||
|
||||
--- Emited when the UPower device notify an update.
|
||||
-- @signal upower::update
|
||||
-- @tparam battery_widget widget The widget.
|
||||
-- @tparam UPowerGlib.Device device The Upower device.
|
||||
|
||||
|
||||
--- battery_widget constructor.
|
||||
--
|
||||
-- This function creates a new `battery_widget` instance. This widget watches
|
||||
-- the `display_device` status and report.
|
||||
-- @tparam table args The arguments table.
|
||||
-- @tparam[opt] widget args.widget_template The widget template to use to
|
||||
-- create the widget instance.
|
||||
-- @tparam[opt] string args.device_path Path of the device to monitor.
|
||||
-- @tparam[opt=false] boolean args.use_display_device Should the widget monitor
|
||||
-- the _display device_?
|
||||
-- @tparam[opt] boolean args.instant_update Call an update cycle right after the
|
||||
-- widget creation.
|
||||
-- @treturn battery_widget The battery_widget instance build.
|
||||
-- @constructorfct battery_widget.new
|
||||
function battery_widget.new (args)
|
||||
args = gtable.crush({
|
||||
widget_template = default_template(),
|
||||
device_path = '',
|
||||
use_display_device = false
|
||||
}, args or {})
|
||||
|
||||
local widget = wbase.make_widget_from_value(args.widget_template)
|
||||
|
||||
widget.device = args.use_display_device
|
||||
and upower.Client():get_display_device()
|
||||
or battery_widget.get_device(args.device_path)
|
||||
|
||||
-- Attach signals:
|
||||
widget.device.on_notify = function (d)
|
||||
widget:emit_signal('upower::update', d)
|
||||
end
|
||||
|
||||
-- Call an update cycle if the user asked to instan update the widget.
|
||||
if args.instant_update then
|
||||
gtimer.delayed_call(widget.emit_signal, widget, 'upower::update', widget.device)
|
||||
end
|
||||
|
||||
return widget
|
||||
end
|
||||
|
||||
|
||||
function mt.__call(self, ...)
|
||||
return battery_widget.new(...)
|
||||
end
|
||||
|
||||
return setmetatable(battery_widget, mt)
|
0
config/awesome/module/better-resize.lua → config/awesome/modules/better-resize.lua
Normal file → Executable file
0
config/awesome/module/bling/.editorconfig → config/awesome/modules/bling/.editorconfig
Normal file → Executable file
0
config/awesome/module/bling/AUTHORS.md → config/awesome/modules/bling/AUTHORS.md
Normal file → Executable file
0
config/awesome/module/bling/CODEOWNERS → config/awesome/modules/bling/CODEOWNERS
Normal file → Executable file
0
config/awesome/module/bling/LICENSE → config/awesome/modules/bling/LICENSE
Normal file → Executable file
0
config/awesome/module/bling/README.md → config/awesome/modules/bling/README.md
Normal file → Executable file
0
config/awesome/module/bling/bling-dev-1.rockspec → config/awesome/modules/bling/bling-dev-1.rockspec
Normal file → Executable file
|
@ -0,0 +1,23 @@
|
|||
- [Home](home.md)
|
||||
|
||||
- [Layouts](layouts/layout.md)
|
||||
|
||||
- Modules
|
||||
- [Flash Focus](module/flash.md)
|
||||
- [Tabbed](module/tabbed.md)
|
||||
- [Tiled Wallpaper](module/twall.md)
|
||||
- [Wallpaper Easy Setup](module/wall.md)
|
||||
- [Window Swallowing](module/swal.md)
|
||||
- [Scratchpad](module/scratch.md)
|
||||
|
||||
- Signals
|
||||
- [Playerctl](signals/pctl.md)
|
||||
|
||||
- Widgets
|
||||
- [Tag Preview](widgets/tag_preview.md)
|
||||
- [Task Preview](widgets/task_preview.md)
|
||||
- [Tabbed Misc](widgets/tabbed_misc.md)
|
||||
- [Window Switcher](widgets/window_switcher.md)
|
||||
|
||||
- Extra
|
||||
- [Theme Variable Template](theme.md)
|
|
@ -0,0 +1,34 @@
|
|||
# <center> 🌟 Bling - Utilities for AwesomeWM 🌟 </center>
|
||||
|
||||
## Why
|
||||
|
||||
[AwesomeWM](https://awesomewm.org/) is literally what it stands for, an awesome window manager.
|
||||
|
||||
Its unique selling point has always been the widget system, which allows for fancy buttons, sliders, bars, dashboards and anything you can imagine. But that feature can be a curse. Most modules focus on the widget side of things which leave the actual window managing part of AwesomeWM underdeveloped compared to, for example, [xmonad](https://xmonad.org/) even though it's probably just as powerfull in that area.
|
||||
|
||||
This project focuses on that problem - adding new layouts and modules that make use of the widget system, but primarily focus on the new window managing features.
|
||||
|
||||
## Installation
|
||||
- clone this repo into your `~/.config/awesome` folder
|
||||
- `git clone https://github.com/BlingCorp/bling.git ~/.config/awesome/bling`
|
||||
- require the module in your `rc.lua`, and make sure it's under the beautiful module initialization
|
||||
|
||||
```lua
|
||||
-- other imports
|
||||
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
-- other configuration stuff here
|
||||
|
||||
beautiful.init("some_theme.lua")
|
||||
local bling = require("bling")
|
||||
```
|
||||
|
||||
## Contributors
|
||||
A special thanks to all our contributors...
|
||||
|
||||
<a href="https://github.com/BlingCorp/bling/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=BlingCorp/bling" />
|
||||
</a>
|
||||
|
||||
Made with [contributors-img](https://contrib.rocks).
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Bling Docs</title>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta name="description" content="Utilities for the awesome window manager">
|
||||
<meta name="og:image" content="https://raw.githubusercontent.com/BlingCorp/bling/master/images/bling_banner.png">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link rel="stylesheet" href="javacafe.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<script>
|
||||
window.$docsify = {
|
||||
name: 'Bling',
|
||||
nameLink: '/',
|
||||
repo: 'https://github.com/BlingCorp/bling',
|
||||
loadSidebar: true,
|
||||
subMaxLevel: 3,
|
||||
homepage: 'home.md'
|
||||
}
|
||||
</script>
|
||||
<!-- Docsify v4 -->
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify@4"></script>
|
||||
<script src="//unpkg.com/prismjs/components/prism-lua.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,65 @@
|
|||
## 📎 Layouts <!-- {docsify-ignore} -->
|
||||
|
||||
Choose layouts from the list below and add them to to your `awful.layouts` list in your `rc.lua`.
|
||||
|
||||
Everyone of them supports multiple master clients and master width factor making them easy to use.
|
||||
|
||||
The mstab layout uses the tab theme from the tabbed module.
|
||||
|
||||
```lua
|
||||
bling.layout.mstab
|
||||
bling.layout.centered
|
||||
bling.layout.vertical
|
||||
bling.layout.horizontal
|
||||
bling.layout.equalarea
|
||||
bling.layout.deck
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
|
||||
```lua
|
||||
-- mstab
|
||||
theme.mstab_bar_disable = false -- disable the tabbar
|
||||
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
|
||||
theme.mstab_dont_resize_slaves = false -- whether the tabbed stack windows should be smaller than the
|
||||
-- currently focused stack window (set it to true if you use
|
||||
-- transparent terminals. False if you use shadows on solid ones
|
||||
theme.mstab_bar_padding = "default" -- how much padding there should be between clients and your tabbar
|
||||
-- by default it will adjust based on your useless gaps.
|
||||
-- If you want a custom value. Set it to the number of pixels (int)
|
||||
theme.mstab_border_radius = 0 -- border radius of the tabbar
|
||||
theme.mstab_bar_height = 40 -- height of the tabbar
|
||||
theme.mstab_tabbar_position = "top" -- position of the tabbar (mstab currently does not support left,right)
|
||||
theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
-- defaults to the tabbar_style so only change if you want a
|
||||
-- different style for mstab and tabbed
|
||||
```
|
||||
|
||||
### Previews
|
||||
|
||||
#### Mstab (dynamic tabbing layout)
|
||||
|
||||
![](https://imgur.com/HZRgApE.png)
|
||||
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
||||
#### Centered
|
||||
|
||||
![](https://media.discordapp.net/attachments/769673106842845194/780095998239834142/unknown.png)
|
||||
|
||||
*screenshot by [HeavyRain266](https://github.com/HeavyRain266)*
|
||||
|
||||
#### Equal area
|
||||
|
||||
![](https://imgur.com/JCFFywv.png)
|
||||
|
||||
*screenshot by [bysmutheye](https://github.com/bysmutheye)*
|
||||
|
||||
#### Deck
|
||||
|
||||
The left area shows the deck layout in action. In this screenshot it is used together with [layout machi](https://github.com/xinhaoyuan/layout-machi) and its sublayout support.
|
||||
|
||||
![](https://cdn.discordapp.com/attachments/635625954219261982/877957824225894430/unknown.png)
|
||||
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
## 🔦 Flash Focus <!-- {docsify-ignore} -->
|
||||
|
||||
Flash focus does an opacity animation effect on a client when it is focused.
|
||||
|
||||
|
||||
### Usage
|
||||
|
||||
There are two ways in which you can use this module. You can enable it by calling the `enable()` function:
|
||||
```lua
|
||||
bling.module.flash_focus.enable()
|
||||
```
|
||||
This connects to the focus signal of a client, which means that the flash focus will activate however you focus the client.
|
||||
|
||||
The other way is to call the function itself like this: `bling.module.flash_focus.flashfocus(someclient)`. This allows you to activate on certain keybinds like so:
|
||||
```lua
|
||||
awful.key({modkey}, "Up",
|
||||
function()
|
||||
awful.client.focus.bydirection("up")
|
||||
bling.module.flash_focus.flashfocus(client.focus)
|
||||
end, {description = "focus up", group = "client"})
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.flash_focus_start_opacity = 0.6 -- the starting opacity
|
||||
theme.flash_focus_step = 0.01 -- the step of animation
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
||||
![](https://imgur.com/5txYrlV.gif)
|
||||
|
||||
*gif by [JavaCafe01](https://github.com/JavaCafe01)*
|
|
@ -0,0 +1,75 @@
|
|||
## 🍃 Scratchpad <!-- {docsify-ignore} -->
|
||||
|
||||
An easy way to create multiple scratchpads.
|
||||
|
||||
### A... what?
|
||||
|
||||
You can think about a scratchpad as a window whose visibility can be toggled, but still runs in the background without being visible (or minimized) most of the time. Many people use it to have one terminal in which to perform minor tasks, but it is the most useful for windows which only need a couple seconds in between your actual activity, such as music players or chat applications.
|
||||
|
||||
### Rubato Animation Support
|
||||
|
||||
#### Awestore is now deprecated from Bling, we are switching to Rubato.
|
||||
|
||||
Please go over to the [rubato](https://github.com/andOrlando/rubato) repository for installation instructions. Give it a star as well! The animations are completely optional, and if you choose not to use it, you do not need rubato installed.
|
||||
|
||||
### Usage
|
||||
|
||||
To initalize a scratchpad you can do something like the following:
|
||||
|
||||
```lua
|
||||
local bling = require("bling")
|
||||
local rubato = require("rubato") -- Totally optional, only required if you are using animations.
|
||||
|
||||
-- These are example rubato tables. You can use one for just y, just x, or both.
|
||||
-- The duration and easing is up to you. Please check out the rubato docs to learn more.
|
||||
local anim_y = rubato.timed {
|
||||
pos = 1090,
|
||||
rate = 60,
|
||||
easing = rubato.quadratic,
|
||||
intro = 0.1,
|
||||
duration = 0.3,
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
}
|
||||
|
||||
local anim_x = rubato.timed {
|
||||
pos = -970,
|
||||
rate = 60,
|
||||
easing = rubato.quadratic,
|
||||
intro = 0.1,
|
||||
duration = 0.3,
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
}
|
||||
|
||||
local term_scratch = bling.module.scratchpad {
|
||||
command = "wezterm start --class spad", -- How to spawn the scratchpad
|
||||
rule = { instance = "spad" }, -- The rule that the scratchpad will be searched by
|
||||
sticky = true, -- Whether the scratchpad should be sticky
|
||||
autoclose = true, -- Whether it should hide itself when losing focus
|
||||
floating = true, -- Whether it should be floating (MUST BE TRUE FOR ANIMATIONS)
|
||||
geometry = {x=360, y=90, height=900, width=1200}, -- The geometry in a floating state
|
||||
reapply = true, -- Whether all those properties should be reapplied on every new opening of the scratchpad (MUST BE TRUE FOR ANIMATIONS)
|
||||
dont_focus_before_close = false, -- When set to true, the scratchpad will be closed by the toggle function regardless of whether its focused or not. When set to false, the toggle function will first bring the scratchpad into focus and only close it on a second call
|
||||
rubato = {x = anim_x, y = anim_y} -- Optional. This is how you can pass in the rubato tables for animations. If you don't want animations, you can ignore this option.
|
||||
}
|
||||
```
|
||||
|
||||
Once initalized, you can use the object (which in this case is named `term_scratch`) like this:
|
||||
|
||||
```lua
|
||||
term_scratch:toggle() -- toggles the scratchpads visibility
|
||||
term_scratch:turn_on() -- turns the scratchpads visibility on
|
||||
term_scratch:turn_off() -- turns the scratchpads visibility off
|
||||
```
|
||||
|
||||
You can also connect to signals as you are used to for further customization. For example like that:
|
||||
|
||||
```lua
|
||||
term_scratch:connect_signal("turn_on", function(c) naughty.notify({title = "Turned on!"}) end)
|
||||
```
|
||||
|
||||
The following signals are currently available. `turn_on`, `turn_off` and `inital_apply` pass the client on which they operated as an argument:
|
||||
|
||||
- `turn_on` fires when the scratchpad is turned on on a tag that it wasn't present on before
|
||||
- `turn_off` fires when the scratchpad is turned off on a tag
|
||||
- `spawn` fires when the scratchpad is launched with the given command
|
||||
- `inital_apply` fires after `spawn`, when a corresponding client has been found and the properties have been applied
|
|
@ -0,0 +1,25 @@
|
|||
## 😋 Window Swallowing <!-- {docsify-ignore} -->
|
||||
|
||||
Can your window manager swallow? It probably can...
|
||||
|
||||
### Usage
|
||||
|
||||
To activate and deactivate window swallowing here are the following functions. If you want to activate it, just call the `start` function once in your `rc.lua`.
|
||||
```lua
|
||||
bling.module.window_swallowing.start() -- activates window swallowing
|
||||
bling.module.window_swallowing.stop() -- deactivates window swallowing
|
||||
bling.module.window_swallowing.toggle() -- toggles window swallowing
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.parent_filter_list = {"firefox", "Gimp"} -- class names list of parents that should not be swallowed
|
||||
theme.child_filter_list = { "Dragon" } -- class names list that should not swallow their parents
|
||||
theme.swallowing_filter = true -- whether the filters above should be active
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
||||
![](https://media.discordapp.net/attachments/635625813143978012/769180910683684864/20-10-23-14-40-32.gif)
|
||||
|
||||
*gif by [Nooo37](https://github.com/Nooo37)*
|
|
@ -0,0 +1,66 @@
|
|||
## 📑 Tabbed <!-- {docsify-ignore} -->
|
||||
|
||||
Tabbed implements a tab container. There are also different themes for the tabs.
|
||||
|
||||
### Usage
|
||||
|
||||
You should bind these functions to keys in order to use the tabbed module effectively:
|
||||
```lua
|
||||
bling.module.tabbed.pick() -- picks a client with your cursor to add to the tabbing group
|
||||
bling.module.tabbed.pop() -- removes the focused client from the tabbing group
|
||||
bling.module.tabbed.iter() -- iterates through the currently focused tabbing group
|
||||
bling.module.tabbed.pick_with_dmenu() -- picks a client with a dmenu application (defaults to rofi, other options can be set with a string parameter like "dmenu")
|
||||
bling.module.tabbed.pick_by_direction(dir) -- picks a client based on direction ("up", "down", "left" or "right")
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
|
||||
```lua
|
||||
-- For tabbed only
|
||||
theme.tabbed_spawn_in_tab = false -- whether a new client should spawn into the focused tabbing container
|
||||
|
||||
-- For tabbar in general
|
||||
theme.tabbar_ontop = false
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background color of the focused client on the tabbar
|
||||
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
|
||||
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
|
||||
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
|
||||
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
|
||||
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
|
||||
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
|
||||
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
|
||||
theme.tabbar_disable = false -- disable the tab bar entirely
|
||||
|
||||
-- the following variables are currently only for the "modern" tabbar style
|
||||
theme.tabbar_color_close = "#f9929b" -- chnges the color of the close button
|
||||
theme.tabbar_color_min = "#fbdf90" -- chnges the color of the minimize button
|
||||
theme.tabbar_color_float = "#ccaced" -- chnges the color of the float button
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
||||
Modern theme:
|
||||
|
||||
<img src="https://imgur.com/omowmIQ.png" width="600"/>
|
||||
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
||||
### Signals
|
||||
The tabbed module emits a few signals for the purpose of integration,
|
||||
```lua
|
||||
-- bling::tabbed::update -- triggered whenever a tabbed object is updated
|
||||
-- tabobj -- the object that caused the update
|
||||
-- bling::tabbed::client_added -- triggered whenever a new client is added to a tab group
|
||||
-- tabobj -- the object that the client was added to
|
||||
-- client -- the client that added
|
||||
-- bling::tabbed::client_removed -- triggered whenever a client is removed from a tab group
|
||||
-- tabobj -- the object that the client was removed from
|
||||
-- client -- the client that was removed
|
||||
-- bling::tabbed::changed_focus -- triggered whenever a tab group's focus is changed
|
||||
-- tabobj -- the modified tab group
|
||||
```
|
|
@ -0,0 +1,26 @@
|
|||
## 🏬 Tiled Wallpaper <!-- {docsify-ignore} -->
|
||||
|
||||
### Usage
|
||||
|
||||
The function to set an automatically created tiled wallpaper can be called the following way (you don't need to set every option in the table):
|
||||
```lua
|
||||
awful.screen.connect_for_each_screen(function(s) -- that way the wallpaper is applied to every screen
|
||||
bling.module.tiled_wallpaper("x", s, { -- call the actual function ("x" is the string that will be tiled)
|
||||
fg = "#ff0000", -- define the foreground color
|
||||
bg = "#00ffff", -- define the background color
|
||||
offset_y = 25, -- set a y offset
|
||||
offset_x = 25, -- set a x offset
|
||||
font = "Hack", -- set the font (without the size)
|
||||
font_size = 14, -- set the font size
|
||||
padding = 100, -- set padding (default is 100)
|
||||
zickzack = true -- rectangular pattern or criss cross
|
||||
})
|
||||
end)
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
||||
![](https://media.discordapp.net/attachments/702548913999314964/773887721294135296/tiled-wallpapers.png?width=1920&height=1080)
|
||||
|
||||
*screenshots by [Nooo37](https://github.com/Nooo37)*
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
## 🎇 Wallpaper Easy Setup <!-- {docsify-ignore} -->
|
||||
|
||||
This is a simple-to-use, extensible, declarative wallpaper manager.
|
||||
|
||||
### Practical Examples
|
||||
|
||||
```lua
|
||||
-- A default Awesome wallpaper
|
||||
bling.module.wallpaper.setup()
|
||||
|
||||
-- A slideshow with pictures from different sources changing every 30 minutes
|
||||
bling.module.wallpaper.setup {
|
||||
wallpaper = {"/images/my_dog.jpg", "/images/my_cat.jpg"},
|
||||
change_timer = 1800
|
||||
}
|
||||
|
||||
-- A random wallpaper with images from multiple folders
|
||||
bling.module.wallpaper.setup {
|
||||
set_function = bling.module.wallpaper.setters.random,
|
||||
wallpaper = {"/path/to/a/folder", "/path/to/another/folder"},
|
||||
change_timer = 631, -- prime numbers are better for timers
|
||||
position = "fit",
|
||||
background = "#424242"
|
||||
}
|
||||
|
||||
-- wallpapers based on a schedule, like awesome-glorious-widgets dynamic wallpaper
|
||||
-- https://github.com/manilarome/awesome-glorious-widgets/tree/master/dynamic-wallpaper
|
||||
bling.module.wallpaper.setup {
|
||||
set_function = bling.module.wallpaper.setters.simple_schedule,
|
||||
wallpaper = {
|
||||
["06:22:00"] = "morning-wallpaper.jpg",
|
||||
["12:00:00"] = "noon-wallpaper.jpg",
|
||||
["17:58:00"] = "night-wallpaper.jpg",
|
||||
["24:00:00"] = "midnight-wallpaper.jpg",
|
||||
},
|
||||
position = "maximized",
|
||||
}
|
||||
|
||||
-- random wallpapers, from different folder depending on time of the day
|
||||
bling.module.wallpaper.setup {
|
||||
set_function = bling.module.wallpaper.setters.simple_schedule,
|
||||
wallpaper = {
|
||||
["09:00:00"] = "~/Pictures/safe_for_work",
|
||||
["18:00:00"] = "~/Pictures/personal",
|
||||
},
|
||||
schedule_set_function = bling.module.wallpaper.setters.random
|
||||
position = "maximized",
|
||||
recursive = false,
|
||||
change_timer = 600
|
||||
}
|
||||
|
||||
-- setup for multiple screens at once
|
||||
-- the 'screen' argument can be a table of screen objects
|
||||
bling.module.wallpaper.setup {
|
||||
set_function = bling.module.wallpaper.setters.random,
|
||||
screen = screen, -- The awesome 'screen' variable is an array of all screen objects
|
||||
wallpaper = {"/path/to/a/folder", "/path/to/another/folder"},
|
||||
change_timer = 631
|
||||
}
|
||||
```
|
||||
### Details
|
||||
|
||||
The setup function will do 2 things: call the set-function when awesome requests a wallpaper, and manage a timer to call `set_function` periodically.
|
||||
|
||||
Its argument is a args table that is passed to ohter functions (setters and wallpaper functions), so you define everything with setup.
|
||||
|
||||
The `set_function` is a function called every times a wallpaper is needed.
|
||||
|
||||
The module provides some setters:
|
||||
|
||||
* `bling.module.wallpaper.setters.awesome_wallpaper`: beautiful.theme_assets.wallpaper with defaults from beautiful.
|
||||
* `bling.module.wallpaper.setters.simple`: slideshow from the `wallpaper` argument.
|
||||
* `bling.module.wallpaper.setters.random`: same as simple but in a random way.
|
||||
* `bling.module.wallpaper.setters.simple_schedule`: takes a table of `["HH:MM:SS"] = wallpaper` arguments, where wallpaper is the `wallpaper` argument used by `schedule_set_function`.
|
||||
|
||||
A wallpaper is one of the following elements:
|
||||
|
||||
* a color
|
||||
* an image
|
||||
* a folder containing images
|
||||
* a function that sets a wallpaper
|
||||
* everything gears.wallpaper functions can manage (cairo surface, cairo pattern string)
|
||||
* a list containing any of the elements above
|
||||
|
||||
To set up for multiple screens, two possible methods are:
|
||||
* Call the `setup` function for each screen, passing the appropriate configuration and `screen` arg
|
||||
* Call the `setup` function once, passing a table of screens as the `screen` arg. This applies the same configuration to all screens in the table
|
||||
_Note_: Multiple screen setup only works for the `simple` and `random` setters
|
||||
|
||||
```lua
|
||||
-- This is a valid wallpaper definition
|
||||
bling.module.wallpaper.setup {
|
||||
wallpaper = { -- a list
|
||||
"black", "#112233", -- colors
|
||||
"wall1.jpg", "wall2.png", -- files
|
||||
"/path/to/wallpapers", -- folders
|
||||
-- cairo patterns
|
||||
"radial:600,50,100:105,550,900:0,#2200ff:0.5,#00ff00:1,#101010",
|
||||
-- or functions that set a wallpaper
|
||||
function(args) bling.module.tiled_wallpaper("\\o/", args.screen) end,
|
||||
bling.module.wallpaper.setters.awesome_wallpaper,
|
||||
},
|
||||
change_timer = 10,
|
||||
}
|
||||
```
|
||||
The provided setters `simple` and `random` will use 2 internal functions that you can use to write your own setter:
|
||||
|
||||
* `bling.module.wallpaper.prepare_list`: return a list of wallpapers directly usable by `apply` (for now, it just explores folders)
|
||||
* `bling.module.wallpaper.apply`: a wrapper for gears.wallpaper functions, using the args table of setup
|
||||
|
||||
Here are the defaults:
|
||||
|
||||
```lua
|
||||
-- Default parameters
|
||||
bling.module.wallpaper.setup {
|
||||
screen = nil, -- the screen to apply the wallpaper, as seen in gears.wallpaper functions
|
||||
screens = nil, -- an array of screens to apply the wallpaper on. If 'screen' is also provided, this is overridden
|
||||
change_timer = nil, -- the timer in seconds. If set, call the set_function every change_timer seconds
|
||||
set_function = nil, -- the setter function
|
||||
|
||||
-- parameters used by bling.module.wallpaper.prepare_list
|
||||
wallpaper = nil, -- the wallpaper object, see simple or simple_schedule documentation
|
||||
image_formats = {"jpg", "jpeg", "png", "bmp"}, -- when searching in folder, consider these files only
|
||||
recursive = true, -- when searching in folder, search also in subfolders
|
||||
|
||||
-- parameters used by bling.module.wallpaper.apply
|
||||
position = nil, -- use a function of gears.wallpaper when applicable ("centered", "fit", "maximized", "tiled")
|
||||
background = beautiful.bg_normal or "black", -- see gears.wallpaper functions
|
||||
ignore_aspect = false, -- see gears.wallpaper.maximized
|
||||
offset = {x = 0, y = 0}, -- see gears.wallpaper functions
|
||||
scale = 1, -- see gears.wallpaper.centered
|
||||
|
||||
-- parameters that only apply to bling.module.wallpaper.setter.awesome (as a setter or as a wallpaper function)
|
||||
colors = { -- see beautiful.theme_assets.wallpaper
|
||||
bg = beautiful.bg_color, -- the actual default is this color but darkened or lightned
|
||||
fg = beautiful.fg_color,
|
||||
alt_fg = beautiful.fg_focus
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Check documentation in [module/wallpaper.lua](module/wallpaper.lua) for more details.
|
|
@ -0,0 +1,240 @@
|
|||
## 🎵 Playerctl <!-- {docsify-ignore} -->
|
||||
|
||||
This is a signal module in which you can connect to certain bling signals to grab playerctl info. Currently, this is what it supports:
|
||||
|
||||
- Song title and artist
|
||||
- Album art (the path this module downloaded the art to)
|
||||
- If playing or not
|
||||
- Position
|
||||
- Song length
|
||||
- If there are no players on
|
||||
|
||||
This module relies on `playerctl` and `curl`. If you have this module disabled, you won't need those programs. With this module, you can create a widget like below without worrying about the backend.
|
||||
|
||||
![](https://user-images.githubusercontent.com/33443763/107377569-fa807900-6a9f-11eb-93c1-174c58eb7bf1.png)
|
||||
|
||||
*screenshot by [javacafe](https://github.com/JavaCafe01)*
|
||||
|
||||
### Usage
|
||||
|
||||
To enable: `playerctl = bling.signal.playerctl.lib/cli()`
|
||||
|
||||
To disable: `playerctl:disable()`
|
||||
|
||||
#### Playerctl_lib Signals
|
||||
|
||||
**Note**: When connecting to signals with the new `playerctl` module, the object itself is always given to you as the first parameter.
|
||||
|
||||
```lua
|
||||
-- metadata
|
||||
-- title (string)
|
||||
-- artist (string)
|
||||
-- album_path (string)
|
||||
-- album (string)
|
||||
-- new (bool)
|
||||
-- player_name (string)
|
||||
-- position
|
||||
-- interval_sec (number)
|
||||
-- length_sec (number)
|
||||
-- player_name (string)
|
||||
-- playback_status
|
||||
-- playing (boolean)
|
||||
-- player_name (string)
|
||||
-- seeked
|
||||
-- position (number)
|
||||
-- player_name (string)
|
||||
-- volume
|
||||
-- volume (number)
|
||||
-- player_name (string)
|
||||
-- loop_status
|
||||
-- loop_status (string)
|
||||
-- player_name (string)
|
||||
-- shuffle
|
||||
-- shuffle (boolean)
|
||||
-- player_name (string)
|
||||
-- exit
|
||||
-- player_name (string)
|
||||
-- no_players
|
||||
-- (No parameters)
|
||||
```
|
||||
|
||||
#### Playerctl_cli Signals
|
||||
|
||||
```lua
|
||||
-- metadata
|
||||
-- title (string)
|
||||
-- artist (string)
|
||||
-- album_path (string)
|
||||
-- album (string)
|
||||
-- player_name (string)
|
||||
-- position
|
||||
-- interval_sec (number)
|
||||
-- length_sec (number)
|
||||
-- playback_status
|
||||
-- playing (boolean)
|
||||
-- volume
|
||||
-- volume (number)
|
||||
-- loop_status
|
||||
-- loop_status (string)
|
||||
-- shuffle
|
||||
-- shuffle (bool)
|
||||
-- no_players
|
||||
-- (No parameters)
|
||||
```
|
||||
|
||||
#### Playerctl Functions
|
||||
|
||||
With this library we also give the user a way to interact with Playerctl, such as playing, pausing, seeking, etc.
|
||||
|
||||
Here are the functions provided:
|
||||
|
||||
```lua
|
||||
-- disable()
|
||||
-- pause(player)
|
||||
-- play(player)
|
||||
-- stop(player)
|
||||
-- play_pause(player)
|
||||
-- previous(player)
|
||||
-- next(player)
|
||||
-- set_loop_status(loop_status, player)
|
||||
-- cycle_loop_status(player)
|
||||
-- set_position(position, player)
|
||||
-- set_shuffle(shuffle, player)
|
||||
-- cycle_shuffle(player)
|
||||
-- set_volume(volume, player)
|
||||
-- get_manager()
|
||||
-- get_active_player()
|
||||
-- get_player_of_name(name)
|
||||
```
|
||||
|
||||
### Example Implementation
|
||||
|
||||
Lets say we have an imagebox. If I wanted to set the imagebox to show the album art, all I have to do is this:
|
||||
|
||||
```lua
|
||||
local art = wibox.widget {
|
||||
image = "default_image.png",
|
||||
resize = true,
|
||||
forced_height = dpi(80),
|
||||
forced_width = dpi(80),
|
||||
widget = wibox.widget.imagebox
|
||||
}
|
||||
|
||||
local name_widget = wibox.widget {
|
||||
markup = 'No players',
|
||||
align = 'center',
|
||||
valign = 'center',
|
||||
widget = wibox.widget.textbox
|
||||
}
|
||||
|
||||
local title_widget = wibox.widget {
|
||||
markup = 'Nothing Playing',
|
||||
align = 'center',
|
||||
valign = 'center',
|
||||
widget = wibox.widget.textbox
|
||||
}
|
||||
|
||||
local artist_widget = wibox.widget {
|
||||
markup = 'Nothing Playing',
|
||||
align = 'center',
|
||||
valign = 'center',
|
||||
widget = wibox.widget.textbox
|
||||
}
|
||||
|
||||
-- Get Song Info
|
||||
local playerctl = bling.signal.playerctl.lib()
|
||||
playerctl:connect_signal("metadata",
|
||||
function(_, title, artist, album_path, album, new, player_name)
|
||||
-- Set art widget
|
||||
art:set_image(gears.surface.load_uncached(album_path))
|
||||
|
||||
-- Set player name, title and artist widgets
|
||||
name_widget:set_markup_silently(player_name)
|
||||
title_widget:set_markup_silently(title)
|
||||
artist_widget:set_markup_silently(artist)
|
||||
end)
|
||||
```
|
||||
|
||||
Thats all! You don't even have to worry about updating the widgets, the signals will handle that for you.
|
||||
|
||||
Here's another example in which you get a notification with the album art, title, and artist whenever the song changes.
|
||||
|
||||
```lua
|
||||
local naughty = require("naughty")
|
||||
local playerctl = bling.signal.playerctl.lib()
|
||||
|
||||
playerctl:connect_signal("metadata",
|
||||
function(_, title, artist, album_path, album, new, player_name)
|
||||
if new == true then
|
||||
naughty.notify({title = title, text = artist, image = album_path})
|
||||
end
|
||||
end)
|
||||
```
|
||||
|
||||
We can also link a playerctl function to a button click!
|
||||
|
||||
```lua
|
||||
local playerctl = bling.signal.playerctl.lib()
|
||||
button:buttons(gears.table.join(
|
||||
awful.button({}, 1, function()
|
||||
playerctl:play_pause()
|
||||
end)
|
||||
))
|
||||
```
|
||||
|
||||
### Theme Variables and Configuration
|
||||
|
||||
By default, this module will output signals from the most recently active player. If you wish to customize the behavior furthur, the following configuration options are available depending on the selected backend. Here is a summary of the two backends and which configuration options they support.
|
||||
|
||||
| Option | playerctl_cli | playerctl_lib |
|
||||
| ------------------- | ------------------ | ------------------ |
|
||||
| ignore | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| player | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| update_on_activity | | :heavy_check_mark: |
|
||||
| interval | :heavy_check_mark: | :heavy_check_mark: |
|
||||
| debounce_delay | :heavy_check_mark: | :heavy_check_mark: |
|
||||
|
||||
- `ignore`: This option is either a string with a single name or a table of strings containing names of players that will be ignored by this module. It is empty by default.
|
||||
|
||||
- `player`: This option is either a string with a single name or a table of strings containing names of players this module will emit signals for. It also acts as a way to prioritize certain players over others with players listed earlier in the table being preferred over players listed later. The special name `%any` can be used once to match any player not found in the list. It is empty by default.
|
||||
|
||||
- `update_on_activity`: This option is a boolean that, when true, will cause the module to output signals from the most recently active player while still adhering to the player priority specified with the `player` option. If `false`, the module will output signals from the player that started first, again, while still adhering to the player priority. It is `true` by default.
|
||||
|
||||
- `interval`: This option is a number specifying the update interval for fetching the player position. It is 1 by default.
|
||||
|
||||
- `debounce_delay`: This option is a number specifying the debounce timer interval. If a new metadata signal gets emitted before debounce_delay has passed, the last signal will be dropped.
|
||||
This is to help with some players sending multiple signals. It is `0.35` by default.
|
||||
|
||||
These options can be set through a call to `bling.signal.playerctl.lib/cli()` or these theme variables:
|
||||
|
||||
```lua
|
||||
theme.playerctl_ignore = {}
|
||||
theme.playerctl_player = {}
|
||||
theme.playerctl_update_on_activity = true
|
||||
theme.playerctl_position_update_interval = 1
|
||||
```
|
||||
|
||||
#### Example Configurations
|
||||
|
||||
```lua
|
||||
-- Prioritize ncspot over all other players and ignore firefox players (e.g. YouTube and Twitch tabs) completely
|
||||
playerctl = bling.signal.playerctl.lib {
|
||||
ignore = "firefox",
|
||||
player = {"ncspot", "%any"}
|
||||
}
|
||||
|
||||
-- OR in your theme file:
|
||||
-- Same config as above but with theme variables
|
||||
theme.playerctl_ignore = "firefox"
|
||||
theme.playerctl_player = {"ncspot", "%any"}
|
||||
|
||||
-- Prioritize vlc over all other players and deprioritize spotify
|
||||
theme.playerctl_backend = "playerctl_lib"
|
||||
theme.playerctl_player = {"vlc", "%any", "spotify"}
|
||||
|
||||
-- Disable priority of most recently active players
|
||||
theme.playerctl_update_on_activity = false
|
||||
|
||||
-- Only emit the position signal every 2 seconds
|
||||
theme.playerctl_position_update_interval = 2
|
||||
```
|
|
@ -0,0 +1,117 @@
|
|||
```lua
|
||||
--[[ Bling theme variables template
|
||||
This file has all theme variables of the bling module.
|
||||
Every variable has a small comment on what it does.
|
||||
You might just want to copy that whole part into your theme.lua and start adjusting from there.
|
||||
--]]
|
||||
|
||||
|
||||
-- window swallowing
|
||||
theme.dont_swallow_classname_list = {"firefox", "Gimp"} -- list of class names that should not be swallowed
|
||||
theme.dont_swallow_filter_activated = true -- whether the filter above should be active
|
||||
|
||||
-- flash focus
|
||||
theme.flash_focus_start_opacity = 0.6 -- the starting opacity
|
||||
theme.flash_focus_step = 0.01 -- the step of animation
|
||||
|
||||
-- playerctl signal
|
||||
theme.playerctl_backend = "playerctl_cli" -- backend to use
|
||||
theme.playerctl_ignore = {} -- list of players to be ignored
|
||||
theme.playerctl_player = {} -- list of players to be used in priority order
|
||||
theme.playerctl_update_on_activity = true -- whether to prioritize the most recently active players or not
|
||||
theme.playerctl_position_update_interval = 1 -- the update interval for fetching the position from playerctl
|
||||
|
||||
-- tabbed
|
||||
theme.tabbed_spawn_in_tab = false -- whether a new client should spawn into the focused tabbing container
|
||||
|
||||
-- tabbar general
|
||||
theme.tabbar_ontop = false
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background color of the focused client on the tabbar
|
||||
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
|
||||
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
|
||||
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
|
||||
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
|
||||
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
|
||||
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
|
||||
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
|
||||
theme.tabbar_disable = false -- disable the tab bar entirely
|
||||
|
||||
-- mstab
|
||||
theme.mstab_bar_disable = false -- disable the tabbar
|
||||
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
|
||||
theme.mstab_dont_resize_slaves = false -- whether the tabbed stack windows should be smaller than the
|
||||
-- currently focused stack window (set it to true if you use
|
||||
-- transparent terminals. False if you use shadows on solid ones
|
||||
theme.mstab_bar_padding = "default" -- how much padding there should be between clients and your tabbar
|
||||
-- by default it will adjust based on your useless gaps.
|
||||
-- If you want a custom value. Set it to the number of pixels (int)
|
||||
theme.mstab_border_radius = 0 -- border radius of the tabbar
|
||||
theme.mstab_bar_height = 40 -- height of the tabbar
|
||||
theme.mstab_tabbar_position = "top" -- position of the tabbar (mstab currently does not support left,right)
|
||||
theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
-- defaults to the tabbar_style so only change if you want a
|
||||
-- different style for mstab and tabbed
|
||||
|
||||
-- the following variables are currently only for the "modern" tabbar style
|
||||
theme.tabbar_color_close = "#f9929b" -- chnges the color of the close button
|
||||
theme.tabbar_color_min = "#fbdf90" -- chnges the color of the minimize button
|
||||
theme.tabbar_color_float = "#ccaced" -- chnges the color of the float button
|
||||
|
||||
-- tag preview widget
|
||||
theme.tag_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.tag_preview_client_border_radius = 0 -- Border radius of each client in the widget (With AA)
|
||||
theme.tag_preview_client_opacity = 0.5 -- Opacity of each client
|
||||
theme.tag_preview_client_bg = "#000000" -- The bg color of each client
|
||||
theme.tag_preview_client_border_color = "#ffffff" -- The border color of each client
|
||||
theme.tag_preview_client_border_width = 3 -- The border width of each client
|
||||
theme.tag_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.tag_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.tag_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.tag_preview_widget_margin = 0 -- The margin of the widget
|
||||
|
||||
-- task preview widget
|
||||
theme.task_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.task_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.task_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.task_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.task_preview_widget_margin = 0 -- The margin of the widget
|
||||
|
||||
-- tabbed misc widget(s)
|
||||
theme.bling_tabbed_misc_titlebar_indicator = {
|
||||
layout_spacing = dpi(4),
|
||||
icon_size = dpi(20),
|
||||
icon_margin = dpi(4),
|
||||
bg_color_focus = "#ff0000",
|
||||
bg_color = "#00000000",
|
||||
icon_shape = function(cr, w, h)
|
||||
gears.shape.rounded_rect(cr, w, h, 0)
|
||||
end,
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
}
|
||||
|
||||
-- window switcher widget
|
||||
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
|
||||
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
|
||||
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.window_switcher_clients_spacing = 20 -- The space between each client item
|
||||
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
|
||||
theme.window_switcher_client_width = 150 -- The width of one client widget
|
||||
theme.window_switcher_client_height = 250 -- The height of one client widget
|
||||
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
|
||||
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
|
||||
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
|
||||
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
|
||||
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
|
||||
theme.window_switcher_name_forced_width = 200 -- The width of one title
|
||||
theme.window_switcher_name_font = "sans 11" -- The font of all titles
|
||||
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
|
||||
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
|
||||
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
|
||||
theme.window_switcher_icon_width = 40 -- The width of one icon
|
||||
```
|
|
@ -0,0 +1,117 @@
|
|||
## 🧱 Tabbed Miscellaneous <!-- {docsify-ignore} -->
|
||||
|
||||
This comprises a few widgets to better represent tabbed groups (from the tabbed module) in your desktop.
|
||||
The widgets currently included are:
|
||||
- Titlebar Indicator
|
||||
- Tasklist
|
||||
|
||||
![Preview Image](https://i.imgur.com/ZeYSrxY.png)
|
||||
|
||||
## Titlebar Indicator
|
||||
|
||||
### Usage
|
||||
|
||||
To use the task list indicator:
|
||||
**NOTE:** Options can be set as theme vars under the table `theme.bling_tabbed_misc_titlebar_indicator`
|
||||
|
||||
```lua
|
||||
bling.widget.tabbed_misc.titlebar_indicator(client, {
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
layout_spacing = dpi(5), -- Set spacing in between items
|
||||
icon_size = dpi(24), -- Set icon size
|
||||
icon_margin = 0, -- Set icon margin
|
||||
fg_color = "#cccccc", -- Normal color for text
|
||||
fg_color_focus = "#ffffff", -- Color for focused text
|
||||
bg_color_focus = "#282828", -- Color for the focused items
|
||||
bg_color = "#1d2021", -- Color for normal / unfocused items
|
||||
icon_shape = gears.shape.circle -- Set icon shape,
|
||||
})
|
||||
```
|
||||
|
||||
a widget_template option is also available:
|
||||
```lua
|
||||
bling.widget.tabbed_misc.titlebar_indicator(client, {
|
||||
widget_template = {
|
||||
{
|
||||
widget = awful.widget.clienticon,
|
||||
id = 'icon_role'
|
||||
},
|
||||
widget = wibox.container.margin,
|
||||
margins = 2,
|
||||
id = 'bg_role',
|
||||
update_callback = function(self, client, group)
|
||||
if client == group.clients[group.focused_idx] then
|
||||
self.margins = 5
|
||||
end
|
||||
end
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Example Implementation
|
||||
|
||||
You normally embed the widget in your titlebar...
|
||||
```lua
|
||||
awful.titlebar(c).widget = {
|
||||
{ -- Left
|
||||
bling.widget.tabbed_misc.titlebar_indicator(c),
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
},
|
||||
{ -- Middle
|
||||
{ -- Title
|
||||
align = "center",
|
||||
widget = awful.titlebar.widget.titlewidget(c)
|
||||
},
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.flex.horizontal
|
||||
},
|
||||
{ -- Right
|
||||
awful.titlebar.widget.maximizedbutton(c),
|
||||
awful.titlebar.widget.closebutton (c),
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
},
|
||||
layout = wibox.layout.align.horizontal
|
||||
}
|
||||
```
|
||||
|
||||
## Tasklist
|
||||
The module exports a function that can be added to your tasklist as a `update_callback`
|
||||
|
||||
### Usage
|
||||
```lua
|
||||
awful.widget.tasklist({
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
layout = {
|
||||
spacing = dpi(10),
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
style = {
|
||||
bg_normal = "#00000000",
|
||||
},
|
||||
widget_template = {
|
||||
{
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
id = "icon_role",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
},
|
||||
width = dpi(24),
|
||||
height = dpi(24),
|
||||
widget = wibox.container.constraint,
|
||||
},
|
||||
widget = wibox.container.background, -- IT MUST BE A CONTAINER WIDGET AS THAT IS WHAT THE FUNCTION EXPECTS
|
||||
update_callback = require("bling.widget.tabbed_misc").custom_tasklist,
|
||||
id = "background_role",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
If you need to do something else, it can be used like so
|
||||
```lua
|
||||
update_callback = function(self, client, index, clients)
|
||||
require("bling.widget.tabbed_misc").custom_tasklist(self, client, index, clients)
|
||||
require("naughty").notify({ text = "Tasklist was updated" })
|
||||
end
|
||||
```
|
|
@ -0,0 +1,155 @@
|
|||
## 🔍 Tag Preview <!-- {docsify-ignore} -->
|
||||
|
||||
This is a popup widget that will show a preview of a specified tag that illustrates the position, size, content, and icon of all clients.
|
||||
|
||||
![](https://imgur.com/zFdvs4K.gif)
|
||||
|
||||
*gif by [javacafe](https://github.com/JavaCafe01)*
|
||||
|
||||
### Usage
|
||||
|
||||
To enable:
|
||||
|
||||
```lua
|
||||
bling.widget.tag_preview.enable {
|
||||
show_client_content = false, -- Whether or not to show the client content
|
||||
x = 10, -- The x-coord of the popup
|
||||
y = 10, -- The y-coord of the popup
|
||||
scale = 0.25, -- The scale of the previews compared to the screen
|
||||
honor_padding = false, -- Honor padding when creating widget size
|
||||
honor_workarea = false, -- Honor work area when creating widget size
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
awful.placement.top_left(c, {
|
||||
margins = {
|
||||
top = 30,
|
||||
left = 30
|
||||
}
|
||||
})
|
||||
end,
|
||||
background_widget = wibox.widget { -- Set a background image (like a wallpaper) for the widget
|
||||
image = beautiful.wallpaper,
|
||||
horizontal_fit_policy = "fit",
|
||||
vertical_fit_policy = "fit",
|
||||
widget = wibox.widget.imagebox
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here are the signals available:
|
||||
|
||||
```lua
|
||||
-- bling::tag_preview::update -- first line is the signal
|
||||
-- t (tag) -- indented lines are function parameters
|
||||
-- bling::tag_preview::visibility
|
||||
-- s (screen)
|
||||
-- v (boolean)
|
||||
```
|
||||
|
||||
By default, the widget is not visible. You must implement when it will update and when it will show.
|
||||
|
||||
### Example Implementation
|
||||
|
||||
We can trigger the widget to show the specific tag when hovering over it in the taglist. The code shown below is the example taglist from the [AwesomeWM docs](https://awesomewm.org/doc/api/classes/awful.widget.taglist.html). Basically, we are going to update the widget and toggle it through the taglist's `create_callback`. (The bling addons are commented)
|
||||
```lua
|
||||
s.mytaglist = awful.widget.taglist {
|
||||
screen = s,
|
||||
filter = awful.widget.taglist.filter.all,
|
||||
style = {
|
||||
shape = gears.shape.powerline
|
||||
},
|
||||
layout = {
|
||||
spacing = -12,
|
||||
spacing_widget = {
|
||||
color = '#dddddd',
|
||||
shape = gears.shape.powerline,
|
||||
widget = wibox.widget.separator,
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
},
|
||||
widget_template = {
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
id = 'index_role',
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
margins = 4,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
bg = '#dddddd',
|
||||
shape = gears.shape.circle,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
{
|
||||
{
|
||||
id = 'icon_role',
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
margins = 2,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
{
|
||||
id = 'text_role',
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
left = 18,
|
||||
right = 18,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
id = 'background_role',
|
||||
widget = wibox.container.background,
|
||||
-- Add support for hover colors and an index label
|
||||
create_callback = function(self, c3, index, objects) --luacheck: no unused args
|
||||
self:get_children_by_id('index_role')[1].markup = '<b> '..index..' </b>'
|
||||
self:connect_signal('mouse::enter', function()
|
||||
|
||||
-- BLING: Only show widget when there are clients in the tag
|
||||
if #c3:clients() > 0 then
|
||||
-- BLING: Update the widget with the new tag
|
||||
awesome.emit_signal("bling::tag_preview::update", c3)
|
||||
-- BLING: Show the widget
|
||||
awesome.emit_signal("bling::tag_preview::visibility", s, true)
|
||||
end
|
||||
|
||||
if self.bg ~= '#ff0000' then
|
||||
self.backup = self.bg
|
||||
self.has_backup = true
|
||||
end
|
||||
self.bg = '#ff0000'
|
||||
end)
|
||||
self:connect_signal('mouse::leave', function()
|
||||
|
||||
-- BLING: Turn the widget off
|
||||
awesome.emit_signal("bling::tag_preview::visibility", s, false)
|
||||
|
||||
if self.has_backup then self.bg = self.backup end
|
||||
end)
|
||||
end,
|
||||
update_callback = function(self, c3, index, objects) --luacheck: no unused args
|
||||
self:get_children_by_id('index_role')[1].markup = '<b> '..index..' </b>'
|
||||
end,
|
||||
},
|
||||
buttons = taglist_buttons
|
||||
}
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
|
||||
```lua
|
||||
theme.tag_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.tag_preview_client_border_radius = 0 -- Border radius of each client in the widget (With AA)
|
||||
theme.tag_preview_client_opacity = 0.5 -- Opacity of each client
|
||||
theme.tag_preview_client_bg = "#000000" -- The bg color of each client
|
||||
theme.tag_preview_client_border_color = "#ffffff" -- The border color of each client
|
||||
theme.tag_preview_client_border_width = 3 -- The border width of each client
|
||||
theme.tag_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.tag_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.tag_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.tag_preview_widget_margin = 0 -- The margin of the widget
|
||||
```
|
||||
|
||||
NOTE: I recommend to only use the widget border radius theme variable when not using shadows with a compositor, as anti-aliased rounding with the outer widgets made with AwesomeWM rely on the actual bg being transparent. If you want rounding with shadows on the widget, use a compositor like [jonaburg's fork](https://github.com/jonaburg/picom).
|
|
@ -0,0 +1,152 @@
|
|||
## 🔍 Task Preview <!-- {docsify-ignore} -->
|
||||
|
||||
This is a popup widget that will show a preview of the specified client. It is supposed to mimic the small popup that Windows has when hovering over the application icon.
|
||||
|
||||
![](https://user-images.githubusercontent.com/33443763/124705653-d7b98b80-deaa-11eb-8091-42bbe62365be.png)
|
||||
|
||||
*image by [javacafe](https://github.com/JavaCafe01)*
|
||||
|
||||
### Usage
|
||||
|
||||
To enable:
|
||||
|
||||
```lua
|
||||
bling.widget.task_preview.enable {
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
awful.placement.bottom(c, {
|
||||
margins = {
|
||||
bottom = 30
|
||||
}
|
||||
})
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
To allow for more customization, there is also a `widget_structure` property (as seen in some default awesome widgets) which is optional. An example is as follows -
|
||||
```lua
|
||||
bling.widget.task_preview.enable {
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
awful.placement.bottom(c, {
|
||||
margins = {
|
||||
bottom = 30
|
||||
}
|
||||
})
|
||||
end,
|
||||
-- Your widget will automatically conform to the given size due to a constraint container.
|
||||
widget_structure = {
|
||||
{
|
||||
{
|
||||
{
|
||||
id = 'icon_role',
|
||||
widget = awful.widget.clienticon, -- The client icon
|
||||
},
|
||||
{
|
||||
id = 'name_role', -- The client name / title
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
layout = wibox.layout.flex.horizontal
|
||||
},
|
||||
widget = wibox.container.margin,
|
||||
margins = 5
|
||||
},
|
||||
{
|
||||
id = 'image_role', -- The client preview
|
||||
resize = true,
|
||||
valign = 'center',
|
||||
halign = 'center',
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
layout = wibox.layout.fixed.vertical
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here are the signals available:
|
||||
|
||||
```lua
|
||||
-- bling::task_preview::visibility -- first line is the signal
|
||||
-- s (screen) -- indented lines are function parameters
|
||||
-- v (boolean)
|
||||
-- c (client)
|
||||
```
|
||||
|
||||
By default, the widget is not visible. You must implement when it will update and when it will show.
|
||||
|
||||
### Example Implementation
|
||||
|
||||
We can trigger the widget to show the specific client when hovering over it in the tasklist. The code shown below is the example icon only tasklist from the [AwesomeWM docs](https://awesomewm.org/doc/api/classes/awful.widget.tasklist.html). Basically, we are going to toggle the widget through the tasklist's `create_callback`. (The bling addons are commented)
|
||||
```lua
|
||||
s.mytasklist = awful.widget.tasklist {
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
buttons = tasklist_buttons,
|
||||
layout = {
|
||||
spacing_widget = {
|
||||
{
|
||||
forced_width = 5,
|
||||
forced_height = 24,
|
||||
thickness = 1,
|
||||
color = '#777777',
|
||||
widget = wibox.widget.separator
|
||||
},
|
||||
valign = 'center',
|
||||
halign = 'center',
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
spacing = 1,
|
||||
layout = wibox.layout.fixed.horizontal
|
||||
},
|
||||
-- Notice that there is *NO* wibox.wibox prefix, it is a template,
|
||||
-- not a widget instance.
|
||||
widget_template = {
|
||||
{
|
||||
wibox.widget.base.make_widget(),
|
||||
forced_height = 5,
|
||||
id = 'background_role',
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
{
|
||||
{
|
||||
id = 'clienticon',
|
||||
widget = awful.widget.clienticon,
|
||||
},
|
||||
margins = 5,
|
||||
widget = wibox.container.margin
|
||||
},
|
||||
nil,
|
||||
create_callback = function(self, c, index, objects) --luacheck: no unused args
|
||||
self:get_children_by_id('clienticon')[1].client = c
|
||||
|
||||
-- BLING: Toggle the popup on hover and disable it off hover
|
||||
self:connect_signal('mouse::enter', function()
|
||||
awesome.emit_signal("bling::task_preview::visibility", s,
|
||||
true, c)
|
||||
end)
|
||||
self:connect_signal('mouse::leave', function()
|
||||
awesome.emit_signal("bling::task_preview::visibility", s,
|
||||
false, c)
|
||||
end)
|
||||
end,
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.task_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.task_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.task_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.task_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.task_preview_widget_margin = 0 -- The margin of the widget
|
||||
```
|
||||
|
||||
NOTE: I recommend to only use the widget border radius theme variable when not using shadows with a compositor, as anti-aliased rounding with the outer widgets made with AwesomeWM rely on the actual bg being transparent. If you want rounding with shadows on the widget, use a compositor like [jonaburg's fork](https://github.com/jonaburg/picom).
|
|
@ -0,0 +1,67 @@
|
|||
## 🎨 Window Switcher <!-- {docsify-ignore} -->
|
||||
|
||||
A popup with client previews that allows you to switch clients similar to the alt-tab menu in MacOS, GNOME, and Windows.
|
||||
|
||||
![](https://user-images.githubusercontent.com/70270606/133311802-8aef1012-346f-4f4c-843d-10d9de54ffeb.png)
|
||||
|
||||
*image by [No37](https://github.com/Nooo37)*
|
||||
|
||||
### Usage
|
||||
|
||||
To enable:
|
||||
|
||||
```lua
|
||||
bling.widget.window_switcher.enable {
|
||||
type = "thumbnail", -- set to anything other than "thumbnail" to disable client previews
|
||||
|
||||
-- keybindings (the examples provided are also the default if kept unset)
|
||||
hide_window_switcher_key = "Escape", -- The key on which to close the popup
|
||||
minimize_key = "n", -- The key on which to minimize the selected client
|
||||
unminimize_key = "N", -- The key on which to unminimize all clients
|
||||
kill_client_key = "q", -- The key on which to close the selected client
|
||||
cycle_key = "Tab", -- The key on which to cycle through all clients
|
||||
previous_key = "Left", -- The key on which to select the previous client
|
||||
next_key = "Right", -- The key on which to select the next client
|
||||
vim_previous_key = "h", -- Alternative key on which to select the previous client
|
||||
vim_next_key = "l", -- Alternative key on which to select the next client
|
||||
|
||||
cycleClientsByIdx = awful.client.focus.byidx, -- The function to cycle the clients
|
||||
filterClients = awful.widget.tasklist.filter.currenttags, -- The function to filter the viewed clients
|
||||
}
|
||||
```
|
||||
|
||||
To run the window swicher you have to emit this signal from within your configuration (usually using a keybind).
|
||||
|
||||
```lua
|
||||
awesome.emit_signal("bling::window_switcher::turn_on")
|
||||
```
|
||||
|
||||
For example:
|
||||
```lua
|
||||
awful.key({Mod1}, "Tab", function()
|
||||
awesome.emit_signal("bling::window_switcher::turn_on")
|
||||
end, {description = "Window Switcher", group = "bling"})
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
|
||||
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
|
||||
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.window_switcher_clients_spacing = 20 -- The space between each client item
|
||||
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
|
||||
theme.window_switcher_client_width = 150 -- The width of one client widget
|
||||
theme.window_switcher_client_height = 250 -- The height of one client widget
|
||||
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
|
||||
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
|
||||
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
|
||||
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
|
||||
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
|
||||
theme.window_switcher_name_forced_width = 200 -- The width of one title
|
||||
theme.window_switcher_name_font = "sans 11" -- The font of all titles
|
||||
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
|
||||
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
|
||||
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
|
||||
theme.window_switcher_icon_width = 40 -- The width of one icon
|
||||
```
|
0
config/awesome/module/bling/helpers/client.lua → config/awesome/modules/bling/helpers/client.lua
Normal file → Executable file
0
config/awesome/module/bling/helpers/color.lua → config/awesome/modules/bling/helpers/color.lua
Normal file → Executable file
0
config/awesome/module/bling/helpers/filesystem.lua → config/awesome/modules/bling/helpers/filesystem.lua
Normal file → Executable file
|
@ -0,0 +1,142 @@
|
|||
local lgi = require("lgi")
|
||||
local Gio = lgi.Gio
|
||||
local Gtk = lgi.require("Gtk", "3.0")
|
||||
local gobject = require("gears.object")
|
||||
local gtable = require("gears.table")
|
||||
local setmetatable = setmetatable
|
||||
local ipairs = ipairs
|
||||
|
||||
local icon_theme = { mt = {} }
|
||||
|
||||
local name_lookup =
|
||||
{
|
||||
["jetbrains-studio"] = "android-studio"
|
||||
}
|
||||
|
||||
local function get_icon_by_pid_command(self, client, apps)
|
||||
local pid = client.pid
|
||||
if pid ~= nil then
|
||||
local handle = io.popen(string.format("ps -p %d -o comm=", pid))
|
||||
local pid_command = handle:read("*a"):gsub("^%s*(.-)%s*$", "%1")
|
||||
handle:close()
|
||||
|
||||
for _, app in ipairs(apps) do
|
||||
local executable = app:get_executable()
|
||||
if executable and executable:find(pid_command, 1, true) then
|
||||
return self:get_gicon_path(app:get_icon())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_icon_by_icon_name(self, client, apps)
|
||||
local icon_name = client.icon_name and client.icon_name:lower() or nil
|
||||
if icon_name ~= nil then
|
||||
for _, app in ipairs(apps) do
|
||||
local name = app:get_name():lower()
|
||||
if name and name:find(icon_name, 1, true) then
|
||||
return self:get_gicon_path(app:get_icon())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function get_icon_by_class(self, client, apps)
|
||||
if client.class ~= nil then
|
||||
local class = name_lookup[client.class] or client.class:lower()
|
||||
|
||||
-- Try to remove dashes
|
||||
local class_1 = class:gsub("[%-]", "")
|
||||
|
||||
-- Try to replace dashes with dot
|
||||
local class_2 = class:gsub("[%-]", ".")
|
||||
|
||||
-- Try to match only the first word
|
||||
local class_3 = class:match("(.-)-") or class
|
||||
class_3 = class_3:match("(.-)%.") or class_3
|
||||
class_3 = class_3:match("(.-)%s+") or class_3
|
||||
|
||||
local possible_icon_names = { class, class_3, class_2, class_1 }
|
||||
for _, app in ipairs(apps) do
|
||||
local id = app:get_id():lower()
|
||||
for _, possible_icon_name in ipairs(possible_icon_names) do
|
||||
if id and id:find(possible_icon_name, 1, true) then
|
||||
return self:get_gicon_path(app:get_icon())
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function icon_theme:get_client_icon_path(client)
|
||||
local apps = Gio.AppInfo.get_all()
|
||||
|
||||
return get_icon_by_pid_command(self, client, apps) or
|
||||
get_icon_by_icon_name(self, client, apps) or
|
||||
get_icon_by_class(self, client, apps) or
|
||||
client.icon or
|
||||
self:choose_icon({"window", "window-manager", "xfwm4-default", "window_list" })
|
||||
end
|
||||
|
||||
function icon_theme:choose_icon(icons_names)
|
||||
local icon_info = self.gtk_theme:choose_icon(icons_names, self.icon_size, 0);
|
||||
if icon_info then
|
||||
local icon_path = icon_info:get_filename()
|
||||
if icon_path then
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
function icon_theme:get_gicon_path(gicon)
|
||||
if gicon == nil then
|
||||
return ""
|
||||
end
|
||||
|
||||
local icon_info = self.gtk_theme:lookup_by_gicon(gicon, self.icon_size, 0);
|
||||
if icon_info then
|
||||
local icon_path = icon_info:get_filename()
|
||||
if icon_path then
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
function icon_theme:get_icon_path(icon_name)
|
||||
local icon_info = self.gtk_theme:lookup_icon(icon_name, self.icon_size, 0)
|
||||
if icon_info then
|
||||
local icon_path = icon_info:get_filename()
|
||||
if icon_path then
|
||||
return icon_path
|
||||
end
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
local function new(theme_name, icon_size)
|
||||
local ret = gobject{}
|
||||
gtable.crush(ret, icon_theme, true)
|
||||
|
||||
ret.name = theme_name or nil
|
||||
ret.icon_size = icon_size or 48
|
||||
|
||||
if theme_name then
|
||||
ret.gtk_theme = Gtk.IconTheme.new()
|
||||
Gtk.IconTheme.set_custom_theme(ret.gtk_theme, theme_name);
|
||||
else
|
||||
ret.gtk_theme = Gtk.IconTheme.get_default()
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function icon_theme.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(icon_theme, icon_theme.mt)
|
0
config/awesome/module/bling/helpers/init.lua → config/awesome/modules/bling/helpers/init.lua
Normal file → Executable file
0
config/awesome/module/bling/helpers/shape.lua → config/awesome/modules/bling/helpers/shape.lua
Normal file → Executable file
0
config/awesome/module/bling/helpers/time.lua → config/awesome/modules/bling/helpers/time.lua
Normal file → Executable file
0
config/awesome/module/bling/icons/layouts/centered.png → config/awesome/modules/bling/icons/layouts/centered.png
Normal file → Executable file
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
0
config/awesome/module/bling/icons/layouts/deck.png → config/awesome/modules/bling/icons/layouts/deck.png
Normal file → Executable file
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |