diff --git a/alacritty/alacritty.yml b/alacritty/alacritty.yml index 4f134ea..d872054 100644 --- a/alacritty/alacritty.yml +++ b/alacritty/alacritty.yml @@ -97,7 +97,7 @@ font: # - (macOS) Menlo # - (Linux/BSD) monospace # - (Windows) Consolas - family: MesloLGS NF + family: VictorMono Nerd Font # The `style` can be specified to pick a specific face. style: Regular @@ -108,7 +108,7 @@ font: # # If the bold family is not specified, it will fall back to the # value specified for the normal font. - family: MesloLGS NF + family: VictorMono Nerd Font # The `style` can be specified to pick a specific face. style: Bold @@ -119,7 +119,7 @@ font: # # If the italic family is not specified, it will fall back to the # value specified for the normal font. - family: MesloLGS NF + family: VictorMono Nerd Font # The `style` can be specified to pick a specific face. style: Italic @@ -315,7 +315,7 @@ colors: # # Window opacity as a floating point number from `0.0` to `1.0`. # The value `0.0` is completely transparent and `1.0` is opaque. -background_opacity: 0.45 +background_opacity: 0.60 #selection: #semantic_escape_chars: ",│`|:\"' ()[]{}<>\t" diff --git a/awesome/awesome-wm-widgets b/awesome/awesome-wm-widgets new file mode 160000 index 0000000..4204fa8 --- /dev/null +++ b/awesome/awesome-wm-widgets @@ -0,0 +1 @@ +Subproject commit 4204fa824181a90c09c4306481a7fa2538bcce52 diff --git a/awesome/binaries/profile-image b/awesome/binaries/profile-image new file mode 100755 index 0000000..350c9ea --- /dev/null +++ b/awesome/binaries/profile-image @@ -0,0 +1,35 @@ +#!/usr/bin/env bash + +# Depends: Mugshot +# Written by manilarome + +awesome_dir="${HOME}/.config/awesome/" +user_profile_dir="${awesome_dir}/configuration/user-profile/" + +accountsservice_user_icons="/var/lib/AccountsService/icons/${USER}" + +# Check if user image exists +if [ -f "${user_profile_dir}${USER}.png" ]; +then + if [ -f "${accountsservice_user_icons}" ]; + then + if ! cmp --silent "${user_profile_dir}${USER}.png" "${accountsservice_user_icons}"; + then + cp "${accountsservice_user_icons}" "${user_profile_dir}${USER}.png" + fi + printf "${user_profile_dir}${USER}.png" + else + printf "${user_profile_dir}${USER}.png" + fi + exit; +else + if [ -f "${accountsservice_user_icons}" ]; + then + cp "${accountsservice_user_icons}" "${user_profile_dir}${USER}.png" + printf "${user_profile_dir}${USER}.png" + exit; + else + printf "default" + exit; + fi +fi \ No newline at end of file diff --git a/awesome/binaries/snap b/awesome/binaries/snap new file mode 100755 index 0000000..970cee2 --- /dev/null +++ b/awesome/binaries/snap @@ -0,0 +1,120 @@ +#!/usr/bin/env bash + +# ---------------------------------------------------------------------------- +# --- Simple screenshot script using maim and AwesomeWM API +# -- +# -- Accepts `area` and `full` string args +# -- +# -- For more details check `man maim` +# -- +# -- @author manilarome <gerome.matilla07@gmail.com> +# -- @copyright 2020 manilarome +# -- @script snap +# ---------------------------------------------------------------------------- + +screenshot_dir=$(xdg-user-dir PICTURES)/Screenshots/ + +# Check save directory +# Create it if it doesn't exist +function check_dir() { + if [ ! -d "$screenshot_dir" ]; + then + mkdir -p "$screenshot_dir" + fi +} + +# Main function +function shot() { + + check_dir + + file_loc="${screenshot_dir}$(date +%Y%m%d_%H%M%S).png" + + maim_command="$1" + notif_message="$2" + + # Execute maim command + ${maim_command} "${file_loc}" + + # Exit if the user cancels the screenshot + # So it means there's no new screenshot image file + if [ ! -f "${file_loc}" ]; + then + exit; + fi + + # Copy to clipboard + xclip -selection clipboard -t image/png -i "${screenshot_dir}"/`ls -1 -t "${screenshot_dir}" | head -1` & + + awesome-client " + + -- IMPORTANT NOTE: THIS PART OF THE SCRIPT IS LUA! + naughty = require('naughty') + awful = require('awful') + beautiful = require('beautiful') + dpi = beautiful.xresources.apply_dpi + + local open_image = naughty.action { + name = 'Open', + icon_only = false, + } + + local open_folder = naughty.action { + name = 'Open Folder', + icon_only = false, + } + + local delete_image = naughty.action { + name = 'Delete', + icon_only = false, + } + + -- Execute the callback when 'Open' is pressed + open_image:connect_signal('invoked', function() + awful.spawn('xdg-open ' .. '${file_loc}', false) + end) + + open_folder:connect_signal('invoked', function() + awful.spawn('xdg-open ' .. '${screenshot_dir}', false) + end) + + -- Execute the callback when 'Delete' is pressed + delete_image:connect_signal('invoked', function() + awful.spawn('gio trash ' .. '${file_loc}', false) + end) + + -- Show notification + naughty.notification ({ + app_name = 'Screenshot Tool', + icon = '${file_loc}', + timeout = 10, + title = 'Snap!', + message = '${notif_message}', + actions = { open_image, open_folder, delete_image } + }) + " + +} + +# Check the args passed +if [ -z "$1" ] || ([ "$1" != 'full' ] && [ "$1" != 'area' ]); +then + echo " + Requires an argument: + area - Area screenshot + full - Fullscreen screenshot + + Example: + ./snap area + ./snap full + " +elif [ "$1" = 'full' ]; +then + msg="Full screenshot saved and copied to clipboard!" + shot 'maim -u -m 1' "${msg}" +elif [ "$1" = 'area' ]; +then + msg='Area screenshot saved and copied to clipboard!' + shot 'maim -u -s -n -m 1' "${msg}" +fi + diff --git a/awesome/configuration/apps.lua b/awesome/configuration/apps.lua new file mode 100644 index 0000000..9f62e86 --- /dev/null +++ b/awesome/configuration/apps.lua @@ -0,0 +1,67 @@ +local filesystem = require('gears.filesystem') + +local config_dir = filesystem.get_configuration_dir() +local bin_dir = config_dir .. 'binaries/' + +return { + + -- The default applications that we will use in keybindings and widgets + default = { + terminal = 'kitty', -- Terminal Emulator + text_editor = 'subl3', -- GUI Text Editor + web_browser = 'firefox', -- Web browser + file_manager = 'dolphin', -- GUI File manager + network_manager = 'nm-connection-editor', -- Network manager + bluetooth_manager = 'blueman-manager', -- Bluetooth manager + power_manager = 'xfce4-power-manager', -- Power manager + package_manager = 'pamac-manager', -- GUI Package manager + lock = 'awesome-client "awesome.emit_signal(\'module::lockscreen_show\')"', -- Lockscreen + quake = 'kitty --name QuakeTerminal', -- Quake-like Terminal + + rofiglobal = 'rofi -dpi ' .. screen.primary.dpi .. + ' -show "Global Search" -modi "Global Search":' .. config_dir .. + '/configuration/rofi/sidebar/rofi-spotlight.sh' .. + ' -theme ' .. config_dir .. + '/configuration/rofi/sidebar/rofi.rasi', -- Rofi Web Search + + + rofiappmenu = 'rofi -dpi ' .. screen.primary.dpi .. + ' -show drun -theme ' .. config_dir .. + '/configuration/rofi/appmenu/rofi.rasi' -- Application Menu + + -- You can add more default applications here + }, + + -- List of apps to start once on start-up + -- auto-start.lua module will start these + + run_on_start_up = { + + 'picom -b --experimental-backends --dbus --config ' .. + config_dir .. '/configuration/picom.conf', -- Compositor + + 'blueman-applet', -- Bluetooth tray icon + 'mpd', -- Music Server + 'xfce4-power-manager', -- Power manager + '/usr/lib/polkit-kde-authentication-agent-1 &' .. + ' eval $(gnome-keyring-daemon -s --components=pkcs11,secrets,ssh,gpg)', -- Credential manager + + 'xrdb $HOME/.Xresources', -- Load X Colors + 'nm-applet', -- NetworkManager Applet + 'pulseeffects --gapplication-service', -- Sound Equalizer + [[ + xidlehook --not-when-fullscreen --not-when-audio --timer 600 \ + "awesome-client 'awesome.emit_signal(\"module::lockscreen_show\")'" "" + ]] -- Auto lock timer + + -- You can add more start-up applications here + }, + + -- List of binaries/shell scripts that will execute a certain task + + bins = { + full_screenshot = bin_dir .. 'snap full', -- Full Screenshot + area_screenshot = bin_dir .. 'snap area', -- Area Selected Screenshot + update_profile = bin_dir .. 'profile-image' -- Update profile picture + } +} diff --git a/awesome/configuration/client/buttons.lua b/awesome/configuration/client/buttons.lua new file mode 100644 index 0000000..e882861 --- /dev/null +++ b/awesome/configuration/client/buttons.lua @@ -0,0 +1,30 @@ +local awful = require('awful') + +local modkey = require('configuration.keys.mod').modKey + +return awful.util.table.join( + awful.button( + {}, + 1, + function(c) + _G.client.focus = c + c:raise() + end + ), + awful.button({modkey}, 1, awful.mouse.client.move), + awful.button({modkey}, 3, awful.mouse.client.resize), + awful.button( + {modkey}, + 4, + function() + awful.layout.inc(1) + end + ), + awful.button( + {modkey}, + 5, + function() + awful.layout.inc(-1) + end + ) +) diff --git a/awesome/configuration/client/init.lua b/awesome/configuration/client/init.lua new file mode 100644 index 0000000..bbd5480 --- /dev/null +++ b/awesome/configuration/client/init.lua @@ -0,0 +1 @@ +require('configuration.client.rules') diff --git a/awesome/configuration/client/keys.lua b/awesome/configuration/client/keys.lua new file mode 100644 index 0000000..9bbf23b --- /dev/null +++ b/awesome/configuration/client/keys.lua @@ -0,0 +1,256 @@ +local awful = require('awful') +local gears = require('gears') + +require('awful.autofocus') + +local modkey = require('configuration.keys.mod').modKey +local altkey = require('configuration.keys.mod').altKey + +local dpi = require('beautiful').xresources.apply_dpi + +local clientKeys = + awful.util.table.join( + + -- toggle fullscreen + awful.key( + {modkey}, + 'f', + function(c) + -- Toggle fullscreen + c.fullscreen = not c.fullscreen + c:raise() + end, + {description = 'toggle fullscreen', group = 'client'} + ), + + -- close client + awful.key( + {modkey}, + 'q', + function(c) + c:kill() + end, + {description = 'close', group = 'client'} + ), + -- Default client focus + awful.key( + {modkey}, + 'd', + function() + awful.client.focus.byidx(1) + end, + {description = 'focus next by index', group = 'client'} + ), + awful.key( + {modkey}, + 'a', + function() + awful.client.focus.byidx(-1) + end, + {description = 'focus previous by index', group = 'client'} + ), + awful.key( + { modkey, "Shift" }, + "d", + function () + awful.client.swap.byidx(1) + end, + {description = "swap with next client by index", group = "client"} + ), + awful.key( + { modkey, "Shift" }, + "a", + function () + awful.client.swap.byidx(-1) + end, + {description = "swap with next client by index", group = "client"} + ), + + awful.key( + {modkey}, + 'u', + awful.client.urgent.jumpto, + {description = 'jump to urgent client', group = 'client'} + ), + awful.key( + {modkey}, + 'Tab', + function() + awful.client.focus.history.previous() + if client.focus then + client.focus:raise() + end + end, + {description = 'go back', group = 'client'} + ), + awful.key( + {modkey}, + 'n', + function(c) + c.minimized = true + end, + {description = "minimize client", group = 'client'} + ), + -- move floating client to center + awful.key( + { modkey, "Shift" }, + "c", + function(c) + local focused = awful.screen.focused() + + awful.placement.centered(c, { + honor_workarea = true + }) + end, + {description = 'align a client to the center of the focused screen.', group = "client"} + ), + + -- toggle client floating mode + awful.key( + {modkey}, + 'c', + function(c) + c.fullscreen = false + c.maximized = false + c.floating = not c.floating + c:raise() + end, + {description = 'toggle floating', group = 'client'} + ), + + -- move client position + awful.key( + {modkey}, + 'Up', + function(c) + if c.floating then + c:relative_move(0, dpi(-10), 0, 0) + end + end, + {description = 'move floating client up by 10 px', group = 'client'} + ), + awful.key( + {modkey}, + 'Down', + function(c) + if c.floating then + c:relative_move(0, dpi(10), 0, 0) + end + end, + {description = 'move floating client down by 10 px', group = 'client'} + ), + awful.key( + {modkey}, + 'Left', + function(c) + if c.floating then + c:relative_move(dpi(-10), 0, 0, 0) + end + end, + {description = 'move floating client to the left by 10 px', group = 'client'} + ), + awful.key( + {modkey}, + 'Right', + function(c) + if c.floating then + c:relative_move(dpi(10), 0, 0, 0) + end + end, + {description = 'move floating client to the right by 10 px', group = 'client'} + ), + + -- Increasing floating client size + awful.key( + {modkey, 'Shift'}, + 'Up', + function(c) + if c.floating then + c:relative_move(0, dpi(-10), 0, dpi(10)) + end + end, + {description = 'increase floating client size vertically by 10 px up', group = 'client'} + ), + awful.key( + {modkey, 'Shift'}, + 'Down', + function(c) + if c.floating then + c:relative_move(0, 0, 0, dpi(10)) + end + end, + {description = 'increase floating client size vertically by 10 px down', group = 'client'} + ), + awful.key( + {modkey, 'Shift'}, + 'Left', + function(c) + if c.floating then + c:relative_move(dpi(-10), 0, dpi(10), 0) + end + end, + {description = 'increase floating client size horizontally by 10 px left', group = 'client'} + ), + awful.key( + {modkey, 'Shift'}, + 'Right', + function(c) + if c.floating then + c:relative_move(0, 0, dpi(10), 0) + end + end, + {description = 'increase floating client size horizontally by 10 px right', group = 'client'} + ), + + -- Decreasing floating client size + awful.key( + {modkey, 'Control'}, + 'Up', + function(c) + if c.floating and c.height > 10 then + c:relative_move(0, 0, 0, dpi(-10)) + end + end, + {description = 'decrease floating client size vertically by 10 px up', group = 'client'} + ), + awful.key( + {modkey, 'Control'}, + 'Down', + function(c) + if c.floating then + local c_height = c.height + c:relative_move(0, 0, 0, dpi(-10)) + if c.height ~= c_height and c.height > 10 then + c:relative_move(0, dpi(10), 0, 0) + end + end + end, + {description = 'decrease floating client size vertically by 10 px down', group = 'client'} + ), + awful.key( + {modkey, 'Control'}, + 'Left', + function(c) + if c.floating and c.width > 10 then + c:relative_move(0, 0, dpi(-10), 0) + end + end, + {description = 'decrease floating client size horizontally by 10 px left', group = 'client'} + ), + awful.key( + {modkey, 'Control'}, + 'Right', + function(c) + if c.floating then + local c_width = c.width + c:relative_move(0, 0, dpi(-10), 0) + if c.width ~= c_width and c.width > 10 then + c:relative_move(dpi(10), 0 , 0, 0) + end + end + end, + {description = 'decrease floating client size horizontally by 10 px right', group = 'client'} + ) +) + +return clientKeys diff --git a/awesome/configuration/client/rules.lua b/awesome/configuration/client/rules.lua new file mode 100644 index 0000000..bd16fe4 --- /dev/null +++ b/awesome/configuration/client/rules.lua @@ -0,0 +1,415 @@ +local awful = require('awful') +local gears = require('gears') +local ruled = require("ruled") +local beautiful = require('beautiful') + +local client_keys = require('configuration.client.keys') +local client_buttons = require('configuration.client.buttons') + +ruled.client.connect_signal( + "request::rules", + function() + + -- All clients will match this rule. + ruled.client.append_rule { + id = "global", + rule = { }, + properties = { + focus = awful.client.focus.filter, + raise = true, + floating = false, + maximized = false, + above = false, + below = false, + ontop = false, + sticky = false, + maximized_horizontal = false, + maximized_vertical = false, + round_corners = true, + keys = client_keys, + buttons = client_buttons, + screen = awful.screen.preferred, + placement = awful.placement.no_overlap + awful.placement.no_offscreen + } + } + + -- Dialogs + ruled.client.append_rule { + id = "dialog", + rule_any = { + type = { "dialog" }, + class = { "Wicd-client.py", "calendar.google.com" } + }, + properties = { + titlebars_enabled = true, + floating = true, + above = true, + draw_backdrop = true, + skip_decoration = true, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.client_radius) + end, + placement = awful.placement.centered + } + } + + -- Modals + ruled.client.append_rule { + id = "dialog", + rule_any = { + type = { "modal" } + }, + properties = { + titlebars_enabled = true, + floating = true, + above = true, + draw_backdrop = true, + skip_decoration = true, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.client_radius) + end, + placement = awful.placement.centered + } + } + + -- Utilities + ruled.client.append_rule { + id = "utility", + rule_any = { + type = { "utility" } + }, + properties = { + titlebars_enabled = false, + floating = true, + hide_titlebars = true, + draw_backdrop = false, + skip_decoration = true, + placement = awful.placement.centered + } + } + + -- Splash + ruled.client.append_rule { + id = "splash", + rule_any = { + type = { "splash" } + }, + properties = { + titlebars_enabled = false, + floating = true, + above = true, + hide_titlebars = true, + draw_backdrop = false, + skip_decoration = true, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.client_radius) + end, + placement = awful.placement.centered + } + } + + -- terminal emulators + ruled.client.append_rule { + id = "terminals", + rule_any = { + class = { + "URxvt", + "XTerm", + "UXTerm", + "kitty", + "K3rmit" + } + }, + except_any = { + instance = { "QuakeTerminal" } + }, + properties = { + tag = '1', + switchtotag = true, + draw_backdrop = false, + size_hints_honor = false + } + } + + -- Browsers + ruled.client.append_rule { + id = "web_browsers", + rule_any = { + class = { + "firefox", + "Tor Browser", + "discord", + "Chromium", + "Google-chrome" + } + }, + properties = { + tag = '2' + } + } + + -- text editors + ruled.client.append_rule { + id = "text_editors", + rule_any = { + class = { + "Geany", + "Atom", + "Subl3", + "code-oss" + }, + name = { + "LibreOffice", + "libreoffice" + } + }, + properties = { + tag = '3' + } + } + + -- File managers + ruled.client.append_rule { + id = "file_managers", + rule_any = { + class = { + "dolphin", + "ark", + "Nemo", + "File-roller" + } + }, + properties = { + tag = '4', + switchtotag = true + } + } + + -- Multimedia + ruled.client.append_rule { + id = "multimedia", + rule_any = { + class = { + "vlc", + "Spotify" + } + }, + properties = { + tag = '5', + switchtotag = true, + draw_backdrop = false + } + } + + -- Gaming + ruled.client.append_rule { + id = "gaming", + rule_any = { + class = { + "Wine", + "dolphin-emu", + "Steam", + "Citra", + "SuperTuxKart" + }, + name = { "Steam" } + }, + properties = { + tag = '6', + skip_decoration = true, + draw_backdrop = false, + switchtotag = true, + floating = true, + hide_titlebars = true, + placement = awful.placement.centered + } + } + + -- Graphics Editing + ruled.client.append_rule { + id = "graphics_editors", + rule_any = { + class = { + "Gimp-2.10", + "Inkscape", + "Flowblade" + } + }, + properties = { + tag = '7' + } + } + + -- Sandboxes and VMs + ruled.client.append_rule { + id = "sandbox", + rule_any = { + class = { + "VirtualBox Manage", + "VirtualBox Machine" + } + }, + properties = { + tag = '8' + } + } + + -- IDEs and Tools + ruled.client.append_rule { + id = "ide", + rule_any = { + class = { + "Oomox", + "Unity", + "UnityHub", + "jetbrains-studio" + } + }, + properties = { + tag = '9', + skip_decoration = true + } + } + + -- Image viewers with splash-like behaviour + ruled.client.append_rule { + id = "splash_like", + rule_any = { + class = { + "feh", + "Pqiv", + "Sxiv" + }, + name = {"Discord Updater"} + }, + properties = { + skip_decoration = true, + hide_titlebars = true, + floating = true, + ontop = true, + placement = awful.placement.centered + } + } + + -- Splash-like but with titlebars enabled + ruled.client.append_rule { + id = "instances", + rule_any = { + instance = { + "file_progress", + "Popup", + "nm-connection-editor", + }, + class = { + "scrcpy" , + "Mugshot", + "Pulseeffects" + } + }, + properties = { + skip_decoration = true, + round_corners = true, + ontop = true, + floating = true, + draw_backdrop = false, + focus = awful.client.focus.filter, + raise = true, + keys = client_keys, + buttons = client_buttons, + placement = awful.placement.centered + } + } + + -- Fullsreen + ruled.client.append_rule { + id = "fullscreen", + rule_any = { + class = { + "SuperTuxKart" + } + }, + properties = { + skip_decoration = true, + round_corners = false, + ontop = true, + floating = false, + fullscreen = true, + draw_backdrop = false, + raise = true, + keys = client_keys, + buttons = client_buttons, + placement = awful.placement.centered + } + } + + end +) + + +-- Normally we'd do this with a rule, but other apps like spotify and supertuxkart doesn't set its class or name +-- until after it starts up, so we need to catch that signal. + +-- If the application is fullscreen in its settings, make sure to set `c.fullscreen = false` first +-- before moving to the desired tag or else the tag where the program spawn will cause panels to hide. +-- After moving the program to specified tag you can set `c.fullscreen = true` now +-- See what I did in `SuperTuxKart` + +client.connect_signal( + "property::class", + function(c) + if c.class == "Spotify" then + -- Check if Spotify is already open + local spotify = function (c) + return ruled.client.match(c, { class = "Spotify" }) + end + + local spotify_count = 0 + for c in awful.client.iterate(spotify) do + spotify_count = spotify_count + 1 + end + + -- If Spotify is already open, don't open a new instance + if spotify_count > 1 then + c:kill() + -- Switch to previous instance + for c in awful.client.iterate(spotify) do + c:jump_to(false) + end + else + -- Move the Spotify instance to "5" tag on this screen + local t = awful.tag.find_by_name(awful.screen.focused(), "5") + c:move_to_tag(t) + end + elseif c.class == "SuperTuxKart" then + -- Disable fullscreen first + c.fullscreen = false + + -- Check if SuperTuxKart is already open + local stk = function (c) + return ruled.client.match(c, { class = "SuperTuxKart" }) + end + + local stk_count = 0 + for c in awful.client.iterate(stk) do + stk_count = stk_count + 1 + end + + -- If SuperTuxKart is already open, don't open a new instance + if stk_count > 1 then + c:kill() + -- Switch to previous instance + for c in awful.client.iterate(stk) do + c:jump_to(false) + end + else + -- Move the instance to specified tag tag on this screen + local t = awful.tag.find_by_name(awful.screen.focused(), "6") + c:move_to_tag(t) + t:view_only() + -- Enable fullscreeen again + c.fullscreen = true + end + end + + end +) \ No newline at end of file diff --git a/awesome/configuration/init.lua b/awesome/configuration/init.lua new file mode 100644 index 0000000..f93e86b --- /dev/null +++ b/awesome/configuration/init.lua @@ -0,0 +1,4 @@ +return { + keys = require('configuration.keys'), + apps = require('configuration.apps') +} diff --git a/awesome/configuration/keys/global.lua b/awesome/configuration/keys/global.lua new file mode 100644 index 0000000..817203a --- /dev/null +++ b/awesome/configuration/keys/global.lua @@ -0,0 +1,564 @@ +local awful = require('awful') +local beautiful = require('beautiful') + +require('awful.autofocus') + +local hotkeys_popup = require('awful.hotkeys_popup').widget + +local modkey = require('configuration.keys.mod').modKey +local altkey = require('configuration.keys.mod').altKey +local apps = require('configuration.apps') + +-- Key bindings +local globalKeys = awful.util.table.join( + + -- Hotkeys + awful.key( + {modkey}, + 'F1', + hotkeys_popup.show_help, + {description = 'show help', group = 'awesome'} + ), + awful.key({modkey, 'Control'}, + 'r', + awesome.restart, + {description = 'reload awesome', group = 'awesome'} + ), + + awful.key({modkey, 'Control'}, + 'q', + awesome.quit, + {description = 'quit awesome', group = 'awesome'} + ), + awful.key( + {altkey, 'Shift'}, + 'l', + function() + awful.tag.incmwfact(0.05) + end, + {description = 'increase master width factor', group = 'layout'} + ), + awful.key( + {altkey, 'Shift'}, + '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'} + ), + awful.key( + {modkey}, + 'w', + awful.tag.viewprev, + {description = 'view previous tag', group = 'tag'} + ), + + awful.key( + {modkey}, + 's', + awful.tag.viewnext, + {description = 'view next tag', group = 'tag'} + ), + awful.key( + {modkey}, + 'Escape', + awful.tag.history.restore, + {description = 'alternate between current and previous tag', group = 'tag'} + ), + awful.key({ modkey, "Control" }, + "w", + function () + -- tag_view_nonempty(-1) + local focused = awful.screen.focused() + for i = 1, #focused.tags do + awful.tag.viewidx(-1, focused) + if #focused.clients > 0 then + return + end + end + end, + {description = "view previous non-empty tag", group = "tag"} + ), + awful.key({ modkey, "Control" }, + "s", + function () + -- tag_view_nonempty(1) + local focused = awful.screen.focused() + for i = 1, #focused.tags do + awful.tag.viewidx(1, focused) + if #focused.clients > 0 then + return + end + end + end, + {description = "view next non-empty tag", group = "tag"} + ), + awful.key( + {modkey, 'Shift'}, + "F1", + function() + awful.screen.focus_relative(-1) + end, + { description = "focus the previous screen", group = "screen"} + ), + awful.key( + {modkey, 'Shift'}, + "F2", + function() + awful.screen.focus_relative(1) + end, + { description = "focus the next screen", group = "screen"} + ), + awful.key( + {modkey, 'Control'}, + 'n', + function() + local c = awful.client.restore() + -- Focus restored client + if c then + client.focus = c + c:raise() + end + end, + {description = 'restore minimized', group = 'screen'} + ), + awful.key( + {}, + 'XF86MonBrightnessUp', + function() + awful.spawn('light -A 10', false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show', true) + end, + {description = 'increase brightness by 10%', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86MonBrightnessDown', + function() + awful.spawn('light -U 10', false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show', true) + end, + {description = 'decrease brightness by 10%', group = 'hotkeys'} + ), + -- ALSA volume control + awful.key( + {}, + 'XF86AudioRaiseVolume', + function() + awful.spawn('amixer -D pulse sset Master 5%+', false) + awesome.emit_signal('widget::volume') + awesome.emit_signal('module::volume_osd:show', true) + end, + {description = 'increase volume up by 5%', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86AudioLowerVolume', + function() + awful.spawn('amixer -D pulse sset Master 5%-', false) + awesome.emit_signal('widget::volume') + awesome.emit_signal('module::volume_osd:show', true) + end, + {description = 'decrease volume up by 5%', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86AudioMute', + function() + awful.spawn('amixer -D pulse set Master 1+ toggle', false) + end, + {description = 'toggle mute', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86AudioNext', + function() + awful.spawn('mpc next', false) + end, + {description = 'next music', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86AudioPrev', + function() + awful.spawn('mpc prev', false) + end, + {description = 'previous music', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86AudioPlay', + function() + awful.spawn('mpc toggle', false) + end, + {description = 'play/pause music', group = 'hotkeys'} + + ), + awful.key( + {}, + 'XF86AudioMicMute', + function() + awful.spawn('amixer set Capture toggle', false) + end, + {description = 'mute microphone', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86PowerDown', + function() + -- + end, + {description = 'shutdown skynet', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86PowerOff', + function() + awesome.emit_signal("module::exit_screen_show") + end, + {description = 'toggle exit screen', group = 'hotkeys'} + ), + awful.key( + {}, + 'XF86Display', + function() + awful.spawn.single_instance('arandr', false) + end, + {description = 'arandr', group = 'hotkeys'} + ), + awful.key( + {modkey}, + '`', + function() + _G.toggle_quake() + end, + {description = 'dropdown application', group = 'launcher'} + ), + awful.key( + {modkey}, + 'm', + function() + if awful.screen.focused().musicpop then + awesome.emit_signal('widget::music', 'keyboard') + end + end, + {description = "toggle music widget", group = 'launcher'} + ), + awful.key( + { }, + "Print", + function () + awful.spawn.easy_async_with_shell(apps.bins.full_screenshot,function() end) + end, + {description = "fullscreen screenshot", group = 'Utility'} + ), + awful.key( + {modkey, "Shift"}, + 's', + function () + awful.spawn.easy_async_with_shell(apps.bins.area_screenshot,function() end) + end, + {description = "area/selected screenshot", group = 'Utility'} + ), + awful.key( + {modkey}, + 'x', + function() + awesome.emit_signal("widget::blur:toggle") + end, + {description = "toggle blur effects", group = 'Utility'} + ), + awful.key( + {modkey}, + ']', + function() + awesome.emit_signal("widget::blur:increase") + end, + {description = "increase blur effect by 10%", group = 'Utility'} + ), + awful.key( + {modkey}, + '[', + function() + awesome.emit_signal("widget::blur:decrease") + end, + {description = "decrease blur effect by 10%", group = 'Utility'} + ), + awful.key( + {modkey}, + 't', + function() + awesome.emit_signal("widget::blue_light:toggle") + end, + {description = "toggle redshift filter", group = 'Utility'} + ), + awful.key( + { 'Control' }, + 'Escape', + function () + if screen.primary.systray then + if not screen.primary.tray_toggler then + local systray = screen.primary.systray + systray.visible = not systray.visible + else + awesome.emit_signal("widget::systray:toggle") + end + end + end, + {description = "toggle systray visibility", group = 'Utility'} + ), + awful.key( + {modkey}, + 'l', + function() + awful.spawn(apps.default.lock, false) + end, + {description = "lock the screen", group = 'Utility'} + ), + awful.key( + {modkey}, + 'Return', + function() + awful.spawn(apps.default.terminal) + end, + {description = "open default terminal", group = 'launcher'} + ), + awful.key( + {modkey, "Shift"}, + 'e', + function() + awful.spawn(apps.default.file_manager) + end, + {description = "open default file manager", group = 'launcher'} + ), + awful.key( + {modkey, "Shift"}, + 'f', + function() + awful.spawn(apps.default.web_browser) + end, + {description = "open default web browser", group = 'launcher'} + ), + awful.key( + {"Control", "Shift"}, + 'Escape', + function() + awful.spawn(apps.default.terminal .. ' ' .. 'htop') + end, + {description = "open system monitor", group = 'launcher'} + ), + awful.key( + {modkey}, + 'e', + function() + local focused = awful.screen.focused() + + if focused.left_panel then + focused.left_panel:HideDashboard() + focused.left_panel.opened = false + end + if focused.right_panel then + focused.right_panel:HideDashboard() + focused.right_panel.opened = false + end + awful.spawn(apps.default.rofiappmenu, false) + end, + {description = "open application drawer", group = 'launcher'} + ), + awful.key( + {modkey}, + 'r', + function() + local focused = awful.screen.focused() + + if focused.right_panel and focused.right_panel.visible then + focused.right_panel.visible = false + end + screen.primary.left_panel:toggle() + end, + {description = 'open sidebar', group = 'launcher'} + ), + awful.key( + {modkey, 'Shift'}, + 'r', + function() + local focused = awful.screen.focused() + + if focused.right_panel and focused.right_panel.visible then + focused.right_panel.visible = false + end + screen.primary.left_panel:toggle(true) + end, + {description = 'open sidebar and global search', group = 'launcher'} + ), + awful.key( + {modkey}, + 'F2', + function() + local focused = awful.screen.focused() + + if focused.left_panel and focused.left_panel.opened then + focused.left_panel:toggle() + end + + if focused.right_panel then + if _G.right_panel_mode == 'today_mode' or not focused.right_panel.visible then + focused.right_panel:toggle() + switch_rdb_pane('today_mode') + else + switch_rdb_pane('today_mode') + end + + _G.right_panel_mode = 'today_mode' + end + end, + {description = "open notification center", group = 'launcher'} + ), + awful.key( + {modkey}, + 'F3', + function() + local focused = awful.screen.focused() + + if focused.left_panel and focused.left_panel.opened then + focused.left_panel:toggle() + end + + if focused.right_panel then + if _G.right_panel_mode == 'notif_mode' or not focused.right_panel.visible then + focused.right_panel:toggle() + switch_rdb_pane('notif_mode') + else + switch_rdb_pane('notif_mode') + end + + _G.right_panel_mode = 'notif_mode' + end + end, + {description = "open today pane", group = 'launcher'} + ) +) + +-- Bind all key numbers to tags. +-- Be careful: we use keycodes to make it work on any keyboard layout. +-- This should map on the top row of your keyboard, usually 1 to 9. +for i = 1, 9 do + -- Hack to only show tags 1 and 9 in the shortcut window (mod+s) + local descr_view, descr_toggle, descr_move, descr_toggle_focus + if i == 1 or i == 9 then + descr_view = {description = 'view tag #', group = 'tag'} + descr_toggle = {description = 'toggle tag #', group = 'tag'} + descr_move = {description = 'move focused client to tag #', group = 'tag'} + descr_toggle_focus = {description = 'toggle focused client on tag #', group = 'tag'} + end + globalKeys = + awful.util.table.join( + globalKeys, + -- View tag only. + awful.key( + {modkey}, + '#' .. i + 9, + function() + local focused = awful.screen.focused() + local tag = focused.tags[i] + if tag then + tag:view_only() + end + end, + descr_view + ), + -- Toggle tag display. + awful.key( + {modkey, 'Control'}, + '#' .. i + 9, + function() + local focused = awful.screen.focused() + local tag = focused.tags[i] + if tag then + awful.tag.viewtoggle(tag) + end + end, + descr_toggle + ), + -- Move client to tag. + awful.key( + {modkey, 'Shift'}, + '#' .. i + 9, + function() + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:move_to_tag(tag) + end + end + end, + descr_move + ), + -- Toggle tag on focused client. + awful.key( + {modkey, 'Control', 'Shift'}, + '#' .. i + 9, + function() + if client.focus then + local tag = client.focus.screen.tags[i] + if tag then + client.focus:toggle_tag(tag) + end + end + end, + descr_toggle_focus + ) + ) +end + +return globalKeys diff --git a/awesome/configuration/keys/init.lua b/awesome/configuration/keys/init.lua new file mode 100644 index 0000000..9591667 --- /dev/null +++ b/awesome/configuration/keys/init.lua @@ -0,0 +1,4 @@ +return { + mod = require('configuration.keys.mod'), + global = require('configuration.keys.global') +} diff --git a/awesome/configuration/keys/mod.lua b/awesome/configuration/keys/mod.lua new file mode 100644 index 0000000..1062e04 --- /dev/null +++ b/awesome/configuration/keys/mod.lua @@ -0,0 +1,4 @@ +return { + modKey = 'Mod4', + altKey = 'Mod1' +} diff --git a/awesome/configuration/picom.conf b/awesome/configuration/picom.conf new file mode 100644 index 0000000..317c24b --- /dev/null +++ b/awesome/configuration/picom.conf @@ -0,0 +1,152 @@ + +# ▀ ▄▀▀ +# ▄▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄▄▄ ▄ ▄▄ ▄▄█▄▄ +# █▀ ▀█ █ █▀ ▀ █▀ ▀█ █ █ █ █▀ ▀ █▀ ▀█ █▀ █ █ +# █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ +# ██▄█▀ ▄▄█▄▄ ▀█▄▄▀ ▀█▄█▀ █ █ █ █ ▀█▄▄▀ ▀█▄█▀ █ █ █ +# █ +# ▀ + + + + +# Shadow + +shadow = true; +shadow-radius = 12; +shadow-offset-x = -12; +shadow-offset-y = -12; +shadow-opacity = 0.7; + +# shadow-red = 0.0; +# shadow-green = 0.0; +# shadow-blue = 0.0; + +# shadow-exclude-reg = "x10+0+0"; +# xinerama-shadow-crop = true; + +shadow-exclude = [ + "name = 'Notification'", + "class_g = 'Conky'", + "class_g ?= 'Notify-osd'", + "class_g = 'Cairo-clock'", + "class_g = 'slop'", + "class_g = 'Firefox' && argb", + "class_g = 'Rofi'", + "_GTK_FRAME_EXTENTS@:c", + "_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'" +]; + +# Logs +log-level = "ERROR"; +log-file = "~/.cache/picom-log.log"; + + +# Opacity + +# inactive-opacity = 0.8; +# active-opacity = 0.8; +# frame-opacity = 0.7; +inactive-opacity-override = false; + +opacity-rule = [ + "80:class_g = 'URxvt'", + "80:class_g = 'UXTerm'", + "80:class_g = 'XTerm'" +]; + +# inactive-dim = 0.2; +# inactive-dim-fixed = true; + + +# Blur + +blur: { + method = "dual_kawase"; + strength = 3.2; + # deviation = 1.0; + # kernel = "11x11gaussian"; +} + +# blur-background = true; +blur-background-frame = true; +blur-background-fixed = true; +# blur-kern = "3x3box"; +# blur-kern = "5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1"; + +blur-background-exclude = [ + "window_type = 'desktop'", + "window_type = 'utility'", + "window_type = 'notification'", + "class_g = 'slop'", + "class_g = 'Firefox' && argb", + "name = 'rofi - Global Search'", + "_GTK_FRAME_EXTENTS@:c" +]; + +# max-brightness = 0.66 + +# Fading + +fading = true; +fade-delta = 3; +fade-in-step = 0.03; +fade-out-step = 0.03; +# no-fading-openclose = true; +# no-fading-destroyed-argb = true; +fade-exclude = [ ]; + +# Other + +backend = "glx"; +mark-wmwin-focused = true; +mark-ovredir-focused = true; +# use-ewmh-active-win = true; +detect-rounded-corners = true; +detect-client-opacity = true; +refresh-rate = 0; +vsync = true; +# sw-opti = true; +unredir-if-possible = false; +# unredir-if-possible-delay = 5000; +# unredir-if-possible-exclude = [ ]; +# focus-exclude = [ "class_g = 'Cairo-clock'" ]; + +focus-exclude = [ + "class_g = 'Cairo-clock'", + "class_g ?= 'rofi'", + "class_g ?= 'slop'", + "class_g ?= 'Steam'" +]; + + +detect-transient = true; +detect-client-leader = true; +invert-color-include = [ ]; +# resize-damage = 1; + +# GLX backend + +glx-no-stencil = true; +# glx-no-rebind-pixmap = true; +# xrender-sync-fence = true; +use-damage = true; + +# Window type settings + +wintypes: +{ + tooltip = { fade = true; shadow = false; focus = false; }; + normal = { shadow = false; }; + dock = { shadow = false; }; + dnd = { shadow = false; }; + popup_menu = { shadow = true; focus = false; opacity = 0.90; }; + dropdown_menu = { shadow = false; focus = false; }; + above = { shadow = true; }; + splash = { shadow = false; }; + utility = { focus = false; shadow = false; }; + notification = { shadow = false; }; + desktop = { shadow = false }; + menu = { focus = false }; + dialog = { shadow = true; }; +}; diff --git a/awesome/configuration/rofi/appmenu/rofi.rasi b/awesome/configuration/rofi/appmenu/rofi.rasi new file mode 100644 index 0000000..28d59f2 --- /dev/null +++ b/awesome/configuration/rofi/appmenu/rofi.rasi @@ -0,0 +1,152 @@ +configuration { + font: "SF Pro Text Regular 10"; + show-icons: true; + drun-display-format: "{name}"; + fullscreen: false; + threads: 0; + matching: "fuzzy"; + scroll-method: 0; + disable-history: false; + monitor: "primary"; + window-thumbnail: true; +} + +* { + background: #00000000; + background-color: #00000066; + background-entry: #00000033; + background-alt: #f2f2f215; + foreground: #f2f2f2EE; + foreground-selected: #ffffffFF; + urgent: #E91E6366; + urgent-selected: #E91E6377; +} + +window { + transparency: "real"; + background-color: @background; + text-color: @foreground; + height: 740px; + width: 1321px; + location: northwest; + anchor: northwest; + x-offset: 45; + y-offset: 28; +} + +prompt { + enabled: false; +} + +button { + action: "ok"; + str: " "; + font: "FantasqueSansMono Nerd Font 11"; + expand: false; + text-color: @foreground; + background-color: @background; + vertical-align: 0.5; + horizontal-align: 0.5; +} + +entry { + font: "SF Pro Text Regular 11"; + background-color: @background; + text-color: @foreground; + expand: true; + vertical-align: 0.5; + horizontal-align: 0.0; + placeholder: "Type to search"; + placeholder-color: @foreground; + blink: true; +} + +case-indicator { + background-color: @background; + text-color: @foreground; + vertical-align: 0.5; + horizontal-align: 0.5; +} + +entry-wrapper { + orientation: horizontal; + vertical-align: 0.5; + spacing: 4px; + background-color: @background; + children: [ case-indicator, entry, button ]; +} + +inputbar { + background-color: @background-alt; + text-color: @foreground; + expand: false; + border-radius: 6px; + margin: 0px 405px 0px 405px; + padding: 10px 10px 10px 10px; + position: north; + children: [ entry-wrapper ]; +} + +listview { + background-color: @background; + columns: 7; + spacing: 4px; + cycle: false; + dynamic: true; + layout: vertical; +} + +mainbox { + background-color: @background-color; + children: [ inputbar, listview ]; + spacing: 25px; + padding: 45px 135px 45px 135px; +} + +element { + background-color: @background; + text-color: @foreground; + orientation: vertical; + border-radius: 9px; + padding: 25px 0px 25px 0px; +} + +element-icon { + size: 64px; + border: 0px; +} + +element-text { + expand: true; + horizontal-align: 0.5; + vertical-align: 0.5; + margin: 5px 10px 0px 10px; +} + +element normal.urgent, +element alternate.urgent { + background-color: @urgent; + text-color: @foreground; + border-radius: 9px; +} + +element normal.active, +element alternate.active { + background-color: @background-alt; + text-color: @foreground; +} + +element selected { + background-color: @background-alt; + text-color: @foreground-selected; +} + +element selected.urgent { + background-color: @urgent-selected; + text-color: @foreground; +} + +element selected.active { + background-color: @background-alt; + color: @foreground-selected; +} \ No newline at end of file diff --git a/awesome/configuration/rofi/sidebar/icons/ddg.svg b/awesome/configuration/rofi/sidebar/icons/ddg.svg new file mode 100644 index 0000000..20ea387 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/icons/ddg.svg @@ -0,0 +1,615 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/configuration/rofi/sidebar/icons/google.svg b/awesome/configuration/rofi/sidebar/icons/google.svg new file mode 100644 index 0000000..21e5bf3 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/icons/google.svg @@ -0,0 +1,365 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/configuration/rofi/sidebar/icons/history.svg b/awesome/configuration/rofi/sidebar/icons/history.svg new file mode 100644 index 0000000..872bac8 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/icons/history.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/configuration/rofi/sidebar/icons/result.svg b/awesome/configuration/rofi/sidebar/icons/result.svg new file mode 100644 index 0000000..0f4d883 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/icons/result.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/configuration/rofi/sidebar/icons/suggestion.svg b/awesome/configuration/rofi/sidebar/icons/suggestion.svg new file mode 100644 index 0000000..bf67346 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/icons/suggestion.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/configuration/rofi/sidebar/rofi-spotlight.sh b/awesome/configuration/rofi/sidebar/rofi-spotlight.sh new file mode 100755 index 0000000..d262d1c --- /dev/null +++ b/awesome/configuration/rofi/sidebar/rofi-spotlight.sh @@ -0,0 +1,745 @@ +#!/usr/bin/env bash + +# ---------------------------------------------------------------------------- +# --- Rofi File Browser +# -- +# -- +# -- @author manilarome <gerome.matilla07@gmail.com> +# -- @copyright 2020 manilarome +# -- @script rofi-spotlight.sh +# ---------------------------------------------------------------------------- + +TMP_DIR="/tmp/rofi/${USER}/" + +PREV_LOC_FILE="${TMP_DIR}rofi_fb_prevloc" +CURRENT_FILE="${TMP_DIR}rofi_fb_current_file" + +MY_PATH="$(dirname "${0}")" +HIST_FILE="${MY_PATH}/history.txt" + +OPENER=xdg-open +TERM_EMU=kitty +TEXT_EDITOR=${EDITOR} +FILE_MANAGER=dolphin +BLUETOOTH_SEND=blueman-sendto + +CUR_DIR=$PWD + +NEXT_DIR="" + +SHOW_HIDDEN=false + +declare -a SHELL_OPTIONS=( + "Run" + "Execute in ${TERM_EMU}" + "Edit" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Move to trash" + "Delete" + "Back" +) + +declare -a SHELL_NO_X_OPTIONS=( + "Edit" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Move to trash" + "Delete" + "Back" +) + +declare -a BIN_OPTIONS=( + "Run" + "Execute in ${TERM_EMU}" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Back" +) + +declare -a BIN_NO_X_OPTIONS=( + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Back" +) + +declare -a TEXT_OPTIONS=( + "Edit" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Move to trash" + "Delete" + "Back" +) + +declare -a XCF_SVG_OPTIONS=( + "Open" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Move to trash" + "Delete" + "Back" +) + +declare -a IMAGE_OPTIONS=( + "Open" + "Send via Bluetooth" + "Open file location in ${TERM_EMU}" + "Open file location in ${FILE_MANAGER}" + "Move to trash" + "Delete" + "Back" +) + +declare -a ALL_OPTIONS=() + +# Combine all context menu +COMBINED_OPTIONS=( + "${SHELL_OPTIONS[@]}" + "${SHELL_NO_X_OPTIONS[@]}" + "${BIN_OPTIONS[@]}" + "${BIN_NO_X_OPTIONS[@]}" + "${TEXT_OPTIONS[@]}" + "${XCF_SVG_OPTIONS[@]}" + "${IMAGE_OPTIONS[@]}" +) + +# Remove duplicates +while IFS= read -r -d '' x; do + ALL_OPTIONS+=("$x") +done < <(printf "%s\0" "${COMBINED_OPTIONS[@]}" | sort -uz) + +# Create tmp dir for rofi +if [ ! -d "${TMP_DIR}" ] +then + mkdir -p "${TMP_DIR}"; +fi + +# Create hist file if it doesn't exist +if [ ! -f "${HIST_FILE}" ] +then + touch "${HIST_FILE}" +fi + +# Help message +if [[ ! -z "$@" ]] && [[ "$@" == ":help" ]] +then + + echo "Rofi Spotlight" + echo "A Rofi with file and web searching functionality" + echo " " + echo "Commands:" + echo ":help to print this help message" + echo ":h or :hidden to show hidden files/dirs" + echo ":sh or :show_hist to show search history" + echo ":ch or :clear_hist to clear search history" + echo ":xdg to jump to an xdg directory" + echo "Examples:" + echo " :xdg DOCUMENTS" + echo " :xdg DOWNLOADS" + echo "Also supports incomplete path:" + echo "Examples:" + echo " :xdg doc" + echo " :xdg down" + echo "For more info about XDG dirs, see:" + echo "\`man xdg-user-dir\`" + echo " " + echo "File search syntaxes:" + echo "! to search for a file and web suggestions" + echo "? to search parent directories" + echo "Examples:" + echo " !half-life 3" + echo " ?portal 3" + echo " " + echo "Web search syntaxes:" + echo "! to gets search suggestions" + echo ":web/:w to also to gets search suggestions" + echo ":webbro/:wb to search directly from your browser" + echo "Examples:" + echo " !how to install archlinux" + echo " :web how to install gentoo" + echo " :w how to make a nuclear fission" + echo " :webbro how to install wine in windowsxp" + + exit; +fi + +# Return the icon string +function icon_file_type(){ + + icon_name="" + mime_type=$(file --mime-type -b "${1}") + + case "${mime_type}" in + "inode/directory") + case "${1}" in + "Desktop/" ) + icon_name='folder-blue-desktop' + ;; + "Documents/" ) + icon_name='folder-blue-documents' + ;; + "Downloads/" ) + icon_name='folder-blue-downloads' + ;; + "Music/" ) + icon_name='folder-blue-music' + ;; + "Pictures/" ) + icon_name='folder-blue-pictures' + ;; + "Public/" ) + icon_name='folder-blue-public' + ;; + "Templates/" ) + icon_name='folder-blue-templates' + ;; + "Videos/" ) + icon_name='folder-blue-videos' + ;; + "root/" ) + icon_name='folder-root' + ;; + "home/" | "${USER}/") + icon_name='folder-home' + ;; + *"$" ) + icon_name='folder-blue' + ;; + *) + icon_name='folder-blue' + ;; + esac + ;; + "inode/symlink" ) + icon_name='inode-symlink' + ;; + "audio/flac" | "audio/mpeg" ) + icon_name='music' + ;; + "video/mp4" ) + icon_name='video-mp4' + ;; + "video/x-matroska" ) + icon_name=video-x-matroska + ;; + "image/x-xcf" ) + # notify-send '123' + icon_name='image-x-xcf' + ;; + "image/jpeg" | "image/png" | "image/svg+xml") + icon_name="${CUR_DIR}/${1}" + ;; + "image/gif" ) + icon_name='gif' + ;; + "image/vnd.adobe.photoshop" ) + icon_name='image-vnd.adobe.photoshop' + ;; + "image/webp" ) + icon_name='gif' + ;; + "application/x-pie-executable" ) + icon_name='binary' + ;; + "application/pdf" ) + icon_name='pdf' + ;; + "application/zip" ) + icon_name='application-zip' + ;; + "application/x-xz" ) + icon_name='application-x-xz-compressed-tar' + ;; + "application/x-7z-compressed" ) + icon_name='application-x-7zip' + ;; + "application/x-rar" ) + icon_name='application-x-rar' + ;; + "application/octet-stream" | "application/x-iso9660-image" ) + icon_name='application-x-iso' + ;; + "application/x-dosexec" ) + icon_name='application-x-ms-dos-executable' + ;; + "text/plain" ) + icon_name='application-text' + ;; + "text/x-shellscript" ) + icon_name='application-x-shellscript' + ;; + "font/sfnt" | "application/vnd.ms-opentype" ) + icon_name='application-x-font-ttf' + ;; + * ) + case "${1}" in + *."docx" | *".doc" ) + icon_name='application-msword' + ;; + *."apk" ) + icon_name='android-package-archive' + ;; + * ) + icon_name='unknown' + ;; + esac + ;; + esac + + echo "${1}""\0icon\x1f""${icon_name}""\n" +} + + +# Pass the argument to python scrupt +function web_search() { + # Pass the search query to web-search script + python "${MY_PATH}/web-search.py" "${1}" + exit; +} + +# Handles the web search method +if [ ! -z "$@" ] && ([[ "$@" == ":webbro"* ]] || [[ "$@" == ":wb"* ]]) +then + remove='' + + if [[ "$@" == ":webbro"* ]] + then + remove=":webbro" + else + remove=":wb" + fi + + # Search directly from your web browser + web_search "$(printf '%s\n' "${1//$remove/}")" + exit; + +elif [ ! -z "$@" ] && ([[ "$@" == ":web"* ]] || [[ "$@" == ":w"* ]]) +then + remove='' + + if [[ "$@" == ":web"* ]] + then + remove=":web" + else + remove=":w" + fi + + # Get search suggestions + web_search "!$(printf '%s\n' "${1//$remove/}")" + exit; +fi + +# File and calls to the web search +if [ ! -z "$@" ] && ([[ "$@" == /* ]] || [[ "$@" == \?* ]] || [[ "$@" == \!* ]]) +then + QUERY=$@ + + echo "${QUERY}" >> "${HIST_FILE}" + + if [[ "$@" == /* ]] + then + + if [[ "$@" == *\?\? ]] + then + coproc ( ${OPENER} "${QUERY%\/* \?\?}" > /dev/null 2>&1 ) + exec 1>&- + exit; + else + coproc ( ${OPENER} "$@" > /dev/null 2>&1 ) + exec 1>&- + exit; + fi + + elif [[ "$@" == \?* ]] + then + while read -r line + do + echo "$line" \?\? + done <<< $(find "${HOME}" -iname *"${QUERY#\?}"* 2>&1 | grep -v 'Permission denied\|Input/output error') + + else + # Find the file + find "${HOME}" -iname *"${QUERY#!}"* -exec echo -ne \ + "{}\0icon\x1f${MY_PATH}/icons/result.svg\n" \; 2>&1 | + grep -av 'Permission denied\|Input/output error' + + # Web search + web_search "${QUERY}" + fi + exit; +fi + +# Create notification if there's an error +function create_notification() { + if [[ "${1}" == "denied" ]] + then + notify-send -a "Global Search" "Permission denied!" \ + 'You have no permission to access '"${CUR_DIR}!" + elif [[ "${1}" == "deleted" ]] + then + notify-send -a "Global Search" "Success!" \ + 'File deleted!' + elif [[ "${1}" == "trashed" ]] + then + notify-send -a "Global Search" "Success!" \ + 'The file has been moved to trash!' + elif [[ "${1}" == "cleared" ]] + then + notify-send -a "Global Search" "Success!" \ + 'Search history has been successfully cleared!' + + else + notify-send -a "Global Search" "Somethings wrong I can feel it!" \ + 'This incident will be reported!' + fi +} + +# Show the files in the current directory +function navigate_to() { + # process current dir. + if [ -n "${CUR_DIR}" ] + then + CUR_DIR=$(readlink -e "${CUR_DIR}") + if [ ! -d "${CUR_DIR}" ] || [ ! -r "${CUR_DIR}" ] + then + echo "${HOME}" > "${PREV_LOC_FILE}" + create_notification "denied" + + else + echo "${CUR_DIR}/" > "${PREV_LOC_FILE}" + fi + pushd "${CUR_DIR}" >/dev/null + fi + + printf "..\0icon\x1fup\n" + + if [[ ${SHOW_HIDDEN} == true ]] + then + + for i in .*/ + do + if [[ -d "${i}" ]] && ([[ "${i}" != "./" ]] && [[ "${i}" != "../"* ]]) + then + printf "$(icon_file_type "${i}")"; + fi + done + + for i in .* + do + if [[ -f "${i}" ]] + then + printf "$(icon_file_type "${i}")"; + fi + done + + fi + + for i in */ + do + if [[ -d "${i}" ]] + then + printf "$(icon_file_type "${i}")"; + fi + done + + for i in * + do + if [[ -f "${i}" ]] + then + printf "$(icon_file_type "${i}")"; + fi + done +} + +# Set XDG dir +function return_xdg_dir() { + target_dir=$(echo "$1" | tr "[:lower:]" "[:upper:]") + + if [[ "HOME" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir) + + elif [[ "DESKTOP" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir DESKTOP) + + elif [[ "DOCUMENTS" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir DOCUMENTS) + + elif [[ "DOWNLOADS" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir DOWNLOAD) + + elif [[ "MUSIC" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir MUSIC) + + elif [[ "PICTURES" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir PICTURES) + + elif [[ "PUBLICSHARE" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir PUBLICSHARE) + + elif [[ "TEMPLATES" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir TEMPLATES) + + elif [[ "VIDEOS" == *"${target_dir}"* ]] + then + CUR_DIR=$(xdg-user-dir VIDEOS) + + elif [[ "ROOT" == *"${target_dir}"* ]] + then + CUR_DIR="/" + + else + CUR_DIR="${HOME}" + fi + navigate_to + exit; +} + +# Show and Clear History +if [ ! -z "$@" ] && ([[ "$@" == ":sh" ]] || [[ "$@" == ":show_hist" ]]) +then + hist=$(tac "${HIST_FILE}") + + if [ ! -n "${hist}" ] + then + printf ".\0icon\x1fback\n" + printf "No history, yet.\0icon\x1ftext-plain\n" + fi + + while IFS= read -r line; + do + printf "${line}\0icon\x1f${MY_PATH}/icons/history.svg\n"; + done <<< "${hist}" + + exit; + +elif [ ! -z "$@" ] && ([[ "$@" == ":ch" ]] || [[ "$@" == ":clear_hist" ]]) +then + :> "${HIST_FILE}" + create_notification "cleared" + + CUR_DIR="${HOME}" + navigate_to + exit; +fi + +# Accepts XDG command +if [[ ! -z "$@" ]] && [[ "$@" == ":xdg"* ]] +then + + NEXT_DIR=$(echo "$@" | awk '{print $2}') + + if [[ ! -z "$NEXT_DIR" ]] + then + return_xdg_dir "${NEXT_DIR}" + else + return_xdg_dir "${HOME}" + fi + +fi + +# Read last location, otherwise we default to PWD. +if [ -f "${PREV_LOC_FILE}" ] +then + CUR_DIR=$(cat "${PREV_LOC_FILE}") +fi + +if [[ ! -z "$@" ]] && ([[ "$@" == ":h" ]] || [[ "$@" == ":hidden" ]]) +then + SHOW_HIDDEN=true + navigate_to + exit; +fi + +# Handle argument. +if [ -n "$@" ] +then + CUR_DIR="${CUR_DIR}/$@" +fi + + +# Context Menu +if [[ ! -z "$@" ]] && [[ "${ALL_OPTIONS[*]} " == *"${1}"* ]] +then + case "${1}" in + "Run" ) + coproc ( eval "$(cat "${CURRENT_FILE}")" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Execute in ${TERM_EMU}" ) + coproc ( eval "${TERM_EMU} "$(cat "${CURRENT_FILE}")"" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Open" ) + coproc ( eval "${OPENER} "$(cat "${CURRENT_FILE}")"" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Open file location in ${TERM_EMU}" ) + file_path="$(cat "${CURRENT_FILE}")" + coproc ( ${TERM_EMU} bash -c "cd "${file_path%/*}" ; ${SHELL}" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Open file location in ${FILE_MANAGER}" ) + file_path="$(cat "${CURRENT_FILE}")" + coproc ( eval "${FILE_MANAGER} "${file_path%/*}"" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Edit" ) + coproc ( eval "${TERM_EMU} ${TEXT_EDITOR} $(cat "${CURRENT_FILE}")" & > /dev/null 2>&1 ) + kill -9 $(pgrep rofi) + ;; + "Move to trash" ) + coproc( gio trash "$(cat "${CURRENT_FILE}")" & > /dev/null 2>&1 ) + create_notification "trashed" + CUR_DIR="$(dirname $(cat "${CURRENT_FILE}"))" + navigate_to + ;; + "Delete" ) + shred "$(cat "${CURRENT_FILE}")" + rm "$(cat "${CURRENT_FILE}")" + create_notification "deleted" + CUR_DIR="$(dirname $(cat "${CURRENT_FILE}"))" + navigate_to + ;; + "Send via Bluetooth" ) + rfkill unblock bluetooth && bluetoothctl power on + sleep 1 + blueman-sendto "$(cat "${CURRENT_FILE}")" & > /dev/null 2>&1 + kill -9 $(pgrep rofi) + ;; + "Back" ) + CUR_DIR=$(cat "${PREV_LOC_FILE}") + navigate_to + ;; + esac + exit; +fi + +function context_menu_icons() { + + if [[ "${1}" == "Run" ]] + then + echo '\0icon\x1fsystem-run\n' + + elif [[ "${1}" == "Execute in ${TERM_EMU}" ]] + then + echo "\0icon\x1f${TERM_EMU}\n" + + elif [[ "${1}" == "Open" ]] + then + echo "\0icon\x1futilities-x-terminal\n" + + elif [[ "${1}" == "Open file location in ${TERM_EMU}" ]] + then + echo "\0icon\x1f${TERM_EMU}\n" + + elif [[ "${1}" == "Open file location in ${FILE_MANAGER}" ]] + then + echo "\0icon\x1fblue-folder-open\n" + + elif [[ "${1}" == "Edit" ]] + then + echo "\0icon\x1faccessories-text-editor\n" + + elif [[ "${1}" == "Move to trash" ]] + then + echo "\0icon\x1fapplication-x-trash\n" + + elif [[ "${1}" == "Delete" ]] + then + echo "\0icon\x1findicator-trashindicator\n" + + elif [[ "${1}" == "Send via Bluetooth" ]] + then + echo "\0icon\x1fbluetooth\n" + + elif [[ "${1}" == "Back" ]] + then + echo "\0icon\x1fback\n" + fi +} + +function print_context_menu() { + declare -a arg_arr=("${!1}") + + for menu in "${arg_arr[@]}" + do + printf "$menu$(context_menu_icons "${menu}")\n" + done +} + +function context_menu() { + + type=$(file --mime-type -b "${CUR_DIR}") + + if [ -w "${CUR_DIR}" ] && [[ "${type}" == "text/x-shellscript" ]] + then + if [ -x "${CUR_DIR}" ]; + then + print_context_menu SHELL_OPTIONS[@] + else + print_context_menu SHELL_NO_X_OPTIONS[@] + fi + + elif [[ "${type}" == "application/x-executable" ]] || [[ "${type}" == "application/x-pie-executable" ]] + then + if [ -x "${CUR_DIR}" ] + then + print_context_menu BIN_OPTIONS[@] + else + print_context_menu BIN_NO_X_OPTIONS[@] + fi + + elif [[ "${type}" == "text/plain" ]] + then + print_context_menu TEXT_OPTIONS[@] + + elif [[ "${type}" == "image/jpeg" ]] || [[ "${type}" == "image/png" ]] + then + print_context_menu IMAGE_OPTIONS[@] + + elif [[ "${type}" == "image/x-xcf" ]] || [[ "${type}" == "image/svg+xml" ]] + then + print_context_menu XCF_SVG_OPTIONS[@] + + elif [ ! -w "${CUR_DIR}" ] && [[ "${type}" == "text/x-shellscript" ]] + then + coproc ( exec "${CUR_DIR}" & > /dev/null 2>&1 ) + + else + if [ ! -d "${CUR_DIR}" ] && [ ! -f "${CUR_DIR}" ] + then + QUERY="${CUR_DIR//*\/\//}" + + echo "${QUERY}" >> "${HIST_FILE}" + + find "${HOME}" -iname *"${QUERY#!}"* -exec echo -ne \ + "{}\0icon\x1f${MY_PATH}/icons/result.svg\n" \; 2>&1 | + grep -av 'Permission denied\|Input/output error' + + web_search "!${QUERY}" + else + coproc ( ${OPENER} "${CUR_DIR}" & > /dev/null 2>&1 ) + fi + fi + exit; + +} + +# If argument is not a directory/folder +if [ ! -d "${CUR_DIR}" ] +then + echo "${CUR_DIR}" > "${CURRENT_FILE}" + context_menu + exit; +fi + +navigate_to diff --git a/awesome/configuration/rofi/sidebar/rofi.rasi b/awesome/configuration/rofi/sidebar/rofi.rasi new file mode 100644 index 0000000..01ee1ee --- /dev/null +++ b/awesome/configuration/rofi/sidebar/rofi.rasi @@ -0,0 +1,155 @@ +configuration { + font: "SF Pro Text Regular 10"; + show-icons: true; + fullscreen: false; + sidebar-mode: true; + threads: 0; + matching: "fuzzy"; + scroll-method: 0; + monitor: "primary"; +} + +* { + background: #00000000; + background-color: #00000000; + background-entry: #00000033; + background-alt: #f2f2f215; + foreground: #f2f2f2EE; + foreground-selected: #ffffffFF; + urgent: #E91E6366; + urgent-selected: #E91E6377; +} + +window { + transparency: "real"; + background: @background; + location: west; + anchor: west; + x-offset: 0px; + height: 100%; + width: 350px; + orientation: vertical; +} + +mainbox { + background-color: @background; + spacing: 0px; + padding: 5px 5px 5px 5px; + width: 200px; + expand: true; + spacing: 12px; + children: [ inputbar, listview]; +} + +scrollbar { + background-color: @background-alt; + handle-width: 10px; + margin: 0px 0px 5px 0px; + border-radius: 9px; +} + +listview { + background-color: @background; + spacing: 0px; + dynamic: true; + cycle: true; + scrollbar: true; +} + +prompt { + enabled: false; +} + +button { + action: "ok"; + str: " "; + font: "FantasqueSansMono Nerd Font 16"; + expand: false; + text-color: @foreground; + background-color: @background; + vertical-align: 0.5; + horizontal-align: 0.5; +} + + +entry { + font: "SF Pro Text Regular 12"; + background-color: @background; + placeholder-color: @foreground; + placeholder: "Global Search"; + blink: true; + expand: true; + text-color: @foreground; + vertical-align: 0.5; +} + +entry-wrapper { + orientation: horizontal; + vertical-align: 0.5; + spacing: 4px; + background-color: @background; + children: [ button, entry ]; +} + +inputbar { + padding: 14px; + margin: 10px 10px 14px 10px; + background-color: @background-alt; + text-color: @foreground; + expand: false; + border-radius: 9px; + position: north; + children: [ entry-wrapper ]; +} + +element { + margin: 0px 12px 0px 12px; + background-color: @background; + text-color: @foreground; + orientation: horizontal; + border-radius: 0px; + padding: 10px 12px 10px 12px; + border: 0 0 2px; + border-color: @background-alt; +} + +element-icon { + size: 16px; + border-color: @background; + border: 2px; +} + +element-text { + font: "SF Pro Text Regular 11"; + expand: true; + horizontal-align: 0.0; + vertical-align: 0.5; +} + +element normal.urgent, +element alternate.urgent { + background-color: @urgent; + text-color: @foreground; + border-radius: 9px; +} + +element normal.active, +element alternate.active { + background-color: @background-alt; + text-color: @foreground; +} + +element selected { + background-color: @background-alt; + text-color: @foreground-selected; +} + +element selected.urgent { + background-color: @urgent-selected; + text-color: @foreground; +} + +element selected.active { + background-color: @background-alt; + color: @foreground-selected; +} diff --git a/awesome/configuration/rofi/sidebar/web-search.py b/awesome/configuration/rofi/sidebar/web-search.py new file mode 100755 index 0000000..ba314d5 --- /dev/null +++ b/awesome/configuration/rofi/sidebar/web-search.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 + +# MIT License + +# Copyright (c) 2019 Paolo Donadeo + +# 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 + +import json +import re +import urllib.parse +import urllib.request +import sys +import os +import datetime +import gzip + +import subprocess as sp + +import html + + +################################################################################ +##### C O N F I G U R A T I O N ###### +################################################################################ +SEARCH_ENGINE = 'google' # or 'duckduckgo' +BROWSER = 'firefox' # or 'firefox', 'chromium', 'brave', 'lynx' +TERMINAL = ['kitty', '--'] # or ['st', '-e'] or something like that +################################################################################ + +CONFIG = { + 'BROWSER_PATH' : { + 'chrome' : ['google-chrome-stable'], + 'firefox' : ['firefox'], + 'chromium' : ['chromium-browser'], + 'brave' : ['brave-browser'], + 'lynx' : TERMINAL + ['lynx'] + }, + 'USER_AGENT' : { + 'chrome' : 'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36', + 'firefox' : 'Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:69.0) Gecko/20100101 Firefox/69.0', + 'chromium' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/76.0.3809.100 Chrome/76.0.3809.100 Safari/537.36', + 'brave' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36', + 'lynx' : 'Lynx/2.8.9rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/1.1.1d' + }, + 'SEARCH_ENGINE_NAME' : { + 'google' : 'Google', + 'duckduckgo' : 'DuckDuckGo' + }, + 'SEARCH_URL' : { + 'google' : 'https://www.google.com/search?q=', + 'duckduckgo' : 'https://duckduckgo.com/?q=' + }, + 'SUGGESTION_URL' : { + 'google' : 'https://www.google.com/complete/search?', + 'duckduckgo' : 'https://duckduckgo.com/ac/?' + } +} + +def cleanhtml(txt): + return re.sub(r'<.*?>', '', txt) + +def fetch_suggestions(search_string): + if SEARCH_ENGINE == 'google': + r = { + 'q' : search_string, + 'cp' : '11', + 'client' : 'psy-ab', + 'xssi' : 't', + 'gs_ri' : 'gws-wiz', + 'hl' : 'en-IT', + 'authuser' : '0' + } + url = CONFIG['SUGGESTION_URL'][SEARCH_ENGINE] + urllib.parse.urlencode(r) + headers = { + 'sec-fetch-mode' : 'cors', + 'dnt' : '1', + 'accept-encoding' : 'gzip', + 'accept-language' : 'en-US;q=0.9,en;q=0.8', + 'pragma' : 'no-cache', + 'user-agent' : CONFIG['USER_AGENT'][BROWSER], + 'accept' : '*/*', + 'cache-control' : 'no-cache', + 'authority' : 'www.google.com', + 'referer' : 'https://www.google.com/', + 'sec-fetch-site' : 'same-origin' + } + req = urllib.request.Request(url, headers=headers, method='GET') + + reply_data = gzip.decompress(urllib.request.urlopen(req).read()).split(b'\n')[1] + reply_data = json.loads(reply_data) + return [ cleanhtml(res[0]).strip() for res in reply_data[0] ] + else: # 'duckduckgo' + if search_string.startswith('!'): + bang_search = True + search_string = search_string.lstrip('!') + else: + bang_search = False + r = { + 'q' : search_string, + 'callback' : 'autocompleteCallback', + 'kl' : 'wt-wt', + '_' : str(int((datetime.datetime.now().timestamp())*1000)) + } + url = CONFIG['SUGGESTION_URL'][SEARCH_ENGINE] + urllib.parse.urlencode(r) + if bang_search: + url = url.replace('?q=', '?q=!') + headers = { + 'pragma' : 'no-cache', + 'dnt' : '1', + 'accept-encoding' : 'gzip', + 'accept-language' : 'en-US;q=0.9,en;q=0.8', + 'user-agent' : CONFIG['USER_AGENT'][BROWSER], + 'sec-fetch-mode' : 'no-cors', + 'accept' : '*/*', + 'cache-control' : 'no-cache', + 'authority' : 'duckduckgo.com', + 'referer' : 'https://duckduckgo.com/', + 'sec-fetch-site' : 'same-origin', + } + req = urllib.request.Request(url, headers=headers, method='GET') + reply_data = gzip.decompress(urllib.request.urlopen(req).read()).decode('utf8') + reply_data = json.loads(re.match(r'autocompleteCallback\((.*)\);', reply_data).group(1)) + return [ cleanhtml(res['phrase']).strip() for res in reply_data ] + +def main(): + search_string = html.unescape((' '.join(sys.argv[1:])).strip()) + + path_str = os.path.dirname(os.path.realpath(__file__)) + '/' + icon_path_str = path_str + 'icons/' + icon_name = icon_path_str + + if SEARCH_ENGINE == 'google': + icon_name += 'google.svg' + else: + icon_name += 'ddg.svg' + + if search_string.startswith('!'): + search_string = search_string.rstrip('!').strip() + results = fetch_suggestions(search_string) + for r in results: + print(":wb " + html.unescape(r) + "\0icon\x1f"+icon_name+"\n") + else: + url = CONFIG['SEARCH_URL'][SEARCH_ENGINE] + urllib.parse.quote_plus(search_string) + sp.Popen(CONFIG['BROWSER_PATH'][BROWSER] + [url], stdout=sp.DEVNULL, stderr=sp.DEVNULL, shell=False) + +if __name__ == "__main__": + try: + main() + except Exception as e: + if e: + sys.exit(1) diff --git a/awesome/configuration/root/init.lua b/awesome/configuration/root/init.lua new file mode 100644 index 0000000..176f13e --- /dev/null +++ b/awesome/configuration/root/init.lua @@ -0,0 +1,84 @@ +local gears = require('gears') +local awful = require('awful') + +local apps = require('configuration.apps') + +root.buttons( + gears.table.join( + awful.button( + {}, + 1, + function() + if mymainmenu then + mymainmenu:hide() + end + end + ), + awful.button( + {}, + 3, + function () + if mymainmenu then + mymainmenu:toggle() + end + end + ), + awful.button( + {}, + 2, + function () + awful.util.spawn(apps.default.rofiappmenu) + end + ), + awful.button( + {'Control'}, + 2, + function () + awesome.emit_signal("module::exit_screen_show") + end + ), + awful.button( + {'Shift'}, + 2, + function () + awesome.emit_signal("widget::blue_light:toggle") + end + ), + awful.button( + {}, + 4, + function() + awful.spawn('light -A 10',false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show',true) + end + ), + awful.button( + {}, + 5, + function() + awful.spawn('light -U 10',false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show',true) + end + ), + awful.button( + {'Control'}, + 4, + function() + awful.spawn('amixer -D pulse sset Master 5%+',false) + awesome.emit_signal('widget::volume') + awesome.emit_signal('module::volume_osd:show',true) + end + ), + awful.button( + {'Control'}, + 5, + function() + awful.spawn('amixer -D pulse sset Master 5%-',false) + awesome.emit_signal('widget::volume') + awesome.emit_signal('module::volume_osd:show',true) + end + ) + ) +) \ No newline at end of file diff --git a/awesome/configuration/secrets.lua b/awesome/configuration/secrets.lua new file mode 100644 index 0000000..c66a5e0 --- /dev/null +++ b/awesome/configuration/secrets.lua @@ -0,0 +1,45 @@ + +-- Credentials Manager + +-- How to get a valid credentials for email widget? +-- The widget uses an IMAP. +-- So it means any email service provider that provides an IMAP support is supported by the widget. +-- First, you need an email_address. +-- Second, you must generate an app password for your account. Your account password WILL NOT WORK! +-- Just search in the internet on how to generate for your email service provider. +-- For example `create app password for gmail account` +-- Third, you need an imap_server. +-- Just get your email service provider's imap server. Gmail's imap server is `imap.gmail.com` +-- Fourth, provide the port. +-- Just search it in the internet. Gmail's port is `993` + + + +-- How to get a credentials for weather widget? +-- OpenWeatherMap is our weather provider. So go to `https://home.openweathermap.org/` +-- Register, log-in, and then go to `https://home.openweathermap.org/api_keys` +-- You can create your API keys there. +-- For `units`, you have to choose for yourself. +-- `metric` or 'imperial' +-- metric uses °C, while imperial uses °F + + +return { + + email = { + + address = '', + app_password = '', + imap_server = 'imap.gmail.com', + port = '993' + + }, + + weather = { + + key = '', + city_id = '', + units = 'metric' + + } +} \ No newline at end of file diff --git a/awesome/configuration/tags/init.lua b/awesome/configuration/tags/init.lua new file mode 100644 index 0000000..9ea43c3 --- /dev/null +++ b/awesome/configuration/tags/init.lua @@ -0,0 +1,109 @@ +local awful = require('awful') +local gears = require('gears') +local beautiful = require('beautiful') + +local icons = require('theme.icons') + +local tags = { + { + icon = icons.terminal, + type = 'terminal', + default_app = 'kitty', + screen = 1 + }, + { + icon = icons.web_browser, + type = 'chrome', + default_app = 'firefox', + screen = 1 + }, + { + icon = icons.text_editor, + type = 'code', + default_app = 'subl3', + screen = 1 + }, + { + icon = icons.file_manager, + type = 'files', + default_app = 'nemo', + screen = 1 + }, + { + icon = icons.multimedia, + type = 'music', + default_app = 'vlc', + screen = 1 + }, + { + icon = icons.games, + type = 'game', + default_app = 'supertuxkart', + screen = 1 + }, + { + icon = icons.graphics, + type = 'art', + default_app = 'gimp-2.10', + screen = 1 + }, + { + icon = icons.sandbox, + type = 'virtualbox', + default_app = 'virtualbox', + screen = 1 + }, + { + icon = icons.development, + type = 'any', + default_app = '', + screen = 1 + } + -- { + -- icon = icons.social, + -- type = 'social', + -- default_app = 'discord', + -- screen = 1 + -- } +} + + +tag.connect_signal("request::default_layouts", function() + awful.layout.append_default_layouts({ + awful.layout.suit.spiral.dwindle, + awful.layout.suit.tile, + awful.layout.suit.max + }) +end) + + +screen.connect_signal("request::desktop_decoration", function(s) + for i, tag in pairs(tags) do + awful.tag.add( + i, + { + icon = tag.icon, + icon_only = true, + layout = awful.layout.suit.spiral.dwindle, + gap_single_client = false, + gap = beautiful.useless_gap, + screen = s, + default_app = tag.default_app, + selected = i == 1 + } + ) + end +end) + + +tag.connect_signal( + 'property::layout', + function(t) + local currentLayout = awful.tag.getproperty(t, 'layout') + if (currentLayout == awful.layout.suit.max) then + t.gap = 0 + else + t.gap = beautiful.useless_gap + end + end +) diff --git a/awesome/configuration/user-profile/default.svg b/awesome/configuration/user-profile/default.svg new file mode 100644 index 0000000..14f8006 --- /dev/null +++ b/awesome/configuration/user-profile/default.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/evil/battery.lua b/awesome/evil/battery.lua new file mode 100644 index 0000000..4a8a413 --- /dev/null +++ b/awesome/evil/battery.lua @@ -0,0 +1,49 @@ +-- Provides: +-- evil::battery +-- percentage (integer) +-- evil::charger +-- plugged (boolean) + +local awful = require("awful") + +local update_interval = 60 + +local battery_script = [[ + sh -c " + upower -i $(upower -e | grep BAT) | grep percentage | awk '{print $2}' + " +]] + +-- Subscribe to power supply status changes with acpi_listen +local charger_script = [[ + sh -c ' + acpi_listen | grep --line-buffered ac_adapter + ' +]] + +-- Periodically get battery info +awful.widget.watch(battery_script, update_interval, function(widget, stdout) + local battery = stdout:gsub("%%", "") + awesome.emit_signal("evil::battery", tonumber(battery)) +end) + +local emit_charger_info = function() + awful.spawn.easy_async_with_shell("cat /sys/class/power_supply/*/online", function (out) + local status = tonumber(out) == 1 + awesome.emit_signal("evil::charger", status) + end) +end + +-- Run once to initialize widgets +emit_charger_info() + +-- Kill old acpi_listen process +awful.spawn.easy_async_with_shell("ps x | grep \"acpi_listen\" | grep -v grep | awk '{print $1}' | xargs kill", function () + -- Update charger status with each line printed + awful.spawn.with_line_callback(charger_script, { + stdout = function(_) + emit_charger_info() + end + }) +end) + diff --git a/awesome/glorious.rc.lua b/awesome/glorious.rc.lua new file mode 100644 index 0000000..0d00091 --- /dev/null +++ b/awesome/glorious.rc.lua @@ -0,0 +1,118 @@ + +-- ▄▄ ▄ ▄ ▄ ▄ +-- ██ ▄ ▄ ▄▄▄ ▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ █ █ █ ██ ██ +-- █ █ ▀▄ ▄ ▄▀ █▀ █ █ ▀ █▀ ▀█ █ █ █ █▀ █ ▀ █▀█ █ █ ██ █ +-- █▄▄█ █▄█▄█ █▀▀▀▀ ▀▀▀▄ █ █ █ █ █ █▀▀▀▀ ██ ██▀ █ ▀▀ █ +-- █ █ █ █ ▀█▄▄▀ ▀▄▄▄▀ ▀█▄█▀ █ █ █ ▀█▄▄▀ █ █ █ █ + +-- Banner generated using `toilet -f mono9 AwesomeWM" + +local gears = require('gears') +local awful = require('awful') +local beautiful = require('beautiful') + +require('awful.autofocus') + +-- ======================================== +-- Theme +-- Load the Aesthetics +-- ======================================== +beautiful.init(require('theme')) + +-- ======================================== +-- Layouts +-- Load the Panels +-- ======================================== + +require('layout') + +-- ======================================== +-- Modules +-- Load all the modules +-- ======================================== + +require('module.notifications') +require('module.auto-start') +require('module.decorate-client') +-- require('module.backdrop') +require('module.exit-screen') +require('module.quake-terminal') +require('module.titlebar') +require('module.menu') +require('module.volume-osd') +require('module.brightness-osd') +require('module.dynamic-wallpaper') +require('module.battery-notifier') +require('module.lockscreen') + +-- ======================================== +-- Configuration +-- Load your prefrences +-- ======================================== + +require('configuration.client') +require('configuration.root') +require('configuration.tags') +root.keys(require('configuration.keys.global')) + + +-- ======================================== +-- Signals +-- Signals Listeners and Senders +-- ======================================== + +screen.connect_signal("request::wallpaper", function(s) + + -- If wallpaper is a function, call it with the screen + if beautiful.wallpaper then + if type(beautiful.wallpaper) == "string" then + if beautiful.wallpaper:sub(1, #"#") == "#" then + gears.wallpaper.set(beautiful.wallpaper) + elseif beautiful.wallpaper:sub(1, #"/") == "/" then + gears.wallpaper.maximized(beautiful.wallpaper, s) + end + else + beautiful.wallpaper(s) + end + end + +end) + +-- Signal function to execute when a new client appears. +client.connect_signal( + 'manage', + function(c) + -- Set the windows at the slave, + -- i.e. put it at the end of others instead of setting it master. + if not _G.awesome.startup then + awful.client.setslave(c) + end + + if _G.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 = true}) + end +) + +client.connect_signal( + 'focus', + function(c) + c.border_color = beautiful.border_focus + end +) + +client.connect_signal( + 'unfocus', + function(c) + c.border_color = beautiful.border_normal + end +) diff --git a/awesome/layout/init.lua b/awesome/layout/init.lua new file mode 100644 index 0000000..a13a980 --- /dev/null +++ b/awesome/layout/init.lua @@ -0,0 +1,72 @@ +local awful = require('awful') +local left_panel = require('layout.left-panel') +local top_panel = require('layout.top-panel') +local right_panel = require('layout.right-panel') + +-- Create a wibox panel for each screen and add it +screen.connect_signal("request::desktop_decoration", function(s) + + if s.index == 1 then + -- Create the left_panel + s.left_panel = left_panel(s) + -- Create the Top bar + s.top_panel = top_panel(s, true) + else + -- Create the Top bar + s.top_panel = top_panel(s, false) + end + s.right_panel = right_panel(s) + s.right_panel_show_again = false +end) + + +-- Hide bars when app go fullscreen +function updateBarsVisibility() + for s in screen do + focused = awful.screen.focused() + if s.selected_tag then + local fullscreen = s.selected_tag.fullscreenMode + -- Order matter here for shadow + s.top_panel.visible = not fullscreen + if s.left_panel then + s.left_panel.visible = not fullscreen + end + if s.right_panel then + if fullscreen and focused.right_panel.visible then + focused.right_panel:toggle() + focused.right_panel_show_again = true + elseif not fullscreen and not focused.right_panel.visible and focused.right_panel_show_again then + focused.right_panel:toggle() + focused.right_panel_show_again = false + end + end + end + end +end + +tag.connect_signal( + 'property::selected', + function(t) + updateBarsVisibility() + end +) + +client.connect_signal( + 'property::fullscreen', + function(c) + if c.first_tag then + c.first_tag.fullscreenMode = c.fullscreen + end + updateBarsVisibility() + end +) + +client.connect_signal( + 'unmanage', + function(c) + if c.fullscreen then + c.screen.selected_tag.fullscreenMode = false + updateBarsVisibility() + end + end +) diff --git a/awesome/layout/left-panel/action-bar.lua b/awesome/layout/left-panel/action-bar.lua new file mode 100755 index 0000000..0cde0c1 --- /dev/null +++ b/awesome/layout/left-panel/action-bar.lua @@ -0,0 +1,74 @@ +local awful = require('awful') +local beautiful = require('beautiful') +local wibox = require('wibox') +local gears = require('gears') + +local dpi = beautiful.xresources.apply_dpi +local icons = require('theme.icons') + +local tag_list = require('widget.tag-list') +local clickable_container = require('widget.clickable-container') + +return function(s, panel, action_bar_width) + + local menu_icon = wibox.widget { + { + id = 'menu_btn', + image = icons.menu, + resize = true, + widget = wibox.widget.imagebox + }, + margins = dpi(10), + widget = wibox.container.margin + } + + local home_button = wibox.widget { + { + menu_icon, + widget = clickable_container + }, + bg = beautiful.background .. '66', + widget = wibox.container.background + } + + home_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + panel:toggle() + end + ) + ) + ) + + panel:connect_signal( + 'opened', + function() + menu_icon.menu_btn:set_image(gears.surface(icons.close_small)) + end + ) + + panel:connect_signal( + 'closed', + function() + menu_icon.menu_btn:set_image(gears.surface(icons.menu)) + end + ) + + return wibox.widget { + id = 'action_bar', + layout = wibox.layout.align.vertical, + forced_width = action_bar_width, + { + require('widget.search-apps')(), + tag_list(s), + require("widget.xdg-folders"), + layout = wibox.layout.fixed.vertical, + }, + nil, + home_button + } +end diff --git a/awesome/layout/left-panel/dashboard/hardware-monitor.lua b/awesome/layout/left-panel/dashboard/hardware-monitor.lua new file mode 100644 index 0000000..350a8f2 --- /dev/null +++ b/awesome/layout/left-panel/dashboard/hardware-monitor.lua @@ -0,0 +1,72 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi + +local hardware_header = wibox.widget +{ + + text = 'Hardware Monitor', + font = 'SF Pro Text Regular 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + +} + +return wibox.widget { + layout = wibox.layout.fixed.vertical, + { + { + hardware_header, + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + }, + bg = beautiful.groups_title_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, beautiful.groups_radius) + end, + forced_height = dpi(35), + widget = wibox.container.background + + }, + { + require('widget.cpu.cpu-meter'), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) + end, + forced_height = dpi(48), + widget = wibox.container.background + }, + { + require('widget.ram.ram-meter'), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) + end, + forced_height = dpi(48), + widget = wibox.container.background + }, + { + require('widget.temperature.temperature-meter'), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) + end, + forced_height = dpi(48), + widget = wibox.container.background + + }, + { + require('widget.harddrive.harddrive-meter'), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, beautiful.groups_radius) + end, + forced_height = dpi(48), + widget = wibox.container.background + }, +} diff --git a/awesome/layout/left-panel/dashboard/init.lua b/awesome/layout/left-panel/dashboard/init.lua new file mode 100644 index 0000000..6074534 --- /dev/null +++ b/awesome/layout/left-panel/dashboard/init.lua @@ -0,0 +1,137 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') +local icons = require('theme.icons') + +return function(_, panel) + local search_widget = wibox.widget { + { + { + { + image = icons.search, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + { + text = 'Global Search', + font = 'SF Pro Text Regular 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin + } + + search_button = wibox.widget { + { + search_widget, + widget = clickable_container + }, + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) + end, + widget = wibox.container.background + } + + search_button:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + panel:run_rofi() + end + ) + ) + ) + + local exit_widget = { + { + { + { + image = icons.logout, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + { + text = 'End work session', + font = 'SF Pro Text Regular 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin + } + + exit_button = wibox.widget { + { + exit_widget, + widget = clickable_container + + }, + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) + end, + widget = wibox.container.background + } + + + exit_button:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + panel:toggle() + awesome.emit_signal("module::exit_screen_show") + end + ) + ) + ) + + return wibox.widget { + { + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(7), + search_button, + require('layout.left-panel.dashboard.hardware-monitor'), + require('layout.left-panel.dashboard.quick-settings'), + + }, + nil, + exit_button, + layout = wibox.layout.align.vertical + }, + margins = dpi(16), + widget = wibox.container.margin + + } +end diff --git a/awesome/layout/left-panel/dashboard/quick-settings.lua b/awesome/layout/left-panel/dashboard/quick-settings.lua new file mode 100644 index 0000000..fc221ae --- /dev/null +++ b/awesome/layout/left-panel/dashboard/quick-settings.lua @@ -0,0 +1,105 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi + +local bar_color = beautiful.groups_bg + +local quick_header = wibox.widget +{ + + text = 'Quick Settings', + font = 'SF Pro Text Regular 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + +} + +return wibox.widget { + layout = wibox.layout.fixed.vertical, + spacing = dpi(7), + { + layout = wibox.layout.fixed.vertical, + { + { + quick_header, + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + }, + forced_height = dpi(35), + bg = beautiful.groups_title_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, beautiful.groups_radius) + end, + widget = wibox.container.background + + }, + + { + require('widget.brightness.brightness-slider'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + + }, + { + require('widget.volume.volume-slider'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + + }, + + { + require('widget.network.network-toggle'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + }, + + { + require('widget.bluetooth.bluetooth-toggle'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, false, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + }, + { + require('widget.blue-light'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + } + }, + { + layout = wibox.layout.fixed.vertical, + { + require('widget.window-effects.blur-toggle'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + }, + { + require('widget.window-effects.blur-strength-slider'), + bg = bar_color, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, beautiful.groups_radius) end, + forced_height = dpi(48), + widget = wibox.container.background + } + } +} diff --git a/awesome/layout/left-panel/init.lua b/awesome/layout/left-panel/init.lua new file mode 100644 index 0000000..f112ff8 --- /dev/null +++ b/awesome/layout/left-panel/init.lua @@ -0,0 +1,124 @@ +local awful = require('awful') +local beautiful = require('beautiful') +local wibox = require('wibox') +local apps = require('configuration.apps') +local dpi = require('beautiful').xresources.apply_dpi + +local left_panel = function(screen) + + local action_bar_width = dpi(45) + local panel_content_width = dpi(350) + + local panel = + wibox { + screen = screen, + width = action_bar_width, + type = 'dock', + height = screen.geometry.height - 500, + x = screen.geometry.x, + y = screen.geometry.y + 250, + ontop = false, + bg = beautiful.background, + fg = beautiful.fg_normal + } + + panel.opened = false + + panel:struts( + { + left = action_bar_width + } + ) + + local backdrop = wibox { + ontop = true, + screen = screen, + bg = beautiful.transparent, + type = 'utility', + x = screen.geometry.x, + y = screen.geometry.y, + width = screen.geometry.width, + height = screen.geometry.height + } + + function panel:run_rofi() + _G.awesome.spawn( + apps.default.rofiglobal, + false, + false, + false, + false, + function() + panel:toggle() + end + ) + + -- Hide panel content if rofi global search is opened + panel:get_children_by_id('panel_content')[1].visible = false + end + + local openPanel = function(should_run_rofi) + panel.width = action_bar_width + panel_content_width + backdrop.visible = true + panel.visible = false + panel.visible = true + panel:get_children_by_id('panel_content')[1].visible = true + if should_run_rofi then + panel:run_rofi() + end + panel:emit_signal('opened') + end + + local closePanel = function() + panel.width = action_bar_width + panel:get_children_by_id('panel_content')[1].visible = false + backdrop.visible = false + panel:emit_signal('closed') + end + + -- Hide this panel when app dashboard is called. + function panel:HideDashboard() + closePanel() + end + + function panel:toggle(should_run_rofi) + self.opened = not self.opened + if self.opened then + openPanel(should_run_rofi) + else + closePanel() + end + end + + backdrop:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + panel:toggle() + end + ) + ) + ) + + panel:setup { + layout = wibox.layout.align.horizontal, + nil, + { + id = 'panel_content', + bg = beautiful.transparent, + widget = wibox.container.background, + visible = false, + forced_width = panel_content_width, + { + require('layout.left-panel.dashboard')(screen, panel), + layout = wibox.layout.stack + } + }, + require('layout.left-panel.action-bar')(screen, panel, action_bar_width) + } + return panel +end + +return left_panel diff --git a/awesome/layout/right-panel/icons/notification.svg b/awesome/layout/right-panel/icons/notification.svg new file mode 100644 index 0000000..c60cf96 --- /dev/null +++ b/awesome/layout/right-panel/icons/notification.svg @@ -0,0 +1,111 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/awesome/layout/right-panel/init.lua b/awesome/layout/right-panel/init.lua new file mode 100644 index 0000000..fede772 --- /dev/null +++ b/awesome/layout/right-panel/init.lua @@ -0,0 +1,175 @@ +local awful = require('awful') +local wibox = require('wibox') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +panel_visible = false + +local right_panel = function(s) + + -- Set right panel geometry + local panel_width = dpi(350) + local panel_x = s.geometry.x + s.geometry.width - panel_width + + local panel = wibox { + ontop = true, + screen = s, + type = 'dock', + width = panel_width, + height = s.geometry.height, + x = panel_x, + y = s.geometry.y, + bg = beautiful.background, + fg = beautiful.fg_normal + } + + panel.opened = false + + s.backdrop_rdb = wibox + { + ontop = true, + screen = s, + bg = beautiful.transparent, + type = 'utility', + x = s.geometry.x, + y = s.geometry.y, + width = s.geometry.width, + height = s.geometry.height + } + + panel:struts + { + right = 0 + } + + open_panel = function() + local focused = awful.screen.focused() + panel_visible = true + + focused.backdrop_rdb.visible = true + focused.right_panel.visible = true + + panel:emit_signal('opened') + end + + close_panel = function() + local focused = awful.screen.focused() + panel_visible = false + + focused.right_panel.visible = false + focused.backdrop_rdb.visible = false + + panel:emit_signal('closed') + end + + -- Hide this panel when app dashboard is called. + function panel:HideDashboard() + close_panel() + end + + function panel:toggle() + self.opened = not self.opened + if self.opened then + open_panel() + else + close_panel() + end + end + + + function panel:switch_pane(mode) + if mode == 'notif_mode' then + -- Update Content + panel:get_children_by_id('notif_id')[1].visible = true + panel:get_children_by_id('pane_id')[1].visible = false + elseif mode == 'today_mode' then + -- Update Content + panel:get_children_by_id('notif_id')[1].visible = false + panel:get_children_by_id('pane_id')[1].visible = true + end + end + + s.backdrop_rdb:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + panel:toggle() + end + ) + ) + ) + + + local separator = wibox.widget { + orientation = 'horizontal', + opacity = 0.0, + forced_height = 15, + widget = wibox.widget.separator, + } + + local line_separator = wibox.widget { + orientation = 'horizontal', + forced_height = dpi(1), + span_ratio = 1.0, + color = beautiful.groups_title_bg, + widget = wibox.widget.separator + } + + panel : setup { + { + expand = 'none', + layout = wibox.layout.fixed.vertical, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + require('layout.right-panel.panel-mode-switcher'), + nil + }, + separator, + line_separator, + separator, + { + layout = wibox.layout.stack, + -- Today Pane + { + id = 'pane_id', + visible = true, + layout = wibox.layout.fixed.vertical, + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(7), + require('widget.user-profile'), + require('widget.weather'), + require('widget.email'), + require('widget.social-media'), + require('widget.calculator') + }, + + }, + + -- Notification Center + { + id = 'notif_id', + visible = false, + require('widget.notif-center')(s), + layout = wibox.layout.fixed.vertical, + } + + }, + }, + margins = dpi(16), + widget = wibox.container.margin + } + + + return panel +end + + +return right_panel + + diff --git a/awesome/layout/right-panel/panel-mode-switcher.lua b/awesome/layout/right-panel/panel-mode-switcher.lua new file mode 100644 index 0000000..0617c38 --- /dev/null +++ b/awesome/layout/right-panel/panel-mode-switcher.lua @@ -0,0 +1,135 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi +local clickable_container = require('widget.clickable-container') + +-- Variable used for switching panel modes +right_panel_mode = 'today_mode' + +local active_button = beautiful.groups_title_bg +local inactive_button = beautiful.transparent + +local notif_text = wibox.widget +{ + text = 'Notifications', + font = 'SF Pro Text Bold 11', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local notif_button = clickable_container( + wibox.container.margin( + notif_text, dpi(0), dpi(0), dpi(7), dpi(7) + ) +) + +local wrap_notif = wibox.widget { + notif_button, + forced_width = dpi(140), + bg = inactive_button, + border_width = dpi(1), + border_color = beautiful.groups_title_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect( + cr, width, height, false, true, true, false, beautiful.groups_radius + ) + end, + widget = wibox.container.background +} + + +local today_text = wibox.widget +{ + text = 'Today', + font = 'SF Pro Text Bold 11', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local today_button = clickable_container( + wibox.container.margin( + today_text, dpi(0), dpi(0), dpi(7), dpi(7) + ) +) + +local wrap_today = wibox.widget { + today_button, + forced_width = dpi(140), + bg = active_button, + border_width = dpi(1), + border_color = beautiful.groups_title_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect( + cr, width, height, true, false, false, true, beautiful.groups_radius + ) + end, + widget = wibox.container.background +} + +local switcher = wibox.widget { + expand = 'none', + layout = wibox.layout.fixed.horizontal, + wrap_today, + wrap_notif +} + + +function switch_rdb_pane(right_panel_mode) + + local focused = awful.screen.focused() + + if right_panel_mode == 'notif_mode' then + + -- Update button color + wrap_notif.bg = active_button + wrap_today.bg = inactive_button + + -- Change panel content of right-panel.lua + focused.right_panel:switch_pane(right_panel_mode) + + elseif right_panel_mode == 'today_mode' then + + -- Update button color + wrap_notif.bg = inactive_button + wrap_today.bg = active_button + + -- Change panel content of right-panel.lua + focused.right_panel:switch_pane(right_panel_mode) + end + +end + + +notif_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + switch_rdb_pane('notif_mode') + end + ) + ) +) + +today_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + switch_rdb_pane('today_mode') + end + ) + ) +) + + +return switcher diff --git a/awesome/layout/right-panel/right-panel-opener.lua b/awesome/layout/right-panel/right-panel-opener.lua new file mode 100644 index 0000000..cfc2e4e --- /dev/null +++ b/awesome/layout/right-panel/right-panel-opener.lua @@ -0,0 +1,62 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'layout/right-panel/icons/' + + +-- ▄▄▄▄▄ ▄ ▄ +-- █ █ ▄ ▄ ▄▄█▄▄ ▄▄█▄▄ ▄▄▄ ▄ ▄▄ +-- █▄▄▄▄▀ █ █ █ █ █▀ ▀█ █▀ █ +-- █ █ █ █ █ █ █ █ █ █ +-- █▄▄▄▄▀ ▀▄▄▀█ ▀▄▄ ▀▄▄ ▀█▄█▀ █ █ + + +-- The button in top panel + +local return_button = function() + + local widget = + wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'notification' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.screen.focused().right_panel:toggle() + end + ) + ) + ) + + return widget_button + +end + + +return return_button \ No newline at end of file diff --git a/awesome/layout/top-panel.lua b/awesome/layout/top-panel.lua new file mode 100755 index 0000000..4c822da --- /dev/null +++ b/awesome/layout/top-panel.lua @@ -0,0 +1,336 @@ +local awful = require('awful') +local beautiful = require('beautiful') +local wibox = require('wibox') +local gears = require('gears') + +local icons = require('theme.icons') +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') +local task_list = require('widget.task-list') + + + +local TopPanel = function(s, offset) + + local offsetx = 0 + if offset == true then + offsetx = dpi(45) + end + + local panel = wibox + { + ontop = true, + screen = s, + type = 'dock', + height = dpi(28), + width = s.geometry.width - offsetx, + x = s.geometry.x + offsetx, + y = s.geometry.y, + stretch = false, + bg = beautiful.background, + fg = beautiful.fg_normal + } + + + panel:struts + { + top = dpi(28) + } + + + panel:connect_signal( + 'mouse::enter', + function() + local w = mouse.current_wibox + if w then + w.cursor = 'left_ptr' + end + end + + ) + + + s.add_button = wibox.widget { + { + { + { + { + image = icons.plus, + resize = true, + widget = wibox.widget.imagebox + }, + margins = dpi(4), + widget = wibox.container.margin + }, + widget = clickable_container + }, + bg = beautiful.transparent, + shape = gears.shape.circle, + widget = wibox.container.background + }, + margins = dpi(4), + widget = wibox.container.margin + } + + s.add_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn( + awful.screen.focused().selected_tag.default_app, + { + tag = mouse.screen.selected_tag, + placement = awful.placement.bottom_right + } + ) + end + ) + ) + ) + + + local layout_box = function(s) + local layoutbox = wibox.widget { + { + awful.widget.layoutbox(s), + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + layoutbox:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + awful.layout.inc(1) + end + ), + awful.button( + {}, + 3, + function() + awful.layout.inc(-1) + end + ), + awful.button( + {}, + 4, + function() + awful.layout.inc(1) + end + ), + awful.button( + {}, + 5, + function() + awful.layout.inc(-1) + end + ) + ) + ) + return layoutbox + end + + + s.clock_widget = wibox.widget.textclock( + '%l:%M %p', + 1 + ) + + s.clock_widget = wibox.widget { + { + s.clock_widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + + s.clock_widget:connect_signal( + 'mouse::enter', + function() + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = 'hand1' + end + end + ) + + + s.clock_widget:connect_signal( + 'mouse::leave', + function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + + s.clock_tooltip = awful.tooltip + { + objects = {s.clock_widget}, + mode = 'outside', + delay_show = 1, + preferred_positions = {'right', 'left', 'top', 'bottom'}, + preferred_alignments = {'middle'}, + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + timer_function = function() + local ordinal = nil + + local day = os.date('%d') + local month = os.date('%B') + + local first_digit = string.sub(day, 0, 1) + local last_digit = string.sub(day, -1) + + if first_digit == '0' then + day = last_digit + end + + + if last_digit == '1' and day ~= '11' then + ordinal = 'st' + elseif last_digit == '2' and day ~= '12' then + ordinal = 'nd' + elseif last_digit == '3' and day ~= '13' then + ordinal = 'rd' + else + ordinal = 'th' + end + + local date_str = 'Today is the ' .. + '' .. day .. ordinal .. + ' of ' .. month .. '.\n' .. + 'And it\'s ' .. os.date('%A') .. ' ya idiot!' + + return date_str + + end, + } + + + s.clock_widget:connect_signal( + 'button::press', + function(self, lx, ly, button) + -- Hide the tooltip when you press the clock widget + if s.clock_tooltip.visible and button == 1 then + s.clock_tooltip.visible = false + end + end + ) + + + s.month_calendar = awful.widget.calendar_popup.month({ + start_sunday = true, + spacing = dpi(5), + font = 'SF Pro Text Regular 10', + long_weekdays = true, + margin = dpi(5), + screen = s, + style_month = { + border_width = dpi(0), + padding = dpi(20), + shape = function(cr, width, height) + gears.shape.partially_rounded_rect( + cr, width, height, true, true, true, true, beautiful.groups_radius + ) + end + }, + style_header = { + border_width = 0, + bg_color = beautiful.transparent + }, + style_weekday = { + border_width = 0, + bg_color = beautiful.transparent + }, + + style_normal = { + border_width = 0, + bg_color = beautiful.transparent + }, + style_focus = { + border_width = dpi(0), + border_color = beautiful.fg_normal, + bg_color = beautiful.accent, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect( + cr, width, height, true, true, true, true, dpi(4)) + end, + }, + }) + + + s.month_calendar:attach( + s.clock_widget, + 'tc', + { + on_pressed = true, + on_hover = false + } + ) + + + s.systray = wibox.widget { + visible = false, + base_size = dpi(20), + horizontal = true, + screen = 'primary', + widget = wibox.widget.systray + } + + + s.tray_toggler = require('widget.tray-toggler') + s.updater = require('widget.package-updater')() + s.screen_rec = require('widget.screen-recorder')() + s.music = require('widget.music')() + s.bluetooth = require('widget.bluetooth')() + s.network = require('widget.network')() + s.battery = require('widget.battery')() + s.r_dashboard = require('layout.right-panel.right-panel-opener')() + + + panel : setup { + layout = wibox.layout.align.horizontal, + expand = "none", + { + layout = wibox.layout.fixed.horizontal, + task_list(s), + s.add_button + }, + s.clock_widget, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(5), + { + s.systray, + margins = dpi(5), + widget = wibox.container.margin + }, + s.tray_toggler, + s.updater, + s.screen_rec, + s.music, + s.bluetooth, + s.network, + s.battery, + layout_box(s), + s.r_dashboard + } + } + + return panel +end + + +return TopPanel diff --git a/awesome/library/liblua_pam.so b/awesome/library/liblua_pam.so new file mode 100755 index 0000000..858bb1e Binary files /dev/null and b/awesome/library/liblua_pam.so differ diff --git a/awesome/module/auto-start.lua b/awesome/module/auto-start.lua new file mode 100644 index 0000000..339d4f7 --- /dev/null +++ b/awesome/module/auto-start.lua @@ -0,0 +1,35 @@ +-- MODULE AUTO-START +-- Run all the apps listed in configuration/apps.lua as run_on_start_up only once when awesome start + +local awful = require('awful') +local apps = require('configuration.apps') + +local debugger_mode = false + +local run_once = function(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), + function(stdout, stderr) + -- Debugger + if not stderr or stderr == '' or not debugger_mode then + return + end + require('naughty').notification({ + app_name = 'Start-up Applications', + title = 'Oof! Error detected when starting an application!', + message = stderr:gsub('%\n', ''), + timeout = 20, + icon = require('beautiful').awesome_icon + }) + end + ) +end + +for _, app in ipairs(apps.run_on_start_up) do + run_once(app) +end diff --git a/awesome/module/backdrop.lua b/awesome/module/backdrop.lua new file mode 100644 index 0000000..ffb6a09 --- /dev/null +++ b/awesome/module/backdrop.lua @@ -0,0 +1,83 @@ +local wibox = require('wibox') +local gears = require('gears') +local awful = require('awful') + +local function update_backdrop(w, c) + local cairo = require('lgi').cairo + local geo = c.screen.geometry + + w.x = geo.x + w.y = geo.y + w.width = geo.width + w.height = geo.height + + -- Create an image surface that is as large as the wibox + local shape = cairo.ImageSurface.create(cairo.Format.A1, geo.width, geo.height) + local cr = cairo.Context(shape) + + -- Fill with "completely opaque" + cr.operator = 'SOURCE' + cr:set_source_rgba(1, 1, 1, 1) + cr:paint() + + -- Remove the shape of the client + local c_geo = c:geometry() + local c_shape = gears.surface(c.shape_bounding) + cr:set_source_rgba(0, 0, 0, 0) + cr:mask_surface(c_shape, c_geo.x + c.border_width - geo.x, c_geo.y + c.border_width - geo.y) + c_shape:finish() + + w.shape_bounding = shape._native + shape:finish() + w:draw() +end + +local function backdrop(c) + local function update() + update_backdrop(c.backdrop, c) + end + if not c.backdrop then + c.backdrop = wibox {ontop = true, bg = '#00000054', type = 'splash'} + c.backdrop:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + c:kill() + end + ) + ) + ) + c:connect_signal('property::geometry', update) + c:connect_signal( + 'property::shape_client_bounding', + function() + gears.timer.delayed_call(update) + end + ) + c:connect_signal( + 'unmanage', + function() + c.backdrop.visible = false + end + ) + c:connect_signal( + 'property::shape_bounding', + function() + gears.timer.delayed_call(update) + end + ) + end + update() + c.backdrop.visible = true +end + +client.connect_signal( + 'manage', + function(c) + if c.draw_backdrop == true then + backdrop(c) + end + end +) diff --git a/awesome/module/battery-notifier.lua b/awesome/module/battery-notifier.lua new file mode 100644 index 0000000..3c56696 --- /dev/null +++ b/awesome/module/battery-notifier.lua @@ -0,0 +1,157 @@ +-- Battery notification module +-- Dependencies: +-- acpid, upower, acpi_listens, acpi_call +-- enabled acpid service + +local awful = require('awful') +local naughty = require('naughty') +local icons = require('theme.icons') + +local update_interval = 30 + +-- Periodically get battery info +awful.widget.watch( + [[ + sh -c " + upower -i $(upower -e | grep BAT) | grep percentage | awk '{print $2}' + "]], + update_interval, + function(widget, stdout) + local battery = stdout:gsub("%%", "") + awesome.emit_signal("module::battery", tonumber(battery)) + end +) + +local emit_charger_info = function() + awful.spawn.easy_async_with_shell( + "cat /sys/class/power_supply/*/online", + function (stdout) + status = tonumber(stdout) + if status == 1 then + awesome.emit_signal("module::charger", true) + else + awesome.emit_signal("module::charger", false) + end + end + ) +end + +emit_charger_info() + +awful.spawn.easy_async_with_shell( + "ps x | grep \"acpi_listen\" | grep -v grep | awk '{print $1}' | xargs kill", + function () + awful.spawn.with_line_callback( + [[ + sh -c ' + acpi_listen | grep --line-buffered ac_adapter + ']], + { + stdout = function(_) + emit_charger_info() + end + } + ) + end +) + +local charger_plugged = true +local battery_full_already_notified = true +local battery_low_already_notified = false +local battery_critical_already_notified = false + +local last_notification + +local function send_notification(title, text, icon, timeout, urgency) + + local args = { + title = title, + text = text, + icon = icon, + timeout = timeout, + urgency = urgency, + app_name = 'Power Notification' + } + + if last_notification and not last_notification.is_expired then + last_notification.title = args.title + last_notification.text = args.text + last_notification.icon = args.icon + else + last_notification = naughty.notification(args) + end + + last_notification = notification +end + +-- Full / Low / Critical notifications +awesome.connect_signal("module::battery", function(battery) + + local text + local icon + local timeout + if not charger_plugged then + + icon = icons.batt_discharging + + if battery < 6 and not battery_critical_already_notified then + battery_critical_already_notified = true + text = "Battery Critical!" + timeout = 0 + urgency = 'critical' + elseif battery < 16 and not battery_low_already_notified then + battery_low_already_notified = true + text = "Battery Full!" + timeout = 6 + urgency = 'normal' + end + + else + icon = icons.batt_charging + if battery ~= nil then + if battery > 99 and not battery_full_already_notified then + battery_full_already_notified = true + text = "Battery Full!" + timeout = 6 + urgency = 'normal' + end + end + end + + -- If text has been initialized, then we need to send a + -- notification + if text then + send_notification("Battery status", text, icon, timeout, urgency) + end + +end) + +-- Charger notifications +local charger_first_time = true +awesome.connect_signal("module::charger", function(plugged) + charger_plugged = plugged + local text + local icon + -- TODO if charger is plugged and battery is full, then set + -- battery_full_already_notified to true + if plugged then + battery_critical_already_notified = false + battery_low_already_notified = false + text = "Plugged" + icon = icons.batt_charging + urgency = 'normal' + else + battery_full_already_notified = false + text = "Unplugged" + icon = icons.batt_discharging + urgency = 'normal' + end + + -- Do not send a notification the first time (when AwesomeWM (re)starts) + if charger_first_time then + charger_first_time = false + else + send_notification("Charger Status", text, icon, 3, urgency) + end +end) + diff --git a/awesome/module/brightness-osd.lua b/awesome/module/brightness-osd.lua new file mode 100644 index 0000000..7c0288f --- /dev/null +++ b/awesome/module/brightness-osd.lua @@ -0,0 +1,272 @@ +local awful = require("awful") +local gears = require("gears") +local wibox = require("wibox") +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') +local icons = require('theme.icons') +local spawn = require('awful.spawn') + +screen.connect_signal("request::desktop_decoration", function(s) + + s.show_bri_osd = false + + local osd_header = wibox.widget { + text = 'Brightness', + font = 'VictorMono Nerd Font 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + } + + local osd_value = wibox.widget { + text = '0%', + font = 'VictorMono Nerd Font 12', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local slider_osd = wibox.widget { + nil, + { + id = 'bri_osd_slider', + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(2), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + } + + local bri_osd_slider = slider_osd.bri_osd_slider + + -- Update brightness level using slider value + bri_osd_slider:connect_signal( + 'property::value', + function() + + local brightness_level = bri_osd_slider:get_value() + + spawn('light -S ' .. math.max(brightness_level, 5), false) + + -- Update textbox widget text + osd_value.text = brightness_level .. '%' + + -- Update the brightness slider if values here change + awesome.emit_signal('widget::brightness:update', brightness_level) + + if s.show_bri_osd then + awesome.emit_signal( + 'module::brightness_osd:show', + true + ) + end + + end + ) + + bri_osd_slider:connect_signal( + 'button::press', + function() + s.show_bri_osd = true + end + ) + bri_osd_slider:connect_signal( + 'button::release', + function() + s.show_bri_osd = false + end + ) + bri_osd_slider:connect_signal( + 'mouse::enter', + function() + s.show_bri_osd = true + end + ) + + -- The emit will come from brightness slider + awesome.connect_signal( + 'module::brightness_osd', + function(brightness) + bri_osd_slider:set_value(brightness) + end + ) + + local icon = wibox.widget { + { + image = icons.brightness, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + } + + local brightness_slider_osd = wibox.widget { + icon, + slider_osd, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + } + + -- Create the box + local osd_height = dpi(100) + local osd_width = dpi(300) + + local osd_margin = dpi(10) + + s.brightness_osd_overlay = awful.popup { + widget = { + -- Removing this block will cause an error... + }, + ontop = true, + visible = false, + type = 'notification', + screen = s, + height = osd_height, + width = osd_width, + maximum_height = osd_height, + maximum_width = osd_width, + offset = dpi(5), + shape = gears.shape.rectangle, + bg = beautiful.transparent, + preferred_anchors = 'middle', + preferred_positions = {'left', 'right', 'top', 'bottom'}, + + } + + s.brightness_osd_overlay : setup { + { + { + { + layout = wibox.layout.align.horizontal, + expand = 'none', + forced_height = dpi(48), + osd_header, + nil, + osd_value + }, + brightness_slider_osd, + layout = wibox.layout.fixed.vertical + }, + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + }, + bg = beautiful.background, + shape = gears.shape.rounded_rect, + widget = wibox.container.background() + } + + local hide_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + awful.screen.focused().brightness_osd_overlay.visible = false + end + } + + local timer_rerun = function() + if hide_osd.started then + hide_osd:again() + else + hide_osd:start() + end + end + + -- Reset timer on mouse hover + s.brightness_osd_overlay:connect_signal( + 'mouse::enter', + function() + s.show_bri_osd = true + timer_rerun() + end + ) + s.brightness_osd_overlay:connect_signal( + 'mouse::enter', + function() + s.show_bri_osd = false + timer_rerun() + end + ) + + local placement_placer = function() + + local focused = awful.screen.focused() + + local right_panel = focused.right_panel + local left_panel = focused.left_panel + local volume_osd = focused.brightness_osd_overlay + + if right_panel and left_panel then + if right_panel.visible then + awful.placement.bottom_left(focused.brightness_osd_overlay, { margins = { + left = osd_margin + left_panel.width, + right = 0, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + return + end + end + + if right_panel then + if right_panel.visible then + awful.placement.bottom_left(focused.brightness_osd_overlay, { margins = { + left = osd_margin, + right = 0, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + return + end + end + + awful.placement.bottom_right(focused.brightness_osd_overlay, { margins = { + left = 0, + right = osd_margin, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + end + + awesome.connect_signal( + 'module::brightness_osd:show', + function(bool) + placement_placer() + awful.screen.focused().brightness_osd_overlay.visible = bool + if bool then + timer_rerun() + awesome.emit_signal( + 'module::volume_osd:show', + false + ) + else + if hide_osd.started then + hide_osd:stop() + end + end + end + ) + + +end) diff --git a/awesome/module/decorate-client.lua b/awesome/module/decorate-client.lua new file mode 100644 index 0000000..7c45111 --- /dev/null +++ b/awesome/module/decorate-client.lua @@ -0,0 +1,112 @@ +local awful = require('awful') +local gears = require('gears') +local beautiful = require('beautiful') + +local function render_client(client, mode) + + if client.skip_decoration or (client.rendering_mode == mode) then + return + end + + client.rendering_mode = mode + client.floating = false + client.maximized = false + client.above = false + client.below = false + client.ontop = false + client.sticky = false + client.maximized_horizontal = false + client.maximized_vertical = false + + if client.rendering_mode == 'maximized' then + client.border_width = 0 + client.shape = function(cr, w, h) + gears.shape.rectangle(cr, w, h) + end + elseif client.rendering_mode ~= 'maximized' then + client.border_width = beautiful.border_width + client.shape = function(cr, w, h) + gears.shape.rounded_rect(cr, w, h, beautiful.client_radius) + end + end + +end + +local changes_on_screen_called = false + +local function changes_on_screen(current_screen) + + local tag_is_max = current_screen.selected_tag ~= nil and + current_screen.selected_tag.layout == awful.layout.suit.max + + local clients_to_manage = {} + + for _, client in pairs(current_screen.clients) do + if not client.skip_decoration and not client.hidden then + table.insert(clients_to_manage, client) + end + end + + if (tag_is_max or #clients_to_manage == 1) then + current_screen.client_mode = 'maximized' + else + current_screen.client_mode = 'dwindle' + end + + for _, client in pairs(clients_to_manage) do + render_client(client, current_screen.client_mode) + end + changes_on_screen_called = false +end + + +function client_callback(client) + if not changes_on_screen_called then + if not client.skip_decoration and client.screen then + changes_on_screen_called = true + local screen = client.screen + gears.timer.delayed_call( + function() + changes_on_screen(screen) + end + ) + end + end +end + +function tag_callback(tag) + if not changes_on_screen_called then + if tag.screen then + changes_on_screen_called = true + local screen = tag.screen + gears.timer.delayed_call( + function() + changes_on_screen(screen) + end + ) + end + end +end + +client.connect_signal('manage', client_callback) + +client.connect_signal('unmanage', client_callback) + +client.connect_signal('property::hidden', client_callback) + +client.connect_signal('property::minimized', client_callback) + +client.connect_signal( + 'property::fullscreen', + function(c) + if c.fullscreen then + render_client(c, 'maximized') + else + client_callback(c) + end + end +) + +tag.connect_signal('property::selected', tag_callback) + +tag.connect_signal('property::layout', tag_callback) diff --git a/awesome/module/dynamic-wallpaper.lua b/awesome/module/dynamic-wallpaper.lua new file mode 100755 index 0000000..e13f99c --- /dev/null +++ b/awesome/module/dynamic-wallpaper.lua @@ -0,0 +1,225 @@ +---------------------------------------------------------------------------- +--- Wallpaper changer module +-- +-- @author Gerome Matilla <gerome.matilla07@gmail.com> +-- @copyright 2019 Gerome Matilla +-- @module wallchange +-- +--- Nevermind this. Do what you want. +---------------------------------------------------------------------------- + +-- This module changes wallpaper based on declared time +-- It checks the difference between the current time and the next scheduled time +-- Then convert it to seconds to set it as a timeout value + +-- Limitations: +-- Timeout paused when laptop/pc is suspended or in sleep mode, and there's probably some bugs too so whatever + +local awful = require('awful') +local filesystem = require('gears.filesystem') +local gears = require('gears') +local beautiful = require('beautiful') + + +-- ======================================== +-- Configuration +-- Change your preference here +-- ======================================== + +-- Wallpaper directory. The default is: +local wall_dir = filesystem.get_configuration_dir() .. 'theme/wallpapers/' +-- local wall_dir = os.getenv('HOME') .. 'Pictures/Wallpapers/' + + +-- Wallpapers filename +-- Note: +-- Default image format is jpg +wallpaper_morning = 'morning-wallpaper.jpg' +wallpaper_noon = 'noon-wallpaper.jpg' +wallpaper_night = 'night-wallpaper.jpg' +wallpaper_midnight = 'midnight-wallpaper.jpg' + + +-- Change the wallpaper on scheduled time +morning_schedule = '06:22:00' +noon_schedule = '12:00:00' +night_schedule = '17:58:00' +midnight_schedule = '24:00:00' + + +-- Update lockscreen background +local update_ls_bg = false + +-- Update lockscreen background command +local update_ls_cmd = 'mantablockscreen --image' + + + +-- ======================================== +-- Processes +-- Don't touch it if it's working +-- ======================================== + + +-- Get current time +local current_time = function() + return os.date("%H:%M:%S") +end + + +-- Countdown variable +-- In seconds +the_countdown = nil + + +-- We will use an array for hour change and wallpaper string +-- Element 0 errm 1 will store the incoming/next scheduled time +-- Geez why the f is lua's array starts with `1`? lol +-- Element 2 will have the wallpaper file name +local wall_data = {} +-- > Why array, you say? +-- Because why not? I'm new to lua and I'm experimenting with it + + +-- Parse HH:MM:SS to seconds +local parse_to_seconds = function(time) + + -- Convert HH in HH:MM:SS + hour_sec = tonumber(string.sub(time, 1, 2)) * 3600 + + -- Convert MM in HH:MM:SS + min_sec = tonumber(string.sub(time, 4, 5)) * 60 + + -- Get SS in HH:MM:SS + get_sec = tonumber(string.sub(time, 7, 8)) + + -- Return computed seconds + return (hour_sec + min_sec + get_sec) + +end + + +-- Get time difference +local time_diff = function(current, schedule) + local diff = parse_to_seconds(current) - parse_to_seconds(schedule) + return diff +end + + +-- Update wallpaper (used by the manage_timer function) +-- I think the gears.wallpaper.maximized is too fast or being ran asynchronously +-- So the wallpaper is not being updated on awesome (re)start without this timer +-- We need some delay. +-- Hey it's working, so whatever +local update_wallpaper = function(wall_name) + gears.timer.start_new(0, function() + + local wall_dir = wall_dir .. wall_name + + gears.wallpaper.maximized (wall_dir, s) + + -- Overwrite the default wallpaper + -- This is important in case we add an extra monitor + beautiful.wallpaper = wall_dir + + if update_ls_bg then + awful.spawn.easy_async_with_shell(update_ls_cmd .. ' ' .. wall_dir, function() + -- + end) + end + end) +end + +-- Updates variables +local manage_timer = function() + + -- Get current time + local time_now = parse_to_seconds(current_time()) + + -- Parse the schedules to seconds + local parsed_morning = parse_to_seconds(morning_schedule) + local parsed_noon = parse_to_seconds(noon_schedule) + local parsed_night = parse_to_seconds(night_schedule) + local parsed_midnight = parse_to_seconds('00:00:00') + + -- Note that we will use '00:00:00' instead of '24:00:00' as midnight + -- As the latter causes an error. The time_diff() returns a negative value + + if time_now >= parsed_midnight and time_now < parsed_morning then + -- Midnight time + + -- Update Wallpaper + update_wallpaper(wallpaper_midnight) + + -- Set the data for the next scheduled time + wall_data = {morning_schedule, wallpaper_morning} + + elseif time_now >= parsed_morning and time_now < parsed_noon then + -- Morning time + + -- Update Wallpaper + update_wallpaper(wallpaper_morning) + + -- Set the data for the next scheduled time + wall_data = {noon_schedule, wallpaper_noon} + + elseif time_now >= parsed_noon and time_now < parsed_night then + -- Noon time + + -- Update Wallpaper + update_wallpaper(wallpaper_noon) + + -- Set the data for the next scheduled time + wall_data = {night_schedule, wallpaper_night} + + else + -- Night time + + -- Update Wallpaper + update_wallpaper(wallpaper_night) + + -- Set the data for the next scheduled time + wall_data = {midnight_schedule, wallpaper_midnight} + + end + + + -- Get the time difference to set as timeout for the wall_updater timer below + the_countdown = time_diff(wall_data[1], current_time()) + +end + +-- Update values at startup +manage_timer() + + + +local wall_updater = gears.timer { + -- The timeout is the difference of current time and the scheduled time we set above. + timeout = the_countdown, + autostart = true, + call_now = true, + callback = function() + + -- Emit signal to update wallpaper + awesome.emit_signal("module::change_wallpaper") + + end +} + +-- Update wallpaper here and update the timeout for the next schedule +awesome.connect_signal("module::change_wallpaper", function() + + -- Update wallpaper based on the data in the array + gears.wallpaper.maximized (wall_dir .. wall_data[2], s) + + -- Update values for the next specified schedule + manage_timer() + + -- Update timer timeout for the next specified schedule + wall_updater.timeout = the_countdown + + -- Restart timer + wall_updater:again() + +end) \ No newline at end of file diff --git a/awesome/module/exit-screen.lua b/awesome/module/exit-screen.lua new file mode 100644 index 0000000..df27656 --- /dev/null +++ b/awesome/module/exit-screen.lua @@ -0,0 +1,351 @@ +local awful = require('awful') +local gears = require('gears') +local wibox = require('wibox') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local icons = require('theme.icons') +local apps = require('configuration.apps') +local clickable_container = require('widget.clickable-container') + +local filesystem = gears.filesystem +local config_dir = filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'configuration/user-profile/' + + +local greeter_message = wibox.widget { + markup = 'Choose wisely!', + font = 'SF Pro Text UltraLight 48', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local profile_name = wibox.widget { + markup = 'user@hostname', + font = 'SF Pro Text Regular 12', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local profile_imagebox = wibox.widget { + image = widget_icon_dir .. 'default.svg', + resize = true, + forced_height = dpi(110), + clip_shape = gears.shape.circle, + widget = wibox.widget.imagebox +} + +local profile_imagebox_bg = wibox.widget { + bg = beautiful.groups_bg, + forced_width = dpi(120), + forced_height = dpi(120), + shape = gears.shape.circle, + widget = wibox.container.background +} + +local update_profile_pic = function() + awful.spawn.easy_async_with_shell( + apps.bins.update_profile, + function(stdout) + stdout = stdout:gsub('%\n','') + if not stdout:match("default") then + profile_imagebox:set_image(stdout) + else + profile_imagebox:set_image(widget_icon_dir .. 'default.svg') + end + end + ) +end + +update_profile_pic() + +local update_user_name = function() + awful.spawn.easy_async_with_shell( + "printf \"$(whoami)@$(hostname)\"", + function(stdout) + local stdout = stdout:gsub('%\n','') + local username = stdout:match("(.*)@") + username = username:sub(1, 1):upper() .. username:sub(2) + greeter_message:set_markup('Choose wisely, ' .. username .. '!') + profile_name:set_markup(stdout) + end + ) +end + +update_user_name() + +local build_button = function(icon, name) + + local button_text = wibox.widget { + text = name, + font = beautiful.font, + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local a_button = wibox.widget { + { + { + { + { + image = icon, + widget = wibox.widget.imagebox + }, + margins = dpi(16), + widget = wibox.container.margin + }, + bg = beautiful.groups_bg, + widget = wibox.container.background + }, + shape = gears.shape.rounded_rect, + forced_width = dpi(90), + forced_height = dpi(90), + widget = clickable_container + }, + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + } + + local build_a_button = wibox.widget { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + a_button, + button_text + } + + return build_a_button +end + +local suspend_command = function() + awesome.emit_signal("module::exit_screen_hide") + awful.spawn.with_shell(apps.default.lock .. ' & systemctl suspend') +end + +local exit_command = function() + awesome.quit() +end + +local lock_command = function() + awesome.emit_signal("module::exit_screen_hide") + awful.spawn.with_shell('sleep 1 && ' .. apps.default.lock) +end + +local poweroff_command = function() + awful.spawn.with_shell('poweroff') + awesome.emit_signal("module::exit_screen_hide") +end + +local reboot_command = function() + awful.spawn.with_shell('reboot') + awesome.emit_signal("module::exit_screen_hide") +end + +local poweroff = build_button(icons.power, 'Shutdown') +poweroff:connect_signal( + 'button::release', + function() + poweroff_command() + end +) + +local reboot = build_button(icons.restart, 'Restart') +reboot:connect_signal( + 'button::release', + function() + reboot_command() + end +) + +local suspend = build_button(icons.sleep, 'Sleep') +suspend:connect_signal( + 'button::release', + function() + suspend_command() + end +) + +local exit = build_button(icons.logout, 'Logout') +exit:connect_signal( + 'button::release', + function() + exit_command() + end +) + +local lock = build_button(icons.lock, 'Lock') +lock:connect_signal( + 'button::release', + function() + lock_command() + end +) + +screen.connect_signal( + "request::desktop_decoration", + function(s) + + s.exit_screen = wibox + { + screen = s, + type = 'splash', + visible = false, + ontop = true, + bg = beautiful.background, + fg = beautiful.fg_normal, + height = s.geometry.height, + width = s.geometry.width, + x = s.geometry.x, + y = s.geometry.y + } + + local exit_screen_hide = function() + awesome.emit_signal("module::exit_screen_hide") + + end + + + local exit_screen_grabber = awful.keygrabber { + + auto_start = true, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + + if key == 's' then + suspend_command() + + elseif key == 'e' then + exit_command() + + elseif key == 'l' then + lock_command() + + elseif key == 'p' then + poweroff_command() + + elseif key == 'r' then + reboot_command() + + elseif key == 'Escape' or key == 'q' or key == 'x' then + awesome.emit_signal("module::exit_screen_hide") + + end + + end + + } + + awesome.connect_signal( + "module::exit_screen_show", + function() + for s in screen do + s.exit_screen.visible = false + end + awful.screen.focused().exit_screen.visible = true + exit_screen_grabber:start() + end + ) + + awesome.connect_signal( + "module::exit_screen_hide", + function() + exit_screen_grabber:stop() + for s in screen do + s.exit_screen.visible = false + end + end + ) + + s.exit_screen : buttons( + gears.table.join( + awful.button( + {}, + 2, + function() + awesome.emit_signal("module::exit_screen_hide") + end + ), + awful.button( + {}, + 3, + function() + awesome.emit_signal("module::exit_screen_hide") + end + ) + ) + ) + + s.exit_screen : setup { + nil, + { + nil, + { + { + nil, + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + { + profile_imagebox_bg, + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + profile_imagebox, + nil + }, + nil + }, + layout = wibox.layout.stack + }, + profile_name + }, + nil, + expand = 'none', + layout = wibox.layout.align.horizontal + }, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + { + greeter_message, + { + poweroff, + reboot, + suspend, + exit, + lock, + layout = wibox.layout.fixed.horizontal + }, + spacing = dpi(30), + layout = wibox.layout.fixed.vertical + }, + spacing = dpi(40), + layout = wibox.layout.fixed.vertical + }, + nil + }, + spacing = dpi(40), + layout = wibox.layout.fixed.vertical + }, + nil, + expand = 'none', + layout = wibox.layout.align.horizontal + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + } + + end +) \ No newline at end of file diff --git a/awesome/module/lockscreen.lua b/awesome/module/lockscreen.lua new file mode 100755 index 0000000..d057e82 --- /dev/null +++ b/awesome/module/lockscreen.lua @@ -0,0 +1,896 @@ +local wibox = require('wibox') +local gears = require('gears') +local awful = require('awful') +local naughty = require('naughty') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local filesystem = require('gears.filesystem') +local config_dir = filesystem.get_configuration_dir() + +local apps = require('configuration.apps') + +local widget_icon_dir = config_dir .. 'configuration/user-profile/' + +package.cpath = package.cpath .. ";" .. config_dir .. "/library/?.so;" +local pam = require('liblua_pam') + +-- General Configuration +local capture_intruder = true -- Capture a picture using webcam +local face_capture_dir = '$(xdg-user-dir PICTURES)/Intruders/' -- Save location, auto creates + +-- Background Mode Configuration +local background_mode = 'blur' -- Available background mode: `image`, `blur`, `root`, `bg_color` +local wall_dir = config_dir .. 'theme/wallpapers/' -- Wallpaper directory +local default_wall_name = 'morning-wallpaper.jpg' -- Default wallpaper +local tmp_wall_dir = '/tmp/awesomewm/' .. os.getenv('USER') .. '/' -- /tmp directory + + +-- Useful variables (DO NOT TOUCH) +local input_password = nil +local lock_again = nil +local type_again = true +local capture_now = capture_intruder +local locked_tag = nil + +-- Processes +local locker = function(s) + + local lockscreen = wibox { + screen = s, + visible = false, + ontop = true, + type = "splash", + width = s.geometry.width, + height = s.geometry.height, + bg = beautiful.background, + fg = beautiful.fg_normal + } + + local uname_text = wibox.widget { + id = 'uname_text', + markup = '$USER', + font = 'SF Pro Display Bold 17', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local uname_text_shadow = wibox.widget { + id = 'uname_text_shadow', + markup = '' .. '$USER' .. "", + font = 'SF Pro Display Bold 17', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local caps_text = wibox.widget { + id = 'uname_text', + markup = 'Caps Lock is on', + font = 'SF Pro Display Italic 10', + align = 'center', + valign = 'center', + opacity = 0.0, + widget = wibox.widget.textbox + } + local caps_text_shadow = wibox.widget { + id = 'uname_text', + markup = '' .. 'Caps Lock is on' .. "", + font = 'SF Pro Display Italic 10', + align = 'center', + valign = 'center', + opacity = 0.0, + widget = wibox.widget.textbox + } + + -- Update username textbox + awful.spawn.easy_async_with_shell('whoami | tr -d "\\n"', function(stdout) + uname_text.markup = stdout + uname_text_shadow.markup = '' .. stdout .. "" + end) + + + local profile_imagebox = wibox.widget { + id = 'user_icon', + image = widget_icon_dir .. 'default' .. '.svg', + resize = true, + forced_height = dpi(100), + forced_width = dpi(100), + clip_shape = gears.shape.circle, + widget = wibox.widget.imagebox + } + + local update_profile_pic = function() + awful.spawn.easy_async_with_shell( + apps.bins.update_profile, + function(stdout) + stdout = stdout:gsub('%\n','') + if not stdout:match("default") then + profile_imagebox:set_image(stdout) + else + profile_imagebox:set_image(widget_icon_dir .. 'default.svg') + end + + end + ) + end + + -- Update image + gears.timer.start_new( + 2, + function() + update_profile_pic() + end + ) + + local time = wibox.widget.textclock( + '%H:%M', + 1 + ) + + local time_shadow = wibox.widget.textclock( + '%H:%M', + 1 + ) + + local wanted_text = wibox.widget { + markup = 'INTRUDER ALERT!', + font = 'SFNS Pro Text Bold 12', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local msg_table = { + 'We are watching you.', + 'We know where you live.', + 'This incident will be reported.', + 'RUN!', + 'Yamete, Oniichan~ uwu', + 'This will self-destruct in 5 seconds!', + 'Image successfully sent!', + 'You\'re doomed!' + } + + local wanted_msg = wibox.widget { + markup = 'This incident will be reported!', + font = 'SFNS Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local wanted_image = wibox.widget { + image = widget_icon_dir .. 'default.svg', + resize = true, + forced_height = dpi(100), + clip_shape = gears.shape.rounded_rect, + widget = wibox.widget.imagebox + } + + local wanted_poster = awful.popup { + + widget = { + { + { + wanted_text, + { + nil, + wanted_image, + nil, + expand = 'none', + layout = wibox.layout.align.horizontal + }, + wanted_msg, + spacing = dpi(10), + layout = wibox.layout.fixed.vertical + }, + margins = dpi(20), + widget = wibox.container.margin + }, + bg = beautiful.background, + shape = gears.shape.rounded_rect, + widget = wibox.container.background + }, + bg = beautiful.transparent, + type = 'utility', + ontop = true, + shape = gears.shape.rectangle, + maximum_width = dpi(250), + maximum_height = dpi(200), + hide_on_right_click = false, + preferred_anchors = {'middle'}, + visible = false + + } + + awful.placement.bottom(wanted_poster, + { + margins = + { + bottom = dpi(10), + }, + parent = screen.primary + } + ) + + + local date_value = function() + local date_val = {} + local ordinal = nil + + local day = os.date('%d') + local month = os.date('%B') + + local first_digit = string.sub(day, 0, 1) + local last_digit = string.sub(day, -1) + + if first_digit == '0' then + day = last_digit + end + + if last_digit == '1' and day ~= '11' then + ordinal = 'st' + elseif last_digit == '2' and day ~= '12' then + ordinal = 'nd' + elseif last_digit == '3' and day ~= '13' then + ordinal = 'rd' + else + ordinal = 'th' + end + + date_val.day = day + date_val.month = month + date_val.ordinal= ordinal + + return date_val + end + + local date = wibox.widget { + markup = date_value().day .. date_value().ordinal .. ' of ' .. date_value().month, + font = 'SF Pro Display Bold 20', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local date_shadow = wibox.widget { + markup = "" .. date_value().day .. date_value().ordinal .. " of " .. + date_value().month .. "", + font = 'SF Pro Display Bold 20', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local circle_container = wibox.widget { + bg = '#f2f2f233', + forced_width = dpi(110), + forced_height = dpi(110), + shape = gears.shape.circle, + widget = wibox.container.background + } + + local locker_arc = wibox.widget { + bg = beautiful.transparent, + forced_width = dpi(110), + forced_height = dpi(110), + shape = function(cr, width, height) + gears.shape.arc(cr, width, height, dpi(5), 0, math.pi/2, true, true) + end, + widget = wibox.container.background + } + + -- Check Capslock state + local check_caps = function() + awful.spawn.easy_async_with_shell( + 'xset q | grep Caps | cut -d: -f3 | cut -d0 -f1 | tr -d " "', + function(stdout) + status = stdout + + if status:match('on') then + caps_text.opacity = 1.0 + caps_text_shadow.opacity = 1.0 + else + caps_text.opacity = 0.0 + caps_text_shadow.opacity = 0.0 + end + caps_text:emit_signal('widget::redraw_needed') + caps_text_shadow:emit_signal('widget::redraw_needed') + end + ) + end + + local rotate_container = wibox.container.rotate() + + local locker_widget = wibox.widget { + { + locker_arc, + widget = rotate_container + }, + layout = wibox.layout.fixed.vertical + } + + -- Rotation direction table + local rotation_direction = {"north", "west", "south", "east"} + + -- Red, Green, Yellow, Blue + local red = beautiful.system_red_dark + local green = beautiful.system_green_dark + local yellow = beautiful.system_yellow_dark + local blue = beautiful.system_blue_dark + + -- Color table + local arc_color = {red, green, yellow, blue} + + + local locker_widget_rotate = function() + + local direction = rotation_direction[math.random(#rotation_direction)] + local color = arc_color[math.random(#arc_color)] + + rotate_container.direction = direction + + locker_arc.bg = color + + rotate_container:emit_signal("widget:redraw_needed") + locker_arc:emit_signal("widget::redraw_needed") + locker_widget:emit_signal("widget::redraw_needed") + + end + + local check_webcam = function() + awful.spawn.easy_async_with_shell( + [[ + ls -l /dev/video* | grep /dev/video0 + ]], + function(stdout) + if not capture_intruder then + capture_now = false + return + end + + if not stdout:match('/dev/video0') then + capture_now = false + else + capture_now = true + end + end + ) + end + + check_webcam() + + local intruder_capture = function() + local capture_image = [[ + + save_dir=]] .. face_capture_dir .. [[ + date=$(date +%Y%m%d_%H%M%S) + file_loc=${save_dir}SUSPECT-${date}.png + + if [ ! -d $save_dir ]; then + mkdir -p $save_dir; + fi + + ffmpeg -f video4linux2 -s 800x600 -i /dev/video0 -ss 0:0:2 -frames 1 ${file_loc} + + canberra-gtk-play -i camera-shutter & + echo ${file_loc} + + ]] + + -- Capture the filthy intruder face + awful.spawn.easy_async_with_shell( + capture_image, + function(stdout) + circle_container.bg = beautiful.groups_title_bg + + -- Humiliate the intruder by showing his/her hideous face + wanted_image:set_image(stdout:gsub('%\n','')) + wanted_poster.visible= true + wanted_msg:set_markup(msg_table[math.random(#msg_table)]) + + awful.placement.bottom(wanted_poster, + { + margins = + { + bottom = dpi(10), + }, + parent = screen.primary + } + ) + wanted_image:emit_signal('widget::redraw_needed') + + type_again = true + end + ) + end + + local stoprightthereyoucriminalscum = function() + + circle_container.bg = red .. 'AA' + + if capture_now then + intruder_capture() + else + gears.timer.start_new( + 1, + function() + circle_container.bg = beautiful.groups_title_bg + type_again = true + end + ) + end + end + + + local generalkenobi_ohhellothere = function() + + circle_container.bg = green .. 'AA' + + -- Add a little delay before unlocking completely + gears.timer.start_new( + 1, + function() + if capture_now then + -- Hide wanted poster + wanted_poster.visible = false + end + + -- Hide all the lockscreen on all screen + for s in screen do + if s.index == 1 then + s.lockscreen.visible = false + else + s.lockscreen_extended.visible = false + end + end + + circle_container.bg = beautiful.groups_title_bg + + -- Enable locking again + lock_again = true + + -- Enable validation again + type_again = true + + -- Select old tag + -- And restore minimized focused client if there's any + if locked_tag then + locked_tag.selected = true + locked_tag = nil + end + local c = awful.client.restore() + if c then + client.focus = c + c:raise() + end + + end + ) + end + + -- A backdoor + local back_door = function() + generalkenobi_ohhellothere() + end + + local password_grabber = awful.keygrabber { + auto_start = true, + stop_event = 'release', + mask_event_callback = true, + keybindings = { + awful.key { + modifiers = {'Control'}, + key = 'u', + on_press = function() + input_password = nil + + end + }, + awful.key { + modifiers = {'Mod1', 'Mod4', 'Shift', 'Control'}, + key = 'Return', + on_press = function(self) + if not type_again then + return + end + self:stop() + back_door() + end + } + }, + keypressed_callback = function(self, mod, key, command) + + if not type_again then + return + end + + -- Clear input string + if key == 'Escape' then + -- Clear input threshold + input_password = nil + return + end + + -- Accept only the single charactered key + -- Ignore 'Shift', 'Control', 'Return', 'F1', 'F2', etc., etc. + if #key == 1 then + locker_widget_rotate() + + if input_password == nil then + input_password = key + return + end + + input_password = input_password .. key + end + + end, + keyreleased_callback = function(self, mod, key, command) + locker_arc.bg = beautiful.transparent + locker_arc:emit_signal('widget::redraw_needed') + + if key == 'Caps_Lock' then + check_caps() + return + end + + if not type_again then + return + end + + -- Validation + if key == 'Return' then + + -- Validate password + local pam_auth = false + if input_password ~= nil then + pam_auth = pam:auth_current_user(input_password) + else + return + end + + if pam_auth then + -- Come in! + self:stop() + generalkenobi_ohhellothere() + else + -- F*ck off, you [REDACTED]! + stoprightthereyoucriminalscum() + end + + type_again = false + + input_password = nil + end + + end + + } + + lockscreen : setup { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + expand = 'none', + spacing = dpi(20), + { + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + time_shadow, + time, + vertical_offset = dpi(-1), + widget = wibox.layout.stack + }, + nil + + }, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + date_shadow, + date, + vertical_offset = dpi(-1), + widget = wibox.layout.stack + }, + nil + + }, + expand = 'none', + layout = wibox.layout.fixed.vertical + }, + { + layout = wibox.layout.fixed.vertical, + { + circle_container, + locker_widget, + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + profile_imagebox, + nil + }, + nil, + }, + layout = wibox.layout.stack + }, + { + uname_text_shadow, + uname_text, + vertical_offset = dpi(-1), + widget = wibox.layout.stack + }, + { + caps_text_shadow, + caps_text, + vertical_offset = dpi(-1), + widget = wibox.layout.stack + } + }, + }, + nil + }, + nil + } + + local show_lockscreen = function() + + -- Unselect all tags and minimize the focused client + -- Will also fix the problem with virtualbox or any other program that has keygrabbing enabled + if client.focus then + client.focus.minimized = true + end + for _, t in ipairs(mouse.screen.selected_tags) do + locked_tag = t + t.selected = false + end + + -- Why is there a lock_again variable? + -- Well, it fixes a bug. + -- What is the bug? + -- It's a secret. + + if lock_again == true or lock_again == nil then + + -- Check capslock status + check_caps() + + -- Check webcam status + check_webcam() + + -- Show all the lockscreen on each screen + for s in screen do + if s.index == 1 then + s.lockscreen.visible = true + else + s.lockscreen_extended.visible = true + end + end + + -- Start key grabbing for password + password_grabber:start() + + -- Dont lock again + lock_again = false + + end + + end + + awesome.connect_signal( + "module::lockscreen_show", + function() + if lock_again == true or lock_again == nil then + show_lockscreen() + end + end + ) + + return lockscreen + +end + +-- This lockscreen is for the extra/multi monitor +local locker_ext = function(s) + local extended_lockscreen = wibox { + screen = s, + visible = false, + ontop = true, + ontype = 'true', + x = s.geometry.x, + y = s.geometry.y, + width = s.geometry.width, + height = s.geometry.height, + bg = beautiful.background, + fg = beautiful.fg_normal + } + + return extended_lockscreen +end + +local cycle_through_screens = function(s) + if s.index == 1 then + s.lockscreen = locker(s) + else + s.lockscreen_extended = locker_ext(s) + end +end + +-- Create a lockscreen for each screen +screen.connect_signal( + "request::desktop_decoration", + function(s) + cycle_through_screens(s) + end +) + +-- Regenerate lockscreens if a screen was added to avoid errors +screen.connect_signal( + 'added', + function(s) + cycle_through_screens(s) + end + +) + +-- Regenerate lockscreens if a screen was removed to avoid errors +screen.connect_signal( + "removed", + function(s) + cycle_through_screens(s) + end +) + +-- Dont show notification popups if the screen is locked +local check_lockscreen_visibility = function() + focused = awful.screen.focused() + if focused.lockscreen and focused.lockscreen.visible then + return true + end + if focused.lockscreen_extended and focused.lockscreen_extended.visible then + return true + end + return false +end + +naughty.connect_signal( + "request::display", + function(_) + if check_lockscreen_visibility() then + naughty.destroy_all_notifications(nil, 1) + end + end +) + +-- Background Mode Processes +local blur_resize_image = function(wall_name, index, ap, width, height) + local magic = [[ + if [ ! -d ]] .. tmp_wall_dir ..[[ ]; then mkdir -p ]] .. tmp_wall_dir .. [[; fi + + convert -quality 100 -filter Gaussian -blur 0x10 ]] .. wall_dir .. wall_name .. + [[ -gravity center -crop ]] .. ap .. [[:1 +repage -resize ]] .. width .. 'x' .. height .. + [[! ]] .. tmp_wall_dir .. index .. wall_name .. [[ + ]] + return magic +end + +local resize_image = function(wall_name, index, ap, width, height) + local magic = [[ + if [ ! -d ]] .. tmp_wall_dir ..[[ ]; then mkdir -p ]] .. tmp_wall_dir .. [[; fi + + convert -quality 100 ]] .. wall_dir .. wall_name .. + [[ -gravity center -crop ]] .. ap .. [[:1 +repage -resize ]] .. width .. 'x' .. height .. + [[! ]] .. tmp_wall_dir .. index .. wall_name .. [[ + ]] + return magic +end + +local apply_ls_bg_image = function(wall_name) + for s in screen do + local index = s.index .. '-' + + local screen_width = s.geometry.width + local screen_height = s.geometry.height + + local aspect_ratio = screen_width / screen_height + + aspect_ratio = math.floor(aspect_ratio * 100) / 100 + + local cmd = nil + if background_mode == 'blur' then + cmd = blur_resize_image(wall_name, index, aspect_ratio, screen_width, screen_height) + else + cmd = resize_image(wall_name, index, aspect_ratio, screen_width, screen_height) + end + + if s.index == 1 then + awful.spawn.easy_async_with_shell( + cmd, + function(stdout, stderr) + s.lockscreen.bgimage = tmp_wall_dir .. index .. wall_name + end + ) + else + awful.spawn.easy_async_with_shell( + cmd, + function() + s.lockscreen_extended.bgimage = tmp_wall_dir .. index .. wall_name + end + ) + end + end +end + +local check_background_mode = function() + + if background_mode == 'root' then + + for s in screen do + if s.index == 1 then + s.lockscreen.bgimage = root.wallpaper() + else + s.lockscreen_extended.bgimage = root.wallpaper() + end + end + + elseif background_mode == 'bg_color' then + for s in screen do + if s.index == 1 then + s.lockscreen.bg = beautiful.background + else + s.lockscreen_extended.bg = beautiful.background + end + end + + elseif background_mode == 'blur' or background_mode == 'image' then + apply_ls_bg_image(default_wall_name) + + else + for s in screen do + if s.index == 1 then + s.lockscreen.bgimage = root.wallpaper() + else + s.lockscreen_extended.bgimage = root.wallpaper() + end + end + end + +end + +check_background_mode() + +-- Regenerate lockscreen's background if a screen was added +screen.connect_signal( + 'added', + function() + check_background_mode() + end + +) + +-- Regenerate lockscreen's background if a screen was removed +screen.connect_signal( + "removed", + function() + check_background_mode() + end +) \ No newline at end of file diff --git a/awesome/module/menu.lua b/awesome/module/menu.lua new file mode 100644 index 0000000..6806d8e --- /dev/null +++ b/awesome/module/menu.lua @@ -0,0 +1,206 @@ +-- An applications menu +-- Required depends: awesome-freedesktop + +local awful = require("awful") +local gears = require("gears") +local beautiful = require("beautiful") +local apps = require('configuration.apps') +local menubar = require("menubar") + +local hotkeys_popup = require('awful.hotkeys_popup').widget + +local terminal = apps.default.terminal +local web_browser = apps.default.web_browser +local file_manager = apps.default.file_manager +local text_editor = apps.default.text_editor +local editor_cmd = terminal .. " -e " .. (os.getenv("EDITOR") or "nano") + +local function is_module_available(name) + if package.loaded[name] then + return true + else + for _, searcher in ipairs(package.searchers or package.loaders) do + local loader = searcher(name) + if type(loader) == 'function' then + package.preload[name] = loader + return true + end + end + return false + end +end + +-- Create a launcher widget and a main menu +awesome_menu = { + { + "Hotkeys", + function() + hotkeys_popup.show_help(nil, awful.screen.focused()) + end, + menubar.utils.lookup_icon("keyboard") + }, + { + "Edit config", + editor_cmd .. " " .. awesome.conffile, + menubar.utils.lookup_icon("accessories-text-editor") + }, + { + "Restart", + awesome.restart, + menubar.utils.lookup_icon("system-restart") + }, + { + "Quit", + function() awesome.quit() end, + menubar.utils.lookup_icon("system-log-out") + } +} + +local default_app_menu = { + { + "Terminal", + terminal, + menubar.utils.lookup_icon("utilities-terminal") + }, + { + "Web browser", + web_browser, + menubar.utils.lookup_icon("webbrowser-app") + }, + { + "File Manager", + file_manager, + menubar.utils.lookup_icon("system-file-manager") + }, + { + "Text Editor", + text_editor, + menubar.utils.lookup_icon("accessories-text-editor") + } +} + +-- Screenshot menu +local screenshot_menu = { + { + "Full", + function() + gears.timer.start_new( + 0.1, + function() + awful.spawn.easy_async_with_shell(apps.bins.full_screenshot) + end + ) + end, + menubar.utils.lookup_icon("accessories-screenshot") + }, + { + "Area", + function() + gears.timer.start_new( + 0.1, + function() + awful.spawn.easy_async_with_shell(apps.bins.area_screenshot) + end, + menubar.utils.lookup_icon("accessories-screenshot") + ) + end, + menubar.utils.lookup_icon("accessories-screenshot") + } +} + +local tools_menu = { + { + "Awesome", + awesome_menu, + beautiful.awesome_icon + }, + { + "Take a Screenshot", + screenshot_menu, + menubar.utils.lookup_icon("accessories-screenshot") + }, + { + "End Session", + function() + awesome.emit_signal("module::exit_screen_show") + end, + menubar.utils.lookup_icon("system-shutdown") + } +} + +-- A menu generated by awesome-freedesktop +-- https://github.com/lcpz/awesome-freedesktop + +if is_module_available("freedesktop") then + + local freedesktop = require("freedesktop") + + mymainmenu = freedesktop.menu.build({ + -- Not actually the size, but the quality of the icon + icon_size = 48, + + before = default_app_menu, + after = tools_menu + }) + mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, menu = mymainmenu }) +else + + mymainmenu = awful.menu({ + + items = { + { + "Instructions", + function() + local naughty = require('naughty') + + local open_github = naughty.action { + name = 'Open Github Page', + icon_only = false, + } + + open_github:connect_signal('invoked', function() + awful.spawn.easy_async_with_shell("xdg-open https://github.com/lcpz/awesome-freedesktop") + end) + + local open_aur = naughty.action { + name = 'Open AUR Page', + icon_only = false, + } + + open_aur:connect_signal('invoked', function() + awful.spawn.easy_async_with_shell("xdg-open https://aur.archlinux.org/packages/awesome-freedesktop-git/") + end) + + naughty.notification({ + title = 'A dependency is missing!', + message = "You need to install awesome-freedesktop. " .. + "This will populate the menu with your installed applications automatically. " .. + "It is also available in AUR, it is called awesome-freedesktop-git.", + app_name = 'System Notification', + timeout = 0, + urgency = 'normal', + actions = { open_github, open_aur } + }) + end, + menubar.utils.lookup_icon("accessories-text-editor") + }, + { + "Awesome", + awesome_menu, + beautiful.awesome_icon + }, + { + "Take a Screenshot", + screenshot_menu, + menubar.utils.lookup_icon("accessories-screenshot") + }, + { + "End Session", + function() + awesome.emit_signal("module::exit_screen_show") + end, + menubar.utils.lookup_icon("system-shutdown") + } + } + }) +end \ No newline at end of file diff --git a/awesome/module/notifications.lua b/awesome/module/notifications.lua new file mode 100644 index 0000000..b32baa1 --- /dev/null +++ b/awesome/module/notifications.lua @@ -0,0 +1,262 @@ +local gears = require('gears') +local wibox = require('wibox') +local awful = require('awful') +local ruled = require('ruled') +local naughty = require('naughty') +local menubar = require("menubar") +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') + +-- Defaults +naughty.config.defaults.ontop = true +naughty.config.defaults.icon_size = dpi(32) +naughty.config.defaults.timeout = 5 +naughty.config.defaults.title = 'System Notification' +naughty.config.defaults.margin = dpi(16) +naughty.config.defaults.border_width = 0 +naughty.config.defaults.position = 'top_right' +naughty.config.defaults.shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, dpi(6)) end + +-- Apply theme variables + +naughty.config.padding = 8 +naughty.config.spacing = 8 +naughty.config.icon_dirs = { + "/usr/share/icons/Tela", + "/usr/share/icons/Tela-blue-dark", + "/usr/share/icons/Papirus/", + "/usr/share/icons/la-capitaine-icon-theme/", + "/usr/share/icons/gnome/", + "/usr/share/icons/hicolor/", + "/usr/share/pixmaps/" +} +naughty.config.icon_formats = { "svg", "png", "jpg", "gif" } + + +-- Presets / rules + +ruled.notification.connect_signal('request::rules', function() + + -- Critical notifs + ruled.notification.append_rule { + rule = { urgency = 'critical' }, + properties = { + font = 'SF Pro Text Bold 10', + bg = '#ff0000', + fg = '#ffffff', + margin = dpi(16), + position = 'top_right', + implicit_timeout = 0 + } + } + + -- Normal notifs + ruled.notification.append_rule { + rule = { urgency = 'normal' }, + properties = { + font = 'SF Pro Text Regular 10', + bg = beautiful.transparent, + fg = beautiful.fg_normal, + margin = dpi(16), + position = 'top_right', + implicit_timeout = 5 + } + } + + -- Low notifs + ruled.notification.append_rule { + rule = { urgency = 'low' }, + properties = { + font = 'SF Pro Text Regular 10', + bg = beautiful.transparent, + fg = beautiful.fg_normal, + margin = dpi(16), + position = 'top_right', + implicit_timeout = 5 + } + } +end) + + +-- Error handling +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, + app_name = 'System Notification', + icon = beautiful.awesome_icon + } + end +) + +-- XDG icon lookup +naughty.connect_signal( + "request::icon", + function(n, context, hints) + if context ~= "app_icon" then return end + + local path = menubar.utils.lookup_icon(hints.app_icon) or + menubar.utils.lookup_icon(hints.app_icon:lower()) + + if path then + n.icon = path + end + end +) + +-- Naughty template +naughty.connect_signal("request::display", function(n) + + -- naughty.actions template + local actions_template = wibox.widget { + notification = n, + base_layout = wibox.widget { + spacing = dpi(0), + layout = wibox.layout.flex.horizontal + }, + widget_template = { + { + { + { + { + id = 'text_role', + font = 'SF Pro Text Regular 10', + widget = wibox.widget.textbox + }, + widget = wibox.container.place + }, + widget = clickable_container + }, + bg = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + forced_height = dpi(30), + widget = wibox.container.background + }, + margins = dpi(4), + widget = wibox.container.margin + }, + style = { underline_normal = false, underline_selected = true }, + widget = naughty.list.actions + } + + -- Custom notification layout + naughty.layout.box { + notification = n, + type = "notification", + screen = awful.screen.preferred(), + shape = gears.shape.rectangle, + widget_template = { + { + { + { + { + { + { + { + { + { + { + { + markup = n.app_name or 'System Notification', + font = 'SF Pro Text Bold 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + + }, + margins = beautiful.notification_margin, + widget = wibox.container.margin, + }, + bg = '#000000'.. '44', + widget = wibox.container.background, + }, + { + { + { + resize_strategy = 'center', + widget = naughty.widget.icon, + }, + margins = beautiful.notification_margin, + widget = wibox.container.margin, + }, + { + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + { + align = 'left', + widget = naughty.widget.title + }, + { + align = "left", + widget = naughty.widget.message, + }, + layout = wibox.layout.fixed.vertical + }, + nil + }, + margins = beautiful.notification_margin, + widget = wibox.container.margin, + }, + layout = wibox.layout.fixed.horizontal, + }, + fill_space = true, + spacing = beautiful.notification_margin, + layout = wibox.layout.fixed.vertical, + }, + -- Margin between the fake background + -- Set to 0 to preserve the 'titlebar' effect + margins = dpi(0), + widget = wibox.container.margin, + }, + bg = beautiful.transparent, + widget = wibox.container.background, + }, + -- Notification action list + -- naughty.list.actions, + actions_template, + spacing = dpi(4), + layout = wibox.layout.fixed.vertical, + }, + bg = beautiful.transparent, + id = "background_role", + widget = naughty.container.background, + }, + strategy = "min", + width = dpi(160), + widget = wibox.container.constraint, + }, + strategy = "max", + width = beautiful.notification_max_width or dpi(500), + widget = wibox.container.constraint, + }, + -- Anti-aliasing container + -- Real BG + bg = beautiful.background, + -- This will be the anti-aliased shape of the notification + shape = gears.shape.rounded_rect, + widget = wibox.container.background + }, + -- Margin of the fake BG to have a space between notification and the screen edge + margins = dpi(5),--beautiful.notification_margin, + widget = wibox.container.margin + } + + } + + -- Destroy popups if dont_disturb mode is on + -- Or if the right_panel is visible + local focused = awful.screen.focused() + if _G.dont_disturb or (focused.right_panel and focused.right_panel.visible) then + naughty.destroy_all_notifications(nil, 1) + end + +end) diff --git a/awesome/module/quake-terminal.lua b/awesome/module/quake-terminal.lua new file mode 100644 index 0000000..6fa6633 --- /dev/null +++ b/awesome/module/quake-terminal.lua @@ -0,0 +1,73 @@ +local gears = require('gears') +local spawn = require('awful.spawn') +local app = require('configuration.apps').default.quake +-- local awful = require('awful') + +local quake_id = 'notnil' +local quake_client +local opened = false +function create_shell() + quake_id = + spawn( + app, + { + skip_decoration = true + } + ) +end + +function open_quake() + quake_client.hidden = false + quake_client:emit_signal('request::activate') +end + +function close_quake() + quake_client.hidden = true +end + +toggle_quake = function() + opened = not opened + if not quake_client then + create_shell() + else + if opened then + open_quake() + else + close_quake() + end + end +end + +client.connect_signal( + 'manage', + function(c) + if c.pid == quake_id then + quake_client = c + c.opacity = 0.95 + c.floating = true + c.skip_taskbar = true + c.ontop = true + c.above = true + c.sticky = true + c.hidden = not opened + c.maximized_horizontal = true + c.hide_titlebars = true + c.skip_center = true + c.round_corners = false + c.shape = function(cr, w, h) + gears.shape.rectangle(cr, w, h) + end + -- awful.placement.top(c) + end + end +) + +client.connect_signal( + 'unmanage', + function(c) + if c.pid == quake_id then + opened = false + quake_client = nil + end + end +) \ No newline at end of file diff --git a/awesome/module/test.lua b/awesome/module/test.lua new file mode 100644 index 0000000..6785ed0 --- /dev/null +++ b/awesome/module/test.lua @@ -0,0 +1,30 @@ +-- Load these libraries (if you haven't already) +local awful = require("awful") +local gears = require("gears") +local wibox = require("wibox") + +-- Create the box +local anti_aliased_wibox = wibox({visible = true, ontop = true, type = "normal", height = 100, width = 100}) + +-- Place it at the center of the screen +awful.placement.centered(anti_aliased_wibox) + +-- Set transparent bg +anti_aliased_wibox.bg = beautiful.transparent + +-- Put its items in a shaped container +anti_aliased_wibox:setup { + -- Container + { + -- Items go here + --wibox.widget.textbox("Hello!"), + awful.spawn('urxvt'), + -- ... + layout = wibox.layout.fixed.vertical + }, + -- The real background color + bg = "#111111", + -- The real, anti-aliased shape + shape = gears.shape.rounded_rect, + widget = wibox.container.background() +} diff --git a/awesome/module/titlebar.lua b/awesome/module/titlebar.lua new file mode 100644 index 0000000..2794a54 --- /dev/null +++ b/awesome/module/titlebar.lua @@ -0,0 +1,282 @@ +local awful = require("awful") +local gears = require("gears") +local beautiful = require("beautiful") +local wibox = require("wibox") + +local dpi = beautiful.xresources.apply_dpi + +awful.titlebar.enable_tooltip = false +awful.titlebar.fallback_name = 'Client\'s name' + + +local titlebar_size = beautiful.titlebar_size + + +-- ▄▄▄▄▄▄▄ ▀ ▄ ▀▀█ █ +-- █ ▄▄▄ ▄▄█▄▄ █ ▄▄▄ █▄▄▄ ▄▄▄ ▄ ▄▄ +-- █ █ █ █ █▀ █ █▀ ▀█ ▀ █ █▀ ▀ +-- █ █ █ █ █▀▀▀▀ █ █ ▄▀▀▀█ █ +-- █ ▄▄█▄▄ ▀▄▄ ▀▄▄ ▀█▄▄▀ ██▄█▀ ▀▄▄▀█ █ + + + +function double_click_event_handler(double_click_event) + if double_click_timer then + double_click_timer:stop() + double_click_timer = nil + + double_click_event() + + return + end + + double_click_timer = gears.timer.start_new(0.20, function() + double_click_timer = nil + return false + end) +end + + + +client.connect_signal("request::titlebars", function(c) + + -- Buttons for moving/resizing functionality + local buttons = gears.table.join( + awful.button( + {}, + 1, + function() + double_click_event_handler(function() + if c.floating then + c.floating = false + return + end + + c.maximized = not c.maximized + c:raise() + return + end) + + c:activate {context = "titlebar", action = "mouse_move"} + end + ), + awful.button( + {}, + 3, + function() + c:activate {context = "titlebar", action = "mouse_resize"} + end + ) + ) + + + local decorate_titlebar = function(c, pos, bg, size) + + c.titlebar_position = pos + + if pos == 'left' or pos == 'right' then + + -- Creates left or right titlebars + awful.titlebar(c, {position = pos, bg = bg, size = size or titlebar_size}) : setup { + { + { + awful.titlebar.widget.closebutton(c), + awful.titlebar.widget.maximizedbutton(c), + awful.titlebar.widget.minimizebutton (c), + spacing = dpi(7), + layout = wibox.layout.fixed.vertical + }, + margins = dpi(10), + widget = wibox.container.margin + }, + { + buttons = buttons, + layout = wibox.layout.flex.vertical + }, + { + awful.titlebar.widget.floatingbutton (c), + margins = dpi(10), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical + + } + + elseif pos == 'top' or pos == 'bottom' then + + -- Creates top or bottom titlebars + awful.titlebar(c, {position = pos, bg = bg, size = size or titlebar_size}) : setup { + { + { + awful.titlebar.widget.closebutton(c), + awful.titlebar.widget.maximizedbutton(c), + awful.titlebar.widget.minimizebutton (c), + spacing = dpi(7), + layout = wibox.layout.fixed.horizontal + }, + margins = dpi(10), + widget = wibox.container.margin + }, + { + buttons = buttons, + layout = wibox.layout.flex.horizontal + }, + { + awful.titlebar.widget.floatingbutton (c), + margins = dpi(10), + widget = wibox.container.margin + }, + layout = wibox.layout.align.horizontal + } + + else + + -- Create a left titlebar (default in this setup) + awful.titlebar(c, {position = 'left', size = titlebar_size}) : setup { + { + { + awful.titlebar.widget.closebutton(c), + awful.titlebar.widget.maximizedbutton(c), + awful.titlebar.widget.minimizebutton (c), + spacing = dpi(7), + layout = wibox.layout.fixed.vertical + }, + margins = dpi(10), + widget = wibox.container.margin + }, + { + buttons = buttons, + layout = wibox.layout.flex.vertical + }, + { + awful.titlebar.widget.floatingbutton (c), + margins = dpi(10), + widget = wibox.container.margin + }, + layout = wibox.layout.align.vertical + } + + end + + end + + -- ▄▄▄ ▄ ▀ + -- ▄▀ ▀ ▄ ▄ ▄▄▄ ▄▄█▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ ▄▄▄▄▄ ▄▄▄ + -- █ █ █ █ ▀ █ █▀ ▀█ █ █ █ █ ▄▀ █▀ █ + -- █ █ █ ▀▀▀▄ █ █ █ █ █ █ █ ▄▀ █▀▀▀▀ + -- ▀▄▄▄▀ ▀▄▄▀█ ▀▄▄▄▀ ▀▄▄ ▀█▄█▀ █ █ █ ▄▄█▄▄ █▄▄▄▄ ▀█▄▄▀ + + -- Generate a custom titlabar for each class, roles, type, etc., etc. + -- The titlebar's position can now be set differently + + if c.class == 'dolphin' or c.class == 'firefox' or c.class == 'pavucontrol-qt' or + c.instance == 'transmission-qt' or c.class == 'ark' or c.class == 'polkit-kde-authentication-agent-1' or + c.class == 'partitionmanager' or c.class == 'discord' or c.class == 'kdesu' then + + if c.type == 'dialog' or c.type == 'modal' then + decorate_titlebar(c, 'top', beautiful.background, titlebar_size) + else + decorate_titlebar(c, 'left', beautiful.background, titlebar_size) + end + + elseif c.role == "GtkFileChooserDialog" or c.type == 'dialog' or c.type == 'modal' then + + -- Let's use the gtk theme's bg_color as titlebar's bg then add some transparency + -- Let's set the titlebar's position to top + -- Isn't it neat? lol + decorate_titlebar(c, 'top', beautiful.gtk.get_theme_variables().bg_color:sub(1,7) .. '66', titlebar_size) + + elseif c.class == "kitty" then + + decorate_titlebar(c, 'left', '#000000AA', titlebar_size) + + elseif c.class == 'XTerm' or c.class == 'UXTerm' then + + -- Let's use the xresources' background color as the titlebar color for xterm + -- awesome is the shit boi! + decorate_titlebar(c, 'top', beautiful.xresources.get_current_theme().background, titlebar_size) + + elseif c.class == 'Nemo' then + + decorate_titlebar(c, 'left', beautiful.xresources.get_current_theme().background, titlebar_size) + + else + + -- Default titlebar + decorate_titlebar(c, 'left', beautiful.background, titlebar_size) + + end + +end) + + +-- ▄▄▄▄ ▀ ▀▀█ +-- █▀ ▀ ▄▄▄ ▄▄▄▄ ▄ ▄▄ ▄▄▄ █ ▄▄▄ +-- ▀█▄▄▄ █ █▀ ▀█ █▀ █ ▀ █ █ █ ▀ +-- ▀█ █ █ █ █ █ ▄▀▀▀█ █ ▀▀▀▄ +-- ▀▄▄▄█▀ ▄▄█▄▄ ▀█▄▀█ █ █ ▀▄▄▀█ ▀▄▄ ▀▄▄▄▀ +-- ▄ █ +-- ▀▀ + + +client.connect_signal( + "manage", + function(c) + + if not c.max and not c.hide_titlebars then + awful.titlebar.show(c, c.titlebar_position or 'left') + else + awful.titlebar.hide(c, c.titlebar_position or 'left') + end + + end +) + +-- Catch the signal when a client's layout is changed +screen.connect_signal( + "arrange", + function(s) + for _, c in pairs(s.clients) do + + if (#s.tiled_clients > 1 or c.floating) and c.first_tag.layout.name ~= 'max' then + + if not c.hide_titlebars then + awful.titlebar.show(c, c.titlebar_position or 'left') + else + awful.titlebar.hide(c, c.titlebar_position or 'left') + end + + if c.maximized or not c.round_corners or c.fullscreen then + c.shape = function(cr, w, h) + gears.shape.rectangle(cr, w, h) + end + else + c.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.client_radius) + end + end + + elseif (#s.tiled_clients == 1 or c.first_tag.layout.name == 'max') and not c.fullscreen then + + awful.titlebar.hide(c, c.titlebar_position or 'left') + + c.shape = function(cr, w, h) + gears.shape.rectangle(cr, w, h) + end + + end + + end + end +) + + +client.connect_signal("property::maximized", function(c) + c.shape = gears.shape.rectangle + + if not c.maximized then + c.shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.client_radius) + end + end +end) \ No newline at end of file diff --git a/awesome/module/volume-osd.lua b/awesome/module/volume-osd.lua new file mode 100644 index 0000000..681fdec --- /dev/null +++ b/awesome/module/volume-osd.lua @@ -0,0 +1,272 @@ +local awful = require("awful") +local gears = require("gears") +local wibox = require("wibox") +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') +local icons = require('theme.icons') +local spawn = require('awful.spawn') + +screen.connect_signal("request::desktop_decoration", function(s) + + s.show_vol_osd = false + + local osd_header = wibox.widget { + text = 'Volume', + font = 'VictorMono Nerd Font 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + } + + local osd_value = wibox.widget { + text = '0%', + font = 'VictorMono Nerd Font 11', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + local slider_osd = wibox.widget { + nil, + { + id = 'vol_osd_slider', + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(2), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + } + + local vol_osd_slider = slider_osd.vol_osd_slider + + -- Update volume level using slider value + vol_osd_slider:connect_signal( + 'property::value', + function() + + local volume_level = vol_osd_slider:get_value() + + spawn('amixer -D pulse sset Master ' .. volume_level .. '%', false) + + -- Update textbox widget text + osd_value.text = volume_level .. '%' + + -- Update the volume slider if values here change + awesome.emit_signal('widget::volume:update', volume_level) + + if s.show_vol_osd then + awesome.emit_signal( + 'module::volume_osd:show', + true + ) + end + + end + ) + + vol_osd_slider:connect_signal( + 'button::press', + function() + s.show_vol_osd = true + end + ) + vol_osd_slider:connect_signal( + 'button::release', + function() + s.show_vol_osd = false + end + ) + vol_osd_slider:connect_signal( + 'mouse::enter', + function() + s.show_vol_osd = true + end + ) + + -- The emit will come from the volume-slider + awesome.connect_signal( + 'module::volume_osd', + function(volume) + vol_osd_slider:set_value(volume) + end + ) + + local icon = wibox.widget { + { + image = icons.volume, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + } + + local volume_slider_osd = wibox.widget { + icon, + slider_osd, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + } + + -- Create the box + local osd_height = dpi(100) + local osd_width = dpi(300) + + local osd_margin = dpi(10) + + s.volume_osd_overlay = awful.popup { + widget = { + -- Removing this block will cause an error... + }, + ontop = true, + visible = false, + type = 'notification', + screen = s, + height = osd_height, + width = osd_width, + maximum_height = osd_height, + maximum_width = osd_width, + offset = dpi(5), + shape = gears.shape.rectangle, + bg = beautiful.transparent, + preferred_anchors = 'middle', + preferred_positions = {'left', 'right', 'top', 'bottom'}, + + } + + s.volume_osd_overlay : setup { + { + { + { + layout = wibox.layout.align.horizontal, + expand = 'none', + forced_height = dpi(48), + osd_header, + nil, + osd_value + }, + volume_slider_osd, + layout = wibox.layout.fixed.vertical + }, + left = dpi(24), + right = dpi(24), + widget = wibox.container.margin + + }, + bg = beautiful.background, + shape = gears.shape.rounded_rect, + widget = wibox.container.background() + } + + + local hide_osd = gears.timer { + timeout = 2, + autostart = true, + callback = function() + awful.screen.focused().volume_osd_overlay.visible = false + end + } + + local timer_rerun = function() + if hide_osd.started then + hide_osd:again() + else + hide_osd:start() + end + end + + -- Reset timer on mouse hover + s.volume_osd_overlay:connect_signal( + 'mouse::enter', + function() + s.show_vol_osd = true + timer_rerun() + end + ) + s.volume_osd_overlay:connect_signal( + 'mouse::leave', + function() + s.show_vol_osd = false + end + ) + + local placement_placer = function() + + local focused = awful.screen.focused() + + local right_panel = focused.right_panel + local left_panel = focused.left_panel + local volume_osd = focused.volume_osd_overlay + + if right_panel and left_panel then + if right_panel.visible then + awful.placement.bottom_left(focused.volume_osd_overlay, { margins = { + left = osd_margin + left_panel.width, + right = 0, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + return + end + end + + if right_panel then + if right_panel.visible then + awful.placement.bottom_left(focused.volume_osd_overlay, { margins = { + left = osd_margin, + right = 0, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + return + end + end + + awful.placement.bottom_right(focused.volume_osd_overlay, { margins = { + left = 0, + right = osd_margin, + top = 0, + bottom = osd_margin, + }, + parent = focused } + ) + end + + awesome.connect_signal( + 'module::volume_osd:show', + function(bool) + placement_placer() + awful.screen.focused().volume_osd_overlay.visible = bool + if bool then + timer_rerun() + awesome.emit_signal( + 'module::brightness_osd:show', + false + ) + else + if hide_osd.started then + hide_osd:stop() + end + end + end + ) + +end) diff --git a/awesome/rc.lua b/awesome/rc.lua index 4b79bc9..d94e53e 100644 --- a/awesome/rc.lua +++ b/awesome/rc.lua @@ -18,6 +18,39 @@ local hotkeys_popup = require("awful.hotkeys_popup") -- when client with a matching name is opened: require("awful.hotkeys_popup.keys") + +-- Widgets to add +-- local batteryarc_widget = require("awesome-wm-widget.batteryarc-widget.batteryarc") + +-- >> Daemons +-- Most widgets that display system/external info depend on evil. +-- Make sure to initialize it last in order to allow all widgets to connect to +-- their needed evil signals. +-- require("evil") +-- =================================================================== +-- =================================================================== + + +-- ======================================== +-- Modules +-- Load all the modules +-- ======================================== + +require('module.notifications') +-- require('module.auto-start') +require('module.decorate-client') +require('module.backdrop') +-- require('module.exit-screen') +-- require('module.quake-terminal') +-- require('module.titlebar') +-- require('module.menu') +require('module.volume-osd') +require('module.brightness-osd') +require('module.dynamic-wallpaper') +-- require('module.battery-notifier') +-- require('module.lockscreen') + + -- {{{ Error handling -- Check if awesome encountered an error during startup and fell back to -- another config (This code will only ever execute for the fallback config) @@ -107,7 +140,7 @@ mykeyboardlayout = awful.widget.keyboardlayout() -- {{{ Wibar -- Create a textclock widget -mytextclock = wibox.widget.textclock() +mytextclock = wibox.widget.textclock(" %a %b %d, %l:%M %p ") -- Create a wibox for each screen and add it local taglist_buttons = gears.table.join( @@ -192,30 +225,91 @@ awful.screen.connect_for_each_screen(function(s) s.mysystray = wibox.widget.systray() -- Create a tasklist widget - s.mytasklist = awful.widget.tasklist { - screen = s, - filter = awful.widget.tasklist.filter.currenttags, - buttons = tasklist_buttons - } + -- s.mytasklist = awful.widget.tasklist { + -- screen = s, + -- filter = awful.widget.tasklist.filter.currenttags, + -- buttons = tasklist_buttons + -- style = + -- } + s.mytasklist = awful.widget.tasklist { + screen = s, + filter = awful.widget.tasklist.filter.currenttags, + buttons = tasklist_buttons, + style = { + border_width = 0, + border_color = '#777777', + shape = gears.shape.rounded_bar, + + }, + layout = { + spacing = 20, + spacing_widget = { + { + forced_width = 5, + forced_height = 30, + -- shape = gears.shape.circle, + widget = wibox.widget.separator + }, + valign = 'center', + halign = 'center', + widget = wibox.container.place, + }, + layout = wibox.layout.flex.horizontal + }, + -- notice that there is *no* wibox.wibox prefix, it is a template, + -- not a widget instance. + widget_template = { + { + { + { + { + id = 'icon_role', + widget = wibox.widget.imagebox, + }, + margins = 4, + widget = wibox.container.margin, + }, + { + id = 'text_role', + widget = wibox.widget.textbox, + }, + layout = wibox.layout.align.horizontal, + }, + left = 10, + right = 10, + widget = wibox.container.margin + }, + id = 'background_role', + widget = wibox.container.background, + }, + } -- Create the wibox s.mywibox = awful.wibar({ position = "bottom", screen = s }) + -- Create Battery, Network, and Volume widget + s.battery = require('widget.battery')() + s.network = require('widget.network')() + -- s.volume = require('widget.volume-slider')() + s.updater = require('widget.package-updater')() -- Add widgets to the wibox s.mywibox:setup { layout = wibox.layout.align.horizontal, { -- Left widgets layout = wibox.layout.fixed.horizontal, - mylauncher, - s.mytaglist, + wibox.container.margin (s.mytaglist,25,0,0,0), s.mypromptbox, }, - s.mytasklist, -- Middle widget + wibox.container.margin (s.mytasklist,35,35,0,0), -- Middle widget { -- Right widgets layout = wibox.layout.fixed.horizontal, s.mysystray, + -- s.volume, + s.updater, + s.network, + s.battery, mytextclock, - s.mylayoutbox, + wibox.container.margin (s.mylayoutbox,0,25,0,0), }, } end) @@ -275,6 +369,11 @@ globalkeys = gears.table.join( end, {description = "go back", group = "client"}), + + -- Screenshots + awful.key({}, "Print", function() awful.util.spawn("flameshot gui") end, + {description = "take a screenshot", group = "screen"}), + -- Increase-Decrease Gap awful.key({ modkey, Mod1 }, "k", function () awful.tag.incgap ( 1, null) end, @@ -321,8 +420,42 @@ globalkeys = gears.table.join( end, {description = "restore minimized", group = "client"}), + -- Volume Keys + awful.key({}, "XF86AudioLowerVolume", function () + awful.util.spawn("amixer -q -D pulse sset Master 5%-", false) + end), + awful.key({}, "XF86AudioRaiseVolume", function () + awful.util.spawn("amixer -q -D pulse sset Master 5%+", false) + end), + awful.key({}, "XF86AudioMute", function () + awful.util.spawn("amixer -D pulse set Master 1+ toggle", false) + end), + -- Media Keys + awful.key({}, "XF86AudioPlay", function() + awful.util.spawn("playerctl play-pause", false) + end), + awful.key({}, "XF86AudioNext", function() + awful.util.spawn("playerctl next", false) + end), + awful.key({}, "XF86AudioPrev", function() + awful.util.spawn("playerctl previous", false) + end), + + -- Brightness Keys + awful.key({}, "XF86MonBrightnessUp", function() + awful.util.spawn("brightnessctl set +10%", false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show', true) + end), + + awful.key({}, "XF86MonBrightnessDown", function() + awful.util.spawn("brightnessctl set 10%-", false) + awesome.emit_signal('widget::brightness') + awesome.emit_signal('module::brightness_osd:show', true) + end), + -- Prompt - awful.key({ modkey }, "r", function () + awful.key({ }, "Menu", function () awful.util.spawn("/home/chris/.dotfiles/rofi/launchers-git/launcher.sh") end, {description = "launch rofi", group = "launcher"}), @@ -502,12 +635,15 @@ awful.rules.rules = { -- Add titlebars to normal clients and dialogs { rule_any = {type = { "normal", "dialog" } - }, properties = { titlebars_enabled = true } + }, properties = { titlebars_enabled = false } }, -- Set Firefox to always map on the tag named "2" on screen 1. - -- { rule = { class = "Firefox" }, - -- properties = { screen = 1, tag = "2" } }, + { rule = { class = "Firefox" }, + properties = { screen = 1, tag = "2", + maximized_vertical = true, + maximized_horizontal = true, + } }, } -- }}} @@ -578,5 +714,6 @@ client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_n -- Autostart Applications awful.spawn.with_shell("picom") -awful.spawn.with_shell("nitrogen --restore") --- awful.spawn.with_shell("polybarstart") +awful.spawn.with_shell("feh --bg-fill /home/chris/Pictures/royalking.png") +awful.spawn.with_shell("libinput-gestures-setup start") +awful.spawn.with_shell("flameshot") diff --git a/awesome/theme.lua b/awesome/theme.lua index 919bc48..fe6ce56 100644 --- a/awesome/theme.lua +++ b/awesome/theme.lua @@ -9,10 +9,12 @@ local gears = require('gears') local gfs = require("gears.filesystem") local themes_path = gfs.get_themes_dir() +-- local theme_dir = filesystem.get_configuration_dir() .. '/theme' local theme = {} -theme.font = "Rec Mono Linear 10" +theme.font = "VictorMono Nerd Font 10" +-- theme.icons = theme_dir .. '/icons/' theme.bg_normal = "#282a36" theme.bg_focus = "#43454f" @@ -25,8 +27,10 @@ theme.fg_focus = "#e2e4e5" theme.fg_urgent = "#e2e4e5" theme.fg_minimize = "#e2e4e5" +theme.red = "#ff5c57" + theme.useless_gap = dpi(8) -theme.border_width = dpi(1) +theme.border_width = dpi(0) theme.border_normal = "#00000000" theme.border_focus = "#00000000" theme.border_marked = "#00000000" @@ -45,7 +49,7 @@ theme.border_marked = "#00000000" --theme.taglist_bg_focus = "#ff0000" -- Generate taglist squares: -local taglist_square_size = dpi(4) +local taglist_square_size = dpi(8) theme.taglist_squares_sel = theme_assets.taglist_squares_sel( taglist_square_size, theme.fg_normal ) @@ -53,6 +57,14 @@ theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel( taglist_square_size, theme.fg_normal ) +-- Tasklists +theme.tasklist_shape = gears.shape.rounded_bar +theme.tasklist_spacing = 40 +theme.tasklist_align = "center" + +theme.tasklist_bg = theme.red + + -- Variables set for theming notifications: -- notification_font -- notification_[bg|fg] @@ -77,7 +89,7 @@ theme.wibar_bg = theme.bg_normal -- theme.wibar_y = 1030 theme.wibar_x = 0 -- theme.wibar_stretch = false -theme.wibar_border_width = 3 +theme.wibar_border_width = dpi(5) theme.wibar_border_color = nil -- theme.wibar_ontop = nil -- theme.wibar_cursor = nil @@ -142,6 +154,7 @@ theme.awesome_icon = theme_assets.awesome_icon( theme.menu_height, theme.bg_focus, theme.fg_focus ) +-- theme.awesome_icon = theme.icons .. 'awesome.svg' -- Define the icon theme for application icons. If not set then the icons -- from /usr/share/icons and /usr/share/icons/hicolor will be used. theme.icon_theme = nil diff --git a/awesome/theme/default-theme.lua b/awesome/theme/default-theme.lua new file mode 100644 index 0000000..ceca1fc --- /dev/null +++ b/awesome/theme/default-theme.lua @@ -0,0 +1,231 @@ +local gears = require('gears') +local beautiful = require('beautiful') + +local filesystem = require('gears.filesystem') +local dpi = require('beautiful').xresources.apply_dpi + +local theme_dir = filesystem.get_configuration_dir() .. '/theme' + +local titlebar_theme = "stoplight" +local titlebar_icon_path = theme_dir .. "/icons/titlebar/" .. titlebar_theme .. '/' +local tip = titlebar_icon_path + + +local theme = {} +theme.icons = theme_dir .. '/icons/' + +-- Font +theme.font = 'SF Pro Text Regular 10' +theme.font_bold = 'SF Pro Text Bold 10' + + +-- Menu icon theme +theme.icon_theme = 'Tela-blue-dark' + + +local awesome_overrides = function(theme) + + theme.dir = theme_dir + + theme.icons = theme.dir .. '/icons/' + + -- Wallpaper + + theme.wallpaper = theme.dir .. '/wallpapers/morning-wallpaper.jpg' + + -- Foreground + + theme.font = 'SF Pro Text Regular 10' + theme.title_font = 'SF Pro Text Bold 14' + + + theme.fg_normal = '#ffffffde' + theme.fg_focus = '#e4e4e4' + theme.fg_urgent = '#CC9393' + + theme.bat_fg_critical = '#232323' + + theme.bg_normal = theme.background + theme.bg_focus = '#5a5a5a' + theme.bg_urgent = '#3F3F3F' + + -- System tray + + theme.bg_systray = theme.background + theme.systray_icon_spacing = dpi(16) + + -- Titlebar + + theme.titlebar_size = dpi(34) + theme.titlebar_bg_focus = beautiful.gtk.get_theme_variables().bg_color:sub(1,7) .. '66' + theme.titlebar_bg_normal = beautiful.gtk.get_theme_variables().base_color:sub(1,7) .. '66' + theme.titlebar_fg_focus = beautiful.gtk.get_theme_variables().fg_color .. '00' + theme.titlebar_fg_normal = beautiful.gtk.get_theme_variables().fg_color .. '00' + + -- Close Button + theme.titlebar_close_button_normal = tip .. "close_normal.svg" + theme.titlebar_close_button_focus = tip .. "close_focus.svg" + + -- Minimize Button + theme.titlebar_minimize_button_normal = tip .. "minimize_normal.svg" + theme.titlebar_minimize_button_focus = tip .. "minimize_focus.svg" + + -- Ontop Button + theme.titlebar_ontop_button_normal_inactive = tip .. "ontop_normal_inactive.svg" + theme.titlebar_ontop_button_focus_inactive = tip .. "ontop_focus_inactive.svg" + theme.titlebar_ontop_button_normal_active = tip .. "ontop_normal_active.svg" + theme.titlebar_ontop_button_focus_active = tip .. "ontop_focus_active.svg" + + -- Sticky Button + theme.titlebar_sticky_button_normal_inactive = tip .. "sticky_normal_inactive.svg" + theme.titlebar_sticky_button_focus_inactive = tip .. "sticky_focus_inactive.svg" + theme.titlebar_sticky_button_normal_active = tip .. "sticky_normal_active.svg" + theme.titlebar_sticky_button_focus_active = tip .. "sticky_focus_active.svg" + + -- Floating Button + theme.titlebar_floating_button_normal_inactive = tip .. "floating_normal_inactive.svg" + theme.titlebar_floating_button_focus_inactive = tip .. "floating_focus_inactive.svg" + theme.titlebar_floating_button_normal_active = tip .. "floating_normal_active.svg" + theme.titlebar_floating_button_focus_active = tip .. "floating_focus_active.svg" + + -- Maximized Button + theme.titlebar_maximized_button_normal_inactive = tip .. "maximized_normal_inactive.svg" + theme.titlebar_maximized_button_focus_inactive = tip .. "maximized_focus_inactive.svg" + theme.titlebar_maximized_button_normal_active = tip .. "maximized_normal_active.svg" + theme.titlebar_maximized_button_focus_active = tip .. "maximized_focus_active.svg" + + -- Hovered Close Button + theme.titlebar_close_button_normal_hover = tip .. "close_normal_hover.svg" + theme.titlebar_close_button_focus_hover = tip .. "close_focus_hover.svg" + + -- Hovered Minimize Buttin + theme.titlebar_minimize_button_normal_hover = tip .. "minimize_normal_hover.svg" + theme.titlebar_minimize_button_focus_hover = tip .. "minimize_focus_hover.svg" + + -- Hovered Ontop Button + theme.titlebar_ontop_button_normal_inactive_hover = tip .. "ontop_normal_inactive_hover.svg" + theme.titlebar_ontop_button_focus_inactive_hover = tip .. "ontop_focus_inactive_hover.svg" + theme.titlebar_ontop_button_normal_active_hover = tip .. "ontop_normal_active_hover.svg" + theme.titlebar_ontop_button_focus_active_hover = tip .. "ontop_focus_active_hover.svg" + + -- Hovered Sticky Button + theme.titlebar_sticky_button_normal_inactive_hover = tip .. "sticky_normal_inactive_hover.svg" + theme.titlebar_sticky_button_focus_inactive_hover = tip .. "sticky_focus_inactive_hover.svg" + theme.titlebar_sticky_button_normal_active_hover = tip .. "sticky_normal_active_hover.svg" + theme.titlebar_sticky_button_focus_active_hover = tip .. "sticky_focus_active_hover.svg" + + -- Hovered Floating Button + theme.titlebar_floating_button_normal_inactive_hover = tip .. "floating_normal_inactive_hover.svg" + theme.titlebar_floating_button_focus_inactive_hover = tip .. "floating_focus_inactive_hover.svg" + theme.titlebar_floating_button_normal_active_hover = tip .. "floating_normal_active_hover.svg" + theme.titlebar_floating_button_focus_active_hover = tip .. "floating_focus_active_hover.svg" + + -- Hovered Maximized Button + theme.titlebar_maximized_button_normal_inactive_hover = tip .. "maximized_normal_inactive_hover.svg" + theme.titlebar_maximized_button_focus_inactive_hover = tip .. "maximized_focus_inactive_hover.svg" + theme.titlebar_maximized_button_normal_active_hover = tip .. "maximized_normal_active_hover.svg" + theme.titlebar_maximized_button_focus_active_hover = tip .. "maximized_focus_active_hover.svg" + + -- UI Groups + + theme.groups_title_bg = "#ffffff" .. "15" + theme.groups_bg = "#ffffff" .. "10" + theme.groups_radius = dpi(9) + + -- Client Decorations + + -- Borders + theme.border_focus = beautiful.gtk.get_theme_variables().bg_color + theme.border_normal = beautiful.gtk.get_theme_variables().base_color + theme.border_marked = '#CC9393' + theme.border_width = dpi(0) + theme.border_radius = dpi(0) + + -- Decorations + theme.client_radius = dpi(9) + theme.useless_gap = dpi(4) + + -- Menu + theme.menu_font = "SF Pro Text Regular 11" + theme.menu_submenu = '' -- ➤ + + theme.menu_height = dpi(34) + theme.menu_width = dpi(200) + theme.menu_border_width = dpi(20) + theme.menu_bg_focus = theme.accent .. 'CC' + + theme.menu_bg_normal = theme.background:sub(1,7) .. '33' + theme.menu_fg_normal = '#ffffff' + theme.menu_fg_focus = '#ffffff' + theme.menu_border_color = theme.background:sub(1,7) .. '5C' + + -- Tooltips + + theme.tooltip_bg = theme.background + theme.tooltip_border_color = theme.transparent + theme.tooltip_border_width = 0 + theme.tooltip_gaps = dpi(5) + theme.tooltip_shape = function(cr, w, h) + gears.shape.rounded_rect(cr, w, h, dpi(6)) + end + + -- Separators + + theme.separator_color = '#f2f2f244' + + -- Layoutbox icons + + theme.layout_max = theme.icons .. 'layouts/max.svg' + theme.layout_tile = theme.icons .. 'layouts/tile.svg' + theme.layout_dwindle = theme.icons .. 'layouts/dwindle.svg' + theme.layout_floating = theme.icons .. 'layouts/floating.svg' + + -- Taglist + + theme.taglist_bg_empty = theme.background .. '99' + theme.taglist_bg_occupied = '#ffffff' .. '1A' + theme.taglist_bg_urgent = "#E91E63" .. '99' + theme.taglist_bg_focus = theme.background + theme.taglist_spacing = dpi(0) + + -- Tasklist + + theme.tasklist_font = 'SF Pro Text Regular 10' + theme.tasklist_bg_normal = theme.background .. '99' + theme.tasklist_bg_focus = theme.background + theme.tasklist_bg_urgent = "#E91E63" .. '99' + theme.tasklist_fg_focus = '#DDDDDD' + theme.tasklist_fg_urgent = "#ffffff" + theme.tasklist_fg_normal = '#AAAAAA' + + -- Notification + + theme.notification_position = 'top_right' + theme.notification_bg = theme.transparent + theme.notification_margin = dpi(5) + theme.notification_border_width = dpi(0) + theme.notification_border_color = theme.transparent + theme.notification_spacing = dpi(0) + theme.notification_icon_resize_strategy = 'center' + theme.notification_icon_size = dpi(32) + + -- Client Snap Theme + + theme.snap_bg = theme.background + theme.snap_shape = gears.shape.rectangle + theme.snap_border_width = dpi(15) + + -- Hotkey popup + + theme.hotkeys_font = 'SF Pro Text Bold' + theme.hotkeys_description_font = 'SF Pro Text Regular Regular' + theme.hotkeys_bg = theme.background + theme.hotkeys_group_margin = dpi(20) + + +end + +return { + theme = theme, + awesome_overrides = awesome_overrides +} diff --git a/awesome/theme/floppy-theme/init.lua b/awesome/theme/floppy-theme/init.lua new file mode 100644 index 0000000..82e2364 --- /dev/null +++ b/awesome/theme/floppy-theme/init.lua @@ -0,0 +1,54 @@ +local filesystem = require('gears.filesystem') +local theme_dir = filesystem.get_configuration_dir() .. '/theme' + +local theme = {} + +theme.icons = theme_dir .. '/icons/' +theme.font = 'SF Pro Text Regular 10' +theme.font_bold = 'SF Pro Text Bold 10' + + +-- Colorscheme +theme.system_black_dark = '#3D4C5F' +theme.system_black_light = '#56687E' + +theme.system_red_dark = '#EE4F84' +theme.system_red_light = '#F48FB1' + +theme.system_green_dark = '#53E2AE' +theme.system_green_light = '#A1EFD3' + +theme.system_yellow_dark = '#F1FF52' +theme.system_yellow_light = '#F1FA8C' + +theme.system_blue_dark = '#6498EF' +theme.system_blue_light = '#92B6F4' + +theme.system_magenta_dark = '#985EFF' +theme.system_magenta_light = '#BD99FF' + +theme.system_cyan_dark = '#24D1E7' +theme.system_cyan_light = '#87DFEB' + +theme.system_white_dark = '#E5E5E5' +theme.system_white_light = '#F8F8F2' + + +-- Accent color +theme.accent = theme.system_blue_dark + +-- Background color +theme.background = '#000000' .. '66' + +-- Transparent +theme.transparent = '#00000000' + +-- Awesome icon +theme.awesome_icon = theme.icons .. 'awesome.svg' + +local awesome_overrides = function(theme) end + +return { + theme = theme, + awesome_overrides = awesome_overrides +} diff --git a/awesome/theme/icons/awesome.svg b/awesome/theme/icons/awesome.svg new file mode 100644 index 0000000..31d715c --- /dev/null +++ b/awesome/theme/icons/awesome.svg @@ -0,0 +1,68 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/battery-charge.svg b/awesome/theme/icons/battery-charge.svg new file mode 100644 index 0000000..f8efe9c --- /dev/null +++ b/awesome/theme/icons/battery-charge.svg @@ -0,0 +1,58 @@ + +image/svg+xml + + + + \ No newline at end of file diff --git a/awesome/theme/icons/battery-discharge.svg b/awesome/theme/icons/battery-discharge.svg new file mode 100644 index 0000000..908ce15 --- /dev/null +++ b/awesome/theme/icons/battery-discharge.svg @@ -0,0 +1,63 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/brightness-7.svg b/awesome/theme/icons/brightness-7.svg new file mode 100644 index 0000000..862549e --- /dev/null +++ b/awesome/theme/icons/brightness-7.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/chart-areaspline.svg b/awesome/theme/icons/chart-areaspline.svg new file mode 100644 index 0000000..58bf0d3 --- /dev/null +++ b/awesome/theme/icons/chart-areaspline.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/close.svg b/awesome/theme/icons/close.svg new file mode 100644 index 0000000..bd89d79 --- /dev/null +++ b/awesome/theme/icons/close.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/effects.svg b/awesome/theme/icons/effects.svg new file mode 100644 index 0000000..e6c514b --- /dev/null +++ b/awesome/theme/icons/effects.svg @@ -0,0 +1,91 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/harddisk.svg b/awesome/theme/icons/harddisk.svg new file mode 100644 index 0000000..4c23f54 --- /dev/null +++ b/awesome/theme/icons/harddisk.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/init.lua b/awesome/theme/icons/init.lua new file mode 100644 index 0000000..5cf636b --- /dev/null +++ b/awesome/theme/icons/init.lua @@ -0,0 +1,42 @@ +-- Icons directory +local dir = os.getenv('HOME') .. '/.config/awesome/theme/icons/' + + +return { + + -- Action Bar + web_browser = dir .. 'tag-list/' .. 'web-browser.svg', + text_editor = dir .. 'tag-list/' .. 'text-editor.svg', + social = dir .. 'tag-list/' .. 'social.svg', + file_manager = dir .. 'tag-list/' .. 'file-manager.svg', + multimedia = dir .. 'tag-list/' .. 'multimedia.svg', + games = dir .. 'tag-list/' .. 'games.svg', + development = dir .. 'tag-list/' .. 'development.svg', + sandbox = dir .. 'tag-list/' .. 'sandbox.svg', + terminal = dir .. 'tag-list/' .. 'terminal.svg', + graphics = dir .. 'tag-list/' .. 'graphics.svg', + menu = dir .. 'tag-list/' .. 'menu.svg', + close_small = dir .. 'tag-list/' .. 'close-small.svg', + + -- Others/System UI + close = dir .. 'close.svg', + logout = dir .. 'logout.svg', + sleep = dir .. 'power-sleep.svg', + power = dir .. 'power.svg', + lock = dir .. 'lock.svg', + restart = dir .. 'restart.svg', + search = dir .. 'magnify.svg', + volume = dir .. 'volume-high.svg', + brightness = dir .. 'brightness-7.svg', + effects = dir .. 'effects.svg', + chart = dir .. 'chart-areaspline.svg', + memory = dir .. 'memory.svg', + harddisk = dir .. 'harddisk.svg', + thermometer = dir .. 'thermometer.svg', + plus = dir .. 'plus.svg', + batt_charging = dir .. 'battery-charge.svg', + batt_discharging = dir .. 'battery-discharge.svg', + toggled_on = dir .. 'toggled-on.svg', + toggled_off = dir .. 'toggled-off.svg' + +} diff --git a/awesome/theme/icons/layouts/dwindle.svg b/awesome/theme/icons/layouts/dwindle.svg new file mode 100644 index 0000000..9e59058 --- /dev/null +++ b/awesome/theme/icons/layouts/dwindle.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/layouts/floating.svg b/awesome/theme/icons/layouts/floating.svg new file mode 100644 index 0000000..5dcd846 --- /dev/null +++ b/awesome/theme/icons/layouts/floating.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/layouts/fullscreen.svg b/awesome/theme/icons/layouts/fullscreen.svg new file mode 100644 index 0000000..6ba320b --- /dev/null +++ b/awesome/theme/icons/layouts/fullscreen.svg @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/awesome/theme/icons/layouts/max.svg b/awesome/theme/icons/layouts/max.svg new file mode 100644 index 0000000..f1b2b2d --- /dev/null +++ b/awesome/theme/icons/layouts/max.svg @@ -0,0 +1,62 @@ + + + + + + + image/svg+xml + + + + + + + + diff --git a/awesome/theme/icons/layouts/tile.svg b/awesome/theme/icons/layouts/tile.svg new file mode 100644 index 0000000..ea62c5d --- /dev/null +++ b/awesome/theme/icons/layouts/tile.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/lock.svg b/awesome/theme/icons/lock.svg new file mode 100644 index 0000000..ac383ed --- /dev/null +++ b/awesome/theme/icons/lock.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/logout.svg b/awesome/theme/icons/logout.svg new file mode 100644 index 0000000..4689c49 --- /dev/null +++ b/awesome/theme/icons/logout.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/magnify.svg b/awesome/theme/icons/magnify.svg new file mode 100644 index 0000000..40d9c1a --- /dev/null +++ b/awesome/theme/icons/magnify.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/memory.svg b/awesome/theme/icons/memory.svg new file mode 100644 index 0000000..0cf4b10 --- /dev/null +++ b/awesome/theme/icons/memory.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/plus.svg b/awesome/theme/icons/plus.svg new file mode 100644 index 0000000..737cad4 --- /dev/null +++ b/awesome/theme/icons/plus.svg @@ -0,0 +1,58 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/power-sleep.svg b/awesome/theme/icons/power-sleep.svg new file mode 100644 index 0000000..a4dbfc0 --- /dev/null +++ b/awesome/theme/icons/power-sleep.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/power.svg b/awesome/theme/icons/power.svg new file mode 100644 index 0000000..770943b --- /dev/null +++ b/awesome/theme/icons/power.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/restart.svg b/awesome/theme/icons/restart.svg new file mode 100644 index 0000000..f0c3367 --- /dev/null +++ b/awesome/theme/icons/restart.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/ship-wheel.svg b/awesome/theme/icons/ship-wheel.svg new file mode 100644 index 0000000..5237ed3 --- /dev/null +++ b/awesome/theme/icons/ship-wheel.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/close-small.svg b/awesome/theme/icons/tag-list/close-small.svg new file mode 100644 index 0000000..f244bae --- /dev/null +++ b/awesome/theme/icons/tag-list/close-small.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/development.svg b/awesome/theme/icons/tag-list/development.svg new file mode 100644 index 0000000..773a538 --- /dev/null +++ b/awesome/theme/icons/tag-list/development.svg @@ -0,0 +1,174 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/file-manager.svg b/awesome/theme/icons/tag-list/file-manager.svg new file mode 100644 index 0000000..ba04747 --- /dev/null +++ b/awesome/theme/icons/tag-list/file-manager.svg @@ -0,0 +1,138 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/games.svg b/awesome/theme/icons/tag-list/games.svg new file mode 100644 index 0000000..6314387 --- /dev/null +++ b/awesome/theme/icons/tag-list/games.svg @@ -0,0 +1,103 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/graphics.svg b/awesome/theme/icons/tag-list/graphics.svg new file mode 100644 index 0000000..caefefb --- /dev/null +++ b/awesome/theme/icons/tag-list/graphics.svg @@ -0,0 +1,150 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/menu.svg b/awesome/theme/icons/tag-list/menu.svg new file mode 100644 index 0000000..c95ecd7 --- /dev/null +++ b/awesome/theme/icons/tag-list/menu.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/menu2.svg b/awesome/theme/icons/tag-list/menu2.svg new file mode 100644 index 0000000..3e82e3d --- /dev/null +++ b/awesome/theme/icons/tag-list/menu2.svg @@ -0,0 +1,123 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/multimedia.svg b/awesome/theme/icons/tag-list/multimedia.svg new file mode 100644 index 0000000..ff5f5b0 --- /dev/null +++ b/awesome/theme/icons/tag-list/multimedia.svg @@ -0,0 +1,77 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/sandbox.svg b/awesome/theme/icons/tag-list/sandbox.svg new file mode 100644 index 0000000..67c1921 --- /dev/null +++ b/awesome/theme/icons/tag-list/sandbox.svg @@ -0,0 +1,80 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/social.svg b/awesome/theme/icons/tag-list/social.svg new file mode 100644 index 0000000..7217709 --- /dev/null +++ b/awesome/theme/icons/tag-list/social.svg @@ -0,0 +1,92 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/terminal.svg b/awesome/theme/icons/tag-list/terminal.svg new file mode 100644 index 0000000..3c4fc1f --- /dev/null +++ b/awesome/theme/icons/tag-list/terminal.svg @@ -0,0 +1,101 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/text-editor.svg b/awesome/theme/icons/tag-list/text-editor.svg new file mode 100644 index 0000000..4aa63b8 --- /dev/null +++ b/awesome/theme/icons/tag-list/text-editor.svg @@ -0,0 +1,76 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/tag-list/web-browser.svg b/awesome/theme/icons/tag-list/web-browser.svg new file mode 100644 index 0000000..4b97514 --- /dev/null +++ b/awesome/theme/icons/tag-list/web-browser.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/theme/icons/thermometer.svg b/awesome/theme/icons/thermometer.svg new file mode 100644 index 0000000..5c25a1e --- /dev/null +++ b/awesome/theme/icons/thermometer.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/close_focus.svg b/awesome/theme/icons/titlebar/stoplight/close_focus.svg new file mode 100644 index 0000000..8b63331 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/close_focus.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/close_focus_hover.svg b/awesome/theme/icons/titlebar/stoplight/close_focus_hover.svg new file mode 100644 index 0000000..2d77a2f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/close_focus_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/close_normal.svg b/awesome/theme/icons/titlebar/stoplight/close_normal.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/close_normal.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/close_normal_hover.svg b/awesome/theme/icons/titlebar/stoplight/close_normal_hover.svg new file mode 100644 index 0000000..2d77a2f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/close_normal_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_focus_active.svg b/awesome/theme/icons/titlebar/stoplight/floating_focus_active.svg new file mode 100644 index 0000000..ae9727f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_focus_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_focus_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/floating_focus_active_hover.svg new file mode 100644 index 0000000..2faad37 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_focus_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive.svg b/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive.svg new file mode 100644 index 0000000..ae9727f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive_hover.svg new file mode 100644 index 0000000..2faad37 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_focus_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_normal_active.svg b/awesome/theme/icons/titlebar/stoplight/floating_normal_active.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_normal_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_normal_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/floating_normal_active_hover.svg new file mode 100644 index 0000000..2faad37 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_normal_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive.svg b/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive_hover.svg new file mode 100644 index 0000000..2faad37 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/floating_normal_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_focus_active.svg b/awesome/theme/icons/titlebar/stoplight/maximized_focus_active.svg new file mode 100644 index 0000000..e522d74 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_focus_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_focus_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/maximized_focus_active_hover.svg new file mode 100644 index 0000000..7a5c055 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_focus_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive.svg b/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive.svg new file mode 100644 index 0000000..e522d74 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive_hover.svg new file mode 100644 index 0000000..7a5c055 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_focus_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_normal_active.svg b/awesome/theme/icons/titlebar/stoplight/maximized_normal_active.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_normal_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_normal_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/maximized_normal_active_hover.svg new file mode 100644 index 0000000..7a5c055 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_normal_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive.svg b/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive_hover.svg new file mode 100644 index 0000000..7a5c055 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/maximized_normal_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/minimize_focus.svg b/awesome/theme/icons/titlebar/stoplight/minimize_focus.svg new file mode 100644 index 0000000..215d91c --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/minimize_focus.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/minimize_focus_hover.svg b/awesome/theme/icons/titlebar/stoplight/minimize_focus_hover.svg new file mode 100644 index 0000000..282d8b0 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/minimize_focus_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/minimize_normal.svg b/awesome/theme/icons/titlebar/stoplight/minimize_normal.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/minimize_normal.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/minimize_normal_hover.svg b/awesome/theme/icons/titlebar/stoplight/minimize_normal_hover.svg new file mode 100644 index 0000000..282d8b0 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/minimize_normal_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_focus_active.svg b/awesome/theme/icons/titlebar/stoplight/ontop_focus_active.svg new file mode 100644 index 0000000..432f74f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_focus_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_focus_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/ontop_focus_active_hover.svg new file mode 100644 index 0000000..a3da6d2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_focus_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive.svg b/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive.svg new file mode 100644 index 0000000..432f74f --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive_hover.svg new file mode 100644 index 0000000..a3da6d2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_focus_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_normal_active.svg b/awesome/theme/icons/titlebar/stoplight/ontop_normal_active.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_normal_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_normal_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/ontop_normal_active_hover.svg new file mode 100644 index 0000000..a3da6d2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_normal_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive.svg b/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive_hover.svg new file mode 100644 index 0000000..a3da6d2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/ontop_normal_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_focus_active.svg b/awesome/theme/icons/titlebar/stoplight/sticky_focus_active.svg new file mode 100644 index 0000000..47248cb --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_focus_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_focus_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/sticky_focus_active_hover.svg new file mode 100644 index 0000000..fe22df2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_focus_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive.svg b/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive.svg new file mode 100644 index 0000000..47248cb --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive_hover.svg new file mode 100644 index 0000000..fe22df2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_focus_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_normal_active.svg b/awesome/theme/icons/titlebar/stoplight/sticky_normal_active.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_normal_active.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_normal_active_hover.svg b/awesome/theme/icons/titlebar/stoplight/sticky_normal_active_hover.svg new file mode 100644 index 0000000..fe22df2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_normal_active_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive.svg b/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive.svg new file mode 100644 index 0000000..6acee08 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive_hover.svg new file mode 100644 index 0000000..fe22df2 --- /dev/null +++ b/awesome/theme/icons/titlebar/stoplight/sticky_normal_inactive_hover.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/close_focus.svg b/awesome/theme/icons/titlebar/win10/close_focus.svg new file mode 100644 index 0000000..d1bc232 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/close_focus.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/close_normal.svg b/awesome/theme/icons/titlebar/win10/close_normal.svg new file mode 100644 index 0000000..d013ac8 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/close_normal.svg @@ -0,0 +1,114 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/close_normal_hover.svg b/awesome/theme/icons/titlebar/win10/close_normal_hover.svg new file mode 100644 index 0000000..d1bc232 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/close_normal_hover.svg @@ -0,0 +1,116 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_focus_active.svg b/awesome/theme/icons/titlebar/win10/floating_focus_active.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_focus_active.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_focus_active_hover.svg b/awesome/theme/icons/titlebar/win10/floating_focus_active_hover.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_focus_active_hover.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_focus_inactive.svg b/awesome/theme/icons/titlebar/win10/floating_focus_inactive.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_focus_inactive.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/win10/floating_focus_inactive_hover.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_focus_inactive_hover.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_normal_active.svg b/awesome/theme/icons/titlebar/win10/floating_normal_active.svg new file mode 100644 index 0000000..6f0faf1 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_normal_active.svg @@ -0,0 +1,108 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_normal_active_hover.svg b/awesome/theme/icons/titlebar/win10/floating_normal_active_hover.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_normal_active_hover.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_normal_inactive.svg b/awesome/theme/icons/titlebar/win10/floating_normal_inactive.svg new file mode 100644 index 0000000..6f0faf1 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_normal_inactive.svg @@ -0,0 +1,108 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/floating_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/win10/floating_normal_inactive_hover.svg new file mode 100644 index 0000000..cdda009 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/floating_normal_inactive_hover.svg @@ -0,0 +1,130 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_focus_active.svg b/awesome/theme/icons/titlebar/win10/maximized_focus_active.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_focus_active.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_focus_active_hover.svg b/awesome/theme/icons/titlebar/win10/maximized_focus_active_hover.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_focus_active_hover.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_focus_inactive.svg b/awesome/theme/icons/titlebar/win10/maximized_focus_inactive.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_focus_inactive.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_focus_inactive_hover.svg b/awesome/theme/icons/titlebar/win10/maximized_focus_inactive_hover.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_focus_inactive_hover.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_normal_active.svg b/awesome/theme/icons/titlebar/win10/maximized_normal_active.svg new file mode 100644 index 0000000..d9dea80 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_normal_active.svg @@ -0,0 +1,113 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_normal_active_hover.svg b/awesome/theme/icons/titlebar/win10/maximized_normal_active_hover.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_normal_active_hover.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_normal_inactive.svg b/awesome/theme/icons/titlebar/win10/maximized_normal_inactive.svg new file mode 100644 index 0000000..d9dea80 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_normal_inactive.svg @@ -0,0 +1,113 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/maximized_normal_inactive_hover.svg b/awesome/theme/icons/titlebar/win10/maximized_normal_inactive_hover.svg new file mode 100644 index 0000000..6b6452c --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/maximized_normal_inactive_hover.svg @@ -0,0 +1,117 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/minimize_focus.svg b/awesome/theme/icons/titlebar/win10/minimize_focus.svg new file mode 100644 index 0000000..b8a5cc7 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/minimize_focus.svg @@ -0,0 +1,107 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/minimize_focus_hover.svg b/awesome/theme/icons/titlebar/win10/minimize_focus_hover.svg new file mode 100644 index 0000000..b8a5cc7 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/minimize_focus_hover.svg @@ -0,0 +1,107 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/minimize_normal.svg b/awesome/theme/icons/titlebar/win10/minimize_normal.svg new file mode 100644 index 0000000..a3efb9b --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/minimize_normal.svg @@ -0,0 +1,119 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/titlebar/win10/minimize_normal_hover.svg b/awesome/theme/icons/titlebar/win10/minimize_normal_hover.svg new file mode 100644 index 0000000..b8a5cc7 --- /dev/null +++ b/awesome/theme/icons/titlebar/win10/minimize_normal_hover.svg @@ -0,0 +1,107 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/icons/toggled-off.svg b/awesome/theme/icons/toggled-off.svg new file mode 100644 index 0000000..a73de49 --- /dev/null +++ b/awesome/theme/icons/toggled-off.svg @@ -0,0 +1,74 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/theme/icons/toggled-on.svg b/awesome/theme/icons/toggled-on.svg new file mode 100644 index 0000000..a75ef1c --- /dev/null +++ b/awesome/theme/icons/toggled-on.svg @@ -0,0 +1,74 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/theme/icons/volume-high.svg b/awesome/theme/icons/volume-high.svg new file mode 100644 index 0000000..7a59aa1 --- /dev/null +++ b/awesome/theme/icons/volume-high.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/theme/init.lua b/awesome/theme/init.lua new file mode 100644 index 0000000..23b0af5 --- /dev/null +++ b/awesome/theme/init.lua @@ -0,0 +1,12 @@ +local gtable = require('gears.table') +local default_theme = require('theme.default-theme') +-- PICK THEME HERE +local theme = require('theme.floppy-theme') + +local final_theme = {} +gtable.crush(final_theme, default_theme.theme) +gtable.crush(final_theme, theme.theme) +default_theme.awesome_overrides(final_theme) +theme.awesome_overrides(final_theme) + +return final_theme diff --git a/awesome/theme/wallpapers/LICENSE b/awesome/theme/wallpapers/LICENSE new file mode 100644 index 0000000..730138d --- /dev/null +++ b/awesome/theme/wallpapers/LICENSE @@ -0,0 +1,2 @@ +THESE WALLPAPERS ARE NOT MINE IT IS OWNED BY THEIR RESPECTIVE OWNERS. +CREDITS TO THE OWNERS. diff --git a/awesome/theme/wallpapers/midnight-wallpaper.jpg b/awesome/theme/wallpapers/midnight-wallpaper.jpg new file mode 100644 index 0000000..0a50832 Binary files /dev/null and b/awesome/theme/wallpapers/midnight-wallpaper.jpg differ diff --git a/awesome/theme/wallpapers/morning-wallpaper.jpg b/awesome/theme/wallpapers/morning-wallpaper.jpg new file mode 100644 index 0000000..a31cb9b Binary files /dev/null and b/awesome/theme/wallpapers/morning-wallpaper.jpg differ diff --git a/awesome/theme/wallpapers/night-wallpaper.jpg b/awesome/theme/wallpapers/night-wallpaper.jpg new file mode 100644 index 0000000..95408ec Binary files /dev/null and b/awesome/theme/wallpapers/night-wallpaper.jpg differ diff --git a/awesome/theme/wallpapers/noon-wallpaper.jpg b/awesome/theme/wallpapers/noon-wallpaper.jpg new file mode 100644 index 0000000..81382cb Binary files /dev/null and b/awesome/theme/wallpapers/noon-wallpaper.jpg differ diff --git a/awesome/widget/battery/icons/battery-100.svg b/awesome/widget/battery/icons/battery-100.svg new file mode 100644 index 0000000..b3d3337 --- /dev/null +++ b/awesome/widget/battery/icons/battery-100.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-20.svg b/awesome/widget/battery/icons/battery-20.svg new file mode 100644 index 0000000..116a7f9 --- /dev/null +++ b/awesome/widget/battery/icons/battery-20.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-30.svg b/awesome/widget/battery/icons/battery-30.svg new file mode 100644 index 0000000..d1f4463 --- /dev/null +++ b/awesome/widget/battery/icons/battery-30.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-50.svg b/awesome/widget/battery/icons/battery-50.svg new file mode 100644 index 0000000..8dca81e --- /dev/null +++ b/awesome/widget/battery/icons/battery-50.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-60.svg b/awesome/widget/battery/icons/battery-60.svg new file mode 100644 index 0000000..25eaca0 --- /dev/null +++ b/awesome/widget/battery/icons/battery-60.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-80.svg b/awesome/widget/battery/icons/battery-80.svg new file mode 100644 index 0000000..5612658 --- /dev/null +++ b/awesome/widget/battery/icons/battery-80.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-90.svg b/awesome/widget/battery/icons/battery-90.svg new file mode 100644 index 0000000..d11ab44 --- /dev/null +++ b/awesome/widget/battery/icons/battery-90.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-alert-red.svg b/awesome/widget/battery/icons/battery-alert-red.svg new file mode 100644 index 0000000..469b0ba --- /dev/null +++ b/awesome/widget/battery/icons/battery-alert-red.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-alert.svg b/awesome/widget/battery/icons/battery-alert.svg new file mode 100644 index 0000000..6ec71c1 --- /dev/null +++ b/awesome/widget/battery/icons/battery-alert.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-10.svg b/awesome/widget/battery/icons/battery-charging-10.svg new file mode 100644 index 0000000..4de288a --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-10.svg @@ -0,0 +1,75 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-20.svg b/awesome/widget/battery/icons/battery-charging-20.svg new file mode 100644 index 0000000..af759b5 --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-20.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-30.svg b/awesome/widget/battery/icons/battery-charging-30.svg new file mode 100644 index 0000000..f721545 --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-30.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-50.svg b/awesome/widget/battery/icons/battery-charging-50.svg new file mode 100644 index 0000000..42bb375 --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-50.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-60.svg b/awesome/widget/battery/icons/battery-charging-60.svg new file mode 100644 index 0000000..4057d33 --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-60.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-80.svg b/awesome/widget/battery/icons/battery-charging-80.svg new file mode 100644 index 0000000..5febc30 --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-80.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-charging-90.svg b/awesome/widget/battery/icons/battery-charging-90.svg new file mode 100644 index 0000000..544aa5d --- /dev/null +++ b/awesome/widget/battery/icons/battery-charging-90.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-fully-charged.svg b/awesome/widget/battery/icons/battery-fully-charged.svg new file mode 100644 index 0000000..7e923fc --- /dev/null +++ b/awesome/widget/battery/icons/battery-fully-charged.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-standard.svg b/awesome/widget/battery/icons/battery-standard.svg new file mode 100644 index 0000000..adba7ac --- /dev/null +++ b/awesome/widget/battery/icons/battery-standard.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/icons/battery-unknown.svg b/awesome/widget/battery/icons/battery-unknown.svg new file mode 100644 index 0000000..ad67bdf --- /dev/null +++ b/awesome/widget/battery/icons/battery-unknown.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/battery/init.lua b/awesome/widget/battery/init.lua new file mode 100644 index 0000000..1a0f988 --- /dev/null +++ b/awesome/widget/battery/init.lua @@ -0,0 +1,264 @@ +local awful = require('awful') +local wibox = require('wibox') +local awful = require('awful') +local gears = require('gears') +local naughty = require('naughty') + +local watch = awful.widget.watch + +local apps = require('configuration.apps') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/battery/icons/' + + +local return_button = function() + + local battery_imagebox = wibox.widget { + nil, + { + id = 'icon', + image = widget_icon_dir .. 'battery-standard' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + } + + local battery_percentage_text = wibox.widget { + id = 'percent_text', + text = '100%', + font = 'VictorMono Nerd Font 10', + align = 'center', + valign = 'center', + visible = false, + widget = wibox.widget.textbox + } + + + local battery_widget = wibox.widget { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(0), + battery_imagebox, + battery_percentage_text + } + + + local battery_button = wibox.widget { + { + battery_widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + battery_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn(apps.default.power_manager , false) + end + ) + ) + ) + + local battery_tooltip = awful.tooltip + { + objects = {battery_button}, + text = 'None', + mode = 'outside', + align = 'right', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } + + -- Get battery info script + local get_battery_info = function() + awful.spawn.easy_async_with_shell('upower -i $(upower -e | grep BAT)', function(stdout) + + if (stdout == nil or stdout == '') then + battery_tooltip:set_text('No battery detected!') + return + end + + -- Remove new line from the last line + battery_tooltip:set_text(stdout:sub(1, -2)) + end) + end + + -- Update tooltip on startup + get_battery_info() + + -- Update tooltip on hover + battery_widget:connect_signal('mouse::enter', function() + get_battery_info() + end) + + + local check_percentage_cmd = [[ + upower -i $(upower -e | grep BAT) | grep percentage | awk '{print $2}' | tr -d '\n%' + ]] + + local check_status_cmd = [[bash -c " + upower -i $(upower -e | grep BAT) | grep state | awk '{print $2}' | tr -d '\n' + "]] + + local last_battery_check = os.time() + local notify_critcal_battery = true + + local function show_battery_warning() + naughty.notification ({ + icon = widget_icon_dir .. 'battery-alert.svg', + app_name = 'System notification', + title = 'Battery is dying!', + message = 'Hey, I think we have a problem here. Save your work before reaching the oblivion.', + urgency = 'critical' + }) + end + + local update_battery = function(status) + + local status = status:gsub('%\n', '') + + awful.spawn.easy_async_with_shell(check_percentage_cmd, function(stdout) + + local battery_percentage = tonumber(stdout) + + battery_widget.spacing = dpi(5) + battery_percentage_text.visible = true + battery_percentage_text:set_text(battery_percentage .. '%') + + local icon_name = 'battery' + + + if status:match('discharging') then + + if battery_percentage >= 0 and battery_percentage < 10 then + + icon_name = icon_name .. '-' .. 'alert-red' + + if os.difftime(os.time(), last_battery_check) > 300 or notify_critcal_battery then + last_battery_check = os.time() + notify_critcal_battery = false + show_battery_warning() + end + + elseif battery_percentage > 10 and battery_percentage < 20 then + + icon_name = icon_name .. '-' .. '10' + + elseif battery_percentage >= 20 and battery_percentage < 30 then + + icon_name = icon_name .. '-' .. '20' + + elseif battery_percentage >= 30 and battery_percentage < 50 then + + icon_name = icon_name .. '-' .. '30' + + elseif battery_percentage >= 50 and battery_percentage < 60 then + + icon_name = icon_name .. '-' .. '50' + + elseif battery_percentage >= 60 and battery_percentage < 80 then + + icon_name = icon_name .. '-' .. '60' + + elseif battery_percentage >= 80 and battery_percentage < 90 then + + icon_name = icon_name .. '-' .. '80' + + elseif battery_percentage >= 90 and battery_percentage < 100 then + + icon_name = icon_name .. '-' .. '90' + + elseif battery_percentage == 100 then + + icon_name = icon_name .. '-' .. battery_percentage + end + + elseif status:match('charging') then + + if battery_percentage > 0 and battery_percentage < 20 then + + icon_name = icon_name .. '-' .. status .. '-' .. '10' + + elseif battery_percentage >= 20 and battery_percentage < 30 then + + icon_name = icon_name .. '-' .. status .. '-' .. '20' + + elseif battery_percentage >= 30 and battery_percentage < 50 then + + icon_name = icon_name .. '-' .. status .. '-' .. '30' + + elseif battery_percentage >= 50 and battery_percentage < 60 then + + icon_name = icon_name .. '-' .. status .. '-' .. '50' + + elseif battery_percentage >= 60 and battery_percentage < 80 then + + icon_name = icon_name .. '-' .. status .. '-' .. '60' + + elseif battery_percentage >= 80 and battery_percentage < 90 then + + icon_name = icon_name .. '-' .. status .. '-' .. '80' + + elseif battery_percentage >= 90 and battery_percentage < 100 then + + icon_name = icon_name .. '-' .. status .. '-' .. '90' + + else + icon_name = icon_name .. '-' .. 'fully-charged' + end + + elseif status:match('fully') then + + icon_name = icon_name .. '-' .. '100' + + end + + -- Debugger ;) + -- naughty.notification({message=widget_icon_dir .. icon_name .. '.svg'}) + + battery_imagebox.icon:set_image(gears.surface.load_uncached(widget_icon_dir .. icon_name .. '.svg')) + + collectgarbage('collect') + end) + end + + -- Watch status if charging, discharging, fully-charged + watch(check_status_cmd, 5, function(widget, stdout) + + -- If no output or battery detected + if (stdout == nil or stdout == '') then + + battery_widget.spacing = dpi(0) + battery_percentage_text.visible = false + + battery_tooltip:set_text('No battery detected!') + battery_imagebox.icon:set_image(gears.surface.load_uncached(widget_icon_dir .. 'battery-unknown' .. '.svg')) + + return + + end + + update_battery(stdout) + + end) + + return battery_button + + +end + + +return return_button diff --git a/awesome/widget/blue-light/init.lua b/awesome/widget/blue-light/init.lua new file mode 100644 index 0000000..62f914b --- /dev/null +++ b/awesome/widget/blue-light/init.lua @@ -0,0 +1,127 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local dpi = require('beautiful').xresources.apply_dpi +local clickable_container = require('widget.window-effects.clickable-container') + +local icons = require('theme.icons') + +local blue_light_state = nil + +local action_name = wibox.widget { + text = 'Blue Light Filter', + font = 'SF Pro Text Regular 11', + align = 'left', + widget = wibox.widget.textbox +} + +local button_widget = wibox.widget { + { + id = 'icon', + image = icons.toggled_off, + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local widget_button = wibox.widget { + { + button_widget, + top = dpi(7), + bottom = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + + +local update_imagebox = function() + local button_icon = button_widget.icon + if blue_light_state then + button_icon:set_image(icons.toggled_on) + else + button_icon:set_image(icons.toggled_off) + end +end + +local kill_state = function() + awful.spawn.easy_async_with_shell( + [[ + redshift -x + kill -9 $(pgrep redshift) + ]], + function(stdout) + stdout = tonumber(stdout) + if stdout then + blue_light_state = false + update_imagebox() + end + end + ) +end + +kill_state() + +local toggle_action = function() + awful.spawn.easy_async_with_shell( + [[ + if [ ! -z $(pgrep redshift) ]; + then + redshift -x && pkill redshift && killall redshift + echo 'OFF' + else + redshift -l 0:0 -t 4500:4500 -r &>/dev/null & + echo 'ON' + fi + ]], + function(stdout) + if stdout:match('ON') then + blue_light_state = true + else + blue_light_state = false + end + update_imagebox() + end + ) + +end + +widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_action() + end + ) + ) +) + +local action_widget = wibox.widget { + { + action_name, + nil, + { + widget_button, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +awesome.connect_signal( + 'widget::blue_light:toggle', + function() + toggle_action() + end +) + +return action_widget diff --git a/awesome/widget/bluetooth/bluetooth-toggle.lua b/awesome/widget/bluetooth/bluetooth-toggle.lua new file mode 100644 index 0000000..b36cdd0 --- /dev/null +++ b/awesome/widget/bluetooth/bluetooth-toggle.lua @@ -0,0 +1,174 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local naughty = require('naughty') + +local watch = awful.widget.watch +local dpi = require('beautiful').xresources.apply_dpi + +local clickable_container = require('widget.bluetooth.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/bluetooth/icons/' + +local icons = require('theme.icons') + +local device_state = false + + + + +local action_name = wibox.widget { + text = 'Bluetooth Connection', + font = 'SF Pro Text Regular 11', + align = 'left', + widget = wibox.widget.textbox +} + +local button_widget = wibox.widget { + { + id = 'icon', + image = icons.toggled_off, + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local widget_button = wibox.widget { + { + button_widget, + top = dpi(7), + bottom = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +local action_widget = wibox.widget { + { + action_name, + nil, + { + widget_button, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + + +local update_imagebox = function() + if device_state then + + button_widget.icon:set_image(icons.toggled_on) + else + button_widget.icon:set_image(icons.toggled_off) + end +end + + +local check_device_state = function() + awful.spawn.easy_async_with_shell( + 'rfkill list bluetooth', + function(stdout) + + if stdout:match('Soft blocked: yes') then + device_state = false + else + device_state = true + end + + update_imagebox() + end + ) +end + +check_device_state() + + +local power_on_cmd = [[ + rfkill unblock bluetooth + + # Create an AwesomeWM Notification + awesome-client " + naughty = require('naughty') + naughty.notification({ + app_name = 'Bluetooth Manager', + title = 'System Notification', + message = 'Initializing bluetooth device...', + icon = ']] .. widget_icon_dir .. 'loading' .. '.svg' .. [[' + }) + " + + # Add a delay here so we can enable the bluetooth + sleep 1 + + bluetoothctl power on +]] + +local power_off_cmd = [[ + bluetoothctl power off + rfkill block bluetooth + + # Create an AwesomeWM Notification + awesome-client " + naughty = require('naughty') + naughty.notification({ + app_name = 'Bluetooth Manager', + title = 'System Notification', + message = 'The bluetooth device has been disabled.', + icon = ']] .. widget_icon_dir .. 'bluetooth-off' .. '.svg' .. [[' + }) + " +]] + + +local toggle_action = function() + + if device_state then + device_state = false + awful.spawn.easy_async_with_shell( + power_off_cmd, + function(stdout) end + ) + else + device_state = true + awful.spawn.easy_async_with_shell( + power_on_cmd, + function(stdout) end + ) + end + + update_imagebox() +end + + +widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_action() + end + ) + ) +) + +watch( + 'rfkill list bluetooth', + 5, + function(_, stdout) + check_device_state() + collectgarbage('collect') + end +) + + +return action_widget diff --git a/awesome/widget/bluetooth/clickable-container.lua b/awesome/widget/bluetooth/clickable-container.lua new file mode 100644 index 0000000..f531740 --- /dev/null +++ b/awesome/widget/bluetooth/clickable-container.lua @@ -0,0 +1,35 @@ +local wibox = require('wibox') + +function build(widget) + local container = + wibox.widget { + widget, + widget = wibox.container.background, + } + local old_cursor, old_wibox + container:connect_signal( + 'mouse::enter', + function() + -- Hm, no idea how to get the wibox from this signal's arguments... + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = 'hand1' + end + end + ) + + container:connect_signal( + 'mouse::leave', + function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + + return container +end + +return build diff --git a/awesome/widget/bluetooth/icons/bluetooth-connected.svg b/awesome/widget/bluetooth/icons/bluetooth-connected.svg new file mode 100644 index 0000000..bbda6ad --- /dev/null +++ b/awesome/widget/bluetooth/icons/bluetooth-connected.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/bluetooth/icons/bluetooth-off.svg b/awesome/widget/bluetooth/icons/bluetooth-off.svg new file mode 100644 index 0000000..f3e52ab --- /dev/null +++ b/awesome/widget/bluetooth/icons/bluetooth-off.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/bluetooth/icons/bluetooth-scanning.svg b/awesome/widget/bluetooth/icons/bluetooth-scanning.svg new file mode 100644 index 0000000..029f145 --- /dev/null +++ b/awesome/widget/bluetooth/icons/bluetooth-scanning.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/bluetooth/icons/bluetooth.svg b/awesome/widget/bluetooth/icons/bluetooth.svg new file mode 100644 index 0000000..32fbc3e --- /dev/null +++ b/awesome/widget/bluetooth/icons/bluetooth.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/bluetooth/icons/loading.svg b/awesome/widget/bluetooth/icons/loading.svg new file mode 100644 index 0000000..cd7bc0e --- /dev/null +++ b/awesome/widget/bluetooth/icons/loading.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/bluetooth/init.lua b/awesome/widget/bluetooth/init.lua new file mode 100644 index 0000000..e852844 --- /dev/null +++ b/awesome/widget/bluetooth/init.lua @@ -0,0 +1,90 @@ +------------------------------------------------- +-- Bluetooth Widget for Awesome Window Manager +-- Shows the bluetooth status using the bluetoothctl command +-- Better with Blueman Manager +------------------------------------------------- + +local awful = require('awful') +local gears = require('gears') +local naughty = require('naughty') +local wibox = require('wibox') + +local watch = awful.widget.watch +local dpi = require('beautiful').xresources.apply_dpi + +local apps = require('configuration.apps') + +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() + +local widget_icon_dir = config_dir .. 'widget/bluetooth/icons/' + +local return_button = function() + + local widget = + wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'bluetooth-off' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn(apps.default.bluetooth_manager, false) + end + ) + ) + ) + + local bluetooth_tooltip = awful.tooltip + { + objects = {widget_button}, + mode = 'outside', + align = 'right', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } + + watch( + 'rfkill list bluetooth', + 5, + function(_, stdout) + local widget_icon_name = nil + if stdout:match('Soft blocked: yes') then + widget_icon_name = 'bluetooth-off' + bluetooth_tooltip.markup = 'Bluetooth is off' + else + widget_icon_name = 'bluetooth' + bluetooth_tooltip.markup = 'Bluetooth is on' + end + widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg') + collectgarbage('collect') + end, + widget + ) + + return widget_button + +end + +return return_button \ No newline at end of file diff --git a/awesome/widget/brightness/brightness-slider.lua b/awesome/widget/brightness/brightness-slider.lua new file mode 100644 index 0000000..ebc95ec --- /dev/null +++ b/awesome/widget/brightness/brightness-slider.lua @@ -0,0 +1,140 @@ +local wibox = require('wibox') +local gears = require('gears') +local awful = require('awful') +local beautiful = require('beautiful') + +local spawn = awful.spawn + +local dpi = beautiful.xresources.apply_dpi + +local icons = require('theme.icons') + +local slider = wibox.widget { + nil, + { + id = 'brightness_slider', + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(2), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + + +local brightness_slider = slider.brightness_slider + +brightness_slider:connect_signal( + 'property::value', + function() + + local brightness_level = brightness_slider:get_value() + + spawn('brightnessctl s ' .. + math.max(brightness_level, 5), + false + ) + + -- Update brightness osd + awesome.emit_signal( + 'module::brightness_osd', + brightness_level + ) + end +) + +brightness_slider:buttons( + gears.table.join( + awful.button( + {}, + 4, + nil, + function() + if brightness_slider:get_value() > 100 then + brightness_slider:set_value(100) + return + end + brightness_slider:set_value(brightness_slider:get_value() + 5) + end + ), + awful.button( + {}, + 5, + nil, + function() + if brightness_slider:get_value() < 0 then + brightness_slider:set_value(0) + return + end + brightness_slider:set_value(brightness_slider:get_value() - 5) + end + ) + ) +) + + +local update_slider = function() + awful.spawn.easy_async_with_shell( + "brightnessctl g", + function(stdout) + + local brightness = string.match(stdout, '(%d+)') + + brightness_slider:set_value(tonumber(stdout) / 75) + end + ) +end + +-- Update on startup +update_slider() + +-- The emit will come from the global keybind +awesome.connect_signal( + 'widget::brightness', + function() + update_slider() + end +) + +-- The emit will come from the OSD +awesome.connect_signal( + 'widget::brightness:update', + function(value) + brightness_slider:set_value(tonumber(value)) + end +) + + +local brightness_setting = wibox.widget { + { + { + { + image = icons.brightness, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return brightness_setting diff --git a/awesome/widget/calculator/icons/kb-off.svg b/awesome/widget/calculator/icons/kb-off.svg new file mode 100644 index 0000000..0bcea86 --- /dev/null +++ b/awesome/widget/calculator/icons/kb-off.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/calculator/icons/kb.svg b/awesome/widget/calculator/icons/kb.svg new file mode 100644 index 0000000..edccdc8 --- /dev/null +++ b/awesome/widget/calculator/icons/kb.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/calculator/init.lua b/awesome/widget/calculator/init.lua new file mode 100644 index 0000000..91dec20 --- /dev/null +++ b/awesome/widget/calculator/init.lua @@ -0,0 +1,476 @@ +---------------------------------------------------------------------------- +--- Basic Calculator Widget +-- +-- +-- For more details check my repos README.md +-- +-- +-- @author manilarome <gerome.matilla07@gmail.com> +-- @copyright 2019 manilarome +-- @widget calculator +---------------------------------------------------------------------------- + +-- A basic calculator widget +-- Supports keyboard input! +-- Just hover your cursor above the calculator widget and start typing +-- Stop keygrabbing by leaving the calculator + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/calculator/icons/' + +local calculator_screen = wibox.widget { + { + id = 'calcu_screen', + text = '0', + font = 'SF Pro Text Regular 20', + align = 'right', + valign = 'center', + widget = wibox.widget.textbox, + }, + margins = dpi(5), + widget = wibox.container.margin +} + +-- Evaluate +local calculate = function () + + local calcu_screen = calculator_screen.calcu_screen + + local string_expression = calcu_screen:get_text() + + if string_expression:sub(-1):match("[%+%-%/%*%^%.]") then + return + end + + + local func = assert(load("return " .. string_expression)) + local ans = tostring(func()) + + -- Convert -nan to undefined + if ans == '-nan' then + calcu_screen:set_text('undefined') + return + end + + -- Set the answer in textbox + calcu_screen:set_text(ans) + +end + +local txt_on_screen = function() + + screen_text = calculator_screen.calcu_screen:get_text() + + return screen_text == 'inf' or screen_text == 'undefined' or screen_text == 'SYNTAX ERROR' or #screen_text == 1 +end + +-- Delete the last digit in screen + +local delete_value = function() + + calcu_screen = calculator_screen.calcu_screen + + -- Set the screen text to 0 if conditions met + if txt_on_screen() then + calcu_screen:set_text('0') + else + -- Delete the last digit + calcu_screen:set_text(calcu_screen:get_text():sub(1, -2)) + end +end + +-- Clear screen +local clear_screen = function() + + calculator_screen.calcu_screen:set_text('0') +end + +-- The one that filters and checks the user input to avoid errors and bugs +local format_screen = function(value) + + local calcu_screen = calculator_screen.calcu_screen + + -- If the screen has only 0 + if calcu_screen:get_text() == '0' then + + -- Check if the button pressed sends a value of either +, -, /, *, ^, . + + if value:sub(-1):match("[%+%/%*%^%.]") then + + calcu_screen:set_text(calcu_screen:get_text() .. tostring(value)) + + else + + calcu_screen:set_text(value) + + end + + elseif calcu_screen:get_text() == 'inf' or + calcu_screen:get_text() == 'undefined' or + calcu_screen:get_text() == 'SYNTAX ERROR' then + + -- Clear screen if an operator is selected + if value:sub(-1):match("[%+%/%*%^%.]") then + clear_screen() + + else + -- Replace screen txt with the number value pressed + clear_screen() + calcu_screen:set_text(tostring(value)) + end + + else + + -- Don't let the user to input two or more consecutive arithmetic operators and decimals + if calcu_screen:get_text():sub(-1):match("[%+%-%/%*%^%.]") and value:sub(-1):match("[%+%-%/%*%^%.%%]") then + + -- Get the operator from button pressed + local string_eval = calcu_screen:get_text():sub(-1):gsub("[%+%-%/%*%^%.]", value) + + -- This will prevent the user to input consecutive operators and decimals + -- It will replace the previous operator with the value of input + calcu_screen:set_text(calcu_screen:get_text():sub(1, -2)) + + -- Concatenate the value operator to the screen string to replace the deleted operator + calcu_screen:set_text(calcu_screen:get_text() .. tostring(string_eval)) + + else + -- Concatenate the value to screen string + calcu_screen:set_text(calcu_screen:get_text() .. tostring(value)) + + end + end + +end + +-- Shape generator +local build_shape = function (position, radius) + + -- Position represents the position of rounded corners + if position == 'top' then + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, radius) + end + + elseif position == 'top_left' then + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, false, false, false, radius) + end + + elseif position == 'top_right' then + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, true, false, false, radius) + end + + elseif position == 'bottom_right' then + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, true, false, radius) + end + + elseif position == 'bottom_left' then + return function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, false, false, false, true, radius) + end + + else + return function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, radius) + end + + end +end + +-- Themes widgets +local decorate_widget = function(widget_arg, pos, rad) + return wibox.widget { + widget_arg, + bg = beautiful.groups_bg, + shape = build_shape(pos, rad), + widget = wibox.container.background + } +end + +-- Build a button +local build_button_widget = function(text, rcp, rad) + + local value = text + + local build_textbox = wibox.widget { + { + id = 'btn_name', + text = value, + font = 'SF Pro Text 12', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox, + }, + margins = dpi(5), + widget = wibox.container.margin + } + + local build_button = wibox.widget { + { + build_textbox, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + build_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function () + + if value == 'C' then + clear_screen() + + elseif value == '=' then + -- Calculate and error handling + if not pcall(calculate) then + calculator_screen.calcu_screen:set_text('SYNTAX ERROR') + end + + elseif value == 'DEL' then + delete_value() + + else + format_screen(value) + + end + end + ) + ) + ) + + return decorate_widget(build_button, rcp, rad) + +end + +local keygrab_running = false + +local kb_imagebox = wibox.widget { + + id = 'kb_icon', + image = widget_icon_dir .. 'kb-off' .. '.svg', + resize = true, + forced_height = dpi(15), + widget = wibox.widget.imagebox +} + +local kb_button_widget = wibox.widget { + { + { + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + kb_imagebox, + nil + }, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container + }, + bg = beautiful.groups_bg, + shape = build_shape('bottom_left', beautiful.groups_radius), + widget = wibox.container.background +} + +local toggle_btn_keygrab = function() + + if keygrab_running then + kb_imagebox:set_image(widget_icon_dir .. 'kb-off' .. '.svg') + awesome.emit_signal("widget::calc_stop_keygrab") + keygrab_running = false + else + kb_imagebox:set_image(widget_icon_dir .. 'kb' .. '.svg') + awesome.emit_signal("widget::calc_start_keygrab") + keygrab_running = true + end + +end + +local kb_button = kb_button_widget + +kb_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_btn_keygrab() + end + ) + ) +) + +local calcu_keygrabber = awful.keygrabber { + + auto_start = true, + stop_event = 'release', + start_callback = function() + + keygrab_running = true + kb_imagebox:set_image(widget_icon_dir .. 'kb' .. '.svg') + + end, + stop_callback = function() + + keygrab_running = false + kb_imagebox:set_image(widget_icon_dir .. 'kb-off' .. '.svg') + + end, + keypressed_callback = function(self, mod, key, command) + + if #key == 1 and (key:match('%d+') or key:match('[%+%-%/%*%^%.]')) then + format_screen(key) + + elseif key == 'BackSpace' then + delete_value() + + elseif key == 'Escape' then + clear_screen() + + elseif key == 'x' then + awesome.emit_signal("widget::calc_stop_keygrab") + + elseif key == '=' or key == 'Return' then + -- Calculate + if not pcall(calculate) then + calculator_screen.calcu_screen:set_text('SYNTAX ERROR') + end + + end + + end, +} + +local calculator_body = wibox.widget { + layout = wibox.layout.fixed.vertical, + spacing = dpi(1), + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + decorate_widget(calculator_screen, 'top', beautiful.groups_radius), + }, + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + build_button_widget('C', 'flat' , 0), + build_button_widget('^', 'flat', 0), + build_button_widget('/', 'flat', 0), + build_button_widget('DEL', 'flat', 0), + }, + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + build_button_widget('7', 'flat', 0), + build_button_widget('8', 'flat', 0), + build_button_widget('9', 'flat', 0), + build_button_widget('*', 'flat', 0), + }, + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + build_button_widget('4', 'flat', 0), + build_button_widget('5', 'flat', 0), + build_button_widget('6', 'flat', 0), + build_button_widget('-', 'flat', 0), + }, + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + build_button_widget('1', 'flat', 0), + build_button_widget('2', 'flat', 0), + build_button_widget('3', 'flat', 0), + build_button_widget('+', 'flat', 0), + }, + { + spacing = dpi(1), + layout = wibox.layout.flex.horizontal, + kb_button, + build_button_widget('0', 'flat', 0), + build_button_widget('.', 'flat', 0), + build_button_widget('=', 'bottom_right', beautiful.groups_radius) + }, +} + +calculator_body:connect_signal( + "mouse::enter", + function() + -- Start keygrabbing + calcu_keygrabber:start() + end +) + +calculator_body:connect_signal( + "mouse::leave", + function() + -- Stop keygrabbing + calcu_keygrabber:stop() + end +) + +awesome.connect_signal( + "widget::calc_start_keygrab", + function() + -- Stop keygrabbing + calcu_keygrabber:start() + end +) + +awesome.connect_signal( + "widget::calc_stop_keygrab", + function() + -- Stop keygrabbing + calcu_keygrabber:stop() + end +) + +local calcu_tooltip = awful.tooltip { + + objects = {kb_button}, + mode = 'outside', + align = 'right', + delay_show = 1, + preferred_positions = {'right', 'left', 'top', 'bottom'}, + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + markup = [[ + Tips: + Enable keyboard support by hovering your mouse above the calculator. + Or toggle it on/off by pressing the keyboard button. + Only numbers, arithmetic operators, and decimal point is accepted. + + Keyboard bindings: + = and Return to get the answer. + BackSpace to delete the last digit. + Escape clears the screen. + x stops keygrabbing. + + Note: + While in keygrabbing mode, your keyboard's focus will be on the calculator. + So you're AwesomeWM keybinding will stop working. + + Stopping the keygrabbing mode: + * Move away your cursor from the calculator. + * Toggle it off using the keyboard button. + * Press x. + ]] +} + +return calculator_body diff --git a/awesome/widget/clickable-container/init.lua b/awesome/widget/clickable-container/init.lua new file mode 100644 index 0000000..0ebff66 --- /dev/null +++ b/awesome/widget/clickable-container/init.lua @@ -0,0 +1,53 @@ +local wibox = require('wibox') +local beautiful = require('beautiful') + +function build(widget) + local container = + wibox.widget { + widget, + widget = wibox.container.background + } + local old_cursor, old_wibox + + container:connect_signal( + 'mouse::enter', + function() + container.bg = beautiful.groups_bg + -- Hm, no idea how to get the wibox from this signal's arguments... + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = 'hand1' + end + end + ) + + container:connect_signal( + 'mouse::leave', + function() + container.bg = beautiful.transparent + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + + container:connect_signal( + 'button::press', + function() + container.bg = beautiful.groups_title_bg + end + ) + + container:connect_signal( + 'button::release', + function() + container.bg = beautiful.groups_bg + end + ) + + return container +end + +return build diff --git a/awesome/widget/cpu/cpu-meter.lua b/awesome/widget/cpu/cpu-meter.lua new file mode 100644 index 0000000..53f6d69 --- /dev/null +++ b/awesome/widget/cpu/cpu-meter.lua @@ -0,0 +1,74 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local watch = require('awful.widget.watch') + +local icons = require('theme.icons') +local dpi = beautiful.xresources.apply_dpi + +local total_prev = 0 +local idle_prev = 0 + +local slider = wibox.widget { + nil, + { + id = 'cpu_usage', + max_value = 100, + value = 29, + forced_height = dpi(2), + color = beautiful.fg_normal, + background_color = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + widget = wibox.widget.progressbar + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +watch( + [[bash -c "cat /proc/stat | grep '^cpu '"]], + 5, + function(_, stdout) + local user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice = + stdout:match('(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s(%d+)%s') + + local total = user + nice + system + idle + iowait + irq + softirq + steal + + local diff_idle = idle - idle_prev + local diff_total = total - total_prev + local diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 + + slider.cpu_usage:set_value(diff_usage) + + total_prev = total + idle_prev = idle + collectgarbage('collect') + end +) + +local cpu_meter = wibox.widget { + { + { + { + image = icons.chart, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return cpu_meter diff --git a/awesome/widget/email/icons/email-1.svg b/awesome/widget/email/icons/email-1.svg new file mode 100644 index 0000000..9170d0b --- /dev/null +++ b/awesome/widget/email/icons/email-1.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-2.svg b/awesome/widget/email/icons/email-2.svg new file mode 100644 index 0000000..58406a7 --- /dev/null +++ b/awesome/widget/email/icons/email-2.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-3.svg b/awesome/widget/email/icons/email-3.svg new file mode 100644 index 0000000..597b144 --- /dev/null +++ b/awesome/widget/email/icons/email-3.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-4.svg b/awesome/widget/email/icons/email-4.svg new file mode 100644 index 0000000..dc915fb --- /dev/null +++ b/awesome/widget/email/icons/email-4.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-5.svg b/awesome/widget/email/icons/email-5.svg new file mode 100644 index 0000000..935140c --- /dev/null +++ b/awesome/widget/email/icons/email-5.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-6.svg b/awesome/widget/email/icons/email-6.svg new file mode 100644 index 0000000..edf1298 --- /dev/null +++ b/awesome/widget/email/icons/email-6.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-7.svg b/awesome/widget/email/icons/email-7.svg new file mode 100644 index 0000000..980d79c --- /dev/null +++ b/awesome/widget/email/icons/email-7.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-8.svg b/awesome/widget/email/icons/email-8.svg new file mode 100644 index 0000000..4c6618a --- /dev/null +++ b/awesome/widget/email/icons/email-8.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-9+.svg b/awesome/widget/email/icons/email-9+.svg new file mode 100644 index 0000000..53a0a68 --- /dev/null +++ b/awesome/widget/email/icons/email-9+.svg @@ -0,0 +1,104 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-9.svg b/awesome/widget/email/icons/email-9.svg new file mode 100644 index 0000000..9c65b74 --- /dev/null +++ b/awesome/widget/email/icons/email-9.svg @@ -0,0 +1,100 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email-unread.svg b/awesome/widget/email/icons/email-unread.svg new file mode 100644 index 0000000..829d3a9 --- /dev/null +++ b/awesome/widget/email/icons/email-unread.svg @@ -0,0 +1,117 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/email/icons/email.svg b/awesome/widget/email/icons/email.svg new file mode 100644 index 0000000..a8860b4 --- /dev/null +++ b/awesome/widget/email/icons/email.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/email/init.lua b/awesome/widget/email/init.lua new file mode 100644 index 0000000..9c450c9 --- /dev/null +++ b/awesome/widget/email/init.lua @@ -0,0 +1,412 @@ +local awful = require('awful') +local gears = require('gears') +local wibox = require('wibox') +local naughty = require('naughty') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/email/icons/' + +local secrets = require('configuration.secrets') + +local email_account = secrets.email.address +local app_password = secrets.email.app_password +local imap_server = secrets.email.imap_server +local port = secrets.email.port + +local unread_email_count = 0 +local startup_show = true + +local scroll_container = function(widget) + return wibox.widget { + widget, + id = 'scroll_container', + max_size = 345, + speed = 75, + expand = true, + direction = 'h', + step_function = wibox.container.scroll + .step_functions.waiting_nonlinear_back_and_forth, + fps = 30, + layout = wibox.container.scroll.horizontal, + } +end + +local email_icon_widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'email.svg', + resize = true, + forced_height = dpi(45), + forced_width = dpi(45), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local email_from_text = wibox.widget { + font = 'SF Pro Text Bold 10', + markup = 'From:', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + + +local email_recent_from = wibox.widget { + font = 'SF Pro Text Regular 10', + markup = 'loading@stdout.sh', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local email_subject_text = wibox.widget { + font = 'SF Pro Text Regular 10', + markup = 'Subject:', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local email_recent_subject = wibox.widget { + font = 'SF Pro Text Regular 10', + markup = 'Loading data', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local email_date_text = wibox.widget { + font = 'SF Pro Text Regular 10', + markup = 'Local Date:', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local email_recent_date = wibox.widget { + font = 'SF Pro Text Regular 10', + markup = 'Loading date...', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local email_report = wibox.widget{ + { + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(10), + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + email_icon_widget, + nil + }, + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + { + email_from_text, + scroll_container(email_recent_from), + spacing = dpi(5), + layout = wibox.layout.fixed.horizontal + }, + { + email_subject_text, + scroll_container(email_recent_subject), + spacing = dpi(5), + layout = wibox.layout.fixed.horizontal + }, + { + email_date_text, + scroll_container(email_recent_date), + spacing = dpi(5), + layout = wibox.layout.fixed.horizontal + } + }, + nil + } + }, + margins = dpi(10), + widget = wibox.container.margin + }, + forced_height = dpi(92), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius) + end, + widget = wibox.container.background +} + +local email_details_tooltip = awful.tooltip +{ + text = 'Loading...', + objects = {email_icon_widget}, + mode = 'outside', + align = 'right', + preferred_positions = {'left', 'right', 'top', 'bottom'}, + margin_leftright = dpi(8), + margin_topbottom = dpi(8) +} + +local fetch_email_command = [[ +python3 - < 1 then + title = 'You have ' .. unread_counter .. ' unread emails!' + else + title = 'You have ' .. unread_counter .. ' unread email!' + end + + naughty.notification ({ + app_name = 'Email', + title = title, + message = email_data, + timeout = 30, + icon = widget_icon_dir .. 'email-unread.svg' + }) +end + +local notify_new_email = function(count, from, subject) + if not startup_show and (tonumber(count) > tonumber(unread_email_count)) then + unread_email_count = tonumber(count) + + local message = "From: " .. from .. + "\nSubject: " .. subject + + naughty.notification ({ + app_name = 'Email', + title = 'You have a new unread email!', + message = message, + timeout = 10, + icon = widget_icon_dir .. 'email-unread.svg' + }) + else + unread_email_count = tonumber(count) + end + +end + +local set_email_data_tooltip = function(email_data) + local email_data = email_data:match('(From:.*)') + local counter = "Unread Count: " .. unread_email_count + email_details_tooltip:set_markup(counter .. '\n\n' .. email_data) +end + +local set_widget_markup = function(from, subject, date, tooltip) + + email_recent_from:set_markup(from:gsub('%\n', '')) + email_recent_subject:set_markup(subject:gsub('%\n', '')) + email_recent_date:set_markup(date:gsub('%\n', '')) + + if tooltip then + email_details_tooltip:set_markup(tooltip) + end +end + +local set_no_connection_msg = function() + set_widget_markup( + 'message@stderr.sh', + 'Check network connection!', + os.date("%d-%m-%Y %H:%M:%S"), + 'No internet connection!' + ) +end + +local set_invalid_credentials_msg = function() + set_widget_markup( + 'message@stderr.sh', + 'Invalid Credentials!', + os.date("%d-%m-%Y %H:%M:%S"), + 'You have an invalid credentials!' + ) +end + +local set_latest_email_data = function(email_data) + + local unread_count = email_data:match('Unread Count: (.-)From:'):sub(1, -2) + local recent_from = email_data:match('From: (.-)Subject:'):sub(1, -2) + local recent_subject = email_data:match('Subject: (.-)Local Date:'):sub(1, -2) + local recent_date = email_data:match('Local Date: (.-)\n') + + recent_from = recent_from:match('<(.*)>') or recent_from:match('<(.*)>') or recent_from + + local count = tonumber(unread_count) + if count > 0 and count <= 9 then + email_icon_widget.icon:set_image(widget_icon_dir .. 'email-'.. tostring(count) .. '.svg') + elseif count > 9 then + email_icon_widget.icon:set_image(widget_icon_dir .. 'email-9+.svg') + end + + set_widget_markup( + recent_from, + recent_subject, + recent_date + ) + + notify_new_email(unread_count, recent_from, recent_subject) +end + +local set_empty_inbox_msg = function() + set_widget_markup( + 'empty@stdout.sh', + 'Empty inbox', + os.date("%d-%m-%Y %H:%M:%S"), + 'Empty inbox.' + ) +end + +local fetch_email_data = function() + awful.spawn.easy_async_with_shell( + fetch_email_command, + function(stdout) + stdout = gears.string.xml_escape(stdout:sub(1, -2)) + + if stdout:match("Temporary failure in name resolution") then + set_no_connection_msg() + return + elseif stdout:match("Invalid credentials") then + set_invalid_credentials_msg() + return + elseif stdout:match("Unread Count: 0") then + email_icon_widget.icon:set_image(widget_icon_dir .. 'email.svg') + set_empty_inbox_msg() + return + elseif not stdout:match('Unread Count: (.-)From:') then + return + elseif not stdout or stdout == '' then + return + end + + set_latest_email_data(stdout) + set_email_data_tooltip(stdout) + + if startup_show then + notify_all_unread_email(stdout) + startup_show = false + end + end + ) +end + +local set_missing_secrets_msg = function() + set_widget_markup( + 'message@stderr.sh', + 'Credentials are missing!', + os.date("%d-%m-%Y %H:%M:%S"), + 'Missing credentials!' + ) +end + +local check_secrets = function() + if email_account == '' or app_password == '' or imap_server == '' or port == '' then + set_missing_secrets_msg() + return + else + fetch_email_data() + end +end + +check_secrets() + +local update_widget_timer = gears.timer { + timeout = 30, + autostart = true, + call_now = true, + callback = function() + check_secrets() + end +} + + +email_report:connect_signal( + "mouse::enter", + function() + check_secrets() + end +) + +awesome.connect_signal( + 'system::wifi_connected', + function() + gears.timer.start_new( + 5, + function() + check_secrets() + end + ) + end +) + +return email_report diff --git a/awesome/widget/harddrive/harddrive-meter.lua b/awesome/widget/harddrive/harddrive-meter.lua new file mode 100644 index 0000000..b3972c3 --- /dev/null +++ b/awesome/widget/harddrive/harddrive-meter.lua @@ -0,0 +1,61 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local watch = require('awful.widget.watch') +local icons = require('theme.icons') + +local dpi = beautiful.xresources.apply_dpi + +local slider = wibox.widget { + nil, + { + id = 'hdd_usage', + max_value = 100, + value = 29, + forced_height = dpi(2), + color = beautiful.fg_normal, + background_color = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + widget = wibox.widget.progressbar + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +watch( + [[bash -c "df -h /home|grep '^/' | awk '{print $5}'"]], + 10, + function(_, stdout) + local space_consumed = stdout:match('(%d+)') + slider.hdd_usage:set_value(tonumber(space_consumed)) + collectgarbage('collect') + end +) + + +local harddrive_meter = wibox.widget { + { + { + { + image = icons.harddisk, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return harddrive_meter diff --git a/awesome/widget/music/content/album-cover.lua b/awesome/widget/music/content/album-cover.lua new file mode 100755 index 0000000..135aaa7 --- /dev/null +++ b/awesome/widget/music/content/album-cover.lua @@ -0,0 +1,22 @@ +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') + +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/music/icons/' + +local album_cover_img = wibox.widget { + { + id = 'cover', + image = widget_icon_dir .. 'vinyl' .. '.svg', + resize = true, + clip_shape = gears.shape.rounded_rect, + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.vertical +} + + +return album_cover_img \ No newline at end of file diff --git a/awesome/widget/music/content/init.lua b/awesome/widget/music/content/init.lua new file mode 100644 index 0000000..ff0be29 --- /dev/null +++ b/awesome/widget/music/content/init.lua @@ -0,0 +1,9 @@ +-- Return UI Table +return { + album_cover = require('widget.music.content.album-cover'), + progress_bar = require('widget.music.content.progress-bar'), + track_time = require('widget.music.content.track-time'), + song_info = require('widget.music.content.song-info'), + media_buttons = require('widget.music.content.media-buttons'), + volume_slider = require('widget.music.content.volume-slider'), +} \ No newline at end of file diff --git a/awesome/widget/music/content/media-buttons.lua b/awesome/widget/music/content/media-buttons.lua new file mode 100755 index 0000000..260230f --- /dev/null +++ b/awesome/widget/music/content/media-buttons.lua @@ -0,0 +1,124 @@ +local beautiful = require('beautiful') +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/music/icons/' + +local media_buttons = {} + +media_buttons.play_button_image = wibox.widget { + { + id = 'play', + image = widget_icon_dir .. 'play' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +media_buttons.next_button_image = wibox.widget { + { + id = 'next', + image = widget_icon_dir .. 'next' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +media_buttons.prev_button_image = wibox.widget { + { + id = 'prev', + image = widget_icon_dir .. 'prev' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +media_buttons.repeat_button_image = wibox.widget { + { + id = 'rep', + image = widget_icon_dir .. 'repeat-on' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +media_buttons.random_button_image = wibox.widget { + { + id = 'rand', + image = widget_icon_dir .. 'random-on' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +media_buttons.play_button = wibox.widget { + { + media_buttons.play_button_image, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +media_buttons.next_button = wibox.widget { + { + media_buttons.next_button_image, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +media_buttons.prev_button = wibox.widget { + { + media_buttons.prev_button_image, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +media_buttons.repeat_button = wibox.widget { + { + media_buttons.repeat_button_image, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +media_buttons.random_button = wibox.widget { + { + media_buttons.random_button_image, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +media_buttons.navigate_buttons = wibox.widget { + expand = 'none', + layout = wibox.layout.align.horizontal, + media_buttons.repeat_button, + { + layout = wibox.layout.fixed.horizontal, + media_buttons.prev_button, + media_buttons.play_button, + media_buttons.next_button, + forced_height = dpi(35), + }, + media_buttons.random_button, + forced_height = dpi(35), +} + +return media_buttons \ No newline at end of file diff --git a/awesome/widget/music/content/progress-bar.lua b/awesome/widget/music/content/progress-bar.lua new file mode 100755 index 0000000..7069011 --- /dev/null +++ b/awesome/widget/music/content/progress-bar.lua @@ -0,0 +1,22 @@ +local beautiful = require('beautiful') +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') +local dpi = beautiful.xresources.apply_dpi + +local progressbar = wibox.widget { + { + id = 'music_bar', + max_value = 100, + forced_height = dpi(3), + forced_width = dpi(100), + color = '#ffffff', + background_color = '#ffffff20', + shape = gears.shape.rounded_bar, + widget = wibox.widget.progressbar + }, + layout = wibox.layout.stack +} + + +return progressbar \ No newline at end of file diff --git a/awesome/widget/music/content/song-info.lua b/awesome/widget/music/content/song-info.lua new file mode 100755 index 0000000..9570e00 --- /dev/null +++ b/awesome/widget/music/content/song-info.lua @@ -0,0 +1,63 @@ +local wibox = require('wibox') +local dpi = require('beautiful').xresources.apply_dpi + +local song_info = {} + +song_info.music_title = wibox.widget { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + { + id = 'title', + text = 'The song title is here', + font = 'SF Pro Text Bold 12', + align = 'center', + valign = 'center', + ellipsize = 'end', + widget = wibox.widget.textbox + }, + id = 'scroll_container', + max_size = 345, + speed = 75, + expand = true, + direction = 'h', + step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth, + -- fps = 60, + layout = wibox.container.scroll.horizontal, + }, + nil +} + +song_info.music_artist = wibox.widget { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + { + id = 'artist', + text = 'The artist name is here', + font = 'SF Pro Text 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + }, + id = 'scroll_container', + max_size = 345, + speed = 75, + expand = true, + direction = 'h', + step_function = wibox.container.scroll.step_functions.waiting_nonlinear_back_and_forth, + layout = wibox.container.scroll.horizontal, + fps = 60 + }, + nil, +} + +song_info.music_info = wibox.widget { + layout = wibox.layout.fixed.vertical, + song_info.music_title, + song_info.music_artist +} + +return song_info \ No newline at end of file diff --git a/awesome/widget/music/content/track-time.lua b/awesome/widget/music/content/track-time.lua new file mode 100755 index 0000000..db2abe6 --- /dev/null +++ b/awesome/widget/music/content/track-time.lua @@ -0,0 +1,37 @@ +local beautiful = require('beautiful') +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') +local dpi = beautiful.xresources.apply_dpi + +local time_info = {} + +time_info.time_status = wibox.widget { + id = 'statustime', + text = '00:00', + font = 'SF Pro Text 8', + align = 'center', + valign = 'center', + forced_height = dpi(10), + widget = wibox.widget.textbox +} + +time_info.time_duration = wibox.widget { + id = 'durationtime', + text = '00:00', + font = 'SF Pro Text 8', + align = 'center', + valign = 'center', + forced_height = dpi(10), + widget = wibox.widget.textbox +} + +time_info.time_track = wibox.widget { + expand = 'none', + layout = wibox.layout.align.horizontal, + time_info.time_status, + nil, + time_info.time_duration +} + +return time_info \ No newline at end of file diff --git a/awesome/widget/music/content/volume-slider.lua b/awesome/widget/music/content/volume-slider.lua new file mode 100755 index 0000000..e417893 --- /dev/null +++ b/awesome/widget/music/content/volume-slider.lua @@ -0,0 +1,24 @@ +local beautiful = require('beautiful') +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') +local dpi = beautiful.xresources.apply_dpi + +local slider = {} + +slider.vol_slider = wibox.widget { + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(5), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, +} + +return slider + diff --git a/awesome/widget/music/icons/music.svg b/awesome/widget/music/icons/music.svg new file mode 100755 index 0000000..a2aa04e --- /dev/null +++ b/awesome/widget/music/icons/music.svg @@ -0,0 +1,62 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/music/icons/next.svg b/awesome/widget/music/icons/next.svg new file mode 100644 index 0000000..7df5063 --- /dev/null +++ b/awesome/widget/music/icons/next.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/pause.svg b/awesome/widget/music/icons/pause.svg new file mode 100644 index 0000000..9fc7767 --- /dev/null +++ b/awesome/widget/music/icons/pause.svg @@ -0,0 +1,59 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/play.svg b/awesome/widget/music/icons/play.svg new file mode 100755 index 0000000..3a56779 --- /dev/null +++ b/awesome/widget/music/icons/play.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/prev.svg b/awesome/widget/music/icons/prev.svg new file mode 100644 index 0000000..0e39d34 --- /dev/null +++ b/awesome/widget/music/icons/prev.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/random-off.svg b/awesome/widget/music/icons/random-off.svg new file mode 100755 index 0000000..76f2e06 --- /dev/null +++ b/awesome/widget/music/icons/random-off.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/random-on.svg b/awesome/widget/music/icons/random-on.svg new file mode 100755 index 0000000..3baf2ed --- /dev/null +++ b/awesome/widget/music/icons/random-on.svg @@ -0,0 +1,64 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/repeat-off.svg b/awesome/widget/music/icons/repeat-off.svg new file mode 100644 index 0000000..00a4c06 --- /dev/null +++ b/awesome/widget/music/icons/repeat-off.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/repeat-on.svg b/awesome/widget/music/icons/repeat-on.svg new file mode 100644 index 0000000..6917ca6 --- /dev/null +++ b/awesome/widget/music/icons/repeat-on.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/music/icons/vinyl.svg b/awesome/widget/music/icons/vinyl.svg new file mode 100755 index 0000000..d26a4a8 --- /dev/null +++ b/awesome/widget/music/icons/vinyl.svg @@ -0,0 +1,5698 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/music/init.lua b/awesome/widget/music/init.lua new file mode 100755 index 0000000..d79a84a --- /dev/null +++ b/awesome/widget/music/init.lua @@ -0,0 +1,92 @@ +-- # # +-- ## ## # # #### # #### +-- # # # # # # # # # # +-- # # # # # #### # # +-- # # # # # # # +-- # # # # # # # # # +-- # # #### #### # #### + +local gears = require('gears') +local awful = require('awful') +local wibox = require('wibox') + +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/music/icons/' + +local clickable_container = require('widget.clickable-container') + +local music_box = require('widget.music.music-box') +local toggle_music_box = music_box.toggle_music_box + + +local return_button = function() + + + local widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'music' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + + local music_tooltip = awful.tooltip + { + objects = {widget_button}, + text = 'None', + mode = 'outside', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + align = 'right', + preferred_positions = {'right', 'left', 'top', 'bottom'} + } + + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + music_tooltip.visible = false + awesome.emit_signal('widget::music', 'mouse') + end + ) + ) + ) + + + widget_button:connect_signal( + "mouse::enter", + function() + awful.spawn.easy_async_with_shell( + 'mpc status', + function(stdout) + music_tooltip.text = string.gsub(stdout, '\n$', '') + end + ) + end + ) + + + return widget_button + +end + + +return return_button \ No newline at end of file diff --git a/awesome/widget/music/mpd-music-updater.lua b/awesome/widget/music/mpd-music-updater.lua new file mode 100755 index 0000000..c8229b0 --- /dev/null +++ b/awesome/widget/music/mpd-music-updater.lua @@ -0,0 +1,506 @@ +-- Update Music info using mpd/mpc +-- Depends mpd, mpc + +local gears = require('gears') +local awful = require('awful') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/music/icons/' + +local ui_content = require('widget.music.content') + +local album_cover = ui_content.album_cover +local prog_bar = ui_content.progress_bar +local track_time = ui_content.track_time +local song_info = ui_content.song_info +local vol_slider = ui_content.volume_slider +local media_buttons = ui_content.media_buttons + +local apps = require('configuration.apps') + +local update_cover = function() + + local extract_script = [[ + MUSIC_DIR="$(xdg-user-dir MUSIC)" + TMP_DIR="/tmp/awesomewm/${USER}/" + TMP_COVER_PATH=${TMP_DIR}"cover.jpg" + TMP_SONG="${TMP_DIR}current-song" + + CHECK_EXIFTOOL=$(command -v exiftool) + + if [ ! -d "${TMP_DIR}" ]; then + mkdir -p "${TMP_DIR}"; + fi + + if [ ! -z "$CHECK_EXIFTOOL" ]; then + + # Extract album cover using perl-image-exiftool + exiftool -b -Picture \ + "$MUSIC_DIR/$(mpc -p 6600 --format "%file%" current)" > "$TMP_COVER_PATH" + + else + + #Extract image using ffmpeg + cp "$MUSIC_DIR/$(mpc --format %file% current)" "$TMP_SONG" + + ffmpeg \ + -hide_banner \ + -loglevel 0 \ + -y \ + -i "$TMP_SONG" \ + -vf scale=300:-1 \ + "$TMP_COVER_PATH" > /dev/null 2>&1 + + rm "$TMP_SONG" + fi + + img_data=$(identify $TMP_COVER_PATH 2>&1) + + # Delete the cover.jpg if it's not a valid image + if [[ $img_data == *"insufficient"* ]] .. ']]' .. [[; then + rm $TMP_COVER_PATH + fi + + if [ -f $TMP_COVER_PATH ]; then + echo $TMP_COVER_PATH; + fi + ]] + + awful.spawn.easy_async_with_shell( + extract_script, + function(stdout) + local album_icon = widget_icon_dir .. 'vinyl' .. '.svg' + + if not (stdout == nil or stdout == '') then + album_icon = stdout:gsub('%\n', '') + end + + album_cover.cover:set_image(gears.surface.load_uncached(album_icon)) + + album_cover:emit_signal("widget::redraw_needed") + album_cover:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) +end + +local update_progress_bar = function() + awful.spawn.easy_async_with_shell( + [[ + mpc status | awk 'NR==2 { split($4, a); print a[1]}' | tr -d '[\%\(\)]' + ]], + function(stdout) + + local progress_bar = prog_bar.music_bar + + if stdout ~= nil then + progress_bar:set_value(tonumber(stdout)) + else + progress_bar:set_value(0) + end + end + ) +end + + +local update_time_progress = function() + awful.spawn.easy_async_with_shell( + [[ + mpc status | awk 'NR==2 { split($3, a, "/"); print a[1]}' | tr -d '[\%\(\)]' + ]], + function(stdout) + + local time_status = track_time.time_status + + if stdout ~= nil then + time_status:set_text(tostring(stdout)) + else + time_status:set_text(tostring("00:00")) + end + end + ) + +end + + +local update_time_duration = function() + awful.spawn.easy_async_with_shell( + [[ + mpc --format %time% current + ]], + function(stdout) + + local time_duration = track_time.time_duration + + if stdout ~= nil then + time_duration:set_text(tostring(stdout)) + else + time_duration:set_text(tostring("99:59")) + end + end + ) +end + + +local update_file = function() + awful.spawn.easy_async_with_shell( + [[ + mpc -f %file% current + ]], + function(stdout) + file_name = stdout:gsub('%\n','') + end + ) + return file_name +end + + +local update_title = function() + + awful.spawn.easy_async_with_shell( + [[ + mpc -f %title% current + ]], + function(stdout) + + -- Remove new lines + local title = stdout:gsub('%\n', '') + + local title_widget = song_info.music_title + local title_text = song_info.music_title:get_children_by_id('title')[1] + + -- Make sure it's not null + if not (title == nil or title == '') then + + title_text:set_text(title) + + else + + awful.spawn.easy_async_with_shell( + [[ + mpc -f %file% current + ]], + function(stdout) + + if not (stdout == nil or stdout == '') then + + file_name = stdout:gsub('%\n','') + + file_name = file_name:sub(1, title:len() - 5) .. '' + + title_text:set_text(file_name) + + else + -- Set title + title_text:set_text("Play some music!") + + end + title_widget:emit_signal("widget::redraw_needed") + title_widget:emit_signal("widget::layout_changed") + end + ) + + end + + title_widget:emit_signal("widget::redraw_needed") + title_widget:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) +end + + +local update_artist = function() + + + awful.spawn.easy_async_with_shell( + [[ + mpc -f %artist% current + ]], + function(stdout) + + -- Remove new lines + local artist = stdout:gsub('%\n', '') + + local artist_widget = song_info.music_artist + + local artist_text = artist_widget:get_children_by_id('artist')[1] + + if not (artist == nil or artist == '') then + + artist_text:set_text(artist) + + else + + + awful.spawn.easy_async_with_shell( + [[ + mpc -f %file% current + ]], + function(stdout) + if not (stdout == nil or stdout == '') then + + artist_text:set_text('unknown artist') + + else + artist_text:set_text("or play some porn?") + + end + artist_widget:emit_signal("widget::redraw_needed") + artist_widget:emit_signal("widget::layout_changed") + end + ) + end + + artist_widget:emit_signal("widget::redraw_needed") + artist_widget:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) +end + + +local update_volume_slider = function() + awful.spawn.easy_async_with_shell( + [[ + mpc volume + ]], + function(stdout) + + local volume_slider = vol_slider.vol_slider + + if stdout:match('n/a') then + return + end + volume_slider:set_value(tonumber(stdout:match('%d+'))) + end + ) +end + + +local check_if_playing = function() + awful.spawn.easy_async_with_shell( + [[ + mpc status | awk 'NR==2' | grep -o playing + ]], + function(stdout) + + local play_button_img = media_buttons.play_button_image.play + + if not (stdout == nil or stdout == '') then + play_button_img:set_image(widget_icon_dir .. 'pause.svg') + update_volume_slider() + else + play_button_img:set_image(widget_icon_dir .. 'play.svg') + end + end + ) +end + + +local check_repeat_status = function() + awful.spawn.easy_async_with_shell( + [[ + mpc status | sed -n '/random/p' | cut -c23-24 | sed 's/^[ \t]*//' + ]], + function(stdout) + local repeat_button_img = media_buttons.repeat_button_image.rep + + if stdout:match("on") then + repeat_button_img:set_image(widget_icon_dir .. 'repeat-on.svg') + else + repeat_button_img:set_image(widget_icon_dir .. 'repeat-off.svg') + end + end + ) +end + + +local check_random_status = function() + awful.spawn.easy_async_with_shell( + [[ + mpc status | sed -n '/random/p' | cut -c37-38 | sed 's/^[ \t]*//' + ]], + function(stdout) + + local random_button_image = media_buttons.random_button_image.rand + + if stdout:match("on") then + random_button_image:set_image(widget_icon_dir .. 'random-on.svg') + else + random_button_image:set_image(widget_icon_dir .. 'random-off.svg') + end + end + ) +end + + +vol_slider.vol_slider:connect_signal( + 'property::value', + function() + awful.spawn.easy_async_with_shell( + 'mpc volume ' .. vol_slider.vol_slider:get_value(), + function() end + ) + end +) + + +local update_all_content = function() + update_progress_bar() + update_time_progress() + update_time_duration() + update_title() + update_artist() + update_cover() + check_if_playing() + check_repeat_status() + check_random_status() + update_volume_slider() +end + + +local startup_update_quota = 0 + +gears.timer.start_new(3, function() + + update_all_content() + + startup_update_quota = startup_update_quota + 1 + + if startup_update_quota <= 5 then + return true + else + return false + end +end) + + +gears.timer.start_new( + 5, + function() + update_progress_bar() + update_time_progress() + return true + end +) + + +local mpd_startup = [[ +# Let's make sure that MPD is running. +if [ -z $(pgrep mpd) ]; then mpd; fi +]] + +local mpd_change_event_listener = [[ +sh -c ' +mpc idleloop player +' +]] + +local kill_mpd_change_event_listener = [[ +ps x | +grep "mpc idleloop player" | +grep -v grep | +awk '{print $1}' | +xargs kill +]] + +awful.spawn.easy_async_with_shell( + mpd_startup, + function () + awful.spawn.easy_async_with_shell( + kill_mpd_change_event_listener, + function () + awful.spawn.with_line_callback( + mpd_change_event_listener, { + stdout = function(line) + update_all_content() + end + } + ) + end + ) + end +) + + +media_buttons.play_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('mpc toggle') + end + ) + ) +) + +media_buttons.next_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('mpc next') + end + ) + ) +) + + +media_buttons.prev_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('mpc prev') + end + ) + ) +) + + +media_buttons.repeat_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.easy_async_with_shell( + 'mpc repeat', + function () + check_repeat_status() + end + ) + end + ) + ) +) + + +media_buttons.random_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.easy_async_with_shell( + 'mpc random', + function () + check_random_status() + end + ) + end + ) + ) +) \ No newline at end of file diff --git a/awesome/widget/music/music-box.lua b/awesome/widget/music/music-box.lua new file mode 100755 index 0000000..20bba0a --- /dev/null +++ b/awesome/widget/music/music-box.lua @@ -0,0 +1,171 @@ +-- # # ###### +-- ## ## # # #### # #### # # #### # # +-- # # # # # # # # # # # # # # # # +-- # # # # # #### # # ###### # # ## +-- # # # # # # # # # # # ## +-- # # # # # # # # # # # # # # # +-- # # #### #### # #### ###### #### # # + +-- Creates the music box widget here + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local music_func = {} + +screen.connect_signal("request::desktop_decoration", function(s) + + -- Set music box geometry + local music_box_margin = dpi(5) + local music_box_height = dpi(375) + local music_box_width = dpi(260) + local music_box_x = nil + + + s.musicpop = awful.popup { + widget = { + -- Removing this block will cause an error... + }, + ontop = true, + visible = false, + type = 'dock', + screen = s, + width = music_box_width, + height = music_box_height, + maximum_width = music_box_width, + maximum_height = music_box_height, + offset = dpi(5), + shape = gears.shape.rectangle, + bg = beautiful.transparent, + preferred_anchors = {'middle', 'back', 'front'}, + preferred_positions = {'left', 'right', 'top', 'bottom'}, + + } + + local ui_content = require('widget.music.content') + + s.album = ui_content.album_cover + s.progress_bar = ui_content.progress_bar + s.time_track = ui_content.track_time.time_track + s.song_info = ui_content.song_info.music_info + s.media_buttons = ui_content.media_buttons.navigate_buttons + s.volume_slider = ui_content.volume_slider.vol_slider + + s.musicpop : setup { + { + { + layout = wibox.layout.fixed.vertical, + expand = 'none', + spacing = dpi(8), + { + s.album, + bottom = dpi(5), + widget = wibox.container.margin, + }, + { + layout = wibox.layout.fixed.vertical, + { + spacing = dpi(4), + layout = wibox.layout.fixed.vertical, + s.progress_bar, + s.time_track, + }, + s.song_info, + s.media_buttons, + s.volume_slider, + }, + }, + top = dpi(15), + left = dpi(15), + right = dpi(15), + widget = wibox.container.margin + + }, + bg = beautiful.background, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect( + cr, width, height, true, true, true, true, beautiful.groups_radius + ) + end, + widget = wibox.container.background() + } + + s.backdrop_music = wibox { + ontop = true, + visible = false, + screen = s, + type = 'utility', + input_passthrough = false, + bg = beautiful.transparent, + x = s.geometry.x, + y = s.geometry.y, + width = s.geometry.width, + height = s.geometry.height + } + + local toggle_music_box = function(type) + + local focused = awful.screen.focused() + local music_box = focused.musicpop + local music_backdrop = focused.backdrop_music + + if music_box.visible then + music_backdrop.visible = not music_backdrop.visible + music_box.visible = not music_box.visible + + else + + if type == 'keyboard' then + music_backdrop.visible = true + music_box.visible = true + + awful.placement.top_right(music_box, { margins = { + top = dpi(5), + right = dpi(music_box_x or 5) + }, + honor_workarea = true + }) + else + local widget_button = mouse.current_widget_geometry + + music_backdrop.visible = true + music_box:move_next_to(widget_button) + music_box_x = (focused.geometry.width - music_box.x) - music_box_width + end + + end + + end + + awesome.connect_signal( + 'widget::music', + function(type) + toggle_music_box(type) + end + ) + + + s.backdrop_music:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_music_box() + end + ) + ) + ) +end) + + +music_func.toggle_music_box = toggle_music_box + +local mpd_updater = require('widget.music.mpd-music-updater') + +return music_func \ No newline at end of file diff --git a/awesome/widget/music/spotify-music-updater.lua b/awesome/widget/music/spotify-music-updater.lua new file mode 100644 index 0000000..40331f6 --- /dev/null +++ b/awesome/widget/music/spotify-music-updater.lua @@ -0,0 +1,324 @@ +local gears = require('gears') +local awful = require('awful') +local naughty = require('naughty') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/music/icons/' + +local ui_content = require('widget.music.content') + +local album_cover = ui_content.album_cover +local prog_bar = ui_content.progress_bar +local track_time = ui_content.track_time +local song_info = ui_content.song_info +local vol_slider = ui_content.volume_slider +local media_buttons = ui_content.media_buttons + +-- We can't set/get the data for these +-- So let's hide them + +prog_bar.visible = false +track_time.time_status.visible = false +track_time.time_duration.visible = false +media_buttons.repeat_button.visible = false +media_buttons.random_button.visible = false + + +local update_cover = function() + local get_art_url = [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get \ + string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | + egrep -A 1 "artUrl"| egrep -v "artUrl" | awk -F '"' '{print $2}' | + sed -e 's/open.spotify.com/i.scdn.co/g' + ]] + + awful.spawn.easy_async_with_shell( + get_art_url, + function(link) + + local download_art = [[ + tmp_dir="/tmp/awesomewm/${USER}/" + tmp_cover_path=${tmp_dir}"cover.jpg" + + if [ ! -d $tmp_dir ]; then + mkdir -p $tmp_dir; + fi + + if [ -f $tmp_cover_path]; then + rm $tmp_cover_path + fi + + wget -O $tmp_cover_path ]] ..link .. [[ + + echo $tmp_cover_path + ]] + + awful.spawn.easy_async_with_shell( + download_art, + function(stdout) + + local album_icon = stdout:gsub('%\n', '') + + album_cover.cover:set_image(gears.surface.load_uncached(album_icon)) + + album_cover:emit_signal("widget::redraw_needed") + album_cover:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) + end + ) +end + + +local update_title = function() + awful.spawn.easy_async_with_shell( + [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata' | + egrep -A 1 "title" | egrep -v "title" | awk -F '"' '{print $2}' + ]], + function(stdout) + + local title = stdout:gsub('%\n', '') + + local title_widget = song_info.music_title + + local title_text = song_info.music_title:get_children_by_id('title')[1] + + title_text:set_text(title) + + title_widget:emit_signal("widget::redraw_needed") + title_widget:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) +end + + +local update_artist = function() + + + awful.spawn.easy_async_with_shell( + [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:'org.mpris.MediaPlayer2.Player' string:'Metadata'| + egrep -A 2 "artist" | egrep -v "artist" | egrep -v "array" | awk -F '"' '{print $2}' + ]], + function(stdout) + + -- Remove new lines + local artist = stdout:gsub('%\n', '') + + if (stdout == nil or stdout == '') then + artist = 'Advertisement' + end + + local artist_widget = song_info.music_artist + + local artist_text = artist_widget:get_children_by_id('artist')[1] + + artist_text:set_text(artist) + + artist_widget:emit_signal("widget::redraw_needed") + artist_widget:emit_signal("widget::layout_changed") + + collectgarbage('collect') + end + ) +end + + +local update_volume_slider = function() + +-- Stop. Don't indent. +-- It's python. Nuff said + local get_volume = [[ +python - < 100: + arg = 100 + subprocess.run(['pactl', 'set-sink-input-volume', sink_id, str(arg) + '%']) + +END + ]] + + awful.spawn.easy_async_with_shell( + set_volume, + function(stdout) end + ) + +end + + +vol_slider.vol_slider:connect_signal( + 'property::value', + function() + local volume_slider = vol_slider.vol_slider + set_spotify_volume(tostring(volume_slider:get_value())) + end +) + + +local update_all_content = function() + -- Add a delay + gears.timer.start_new(2, function() + update_title() + update_artist() + update_cover() + check_if_playing() + update_volume_slider() + end) +end + + +update_all_content() + + +media_buttons.play_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.easy_async_with_shell( + [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause + ]], + function() + check_if_playing() + end + ) + end + ) + ) +) + + +media_buttons.next_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.easy_async_with_shell( + [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next + ]], + function() + update_all_content() + end + ) + end + ) + ) +) + + +media_buttons.prev_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.easy_async_with_shell( + [[ + dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous + ]], + function() + update_all_content() + end + ) + end + ) + ) +) \ No newline at end of file diff --git a/awesome/widget/network/airplane_mode b/awesome/widget/network/airplane_mode new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/awesome/widget/network/airplane_mode @@ -0,0 +1 @@ +false diff --git a/awesome/widget/network/clickable-container.lua b/awesome/widget/network/clickable-container.lua new file mode 100755 index 0000000..f531740 --- /dev/null +++ b/awesome/widget/network/clickable-container.lua @@ -0,0 +1,35 @@ +local wibox = require('wibox') + +function build(widget) + local container = + wibox.widget { + widget, + widget = wibox.container.background, + } + local old_cursor, old_wibox + container:connect_signal( + 'mouse::enter', + function() + -- Hm, no idea how to get the wibox from this signal's arguments... + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = 'hand1' + end + end + ) + + container:connect_signal( + 'mouse::leave', + function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + + return container +end + +return build diff --git a/awesome/widget/network/icons/airplane-mode-off.svg b/awesome/widget/network/icons/airplane-mode-off.svg new file mode 100644 index 0000000..7a4c91c --- /dev/null +++ b/awesome/widget/network/icons/airplane-mode-off.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/airplane-mode.svg b/awesome/widget/network/icons/airplane-mode.svg new file mode 100644 index 0000000..70fc89d --- /dev/null +++ b/awesome/widget/network/icons/airplane-mode.svg @@ -0,0 +1,62 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/loading.svg b/awesome/widget/network/icons/loading.svg new file mode 100755 index 0000000..cd7bc0e --- /dev/null +++ b/awesome/widget/network/icons/loading.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-off.svg b/awesome/widget/network/icons/wifi-off.svg new file mode 100755 index 0000000..dbcbc7a --- /dev/null +++ b/awesome/widget/network/icons/wifi-off.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-1-alert.svg b/awesome/widget/network/icons/wifi-strength-1-alert.svg new file mode 100755 index 0000000..7a8de11 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-1-alert.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-1-lock.svg b/awesome/widget/network/icons/wifi-strength-1-lock.svg new file mode 100755 index 0000000..9bcf910 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-1-lock.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-1.svg b/awesome/widget/network/icons/wifi-strength-1.svg new file mode 100755 index 0000000..9e90049 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-1.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-2-alert.svg b/awesome/widget/network/icons/wifi-strength-2-alert.svg new file mode 100755 index 0000000..970987a --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-2-alert.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-2-lock.svg b/awesome/widget/network/icons/wifi-strength-2-lock.svg new file mode 100755 index 0000000..cbedd27 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-2-lock.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-2.svg b/awesome/widget/network/icons/wifi-strength-2.svg new file mode 100755 index 0000000..e65871e --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-2.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-3-alert.svg b/awesome/widget/network/icons/wifi-strength-3-alert.svg new file mode 100755 index 0000000..e1b5a5f --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-3-alert.svg @@ -0,0 +1,71 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-3-lock.svg b/awesome/widget/network/icons/wifi-strength-3-lock.svg new file mode 100755 index 0000000..865d01a --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-3-lock.svg @@ -0,0 +1,62 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-3.svg b/awesome/widget/network/icons/wifi-strength-3.svg new file mode 100755 index 0000000..cec90d5 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-3.svg @@ -0,0 +1,61 @@ + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-4-alert.svg b/awesome/widget/network/icons/wifi-strength-4-alert.svg new file mode 100755 index 0000000..2d9d47d --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-4-alert.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-4-lock.svg b/awesome/widget/network/icons/wifi-strength-4-lock.svg new file mode 100755 index 0000000..fb51f35 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-4-lock.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-4.svg b/awesome/widget/network/icons/wifi-strength-4.svg new file mode 100755 index 0000000..259a3a9 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-4.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-alert-outline.svg b/awesome/widget/network/icons/wifi-strength-alert-outline.svg new file mode 100755 index 0000000..3e4c33a --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-alert-outline.svg @@ -0,0 +1,48 @@ + +image/svg+xml + + \ No newline at end of file diff --git a/awesome/widget/network/icons/wifi-strength-alert.svg b/awesome/widget/network/icons/wifi-strength-alert.svg new file mode 100755 index 0000000..ca80f6c --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-alert.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-empty.svg b/awesome/widget/network/icons/wifi-strength-empty.svg new file mode 100755 index 0000000..0a1380a --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-empty.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-lock-outline.svg b/awesome/widget/network/icons/wifi-strength-lock-outline.svg new file mode 100755 index 0000000..3edc636 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-lock-outline.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-off-outline.svg b/awesome/widget/network/icons/wifi-strength-off-outline.svg new file mode 100755 index 0000000..2f9b636 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-off-outline.svg @@ -0,0 +1,48 @@ + +image/svg+xml + + \ No newline at end of file diff --git a/awesome/widget/network/icons/wifi-strength-off.svg b/awesome/widget/network/icons/wifi-strength-off.svg new file mode 100755 index 0000000..12cb043 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-off.svg @@ -0,0 +1,56 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wifi-strength-outline.svg b/awesome/widget/network/icons/wifi-strength-outline.svg new file mode 100755 index 0000000..00fcd26 --- /dev/null +++ b/awesome/widget/network/icons/wifi-strength-outline.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/network/icons/wifi.svg b/awesome/widget/network/icons/wifi.svg new file mode 100755 index 0000000..7887868 --- /dev/null +++ b/awesome/widget/network/icons/wifi.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/awesome/widget/network/icons/wired-alert.svg b/awesome/widget/network/icons/wired-alert.svg new file mode 100755 index 0000000..35481c0 --- /dev/null +++ b/awesome/widget/network/icons/wired-alert.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wired-off.svg b/awesome/widget/network/icons/wired-off.svg new file mode 100755 index 0000000..f7c586a --- /dev/null +++ b/awesome/widget/network/icons/wired-off.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/icons/wired.svg b/awesome/widget/network/icons/wired.svg new file mode 100755 index 0000000..00441ac --- /dev/null +++ b/awesome/widget/network/icons/wired.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/network/init.lua b/awesome/widget/network/init.lua new file mode 100755 index 0000000..38dc463 --- /dev/null +++ b/awesome/widget/network/init.lua @@ -0,0 +1,376 @@ +---------------------------------------------------------------------------- +--- Simple Network Widget +-- +-- Depends: iproute2, iw +-- +-- For more details check `man maim` +-- +-- @author manilarome <gerome.matilla07@gmail.com> +-- @copyright 2020 manilarome +-- @widget network +---------------------------------------------------------------------------- + + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local naughty = require('naughty') + +local dpi = require('beautiful').xresources.apply_dpi + +local apps = require('configuration.apps') +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/network/icons/' + +local wlan_interface = 'wlp3s0' +local lan_interface = 'enp0s25' + +local return_button = function() + + local wifi_strength = nil + + local connected_to_network = false + local conn_status = 'disconnected' + local essid = nil + + local update_notify_no_access = true + local notify_no_access_quota = 0 + + local startup = true + local notify_new_wifi_conn = false + + local net_speed = 'N/A' + + local widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'wifi-strength-off' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn(apps.default.network_manager, false) + end + ) + ) + ) + + local notify_not_connected = function() + local message = 'The network has been disconnected' + local title = 'Connection Disconnected' + + if conn_status == 'wireless' then + icon = widget_icon_dir .. 'wifi-strength-off.svg' + elseif conn_status == 'wired' then + icon = widget_icon_dir .. 'wired-off.svg' + else + icon = widget_icon_dir .. 'wifi-strength-off.svg' + end + + naughty.notification({ + message = message, + title = title, + app_name = 'System Notification', + icon = icon + }) + + conn_status = 'disconnected' + end + + local update_disconnected = function() + if conn_status == 'wireless' or conn_status == 'wired' then + + local widget_icon_name = nil + + connected_to_network = false + notify_new_wifi_conn = true + essid = nil + update_notify_no_access = true + + if conn_status == 'wireless' then + widget_icon_name = 'wifi-strength-off' + elseif conn_status == 'wired' then + widget_icon_name = 'wired-off' + end + + notify_not_connected() + widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg') + end + end + + local notify_no_access = function(strength) + if conn_status == 'wireless' or conn_status == 'wired' then + + local message = 'Internet may not be available or it is too slow right now' + + if conn_status == 'wireless' then + icon = widget_icon_dir .. 'wifi-strength-' .. tostring(strength) .. '-alert.svg' + elseif conn_status == 'wired' then + icon = widget_icon_dir .. 'wired-off.svg' + end + + naughty.notification({ + message = message, + title = 'Connection Status', + app_name = 'System Notification', + icon = icon + }) + + end + end + + local update_no_access = function(strength) + + if not update_notify_no_access then + return + end + + local widget_icon_name = nil + + if conn_status == 'wireless' then + widget_icon_name = 'wifi-strength-' .. tostring(strength) .. '-alert' + elseif conn_status == 'wired' then + widget_icon_name = 'wired-alert' + end + notify_no_access(strength) + widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg') + + update_notify_no_access = false + + end + + + local notify_wifi_conn = function() + if startup then + startup = false + return + end + + if not notify_new_wifi_conn then + return + end + + local message = "You are now connected to \"" .. essid .. "\"" + local title = "Connection Established" + local app_name = "System Notification" + local icon = widget_icon_dir .. 'wifi.svg' + + naughty.notification({ + message = message, + title = title, + app_name = app_name, + icon = icon + }) + + notify_new_wifi_conn = false + end + + + local update_essid = function() + if not essid and connected_to_network == true then + awful.spawn.easy_async_with_shell( + [[ + iw dev ]] .. wlan_interface .. [[ link + ]], + function(stdout) + essid = stdout:match('SSID: (.-)\n') + if essid == nil then + essid = 'N/A' + end + notify_wifi_conn() + end + ) + end + end + + local check_internet_health = [[ + status_curl=0 + status_ping=0 + + ip="$(curl --connect-timeout 5 ifconfig.co)" + if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null; + then + status_curl=1 + else + status_curl=0 + fi + + packets="$(ping -q -w4 -c4 1.1.1.1 | grep -o "100% packet loss")" + if [ ! -z "${packets}" ]; + then + status_ping=0 + else + status_ping=1 + fi + + if [ $status_ping -eq 0 ] && [ $status_curl -eq 0 ]; + then + echo 'noaccess' + fi + ]] + + local update_net_speed = function() + + awful.spawn.easy_async_with_shell( + 'iw dev ' .. wlan_interface .. ' link', + function(stdout) + net_speed = stdout:match("tx bitrate: (.+/s)") or 'N/A' + end + ) + end + + local update_wireless = function() + conn_status = 'wireless' + connected_to_network = true + + awful.spawn.easy_async_with_shell( + [[ + awk 'NR==3 {printf "%3.0f" ,($3/70)*100}' /proc/net/wireless + ]], + function(stdout) + + if not tonumber(stdout) then + return + end + + local widget_icon_name = 'wifi-strength' + + wifi_strength = tonumber(stdout) + + local wifi_strength_rounded = math.floor(wifi_strength / 25 + 0.5) + + awful.spawn.easy_async_with_shell( + check_internet_health, + function(stdout) + local widget_icon_name = widget_icon_name .. '-' .. wifi_strength_rounded + if stdout:match('noaccess') then + update_no_access(wifi_strength_rounded) + return + else + update_net_speed() + if startup then + awesome.emit_signal('system::wifi_connected') + end + update_notify_no_access = true + end + widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg') + end + ) + end + ) + update_essid() + end + + local update_wired = function() + conn_status = 'wired' + connected_to_network = true + + awful.spawn.easy_async_with_shell( + check_internet_health, + function(stdout) + widget_icon_name = 'wired' + if stdout:match('fail') then + update_no_access() + return + else + if startup then + awesome.emit_signal('system::wifi_connected') + startup = false + end + update_notify_no_access = true + end + widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg') + end + ) + + end + + awful.tooltip( + { + objects = {widget_button}, + mode = 'outside', + align = 'right', + timer_function = function() + if connected_to_network then + if conn_status == 'wireless' then + return 'Wireless Interface: ' .. wlan_interface .. + '\nConnected to: ' .. (essid or "*LOADING...*") .. + '\nWiFi-Strength: ' .. tostring(wifi_strength) .. '%' .. + '\nBit rate: ' .. tostring(net_speed) .. '' + else + return 'Ethernet Interface: ' .. lan_interface + end + else + return 'Network is currently disconnected' + end + end, + preferred_positions = {'left', 'right', 'top', 'bottom'}, + margin_leftright = dpi(8), + margin_topbottom = dpi(8) + } + ) + + gears.timer { + timeout = 9, + autostart = true, + call_now = true, + callback = function() + awful.spawn.easy_async_with_shell( + [[ + net_status="$(ip route get 8.8.8.8 2>&1 >/dev/null)" + if ]] .. "[[ " .. [[ "$(echo ${net_status} | awk -F ": " '{print $2}')" == *'unreachable'* ]] .. " ]];" .. [[ + then + echo 'No internet connection' + exit; + fi + + net_status="$(ip route get 8.8.8.8 | grep -Po 'dev \K\w+' | grep -Ff - /proc/net/wireless)" + + if [ ! -z "${net_status}" ] + then + echo 'wireless' + else + echo 'wired' + fi + ]], + function(stdout) + if stdout:match('No internet connection') then + update_disconnected() + return + end + + if stdout:match('wireless') then + update_wireless() + elseif stdout:match('wired') then + update_wired() + end + end + ) + end + } + + return widget_button + +end + +return return_button diff --git a/awesome/widget/network/network-toggle.lua b/awesome/widget/network/network-toggle.lua new file mode 100755 index 0000000..20f57be --- /dev/null +++ b/awesome/widget/network/network-toggle.lua @@ -0,0 +1,173 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local watch = awful.widget.watch +local dpi = require('beautiful').xresources.apply_dpi + +local clickable_container = require('widget.network.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_dir = config_dir .. 'widget/network/' +local widget_icon_dir = widget_dir .. 'icons/' + +local icons = require('theme.icons') + +local ap_state = false + +local action_name = wibox.widget { + text = 'Airplane Mode', + font = 'SF Pro Text Regular 11', + align = 'left', + widget = wibox.widget.textbox +} + +local button_widget = wibox.widget { + { + id = 'icon', + image = icons.toggled_off, + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local widget_button = wibox.widget { + { + button_widget, + top = dpi(7), + bottom = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +local update_imagebox = function() + if ap_state then + button_widget.icon:set_image(icons.toggled_on) + else + button_widget.icon:set_image(icons.toggled_off) + end +end + +local check_airplane_mode_state = function() + + local cmd = "cat " .. widget_dir .. "airplane_mode" + + awful.spawn.easy_async_with_shell( + cmd, + function(stdout) + + local status = stdout + + if status:match("true") then + ap_state = true + elseif status:match("false") then + ap_state = false + else + ap_state = false + awful.spawn.easy_async_with_shell( + "echo 'false' > " .. widget_dir .. "airplane_mode", + function(stdout) end + ) + end + update_imagebox() + end + ) +end + +check_airplane_mode_state() + +local ap_off_cmd = [[ + + rfkill unblock wlan + + # Create an AwesomeWM Notification + awesome-client " + naughty = require('naughty') + naughty.notification({ + app_name = 'Network Manager', + title = 'Airplane mode disabled!', + message = 'Initializing network devices', + icon = ']] .. widget_icon_dir .. 'airplane-mode-off' .. '.svg' .. [[' + }) + " + ]] .. "echo false > " .. widget_dir .. "airplane_mode" .. [[ +]] + +local ap_on_cmd = [[ + + rfkill block wlan + + # Create an AwesomeWM Notification + awesome-client " + naughty = require('naughty') + naughty.notification({ + app_name = 'Network Manager', + title = 'Airplane mode enabled!', + message = 'Disabling radio devices', + icon = ']] .. widget_icon_dir .. 'airplane-mode' .. '.svg' .. [[' + }) + " + ]] .. "echo true > " .. widget_dir .. "airplane_mode" .. [[ +]] + + +local toggle_action = function() + if ap_state then + awful.spawn.easy_async_with_shell( + ap_off_cmd, + function(stdout) + ap_state = false + update_imagebox() + end + ) + else + awful.spawn.easy_async_with_shell( + ap_on_cmd, + function(stdout) + ap_state = true + update_imagebox() + end + ) + end +end + +widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_action() + end + ) + ) +) + +gears.timer { + timeout = 5, + autostart = true, + callback = function() + check_airplane_mode_state() + end +} + +local action_widget = wibox.widget { + { + action_name, + nil, + { + widget_button, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return action_widget diff --git a/awesome/widget/notif-center/build-notifbox/empty-notifbox.lua b/awesome/widget/notif-center/build-notifbox/empty-notifbox.lua new file mode 100644 index 0000000..877d241 --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/empty-notifbox.lua @@ -0,0 +1,65 @@ +-- This returns the "Wow, such empty." message. + +local wibox = require('wibox') + +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = require('gears').filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/notif-center/icons/' + +local empty_notifbox = wibox.widget { + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + { + expand = 'none', + layout = wibox.layout.align.horizontal, + nil, + { + image = widget_icon_dir .. 'empty-notification' .. '.svg', + resize = true, + forced_height = dpi(35), + forced_width = dpi(35), + widget = wibox.widget.imagebox, + }, + nil + }, + { + text = 'Wow, such empty.', + font = 'SF Pro Text Bold 14', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + }, + { + text = 'Come back later.', + font = 'SF Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + }, + }, + margins = dpi(20), + widget = wibox.container.margin + +} + + +local separator_for_empty_msg = wibox.widget +{ + orientation = 'vertical', + opacity = 0.0, + widget = wibox.widget.separator +} + +-- Make empty_notifbox center +local centered_empty_notifbox = wibox.widget { + expand = 'none', + layout = wibox.layout.align.vertical, + separator_for_empty_msg, + empty_notifbox, + separator_for_empty_msg +} + +return centered_empty_notifbox + diff --git a/awesome/widget/notif-center/build-notifbox/init.lua b/awesome/widget/notif-center/build-notifbox/init.lua new file mode 100644 index 0000000..46b779b --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/init.lua @@ -0,0 +1,80 @@ +local wibox = require('wibox') +local awful = require('awful') +local gears = require('gears') +local naughty = require('naughty') +local beautiful = require('beautiful') +local dpi = beautiful.xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/notif-center/icons/' + +local empty_notifbox = require('widget.notif-center.build-notifbox.empty-notifbox') +local notifbox_scroller = require('widget.notif-center.build-notifbox.notifbox-scroller') + +local notif_core = {} + +notif_core.remove_notifbox_empty = true + +notif_core.notifbox_layout = wibox.widget { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + empty_notifbox +} + +notifbox_scroller(notif_core.notifbox_layout) + +notif_core.reset_notifbox_layout = function() + notif_core.notifbox_layout:reset() + notif_core.notifbox_layout:insert(1, empty_notifbox) + notif_core.remove_notifbox_empty = true +end + +local notifbox_add = function(n, notif_icon, notifbox_color) + if #notif_core.notifbox_layout.children == 1 and notif_core.remove_notifbox_empty then + notif_core.notifbox_layout:reset(notif_core.notifbox_layout) + notif_core.remove_notifbox_empty = false + end + + local notifbox_box = require('widget.notif-center.build-notifbox.notifbox-builder') + notif_core.notifbox_layout:insert( + 1, + notifbox_box( + n, + notif_icon, + n.title, + n.message, + n.app_name, + notifbox_color + ) + ) +end + +local notifbox_add_expired = function(n, notif_icon, notifbox_color) + n:connect_signal( + 'destroyed', + function(self, reason, keep_visble) + if reason == 1 then + notifbox_add(n, notif_icon, notifbox_color) + end + end + ) +end + +naughty.connect_signal( + "request::display", + function(n) + local notifbox_color = beautiful.groups_bg + if n.urgency == 'critical' then + notifbox_color = n.bg .. '66' + end + + local notif_icon = n.icon or n.app_icon + if not notif_icon then + notif_icon = widget_icon_dir .. 'new-notif' .. '.svg' + end + + notifbox_add_expired(n, notif_icon, notifbox_color) + end +) + +return notif_core diff --git a/awesome/widget/notif-center/build-notifbox/notifbox-builder.lua b/awesome/widget/notif-center/build-notifbox/notifbox-builder.lua new file mode 100644 index 0000000..55bf6ee --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/notifbox-builder.lua @@ -0,0 +1,177 @@ +local wibox = require('wibox') +local awful = require('awful') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local builder = require('widget.notif-center.build-notifbox.notifbox-ui-elements') +local notifbox_core = require('widget.notif-center.build-notifbox') + +local notifbox_layout = notifbox_core.notifbox_layout +local remove_notifbox_empty = notifbox_core.remove_notifbox_empty +local reset_notifbox_layout = notifbox_core.reset_notifbox_layout + +local return_date_time = function(format) + return os.date(format) +end + +local parse_to_seconds = function(time) + local hourInSec = tonumber(string.sub(time, 1, 2)) * 3600 + local minInSec = tonumber(string.sub(time, 4, 5)) * 60 + local getSec = tonumber(string.sub(time, 7, 8)) + return (hourInSec + minInSec + getSec) +end + +notifbox_box = function(notif, icon, title, message, app, bgcolor) + + local time_of_pop = return_date_time('%H:%M:%S') + local exact_time = return_date_time('%I:%M %p') + local exact_date_time = return_date_time('%b %d, %I:%M %p') + + local notifbox_timepop = wibox.widget { + id = 'time_pop', + markup = nil, + font = 'SF Pro Text Regular 10', + align = 'left', + valign = 'center', + visible = true, + widget = wibox.widget.textbox + } + + local notifbox_dismiss = builder.notifbox_dismiss() + + local time_of_popup = gears.timer { + timeout = 60, + call_now = true, + autostart = true, + callback = function() + + local time_difference = nil + + time_difference = parse_to_seconds(return_date_time('%H:%M:%S')) - parse_to_seconds(time_of_pop) + time_difference = tonumber(time_difference) + + if time_difference < 60 then + notifbox_timepop:set_markup('now') + + elseif time_difference >= 60 and time_difference < 3600 then + local time_in_minutes = math.floor(time_difference / 60) + notifbox_timepop:set_markup(time_in_minutes .. 'm ago') + + elseif time_difference >= 3600 and time_difference < 86400 then + notifbox_timepop:set_markup(exact_time) + + elseif time_difference >= 86400 then + notifbox_timepop:set_markup(exact_date_time) + return false + + end + + collectgarbage('collect') + end + } + + local notifbox_template = wibox.widget { + id = 'notifbox_template', + expand = 'none', + { + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + { + expand = 'none', + layout = wibox.layout.align.horizontal, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(5), + builder.notifbox_icon(icon), + builder.notifbox_appname(app), + }, + nil, + { + notifbox_timepop, + notifbox_dismiss, + layout = wibox.layout.fixed.horizontal + } + }, + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + { + builder.notifbox_title(title), + builder.notifbox_message(message), + layout = wibox.layout.fixed.vertical + }, + builder.notifbox_actions(notif), + }, + + }, + margins = dpi(10), + widget = wibox.container.margin + }, + bg = bgcolor, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius) + end, + widget = wibox.container.background, + } + + -- Put the generated template to a container + local notifbox = wibox.widget { + notifbox_template, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius) + end, + widget = wibox.container.background + } + + -- Delete notification box + local notifbox_delete = function() + notifbox_layout:remove_widgets(notifbox, true) + end + + -- Delete notifbox on LMB + notifbox:buttons( + awful.util.table.join( + awful.button( + {}, + 1, + function() + if #notifbox_layout.children == 1 then + reset_notifbox_layout() + else + notifbox_delete() + end + collectgarbage('collect') + end + ) + ) + ) + + -- Add hover, and mouse leave events + notifbox_template:connect_signal( + "mouse::enter", + function() + notifbox.bg = beautiful.groups_bg + notifbox_timepop.visible = false + notifbox_dismiss.visible = true + end + ) + + notifbox_template:connect_signal( + "mouse::leave", + function() + notifbox.bg = beautiful.tranparent + notifbox_timepop.visible = true + notifbox_dismiss.visible = false + end + ) + + collectgarbage('collect') + + return notifbox +end + + +return notifbox_box \ No newline at end of file diff --git a/awesome/widget/notif-center/build-notifbox/notifbox-geometry.lua b/awesome/widget/notif-center/build-notifbox/notifbox-geometry.lua new file mode 100644 index 0000000..3fe79da --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/notifbox-geometry.lua @@ -0,0 +1,33 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') + +local find_widget_in_wibox = function(wb, widget) + local function find_widget_in_hierarchy(h, widget) + if h:get_widget() == widget then + return h + end + local result + + for _, ch in ipairs(h:get_children()) do + result = result or find_widget_in_hierarchy(ch, widget) + end + return result + end + local h = wb._drawable._widget_hierarchy + return h and find_widget_in_hierarchy(h, widget) +end + + +local focused = awful.screen.focused() +local h = find_widget_in_wibox(focused.top_panel, focused.music) +local x, y, width, height = h:get_matrix_to_device():transform_rectangle(0, 0, h:get_size()) +-- local geo = focused.mywibox:geometry() + + +-- x, y = x + geo.x, y + geo.y + +-- print(string.format("The widget is inside of the rectangle (%d, %d, %d, %d) on the screen", x, y, width, height) + + +naughty.notification({message=tostring(height)}) \ No newline at end of file diff --git a/awesome/widget/notif-center/build-notifbox/notifbox-scroller.lua b/awesome/widget/notif-center/build-notifbox/notifbox-scroller.lua new file mode 100644 index 0000000..f05d323 --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/notifbox-scroller.lua @@ -0,0 +1,37 @@ +local awful = require('awful') +local gears = require('gears') + +local add_button_event = function(widget) + + widget:buttons( + gears.table.join( + awful.button( + {}, + 4, + nil, + function() + if #widget.children == 1 then + return + end + widget:insert(1, widget.children[#widget.children]) + widget:remove(#widget.children) + end + ), + awful.button( + {}, + 5, + nil, + function() + if #widget.children == 1 then + return + end + widget:insert(#widget.children + 1, widget.children[1]) + widget:remove(1) + end + ) + ) + ) + +end + +return add_button_event \ No newline at end of file diff --git a/awesome/widget/notif-center/build-notifbox/notifbox-ui-elements.lua b/awesome/widget/notif-center/build-notifbox/notifbox-ui-elements.lua new file mode 100644 index 0000000..2e1b30a --- /dev/null +++ b/awesome/widget/notif-center/build-notifbox/notifbox-ui-elements.lua @@ -0,0 +1,136 @@ +local wibox = require('wibox') +local beautiful = require('beautiful') +local naughty = require('naughty') +local gears = require('gears') + +local dpi = beautiful.xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/notif-center/icons/' + +local clickable_container = require('widget.clickable-container') + +local ui_noti_builder = {} + +-- Notification icon container +ui_noti_builder.notifbox_icon = function(ico_image) + local noti_icon = wibox.widget { + { + id = 'icon', + resize = true, + forced_height = dpi(25), + forced_width = dpi(25), + widget = wibox.widget.imagebox + }, + layout = wibox.layout.fixed.horizontal + } + noti_icon.icon:set_image(ico_image) + return noti_icon +end + +-- Notification title container +ui_noti_builder.notifbox_title = function(title) + return wibox.widget { + markup = title, + font = 'SF Pro Text Bold 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + } +end + +-- Notification message container +ui_noti_builder.notifbox_message = function(msg) + return wibox.widget { + markup = msg, + font = 'SF Pro Text Regular 11', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + } +end + +-- Notification app name container +ui_noti_builder.notifbox_appname = function(app) + return wibox.widget { + markup = app, + font = 'SF Pro Text Bold 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + } +end + +-- Notification actions container +ui_noti_builder.notifbox_actions = function(n) + actions_template = wibox.widget { + notification = n, + base_layout = wibox.widget { + spacing = dpi(0), + layout = wibox.layout.flex.horizontal + }, + widget_template = { + { + { + { + { + id = 'text_role', + font = 'SF Pro Text Regular 10', + widget = wibox.widget.textbox + }, + widget = wibox.container.place + }, + widget = clickable_container + }, + bg = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + forced_height = 30, + widget = wibox.container.background + }, + margins = 4, + widget = wibox.container.margin + }, + style = { underline_normal = false, underline_selected = true }, + widget = naughty.list.actions, + } + + return actions_template +end + + +-- Notification dismiss button +ui_noti_builder.notifbox_dismiss = function() + + local dismiss_imagebox = wibox.widget { + { + id = 'dismiss_icon', + image = widget_icon_dir .. 'delete.svg', + resize = true, + forced_height = dpi(5), + widget = wibox.widget.imagebox + }, + layout = wibox.layout.fixed.horizontal + } + + local dismiss_button = wibox.widget { + { + dismiss_imagebox, + margins = dpi(5), + widget = wibox.container.margin + }, + widget = clickable_container + } + + local notifbox_dismiss = wibox.widget { + dismiss_button, + visible = false, + bg = beautiful.groups_title_bg, + shape = gears.shape.circle, + widget = wibox.container.background + } + + return notifbox_dismiss +end + + +return ui_noti_builder \ No newline at end of file diff --git a/awesome/widget/notif-center/clear-all/init.lua b/awesome/widget/notif-center/clear-all/init.lua new file mode 100644 index 0000000..7c14657 --- /dev/null +++ b/awesome/widget/notif-center/clear-all/init.lua @@ -0,0 +1,61 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/notif-center/icons/' + +local notifbox_core = require('widget.notif-center.build-notifbox') +local reset_notifbox_layout = notifbox_core.reset_notifbox_layout + +local clear_all_imagebox = wibox.widget { + { + image = widget_icon_dir .. 'clear_all.svg', + resize = true, + forced_height = dpi(20), + forced_width = dpi(20), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local clear_all_button = wibox.widget { + { + clear_all_imagebox, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +clear_all_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + reset_notifbox_layout() + end + ) + ) +) + +local clear_all_button_wrapped = wibox.widget { + nil, + { + clear_all_button, + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +return clear_all_button_wrapped \ No newline at end of file diff --git a/awesome/widget/notif-center/dont-disturb/disturb_status b/awesome/widget/notif-center/dont-disturb/disturb_status new file mode 100644 index 0000000..c508d53 --- /dev/null +++ b/awesome/widget/notif-center/dont-disturb/disturb_status @@ -0,0 +1 @@ +false diff --git a/awesome/widget/notif-center/dont-disturb/init.lua b/awesome/widget/notif-center/dont-disturb/init.lua new file mode 100644 index 0000000..df9d952 --- /dev/null +++ b/awesome/widget/notif-center/dont-disturb/init.lua @@ -0,0 +1,122 @@ +local awful = require('awful') +local naughty = require('naughty') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() + +local widget_dir = config_dir .. 'widget/notif-center/dont-disturb/' +local widget_icon_dir = config_dir .. 'widget/notif-center/icons/' + +_G.dont_disturb = false + +local dont_disturb_imagebox = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'dont-disturb-mode.svg', + resize = true, + forced_height = dpi(20), + forced_width = dpi(20), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local function update_icon() + + local widget_icon_name = nil + local dd_icon = dont_disturb_imagebox.icon + + if dont_disturb then + widget_icon_name = 'toggled-on' + dd_icon:set_image(widget_icon_dir .. 'dont-disturb-mode.svg') + else + widget_icon_name = 'toggled-off' + dd_icon:set_image(widget_icon_dir .. 'notify-mode.svg') + end +end + +local check_disturb_status = function() + + awful.spawn.easy_async_with_shell( + "cat " .. widget_dir .. "disturb_status", + function(stdout) + + local status = stdout + + if status:match("true") then + dont_disturb = true + elseif status:match("false") then + dont_disturb = false + else + dont_disturb = false + awful.spawn.with_shell("echo 'false' > " .. widget_dir .. "disturb_status") + end + + update_icon() + end + ) +end + +check_disturb_status() + +local toggle_disturb = function() + if dont_disturb then + dont_disturb = false + else + dont_disturb = true + end + awful.spawn.with_shell("echo " .. tostring(dont_disturb) .. " > " .. widget_dir .. "disturb_status") + update_icon() +end + +local dont_disturb_button = wibox.widget { + { + dont_disturb_imagebox, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +dont_disturb_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_disturb() + end + ) + ) +) + +local dont_disturb_wrapped = wibox.widget { + nil, + { + dont_disturb_button, + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +-- Create a notification sound +naughty.connect_signal( + "request::display", + function(n) + if not dont_disturb then + awful.spawn.with_shell('canberra-gtk-play -i message') + end + end +) + +return dont_disturb_wrapped \ No newline at end of file diff --git a/awesome/widget/notif-center/icons/clear_all.svg b/awesome/widget/notif-center/icons/clear_all.svg new file mode 100644 index 0000000..3f5b9b4 --- /dev/null +++ b/awesome/widget/notif-center/icons/clear_all.svg @@ -0,0 +1,91 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/notif-center/icons/delete.svg b/awesome/widget/notif-center/icons/delete.svg new file mode 100644 index 0000000..3f1f88c --- /dev/null +++ b/awesome/widget/notif-center/icons/delete.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/widget/notif-center/icons/dont-disturb-mode.svg b/awesome/widget/notif-center/icons/dont-disturb-mode.svg new file mode 100644 index 0000000..d5dc170 --- /dev/null +++ b/awesome/widget/notif-center/icons/dont-disturb-mode.svg @@ -0,0 +1,64 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/awesome/widget/notif-center/icons/empty-notification.svg b/awesome/widget/notif-center/icons/empty-notification.svg new file mode 100644 index 0000000..df4154c --- /dev/null +++ b/awesome/widget/notif-center/icons/empty-notification.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/widget/notif-center/icons/new-notif.svg b/awesome/widget/notif-center/icons/new-notif.svg new file mode 100644 index 0000000..630b90a --- /dev/null +++ b/awesome/widget/notif-center/icons/new-notif.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/awesome/widget/notif-center/icons/notify-mode.svg b/awesome/widget/notif-center/icons/notify-mode.svg new file mode 100644 index 0000000..92b960b --- /dev/null +++ b/awesome/widget/notif-center/icons/notify-mode.svg @@ -0,0 +1,91 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/notif-center/init.lua b/awesome/widget/notif-center/init.lua new file mode 100644 index 0000000..76c50f5 --- /dev/null +++ b/awesome/widget/notif-center/init.lua @@ -0,0 +1,38 @@ +local wibox = require('wibox') +local dpi = require('beautiful').xresources.apply_dpi + +local notif_header = wibox.widget { + text = 'Notification Center', + font = 'SF Pro Text Bold 16', + align = 'left', + valign = 'bottom', + widget = wibox.widget.textbox +} + +local notif_center = function(s) + + s.dont_disturb = require('widget.notif-center.dont-disturb') + s.clear_all = require('widget.notif-center.clear-all') + s.notifbox_layout = require('widget.notif-center.build-notifbox').notifbox_layout + + return wibox.widget { + expand = 'none', + layout = wibox.layout.fixed.vertical, + spacing = dpi(10), + { + expand = 'none', + layout = wibox.layout.align.horizontal, + notif_header, + nil, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(5), + s.dont_disturb, + s.clear_all + }, + }, + s.notifbox_layout + } +end + +return notif_center \ No newline at end of file diff --git a/awesome/widget/package-updater/icons/package-up.svg b/awesome/widget/package-updater/icons/package-up.svg new file mode 100644 index 0000000..2251baa --- /dev/null +++ b/awesome/widget/package-updater/icons/package-up.svg @@ -0,0 +1,48 @@ + +image/svg+xml + + \ No newline at end of file diff --git a/awesome/widget/package-updater/icons/package.svg b/awesome/widget/package-updater/icons/package.svg new file mode 100644 index 0000000..7d4b2f9 --- /dev/null +++ b/awesome/widget/package-updater/icons/package.svg @@ -0,0 +1,48 @@ + +image/svg+xml + + \ No newline at end of file diff --git a/awesome/widget/package-updater/init.lua b/awesome/widget/package-updater/init.lua new file mode 100644 index 0000000..c131f3b --- /dev/null +++ b/awesome/widget/package-updater/init.lua @@ -0,0 +1,122 @@ +------------------------------------------------- +-- Package Updater Widget for Awesome Window Manager +-- Shows the package updates information in Arch Linux +-- Will only show if there is/are updates available +------------------------------------------------- + +local awful = require('awful') +local naughty = require('naughty') +local wibox = require('wibox') +local gears = require('gears') + +local watch = awful.widget.watch + +local apps = require('configuration.apps') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() + +local widget_icon_dir = config_dir .. 'widget/package-updater/icons/' + + +local update_available = false +local number_of_updates_available = nil +local update_package = nil + +local return_button = function() + + local widget = wibox.widget { + { + id = 'icon', + widget = wibox.widget.imagebox, + image = widget_icon_dir .. 'package' .. '.svg', + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + + if update_available then + awful.spawn(apps.default.package_manager .. ' --updates', false) + + else + awful.spawn(apps.default.package_manager, false) + + end + end + ) + ) + ) + + + -- Tooltip + awful.tooltip( + { + objects = {widget_button}, + mode = 'outside', + align = 'right', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + timer_function = function() + + if update_available then + return update_package:gsub('\n$', '') + else + return 'We are up-to-date!' + end + + end, + preferred_positions = {'right', 'left', 'top', 'bottom'} + } + ) + + + watch('pamac checkupdates', 60, function(_, stdout) + + number_of_updates_available = tonumber(stdout:match('.-\n'):match('%d*')) + update_package = stdout + + local icon_name + + if number_of_updates_available ~= nil then + + update_available = true + icon_name = 'package-up' + + else + + update_available = false + icon_name = 'package' + + end + + widget.icon:set_image(widget_icon_dir .. icon_name .. '.svg') + + collectgarbage('collect') + + + end) + + return widget_button + +end + +return return_button \ No newline at end of file diff --git a/awesome/widget/ram/ram-meter.lua b/awesome/widget/ram/ram-meter.lua new file mode 100644 index 0000000..98cd68d --- /dev/null +++ b/awesome/widget/ram/ram-meter.lua @@ -0,0 +1,61 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local watch = require('awful.widget.watch') +local icons = require('theme.icons') + +local dpi = beautiful.xresources.apply_dpi + +local slider = wibox.widget { + nil, + { + id = 'ram_usage', + max_value = 100, + value = 29, + forced_height = dpi(2), + color = beautiful.fg_normal, + background_color = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + widget = wibox.widget.progressbar + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +watch( + 'bash -c "free | grep -z Mem.*Swap.*"', + 5, + function(_, stdout) + local total, used, free, shared, buff_cache, available, total_swap, used_swap, free_swap = + stdout:match('(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*(%d+)%s*Swap:%s*(%d+)%s*(%d+)%s*(%d+)') + slider.ram_usage:set_value(used / total * 100) + collectgarbage('collect') + end +) + +local ram_meter = wibox.widget { + { + { + { + image = icons.memory, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return ram_meter diff --git a/awesome/widget/screen-recorder/icons/audio.svg b/awesome/widget/screen-recorder/icons/audio.svg new file mode 100644 index 0000000..2f8668f --- /dev/null +++ b/awesome/widget/screen-recorder/icons/audio.svg @@ -0,0 +1,71 @@ + +image/svg+xml + + + + + + + + \ No newline at end of file diff --git a/awesome/widget/screen-recorder/icons/back.svg b/awesome/widget/screen-recorder/icons/back.svg new file mode 100644 index 0000000..f0e76e5 --- /dev/null +++ b/awesome/widget/screen-recorder/icons/back.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/screen-recorder/icons/close-screen.svg b/awesome/widget/screen-recorder/icons/close-screen.svg new file mode 100644 index 0000000..3f1f88c --- /dev/null +++ b/awesome/widget/screen-recorder/icons/close-screen.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/awesome/widget/screen-recorder/icons/recorder-countdown.svg b/awesome/widget/screen-recorder/icons/recorder-countdown.svg new file mode 100644 index 0000000..63134d5 --- /dev/null +++ b/awesome/widget/screen-recorder/icons/recorder-countdown.svg @@ -0,0 +1,68 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/awesome/widget/screen-recorder/icons/recorder-off.svg b/awesome/widget/screen-recorder/icons/recorder-off.svg new file mode 100644 index 0000000..8ade140 --- /dev/null +++ b/awesome/widget/screen-recorder/icons/recorder-off.svg @@ -0,0 +1,63 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/screen-recorder/icons/recorder-on.svg b/awesome/widget/screen-recorder/icons/recorder-on.svg new file mode 100644 index 0000000..29800ca --- /dev/null +++ b/awesome/widget/screen-recorder/icons/recorder-on.svg @@ -0,0 +1,71 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/screen-recorder/icons/recording-button.svg b/awesome/widget/screen-recorder/icons/recording-button.svg new file mode 100644 index 0000000..4caa7b3 --- /dev/null +++ b/awesome/widget/screen-recorder/icons/recording-button.svg @@ -0,0 +1,86 @@ + +image/svg+xml + + + + + + + + + + + + \ No newline at end of file diff --git a/awesome/widget/screen-recorder/icons/settings.svg b/awesome/widget/screen-recorder/icons/settings.svg new file mode 100644 index 0000000..2c5a0b9 --- /dev/null +++ b/awesome/widget/screen-recorder/icons/settings.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/screen-recorder/icons/start-recording-button.svg b/awesome/widget/screen-recorder/icons/start-recording-button.svg new file mode 100644 index 0000000..986f9dd --- /dev/null +++ b/awesome/widget/screen-recorder/icons/start-recording-button.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/awesome/widget/screen-recorder/init.lua b/awesome/widget/screen-recorder/init.lua new file mode 100644 index 0000000..230924f --- /dev/null +++ b/awesome/widget/screen-recorder/init.lua @@ -0,0 +1,23 @@ +local wibox = require('wibox') +local awful = require('awful') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local HOME = os.getenv('HOME') + +local recorder_table = require('widget.screen-recorder.screen-recorder-ui') + +require('widget.screen-recorder.screen-recorder-ui-backend') + +local screen_rec_toggle_button = recorder_table.screen_rec_toggle_button + + +local return_button = function() + + return screen_rec_toggle_button + +end + +return return_button \ No newline at end of file diff --git a/awesome/widget/screen-recorder/screen-recorder-config.lua b/awesome/widget/screen-recorder/screen-recorder-config.lua new file mode 100644 index 0000000..8e0c2e2 --- /dev/null +++ b/awesome/widget/screen-recorder/screen-recorder-config.lua @@ -0,0 +1,10 @@ +local user_preferences = {} + +user_preferences.user_resolution = '1366x768' -- Screen WIDTHxHEIGHT +user_preferences.user_offset = '0,0' -- Offset x,y +user_preferences.user_audio = false -- bool true or false +user_preferences.user_save_directory = '$(xdg-user-dir VIDEOS)/Recordings/' -- String $HOME +user_preferences.user_mic_lvl = '20' -- String +user_preferences.user_fps = '30' -- String + +return user_preferences \ No newline at end of file diff --git a/awesome/widget/screen-recorder/screen-recorder-scripts.lua b/awesome/widget/screen-recorder/screen-recorder-scripts.lua new file mode 100644 index 0000000..12c7fa8 --- /dev/null +++ b/awesome/widget/screen-recorder/screen-recorder-scripts.lua @@ -0,0 +1,172 @@ +local awful = require('awful') +local naughty = require('naughty') + +local user_config = require('widget.screen-recorder.screen-recorder-config') + +local scripts_tbl = {} + +local ffmpeg_pid = nil + +-- Get user settings +scripts_tbl.user_resolution = user_config.user_resolution +scripts_tbl.user_offset = user_config.user_offset +scripts_tbl.user_audio = user_config.user_audio +scripts_tbl.user_dir = user_config.user_save_directory +scripts_tbl.user_mic_lvl = user_config.user_mic_lvl +scripts_tbl.user_fps = user_config.user_fps + +scripts_tbl.update_user_settings = function(res, offset, audio) + scripts_tbl.user_resolution = res + scripts_tbl.user_offset = offset + scripts_tbl.user_audio = audio +end + +scripts_tbl.check_settings = function() + -- For debugging purpose only + -- naughty.notification({ + -- message=scripts_tbl.user_resolution .. ' ' .. scripts_tbl.user_offset .. tostring(scripts_tbl.user_audio) + -- }) +end + +local create_save_directory = function() + + local create_dir_cmd = [[ + dir=]] .. scripts_tbl.user_dir .. [[ + + if [ ! -d $dir ]; then + mkdir -p $dir + fi + ]] + + awful.spawn.easy_async_with_shell( + create_dir_cmd, + function(stdout) end + ) + +end + +create_save_directory() + +local kill_existing_recording_ffmpeg = function() + -- Let's killall ffmpeg instance first after awesome (re)-starts if there's any + awful.spawn.easy_async_with_shell( + [[ + ps x | grep "ffmpeg -video_size" | grep -v grep | awk '{print $1}' | xargs kill + ]], + function(stdout) end + ) +end + +kill_existing_recording_ffmpeg() + +local turn_on_the_mic = function() + awful.spawn.easy_async_with_shell( + [[ + amixer set Capture cap + amixer set Capture ]].. scripts_tbl.user_mic_lvl ..[[% + ]], + function() end + ) +end + +local ffmpeg_stop_recording = function() + awesome.kill( + ffmpeg_pid, awesome.unix_signal.SIGINT + ) +end + +local create_notification = function(file_dir) + local open_video = naughty.action { + name = 'Open', + icon_only = false, + } + + local delete_video = naughty.action { + name = 'Delete', + icon_only = false, + } + + open_video:connect_signal( + 'invoked', + function() + awful.spawn('xdg-open ' .. file_dir, false) + end + ) + + delete_video:connect_signal( + 'invoked', + function() + awful.spawn('gio trash ' .. file_dir, false) + end + ) + + naughty.notification ({ + app_name = 'Screenshot Recorder', + timeout = 60, + title = 'Recording Finished!', + message = 'Recording can now be viewed.', + actions = { open_video, delete_video } + }) +end + +local ffmpeg_start_recording = function(audio, filename) + + local add_audio_str = ' ' + + if audio then + turn_on_the_mic() + add_audio_str = ' -f pulse -ac 2 -i default ' + end + + ffmpeg_pid = awful.spawn.easy_async_with_shell( + [[ + file_name=]] .. filename .. [[ + + ffmpeg -video_size ]] .. scripts_tbl.user_resolution .. [[ -framerate ]] .. scripts_tbl.user_fps .. [[ -f x11grab \ + -i :0.0+]] .. scripts_tbl.user_offset .. add_audio_str .. [[ $file_name + ]], + function(stdout, stderr) + + if stderr and stderr:match('Invalid argument') then + naughty.notification({ + app_name = 'Screen Recorder', + title = 'Invalid Configuration!', + message = 'Please, put a valid settings!', + timeout = 60, + urgency = 'normal' + }) + awesome.emit_signal('widget::screen_recorder') + return + end + create_notification(filename) + end + ) +end + +local create_unique_filename = function(audio) + awful.spawn.easy_async_with_shell( + [[ + dir=]] .. scripts_tbl.user_dir .. [[ + date=$(date '+%Y-%m-%d_%H-%M-%S') + format=.mp4 + + echo ${dir}${date}${format} | tr -d '\n' + ]], + function(stdout) + local filename = stdout + ffmpeg_start_recording(audio, filename) + end + ) +end + +scripts_tbl.start_recording = function(audio_mode) + create_save_directory() + create_unique_filename(audio_mode) +end + +scripts_tbl.stop_recording = function() + ffmpeg_stop_recording() +end + + +return scripts_tbl \ No newline at end of file diff --git a/awesome/widget/screen-recorder/screen-recorder-ui-backend.lua b/awesome/widget/screen-recorder/screen-recorder-ui-backend.lua new file mode 100644 index 0000000..f1cbab5 --- /dev/null +++ b/awesome/widget/screen-recorder/screen-recorder-ui-backend.lua @@ -0,0 +1,597 @@ +local wibox = require('wibox') +local awful = require('awful') +local gears = require('gears') +local naughty = require('naughty') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/screen-recorder/icons/' + +-- The screen-recorders scripting +local screen_rec_backend = require('widget.screen-recorder.screen-recorder-scripts') + + +-- The screen-recorder's UI +local screen_rec_ui = require('widget.screen-recorder.screen-recorder-ui') + + +-- User Preferences + +local sr_user_resolution = screen_rec_backend.user_resolution +local sr_user_offset = screen_rec_backend.user_offset +local sr_user_audio = screen_rec_backend.user_audio +local sr_user_update = screen_rec_backend.update_user_settings + +-- Panel UIs + +local sr_toggle_imgbox = screen_rec_ui.screen_rec_toggle_imgbox +local sr_toggle_button = screen_rec_ui.screen_rec_toggle_button +local sr_countdown_text = screen_rec_ui.screen_rec_countdown_txt +local sr_main_imgbox = screen_rec_ui.screen_rec_main_imgbox +local sr_main_button = screen_rec_ui.screen_rec_main_button +local sr_audio_imgbox = screen_rec_ui.screen_rec_audio_imgbox +local sr_audio_button = screen_rec_ui.screen_rec_audio_button +local sr_settings_button = screen_rec_ui.screen_rec_settings_button +local sr_close_button = screen_rec_ui.screen_rec_close_button + + +-- Settings UIs + +local sr_back_button = screen_rec_ui.screen_rec_back_button + +local sr_resolution_box = screen_rec_ui.screen_rec_res_txtbox +local sr_offset_box = screen_rec_ui.screen_rec_offset_txtbox + +local sr_resolution_tbox = sr_resolution_box:get_children_by_id('res_tbox')[1] +local sr_offset_tbox = sr_offset_box:get_children_by_id('offset_tbox')[1] + + +-- Main Scripts + +local sr_start_recording = screen_rec_backend.start_recording +local sr_stop_recording = screen_rec_backend.stop_recording + + +-- Active Screen Recorder +local sr_screen = nil + + +-- Active textbox +local sr_active_tbox = nil + + +-- Status variables + +local status_countdown = false +local status_recording = false + +local status_audio = sr_user_audio + + +-- Update UI on startup using the user config + +sr_resolution_tbox:set_markup('' .. sr_user_resolution .. "") +sr_offset_tbox:set_markup('' .. sr_user_offset .. "") + +local sr_res_default_markup = sr_resolution_tbox:get_markup() +local sr_offset_default_markup = sr_offset_tbox:get_markup() + + +if status_audio then + sr_audio_button.bg = '#EE4F84' .. '66' +else + sr_audio_button.bg = beautiful.groups_bg +end + + +-- Textbox ui manipulators + +local emphasize_inactive_tbox = function() + if sr_active_tbox == 'res_tbox' then + + sr_resolution_box.shape_border_width = dpi(0) + sr_resolution_box.shape_border_color = beautiful.transparent + + elseif sr_active_tbox == 'offset_tbox' then + + sr_offset_box.shape_border_width = dpi(0) + sr_offset_box.shape_border_color = beautiful.transparent + end + + sr_active_tbox = nil +end + +local emphasize_active_tbox = function() + + if sr_active_tbox == 'res_tbox' then + + sr_resolution_box.border_width = dpi(1) + sr_resolution_box.border_color = '#F2F2F2AA' + + elseif sr_active_tbox == 'offset_tbox' then + + sr_offset_box.border_width = dpi(1) + sr_offset_box.border_color = '#F2F2F2AA' + + end + +end + + +-- Delete, reset and write to the textbox + +local write_to_textbox = function(char) + + -- naughty.notification({message=sr_active_tbox}) + + if sr_active_tbox == 'res_tbox' and (char:match('%d') or char == 'x') then + + if sr_resolution_tbox:get_markup() == sr_res_default_markup then + sr_resolution_tbox:set_text('') + end + + if tonumber(#sr_resolution_tbox:get_text()) <= 8 then + sr_resolution_tbox:set_text(sr_resolution_tbox:get_text() .. char) + end + + elseif sr_active_tbox == 'offset_tbox' and (char:match('%d') or char == ',') then + + if sr_offset_tbox:get_markup() == sr_offset_default_markup then + sr_offset_tbox:set_text('') + end + + sr_offset_tbox:set_text(sr_offset_tbox:get_text() .. char) + end +end + + +local reset_textbox = function() + + if sr_active_tbox == 'res_tbox' then + + sr_resolution_tbox:set_markup(sr_res_default_markup) + + elseif sr_active_tbox == 'offset_tbox' then + + sr_offset_tbox:set_markup(sr_offset_default_markup) + + end + + emphasize_inactive_tbox() + +end + + +-- Set audio mode + + +local sr_audio_mode = function() + + if not status_recording and not status_countdown then + + -- screen_rec_audio_button + + if status_audio then + + status_audio = false + + sr_audio_button.bg = beautiful.groups_bg + + else + + status_audio = true + + sr_audio_button.bg = '#EE4F84' .. '66' + + end + + end + +end + + +local delete_key = function() + + if sr_active_tbox == 'res_tbox' then + + if tonumber(#sr_resolution_tbox:get_text()) == 1 then + reset_textbox() + return + end + + sr_resolution_tbox:set_text(sr_resolution_tbox:get_text():sub(1, -2)) + + + elseif sr_active_tbox == 'offset_tbox' then + + if tonumber(#sr_offset_tbox:get_text()) == 1 then + reset_textbox() + return + end + + sr_offset_tbox:set_text(sr_offset_tbox:get_text():sub(1, -2)) + + end + +end + + +local apply_new_settings = function() + + -- Get the text on texbox + sr_user_resolution = sr_resolution_tbox:get_text() + sr_user_offset = sr_offset_tbox:get_text() + + -- Apply new settings + sr_user_update(sr_user_resolution, sr_user_offset, status_audio) + + + -- Debugger + screen_rec_backend.check_settings() + +end + + +-- Settings Key grabber + +local settings_updater = awful.keygrabber { + auto_start = true, + stop_event = 'release', + keypressed_callback = function(self, mod, key, command) + if key == 'BackSpace' then + delete_key() + end + end, + keyreleased_callback = function(self, mod, key, command) + + if key == 'Return' then + apply_new_settings() + self:stop() + end + + if key == 'Escape' then + self:stop() + reset_textbox() + end + + if key:match('%d') or key == 'x' or key == ',' then + write_to_textbox(key) + end + + end +} + + +-- Textboxes + + +sr_resolution_tbox:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + emphasize_inactive_tbox() + + sr_active_tbox = 'res_tbox' + + emphasize_active_tbox() + + settings_updater:start() + end + ) + ) +) + +sr_offset_tbox:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + emphasize_inactive_tbox() + + sr_active_tbox = 'offset_tbox' + + emphasize_active_tbox() + + settings_updater:start() + end + ) + ) +) + + +-- UI switcher + + +local sr_navigation_reset = function() + if sr_screen then + local recorder_panel = sr_screen:get_children_by_id('recorder_panel')[1] + local recorder_settings = sr_screen:get_children_by_id('recorder_settings')[1] + + recorder_settings.visible = false + recorder_panel.visible = true + end +end + +local sr_navigation = function() + + if sr_screen then + + local recorder_panel = sr_screen:get_children_by_id('recorder_panel')[1] + local recorder_settings = sr_screen:get_children_by_id('recorder_settings')[1] + + if recorder_panel.visible then + recorder_panel.visible = false + recorder_settings.visible = true + else + recorder_settings.visible = false + recorder_panel.visible = true + + end + + end + +end + +sr_settings_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + if not status_recording and not status_countdown then + sr_navigation() + end + end + ) + ) +) + + +sr_back_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + -- Save settings + apply_new_settings() + + -- Reset textbox UI + emphasize_inactive_tbox() + + -- Go back to UI Panel + sr_navigation() + end + ) + ) +) + +-- Close button functions and buttons + +local screen_rec_close = function() + + for s in screen do + s.recorder_screen.visible = false + end + + settings_updater:stop() + + sr_navigation_reset() + sr_screen = nil +end + +sr_close_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + screen_rec_close() + end + ) + ) +) + +-- Right click to exit + +local screen_close_on_rmb = function(widget) + widget:buttons( + gears.table.join( + awful.button( + {}, + 3, + nil, + function() + screen_rec_close() + end + ) + ) + ) +end + +-- Open recorder screen + +sr_toggle_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + for s in screen do + s.recorder_screen.visible = false + end + + sr_screen = awful.screen.focused().recorder_screen + + screen_close_on_rmb(sr_screen) + + sr_screen.visible = not sr_screen.visible + end + ) + ) +) + +-- Start Recording + +local sr_recording_start = function() + + status_countdown = false + status_recording = true + + local sr_screen = awful.screen.focused().recorder_screen + + -- Hide recorder screen + sr_screen.visible = false + + -- Manipulate UIs + sr_toggle_imgbox:set_image(widget_icon_dir .. 'recording-button' .. '.svg') + sr_main_imgbox:set_image(widget_icon_dir .. 'recorder-on' .. '.svg') + + + sr_start_recording(status_audio) + +end + + +-- Stop Recording + + +local sr_recording_stop = function() + + status_recording = false + status_audio = false + + -- Manipulate UIs + sr_toggle_imgbox:set_image(widget_icon_dir .. 'start-recording-button' .. '.svg') + sr_main_imgbox:set_image(widget_icon_dir .. 'recorder-off' .. '.svg') + + + sr_stop_recording() + +end + +awesome.connect_signal('widget::screen_recorder', + function() + sr_recording_stop() + end +) + +-- Countdown timer functions + +local countdown_timer = nil + +local counter_timer = function() + + status_countdown = true + + local seconds = 3 + + countdown_timer = gears.timer.start_new( + 1, + function() + if seconds == 0 then + + sr_countdown_text.opacity = 0.0 + + -- Start recording function + sr_recording_start() + + sr_countdown_text:emit_signal('widget::redraw_needed') + return false + + else + + sr_main_imgbox:set_image(widget_icon_dir .. 'recorder-countdown' .. '.svg') + + sr_countdown_text.opacity = 1.0 + sr_countdown_text:set_text(tostring(seconds)) + + sr_countdown_text:emit_signal('widget::redraw_needed') + end + + seconds = seconds - 1 + + return true + end + ) + +end + + +-- Stop Countdown timer + + +local sr_countdown_stop = function() + + countdown_timer:stop() + + status_countdown = false + + sr_main_imgbox:set_image(widget_icon_dir .. 'recorder-off' .. '.svg') + + sr_countdown_text.opacity = 0.0 + sr_countdown_text:emit_signal('widget::redraw_needed') + +end + + +sr_audio_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + sr_audio_mode() + end + ) + ) +) + +-- Main button functions and buttons + +local status_checker = function() + + if status_recording and not status_countdown then + + -- Stop recording + sr_recording_stop() + return + + elseif not status_recording and status_countdown then + + -- Stop timer + sr_countdown_stop() + return + end + + + -- Start counting down + counter_timer() + +end + + +sr_main_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + status_checker() + end + ) + ) +) \ No newline at end of file diff --git a/awesome/widget/screen-recorder/screen-recorder-ui.lua b/awesome/widget/screen-recorder/screen-recorder-ui.lua new file mode 100644 index 0000000..df51f4f --- /dev/null +++ b/awesome/widget/screen-recorder/screen-recorder-ui.lua @@ -0,0 +1,352 @@ +local awful = require('awful') +local gears = require('gears') +local wibox = require('wibox') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/screen-recorder/icons/' + +local record_tbl = {} + +-- Panel UI + +record_tbl.screen_rec_toggle_imgbox = wibox.widget { + image = widget_icon_dir .. 'start-recording-button' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_toggle_button = wibox.widget { + { + record_tbl.screen_rec_toggle_imgbox, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +record_tbl.screen_rec_countdown_txt = wibox.widget { + id = 'countdown_text', + font = 'SF Pro Text Bold 64', + text = '4', + align = 'center', + valign = 'bottom', + opacity = 0.0, + widget = wibox.widget.textbox +} + +record_tbl.screen_rec_main_imgbox = wibox.widget { + image = widget_icon_dir .. 'recorder-off' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_main_button = wibox.widget { + { + { + { + record_tbl.screen_rec_main_imgbox, + margins = dpi(24), + widget = wibox.container.margin + }, + widget = clickable_container + }, + forced_width = dpi(200), + forced_height = dpi(200), + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background + }, + margins = dpi(24), + widget = wibox.container.margin +} + + +record_tbl.screen_rec_audio_imgbox = wibox.widget { + image = widget_icon_dir .. 'audio' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_audio_button = wibox.widget { + { + nil, + { + { + record_tbl.screen_rec_audio_imgbox, + margins = dpi(16), + widget = wibox.container.margin + }, + widget = clickable_container + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + }, + forced_width = dpi(60), + forced_height = dpi(60), + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background +} + +record_tbl.screen_rec_close_imgbox = wibox.widget { + image = widget_icon_dir .. 'close-screen' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_close_button = wibox.widget { + { + nil, + { + { + record_tbl.screen_rec_close_imgbox, + margins = dpi(16), + widget = wibox.container.margin + }, + widget = clickable_container + }, + nil, + expand = 'none', + layout = wibox.layout.align.horizontal + }, + forced_width = dpi(60), + forced_height = dpi(60), + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background +} + +record_tbl.screen_rec_settings_imgbox = wibox.widget { + image = widget_icon_dir .. 'settings' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_settings_button = wibox.widget { + { + nil, + { + { + record_tbl.screen_rec_settings_imgbox, + margins = dpi(16), + widget = wibox.container.margin + }, + widget = clickable_container + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + }, + forced_width = dpi(60), + forced_height = dpi(60), + bg = beautiful.groups_bg, + shape = gears.shape.circle, + widget = wibox.container.background +} + +record_tbl.screen_rec_back_imgbox = wibox.widget { + image = widget_icon_dir .. 'back' .. '.svg', + resize = true, + widget = wibox.widget.imagebox +} + +record_tbl.screen_rec_back_button = wibox.widget { + { + nil, + { + { + record_tbl.screen_rec_back_imgbox, + margins = dpi(16), + widget = wibox.container.margin + }, + widget = clickable_container + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical + }, + forced_width = dpi(48), + forced_height = dpi(48), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) + end, + widget = wibox.container.background +} + +record_tbl.screen_rec_back_txt = wibox.widget { + { + text = 'Back', + font = 'SF Pro Display Bold 16', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + margins = dpi(5), + widget = wibox.container.margin + +} + +record_tbl.screen_rec_res_txt = wibox.widget { + { + text = 'Resolution', + font = 'SF Pro Display Bold 16', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + margins = dpi(5), + widget = wibox.container.margin + +} + +record_tbl.screen_rec_res_txtbox = wibox.widget { + { + { + { + id = 'res_tbox', + markup = '' .. '1366x768' .. "", + font = 'SF Pro Display Bold 16', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + margins = dpi(5), + widget = wibox.container.margin + }, + widget = clickable_container + }, + forced_width = dpi(60), + forced_height = dpi(60), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) + end, + widget = wibox.container.background + +} + +record_tbl.screen_rec_offset_txt = wibox.widget { + { + text = 'Offset', + font = 'SF Pro Display Bold 16', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + margins = dpi(5), + widget = wibox.container.margin + +} + +record_tbl.screen_rec_offset_txtbox = wibox.widget { + { + { + { + id = 'offset_tbox', + markup = '' .. '0,0' .. "", + font = 'SF Pro Display Bold 16', + ellipsize = 'start', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + margins = dpi(5), + widget = wibox.container.margin + }, + widget = clickable_container + }, + forced_width = dpi(60), + forced_height = dpi(60), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) + end, + widget = wibox.container.background + +} + +screen.connect_signal("request::desktop_decoration", function(s) + + s.recorder_screen = wibox + ({ + ontop = true, + screen = s, + type = 'dock', + height = s.geometry.height, + width = s.geometry.width, + x = s.geometry.x, + y = s.geometry.y, + bg = beautiful.background, + fg = beautiful.fg_normal + }) + + s.recorder_screen : setup { + layout = wibox.layout.stack, + { + id = 'recorder_panel', + visible = true, + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + record_tbl.screen_rec_countdown_txt, + { + layout = wibox.layout.align.horizontal, + record_tbl.screen_rec_settings_button, + record_tbl.screen_rec_main_button, + record_tbl.screen_rec_audio_button + }, + record_tbl.screen_rec_close_button, + }, + nil + + }, + nil + }, + { + id = 'recorder_settings', + visible = false, + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + forced_width = dpi(240), + spacing = dpi(10), + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(10), + record_tbl.screen_rec_back_button, + record_tbl.screen_rec_back_txt, + }, + record_tbl.screen_rec_res_txt, + record_tbl.screen_rec_res_txtbox, + record_tbl.screen_rec_offset_txt, + record_tbl.screen_rec_offset_txtbox + }, + nil + + }, + nil + } + } + +end) + +return record_tbl \ No newline at end of file diff --git a/awesome/widget/search-apps/icons/app-launcher.svg b/awesome/widget/search-apps/icons/app-launcher.svg new file mode 100644 index 0000000..616879f --- /dev/null +++ b/awesome/widget/search-apps/icons/app-launcher.svg @@ -0,0 +1,257 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/search-apps/init.lua b/awesome/widget/search-apps/init.lua new file mode 100644 index 0000000..d578091 --- /dev/null +++ b/awesome/widget/search-apps/init.lua @@ -0,0 +1,67 @@ +------------------------------------------------- +-- Rofi toggler widget for Awesome Window Manager +-- Shows the application list +-- Use rofi-git master branch +------------------------------------------------- + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local filesystem = gears.filesystem +local dpi = require('beautiful').xresources.apply_dpi + +local apps = require('configuration.apps') +local clickable_container = require('widget.clickable-container') + +local config_dir = filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. '/widget/search-apps/icons/' + +local return_button = function() + + local widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'app-launcher.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal + } + + local widget_button = wibox.widget { + { + widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container + } + + widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + local focused = awful.screen.focused() + + if focused.left_panel then + focused.left_panel:HideDashboard() + focused.left_panel.opened = false + end + if focused.right_panel then + focused.right_panel:HideDashboard() + end + awful.spawn(apps.default.rofiappmenu, false) + end + ) + ) + ) + + + return widget_button +end + +return return_button \ No newline at end of file diff --git a/awesome/widget/social-media/icons/facebook.svg b/awesome/widget/social-media/icons/facebook.svg new file mode 100644 index 0000000..1052f58 --- /dev/null +++ b/awesome/widget/social-media/icons/facebook.svg @@ -0,0 +1,4 @@ + + + + diff --git a/awesome/widget/social-media/icons/instagram.svg b/awesome/widget/social-media/icons/instagram.svg new file mode 100644 index 0000000..afda8b7 --- /dev/null +++ b/awesome/widget/social-media/icons/instagram.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/awesome/widget/social-media/icons/reddit.svg b/awesome/widget/social-media/icons/reddit.svg new file mode 100644 index 0000000..b94ef6f --- /dev/null +++ b/awesome/widget/social-media/icons/reddit.svg @@ -0,0 +1,2 @@ + + diff --git a/awesome/widget/social-media/icons/twitter.svg b/awesome/widget/social-media/icons/twitter.svg new file mode 100644 index 0000000..76840b2 --- /dev/null +++ b/awesome/widget/social-media/icons/twitter.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/awesome/widget/social-media/init.lua b/awesome/widget/social-media/init.lua new file mode 100644 index 0000000..ce049c7 --- /dev/null +++ b/awesome/widget/social-media/init.lua @@ -0,0 +1,130 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/social-media/icons/' + +local decorate_widget = function(widgets) + + return wibox.widget { + widgets, + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.rounded_rect(cr, width, height, groups_radius) + end, + widget = wibox.container.background + } + +end + +local build_social_button = function(website) + + local social_imgbox = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. website .. '.svg', + widget = wibox.widget.imagebox, + resize = true, + forced_height = dpi(35) + }, + layout = wibox.layout.align.horizontal + } + + local social_button = wibox.widget { + { + social_imgbox, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container + } + + local website_url = nil + if website == 'facebook' then + website_url = 'https://facebook.com' + + elseif website == 'reddit' then + website_url = 'https://reddit.com' + + elseif website == 'twitter' then + website_url = 'https://twitter.com' + + elseif website == 'instagram' then + website_url = 'https://instagram.com' + + end + + social_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn({"xdg-open", website_url}, false) + end + ) + ) + ) + + local social_name = website:sub(1,1):upper() .. website:sub(2) + + local social_tbox = wibox.widget { + text = social_name, + font = 'SF Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox + } + + return wibox.widget { + layout = wibox.layout.fixed.vertical, + spacing = dpi(5), + { + layout = wibox.layout.align.horizontal, + expand = 'none', + nil, + decorate_widget(social_button), + nil + }, + social_tbox + } +end + + +local social_layout = wibox.widget { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(5), + build_social_button('reddit'), + build_social_button('facebook'), + build_social_button('twitter'), + build_social_button('instagram'), +} + +local social = wibox.widget { + { + { + expand = "none", + layout = wibox.layout.align.horizontal, + nil, + social_layout, + nil + }, + margins = dpi(10), + widget = wibox.container.margin, + }, + forced_height = dpi(92), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius) + end, + widget = wibox.container.background +} + +return social diff --git a/awesome/widget/tag-list.lua b/awesome/widget/tag-list.lua new file mode 100644 index 0000000..8811ff2 --- /dev/null +++ b/awesome/widget/tag-list.lua @@ -0,0 +1,172 @@ +local awful = require('awful') +local wibox = require('wibox') +local dpi = require('beautiful').xresources.apply_dpi +local capi = {button = _G.button} +local clickable_container = require('widget.clickable-container') +local modkey = require('configuration.keys.mod').modKey +--- Common method to create buttons. +-- @tab buttons +-- @param object +-- @treturn table +local function create_buttons(buttons, object) + if buttons then + local btns = {} + for _, b in ipairs(buttons) do + -- Create a proxy button object: it will receive the real + -- press and release events, and will propagate them to the + -- button object the user provided, but with the object as + -- argument. + local btn = capi.button {modifiers = b.modifiers, button = b.button} + btn:connect_signal( + 'press', + function() + b:emit_signal('press', object) + end + ) + btn:connect_signal( + 'release', + function() + b:emit_signal('release', object) + end + ) + btns[#btns + 1] = btn + end + + return btns + end +end + +local function list_update(w, buttons, label, data, objects) + -- update the widgets, creating them if needed + w:reset() + for i, o in ipairs(objects) do + local cache = data[o] + local ib, tb, bgb, tbm, ibm, l, bg_clickable + if cache then + ib = cache.ib + tb = cache.tb + bgb = cache.bgb + tbm = cache.tbm + ibm = cache.ibm + else + ib = wibox.widget.imagebox() + tb = wibox.widget.textbox() + bgb = wibox.container.background() + tbm = wibox.widget { + tb, + left = dpi(4), + right = dpi(16), + widget = wibox.container.margin + } + ibm = wibox.widget { + ib, + margins = dpi(10), + widget = wibox.container.margin + } + l = wibox.layout.fixed.horizontal() + bg_clickable = clickable_container() + + -- All of this is added in a fixed widget + l:fill_space(true) + l:add(ibm) + -- l:add(tbm) + bg_clickable:set_widget(l) + + -- And all of this gets a background + bgb:set_widget(bg_clickable) + + bgb:buttons(create_buttons(buttons, o)) + + data[o] = { + ib = ib, + tb = tb, + bgb = bgb, + tbm = tbm, + ibm = ibm + } + end + + local text, bg, bg_image, icon, args = label(o, tb) + args = args or {} + + -- The text might be invalid, so use pcall. + if text == nil or text == '' then + tbm:set_margins(0) + else + if not tb:set_markup_silently(text) then + tb:set_markup('<Invalid text>') + end + end + bgb:set_bg(bg) + if type(bg_image) == 'function' then + -- TODO: Why does this pass nil as an argument? + bg_image = bg_image(tb, o, nil, objects, i) + end + bgb:set_bgimage(bg_image) + if icon then + ib.image = icon + else + ibm:set_margins(0) + end + + bgb.shape = args.shape + bgb.shape_border_width = args.shape_border_width + bgb.shape_border_color = args.shape_border_color + + w:add(bgb) + end +end + +local TagList = function(s) + return awful.widget.taglist( + s, + awful.widget.taglist.filter.all, + awful.util.table.join( + awful.button( + {}, + 1, + function(t) + t:view_only() + end + ), + awful.button( + {modkey}, + 1, + function(t) + if _G.client.focus then + _G.client.focus:move_to_tag(t) + t:view_only() + end + end + ), + awful.button({}, 3, awful.tag.viewtoggle), + awful.button( + {modkey}, + 3, + function(t) + if _G.client.focus then + _G.client.focus:toggle_tag(t) + end + end + ), + awful.button( + {}, + 4, + function(t) + awful.tag.viewprev(t.screen) + end + ), + awful.button( + {}, + 5, + function(t) + awful.tag.viewnext(t.screen) + end + ) + ), + {}, + list_update, + wibox.layout.fixed.vertical() + ) +end +return TagList diff --git a/awesome/widget/task-list.lua b/awesome/widget/task-list.lua new file mode 100644 index 0000000..9f8fece --- /dev/null +++ b/awesome/widget/task-list.lua @@ -0,0 +1,248 @@ +local awful = require('awful') +local wibox = require('wibox') +local dpi = require('beautiful').xresources.apply_dpi +local capi = {button = _G.button} +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local icons = require('theme.icons') + +--- sub string for utf8 format +-- @s the string need to be sub +-- @i index of start position +-- @j index of end position +local function utf8_sub(s, i, j) + i = utf8.offset(s, i) + j = (utf8.offset(s, j + 1) or j + 1) - 1 + return gears.string.xml_escape(s:sub(i, j)) +end + +--- Common method to create buttons. +-- @tab buttons +-- @param object +-- @treturn table +local function create_buttons(buttons, object) + if buttons then + local btns = {} + for _, b in ipairs(buttons) do + -- Create a proxy button object: it will receive the real + -- press and release events, and will propagate them to the + -- button object the user provided, but with the object as + -- argument. + local btn = capi.button {modifiers = b.modifiers, button = b.button} + btn:connect_signal( + 'press', + function() + b:emit_signal('press', object) + end + ) + btn:connect_signal( + 'release', + function() + b:emit_signal('release', object) + end + ) + btns[#btns + 1] = btn + end + + return btns + end +end + +local function list_update(w, buttons, label, data, objects) + -- update the widgets, creating them if needed + w:reset() + for i, o in ipairs(objects) do + local cache = data[o] + local ib, cb, tb, cbm, bgb, tbm, ibm, tt, l, ll, bg_clickable + if cache then + ib = cache.ib + tb = cache.tb + bgb = cache.bgb + tbm = cache.tbm + ibm = cache.ibm + tt = cache.tt + else + ib = wibox.widget.imagebox() + tb = wibox.widget.textbox() + cb = wibox.widget { + { + { + image = icons.close, + resize = true, + widget = wibox.widget.imagebox + }, + margins = dpi(4), + widget = wibox.container.margin + }, + widget = clickable_container + } + cb.shape = gears.shape.circle + cbm = wibox.widget { + -- 4, 8 ,12 ,12 -- close button + cb, + left = dpi(4), + right = dpi(8), + top = dpi(4), + bottom = dpi(4), + widget = wibox.container.margin + } + cbm:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + o:kill() + end + ) + ) + ) + bg_clickable = clickable_container() + bgb = wibox.container.background() + tbm = wibox.widget { + tb, + left = dpi(4), + right = dpi(4), + widget = wibox.container.margin + } + ibm = wibox.widget { + -- 12 top bottom + ib, + left = dpi(6), + right = dpi(6), + top = dpi(6), + bottom = dpi(6), + widget = wibox.container.margin + } + l = wibox.layout.fixed.horizontal() + ll = wibox.layout.fixed.horizontal() + + -- All of this is added in a fixed widget + l:fill_space(true) + l:add(ibm) + l:add(tbm) + ll:add(l) + ll:add(cbm) + + bg_clickable:set_widget(ll) + -- And all of this gets a background + bgb:set_widget(bg_clickable) + + l:buttons(create_buttons(buttons, o)) + + -- Tooltip to display whole title, if it was truncated + tt = awful.tooltip({ + objects = {tb}, + mode = 'outside', + align = 'bottom', + delay_show = 1, + }) + + data[o] = { + ib = ib, + tb = tb, + bgb = bgb, + tbm = tbm, + ibm = ibm, + tt = tt + } + end + + local text, bg, bg_image, icon, args = label(o, tb) + args = args or {} + + -- The text might be invalid, so use pcall. + if text == nil or text == '' then + tbm:set_margins(0) + else + -- truncate when title is too long + local text_only = text:match('>(.-)<') + if (text_only:len() > 24) then + text = text:gsub('>(.-)<', '>' .. utf8_sub(text_only,1,21) .. '...<') + tt:set_text(text_only) + tt:add_to_object(tb) + else + tt:remove_from_object(tb) + end + if not tb:set_markup_silently(text) then + tb:set_markup('<Invalid text>') + end + end + bgb:set_bg(bg) + if type(bg_image) == 'function' then + -- TODO: Why does this pass nil as an argument? + bg_image = bg_image(tb, o, nil, objects, i) + end + bgb:set_bgimage(bg_image) + if icon then + ib.image = gears.surface(icon) + else + ibm:set_margins(0) + end + + bgb.shape = args.shape + bgb.shape_border_width = args.shape_border_width + bgb.shape_border_color = args.shape_border_color + + w:add(bgb) + end +end +local tasklist_buttons = + awful.util.table.join( + awful.button( + {}, + 1, + function(c) + if c == _G.client.focus then + c.minimized = true + else + -- Without this, the following + -- :isvisible() makes no sense + c.minimized = false + if not c:isvisible() and c.first_tag then + c.first_tag:view_only() + end + -- This will also un-minimize + -- the client, if needed + _G.client.focus = c + c:raise() + end + end + ), + awful.button( + {}, + 2, + function(c) + c:kill() + end + ), + awful.button( + {}, + 4, + function() + awful.client.focus.byidx(1) + end + ), + awful.button( + {}, + 5, + function() + awful.client.focus.byidx(-1) + end + ) +) + +local TaskList = function(s) + return awful.widget.tasklist( + s, + awful.widget.tasklist.filter.currenttags, + tasklist_buttons, + {}, + list_update, + wibox.layout.fixed.horizontal() + ) +end + +return TaskList diff --git a/awesome/widget/temperature/temperature-meter.lua b/awesome/widget/temperature/temperature-meter.lua new file mode 100644 index 0000000..5fe2e4b --- /dev/null +++ b/awesome/widget/temperature/temperature-meter.lua @@ -0,0 +1,63 @@ +local wibox = require('wibox') +local gears = require('gears') +local beautiful = require('beautiful') + +local watch = require('awful.widget.watch') +local icons = require('theme.icons') + +local dpi = beautiful.xresources.apply_dpi + +local slider = wibox.widget { + nil, + { + id = 'temp_status', + max_value = 100, + value = 29, + forced_height = dpi(2), + color = beautiful.fg_normal, + background_color = beautiful.groups_bg, + shape = gears.shape.rounded_rect, + widget = wibox.widget.progressbar + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +local max_temp = 80 + +watch( + 'bash -c "cat /sys/class/thermal/thermal_zone0/temp"', + 5, + function(_, stdout) + local temp = stdout:match('(%d+)') + slider.temp_status:set_value((temp / 1000) / max_temp * 100) + collectgarbage('collect') + end +) + + +local temperature_meter = wibox.widget { + { + { + { + image = icons.thermometer, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return temperature_meter diff --git a/awesome/widget/tray-toggler/icons/left-arrow.svg b/awesome/widget/tray-toggler/icons/left-arrow.svg new file mode 100644 index 0000000..f0e76e5 --- /dev/null +++ b/awesome/widget/tray-toggler/icons/left-arrow.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/tray-toggler/icons/right-arrow.svg b/awesome/widget/tray-toggler/icons/right-arrow.svg new file mode 100644 index 0000000..7446424 --- /dev/null +++ b/awesome/widget/tray-toggler/icons/right-arrow.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/tray-toggler/init.lua b/awesome/widget/tray-toggler/init.lua new file mode 100644 index 0000000..af5765d --- /dev/null +++ b/awesome/widget/tray-toggler/init.lua @@ -0,0 +1,80 @@ +------------------------------------------------- +-- Toggle System tray +------------------------------------------------- + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local dpi = require('beautiful').xresources.apply_dpi + +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/tray-toggler/icons/' + +local widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'right-arrow' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local widget_button = wibox.widget { + { + widget, + margins = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awesome.emit_signal("widget::systray:toggle") + end + ) + ) +) + + +-- Listen to signal +awesome.connect_signal("widget::systray:toggle", function() + + if screen.primary.systray then + + if screen.primary.systray.visible ~= true then + + widget.icon:set_image(gears.surface.load_uncached(widget_icon_dir .. 'left-arrow' .. '.svg')) + else + + widget.icon:set_image(gears.surface.load_uncached(widget_icon_dir .. 'right-arrow' .. '.svg')) + end + + screen.primary.systray.visible = not screen.primary.systray.visible + end + +end) + +-- Update icon on start-up +if screen.primary.systray then + + if screen.primary.systray.visible then + + widget.icon:set_image(widget_icon_dir .. 'right-arrow' .. '.svg') + + end + +end + +-- Show only the tray button in the primary screen +return awful.widget.only_on_screen(widget_button, 'primary') + diff --git a/awesome/widget/user-profile/init.lua b/awesome/widget/user-profile/init.lua new file mode 100644 index 0000000..eae9c17 --- /dev/null +++ b/awesome/widget/user-profile/init.lua @@ -0,0 +1,222 @@ +-- User profile widget +-- Optional dependency: +-- mugshot (use to update profile picture and information) + + +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') +local naughty = require('naughty') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local apps = require('configuration.apps') +local clickable_container = require('widget.clickable-container') + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'configuration/user-profile/' + +local user_icon_dir = '/var/lib/AccountsService/icons/' + +title_table = { + "Hey, I have a message for you", + "Listen here you little shit!", + "Le' me tell you a secret", + "I never lie", + "Message received from your boss" +} + +message_table = { + "Let me rate your face! Oops... It looks like I can't compute negative numbers. You're ugly af, sorry", + "Lookin' good today, now fuck off!", + "The last thing I want to do is hurt you. But it’s still on the list.", + "If I agreed with you we’d both be wrong.", + "I intend to live forever. So far, so good.", + "Jesus loves you, but everyone else thinks you’re an asshole.", + "Your baby is so ugly, you should have thrown it away and kept the stork.", + "If your brain was dynamite, there wouldn’t be enough to blow your hat off.", + "You are more disappointing than an unsalted pretzel.", + "Your kid is so ugly, he makes his Happy Meal cry.", + "Your secrets are always safe with me. I never even listen when you tell me them.", + "I only take you everywhere I go just so I don’t have to kiss you goodbye.", + "You look so pretty. Not at all gross, today.", + "It’s impossible to underestimate you.", + "I’m not insulting you, I’m describing you.", + "Keep rolling your eyes, you might eventually find a brain.", + "You bring everyone so much joy, when you leave the room.", + "I thought of you today. It reminded me to take out the trash.", + "You are the human version of period cramps.", + "You’re the reason God created the middle finger." +} + +local profile_imagebox = wibox.widget { + { + id = 'icon', + forced_height = dpi(45), + forced_width = dpi(45), + image = widget_icon_dir .. 'default' .. '.svg', + clip_shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) end, + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +profile_imagebox:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + naughty.notification({ + app_name = "FBI's ChatBot v69", + title = title_table[math.random(#title_table)], + message = message_table[math.random(#message_table)] .. + "\n\n- xXChatBOT69Xx", + urgency = 'normal' + }) + end + ) + ) +) + +local profile_name = wibox.widget { + font = "SF Pro Text Bold 14", + markup = 'User', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local distro_name = wibox.widget { + font = "SF Pro Text Regular 11", + markup = 'GNU/Linux', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local kernel_version = wibox.widget { + font = "SF Pro Text Regular 10", + markup = 'Linux', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local uptime_time = wibox.widget { + font = "SF Pro Text Regular 10", + markup = 'up 1 minute', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox +} + +local update_profile_image = function() + awful.spawn.easy_async_with_shell( + apps.bins.update_profile, + function(stdout) + stdout = stdout:gsub('%\n','') + if not stdout:match("default") then + profile_imagebox.icon:set_image(stdout) + else + profile_imagebox.icon:set_image(widget_icon_dir .. 'default.svg') + end + end + ) +end + +update_profile_image() + +awful.spawn.easy_async_with_shell( + "printf \"$(whoami)@$(hostname)\"", + function(stdout) + local stdout = stdout:gsub('%\n', '') + -- stdout = stdout:sub(1,1):upper() .. stdout:sub(2) + profile_name:set_markup(stdout) + end +) + +awful.spawn.easy_async_with_shell( + [[ + cat /etc/os-release | awk 'NR==1'| awk -F '"' '{print $2}' + ]], + function(stdout) + local distroname = stdout:gsub('%\n', '') + distro_name:set_markup(distroname) + end +) + +awful.spawn.easy_async_with_shell( + 'uname -r', + function(stdout) + local kname = stdout:gsub('%\n', '') + kernel_version:set_markup(kname) + end +) + +local update_uptime = function() + awful.spawn.easy_async_with_shell( + "uptime -p", + function(stdout) + local uptime = stdout:gsub('%\n','') + uptime_time:set_markup(uptime) + end + ) +end + +local uptime_updater_timer = gears.timer{ + timeout = 60, + autostart = true, + call_now = true, + callback = function() + update_uptime() + end +} + +local user_profile = wibox.widget { + { + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(10), + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + profile_imagebox, + nil + }, + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + profile_name, + distro_name, + kernel_version, + uptime_time + }, + nil + } + }, + margins = dpi(10), + widget = wibox.container.margin + }, + forced_height = dpi(92), + bg = beautiful.groups_bg, + shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, beautiful.groups_radius) end, + widget = wibox.container.background + +} + +user_profile:connect_signal( + 'mouse::enter', + function() + update_uptime() + end +) + +return user_profile diff --git a/awesome/widget/volume/volume-slider.lua b/awesome/widget/volume/volume-slider.lua new file mode 100644 index 0000000..6e16e63 --- /dev/null +++ b/awesome/widget/volume/volume-slider.lua @@ -0,0 +1,141 @@ +local wibox = require('wibox') +local gears = require('gears') +local awful = require('awful') +local beautiful = require('beautiful') + +local watch = awful.widget.watch +local spawn = awful.spawn + +local dpi = beautiful.xresources.apply_dpi + +local icons = require('theme.icons') + +local slider = wibox.widget { + nil, + { + id = 'vol_slider', + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(2), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +local volume_slider = slider.vol_slider + +volume_slider:connect_signal( + 'property::value', + function() + + local volume_level = volume_slider:get_value() + + spawn('amixer -D pulse sset Master ' .. + volume_level .. '%', + false + ) + + -- Update volume osd + awesome.emit_signal( + 'module::volume_osd', + volume_level + ) + + end +) + +volume_slider:buttons( + gears.table.join( + awful.button( + {}, + 4, + nil, + function() + if volume_slider:get_value() > 100 then + volume_slider:set_value(100) + return + end + volume_slider:set_value(volume_slider:get_value() + 5) + end + ), + awful.button( + {}, + 5, + nil, + function() + if volume_slider:get_value() < 0 then + volume_slider:set_value(0) + return + end + volume_slider:set_value(volume_slider:get_value() - 5) + end + ) + ) +) + + +local update_slider = function() + awful.spawn.easy_async_with_shell( + [[bash -c "amixer -D pulse sget Master"]], + function(stdout) + + local volume = string.match(stdout, '(%d?%d?%d)%%') + + volume_slider:set_value(tonumber(volume)) + end + ) + +end + +-- Update on startup +update_slider() + +-- The emit will come from the global keybind +awesome.connect_signal( + 'widget::volume', + function() + update_slider() + end +) + +-- The emit will come from the OSD +awesome.connect_signal( + 'widget::volume:update', + function(value) + volume_slider:set_value(tonumber(value)) + end +) + +local volume_setting = wibox.widget { + { + { + { + image = icons.volume, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return volume_setting diff --git a/awesome/widget/weather/icons/d_rain.svg b/awesome/widget/weather/icons/d_rain.svg new file mode 100644 index 0000000..44cacc1 --- /dev/null +++ b/awesome/widget/weather/icons/d_rain.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/dbroken_clouds.svg b/awesome/widget/weather/icons/dbroken_clouds.svg new file mode 100644 index 0000000..8fa8005 --- /dev/null +++ b/awesome/widget/weather/icons/dbroken_clouds.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/dfew_clouds.svg b/awesome/widget/weather/icons/dfew_clouds.svg new file mode 100644 index 0000000..a4f1fd3 --- /dev/null +++ b/awesome/widget/weather/icons/dfew_clouds.svg @@ -0,0 +1,72 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/dmist.svg b/awesome/widget/weather/icons/dmist.svg new file mode 100644 index 0000000..b23f3bf --- /dev/null +++ b/awesome/widget/weather/icons/dmist.svg @@ -0,0 +1,77 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/dscattered_clouds.svg b/awesome/widget/weather/icons/dscattered_clouds.svg new file mode 100644 index 0000000..9c0ebcb --- /dev/null +++ b/awesome/widget/weather/icons/dscattered_clouds.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/dshower_rain.svg b/awesome/widget/weather/icons/dshower_rain.svg new file mode 100644 index 0000000..3a88004 --- /dev/null +++ b/awesome/widget/weather/icons/dshower_rain.svg @@ -0,0 +1,72 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/dthunderstorm.svg b/awesome/widget/weather/icons/dthunderstorm.svg new file mode 100644 index 0000000..10375e4 --- /dev/null +++ b/awesome/widget/weather/icons/dthunderstorm.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/moon_icon.svg b/awesome/widget/weather/icons/moon_icon.svg new file mode 100644 index 0000000..b9e5c3a --- /dev/null +++ b/awesome/widget/weather/icons/moon_icon.svg @@ -0,0 +1,67 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/n_rain.svg b/awesome/widget/weather/icons/n_rain.svg new file mode 100644 index 0000000..3ba466a --- /dev/null +++ b/awesome/widget/weather/icons/n_rain.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/nbroken_clouds.svg b/awesome/widget/weather/icons/nbroken_clouds.svg new file mode 100644 index 0000000..d462c33 --- /dev/null +++ b/awesome/widget/weather/icons/nbroken_clouds.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/nfew_clouds.svg b/awesome/widget/weather/icons/nfew_clouds.svg new file mode 100644 index 0000000..74575ee --- /dev/null +++ b/awesome/widget/weather/icons/nfew_clouds.svg @@ -0,0 +1,83 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/nmist.svg b/awesome/widget/weather/icons/nmist.svg new file mode 100644 index 0000000..34d0e41 --- /dev/null +++ b/awesome/widget/weather/icons/nmist.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/nscattered_clouds.svg b/awesome/widget/weather/icons/nscattered_clouds.svg new file mode 100644 index 0000000..007e66b --- /dev/null +++ b/awesome/widget/weather/icons/nscattered_clouds.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/nshower_rain.svg b/awesome/widget/weather/icons/nshower_rain.svg new file mode 100644 index 0000000..50b4ebc --- /dev/null +++ b/awesome/widget/weather/icons/nshower_rain.svg @@ -0,0 +1,73 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/nthunderstorm.svg b/awesome/widget/weather/icons/nthunderstorm.svg new file mode 100644 index 0000000..73f67e5 --- /dev/null +++ b/awesome/widget/weather/icons/nthunderstorm.svg @@ -0,0 +1,78 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/refresh.svg b/awesome/widget/weather/icons/refresh.svg new file mode 100644 index 0000000..0eb9ef7 --- /dev/null +++ b/awesome/widget/weather/icons/refresh.svg @@ -0,0 +1,57 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/snow.svg b/awesome/widget/weather/icons/snow.svg new file mode 100644 index 0000000..f4fcc6a --- /dev/null +++ b/awesome/widget/weather/icons/snow.svg @@ -0,0 +1,63 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/sun_icon.svg b/awesome/widget/weather/icons/sun_icon.svg new file mode 100644 index 0000000..24ac40d --- /dev/null +++ b/awesome/widget/weather/icons/sun_icon.svg @@ -0,0 +1,64 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/awesome/widget/weather/icons/sunrise.svg b/awesome/widget/weather/icons/sunrise.svg new file mode 100644 index 0000000..f0e8a47 --- /dev/null +++ b/awesome/widget/weather/icons/sunrise.svg @@ -0,0 +1,77 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/sunset.svg b/awesome/widget/weather/icons/sunset.svg new file mode 100644 index 0000000..d60f574 --- /dev/null +++ b/awesome/widget/weather/icons/sunset.svg @@ -0,0 +1,72 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/awesome/widget/weather/icons/weather-error.svg b/awesome/widget/weather/icons/weather-error.svg new file mode 100644 index 0000000..afcb331 --- /dev/null +++ b/awesome/widget/weather/icons/weather-error.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/awesome/widget/weather/init.lua b/awesome/widget/weather/init.lua new file mode 100644 index 0000000..dee5371 --- /dev/null +++ b/awesome/widget/weather/init.lua @@ -0,0 +1,369 @@ +local awful = require('awful') +local beautiful = require('beautiful') +local naughty = require('naughty') +local wibox = require('wibox') +local gears = require('gears') + +local dpi = beautiful.xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/weather/icons/' + +local clickable_container = require('widget.clickable-container') + +local secrets = require('configuration.secrets') + +local key = secrets.weather.key +local city_id = secrets.weather.city_id +local units = secrets.weather.units + +local update_interval = 1200 + +local weather_icon_widget = wibox.widget { + { + id = 'icon', + image = widget_icon_dir .. 'weather-error.svg', + resize = true, + forced_height = dpi(45), + forced_width = dpi(45), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local sunrise_icon_widget = wibox.widget { + { + id = 'sunrise_icon', + image = widget_icon_dir .. 'sunrise.svg', + resize = true, + forced_height = dpi(18), + forced_width = dpi(18), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local sunset_icon_widget = wibox.widget { + { + id = 'sunset_icon', + image = widget_icon_dir .. 'sunset.svg', + resize = true, + forced_height = dpi(18), + forced_width = dpi(18), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local refresh_icon_widget = wibox.widget { + { + id = 'refresh_icon', + image = widget_icon_dir .. 'refresh.svg', + resize = true, + forced_height = dpi(18), + forced_width = dpi(18), + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.fixed.horizontal +} + +local refresh_button = clickable_container(refresh_icon_widget) +refresh_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awesome.emit_signal('widget::weather_fetch') + end + ) + ) +) + +local refresh_widget = wibox.widget { + refresh_button, + bg = beautiful.transparent, + shape = gears.shape.circle, + widget = wibox.container.background +} + +local weather_desc_temp = wibox.widget { + { + id = 'description', + markup = 'dust and clouds, -1000°C', + font = 'SF Pro Text Bold 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + id = 'scroll_container', + max_size = 345, + speed = 75, + expand = true, + direction = 'h', + step_function = wibox.container.scroll + .step_functions.waiting_nonlinear_back_and_forth, + fps = 30, + layout = wibox.container.scroll.horizontal, +} + +local weather_location = wibox.widget { + { + id = 'location', + markup = 'Earth, Milky Way', + font = 'SF Pro Text Regular 12', + align = 'left', + valign = 'center', + widget = wibox.widget.textbox + }, + id = 'scroll_container', + max_size = 345, + speed = 75, + expand = true, + direction = 'h', + step_function = wibox.container.scroll + .step_functions.waiting_nonlinear_back_and_forth, + fps = 30, + layout = wibox.container.scroll.horizontal, +} + +local weather_sunrise = wibox.widget { + markup = "00:00", + font = 'SF Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local weather_sunset = wibox.widget { + markup = "00:00", + font = 'SF Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local weather_data_time = wibox.widget { + markup = "00:00", + font = 'SF Pro Text Regular 10', + align = 'center', + valign = 'center', + widget = wibox.widget.textbox +} + +local weather_report = wibox.widget { + { + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(10), + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + weather_icon_widget, + nil + }, + { + layout = wibox.layout.align.vertical, + expand = 'none', + nil, + { + layout = wibox.layout.fixed.vertical, + spacing = dpi(3), + weather_location, + weather_desc_temp, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(7), + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(3), + sunrise_icon_widget, + weather_sunrise + }, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(3), + sunset_icon_widget, + weather_sunset + }, + { + layout = wibox.layout.fixed.horizontal, + spacing = dpi(3), + refresh_widget, + weather_data_time + } + } + }, + nil + } + }, + margins = dpi(10), + widget = wibox.container.margin + }, + forced_height = dpi(92), + bg = beautiful.groups_bg, + shape = function(cr, width, height) + gears.shape.partially_rounded_rect(cr, width, height, true, true, true, true, beautiful.groups_radius) + end, + widget = wibox.container.background +} + +if units == "metric" then + weather_temperature_symbol = "°C" +elseif units == "imperial" then + weather_temperature_symbol = "°F" +end + +-- Weather script using your API KEY +local weather_details_script = [[ +KEY="]]..key..[[" +CITY="]]..city_id..[[" +UNITS="]]..units..[[" + +weather=$(curl -sf "http://api.openweathermap.org/data/2.5/weather?APPID="${KEY}"&id="${CITY}"&units="${UNITS}"") + +if [ ! -z "$weather" ]; then + weather_icon="icon=$(printf "$weather" | jq -r ".weather[].icon" | head -1)" + + weather_location="location=$(printf "$weather" | jq -r ".name")" + weather_country="country=$(printf "$weather" | jq -r ".sys.country")" + + weather_sunrise="sunrise=$(printf "$weather" | jq -r ".sys.sunrise" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)" + weather_sunset="sunset=$(printf "$weather" | jq -r ".sys.sunset" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)" + + weather_data_time="update=$(printf "$weather" | jq -r ".dt" | xargs -0 -L1 -I '$' echo '@$' | xargs date +"%H:%M" -d)" + + weather_temp="temperature=$(printf "$weather" | jq ".main.temp" | cut -d "." -f 1)" + + weather_description="details=$(printf "$weather" | jq -r ".weather[].description" | head -1)" + + DATA="${weather_icon}\n${weather_location}\n${weather_country}\n${weather_sunrise}\n${weather_sunset}\n${weather_data_time}\n${weather_temp}\n${weather_description}\n" + printf "${DATA}" + +else + printf "icon=..." +fi +]] + +awesome.connect_signal( + 'widget::weather_fetch', + function() + + awful.spawn.easy_async_with_shell( + weather_details_script, + function(stdout) + + local weather_data_tbl = {} + + for data in stdout:gmatch("[^\n]+") do + local key = data:match("(.*)=") + local value = data:match("=(.*)") + weather_data_tbl[key] = value + end + + local icon_code = weather_data_tbl['icon'] + + if icon_code == '...' then + + awesome.emit_signal("widget::weather_update", + icon_code, + 'dust and clouds, -1000°C', + 'Earth, Milky Way', + '00:00', + '00:00', + '00:00' + ) + + else + local location = weather_data_tbl['location'] + local country = weather_data_tbl['country'] + local sunrise = weather_data_tbl['sunrise'] + local sunset = weather_data_tbl['sunset'] + local update_time = weather_data_tbl['update'] + local temperature = weather_data_tbl['temperature'] + local details = weather_data_tbl['details'] + + local description = details:sub(1, 1):upper() .. details:sub(2) + local weather_description = description .. ', ' .. temperature .. weather_temperature_symbol + local weather_location = location .. ', ' .. country + + awesome.emit_signal("widget::weather_update", + icon_code, + weather_description, + weather_location, + sunrise, + sunset, + update_time + ) + end + collectgarbage('collect') + end + ) +end) + +local update_widget_timer = gears.timer { + timeout = update_interval, + autostart = true, + call_now = true, + single_shot = false, + callback = function() + awesome.emit_signal('widget::weather_fetch') + end +} + +awesome.connect_signal( + 'system::wifi_connected', + function() + gears.timer.start_new( + 5, + function() + awesome.emit_signal('widget::weather_fetch') + end + ) + end +) + +awesome.connect_signal( + "widget::weather_update", + function(code, desc, location, sunrise, sunset, data_receive) + local widget_icon_name = 'weather-error' + + local icon_tbl = { + ['01d'] = 'sun_icon.svg', + ['01n'] = 'moon_icon.svg', + ['02d'] = 'dfew_clouds.svg', + ['02n'] = 'nfew_clouds.svg', + ['03d'] = 'dscattered_clouds.svg', + ['03n'] = 'nscattered_clouds.svg', + ['04d'] = 'dbroken_clouds.svg', + ['04n'] = 'nbroken_clouds.svg', + ['09d'] = 'dshower_rain.svg', + ['09n'] = 'nshower_rain.svg', + ['10d'] = 'd_rain.svg', + ['10n'] = 'n_rain.svg', + ['11d'] = 'dthunderstorm.svg', + ['11n'] = 'nthunderstorm.svg', + ['13d'] = 'snow.svg', + ['13n'] = 'snow.svg', + ['50d'] = 'dmist.svg', + ['50n'] = 'nmist.svg', + ['...'] = 'weather-error.svg' + } + + widget_icon_name = icon_tbl[code] + + weather_icon_widget.icon:set_image(widget_icon_dir .. widget_icon_name) + weather_icon_widget.icon:emit_signal('widget::redraw_needed') + + weather_desc_temp.description:set_markup(desc) + weather_location.location:set_markup(location) + weather_sunrise:set_markup(sunrise) + weather_sunset:set_markup(sunset) + weather_data_time:set_markup(data_receive) + + end +) + +return weather_report diff --git a/awesome/widget/window-effects/blur-strength-slider.lua b/awesome/widget/window-effects/blur-strength-slider.lua new file mode 100644 index 0000000..1fc4b11 --- /dev/null +++ b/awesome/widget/window-effects/blur-strength-slider.lua @@ -0,0 +1,141 @@ +local wibox = require('wibox') +local gears = require('gears') +local awful = require('awful') +local beautiful = require('beautiful') + +local dpi = beautiful.xresources.apply_dpi + +local start_up = true + +local icons = require('theme.icons') + +local slider = wibox.widget { + nil, + { + id = 'blur_strength_slider', + bar_shape = gears.shape.rounded_rect, + bar_height = dpi(2), + bar_color = '#ffffff20', + bar_active_color = '#f2f2f2EE', + handle_color = '#ffffff', + handle_shape = gears.shape.circle, + handle_width = dpi(15), + handle_border_color = '#00000012', + handle_border_width = dpi(1), + maximum = 100, + widget = wibox.widget.slider, + }, + nil, + expand = 'none', + layout = wibox.layout.align.vertical +} + +local blur_slider = slider.blur_strength_slider + + +local update_slider_value = function() + + awful.spawn.easy_async_with_shell( + [[bash -c " + grep -F 'strength =' $HOME/.config/awesome/configuration/picom.conf | + awk 'NR==1 {print $3}' | tr -d ';' + "]], + function(stdout, stderr) + local strength = stdout:match('%d+') + blur_strength = tonumber(strength) / 20 * 100 + blur_slider:set_value(tonumber(blur_strength)) + start_up = false + end + ) +end + +update_slider_value() + +local adjust_blur = function(power) + + awful.spawn.with_shell( + [[bash -c " + sed -i 's/.*strength = .*/ strength = ]] .. power .. [[;/g' \ + $HOME/.config/awesome/configuration/picom.conf + "]] + ) +end + +blur_slider:connect_signal( + 'property::value', + function() + if not start_up then + strength = blur_slider:get_value() / 50 * 10 + adjust_blur(strength) + end + end +) + +-- Adjust slider value to change blur strength +awesome.connect_signal( + 'widget::blur:increase', + function() + + -- On startup, the slider.value returns nil so... + if blur_slider:get_value() == nil then + return + end + + local blur_value = blur_slider:get_value() + 10 + + -- No more than 100! + if blur_value > 100 then + blur_slider:set_value(100) + return + end + + blur_slider:set_value(blur_value) + end +) + +-- Decrease blur +awesome.connect_signal( + 'widget::blur:decrease', + function() + + -- On startup, the slider.value returns nil so... + if blur_slider:get_value() == nil then + return + end + + local blur_value = blur_slider:get_value() - 10 + + -- No negatives! + if blur_value < 0 then + blur_slider:set_value(0) + return + end + + blur_slider:set_value(blur_value) + end +) + +local blur_slider_setting = wibox.widget { + { + { + { + image = icons.effects, + resize = true, + widget = wibox.widget.imagebox + }, + top = dpi(12), + bottom = dpi(12), + widget = wibox.container.margin + }, + slider, + spacing = dpi(24), + layout = wibox.layout.fixed.horizontal + + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +return blur_slider_setting diff --git a/awesome/widget/window-effects/blur-toggle.lua b/awesome/widget/window-effects/blur-toggle.lua new file mode 100644 index 0000000..e8d078c --- /dev/null +++ b/awesome/widget/window-effects/blur-toggle.lua @@ -0,0 +1,144 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local clickable_container = require('widget.window-effects.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local filesystem = gears.filesystem +local config_dir = filesystem.get_configuration_dir() + +local icons = require('theme.icons') + +local apps = require('configuration.apps') + +local frame_status = nil + +local action_name = wibox.widget { + text = 'Blur Effects', + font = 'SF Pro Text Regular 11', + align = 'left', + widget = wibox.widget.textbox +} + +local button_widget = wibox.widget { + { + id = 'icon', + image = icons.toggled_off, + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local widget_button = wibox.widget { + { + button_widget, + top = dpi(7), + bottom = dpi(7), + widget = wibox.container.margin + }, + widget = clickable_container +} + +local update_imagebox = function() + if action_status then + button_widget.icon:set_image(icons.toggled_on) + else + button_widget.icon:set_image(icons.toggled_off) + end +end + +local check_blur_status = function() + awful.spawn.easy_async_with_shell( + [[bash -c " + grep -F 'method = \"none\";' ]] .. config_dir .. [[/configuration/picom.conf | tr -d '[\"\;\=\ ]' + "]], + function(stdout, stderr) + if stdout:match('methodnone') then + action_status = false + else + action_status = true + end + + update_imagebox() + end + ) +end + +check_blur_status() + +local toggle_blur = function(togglemode) + + local toggle_blur_script = [[bash -c " + # Check picom if it's not running then start it + if [ -z $(pgrep picom) ]; then + picom -b --experimental-backends --dbus --config ]] .. config_dir .. [[configuration/picom.conf + fi + + case ]] .. togglemode .. [[ in + 'enable') + sed -i -e 's/method = \"none\"/method = \"dual_kawase\"/g' \"]] .. config_dir .. [[configuration/picom.conf\" + ;; + 'disable') + sed -i -e 's/method = \"dual_kawase\"/method = \"none\"/g' \"]] .. config_dir .. [[configuration/picom.conf\" + ;; + esac + "]] + + -- Run the script + awful.spawn.with_shell(toggle_blur_script) + +end + +local toggle_blur_fx = function() + local state = nil + if action_status then + action_status = false + state = 'disable' + else + action_status = true + state = 'enable' + end + toggle_blur(state) + update_imagebox() +end + +widget_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + toggle_blur_fx() + end + ) + ) +) + +local action_widget = wibox.widget { + { + action_name, + nil, + { + widget_button, + layout = wibox.layout.fixed.horizontal, + }, + layout = wibox.layout.align.horizontal, + }, + left = dpi(24), + right = dpi(24), + forced_height = dpi(48), + widget = wibox.container.margin +} + +awesome.connect_signal( + 'widget::blur:toggle', + function() + toggle_blur_fx() + end +) + + +return action_widget diff --git a/awesome/widget/window-effects/clickable-container.lua b/awesome/widget/window-effects/clickable-container.lua new file mode 100644 index 0000000..f531740 --- /dev/null +++ b/awesome/widget/window-effects/clickable-container.lua @@ -0,0 +1,35 @@ +local wibox = require('wibox') + +function build(widget) + local container = + wibox.widget { + widget, + widget = wibox.container.background, + } + local old_cursor, old_wibox + container:connect_signal( + 'mouse::enter', + function() + -- Hm, no idea how to get the wibox from this signal's arguments... + local w = mouse.current_wibox + if w then + old_cursor, old_wibox = w.cursor, w + w.cursor = 'hand1' + end + end + ) + + container:connect_signal( + 'mouse::leave', + function() + if old_wibox then + old_wibox.cursor = old_cursor + old_wibox = nil + end + end + ) + + return container +end + +return build diff --git a/awesome/widget/xdg-folders/documents.lua b/awesome/widget/xdg-folders/documents.lua new file mode 100644 index 0000000..dc05b06 --- /dev/null +++ b/awesome/widget/xdg-folders/documents.lua @@ -0,0 +1,55 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local docu_widget = wibox.widget { + { + image = widget_icon_dir .. 'folder-documents' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +local docu_button = wibox.widget { + { + docu_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +docu_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('xdg-open $(xdg-user-dir DOCUMENTS)') + end + ) + ) +) + +awful.tooltip( + { + objects = {docu_button}, + mode = 'outside', + align = 'right', + text = 'Documents', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } +) + +return docu_button diff --git a/awesome/widget/xdg-folders/downloads.lua b/awesome/widget/xdg-folders/downloads.lua new file mode 100644 index 0000000..ed0f5a2 --- /dev/null +++ b/awesome/widget/xdg-folders/downloads.lua @@ -0,0 +1,56 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local dl_widget = wibox.widget { + { + image = widget_icon_dir .. 'folder-download' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +local downloads_button = wibox.widget { + { + dl_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +downloads_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('xdg-open $(xdg-user-dir DOWNLOAD)') + end + ) + ) +) + +awful.tooltip( + { + objects = {downloads_button}, + mode = 'outside', + align = 'right', + text = 'Downloads', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } +) + + +return downloads_button diff --git a/awesome/widget/xdg-folders/home.lua b/awesome/widget/xdg-folders/home.lua new file mode 100644 index 0000000..93bf43a --- /dev/null +++ b/awesome/widget/xdg-folders/home.lua @@ -0,0 +1,55 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local home_widget = wibox.widget { + { + image = widget_icon_dir .. 'user-home' .. '.svg', + resize = true, + widget = wibox.widget.imagebox, + }, + layout = wibox.layout.align.horizontal +} + +local home_button = wibox.widget { + { + home_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} +home_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('xdg-open $(xdg-user-dir)') + end + ) + ) +) + +awful.tooltip( + { + objects = {home_button}, + mode = 'outside', + align = 'right', + text = 'Home', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } +) + + +return home_button diff --git a/awesome/widget/xdg-folders/icons/folder-documents.svg b/awesome/widget/xdg-folders/icons/folder-documents.svg new file mode 100644 index 0000000..e6a53e5 --- /dev/null +++ b/awesome/widget/xdg-folders/icons/folder-documents.svg @@ -0,0 +1,126 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/folder-download.svg b/awesome/widget/xdg-folders/icons/folder-download.svg new file mode 100644 index 0000000..9b75134 --- /dev/null +++ b/awesome/widget/xdg-folders/icons/folder-download.svg @@ -0,0 +1,134 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/folder-pictures.svg b/awesome/widget/xdg-folders/icons/folder-pictures.svg new file mode 100644 index 0000000..014b5b3 --- /dev/null +++ b/awesome/widget/xdg-folders/icons/folder-pictures.svg @@ -0,0 +1,127 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/folder-videos.svg b/awesome/widget/xdg-folders/icons/folder-videos.svg new file mode 100644 index 0000000..50b53df --- /dev/null +++ b/awesome/widget/xdg-folders/icons/folder-videos.svg @@ -0,0 +1,126 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/no.svg b/awesome/widget/xdg-folders/icons/no.svg new file mode 100644 index 0000000..0654b8a --- /dev/null +++ b/awesome/widget/xdg-folders/icons/no.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/open-folder.svg b/awesome/widget/xdg-folders/icons/open-folder.svg new file mode 100644 index 0000000..f1f131d --- /dev/null +++ b/awesome/widget/xdg-folders/icons/open-folder.svg @@ -0,0 +1,110 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/user-home.svg b/awesome/widget/xdg-folders/icons/user-home.svg new file mode 100644 index 0000000..b0a0839 --- /dev/null +++ b/awesome/widget/xdg-folders/icons/user-home.svg @@ -0,0 +1,126 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/user-trash-empty.svg b/awesome/widget/xdg-folders/icons/user-trash-empty.svg new file mode 100644 index 0000000..f4d107f --- /dev/null +++ b/awesome/widget/xdg-folders/icons/user-trash-empty.svg @@ -0,0 +1,160 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/user-trash-full.svg b/awesome/widget/xdg-folders/icons/user-trash-full.svg new file mode 100644 index 0000000..2d75d2d --- /dev/null +++ b/awesome/widget/xdg-folders/icons/user-trash-full.svg @@ -0,0 +1,979 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/icons/yes.svg b/awesome/widget/xdg-folders/icons/yes.svg new file mode 100644 index 0000000..2617c5d --- /dev/null +++ b/awesome/widget/xdg-folders/icons/yes.svg @@ -0,0 +1,69 @@ + + + + + + image/svg+xml + + + + + + + + + + + + diff --git a/awesome/widget/xdg-folders/init.lua b/awesome/widget/xdg-folders/init.lua new file mode 100644 index 0000000..e8adc84 --- /dev/null +++ b/awesome/widget/xdg-folders/init.lua @@ -0,0 +1,27 @@ +local awful = require('awful') +local wibox = require('wibox') +local beautiful = require('beautiful') + +local dpi = require('beautiful').xresources.apply_dpi + +local separator = wibox.widget { + orientation = 'horizontal', + forced_height = dpi(1), + span_ratio = 0.55, + widget = wibox.widget.separator +} + +return wibox.widget { + layout = wibox.layout.align.vertical, + { + separator, + require("widget.xdg-folders.home"), + require("widget.xdg-folders.documents"), + require("widget.xdg-folders.downloads"), + -- require("widget.xdg-folders.pictures"), + -- require("widget.xdg-folders.videos"), + separator, + require("widget.xdg-folders.trash"), + layout = wibox.layout.fixed.vertical, + }, +} diff --git a/awesome/widget/xdg-folders/pictures.lua b/awesome/widget/xdg-folders/pictures.lua new file mode 100644 index 0000000..4123c75 --- /dev/null +++ b/awesome/widget/xdg-folders/pictures.lua @@ -0,0 +1,56 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local pic_widget = wibox.widget { + { + image = widget_icon_dir .. 'folder-pictures' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +local pic_button = wibox.widget { + { + pic_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +pic_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('xdg-open $(xdg-user-dir PICTURES)') + end + ) + ) +) + +awful.tooltip( + { + objects = {pic_button}, + mode = 'outside', + align = 'right', + text = 'Pictures', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} + } +) + + +return pic_button diff --git a/awesome/widget/xdg-folders/trash.lua b/awesome/widget/xdg-folders/trash.lua new file mode 100644 index 0000000..909036a --- /dev/null +++ b/awesome/widget/xdg-folders/trash.lua @@ -0,0 +1,134 @@ +local wibox = require('wibox') +local awful = require('awful') +local naughty = require('naughty') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local trash_widget = wibox.widget { + { + id = 'trash_icon', + image = widget_icon_dir .. 'user-trash-empty' .. '.svg', + resize = true, + widget = wibox.widget.imagebox + }, + layout = wibox.layout.align.horizontal +} + +local trash_menu = awful.menu({ + items = { + { + "Open trash", + function() awful.spawn.easy_async_with_shell("gio open trash:///", function(stdout) end, 1) end, + widget_icon_dir .. 'open-folder' .. '.svg' + }, + { + "Delete forever", + { + { + 'Yes', + function() awful.spawn.easy_async_with_shell("gio trash --empty", function(stdout) end, 1) end, + widget_icon_dir .. 'yes' .. '.svg' + }, + { + 'No', + '', + widget_icon_dir .. 'no' .. '.svg' + } + }, + widget_icon_dir .. 'user-trash-empty' .. '.svg' + }, + + } +}) + + +local trash_button = wibox.widget { + { + trash_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +-- Tooltip for trash_button +trash_tooltip = awful.tooltip { + objects = {trash_button}, + mode = 'outside', + align = 'right', + markup = 'Trash', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + preferred_positions = {'right', 'left', 'top', 'bottom'} +} + +-- Mouse event for trash_button +trash_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn({'gio', 'open', 'trash:///'}, false) + end + ), + awful.button( + {}, + 3, + nil, + function() + trash_menu:toggle() + trash_tooltip.visible = not trash_tooltip.visible + end + ) + ) +) + + + +-- Update icon on changes +local check_trash_list = function() + awful.spawn.easy_async_with_shell('gio list trash:/// | wc -l', function(stdout) + if tonumber(stdout) > 0 then + trash_widget.trash_icon:set_image(widget_icon_dir .. 'user-trash-full' .. '.svg') + + awful.spawn.easy_async_with_shell('gio list trash:///', function(stdout) + + trash_tooltip.markup = 'Trash contains:\n' .. stdout:gsub('\n$', '') + + end, false) + + + else + trash_widget.trash_icon:set_image(widget_icon_dir .. 'user-trash-empty' .. '.svg') + + trash_tooltip.markup = 'Trash empty' + + end + end, false) +end + + +-- Check trash on awesome (re)-start +check_trash_list() + + +-- Kill the old process of gio monitor trash:/// +awful.spawn.easy_async_with_shell('ps x | grep \'gio monitor trash:///\' | grep -v grep | awk \'{print $1}\' | xargs kill', function() + + awful.spawn.with_line_callback('gio monitor trash:///', { + stdout = function(_) + check_trash_list() + end + }) + +end, false) + + +return trash_button diff --git a/awesome/widget/xdg-folders/videos.lua b/awesome/widget/xdg-folders/videos.lua new file mode 100644 index 0000000..d2e8b6d --- /dev/null +++ b/awesome/widget/xdg-folders/videos.lua @@ -0,0 +1,56 @@ +local awful = require('awful') +local wibox = require('wibox') +local gears = require('gears') + +local clickable_container = require('widget.clickable-container') +local dpi = require('beautiful').xresources.apply_dpi + +local config_dir = gears.filesystem.get_configuration_dir() +local widget_icon_dir = config_dir .. 'widget/xdg-folders/icons/' + +local vid_widget = + wibox.widget { + { + image = widget_icon_dir .. 'folder-videos' .. '.svg', + widget = wibox.widget.imagebox, + resize = true + }, + layout = wibox.layout.align.horizontal +} + +local videos_button = wibox.widget { + { + vid_widget, + margins = dpi(10), + widget = wibox.container.margin + }, + widget = clickable_container +} + +videos_button:buttons( + gears.table.join( + awful.button( + {}, + 1, + nil, + function() + awful.spawn.with_shell('xdg-open $(xdg-user-dir VIDEOS)') + end + ) + ) +) + +awful.tooltip +{ + objects = {videos_button}, + mode = 'outside', + align = 'right', + margin_leftright = dpi(8), + margin_topbottom = dpi(8), + timer_function = function() + return 'Videos' + end, + preferred_positions = {'right', 'left', 'top', 'bottom'} +} + +return videos_button diff --git a/picom.conf b/picom.conf index 9cbedec..a6fb7fb 100644 --- a/picom.conf +++ b/picom.conf @@ -41,11 +41,11 @@ shadow-opacity = .75 # The left offset for shadows, in pixels. (defaults to -15) # shadow-offset-x = -15 -shadow-offset-x = -7; +shadow-offset-x = -17; # The top offset for shadows, in pixels. (defaults to -15) # shadow-offset-y = -15 -shadow-offset-y = -7; +shadow-offset-y = -17; # Avoid drawing shadows on dock/panel windows. This option is deprecated, # you should use the *wintypes* option in your config file instead.