My configuration files for Debian/Ubuntu applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

815 lines
31 KiB

  1. --[[
  2. Awesome WM configuration template
  3. github.com/lcpz
  4. --]]
  5. -- {{{ Required libraries
  6. -- If LuaRocks is installed, make sure that packages installed through it are
  7. -- found (e.g. lgi). If LuaRocks is not installed, do nothing.
  8. pcall(require, "luarocks.loader")
  9. local gears = require("gears")
  10. local awful = require("awful")
  11. require("awful.autofocus")
  12. local wibox = require("wibox")
  13. local beautiful = require("beautiful")
  14. local naughty = require("naughty")
  15. local lain = require("lain")
  16. --local menubar = require("menubar")
  17. local freedesktop = require("freedesktop")
  18. local hotkeys_popup = require("awful.hotkeys_popup")
  19. require("awful.hotkeys_popup.keys")
  20. local mytable = awful.util.table or gears.table -- 4.{0,1} compatibility
  21. -- }}}
  22. -- {{{ Error handling
  23. -- Check if awesome encountered an error during startup and fell back to
  24. -- another config (This code will only ever execute for the fallback config)
  25. if awesome.startup_errors then
  26. naughty.notify {
  27. preset = naughty.config.presets.critical,
  28. title = "Oops, there were errors during startup!",
  29. text = awesome.startup_errors
  30. }
  31. end
  32. -- Handle runtime errors after startup
  33. do
  34. local in_error = false
  35. awesome.connect_signal("debug::error", function (err)
  36. if in_error then return end
  37. in_error = true
  38. naughty.notify {
  39. preset = naughty.config.presets.critical,
  40. title = "Oops, an error happened!",
  41. text = tostring(err)
  42. }
  43. in_error = false
  44. end)
  45. end
  46. -- }}}
  47. -- {{{ Autostart windowless processes
  48. -- This function will run once every time Awesome is started
  49. local function run_once(cmd_arr)
  50. for _, cmd in ipairs(cmd_arr) do
  51. awful.spawn.with_shell(string.format("pgrep -u $USER -fx '%s' > /dev/null || (%s)", cmd, cmd))
  52. end
  53. end
  54. run_once({ "urxvtd", "unclutter -root" }) -- comma-separated entries
  55. -- This function implements the XDG autostart specification
  56. --[[
  57. awful.spawn.with_shell(
  58. 'if (xrdb -query | grep -q "^awesome\\.started:\\s*true$"); then exit; fi;' ..
  59. 'xrdb -merge <<< "awesome.started:true";' ..
  60. -- list each of your autostart commands, followed by ; inside single quotes, followed by ..
  61. 'dex --environment Awesome --autostart --search-paths "$XDG_CONFIG_DIRS/autostart:$XDG_CONFIG_HOME/autostart"' -- https://github.com/jceb/dex
  62. )
  63. --]]
  64. -- }}}
  65. -- {{{ Variable definitions
  66. local themes = {
  67. "blackburn", -- 1
  68. "copland", -- 2
  69. "dremora", -- 3
  70. "holo", -- 4
  71. "multicolor", -- 5
  72. "powerarrow", -- 6
  73. "powerarrow-dark", -- 7
  74. "rainbow", -- 8
  75. "steamburn", -- 9
  76. "vertex" -- 10
  77. }
  78. local chosen_theme = themes[5]
  79. local modkey = "Mod4"
  80. local altkey = "Mod1"
  81. local terminal = "urxvtc"
  82. local vi_focus = false -- vi-like client focus https://github.com/lcpz/awesome-copycats/issues/275
  83. local cycle_prev = true -- cycle with only the previously focused client or all https://github.com/lcpz/awesome-copycats/issues/274
  84. local editor = os.getenv("EDITOR") or "nvim"
  85. local browser = "librewolf"
  86. awful.util.terminal = terminal
  87. awful.util.tagnames = { "1", "2", "3", "4", "5" }
  88. awful.layout.layouts = {
  89. awful.layout.suit.floating,
  90. awful.layout.suit.tile,
  91. awful.layout.suit.tile.left,
  92. awful.layout.suit.tile.bottom,
  93. awful.layout.suit.tile.top,
  94. --awful.layout.suit.fair,
  95. --awful.layout.suit.fair.horizontal,
  96. --awful.layout.suit.spiral,
  97. --awful.layout.suit.spiral.dwindle,
  98. --awful.layout.suit.max,
  99. --awful.layout.suit.max.fullscreen,
  100. --awful.layout.suit.magnifier,
  101. --awful.layout.suit.corner.nw,
  102. --awful.layout.suit.corner.ne,
  103. --awful.layout.suit.corner.sw,
  104. --awful.layout.suit.corner.se,
  105. --lain.layout.cascade,
  106. --lain.layout.cascade.tile,
  107. --lain.layout.centerwork,
  108. --lain.layout.centerwork.horizontal,
  109. --lain.layout.termfair,
  110. --lain.layout.termfair.center
  111. }
  112. lain.layout.termfair.nmaster = 3
  113. lain.layout.termfair.ncol = 1
  114. lain.layout.termfair.center.nmaster = 3
  115. lain.layout.termfair.center.ncol = 1
  116. lain.layout.cascade.tile.offset_x = 2
  117. lain.layout.cascade.tile.offset_y = 32
  118. lain.layout.cascade.tile.extra_padding = 5
  119. lain.layout.cascade.tile.nmaster = 5
  120. lain.layout.cascade.tile.ncol = 2
  121. awful.util.taglist_buttons = mytable.join(
  122. awful.button({ }, 1, function(t) t:view_only() end),
  123. awful.button({ modkey }, 1, function(t)
  124. if client.focus then client.focus:move_to_tag(t) end
  125. end),
  126. awful.button({ }, 3, awful.tag.viewtoggle),
  127. awful.button({ modkey }, 3, function(t)
  128. if client.focus then client.focus:toggle_tag(t) end
  129. end),
  130. awful.button({ }, 4, function(t) awful.tag.viewnext(t.screen) end),
  131. awful.button({ }, 5, function(t) awful.tag.viewprev(t.screen) end)
  132. )
  133. awful.util.tasklist_buttons = mytable.join(
  134. awful.button({ }, 1, function(c)
  135. if c == client.focus then
  136. c.minimized = true
  137. else
  138. c:emit_signal("request::activate", "tasklist", { raise = true })
  139. end
  140. end),
  141. awful.button({ }, 3, function()
  142. awful.menu.client_list({ theme = { width = 250 } })
  143. end),
  144. awful.button({ }, 4, function() awful.client.focus.byidx(1) end),
  145. awful.button({ }, 5, function() awful.client.focus.byidx(-1) end)
  146. )
  147. beautiful.init(string.format("%s/.config/awesome/themes/%s/theme.lua", os.getenv("HOME"), chosen_theme))
  148. -- }}}
  149. -- {{{ Menu
  150. -- Create a launcher widget and a main menu
  151. local myawesomemenu = {
  152. { "Hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end },
  153. { "Manual", string.format("%s -e man awesome", terminal) },
  154. { "Edit config", string.format("%s -e %s %s", terminal, editor, awesome.conffile) },
  155. { "Restart", awesome.restart },
  156. { "Quit", function() awesome.quit() end },
  157. }
  158. awful.util.mymainmenu = freedesktop.menu.build {
  159. before = {
  160. { "Awesome", myawesomemenu, beautiful.awesome_icon },
  161. -- other triads can be put here
  162. },
  163. after = {
  164. { "Open terminal", terminal },
  165. -- other triads can be put here
  166. }
  167. }
  168. -- Hide the menu when the mouse leaves it
  169. --[[
  170. awful.util.mymainmenu.wibox:connect_signal("mouse::leave", function()
  171. if not awful.util.mymainmenu.active_child or
  172. (awful.util.mymainmenu.wibox ~= mouse.current_wibox and
  173. awful.util.mymainmenu.active_child.wibox ~= mouse.current_wibox) then
  174. awful.util.mymainmenu:hide()
  175. else
  176. awful.util.mymainmenu.active_child.wibox:connect_signal("mouse::leave",
  177. function()
  178. if awful.util.mymainmenu.wibox ~= mouse.current_wibox then
  179. awful.util.mymainmenu:hide()
  180. end
  181. end)
  182. end
  183. end)
  184. --]]
  185. -- Set the Menubar terminal for applications that require it
  186. --menubar.utils.terminal = terminal
  187. -- }}}
  188. -- {{{ Screen
  189. -- Re-set wallpaper when a screen's geometry changes (e.g. different resolution)
  190. screen.connect_signal("property::geometry", function(s)
  191. -- Wallpaper
  192. if beautiful.wallpaper then
  193. local wallpaper = beautiful.wallpaper
  194. -- If wallpaper is a function, call it with the screen
  195. if type(wallpaper) == "function" then
  196. wallpaper = wallpaper(s)
  197. end
  198. gears.wallpaper.maximized(wallpaper, s, true)
  199. end
  200. end)
  201. -- No borders when rearranging only 1 non-floating or maximized client
  202. screen.connect_signal("arrange", function (s)
  203. local only_one = #s.tiled_clients == 1
  204. for _, c in pairs(s.clients) do
  205. if only_one and not c.floating or c.maximized or c.fullscreen then
  206. c.border_width = 0
  207. else
  208. c.border_width = beautiful.border_width
  209. end
  210. end
  211. end)
  212. -- Create a wibox for each screen and add it
  213. awful.screen.connect_for_each_screen(function(s) beautiful.at_screen_connect(s) end)
  214. -- }}}
  215. -- {{{ Mouse bindings
  216. root.buttons(mytable.join(
  217. awful.button({ }, 3, function () awful.util.mymainmenu:toggle() end),
  218. awful.button({ }, 4, awful.tag.viewnext),
  219. awful.button({ }, 5, awful.tag.viewprev)
  220. ))
  221. -- }}}
  222. -- {{{ Key bindings
  223. globalkeys = mytable.join(
  224. -- Destroy all notifications
  225. awful.key({ "Control", }, "space", function() naughty.destroy_all_notifications() end,
  226. {description = "destroy all notifications", group = "hotkeys"}),
  227. -- Take a screenshot
  228. -- https://github.com/lcpz/dots/blob/master/bin/screenshot
  229. awful.key({ altkey }, "p", function() os.execute("screenshot") end,
  230. {description = "take a screenshot", group = "hotkeys"}),
  231. -- X screen locker
  232. awful.key({ altkey, "Control" }, "l", function () os.execute(scrlocker) end,
  233. {description = "lock screen", group = "hotkeys"}),
  234. -- Show help
  235. awful.key({ modkey, }, "s", hotkeys_popup.show_help,
  236. {description="show help", group="awesome"}),
  237. -- Tag browsing
  238. awful.key({ modkey, }, "Left", awful.tag.viewprev,
  239. {description = "view previous", group = "tag"}),
  240. awful.key({ modkey, }, "Right", awful.tag.viewnext,
  241. {description = "view next", group = "tag"}),
  242. awful.key({ modkey, }, "Escape", awful.tag.history.restore,
  243. {description = "go back", group = "tag"}),
  244. -- Non-empty tag browsing
  245. awful.key({ altkey }, "Left", function () lain.util.tag_view_nonempty(-1) end,
  246. {description = "view previous nonempty", group = "tag"}),
  247. awful.key({ altkey }, "Right", function () lain.util.tag_view_nonempty(1) end,
  248. {description = "view previous nonempty", group = "tag"}),
  249. -- Default client focus
  250. awful.key({ altkey, }, "j",
  251. function ()
  252. awful.client.focus.byidx( 1)
  253. end,
  254. {description = "focus next by index", group = "client"}
  255. ),
  256. awful.key({ altkey, }, "k",
  257. function ()
  258. awful.client.focus.byidx(-1)
  259. end,
  260. {description = "focus previous by index", group = "client"}
  261. ),
  262. -- By-direction client focus
  263. awful.key({ modkey }, "j",
  264. function()
  265. awful.client.focus.global_bydirection("down")
  266. if client.focus then client.focus:raise() end
  267. end,
  268. {description = "focus down", group = "client"}),
  269. awful.key({ modkey }, "k",
  270. function()
  271. awful.client.focus.global_bydirection("up")
  272. if client.focus then client.focus:raise() end
  273. end,
  274. {description = "focus up", group = "client"}),
  275. awful.key({ modkey }, "h",
  276. function()
  277. awful.client.focus.global_bydirection("left")
  278. if client.focus then client.focus:raise() end
  279. end,
  280. {description = "focus left", group = "client"}),
  281. awful.key({ modkey }, "l",
  282. function()
  283. awful.client.focus.global_bydirection("right")
  284. if client.focus then client.focus:raise() end
  285. end,
  286. {description = "focus right", group = "client"}),
  287. -- Menu
  288. awful.key({ modkey, }, "w", function () awful.util.mymainmenu:show() end,
  289. {description = "show main menu", group = "awesome"}),
  290. -- Layout manipulation
  291. awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
  292. {description = "swap with next client by index", group = "client"}),
  293. awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
  294. {description = "swap with previous client by index", group = "client"}),
  295. awful.key({ modkey, "Control" }, "j", function () awful.screen.focus_relative( 1) end,
  296. {description = "focus the next screen", group = "screen"}),
  297. awful.key({ modkey, "Control" }, "k", function () awful.screen.focus_relative(-1) end,
  298. {description = "focus the previous screen", group = "screen"}),
  299. awful.key({ modkey, }, "u", awful.client.urgent.jumpto,
  300. {description = "jump to urgent client", group = "client"}),
  301. awful.key({ modkey, }, "Tab",
  302. function ()
  303. if cycle_prev then
  304. awful.client.focus.history.previous()
  305. else
  306. awful.client.focus.byidx(-1)
  307. end
  308. if client.focus then
  309. client.focus:raise()
  310. end
  311. end,
  312. {description = "cycle with previous/go back", group = "client"}),
  313. -- Show/hide wibox
  314. awful.key({ modkey }, "b", function ()
  315. for s in screen do
  316. s.mywibox.visible = not s.mywibox.visible
  317. if s.mybottomwibox then
  318. s.mybottomwibox.visible = not s.mybottomwibox.visible
  319. end
  320. end
  321. end,
  322. {description = "toggle wibox", group = "awesome"}),
  323. -- On-the-fly useless gaps change
  324. awful.key({ altkey, "Control" }, "+", function () lain.util.useless_gaps_resize(1) end,
  325. {description = "increment useless gaps", group = "tag"}),
  326. awful.key({ altkey, "Control" }, "-", function () lain.util.useless_gaps_resize(-1) end,
  327. {description = "decrement useless gaps", group = "tag"}),
  328. -- Dynamic tagging
  329. awful.key({ modkey, "Shift" }, "n", function () lain.util.add_tag() end,
  330. {description = "add new tag", group = "tag"}),
  331. awful.key({ modkey, "Shift" }, "r", function () lain.util.rename_tag() end,
  332. {description = "rename tag", group = "tag"}),
  333. awful.key({ modkey, "Shift" }, "Left", function () lain.util.move_tag(-1) end,
  334. {description = "move tag to the left", group = "tag"}),
  335. awful.key({ modkey, "Shift" }, "Right", function () lain.util.move_tag(1) end,
  336. {description = "move tag to the right", group = "tag"}),
  337. awful.key({ modkey, "Shift" }, "d", function () lain.util.delete_tag() end,
  338. {description = "delete tag", group = "tag"}),
  339. -- Standard program
  340. awful.key({ modkey, }, "Return", function () awful.spawn(terminal) end,
  341. {description = "open a terminal", group = "launcher"}),
  342. awful.key({ modkey, "Control" }, "r", awesome.restart,
  343. {description = "reload awesome", group = "awesome"}),
  344. awful.key({ modkey, "Shift" }, "q", awesome.quit,
  345. {description = "quit awesome", group = "awesome"}),
  346. awful.key({ modkey, altkey }, "l", function () awful.tag.incmwfact( 0.05) end,
  347. {description = "increase master width factor", group = "layout"}),
  348. awful.key({ modkey, altkey }, "h", function () awful.tag.incmwfact(-0.05) end,
  349. {description = "decrease master width factor", group = "layout"}),
  350. awful.key({ modkey, "Shift" }, "h", function () awful.tag.incnmaster( 1, nil, true) end,
  351. {description = "increase the number of master clients", group = "layout"}),
  352. awful.key({ modkey, "Shift" }, "l", function () awful.tag.incnmaster(-1, nil, true) end,
  353. {description = "decrease the number of master clients", group = "layout"}),
  354. awful.key({ modkey, "Control" }, "h", function () awful.tag.incncol( 1, nil, true) end,
  355. {description = "increase the number of columns", group = "layout"}),
  356. awful.key({ modkey, "Control" }, "l", function () awful.tag.incncol(-1, nil, true) end,
  357. {description = "decrease the number of columns", group = "layout"}),
  358. awful.key({ modkey, }, "space", function () awful.layout.inc( 1) end,
  359. {description = "select next", group = "layout"}),
  360. awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(-1) end,
  361. {description = "select previous", group = "layout"}),
  362. awful.key({ modkey, "Control" }, "n", function ()
  363. local c = awful.client.restore()
  364. -- Focus restored client
  365. if c then
  366. c:emit_signal("request::activate", "key.unminimize", {raise = true})
  367. end
  368. end, {description = "restore minimized", group = "client"}),
  369. -- Dropdown application
  370. awful.key({ modkey, }, "z", function () awful.screen.focused().quake:toggle() end,
  371. {description = "dropdown application", group = "launcher"}),
  372. -- Widgets popups
  373. awful.key({ altkey, }, "c", function () if beautiful.cal then beautiful.cal.show(7) end end,
  374. {description = "show calendar", group = "widgets"}),
  375. awful.key({ altkey, }, "h", function () if beautiful.fs then beautiful.fs.show(7) end end,
  376. {description = "show filesystem", group = "widgets"}),
  377. awful.key({ altkey, }, "w", function () if beautiful.weather then beautiful.weather.show(7) end end,
  378. {description = "show weather", group = "widgets"}),
  379. -- Screen brightness
  380. awful.key({ }, "XF86MonBrightnessUp", function () os.execute("xbacklight -inc 10") end,
  381. {description = "+10%", group = "hotkeys"}),
  382. awful.key({ }, "XF86MonBrightnessDown", function () os.execute("xbacklight -dec 10") end,
  383. {description = "-10%", group = "hotkeys"}),
  384. -- ALSA volume control
  385. awful.key({ altkey }, "Up",
  386. function ()
  387. os.execute(string.format("amixer -q set %s 1%%+", beautiful.volume.channel))
  388. beautiful.volume.update()
  389. end,
  390. {description = "volume up", group = "hotkeys"}),
  391. awful.key({ altkey }, "Down",
  392. function ()
  393. os.execute(string.format("amixer -q set %s 1%%-", beautiful.volume.channel))
  394. beautiful.volume.update()
  395. end,
  396. {description = "volume down", group = "hotkeys"}),
  397. awful.key({ altkey }, "m",
  398. function ()
  399. os.execute(string.format("amixer -q set %s toggle", beautiful.volume.togglechannel or beautiful.volume.channel))
  400. beautiful.volume.update()
  401. end,
  402. {description = "toggle mute", group = "hotkeys"}),
  403. awful.key({ altkey, "Control" }, "m",
  404. function ()
  405. os.execute(string.format("amixer -q set %s 100%%", beautiful.volume.channel))
  406. beautiful.volume.update()
  407. end,
  408. {description = "volume 100%", group = "hotkeys"}),
  409. awful.key({ altkey, "Control" }, "0",
  410. function ()
  411. os.execute(string.format("amixer -q set %s 0%%", beautiful.volume.channel))
  412. beautiful.volume.update()
  413. end,
  414. {description = "volume 0%", group = "hotkeys"}),
  415. -- MPD control
  416. awful.key({ altkey, "Control" }, "Up",
  417. function ()
  418. os.execute("mpc toggle")
  419. beautiful.mpd.update()
  420. end,
  421. {description = "mpc toggle", group = "widgets"}),
  422. awful.key({ altkey, "Control" }, "Down",
  423. function ()
  424. os.execute("mpc stop")
  425. beautiful.mpd.update()
  426. end,
  427. {description = "mpc stop", group = "widgets"}),
  428. awful.key({ altkey, "Control" }, "Left",
  429. function ()
  430. os.execute("mpc prev")
  431. beautiful.mpd.update()
  432. end,
  433. {description = "mpc prev", group = "widgets"}),
  434. awful.key({ altkey, "Control" }, "Right",
  435. function ()
  436. os.execute("mpc next")
  437. beautiful.mpd.update()
  438. end,
  439. {description = "mpc next", group = "widgets"}),
  440. awful.key({ altkey }, "0",
  441. function ()
  442. local common = { text = "MPD widget ", position = "top_middle", timeout = 2 }
  443. if beautiful.mpd.timer.started then
  444. beautiful.mpd.timer:stop()
  445. common.text = common.text .. lain.util.markup.bold("OFF")
  446. else
  447. beautiful.mpd.timer:start()
  448. common.text = common.text .. lain.util.markup.bold("ON")
  449. end
  450. naughty.notify(common)
  451. end,
  452. {description = "mpc on/off", group = "widgets"}),
  453. -- Copy primary to clipboard (terminals to gtk)
  454. awful.key({ modkey }, "c", function () awful.spawn.with_shell("xsel | xsel -i -b") end,
  455. {description = "copy terminal to gtk", group = "hotkeys"}),
  456. -- Copy clipboard to primary (gtk to terminals)
  457. awful.key({ modkey }, "v", function () awful.spawn.with_shell("xsel -b | xsel") end,
  458. {description = "copy gtk to terminal", group = "hotkeys"}),
  459. -- User programs
  460. awful.key({ modkey }, "q", function () awful.spawn(browser) end,
  461. {description = "run browser", group = "launcher"}),
  462. -- Default
  463. --[[ Menubar
  464. awful.key({ modkey }, "p", function() menubar.show() end,
  465. {description = "show the menubar", group = "launcher"}),
  466. --]]
  467. --[[ dmenu
  468. awful.key({ modkey }, "x", function ()
  469. os.execute(string.format("dmenu_run -i -fn 'Monospace' -nb '%s' -nf '%s' -sb '%s' -sf '%s'",
  470. beautiful.bg_normal, beautiful.fg_normal, beautiful.bg_focus, beautiful.fg_focus))
  471. end,
  472. {description = "show dmenu", group = "launcher"}),
  473. --]]
  474. -- alternatively use rofi, a dmenu-like application with more features
  475. -- check https://github.com/DaveDavenport/rofi for more details
  476. --[[ rofi
  477. awful.key({ modkey }, "x", function ()
  478. os.execute(string.format("rofi -show %s -theme %s",
  479. 'run', 'dmenu'))
  480. end,
  481. {description = "show rofi", group = "launcher"}),
  482. --]]
  483. -- Prompt
  484. awful.key({ modkey }, "r", function () awful.screen.focused().mypromptbox:run() end,
  485. {description = "run prompt", group = "launcher"}),
  486. awful.key({ modkey }, "x",
  487. function ()
  488. awful.prompt.run {
  489. prompt = "Run Lua code: ",
  490. textbox = awful.screen.focused().mypromptbox.widget,
  491. exe_callback = awful.util.eval,
  492. history_path = awful.util.get_cache_dir() .. "/history_eval"
  493. }
  494. end,
  495. {description = "lua execute prompt", group = "awesome"})
  496. --]]
  497. )
  498. clientkeys = mytable.join(
  499. awful.key({ altkey, "Shift" }, "m", lain.util.magnify_client,
  500. {description = "magnify client", group = "client"}),
  501. awful.key({ modkey, }, "f",
  502. function (c)
  503. c.fullscreen = not c.fullscreen
  504. c:raise()
  505. end,
  506. {description = "toggle fullscreen", group = "client"}),
  507. awful.key({ modkey, "Shift" }, "c", function (c) c:kill() end,
  508. {description = "close", group = "client"}),
  509. awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle ,
  510. {description = "toggle floating", group = "client"}),
  511. awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
  512. {description = "move to master", group = "client"}),
  513. awful.key({ modkey, }, "o", function (c) c:move_to_screen() end,
  514. {description = "move to screen", group = "client"}),
  515. awful.key({ modkey, }, "t", function (c) c.ontop = not c.ontop end,
  516. {description = "toggle keep on top", group = "client"}),
  517. awful.key({ modkey, }, "n",
  518. function (c)
  519. -- The client currently has the input focus, so it cannot be
  520. -- minimized, since minimized clients can't have the focus.
  521. c.minimized = true
  522. end ,
  523. {description = "minimize", group = "client"}),
  524. awful.key({ modkey, }, "m",
  525. function (c)
  526. c.maximized = not c.maximized
  527. c:raise()
  528. end ,
  529. {description = "(un)maximize", group = "client"}),
  530. awful.key({ modkey, "Control" }, "m",
  531. function (c)
  532. c.maximized_vertical = not c.maximized_vertical
  533. c:raise()
  534. end ,
  535. {description = "(un)maximize vertically", group = "client"}),
  536. awful.key({ modkey, "Shift" }, "m",
  537. function (c)
  538. c.maximized_horizontal = not c.maximized_horizontal
  539. c:raise()
  540. end ,
  541. {description = "(un)maximize horizontally", group = "client"})
  542. )
  543. -- Bind all key numbers to tags.
  544. -- Be careful: we use keycodes to make it work on any keyboard layout.
  545. -- This should map on the top row of your keyboard, usually 1 to 9.
  546. for i = 1, 9 do
  547. globalkeys = mytable.join(globalkeys,
  548. -- View tag only.
  549. awful.key({ modkey }, "#" .. i + 9,
  550. function ()
  551. local screen = awful.screen.focused()
  552. local tag = screen.tags[i]
  553. if tag then
  554. tag:view_only()
  555. end
  556. end,
  557. {description = "view tag #"..i, group = "tag"}),
  558. -- Toggle tag display.
  559. awful.key({ modkey, "Control" }, "#" .. i + 9,
  560. function ()
  561. local screen = awful.screen.focused()
  562. local tag = screen.tags[i]
  563. if tag then
  564. awful.tag.viewtoggle(tag)
  565. end
  566. end,
  567. {description = "toggle tag #" .. i, group = "tag"}),
  568. -- Move client to tag.
  569. awful.key({ modkey, "Shift" }, "#" .. i + 9,
  570. function ()
  571. if client.focus then
  572. local tag = client.focus.screen.tags[i]
  573. if tag then
  574. client.focus:move_to_tag(tag)
  575. end
  576. end
  577. end,
  578. {description = "move focused client to tag #"..i, group = "tag"}),
  579. -- Toggle tag on focused client.
  580. awful.key({ modkey, "Control", "Shift" }, "#" .. i + 9,
  581. function ()
  582. if client.focus then
  583. local tag = client.focus.screen.tags[i]
  584. if tag then
  585. client.focus:toggle_tag(tag)
  586. end
  587. end
  588. end,
  589. {description = "toggle focused client on tag #" .. i, group = "tag"})
  590. )
  591. end
  592. clientbuttons = mytable.join(
  593. awful.button({ }, 1, function (c)
  594. c:emit_signal("request::activate", "mouse_click", {raise = true})
  595. end),
  596. awful.button({ modkey }, 1, function (c)
  597. c:emit_signal("request::activate", "mouse_click", {raise = true})
  598. awful.mouse.client.move(c)
  599. end),
  600. awful.button({ modkey }, 3, function (c)
  601. c:emit_signal("request::activate", "mouse_click", {raise = true})
  602. awful.mouse.client.resize(c)
  603. end)
  604. )
  605. -- Set keys
  606. root.keys(globalkeys)
  607. -- }}}
  608. -- {{{ Rules
  609. -- Rules to apply to new clients (through the "manage" signal).
  610. awful.rules.rules = {
  611. -- All clients will match this rule.
  612. { rule = { },
  613. properties = { border_width = beautiful.border_width,
  614. border_color = beautiful.border_normal,
  615. callback = awful.client.setslave,
  616. focus = awful.client.focus.filter,
  617. raise = true,
  618. keys = clientkeys,
  619. buttons = clientbuttons,
  620. screen = awful.screen.preferred,
  621. placement = awful.placement.no_overlap+awful.placement.no_offscreen,
  622. size_hints_honor = false
  623. }
  624. },
  625. -- Floating clients.
  626. { rule_any = {
  627. instance = {
  628. "DTA", -- Firefox addon DownThemAll.
  629. "copyq", -- Includes session name in class.
  630. "pinentry",
  631. },
  632. class = {
  633. "Arandr",
  634. "Blueman-manager",
  635. "Gpick",
  636. "Kruler",
  637. "MessageWin", -- kalarm.
  638. "Sxiv",
  639. "Tor Browser", -- Needs a fixed window size to avoid fingerprinting by screen size.
  640. "Wpa_gui",
  641. "veromix",
  642. "xtightvncviewer"},
  643. -- Note that the name property shown in xprop might be set slightly after creation of the client
  644. -- and the name shown there might not match defined rules here.
  645. name = {
  646. "Event Tester", -- xev.
  647. },
  648. role = {
  649. "AlarmWindow", -- Thunderbird's calendar.
  650. "ConfigManager", -- Thunderbird's about:config.
  651. "pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
  652. }
  653. }, properties = { floating = true }},
  654. -- Add titlebars to normal clients and dialogs
  655. { rule_any = {type = { "normal", "dialog" }
  656. }, properties = { titlebars_enabled = true }
  657. },
  658. -- Set Firefox to always map on the tag named "2" on screen 1.
  659. -- { rule = { class = "Firefox" },
  660. -- properties = { screen = 1, tag = "2" } },
  661. }
  662. -- }}}
  663. -- {{{ Signals
  664. -- Signal function to execute when a new client appears.
  665. client.connect_signal("manage", function (c)
  666. -- Set the windows at the slave,
  667. -- i.e. put it at the end of others instead of setting it master.
  668. -- if not awesome.startup then awful.client.setslave(c) end
  669. if awesome.startup
  670. and not c.size_hints.user_position
  671. and not c.size_hints.program_position then
  672. -- Prevent clients from being unreachable after screen count changes.
  673. awful.placement.no_offscreen(c)
  674. end
  675. end)
  676. -- Add a titlebar if titlebars_enabled is set to true in the rules.
  677. client.connect_signal("request::titlebars", function(c)
  678. -- Custom
  679. if beautiful.titlebar_fun then
  680. beautiful.titlebar_fun(c)
  681. return
  682. end
  683. -- Default
  684. -- buttons for the titlebar
  685. local buttons = mytable.join(
  686. awful.button({ }, 1, function()
  687. c:emit_signal("request::activate", "titlebar", {raise = true})
  688. awful.mouse.client.move(c)
  689. end),
  690. awful.button({ }, 3, function()
  691. c:emit_signal("request::activate", "titlebar", {raise = true})
  692. awful.mouse.client.resize(c)
  693. end)
  694. )
  695. awful.titlebar(c, { size = 16 }) : setup {
  696. { -- Left
  697. awful.titlebar.widget.iconwidget(c),
  698. buttons = buttons,
  699. layout = wibox.layout.fixed.horizontal
  700. },
  701. { -- Middle
  702. { -- Title
  703. align = "center",
  704. widget = awful.titlebar.widget.titlewidget(c)
  705. },
  706. buttons = buttons,
  707. layout = wibox.layout.flex.horizontal
  708. },
  709. { -- Right
  710. awful.titlebar.widget.floatingbutton (c),
  711. awful.titlebar.widget.maximizedbutton(c),
  712. awful.titlebar.widget.stickybutton (c),
  713. awful.titlebar.widget.ontopbutton (c),
  714. awful.titlebar.widget.closebutton (c),
  715. layout = wibox.layout.fixed.horizontal()
  716. },
  717. layout = wibox.layout.align.horizontal
  718. }
  719. end)
  720. -- Enable sloppy focus, so that focus follows mouse.
  721. client.connect_signal("mouse::enter", function(c)
  722. c:emit_signal("request::activate", "mouse_enter", {raise = vi_focus})
  723. end)
  724. client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
  725. client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
  726. -- }}}