(let [;; Standard awesome library gears (require :gears) awful (require :awful) ;; Widget and layout library wibox (require :wibox) ;; Theme handling library beautiful (require :beautiful) ;; Notification library naughty (require :naughty) menubar (require :menubar) hotkeys-popup (. (require :awful.hotkeys_popup) :widget)] (require :awful.autofocus) ;; Enable hotkeys help client widget for VIM and other apps ;; when client with a matching name is open (require :awful.hotkeys_popup.keys) ;; {{{ Error handling ;; Check if aweseom 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 error? false) (awesome.connect_signal "debug::error" (lambda [err] (when (not error?) (set error? true) (naughty.notify {:preset naughty.config.presets.critical :title "Oops, an error happened!" :text (tostring err)}) (set 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. (local terminal "xterm") (local editor (or (os.getenv "EDITOR") "nano")) (local 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. (local 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 ]) ;; }}} ;; {{{ Helper functions (fn client-menu-toggle-fn [] (var instance nil) (lambda [] (if (and instance (. instance :wibox :visible)) (do (: instance :hide) (set instance nil)) (set instance (awful.menu.clients {:theme {:width 250}}))))) ;; }}} ;; {{{ Menu ;; Create a launcher widget and a main menu (local myawesomemenu [["hotkeys" (lambda [] (values false hotkeys-popup.show_help))] ["manual" (.. terminal "-e man awesome")] ["edit config" (.. editor-cmd " " awesome.conffile)] ["restart" awesome.restart] ["quit" (lambda [] (awesome.quit))]]) (local mymainmenu (awful.menu {:items [["awesome" myawesomemenu beautiful.awesome_icon] ["open terminal" terminal]]})) (local 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 (local mykeyboardlayout (awful.widget.keyboardlayout)) ;; {{{ Wibar ;; Create a textclock widget (local mytextclock (wibox.widget.textclock)) ;; Create a wibox for each screen and add it (local taglist-buttons (gears.table.join (awful.button [] 1 (lambda [t] (: t :view_only))) (awful.button [modkey] 1 (lambda [t] (when client.focus (: client.focus :move_to_tag t)))) (awful.button [] 3 awful.tag.viewtoggle) (awful.button [modkey] 3 (lambda [t] (when client.focus (: client.focus :toggle_tag t)))) (awful.button [] 4 (lambda [t] (awful.tag.viewnext t.screen))) (awful.button [] 5 (lambda [t] (awful.tag.viewprev t.screen))))) (local tasklist-buttons (gears.table.join (awful.button [] 1 (lambda [c] (if (= c client.focus) (set c.minimized true) (do ;; Without this, the following ;; :isvisible makes no sense (set c.minimized false) (when (and (not (: c :isvisible)) c.first_tag) (: c.first_tag :view_only) ;; This will also un-minimize ;; the client, if needed (set client.focus c) (: c :raise)))))) (awful.button [] 3 (client-menu-toggle-fn)) (awful.button [] 4 (lambda [] (awful.client.focus.byidx 1))) (awful.button [] 5 (lambda [] (awful.client.focus.byidx -1))))) (fn set-wallpaper [s] (when beautiful.wallpaper (var wallpaper beautiful.wallpaper) (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 (lambda [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 layout box per screen. (set s.mylayoutbox (awful.widget.layoutbox s)) (: s.mylayoutbox :buttons (gears.table.join (awful.button [] 1 (lambda [] (awful.layout.inc 1))) (awful.button [] 3 (lambda [] (awful.layout.inc -1))) (awful.button [] 4 (lambda [] (awful.layout.inc 1))) (awful.button [] 5 (lambda [] (awful.layout.inc -1))))) ;; Create a taglist widget (set s.mytaglist (awful.widget.taglist s awful.widget.taglist.filter.all taglist-buttons)) ;; Create a tasklist widget (set s.mytasklist (awful.widget.tasklist s awful.widget.tasklist.filter.currenttags tasklist-buttons)) ;; Create the wibox (set s.mywibox (awful.wibar {:position "top" :screen s})) ;; Add widgets to the wibox ;; XXX Adding numbers is required workaround for mixed named and not tables. ;; Alternative is to construct table and then tset the named entry(s). (: 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 (lambda [] (: mymainmenu :toggle))) (awful.button [] 4 awful.tag.viewnext) (awful.button [] 5 awful.tag.viewprev))) ;;}}} ;; {{{ Key bindings (var 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 (lambda [] (awful.client.focus.byidx 1)) {:description "focus next by index" :group "client"}) (awful.key [modkey] :k (lambda [] (awful.client.focus.byidx -1)) {:description "focus previous by index" :group "client"}) (awful.key [modkey] :w (lambda [] (: mymainmenu :show)) {:description "show main menu" :group "awesome"}) ;; Layout manipulation (awful.key [modkey :Shift] :j (lambda [] (awful.client.swap.byidx 1)) {:description "swap with next client by index", :group "client"}) (awful.key [modkey :Shift] :k (lambda [] (awful.client.swap.byidx -1)) {:description "swap with previous client by index", :group "client"}) (awful.key [modkey :Control] :j (lambda [] (awful.screen.focus_relative 1)) {:description "focus the next screen", :group "screen"}) (awful.key [modkey :Control] :k (lambda [] (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 (lambda [] (awful.client.focus.history.previous) (when client.focus (: client.focus :raise))) {:description "go back" :group "client"}) ;; Standard program (awful.key [modkey] :Return (lambda [] (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 (lambda [] (awful.tag.incmwfact 0.05)) {:description "increase master width factor" :group "layout"}) (awful.key [modkey] :h (lambda [] (awful.tag.incmwfact -0.05)) {:description "decrease master width factor" :group "layout"}) (awful.key [modkey :Shift] :h (lambda [] (awful.tag.incnmaster 1 nil true)) {:description "increase the number of master clients" :group "layout"}) (awful.key [modkey :Shift] :l (lambda [] (awful.tag.incnmaster -1 nil true)) {:description "decrease the number of master clients" :group "layout"}) (awful.key [modkey :Control] :h (lambda [] (awful.tag.incncol 1 nil true)) {:description "increase the number of columns" :group "layout"}) (awful.key [modkey :Control] :l (lambda [] (awful.tag.incncol -1 nil true)) {:description "decrease the number of columns" :group "layout"}) (awful.key [modkey] :space (lambda [] (awful.layout.inc 1)) {:description "select next" :group "layout"}) (awful.key [modkey :Shift] :space (lambda [] (awful.layout.inc -1)) {:description "select previous" :group "layout"}) (awful.key [modkey :Control] :n (lambda [] (let [c (awful.client.restore)] ;; Focus restored client (when c (set client.focus c) (: c :raise)))) {:description "restore minimized" :group "client"}) ;; Prompt (awful.key [modkey] :r (lambda [] (: (. (awful.screen.focused) :mypromptbox) :run)) {:description "run prompt" :group "launcher"}) (awful.key [modkey] :x (lambda [] (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")})) {:description "lua execute prompt" :group "awesome"}) ;; Menubar (awful.key [modkey] :p (lambda [] (menubar.show)) {:description "show the menubar" :group "launcher"}))) (local clientkeys (gears.table.join (awful.key [modkey] :f (lambda [c] (set c.fullscreen (not c.fullscreen)) (: c :raise)) {:description "toggle fullscreen" :group "client"}) (awful.key [modkey :Shift] :c (lambda [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 (lambda [c] (: c :swap (awful.client.getmaster))) {:description "move to master" :group "client"}) (awful.key [modkey] :o (lambda [c] (: c :move_to_screen)) {:description "move to screen" :group "client"}) (awful.key [modkey] :t (lambda [c] (set c.ontop (not c.ontop))) {:description "toggle keep on top" :group "client"}) (awful.key [modkey] :n (lambda [c] (set c.minimized true)) ;; The client currently has the input focus, so it cannot be ;; minimized, since minimized clients can't have the focus {:description "minimize" :group "client"}) (awful.key [modkey] :m (lambda [c] (set c.maximized (not c.maximized)) (: c :raise)) {:description "(un)maximize" :group "client"}) (awful.key [modkey :Control] :m (lambda [c] (set c.maximized_vertical (not c.maximized_vertical)) (: c :raise)) {:description "(un)maximize vertically" :group "client"}) (awful.key [modkey :Shift] :m (lambda [c] (set c.maximized_horizontal (not c.maximized_horizontal)) (: c :raise)) {:description "(un)maximize horizontally" :group "client"}))) ;; Bind all keys numbers to tags. ;; Be careful: we use keycodes to make it work on any keyboard layout. ;; This should ma on the top row of your keyboard, usually 1 to 9. (for [i 1 9] (set globalkeys (gears.table.join globalkeys ;; View tag only. (awful.key [modkey] (.. "#" (+ i 9)) (lambda [] (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)) (lambda [] (let [screen (awful.screen.focused) tag (. screen.tags i)] (when tag (awful.tag.viewtoggle tag)))) {:description (.. "toggle tag #" i) :group "tag"}) ;; Move client to tag. (awful.key [modkey :Shift] (.. "#" (+ i 9)) (lambda [] (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)) (lambda [] (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"})))) (local clientbuttons (gears.table.join (awful.button [] 1 (lambda [c] (set client.focus c) (: c :raise))) (awful.button [modkey] 1 awful.mouse.client.move) (awful.button [modkey] 3 awful.mouse.client.resize))) ;; Set keys (root.keys globalkeys) ;;}}} ;; {{{ Rules ;; Rules 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. :class ["Arandr" "Gpick" "Kruler" "MessageWin" ;; kalarm. "Sxiv" "Wpa_gui" "pinentry" "veromix" "xtightvncviewer"] :name ["Event Tester"] ;; xev :role ["AlarmWindow" ;; Thunderbird's calendar "pop-up"]} ;; e.g. Google Chrome's (detatched) Developer Tools. :properties {:floating true}} ;; Add titlebars to normal clients and dialogs. {:rule_any {:type ["normal" "dialog"]} :properties {:titlebars_enabled true}} ;; 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" (lambda [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" (lambda [c] (let [buttons (gears.table.join (awful.button [] 1 (lambda [] (set client.focus c) (: c :raise) (awful.mouse.client.move c))) (awful.button [] 3 (lambda [] (set client.focus c) (: c :raise) (awful.mouse.client.resize c))))] (: (awful.titlebar c) :setup { ;; Left 1 {1 (awful.titlebar.widget.iconwidget c) :buttons buttons :layout wibox.layout.fixed.horizontal} ;; Middle 2 {1 {:align "center" ;; Title :widget (awful.titlebar.widget.titlewidget c)} :buttons buttons :layout wibox.layout.flex.horizontal} ;; Right 3 {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 the focus follows mouse. (client.connect_signal "mouse::enter" (lambda [c] (when (and (~= (awful.layout.get c.screen) awful.layout.suit.magnifier) (awful.client.focus.filter c)) (set client.focus c)))) (client.connect_signal "focus" (lambda [c] (set c.border_color beautiful.border_focus))) (client.connect_signal "unfocus" (lambda [c] (set c.border_color beautiful.border_normal)))) ;; }}}