moved to personal fennel config for awesome and added qutebrowser

This commit is contained in:
Chris Cochrun 2020-10-13 17:35:26 -05:00
parent 403cb92b7d
commit 688748f8a6
502 changed files with 8576 additions and 9597 deletions

View file

@ -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 = '<b>Oof! Error detected when starting an application!</b>',
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

83
awes2/module/backdrop.lua Normal file
View file

@ -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
)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -0,0 +1,225 @@
----------------------------------------------------------------------------
--- Wallpaper changer module
--
-- @author Gerome Matilla &lt;gerome.matilla07@gmail.com&gt;
-- @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)

View file

@ -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
)

896
awes2/module/lockscreen.lua Executable file
View file

@ -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 = '<span foreground="#00000066">' .. '$USER' .. "</span>",
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 = '<span foreground="#00000066">' .. 'Caps Lock is on' .. "</span>",
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 = '<span foreground="#00000066">' .. stdout .. "</span>"
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(
'<span font="SF Pro Display Bold 56">%H:%M</span>',
1
)
local time_shadow = wibox.widget.textclock(
'<span foreground="#00000066" font="SF Pro Display Bold 56">%H:%M</span>',
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 = "<span foreground='#00000066'>" .. date_value().day .. date_value().ordinal .. " of " ..
date_value().month .. "</span>",
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
)

206
awes2/module/menu.lua Normal file
View file

@ -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 <b>awesome-freedesktop.</b> " ..
"This will populate the menu with your installed applications automatically. " ..
"It is also available in AUR, it is called <b>awesome-freedesktop-git</b>.",
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

View file

@ -0,0 +1,264 @@
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(100)
naughty.config.defaults.border_width = 0
naughty.config.defaults.position = 'top_right'
naughty.config.defaults.screen = 1
naughty.config.defaults.shape = function(cr, w, h) gears.shape.rounded_rect(cr, w, h, dpi(6)) end
-- Apply theme variables
naughty.config.padding = dpi(20)
naughty.config.spacing = dpi(20)
naughty.config.icon_dirs = {
"/usr/share/icons/Papirus/",
"/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 = 'VictorMono Nerd Font 10',
bg = '#ff0000',
fg = '#ffffff',
margin = dpi(16),
position = 'top_right',
implicit_timeout = 15
}
}
-- Normal notifs
ruled.notification.append_rule {
rule = { urgency = 'normal' },
properties = {
font = 'VictorMono Nerd Font 10',
bg = beautiful.transparent,
fg = beautiful.fg_normal,
margin = dpi(16),
position = 'top_right',
implicit_timeout = 8
}
}
-- Low notifs
ruled.notification.append_rule {
rule = { urgency = 'low' },
properties = {
font = 'VictorMono Nerd Font 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(4),
layout = wibox.layout.flex.horizontal
},
widget_template = {
{
{
{
{
id = 'text_role',
font = 'VictorMono Nerd Font 10',
widget = wibox.widget.textbox
},
widget = wibox.container.place
},
widget = clickable_container
},
bg = beautiful.groups_bg,
shape = gears.shape.rounded_rect,
forced_height = dpi(35),
widget = wibox.container.background
},
margins = dpi(8),
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.rounded_rectangle,
widget_template = {
{
{
{
{
{
{
{
{
{
{
{
markup = n.app_name or 'System Notification',
font = 'VictorMono Nerd Font 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 = 'center',
widget = naughty.widget.title
},
{
align = "center",
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.bg_normal,
widget = wibox.container.background,
},
-- Notification action list
-- naughty.list.actions,
actions_template,
spacing = dpi(4),
layout = wibox.layout.fixed.vertical,
},
bg = beautiful.bg_normal,
id = "background_role",
shape = gears.shape.rounded_rect,
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.bg_normal,
-- 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(15),--beautiful.notification_margin,
right = dpi(20),
left = dpi(0),
bottom = dpi(0),
top = dpi(20),
widget = wibox.container.margin
},
bg = beautiful.transparent,
widget = wibox.container.background
}
-- 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)

View file

@ -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
)

30
awes2/module/test.lua Normal file
View file

@ -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()
}

282
awes2/module/titlebar.lua Normal file
View file

@ -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)

271
awes2/module/volume-osd.lua Normal file
View file

@ -0,0 +1,271 @@
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 = true
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 set 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.rounded_rect,
bg = "#282a36",
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
},
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.centered(focused.volume_osd_overlay, { margins = {
left = 0,
right = osd_margin,
top = dpi(800),
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)