diff --git a/cfg.fnl b/cfg.fnl index 8e92d3d..d595347 100644 --- a/cfg.fnl +++ b/cfg.fnl @@ -5,7 +5,7 @@ (local naughty (require :naughty)) (local beautiful (require :beautiful)) -(beautiful.init (require :conf.theme)) +(beautiful.init (require :theme)) (require :module.decorate) (require :module.sidebar) @@ -36,7 +36,7 @@ :unfocus (lambda [c] (set c.border_color beautiful.border_normal))} (fun.each (fn [event callback] (client.connect_signal event callback)))) -(awful.spawn.with_shell "~/.config/awesome/autostart") +;; (awful.spawn.with_shell "~/.config/awesome/autostart") ;; Empty return {} diff --git a/conf/tags.fnl b/conf/tags.fnl index 80513af..6686315 100644 --- a/conf/tags.fnl +++ b/conf/tags.fnl @@ -3,6 +3,7 @@ ;;; Code: (local awful (require :awful)) +(local beautiful (require :beautiful)) ;;; ;; Configuration @@ -12,10 +13,21 @@ (set awful.layout.layouts layouts) -(awful.screen.connect_for_each_screen - (lambda [s] - (awful.tag ["1", "2", "3", "4", "5", "6", "7", "8", "9"] - s (. layouts 1)))) +;; TODO Rasterize? +(local tags [:firefox.png :code.png :code.svg]) + +(let [icon-path (.. (os.getenv "HOME") "/.config/awesome/theme/icons/tag/")] + (awful.screen.connect_for_each_screen + (lambda [s] + (each [n tag (ipairs tags)] + (awful.tag.add + n {:icon (.. icon-path tag) + :icon_only true + :layout (. layouts 1) + :gap_single_client false + :gap beautiful.useless_gap + :screen s + :selected (= n 1)}))))) {} ;;; conf/tags.fnl ends here diff --git a/lib/std.fnl b/lib/std.fnl index 97bf29c..18650aa 100644 --- a/lib/std.fnl +++ b/lib/std.fnl @@ -13,5 +13,12 @@ (fn std.zero? [n] (= 0 n)) +(fn std.fn? [f] + (= (type f) :function)) + +(fn std.s-empty? [s] + (or (= nil s) + (= "" s))) + std ;;; std.fnl ends here diff --git a/module/sidebar.fnl b/module/sidebar.fnl index 896e6ba..4c1ad66 100644 --- a/module/sidebar.fnl +++ b/module/sidebar.fnl @@ -8,46 +8,49 @@ (local tag-list (require :widget.tag-list)) (local task-list (require :widget.task-list)) - -(local sb-clock (wibox.widget.textclock "%H\n%M")) -(local sb-systray (doto (wibox.widget.systray) - (: :set_base_size 24))) -(local fill-width (doto (wibox.layout.fixed.horizontal) - (: :fill_space true) - (: :set_spacing 10))) - -(local bounding (wibox.container.margin - (wibox.container.place - (wibox.container.margin - nil - 10 10 10 10 beautiful.sidebar_subbox)) - 1 1 1 1 beautiful.sidebar_bg)) +(local textclock (require :widget.textclock)) ;;; ;; Functions -(fn draw-sidebar [s] - (set s.sb-tag (tag-list s)) - (set s.sb-tasks (task-list s)) +(fn border [t margin] + (let [side (or margin 2) + end (+ side 1)] + {1 t + :bottom end + :left side + :right side + :top end + :widget wibox.container.margin} )) +(local sb-clock (textclock "%H\n%M")) +(local sb-systray (doto (wibox.widget.systray) + (: :set_base_size 24))) + +(fn draw-sidebar [s] (set s.sb (awful.wibar {:position beautiful.sidebar_position :width beautiful.sidebar_width :screen s})) (: s.sb :setup {:layout wibox.layout.align.vertical - 1 {:layout wibox.layout.fixed.vertical - 1 {1 s.sb-tag - :halign "center" - :layout (wibox.container.margin nil 10 10 10 10)} - 2 s.sb-tasks} + 1 {1 (border (tag-list s)) + ;; 2 (task-list s) + :layout wibox.layout.fixed.vertical} 2 {:layout wibox.layout.fixed.vertical} - 3 {:layout wibox.layout.fixed.vertical - 1 sb-systray - 2 {1 sb-clock - :valign "center" - :halign "center" - :layout bounding}}})) + 3 {1 sb-systray + 2 {1 (border + {1 {1 {1 sb-clock + :valign "center" + :halign "center" + :widget wibox.container.place} + :top 2 + :bottom 2 + :widget wibox.container.margin} + :widget wibox.container.background + :bg beautiful.sidebar_bg_info}) + :layout wibox.layout.fixed.vertical} + :layout wibox.layout.fixed.vertical}})) ;;; ;; Configuration diff --git a/theme/icons/tag-list/occupied-border.png b/theme/icons/tag-list/occupied-border.png new file mode 100644 index 0000000..8960968 Binary files /dev/null and b/theme/icons/tag-list/occupied-border.png differ diff --git a/theme/icons/tag-list/occupied.png b/theme/icons/tag-list/occupied.png new file mode 100644 index 0000000..7ed9710 Binary files /dev/null and b/theme/icons/tag-list/occupied.png differ diff --git a/theme/icons/tag-list/panel.png b/theme/icons/tag-list/panel.png new file mode 100644 index 0000000..40d09df Binary files /dev/null and b/theme/icons/tag-list/panel.png differ diff --git a/theme/icons/tag-list/selected.png b/theme/icons/tag-list/selected.png new file mode 100644 index 0000000..3204030 Binary files /dev/null and b/theme/icons/tag-list/selected.png differ diff --git a/theme/icons/tag-list/unselected.png b/theme/icons/tag-list/unselected.png new file mode 100644 index 0000000..9959194 Binary files /dev/null and b/theme/icons/tag-list/unselected.png differ diff --git a/theme/icons/tag-list/urgent.png b/theme/icons/tag-list/urgent.png new file mode 100644 index 0000000..2c2b87e Binary files /dev/null and b/theme/icons/tag-list/urgent.png differ diff --git a/theme/icons/tag/code.png b/theme/icons/tag/code.png new file mode 100644 index 0000000..9d7728c Binary files /dev/null and b/theme/icons/tag/code.png differ diff --git a/theme/icons/tag/code.svg b/theme/icons/tag/code.svg new file mode 100644 index 0000000..bf03e30 --- /dev/null +++ b/theme/icons/tag/code.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/theme/icons/tag/firefox.png b/theme/icons/tag/firefox.png new file mode 100644 index 0000000..0d191a8 Binary files /dev/null and b/theme/icons/tag/firefox.png differ diff --git a/theme/icons/tag/firefox.svg b/theme/icons/tag/firefox.svg new file mode 100644 index 0000000..3bc709a --- /dev/null +++ b/theme/icons/tag/firefox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/theme/init.fnl b/theme/init.fnl index 75f73b4..b6e6616 100644 --- a/theme/init.fnl +++ b/theme/init.fnl @@ -1,35 +1,42 @@ ;; Have to use underscores for `beautiful' compat. ;; Non-beautiful variables are commented with an asterisk. -{ - :font "Sarasa Mono J" - :variable_font "Sarasa UI J" +(let [theme-dir (.. (os.getenv "HOME") "/.config/awesome/theme") + icon-dir (.. theme-dir "/icons/")] + { + :font "Sarasa Mono J" + :variable_font "Sarasa UI J" + :textclock_font "Sarasa UI J" - :sidebar_position :left ;; * - :sidebar_width 36 ;; * - :sidebar_bg "#1a1e24" ;; * - :sidebar_subbox "#252b33" ;; * + :sidebar_position :left ;; * + :sidebar_width 36 ;; * + :sidebar_bg_info "#252b33" ;; * - :bg_focus "#252b33" - :bg_normal "#1a1e24" - :fg_focus "#cfcfcf" - :fg_normal "#cfcfcf" + :bg_focus "#252b33" + :bg_normal "#1a1e24" + :fg_focus "#cfcfcf" + :fg_normal "#cfcfcf" - :useless_gap 0 - :border_width 0 - :border_focus "#5bb3b4" - :border_normal "#1a1e24" - :use_titlebars_for_borders nil ;; * - :titlebar_border_width 1 ;; * + :useless_gap 0 + :border_width 0 + :border_focus "#5bb3b4" + :border_normal "#1a1e24" + :use_titlebars_for_borders nil ;; * + :titlebar_border_width 1 ;; * - :titlebar_position :left ;; * - :titlebar_size 15 ;; * - :titlebar_bg_focus "#926b3e" - :titlebar_bg_normal "#252b33" - :titlebar_fg_focus "#1a1e24" - :titlebar_fg_normal "#cfcfcf" + :titlebar_position :left ;; * + :titlebar_size 15 ;; * + :titlebar_bg_focus "#926b3e" + :titlebar_bg_normal "#252b33" + :titlebar_fg_focus "#1a1e24" + :titlebar_fg_normal "#cfcfcf" - :icon_theme "Vertex Maia" - :notification_icon_size 48 - :notification_border_width 0 - :notification_bg "#252b33" - } + :icon_theme "Vertex Maia" + :notification_icon_size 48 + :notification_border_width 0 + :notification_bg "#252b33" + + :taglist_bg_empty (.. "png:" icon-dir "tag-list/unselected.png") + :taglist_bg_focus (.. "png:" icon-dir "tag-list/selected.png") + :taglist_bg_occupied (.. "png:" icon-dir "tag-list/occupied.png") + :taglist_bg_urgent (.. "png:" icon-dir "tag-list/urgent.png") + }) diff --git a/widget/clickable-container.fnl b/widget/clickable-container.fnl new file mode 100644 index 0000000..b3c85d2 --- /dev/null +++ b/widget/clickable-container.fnl @@ -0,0 +1,52 @@ +;;; widget/clickable-container.fnl --- Clickable container + +;;; Commentary: +;; From https://github.com/PapyElGringo/material-awesome/blob/57116136a904560e8626b673370d2130b40dc62a/widgets/clickable-container.lua + +;;; Code: + +(local wibox (require :wibox)) +(local naughty (require :naughty)) +(local awful (require :awful)) + +;;; +;; Functions + +(fn build [widget] + (let [container (wibox.container.background widget)] + (var old-cursor {}) + (var old-wibox {}) + + (: container :connect_signal + :mouse::enter + (lambda [] + (let [cw _G.mouse.current_wibox] + (tset container :bg "#ffffff11") + ;; Hm, no idea how to get the wibox from this signal's arguments... + (when cw + (set old-cursor cw.cursor) + (set old-wibox cw) + (tset cw :cursor :hand1))))) + + (: container :connect_signal + :mouse::leave + (lambda [] + (tset container :bg "#ffffff00") + (when old-wibox + (tset old-wibox :cursor old-cursor) + (set old-wibox nil)))) + + (: container :connect_signal + :button::press + (lambda [] + (tset container :bg "#ffffff22"))) + + (: container :connect_signal + :button::release + (lambda [] + (tset container :bg "#ffffff11"))) + + container)) + +build +;;; widget/clickable-container.fnl ends here diff --git a/widget/list_update.lua b/widget/list_update.lua new file mode 100644 index 0000000..03f1c3d --- /dev/null +++ b/widget/list_update.lua @@ -0,0 +1,80 @@ +local common = require("awful.widget.common") +local dpi = require("beautiful").xresources.apply_dpi +local wibox = require("wibox") +local clickable_container = require("widget.clickable-container") + +function list_update(w, buttons, label, data, objects) + -- update the widgets, creating them if needed + w:reset() + for i, o in ipairs(objects) do + local cache = data[o] + local ib, tb, bgb, tbm, ibm, l + if cache then + ib = cache.ib + tb = cache.tb + bgb = cache.bgb + tbm = cache.tbm + ibm = cache.ibm + else + ib = wibox.widget.imagebox() + tb = wibox.widget.textbox() + bgb = wibox.container.background() + tbm = wibox.container.margin(tb, dpi(4), dpi(4)) + ibm = wibox.container.margin(ib, dpi(10), dpi(8), dpi(8), dpi(8)) + -- ibm = wibox.container.margin(ib, dpi(4)) + l = wibox.layout.fixed.horizontal() + bg_clickable = clickable_container() + + -- All of this is added in a fixed widget + l:fill_space(true) + l:add(ibm) + -- l:add(tbm) + bg_clickable:set_widget(l) + + -- And all of this gets a background + -- bgb:set_widget(l) + bgb:set_widget(bg_clickable) + + bgb:buttons(common.create_buttons(buttons, o)) + + data[o] = { + ib = ib, + tb = tb, + bgb = bgb, + tbm = tbm, + ibm = ibm, + } + end + + local text, bg, bg_image, icon, args = label(o, tb) + args = args or {} + + -- The text might be invalid, so use pcall. + if text == nil or text == "" then + tbm:set_margins(0) + else + if not tb:set_markup_silently(text) then + tb:set_markup("<Invalid text>") + end + end + bgb:set_bg(bg) + if type(bg_image) == "function" then + -- TODO: Why does this pass nil as an argument? + bg_image = bg_image(tb,o,nil,objects,i) + end + bgb:set_bgimage(bg_image) + if icon then + ib:set_image(icon) + else + ibm:set_margins(0) + end + + bgb.shape = args.shape + bgb.shape_border_width = args.shape_border_width + bgb.shape_border_color = args.shape_border_color + + w:add(bgb) + end +end + +return list_update diff --git a/widget/tag-list.fnl b/widget/tag-list.fnl index 29f1f4a..c0b73e5 100644 --- a/widget/tag-list.fnl +++ b/widget/tag-list.fnl @@ -5,17 +5,101 @@ (local awful (require :awful)) (local beautiful (require :beautiful)) (local wibox (require :wibox)) +(local common (require :awful.widget.common)) +(local dpi (. (require :beautiful) :xresources :apply_dpi)) + +(local std (require :lib.std)) ;;; ;; Functions +(fn update-tag-list [w buttons label data objects] + (: w :reset) + (each [i o (ipairs objects)] + (let [cache (. data o)] + (var ib nil) + (var tb nil) + (var bgb nil) + (var tbm nil) + (var ibm nil) + (var l nil) + (if cache + (do + (set ib cache.ib) + (set tb cache.tb) + (set bgb cache.bgb) + (set tbm cache.tbm) + (set ibm cache.ibm)) + (do + (set ib (wibox.widget.imagebox)) + (set tb (wibox.widget.textbox)) + (set bgb (wibox.container.background)) + (set tbm (wibox.container.margin tb (dpi 4) (dpi 4))) + ;; (set ibm (wibox.container.margin ib (dpi 12) (dpi 12) (dpi 12) (dpi 12))) + (set ibm (wibox.container.margin ib (dpi 4))) + (set l (wibox.layout.fixed.horizontal)) + + ;; All of this is added in a fixed widget + (doto l + (: :fill_space true) + (: :add ibm) + (: :add tbm)) + + ;; And all of this gets a background + (: bgb :set_widget l) + + (: bgb :buttons (common.create_buttons buttons o)) + + (tset data o {:ib ib :tb tb :bgb bgb :tbm tbm :ibm ibm}))) + + (let [[text bg bg-image icon args] (label o tb)] + ;; The text might be invalid, so use pcall. + (if (std.s-empty? text) + (: tbm :set_margins 0) + (when (not (: tb :set_markup_silently text)) + (: tb :set_markup "<Invalid text>"))) + (: bgb :set_bg bg) + + (: bgb :set_bgimage (if (std.fn? bg-image) + ;; TODO: Why does this pass nil as an argument? + (bg-image tb o nil objects i) + bg-image)) + + (if icon + (: ib :set_image icon) + (: ibm :set_margins 0)) + + (let [args (or args {})] + (doto bgb + (tset :shape args.shape) + (tset :shape_border_width args.shape_border_width) + (tset :shape_border_color args.shape_border_color))) + + (: w :add bgb))))) + +(fn container [] + (let [l (wibox.layout.fixed.vertical)] + ;; Wishlist: let* + (local innerm (wibox.container.margin nil 10 10)) + (local bg (wibox.container.background innerm "#faa")) + (local outerm (wibox.container.margin bg 4 4)) + + (: l :fill_space true) + (: l :add outerm) + + l)) + (fn tag-list [s] (awful.widget.taglist s - awful.widget.taglist.filter.selected + awful.widget.taglist.filter.all {} - {:font (.. beautiful.font " Bold 10")} - nil + {:font (.. beautiful.font " Bold 10") + :spacing 2} + ;; update-tag-list + (require :widget.list_update) + ;; awful.widget.common.list_update + ;; (container) (wibox.layout.fixed.vertical) )) diff --git a/widget/textclock.fnl b/widget/textclock.fnl new file mode 100644 index 0000000..95f57ee --- /dev/null +++ b/widget/textclock.fnl @@ -0,0 +1,43 @@ +;;; widget/textclock.fnl --- Configurable text clock widget + +;;; Commentary: +;; More modular than the standard library + +;;; Code: + +(local beautiful (require :beautiful)) +(local gears (require :gears)) +(local glib (. (require :lgi) :GLib)) +(local wibox (require :wibox)) +(local DateTime glib.DateTime) +(local TimeZone glib.TimeZone) + +;;; +;; Functions + +(fn calc-timeout [real-timeout] + (% (- real-timeout (os.time)) real-timeout)) + +(fn textclock [format timeout timezone font] + (let [format (or format " %a %b %d, %H:%M ") + timeout (or timeout 60) + timezone (or (and timezone (TimeZone.new timezone)) + (TimeZone.new_local)) + font (or font beautiful.textclock_font) + w (wibox.widget.textbox)] + (var t nil) + + (tset w :font font) + + (fn w._private.textclock_update_cb [] + (: w :set_markup (: (DateTime.new_now timezone) :format format)) + (tset t :timeout (calc-timeout timeout)) + (: t :again) + true) + + (set t (gears.timer.weak_start_new timeout w._private.textclock_update_cb)) + (: t :emit_signal :timeout) + w)) + +textclock +;;; widget/textclock.fnl ends here