updated rc.lua for upgrade in winter 2017-2018
[awesome-config] / rc.lua
1 -- Standard awesome library
2 local gears = require("gears")
3 local awful = require("awful")
4 require("awful.autofocus")
5 -- Widget and layout library
6 local wibox = require("wibox")
7 -- Theme handling library
8 local beautiful = require("beautiful")
9 -- Notification library
10 local naughty = require("naughty")
11 local menubar = require("menubar")
12 local hotkeys_popup = require("awful.hotkeys_popup").widget
13
14 -- Load Debian menu entries
15 require("debian.menu")
16
17 -- {{{ Error handling
18 -- Check if awesome encountered an error during startup and fell back to
19 -- another config (This code will only ever execute for the fallback config)
20 if awesome.startup_errors then
21     naughty.notify({ preset = naughty.config.presets.critical,
22                      title = "Oops, there were errors during startup!",
23                      text = awesome.startup_errors })
24 end
25
26 -- Handle runtime errors after startup
27 do
28     local in_error = false
29     awesome.connect_signal("debug::error", function (err)
30         -- Make sure we don't go into an endless error loop
31         if in_error then return end
32         in_error = true
33
34         naughty.notify({ preset = naughty.config.presets.critical,
35                          title = "Oops, an error happened!",
36                          text = tostring(err) })
37         in_error = false
38     end)
39 end
40 -- }}}
41
42 -- {{{ Variable definitions
43 -- Themes define colours, icons, font and wallpapers.
44 -- beautiful.init(awful.util.get_themes_dir() .. "default/theme.lua")
45 beautiful.init(awful.util.get_themes_dir() .. "sky/theme.lua")
46 beautiful.wallpaper = "/home/mako/images/Flag_of_Cascadia.png"
47
48 -- This is used later as the default terminal and editor to run.
49 terminal = "x-terminal-emulator"
50 editor = os.getenv("EDITOR") or "editor"
51 editor_cmd = terminal .. " -e " .. editor
52
53 -- Default modkey.
54 -- Usually, Mod4 is the key with a logo between Control and Alt.
55 -- If you do not like this or do not have such a key,
56 -- I suggest you to remap Mod4 to another key using xmodmap or other tools.
57 -- However, you can use another modifier like Mod1, but it may interact with others.
58 modkey = "Mod4"
59
60 -- Table of layouts to cover with awful.layout.inc, order matters.
61 awful.layout.layouts = {
62     awful.layout.suit.tile,
63     awful.layout.suit.max,
64     awful.layout.suit.floating
65 }
66 -- }}}
67
68 -- {{{ Helper functions
69 local function client_menu_toggle_fn()
70     local instance = nil
71
72     return function ()
73         if instance and instance.wibox.visible then
74             instance:hide()
75             instance = nil
76         else
77             instance = awful.menu.clients({ theme = { width = 250 } })
78         end
79     end
80 end
81 -- }}}
82
83 -- {{{ Menu
84 -- Create a launcher widget and a main menu
85 myawesomemenu = {
86    { "hotkeys", function() return false, hotkeys_popup.show_help end},
87    { "manual", terminal .. " -e man awesome" },
88    { "edit config", editor_cmd .. " " .. awesome.conffile },
89    { "restart", awesome.restart },
90    { "quit", function() awesome.quit() end}
91 }
92
93 mymainmenu = awful.menu({ items = { { "awesome", myawesomemenu, beautiful.awesome_icon },
94                                     { "Debian", debian.menu.Debian_menu.Debian },
95                                     { "open terminal", terminal }
96                                   }
97                         })
98
99 mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon,
100                                      menu = mymainmenu })
101
102 -- Menubar configuration
103 menubar.utils.terminal = terminal -- Set the terminal for applications that require it
104 -- }}}
105
106 -- Keyboard map indicator and switcher
107 mykeyboardlayout = awful.widget.keyboardlayout()
108
109 -- {{{ Wibar
110 -- Create a textclock widget
111 mytextclock = wibox.widget.textclock()
112
113 -- Create a wibox for each screen and add it
114 local taglist_buttons = awful.util.table.join(
115                     awful.button({ }, 1, function(t) t:view_only() end),
116                     awful.button({ modkey }, 1, function(t)
117                                               if client.focus then
118                                                   client.focus:move_to_tag(t)
119                                               end
120                                           end),
121                     awful.button({ }, 3, awful.tag.viewtoggle),
122                     awful.button({ modkey }, 3, function(t)
123                                               if client.focus then
124                                                   client.focus:toggle_tag(t)
125                                               end
126                                           end),
127                     awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
128                     awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
129                 )
130
131 local tasklist_buttons = awful.util.table.join(
132                      awful.button({ }, 1, function (c)
133                                               if c == client.focus then
134                                                   c.minimized = true
135                                               else
136                                                   -- Without this, the following
137                                                   -- :isvisible() makes no sense
138                                                   c.minimized = false
139                                                   if not c:isvisible() and c.first_tag then
140                                                       c.first_tag:view_only()
141                                                   end
142                                                   -- This will also un-minimize
143                                                   -- the client, if needed
144                                                   client.focus = c
145                                                   c:raise()
146                                               end
147                                           end),
148                      awful.button({ }, 3, client_menu_toggle_fn()),
149                      awful.button({ }, 4, function ()
150                                               awful.client.focus.byidx(1)
151                                           end),
152                      awful.button({ }, 5, function ()
153                                               awful.client.focus.byidx(-1)
154                                           end))
155
156 local function set_wallpaper(s)
157     -- Wallpaper
158     if beautiful.wallpaper then
159         local wallpaper = beautiful.wallpaper
160         -- If wallpaper is a function, call it with the screen
161         if type(wallpaper) == "function" then
162             wallpaper = wallpaper(s)
163         end
164         gears.wallpaper.maximized(wallpaper, s, true)
165     end
166 end
167
168 -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
169 screen.connect_signal("property::geometry", set_wallpaper)
170
171 awful.screen.connect_for_each_screen(function(s)
172     -- Wallpaper
173     set_wallpaper(s)
174
175     -- Each screen has its own tag table.
176     awful.tag({ "1", "2", "3", "4", "5", "6", "7", "8", "9" }, s, awful.layout.layouts[1])
177
178     -- Create a promptbox for each screen
179     s.mypromptbox = awful.widget.prompt()
180     -- Create an imagebox widget which will contains an icon indicating which layout we're using.
181     -- We need one layoutbox per screen.
182     s.mylayoutbox = awful.widget.layoutbox(s)
183     s.mylayoutbox:buttons(awful.util.table.join(
184                            awful.button({ }, 1, function () awful.layout.inc( 1) end),
185                            awful.button({ }, 3, function () awful.layout.inc(-1) end),
186                            awful.button({ }, 4, function () awful.layout.inc( 1) end),
187                            awful.button({ }, 5, function () awful.layout.inc(-1) end)))
188     -- Create a taglist widget
189     s.mytaglist = awful.widget.taglist(s, awful.widget.taglist.filter.all, taglist_buttons)
190
191     -- Create a tasklist widget
192     s.mytasklist = awful.widget.tasklist(s, awful.widget.tasklist.filter.currenttags, tasklist_buttons)
193
194     -- Create the wibox
195     s.mywibox = awful.wibar({ position = "top", screen = s })
196
197     -- Add widgets to the wibox
198     s.mywibox:setup {
199         layout = wibox.layout.align.horizontal,
200         { -- Left widgets
201             layout = wibox.layout.fixed.horizontal,
202             mylauncher,
203             s.mytaglist,
204             s.mypromptbox,
205         },
206         s.mytasklist, -- Middle widget
207         { -- Right widgets
208             layout = wibox.layout.fixed.horizontal,
209             mykeyboardlayout,
210             wibox.widget.systray(),
211             mytextclock,
212             s.mylayoutbox,
213         },
214     }
215 end)
216 -- }}}
217
218 -- {{{ Mouse bindings
219 root.buttons(awful.util.table.join(
220     awful.button({ }, 3, function () mymainmenu:toggle() end),
221     awful.button({ }, 4, awful.tag.viewnext),
222     awful.button({ }, 5, awful.tag.viewprev)
223 ))
224 -- }}}
225
226 -- {{{ Key bindings
227 globalkeys = awful.util.table.join(
228     awful.key({ modkey,           }, "s",      hotkeys_popup.show_help,
229               {description="show help", group="awesome"}),
230     awful.key({ modkey,           }, "Left",   awful.tag.viewprev,
231               {description = "view previous", group = "tag"}),
232     awful.key({ modkey,           }, "Right",  awful.tag.viewnext,
233               {description = "view next", group = "tag"}),
234     awful.key({ modkey,           }, "Escape", awful.tag.history.restore,
235               {description = "go back", group = "tag"}),
236
237     awful.key({ modkey,           }, "j",
238         function ()
239             awful.client.focus.byidx( 1)
240         end,
241         {description = "focus next by index", group = "client"}
242     ),
243     awful.key({ modkey,           }, "k",
244         function ()
245             awful.client.focus.byidx(-1)
246         end,
247         {description = "focus previous by index", group = "client"}
248     ),
249     awful.key({ modkey,           }, "w", function () mymainmenu:show() end,
250               {description = "show main menu", group = "awesome"}),
251
252     -- Layout manipulation
253     awful.key({ modkey, "Shift"   }, "j", function () awful.client.swap.byidx(  1)    end,
254               {description = "swap with next client by index", group = "client"}),
255     awful.key({ modkey, "Shift"   }, "k", function () awful.client.swap.byidx( -1)    end,
256               {description = "swap with previous client by index", group = "client"}),
257     awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
258               {description = "focus the next screen", group = "screen"}),
259     awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
260               {description = "focus the previous screen", group = "screen"}),
261     awful.key({ modkey,           }, "u", awful.client.urgent.jumpto,
262               {description = "jump to urgent client", group = "client"}),
263     awful.key({ modkey,           }, "Tab",
264         function ()
265             awful.client.focus.history.previous()
266             if client.focus then
267                 client.focus:raise()
268             end
269         end,
270         {description = "go back", group = "client"}),
271
272     -- Standard program
273     awful.key({ modkey,           }, "Return", function () awful.spawn(terminal) end,
274               {description = "open a terminal", group = "launcher"}),
275     awful.key({ modkey, "Control" }, "r", awesome.restart,
276               {description = "reload awesome", group = "awesome"}),
277     awful.key({ modkey, "Shift"   }, "q", awesome.quit,
278               {description = "quit awesome", group = "awesome"}),
279
280     awful.key({ modkey,           }, "l",     function () awful.tag.incmwfact( 0.05)          end,
281               {description = "increase master width factor", group = "layout"}),
282     awful.key({ modkey,           }, "h",     function () awful.tag.incmwfact(-0.05)          end,
283               {description = "decrease master width factor", group = "layout"}),
284     awful.key({ modkey, "Shift"   }, "h",     function () awful.tag.incnmaster( 1, nil, true) end,
285               {description = "increase the number of master clients", group = "layout"}),
286     awful.key({ modkey, "Shift"   }, "l",     function () awful.tag.incnmaster(-1, nil, true) end,
287               {description = "decrease the number of master clients", group = "layout"}),
288     awful.key({ modkey, "Control" }, "h",     function () awful.tag.incncol( 1, nil, true)    end,
289               {description = "increase the number of columns", group = "layout"}),
290     awful.key({ modkey, "Control" }, "l",     function () awful.tag.incncol(-1, nil, true)    end,
291               {description = "decrease the number of columns", group = "layout"}),
292     awful.key({ modkey,           }, "space", function () awful.layout.inc( 1)                end,
293               {description = "select next", group = "layout"}),
294     awful.key({ modkey, "Shift"   }, "space", function () awful.layout.inc(-1)                end,
295               {description = "select previous", group = "layout"}),
296
297     awful.key({ modkey, "Control" }, "n",
298               function ()
299                   local c = awful.client.restore()
300                   -- Focus restored client
301                   if c then
302                       client.focus = c
303                       c:raise()
304                   end
305               end,
306               {description = "restore minimized", group = "client"}),
307
308     -- Prompt
309     awful.key({ modkey },            "r",     function () awful.screen.focused().mypromptbox:run() end,
310               {description = "run prompt", group = "launcher"}),
311     
312     awful.key({ modkey,  }, "x",
313               function ()
314                   awful.prompt.run {
315                     prompt       = "Run in terminal: ",
316                     textbox      = awful.screen.focused().mypromptbox.widget,
317                     exe_callback = function (prog) awful.util.spawn_with_shell(terminal .. " -title " .. prog .. " -e " .. prog) end
318                   }
319               end,
320               {description = "terminal execute prompt", group = "awesome"}),
321
322     -- Mako's additional keybindings
323     --- {{{
324     awful.key({ modkey, "Shift", }, "x",
325               function ()
326                   awful.prompt.run {
327                     prompt       = "Run Lua code: ",
328                     textbox      = awful.screen.focused().mypromptbox.widget,
329                     exe_callback = awful.util.eval,
330                     history_path = awful.util.get_cache_dir() .. "/history_eval"
331                   }
332               end,
333               {description = "lua execute prompt", group = "awesome"}),
334
335     awful.key({ modkey }, "q",
336                   function ()
337                       awful.tag.incnmaster(-1)
338                       awful.tag.incncol(3)
339               end),
340
341     awful.key({ modkey, "Shift" }, "t", awful.titlebar.toggle),
342
343     --- }}}
344
345     -- Menubar
346     awful.key({ modkey }, "p", function() menubar.show() end,
347               {description = "show the menubar", group = "launcher"})
348 )
349
350 clientkeys = awful.util.table.join(
351     awful.key({ modkey,           }, "f",
352         function (c)
353             c.fullscreen = not c.fullscreen
354             c:raise()
355         end,
356         {description = "toggle fullscreen", group = "client"}),
357     awful.key({ modkey, "Shift"   }, "c",      function (c) c:kill()                         end,
358               {description = "close", group = "client"}),
359     awful.key({ modkey, "Control" }, "space",  awful.client.floating.toggle                     ,
360               {description = "toggle floating", group = "client"}),
361     awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
362               {description = "move to master", group = "client"}),
363     awful.key({ modkey,           }, "o",      function (c) c:move_to_screen()               end,
364               {description = "move to screen", group = "client"}),
365     awful.key({ modkey,           }, "t",      function (c) c.ontop = not c.ontop            end,
366               {description = "toggle keep on top", group = "client"}),
367     awful.key({ modkey,           }, "n",
368         function (c)
369             -- The client currently has the input focus, so it cannot be
370             -- minimized, since minimized clients can't have the focus.
371             c.minimized = true
372         end ,
373         {description = "minimize", group = "client"}),
374     awful.key({ modkey,           }, "m",
375         function (c)
376             c.maximized = not c.maximized
377             c:raise()
378         end ,
379         {description = "maximize", group = "client"})
380 )
381
382 -- Bind all key numbers to tags.
383 -- Be careful: we use keycodes to make it works on any keyboard layout.
384 -- This should map on the top row of your keyboard, usually 1 to 9.
385 for i = 1, 9 do
386     globalkeys = awful.util.table.join(globalkeys,
387         -- View tag only.
388         awful.key({ modkey }, "#" .. i + 9,
389                   function ()
390                         local screen = awful.screen.focused()
391                         local tag = screen.tags[i]
392                         if tag then
393                            tag:view_only()
394                         end
395                   end,
396                   {description = "view tag #"..i, group = "tag"}),
397         -- Toggle tag display.
398         awful.key({ modkey, "Control" }, "#" .. i + 9,
399                   function ()
400                       local screen = awful.screen.focused()
401                       local tag = screen.tags[i]
402                       if tag then
403                          awful.tag.viewtoggle(tag)
404                       end
405                   end,
406                   {description = "toggle tag #" .. i, group = "tag"}),
407         -- Move client to tag.
408         awful.key({ modkey, "Shift" }, "#" .. i + 9,
409                   function ()
410                       if client.focus then
411                           local tag = client.focus.screen.tags[i]
412                           if tag then
413                               client.focus:move_to_tag(tag)
414                           end
415                      end
416                   end,
417                   {description = "move focused client to tag #"..i, group = "tag"}),
418         -- Toggle tag on focused client.
419         awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
420                   function ()
421                       if client.focus then
422                           local tag = client.focus.screen.tags[i]
423                           if tag then
424                               client.focus:toggle_tag(tag)
425                           end
426                       end
427                   end,
428                   {description = "toggle focused client on tag #" .. i, group = "tag"})
429     )
430 end
431
432 clientbuttons = awful.util.table.join(
433     awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
434     awful.button({ modkey }, 1, awful.mouse.client.move),
435     awful.button({ modkey }, 3, awful.mouse.client.resize))
436
437 -- Set keys
438 root.keys(globalkeys)
439 -- }}}
440
441 -- {{{ Rules
442 -- Rules to apply to new clients (through the "manage" signal).
443 awful.rules.rules = {
444     -- All clients will match this rule.
445     { rule = { },
446       properties = { border_width = beautiful.border_width,
447                      border_color = beautiful.border_normal,
448                      focus = awful.client.focus.filter,
449                      raise = true,
450                      keys = clientkeys,
451                      buttons = clientbuttons,
452                      screen = awful.screen.preferred,
453                      placement = awful.placement.no_overlap+awful.placement.no_offscreen
454      }
455     },
456
457     -- Floating clients.
458     { rule_any = {
459         instance = {
460           "DTA",  -- Firefox addon DownThemAll.
461           "copyq",  -- Includes session name in class.
462         },
463         class = {
464           "Arandr",
465           "Gpick",
466           "Kruler",
467           "MessageWin",  -- kalarm.
468           "Sxiv",
469           "Wpa_gui",
470           "pinentry",
471           "veromix",
472           "xtightvncviewer"},
473
474         name = {
475           "Event Tester",  -- xev.
476         },
477         role = {
478           "AlarmWindow",  -- Thunderbird's calendar.
479           "pop-up",       -- e.g. Google Chrome's (detached) Developer Tools.
480         }
481       }, properties = { floating = true }},
482
483     -- Add titlebars to normal clients and dialogs
484     { rule_any = {type = { "normal", "dialog" }
485       }, properties = { titlebars_enabled = false }
486     },
487
488     -- Set Firefox to always map on the tag named "2" on screen 1.
489     -- { rule = { class = "Firefox" },
490     --   properties = { screen = 1, tag = "2" } },
491 }
492 -- }}}
493
494 -- {{{ Signals
495 -- Signal function to execute when a new client appears.
496 client.connect_signal("manage", function (c)
497     -- Set the windows at the slave,
498     -- i.e. put it at the end of others instead of setting it master.
499     -- if not awesome.startup then awful.client.setslave(c) end
500
501     if awesome.startup and
502       not c.size_hints.user_position
503       and not c.size_hints.program_position then
504         -- Prevent clients from being unreachable after screen count changes.
505         awful.placement.no_offscreen(c)
506     end
507 end)
508
509 -- Add a titlebar if titlebars_enabled is set to true in the rules.
510 client.connect_signal("request::titlebars", function(c)
511     -- buttons for the titlebar
512     local buttons = awful.util.table.join(
513         awful.button({ }, 1, function()
514             client.focus = c
515             c:raise()
516             awful.mouse.client.move(c)
517         end),
518         awful.button({ }, 3, function()
519             client.focus = c
520             c:raise()
521             awful.mouse.client.resize(c)
522         end)
523     )
524
525     awful.titlebar(c) : setup {
526         { -- Left
527             awful.titlebar.widget.iconwidget(c),
528             buttons = buttons,
529             layout  = wibox.layout.fixed.horizontal
530         },
531         { -- Middle
532             { -- Title
533                 align  = "center",
534                 widget = awful.titlebar.widget.titlewidget(c)
535             },
536             buttons = buttons,
537             layout  = wibox.layout.flex.horizontal
538         },
539         { -- Right
540             awful.titlebar.widget.floatingbutton (c),
541             awful.titlebar.widget.maximizedbutton(c),
542             awful.titlebar.widget.stickybutton   (c),
543             awful.titlebar.widget.ontopbutton    (c),
544             awful.titlebar.widget.closebutton    (c),
545             layout = wibox.layout.fixed.horizontal()
546         },
547         layout = wibox.layout.align.horizontal
548     }
549 end)
550
551 -- Enable sloppy focus, so that focus follows mouse.
552 client.connect_signal("mouse::enter", function(c)
553     if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier
554         and awful.client.focus.filter(c) then
555         client.focus = c
556     end
557 end)
558
559 client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
560 client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
561 -- }}}

Benjamin Mako Hill || Want to submit a patch?