;; 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")) ;; Enable hotkeys help widget for VIM and other apps ;; when client with a matching name is opened: (local hotkeys_popup (require "awful.hotkeys_popup")) (require "awful.hotkeys_popup.keys") ;; 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) (when awesome.startup_errors (naughty.notify {:preset naughty.config.presets.critical :title "Oops, there were errors during startup!" :text awesome.startup_errors})) ;; Handle runtime errors after startup (do (var in_error false) (awesome.connect_signal "debug::error" (fn [err] ;; Make sure we don't go into an endless error loop (when (not in_error) (set in_error true) (naughty.notify {:preset naughty.config.presets.critical :title "Oops, an error happened!" :text (tostring err)}) (set in_error false))))) ;; Variable definitions ;; Themes define colours, icons, font and wallpapers. (beautiful.init (.. (gears.filesystem.get_themes_dir) "default/theme.lua")) ;; This is used later as the default terminal and editor to run. (var terminal "xterm") (var editor (or (os.getenv "EDITOR") "nano")) (var 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. (var modkey "Mod4") ;; Table of layouts to cover with awful.layout.inc, order matters. (set 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 (global myawesomemenu [ [ "hotkeys" (fn [] (hotkeys_popup.show_help nil (awful.screen.focused))) ] [ "manual" (.. terminal " -e man awesome") ] [ "edit config" (.. editor_cmd " " awesome.conffile) ] [ "restart" awesome.restart ] [ "quit" (fn [] (awesome.quit)) ]]) (global mymainmenu (awful.menu {:items [ [ "awesome" myawesomemenu beautiful.awesome_icon ] [ "open terminal" terminal ]]})) (global mylauncher (awful.widget.launcher {:image beautiful.awesome_icon :menu mymainmenu })) ;; Menubar configuration (set menubar.utils.terminal terminal) ;; Set the terminal for applications that require it ;; Keyboard map indicator and switcher (global mykeyboardlayout (awful.widget.keyboardlayout)) ;; Wibar ;; Create a textclock widget (global mytextclock (wibox.widget.textclock)) ;; Create a wibox for each screen and add it (local taglist_buttons (gears.table.join (awful.button [] 1 (fn [t] (: t :view_only))) (awful.button [ modkey ] 1 (fn [t] (when client.focus (: client.focus :move_to_tag t)))) (awful.button [] 3 awful.tag.viewtoggle) (awful.button [ modkey ] 3 (fn [t] (when client.focus (: client.focus :toggle_tag t)))) (awful.button [] 4 (fn [t] (awful.tag.viewnext t.screen))) (awful.button [] 5 (fn [t] (awful.tag.viewprev t.screen))))) (local tasklist_buttons (gears.table.join (awful.button [] 1 (fn [c] (if (= c client.focus) (set c.minimized true) (: c :emit_signal "request::activate" "tasklist" {:raise true} )))) (awful.button [] 3 (fn [] (awful.menu.client_list {:theme {:width 250 }}))) (awful.button [] 4 (fn [] (awful.client.focus.byidx 1))) (awful.button [] 5 (fn [] (awful.client.focus.byidx -1))))) (fn set_wallpaper [s] ;; Wallpaper (when beautiful.wallpaper (var wallpaper beautiful.wallpaper) ;; If wallpaper is a function, call it with the screen (when (= (type wallpaper) "function") (set wallpaper (wallpaper s))) (gears.wallpaper.maximized wallpaper s true))) ;; Re-set wallpaper when a screen's geometry changes (e.g. different resolution) (screen.connect_signal "property::geometry" set_wallpaper) (awful.screen.connect_for_each_screen (fn [s] ;; Wallpaper (set_wallpaper s) ;; Each screen has its own tag table. (awful.tag [ "1" "2" "3" "4" "5" "6" "7" "8" "9" ] s (. awful.layout.layouts 1)) ;; Create a promptbox for each screen (set s.mypromptbox (awful.widget.prompt)) ;; Create an imagebox widget which will contain an icon indicating which layout we're using. ;; We need one layoutbox per screen. (set s.mylayoutbox (awful.widget.layoutbox s)) (: s.mylayoutbox :buttons (gears.table.join (awful.button [] 1 (fn [] (awful.layout.inc 1 s awful.layout.layouts))) (awful.button [] 3 (fn [] (awful.layout.inc -1 s))) (awful.button [] 4 (fn [] (awful.layout.inc 1 s))) (awful.button [] 5 (fn [] (awful.layout.inc -1 s))))) ;; Create a taglist widget (set s.mytaglist (awful.widget.taglist { :screen s :filter awful.widget.taglist.filter.all :buttons taglist_buttons })) ;; Create a tasklist widget (set s.mytasklist (awful.widget.tasklist { :screen s :filter awful.widget.tasklist.filter.currenttags :buttons tasklist_buttons })) ;; Create the wibox (set s.mywibox (awful.wibar { :position "top" :screen s })) ;; Add widgets to the wibox (: s.mywibox :setup { :layout wibox.layout.align.horizontal 1 { ;; Left widgets :layout wibox.layout.fixed.horizontal 1 mylauncher 2 s.mytaglist 3 s.mypromptbox } 2 s.mytasklist ;; Middle widget 3 { ;; Right widgets :layout wibox.layout.fixed.horizontal 1 mykeyboardlayout 2 (wibox.widget.systray) 3 mytextclock 4 s.mylayoutbox } }))) ;; Mouse bindings (root.buttons (gears.table.join (awful.button [ ] 3 (fn [] (: mymainmenu :toggle))) (awful.button [ ] 4 awful.tag.viewnext) (awful.button [ ] 5 awful.tag.viewprev))) ;; key bindings (global 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" (fn [] (awful.client.focus.byidx 1)) {:description "focus next by index" :group "client"}) (awful.key [ modkey ] "k" (fn [] (awful.client.focus.byidx -1)) {:description "focus previous by index" :group "client"}) (awful.key [ modkey ] "w" (fn [] (: mymainmenu :show)) {:description "show main menu" :group "awesome"}) ;; Layout manipulation (awful.key [ modkey "Shift" ] "j" (fn [] (awful.client.swap.byidx 1)) {:description "swap with next client by index" :group "client"}) (awful.key [ modkey "Shift" ], "k" (fn [] (awful.client.swap.byidx -1)) {:description "swap with previous client by index" :group "client"}) (awful.key [ modkey "Control" ] "j" (fn [] (awful.screen.focus_relative 1)) {:description "focus the next screen" :group "screen"}) (awful.key [ modkey "Control" ] "k" (fn [] (awful.screen.focus_relative -1)) {: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" (fn [] (awful.client.focus.history.previous) (when client.focus (: client.focus :raise))) {:description "go back" :group "client"}) ;; Standard program (awful.key [ modkey ] "Return" (fn [] (awful.spawn terminal)) {: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" (fn [] (awful.tag.incmwfact 0.05)) {:description "increase master width factor" :group "layout"}) (awful.key [ modkey ] "h" (fn [] (awful.tag.incmwfact -0.05)) {:description "decrease master width factor" :group "layout"}) (awful.key [ modkey "Shift" ] "h" (fn [] (awful.tag.incnmaster 1 nil true)) {:description "increase the number of master clients" :group "layout"}) (awful.key [ modkey "Shift" ] "l" (fn [] (awful.tag.incnmaster -1 nil true)) {:description "decrease the number of master clients" :group "layout"}) (awful.key [ modkey "Control" ] "h" (fn [] (awful.tag.incncol 1 nil true)) {:description "increase the number of columns" :group "layout"}) (awful.key [ modkey "Control" ] "l" (fn [] (awful.tag.incncol -1 nil true)) {:description "decrease the number of columns" :group "layout"}) (awful.key [ modkey ] "space" (fn [] (awful.layout.inc 1)) {:description "select next" :group "layout"}) (awful.key [ modkey "Shift" ] "space" (fn [] (awful.layout.inc -1)) {:description "select previous" :group "layout"}) (awful.key [ modkey "Control" ] "n" (fn [] (local c (awful.client.restore)) (when c ;; Focus restored client (: c :emit_signal "request::activate" "key.unminimize" {:raise true}))) {:description "restore minimized" :group "client"}) ;; Prompt (awful.key [ modkey ] "r" (fn [] (: (. (awful.screen.focused) :mypromptbox) :run)) {:description "run prompt" :group "launcher"}) (awful.key [ modkey ] "x" (fn [] (let [fscr (awful.screen.focused)] (awful.prompt.run { :prompt "Run Lua code: " :textbox fscr.mypromptbox.widget :exe_callback awful.util.eval :history_path (.. (awful.util.get_cache_dir) "/history_eval") }))) {:description "lua execute prompt" :group "awesome"}) ;; Menubar (awful.key [ modkey ] "p" (fn [] (menubar.show)) {:description "show the menubar" :group "launcher"}))) (global clientkeys (gears.table.join (awful.key [ modkey ] "f" (fn [c] (set c.fullscreen (not c.fullscreen)) (: c :raise)) {:description "toggle fullscreen" :group "client"}) (awful.key [ modkey "Shift" ] "c" (fn [c] (: c :kill)) {:description "close" :group "client"}) (awful.key [ modkey "Control" ] "space" awful.client.floating.toggle {:description "toggle floating" :group "client"}) (awful.key [ modkey "Control" ] "Return" (fn [c] (: c :swap (awful.client.getmaster))) {:description "move to master" :group "client"}) (awful.key [ modkey ] "o" (fn [c] (: c :move_to_screen)) {:description "move to screen" :group "client"}) (awful.key [ modkey ] "t"(fn [c] (set c.ontop (not c.ontop))) {:description "toggle keep on top" :group "client"}) (awful.key [ modkey ] "n" (fn [c] ;; The client currently has the input focus, so it cannot be ;; minimized, since minimized clients can't have the focus. (set c.minimized true)) {:description "minimize" :group "client"}), (awful.key [ modkey ] "m" (fn [c] (set c.maximized (not c.maximized)) (: c :raise)) {:description "(un)maximize" :group "client"}), (awful.key [ modkey "Control" ] "m" (fn [c] (set c.maximized_vertical (not c.maximized_vertical)) (: c :raise)) {:description "(un)maximize vertically" :group "client"}), (awful.key [modkey "Shift" ] "m" (fn [c] (set c.maximized_horizontal (not c.maximized_horizontal)) (: c :raise)) {: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] (global globalkeys (gears.table.join globalkeys ;; View tag only. (awful.key [ modkey ] (.. "#" (+ i 9)) (fn [] (let [screen (awful.screen.focused) tag (. screen.tags i)] (when tag (: tag :view_only)))) {:description (.. "view tag #" i) :group "tag"}) ;; Toggle tag display (awful.key [ modkey "Control" ] (.. "#" (+ i 9)) (fn [] (let [screen (awful.screen.focused) tag (. screen.tags i)] (when tag (awful.tag.viewtoggle)))) {:description (.. "toggle tag #" i) :group "tag"}) ;; Move client to tag (awful.key [ modkey, "Shift" ] (.. "#" (+ i 9)) (fn [] (when client.focus (let [tag (. client.focus.screen.tags i)] (when tag (: client.focus :move_to_tag tag))))) {:description (.. "move focused client to tag #" i) :group "tag"}) ;; Toggle tag on focused client. (awful.key [ modkey "Control" "Shift" ] (.. "#" (+ i 9)) (fn [] (when client.focus (let [tag (. client.focus.screen.tags i)] (when tag (: client.focus :toggle_tag tag))))) {:description (.. "toggle focused client on tag #" i) :group "tag"})))) (global clientbuttons (gears.table.join (awful.button [] 1 (fn [c] (: c :emit_signal "request::activate" "mouse_click" {:raise true}))) (awful.button [ modkey ] 1 (fn [c] (: c :emit_signal "request::activate" "mouse_click" {:raise true}) (awful.mouse.client.move c))) (awful.button [ modkey ] 3 (fn [c] (: c :emit_signal "request::activate" "mouse_click" {:raise true}) (awful.mouse.client.resize c))))) ;; Set keys (root.keys globalkeys) ;; Rules ;; Rules to apply to new clients (through the "manage" signal) (set 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" } } ]) ;; Signals ;; Signal function to execute when a new client appears. (client.connect_signal "manage" (fn [c] ;; Set the windows at the slave, ;; i.e. put it at the end of others instead of setting it master. ;; (when (not awesome.startup) (awful.client.setslave c)) (when (and awesome.startup (not c.size_hints.user_position) (not c.size_hints.program_position)) ;; Prevent clients from being unreachable after screen count changes. (awful.placement.no_offscreen c)))) ;; Add a titlebar if titlebars_enabled is set to true in the rules. (client.connect_signal "request::titlebars" (fn [c] ;; buttons for the titlebar (let [buttons (gears.table.join (awful.button [] 1 (fn [] (: c :emit_signal "request::activate" "titlebar" {:raise true}) (awful.mouse.client.move c))) (awful.button [] 3 (fn [] (: c :emit_signal "request::activate" "titlebar" {:raise true}) (awful.mouse.client.resize c)))) titlebar (awful.titlebar c)] (: titlebar :setup { 1 { ;; Left 1 (awful.titlebar.widget.iconwidget c) :buttons buttons :layout wibox.layout.fixed.horizontal } 2 { ;; Middle 1 { ;; Title :align "center" :widget (awful.titlebar.widget.titlewidget c) } :buttons buttons :layout wibox.layout.flex.horizontal } 3 { ;; Right 1 (awful.titlebar.widget.floatingbutton c) 2 (awful.titlebar.widget.maximizedbutton c) 3 (awful.titlebar.widget.stickybutton c) 4 (awful.titlebar.widget.ontopbutton c) 5 (awful.titlebar.widget.closebutton c) :layout (wibox.layout.fixed.horizontal) } :layout wibox.layout.align.horizontal })))) ;; Enable sloppy focus, so that focus follows mouse. (client.connect_signal "mouse::enter" (fn [c] (: c :emit_signal "request::activate" "mouse_enter" {:raise false}))) (client.connect_signal "focus" (fn [c] (set c.border_color beautiful.border_focus))) (client.connect_signal "unfocus" (fn [c] (set c.border_color beautiful.border_normal)))