madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

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