2024-03-17 14:39:54 +10:00
-- If LuaRocks is installed, make sure that packages installed through it are
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
pcall ( require , " luarocks.loader " )
-- Standard awesome library
local gears = require ( " gears " )
local awful = require ( " awful " )
require ( " awful.autofocus " )
-- Widget and layout library
local wibox = require ( " wibox " )
-- Theme handling library
local beautiful = require ( " beautiful " )
-- Notification library
local naughty = require ( " naughty " )
local menubar = require ( " menubar " )
local hotkeys_popup = require ( " awful.hotkeys_popup " )
-- Enable hotkeys help widget for VIM and other apps
-- when client with a matching name is opened:
require ( " awful.hotkeys_popup.keys " )
local volume_widget = require ( ' awesome-wm-widgets.pactl-widget.volume ' )
local blacklisted_snid = setmetatable ( { } , { __mode = " v " } )
-- {{{ 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)
if awesome.startup_errors then
naughty.notify ( { preset = naughty.config . presets.critical ,
title = " Oops, there were errors during startup! " ,
text = awesome.startup_errors } )
end
-- Handle runtime errors after startup
do
local in_error = false
awesome.connect_signal ( " debug::error " , function ( err )
-- Make sure we don't go into an endless error loop
if in_error then return end
in_error = true
naughty.notify ( { preset = naughty.config . presets.critical ,
title = " Oops, an error happened! " ,
text = tostring ( err ) } )
in_error = false
end )
end
-- }}}
-- {{{ Variable definitions
-- Themes define colours, icons, font and wallpapers.
-- beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua")
beautiful.init ( " ~/.config/awesome/theme.lua " )
-- This is used later as the default terminal and editor to run.
terminal = " lxterminal "
editor = os.getenv ( " EDITOR " ) or " vim "
editor_cmd = terminal .. " -e " .. editor
-- Default modkey.
-- Usually, Mod4 is the key with a logo between Control and Alt.
-- If you do not like this or do not have such a key,
-- I suggest you to remap Mod4 to another key using xmodmap or other tools.
-- However, you can use another modifier like Mod1, but it may interact with others.
modkey = " Mod4 "
local l = awful.layout . suit
awful.layout . layouts = {
awful.layout . suit.floating ,
awful.layout . suit.tile ,
awful.layout . suit.tile . left ,
awful.layout . suit.tile . bottom ,
awful.layout . suit.tile . top ,
awful.layout . suit.fair ,
awful.layout . suit.fair . horizontal ,
awful.layout . suit.spiral ,
awful.layout . suit.spiral . dwindle ,
awful.layout . suit.max ,
awful.layout . suit.max . fullscreen ,
awful.layout . suit.magnifier ,
awful.layout . suit.corner . nw ,
-- awful.layout.suit.corner.ne,
-- awful.layout.suit.corner.sw,
-- awful.layout.suit.corner.se,
}
-- }}}
-- {{{ Menu
-- Create a launcher widget and a main menu
myawesomemenu = {
{ " hotkeys " , function ( ) hotkeys_popup.show_help ( nil , awful.screen . focused ( ) ) end } ,
{ " manual " , terminal .. " -e man awesome " } ,
{ " edit config " , editor_cmd .. " " .. awesome.conffile } ,
{ " restart " , awesome.restart } ,
{ " quit " , function ( ) awesome.quit ( ) end } ,
}
mymainmenu = awful.menu ( { items = { { " awesome " , myawesomemenu , beautiful.awesome_icon } ,
{ " open terminal " , terminal }
}
} )
mylauncher = awful.widget . launcher ( { image = beautiful.awesome_icon ,
menu = mymainmenu } )
-- Menubar configuration
menubar.utils . terminal = terminal -- Set the terminal for applications that require it
-- }}}
-- Keyboard map indicator and switcher
-- mykeyboardlayout = awful.widget.keyboardlayout()
-- This is for my current year calendar. I did not feel like setting a reminder to update this every Jan. 1. In 2023, this caused some confusion because it did not roll over automatically.
yr = os.date ( " %Y " )
-- My popup calendar, source adapted from: https://pavelmakhov.com/2017/03/calendar-widget-for-awesome
function cal_notify ( cal_pref , pref_screen )
if cal_notification == nil then
awful.spawn . easy_async ( [[bash -c "]] .. cal_pref .. [[ | sed 's/_.\(.\)/+\1-/g;s/$//g;/]] .. yr .. [[$/d'"]] ,
function ( stdout , stderr , reason , exit_code )
cal_notification = naughty.notify {
text = string.gsub ( string.gsub ( stdout , " + " , " <span background='#85492e'> " ) , " - " , " </span> " ) ,
timeout = 0 ,
margin = 20 ,
font = " Hack Nerd Font " ,
screen = pref_screen ,
width = auto ,
destroy = function ( ) cal_notification = nil end
}
end )
else
naughty.destroy ( cal_notification )
-- naughty.destroy_all_notifications()
end
end
-- Create a textclock widget and attach calendar to it on click.
local mytextclock = wibox.widget . textclock ( " %d %b %I:%M %p " )
mytextclock : connect_signal ( " button::release " , function ( ) cal_notify ( " cal " .. yr ) end )
-- Create a wibox for each screen and add it
local taglist_buttons = gears.table . join (
awful.button ( { } , 1 , function ( t ) t : view_only ( ) end ) ,
awful.button ( { modkey } , 1 , function ( t )
if client.focus then
client.focus : move_to_tag ( t )
end
end ) ,
awful.button ( { } , 3 , awful.tag . viewtoggle ) ,
awful.button ( { modkey } , 3 , function ( t )
if client.focus then
client.focus : toggle_tag ( t )
end
end ) ,
awful.button ( { } , 4 , function ( t ) awful.tag . viewnext ( t.screen ) end ) ,
awful.button ( { } , 5 , function ( t ) awful.tag . viewprev ( t.screen ) end )
)
local tasklist_buttons = gears.table . join (
awful.button ( { } , 1 , function ( c )
if c == client.focus then
c.minimized = true
else
c : emit_signal (
" request::activate " ,
" tasklist " ,
{ raise = true }
)
end
end ) ,
awful.button ( { } , 3 , function ( )
awful.menu . client_list ( { theme = { width = 250 } } )
end ) ,
awful.button ( { } , 4 , function ( )
awful.client . focus.byidx ( 1 )
end ) ,
awful.button ( { } , 5 , function ( )
awful.client . focus.byidx ( - 1 )
end ) )
local function set_wallpaper ( s )
-- Wallpaper
if beautiful.wallpaper then
local wallpaper = beautiful.wallpaper
-- If wallpaper is a function, call it with the screen
if type ( wallpaper ) == " function " then
wallpaper = wallpaper ( s )
end
gears.wallpaper . maximized ( wallpaper , s , true )
end
end
-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
screen.connect_signal ( " property::geometry " , set_wallpaper )
-- These are my tag names.
web = " WEB "
term = " TERM "
mis = " MIS "
news = " NEWS "
irc = " IRC "
mus = " MUS "
pir = " PIR "
mov = " MOV "
gam = " GAM "
awful.screen . connect_for_each_screen ( function ( s )
set_wallpaper ( s )
-- Set my tags for each screen with their own preferred layouts.
awful.tag . add ( web , { layout = l.spiral , screen = s , selected = true , } )
awful.tag . add ( term , { layout = l.spiral , screen = s , } )
awful.tag . add ( mis , { layout = l.spiral , screen = s , } )
if s.index == 1 then
awful.tag . add ( news , { layout = l.spiral , screen = s , } )
awful.tag . add ( irc , { layout = l.tile . bottom , screen = s , } )
awful.tag . add ( mus , { layout = l.tile . bottom , screen = s , } )
awful.tag . add ( pir , { layout = l.spiral , screen = s , } )
awful.tag . add ( mov , { layout = l.spiral , screen = s , } )
awful.tag . add ( gam , { layout = l.spiral , screen = s , } )
end
-- Create an imagebox widget which will contain an icon indicating which layout we're using.
-- We need one layoutbox per screen.
s.mylayoutbox = awful.widget . layoutbox ( s )
s.mylayoutbox : buttons ( gears.table . join ( awful.button ( { } , 1 , function ( ) awful.layout . inc ( 1 ) end ) ) )
-- Create a taglist widget
s.mytaglist = awful.widget . taglist {
screen = s ,
-- There is no point in showing an empty tag.
-- filter = awful.widget.taglist.filter.noempty,
filter = awful.widget . taglist.filter . all ,
buttons = taglist_buttons ,
}
-- Create a tasklist widget
s.mytasklist = awful.widget . tasklist {
screen = s , filter = awful.widget . tasklist.filter . currenttags , buttons = tasklist_buttons ,
}
-- Create the wibox
s.mywibox = awful.wibar ( { position = " top " , screen = s , height = 25 } )
-- Add widgets to the wibox
if s.index == 1 then
-- I only want the system tray, clock, etc. to be on screen one and not on every screen.
s.mywibox : setup {
layout = wibox.layout . align.horizontal ,
{ layout = wibox.layout . fixed.horizontal ,
s.mytaglist ,
} ,
s.mytasklist ,
{ layout = wibox.layout . fixed.horizontal ,
spacer ,
volume_widget {
widget_type = ' arc '
} ,
wibox.widget . systray ( ) ,
spacer ,
battery_status ,
mytextclock ,
s.mylayoutbox ,
} ,
}
else
s.mywibox : setup {
layout = wibox.layout . align.horizontal ,
{ layout = wibox.layout . fixed.horizontal ,
s.mytaglist ,
} ,
s.mytasklist ,
{ layout = wibox.layout . fixed.horizontal ,
s.mylayoutbox ,
} ,
}
end
end )
-- }}}https://wiki.archlinux.org/title/N
-- {{{ Mouse bindingsxproperty
root.buttons ( gears.table . join (
awful.button ( { } , 3 , function ( ) mymainmenu : toggle ( ) end ) ,
awful.button ( { } , 4 , awful.tag . viewnext ) ,
awful.button ( { } , 5 , awful.tag . viewprev )
) )
-- }}}
-- {{{ Key bindings
globalkeys = gears.table . join (
awful.key ( { modkey , } , " s " , hotkeys_popup.show_help ,
{ description = " show help " , group = " awesome " } ) ,
awful.key ( { modkey , } , " Left " , awful.tag . viewprev ,
{ description = " view previous " , group = " tag " } ) ,
awful.key ( { modkey , } , " Right " , awful.tag . viewnext ,
{ description = " view next " , group = " tag " } ) ,
awful.key ( { modkey , } , " Escape " , awful.tag . history.restore ,
{ description = " go back " , group = " tag " } ) ,
awful.key ( { modkey , } , " j " ,
function ( )
awful.client . focus.byidx ( 1 )
end ,
{ description = " focus next by index " , group = " client " }
) ,
awful.key ( { modkey , } , " k " ,
function ( )
awful.client . focus.byidx ( - 1 )
end ,
{ description = " focus previous by index " , group = " client " }
) ,
awful.key ( { modkey , } , " w " , function ( ) mymainmenu : show ( ) end ,
{ description = " show main menu " , group = " awesome " } ) ,
-- Layout manipulation
awful.key ( { modkey , " Shift " } , " j " , function ( ) awful.client . swap.byidx ( 1 ) end ,
{ description = " swap with next client by index " , group = " client " } ) ,
awful.key ( { modkey , " Shift " } , " k " , function ( ) awful.client . swap.byidx ( - 1 ) end ,
{ description = " swap with previous client by index " , group = " client " } ) ,
awful.key ( { modkey , " Control " } , " j " , function ( ) awful.screen . focus_relative ( 1 ) end ,
{ description = " focus the next screen " , group = " screen " } ) ,
awful.key ( { modkey , " Control " } , " k " , function ( ) awful.screen . focus_relative ( - 1 ) end ,
{ description = " focus the previous screen " , group = " screen " } ) ,
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 " } ) ,
-- Standard program
awful.key ( { modkey , } , " Return " , function ( ) awful.spawn ( terminal ) end ,
{ description = " open a terminal " , group = " launcher " } ) ,
awful.key ( { modkey , " Control " } , " r " , awesome.restart ,
{ description = " reload awesome " , group = " awesome " } ) ,
awful.key ( { modkey , " Shift " } , " q " , awesome.quit ,
{ description = " quit awesome " , group = " awesome " } ) ,
awful.key ( { modkey , } , " l " , function ( ) awful.tag . incmwfact ( 0.05 ) end ,
{ description = " increase master width factor " , group = " layout " } ) ,
awful.key ( { modkey , } , " h " , function ( ) awful.tag . incmwfact ( - 0.05 ) end ,
{ description = " decrease master width factor " , group = " layout " } ) ,
awful.key ( { modkey , " Shift " } , " h " , function ( ) awful.tag . incnmaster ( 1 , nil , true ) end ,
{ description = " increase the number of master clients " , group = " layout " } ) ,
awful.key ( { modkey , " Shift " } , " l " , function ( ) awful.tag . incnmaster ( - 1 , nil , true ) end ,
{ description = " decrease the number of master clients " , group = " layout " } ) ,
awful.key ( { modkey , " Control " } , " h " , function ( ) awful.tag . incncol ( 1 , nil , true ) end ,
{ description = " increase the number of columns " , group = " layout " } ) ,
awful.key ( { modkey , " Control " } , " l " , function ( ) awful.tag . incncol ( - 1 , nil , true ) end ,
{ description = " decrease the number of columns " , group = " layout " } ) ,
awful.key ( { modkey , } , " space " , function ( ) awful.layout . inc ( 1 ) end ,
{ description = " select next " , group = " layout " } ) ,
awful.key ( { modkey , " Shift " } , " space " , function ( ) awful.layout . inc ( - 1 ) end ,
{ description = " select previous " , group = " layout " } ) ,
awful.key ( { modkey , " Control " } , " n " ,
function ( )
local c = awful.client . restore ( )
-- Focus restored client
if c then
c : emit_signal (
" request::activate " , " key.unminimize " , { raise = true }
)
end
end ,
{ description = " restore minimized " , group = " client " } ) ,
-- Prompt
awful.key ( { modkey } , " r " ,
-- function () awful.screen.focused().mypromptbox:run() end,
function ( ) awful.util . spawn ( " rofi -modi drun -show drun -show-icons -width 32 -no-click-to-exit " , false ) end ,
{ description = " run prompt " , group = " launcher " } ) ,
awful.key ( { modkey } , " x " ,
function ( )
awful.prompt . run {
prompt = " Run Lua code: " ,
textbox = awful.screen . focused ( ) . mypromptbox.widget ,
exe_callback = awful.util . eval ,
history_path = awful.util . get_cache_dir ( ) .. " /history_eval "
}
end ,
{ description = " lua execute prompt " , group = " awesome " } ) ,
-- Menubar
awful.key ( { modkey } , " p " , function ( ) menubar.show ( ) end ,
{ description = " show the menubar " , group = " launcher " } )
)
clientkeys = gears.table . join (
awful.key ( { modkey , } , " f " ,
function ( c )
c.fullscreen = not c.fullscreen
c : raise ( )
end ,
{ description = " toggle fullscreen " , group = " client " } ) ,
awful.key ( { modkey , " Shift " } , " c " , function ( c ) c : kill ( ) end ,
{ description = " close " , group = " client " } ) ,
awful.key ( { modkey , " Control " } , " space " , awful.client . floating.toggle ,
{ description = " toggle floating " , group = " client " } ) ,
awful.key ( { modkey , " Control " } , " Return " , function ( c ) c : swap ( awful.client . getmaster ( ) ) end ,
{ description = " move to master " , group = " client " } ) ,
awful.key ( { modkey , } , " o " , function ( c ) c : move_to_screen ( ) end ,
{ description = " move to screen " , group = " client " } ) ,
awful.key ( { modkey , } , " t " , function ( c ) c.ontop = not c.ontop end ,
{ description = " toggle keep on top " , group = " client " } ) ,
awful.key ( { modkey , } , " n " ,
function ( c )
-- The client currently has the input focus, so it cannot be
-- minimized, since minimized clients can't have the focus.
c.minimized = true
end ,
{ description = " minimize " , group = " client " } ) ,
awful.key ( { modkey , } , " m " ,
function ( c )
c.maximized = not c.maximized
c : raise ( )
end ,
{ description = " (un)maximize " , group = " client " } ) ,
awful.key ( { modkey , " Control " } , " m " ,
function ( c )
c.maximized_vertical = not c.maximized_vertical
c : raise ( )
end ,
{ description = " (un)maximize vertically " , group = " client " } ) ,
awful.key ( { modkey , " Shift " } , " m " ,
function ( c )
c.maximized_horizontal = not c.maximized_horizontal
c : raise ( )
end ,
{ description = " (un)maximize horizontally " , group = " client " } )
)
-- 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
globalkeys = gears.table . join ( globalkeys ,
-- View tag only.
awful.key ( { modkey } , " # " .. i + 9 ,
function ( )
local screen = awful.screen . focused ( )
local tag = screen.tags [ i ]
if tag then
tag : view_only ( )
end
end ,
{ description = " view tag # " .. i , group = " tag " } ) ,
-- Toggle tag display.
awful.key ( { modkey , " Control " } , " # " .. i + 9 ,
function ( )
local screen = awful.screen . focused ( )
local tag = screen.tags [ i ]
if tag then
awful.tag . viewtoggle ( tag )
end
end ,
{ description = " toggle tag # " .. i , group = " tag " } ) ,
-- 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 ,
{ description = " move focused client to tag # " .. i , group = " tag " } ) ,
-- 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 ,
{ description = " toggle focused client on tag # " .. i , group = " tag " } )
)
end
clientbuttons = gears.table . join (
awful.button ( { } , 1 , function ( c )
c : emit_signal ( " request::activate " , " mouse_click " , { raise = true } )
end ) ,
awful.button ( { modkey } , 1 , function ( c )
c : emit_signal ( " request::activate " , " mouse_click " , { raise = true } )
awful.mouse . client.move ( c )
end ) ,
awful.button ( { modkey } , 3 , function ( c )
c : emit_signal ( " request::activate " , " mouse_click " , { raise = true } )
awful.mouse . client.resize ( c )
end )
)
-- Set keys
root.keys ( globalkeys )
-- }}}
-- {{{ Rules
-- Rules to apply to new clients (through the "manage" signal).
awful.rules . rules = {
-- All clients will match this rule.
{ rule = { } ,
properties = { border_width = beautiful.border_width ,
border_color = beautiful.border_normal ,
focus = awful.client . focus.filter ,
raise = true ,
keys = clientkeys ,
buttons = clientbuttons ,
screen = awful.screen . preferred ,
placement = awful.placement . no_overlap + awful.placement . no_offscreen
}
} ,
-- Floating clients.
{ rule_any = {
instance = {
" DTA " , -- Firefox addon DownThemAll.
" copyq " , -- Includes session name in class.
" pinentry " ,
} ,
class = {
" Arandr " ,
" Blueman-manager " ,
" Gpick " ,
" Kruler " ,
" MessageWin " , -- kalarm.
" Sxiv " ,
" Tor Browser " , -- Needs a fixed window size to avoid fingerprinting by screen size.
" Wpa_gui " ,
" veromix " ,
" xtightvncviewer " } ,
-- Note that the name property shown in xprop might be set slightly after creation of the client
-- and the name shown there might not match defined rules here.
name = {
" Event Tester " , -- xev.
} ,
role = {
" AlarmWindow " , -- Thunderbird's calendar.
" ConfigManager " , -- Thunderbird's about:config.
" pop-up " , -- e.g. Google Chrome's (detached) Developer Tools.
}
} , properties = { floating = true } } ,
-- Add titlebars to normal clients and dialogs
{ rule_any = { type = { " normal " , " dialog " }
} , 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" } },
2024-03-19 20:23:11 +10:00
{ rule = { class = " qutebrowser " } ,
properties = {
screen = " DP-2 " ,
tags = " WEB " }
} ,
2024-03-17 14:39:54 +10:00
}
-- }}}
-- {{{ Signals
-- 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 awesome.startup then awful.client . setslave ( c ) end
if awesome.startup
and not c.size_hints . user_position
and not c.size_hints . program_position then
-- Prevent clients from being unreachable after screen count changes.
awful.placement . no_offscreen ( c )
end
end )
-- Add a titlebar if titlebars_enabled is set to true in the rules.
client.connect_signal ( " request::titlebars " , function ( c )
-- buttons for the titlebar
local buttons = gears.table . join (
awful.button ( { } , 1 , function ( )
c : emit_signal ( " request::activate " , " titlebar " , { raise = true } )
awful.mouse . client.move ( c )
end ) ,
awful.button ( { } , 3 , function ( )
c : emit_signal ( " request::activate " , " titlebar " , { raise = true } )
awful.mouse . client.resize ( c )
end )
)
awful.titlebar ( c ) : setup {
{ -- Left
awful.titlebar . widget.iconwidget ( c ) ,
buttons = buttons ,
layout = wibox.layout . fixed.horizontal
} ,
{ -- Middle
{ -- Title
align = " center " ,
widget = awful.titlebar . widget.titlewidget ( c )
} ,
buttons = buttons ,
layout = wibox.layout . flex.horizontal
} ,
{ -- Right
awful.titlebar . widget.floatingbutton ( c ) ,
awful.titlebar . widget.maximizedbutton ( c ) ,
awful.titlebar . widget.stickybutton ( c ) ,
awful.titlebar . widget.ontopbutton ( c ) ,
awful.titlebar . widget.closebutton ( c ) ,
layout = wibox.layout . fixed.horizontal ( )
} ,
layout = wibox.layout . align.horizontal
}
end )
-- Enable sloppy focus, so that focus follows mouse.
client.connect_signal ( " mouse::enter " , function ( c )
c : emit_signal ( " request::activate " , " mouse_enter " , { raise = false } )
end )
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 )
-- }}}
-- Autostart applications
-- awful.spawn.once("qutebrowser", {unique_id = "Qutebrowser" })
-- awful.spawn(terminal, { tag = "MIS" })
-- awful.spawn("microsoft-edge-dev", { tags = "WEB" })
awful.spawn . with_shell ( " $HOME/.config/awesome/autostart.sh " )