|
(local fun (require "fun")) |
|
(local gears (require "gears")) |
|
(local awful (require "awful")) |
|
(require "awful.autofocus") |
|
(local naughty (require "naughty")) |
|
|
|
(macros |
|
{:with-selected-tag (fn [name body1 ...] |
|
`(let [,name (. mouse.screen :selected_tag)] |
|
(when ,name |
|
,body1 |
|
,...)))}) |
|
|
|
(local focus-colors |
|
; from https://colorhunt.co/palette/153787 |
|
; ["#eb7070" "#fec771" "#e6e56c" "#64e291" ] |
|
; from https://colorhunt.co/palette/6998 |
|
; ["#f06868" "#fab57a" "#edf798" "#80d6ff" ] |
|
; from https://colorhunt.co/palette/68755 |
|
; ["#fffe9f" "#ffd480" "#fca180" "#f56262" ] |
|
; from https://colorhunt.co/palette/136945 |
|
["#cd4545" "#f16821" "#f3a333" "#fffe9a"] |
|
) |
|
|
|
(local background-color "#110022") |
|
(local unfocus-color background-color) |
|
(local focus-border-width 2) |
|
|
|
; Tools |
|
|
|
(fn notify |
|
[text] |
|
(naughty.notify {:text text})) |
|
|
|
(fn debug |
|
[x] |
|
(notify (gears.debug.dump_return x))) |
|
|
|
(fn cset |
|
[k v] |
|
(fn [c] |
|
(tset c k v))) |
|
|
|
(fn cinv |
|
[k] |
|
(fn [c] |
|
(let [v (. c k)] |
|
(tset c k (not v))))) |
|
|
|
(local modifiers {:mod "Mod4" |
|
:shift "Shift" |
|
:ctrl "Control"}) |
|
|
|
(fn map-mods |
|
[mods] |
|
(->> mods |
|
(fun.map (partial . modifiers)) |
|
(fun.totable))) |
|
|
|
(fn key |
|
[mods key-code fun] |
|
(awful.key (map-mods mods) key-code fun)) |
|
|
|
(fn btn |
|
[mods btn-code fun] |
|
(awful.button (map-mods mods) btn-code fun)) |
|
|
|
(fn invert-screen |
|
[invert?] |
|
(os.execute "xcalib -c -a") ; clear |
|
(when invert? |
|
(os.execute "xcalib -i -a"))) |
|
|
|
; Tag managment |
|
|
|
; each client gets an equal share over the width of workarea |
|
(local layout-columns |
|
{:name |
|
"columns" |
|
:arrange |
|
(fn [p] |
|
(let [t (or p.tag (. screen p.screen :selected_tag)) |
|
wa p.workarea |
|
cs p.clients |
|
nc (length cs)] |
|
(when (< 0 nc) |
|
(let [width (math.floor (/ wa.width nc))] |
|
(fun.each (fn [x c] |
|
(tset p :geometries c {:x (+ wa.x x) |
|
:y wa.y |
|
:width width |
|
:height wa.height})) |
|
(fun.zip (fun.range 0 wa.width width) cs))))))}) |
|
|
|
(local layouts [ |
|
layout-columns |
|
awful.layout.suit.fair |
|
awful.layout.suit.tile |
|
awful.layout.suit.max.fullscreen]) |
|
|
|
(local tags {}) |
|
|
|
(var current-tag-pos [0 0]) |
|
|
|
(fn set-tag-pos |
|
[tag pos] |
|
(let [[x y] pos] |
|
(doto tag |
|
(tset :x-pos x) |
|
(tset :y-pos y)))) |
|
|
|
(fn get-tag-pos |
|
[tag] |
|
[(. tag :x-pos) (. tag :y-pos)]) |
|
|
|
(fn translate-pos |
|
[pos off] |
|
(let [[x y] pos |
|
[off-x off-y] off] |
|
[(+ x off-x) (+ y off-y)])) |
|
|
|
(fn tag-name |
|
[pos] |
|
(let [[x y] pos ] |
|
(.. "(" x " " y ")"))) |
|
|
|
(fn get-or-create-tag |
|
[pos] |
|
(let [tn (tag-name pos)] |
|
(when (not (. tags tn)) |
|
(let [[tag] (awful.tag [tn] mouse.screen (. layouts 1))] |
|
(tset tags tn tag) |
|
(set-tag-pos tag pos))) |
|
(. tags tn))) |
|
|
|
(fn current-tag |
|
[] |
|
(get-or-create-tag current-tag-pos)) |
|
|
|
(fn view-current-tag |
|
[] |
|
(: (current-tag) :view_only)) |
|
|
|
(local view-all-tag-name "view-all") |
|
|
|
(local view-all-tag |
|
(. (awful.tag [view-all-tag-name] mouse.screen awful.layout.suit.fair) 1)) |
|
|
|
(fn view-all-tags |
|
[] |
|
(: view-all-tag :view_only)) |
|
|
|
(fn select-tag-by-focused-client |
|
[c] |
|
(->> (c:tags) |
|
(fun.filter (partial not= view-all-tag)) |
|
(fun.each #(set current-tag-pos (get-tag-pos $1)))) |
|
(view-current-tag)) |
|
|
|
(fn select-current-tag-by-offset |
|
[off] |
|
(with-selected-tag tag |
|
(set current-tag-pos (get-tag-pos tag))) |
|
(set current-tag-pos (translate-pos current-tag-pos off)) |
|
(view-current-tag)) |
|
|
|
(fn move-client-relative |
|
[off c] |
|
(c:tags [(get-or-create-tag (translate-pos current-tag-pos off)) view-all-tag])) |
|
|
|
(fn move-client-relative-and-select |
|
[off c] |
|
(move-client-relative off c) |
|
(select-current-tag-by-offset off)) |
|
|
|
(fn move-all-clients-relative-and-select |
|
[off] |
|
(fun.each (partial move-client-relative off) |
|
(awful.client.visible)) |
|
(select-current-tag-by-offset off)) |
|
|
|
(fn focus-client-by-offset |
|
[off] |
|
(awful.client.focus.byidx off) |
|
(when client.focus |
|
(client.focus:raise))) |
|
|
|
(fn is-inverted? |
|
[t] |
|
(if (. t :inverted?) true false)) |
|
|
|
(fn set-inverted |
|
[t inverted?] |
|
(tset t :inverted? inverted?) |
|
(invert-screen inverted?)) |
|
|
|
(fn toggle-invert-screen |
|
[] |
|
(with-selected-tag t |
|
(let [inverted? (not (is-inverted? t))] |
|
(set-inverted t inverted?)))) |
|
|
|
(fn arrange-tag |
|
[screen] |
|
; focus from history |
|
(when (not client.focus) |
|
(let [c (awful.client.focus.history.get screen 0)] |
|
(when c |
|
(tset client :focus c)))) |
|
; set a border width, if there is more than one client on the tag |
|
(let [cs (awful.client.visible screen) |
|
bw (if (> (length cs) 1) focus-border-width 0)] |
|
(fun.each |
|
(fn [c focus-color] |
|
(doto c |
|
(tset :border_width bw) |
|
(tset :focus_color focus-color))) |
|
(fun.zip cs (fun.cycle focus-colors)))) |
|
; set focus color for current client (focus event is before arrange and the colors are not there yet) |
|
(let [c (. client :focus)] |
|
(when c |
|
(tset c :border_color (. c :focus_color)))) |
|
; set inverted screen state from tag |
|
(with-selected-tag t |
|
(invert-screen (is-inverted? t)))) |
|
|
|
(fn unminimize-tag |
|
[tag] |
|
(fun.each (fn [client] |
|
(tset client :minimized false) |
|
(client:redraw)) |
|
(tag:clients))) |
|
|
|
;;; Main Config |
|
|
|
(local global-keys |
|
(gears.table.join |
|
(key [:mod :shift :ctrl] "Escape" awesome.restart) |
|
(key [:mod :shift] "a" view-all-tags) |
|
(key [:mod :shift] "i" toggle-invert-screen) |
|
(key [:mod] "h" #(select-current-tag-by-offset [-1 0])) |
|
(key [:mod] "l" #(select-current-tag-by-offset [ 1 0])) |
|
(key [:mod] "k" #(select-current-tag-by-offset [ 0 -1])) |
|
(key [:mod] "j" #(select-current-tag-by-offset [ 0 1])) |
|
(key [:mod :ctrl] "h" #(move-all-clients-relative-and-select [-1 0])) |
|
(key [:mod :ctrl] "l" #(move-all-clients-relative-and-select [ 1 0])) |
|
(key [:mod :ctrl] "k" #(move-all-clients-relative-and-select [ 0 -1])) |
|
(key [:mod :ctrl] "j" #(move-all-clients-relative-and-select [ 0 1])) |
|
(key [:mod] "space" #(awful.layout.inc layouts 1)) |
|
(key [:mod :shift] "space" #(awful.layout.inc layouts -1)) |
|
(key [:mod :ctrl] "space" awful.client.floating.toggle) |
|
(key [:mod] "Tab" #(focus-client-by-offset 1)) |
|
(key [:mod :shift] "Tab" #(focus-client-by-offset -1)) |
|
(key [:mod :ctrl] "Tab" #(awful.client.swap.byidx 1)) |
|
(key [:mod :shift :ctrl] "Tab" #(awful.client.swap.byidx -1)) |
|
(key [:mod :shift] "BackSpace" #(unminimize-tag (awful.tag.selected))) |
|
)) |
|
|
|
(local client-keys |
|
(gears.table.join |
|
(key [:mod] "Escape" (fn [c] (c:kill))) |
|
(key [:mod] "a" select-tag-by-focused-client) |
|
(key [:mod :shift] "f" (cinv :focusable)) |
|
(key [:mod :shift] "s" (cinv :sticky)) |
|
(key [:mod :shift] "x" (cinv :maximized_horizontal)) |
|
(key [:mod :shift] "y" (cinv :maximized_vertical)) |
|
(key [:mod :shift] "m" (cinv :maximized)) |
|
(key [:mod :shift] "h" (partial move-client-relative-and-select [-1 0])) |
|
(key [:mod :shift] "l" (partial move-client-relative-and-select [ 1 0])) |
|
(key [:mod :shift] "k" (partial move-client-relative-and-select [ 0 -1])) |
|
(key [:mod :shift] "j" (partial move-client-relative-and-select [ 0 1])) |
|
)) |
|
|
|
(local client-buttons |
|
(gears.table.join |
|
(btn [:mod] 1 awful.mouse.client.move) |
|
(btn [:mod] 3 awful.mouse.client.resize) |
|
)) |
|
|
|
(local rules [ |
|
{:rule {} |
|
:properties {:focus true |
|
:keys client-keys |
|
:buttons client-buttons}} |
|
]) |
|
|
|
(local client-event-handlers |
|
{"manage" (fn [c] |
|
(c:tags [(current-tag) view-all-tag])) |
|
"mouse::enter" (fn [c] |
|
; TODO if awful.layout.get(c.screen) ~= awful.layout.suit.magnifier and awful.client.focus.filter(c) then |
|
(if (awful.client.focus.filter c) |
|
(tset client :focus c))) |
|
"focus" (fn [c] |
|
(let [focus-color (. c :focus_color)] |
|
; focus (e.g. from rules) is applied before arrange and the client might not yet have a color |
|
(when focus-color |
|
(tset c :border_color focus-color)))) |
|
"unfocus" (cset :border_color unfocus-color)}) |
|
|
|
; Wire everything up |
|
|
|
(fun.each client.connect_signal client-event-handlers) |
|
|
|
(awful.screen.connect_for_each_screen |
|
(fn [s] |
|
(s:connect_signal "arrange" arrange-tag))) |
|
|
|
(root.keys global-keys) |
|
|
|
(tset awful.rules :rules rules) |
|
|
|
(view-current-tag) |
|
|
|
(gears.wallpaper.set background-color) |
|
|
|
{} |