eufon/blinkenlicht/init.fnl

226 lines
6.4 KiB
Plaintext
Raw Normal View History

2022-03-23 22:58:00 +00:00
(local {: Gtk
2022-03-23 23:20:53 +00:00
: GtkLayerShell
2022-03-23 22:58:00 +00:00
: Gdk
: GdkPixbuf
2022-04-05 20:23:17 +00:00
: Gio
2022-03-23 22:58:00 +00:00
: GLib
: cairo } (require :lgi))
(local posix (require :posix))
2022-03-23 22:58:00 +00:00
(local {: view} (require :fennel))
(local icon-theme (Gtk.IconTheme.get_default))
(local HEIGHT 48)
2022-04-05 20:23:17 +00:00
(local css-provider
(let [p (Gtk.CssProvider)]
(Gtk.StyleContext.add_provider_for_screen
(Gdk.Screen.get_default)
p
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
p))
(fn load-styles [pathname]
2022-04-05 20:23:17 +00:00
(let [(success err) (css-provider:load_from_path pathname)]
(or success
(print "failed to load stylesheet" err))))
2022-04-05 20:23:17 +00:00
(var file-monitor nil)
(fn watch-stylesheet [pathname]
(let [f (Gio.File.new_for_path pathname)
(monitor err)
(Gio.File.monitor f Gio.FileMonitorFlags.NONE nil)]
(load-styles pathname)
(if (not monitor) (print :watch-stylesheet err))
(set file-monitor monitor)
(doto monitor
(tset
:on_changed
2022-04-07 22:38:55 +00:00
#(load-styles (: $2 :get_path))))))
2022-04-05 20:23:17 +00:00
2022-03-23 22:58:00 +00:00
(fn resolve [f]
(match (type f)
"string" f
"function" (f)))
(fn find-icon-pixbuf [name]
(var found nil)
(each [_ res (pairs [HEIGHT 128 64 48]) :until found]
(let [pixbuf (icon-theme:load_icon
name res
(+ Gtk.IconLookupFlags.FORCE_SVG
Gtk.IconLookupFlags.USE_BUILTIN))]
(when pixbuf
(set found (pixbuf:scale_simple
HEIGHT (* pixbuf.width (/ HEIGHT pixbuf.height))
GdkPixbuf.InterpType.BILINEAR)))))
found)
2022-03-24 12:14:08 +00:00
(local found-icons {})
2022-04-07 22:39:56 +00:00
(macro check-err [form]
`(let [(result# err#) ,form]
(or result#
(error err#))))
2022-03-24 12:14:08 +00:00
(fn load-icon [name]
2022-03-24 22:46:58 +00:00
(let [pixbuf
(if (= (name:sub 1 1) "/")
;; From a direct path
2022-04-07 22:39:56 +00:00
(check-err
(GdkPixbuf.Pixbuf.new_from_file_at_scale name HEIGHT -1 true))
2022-03-24 22:46:58 +00:00
;; From icon theme
(find-icon-pixbuf name))]
(Gtk.Image.new_from_pixbuf pixbuf)))
2022-03-23 22:58:00 +00:00
2022-03-24 12:14:08 +00:00
(fn find-icon [name]
(let [icon (. found-icons name)]
(or icon
2022-03-24 22:46:58 +00:00
(let [(icon err) (load-icon name)]
(if (not icon) (print err))
2022-03-24 12:14:08 +00:00
(tset found-icons name icon)
icon))))
(fn add-css-classes [widget classes]
(let [context (widget:get_style_context)]
(each [_ c (ipairs classes)]
(context:add_class c))))
(fn clear-css-classes [widget]
(let [context (widget:get_style_context)]
(each [_ c (ipairs (context:list_classes))]
(context:remove_class c))))
(fn indicator [{: wait-for
: refresh
2022-03-23 22:58:00 +00:00
: on-click}]
(let [button (Gtk.EventBox { })]
(fn update-indicator []
(let [content (resolve refresh)]
(when content
(match (button:get_child) it (button:remove it))
(match content
{:icon icon} (button:add (find-icon icon))
{:text text} (button:add (Gtk.Label {:label text})))
(clear-css-classes button)
(add-css-classes button ["indicator"])
(match content
{:classes classes} (add-css-classes button classes))
(button:show_all))))
(update-indicator)
2022-03-23 22:58:00 +00:00
{
: button
:update update-indicator
:inputs (or wait-for.input [])
:interval wait-for.interval
2022-03-23 22:58:00 +00:00
}))
2022-03-23 23:20:53 +00:00
(fn make-layer-shell [window layer exclusive? anchors]
(let [s GtkLayerShell]
(s.init_for_window window)
(s.set_layer window (. {
:top GtkLayerShell.Layer.TOP
}
layer))
(if exclusive? (s.auto_exclusive_zone_enable window))
(each [edge margin (pairs anchors)]
(let [edge (. {:top GtkLayerShell.Edge.TOP
:bottom GtkLayerShell.Edge.BOTTOM
:left GtkLayerShell.Edge.LEFT
:right GtkLayerShell.Edge.RIGHT}
edge)]
(GtkLayerShell.set_margin window edge margin)
(GtkLayerShell.set_anchor window edge 1)))))
2022-03-23 22:58:00 +00:00
(local bars [])
(fn bar [{: anchor : orientation : indicators
: gravity
: classes }]
2022-03-23 22:58:00 +00:00
(let [window (Gtk.Window {} )
orientation (match orientation
:vertical Gtk.Orientation.VERTICAL
:horizontal Gtk.Orientation.HORIZONTAL)
box (Gtk.Box { :orientation orientation})]
(doto box
(add-css-classes ["bar"])
(add-css-classes (or classes [])))
(if (= gravity :end)
(box:pack_start (Gtk.EventBox) true true 0))
2022-03-23 22:58:00 +00:00
(table.insert bars { : window : anchor : indicators })
(each [_ i (ipairs indicators)]
(box:pack_start i.button false false 0))
(window:add box)))
(fn gsource-for-file-input [file cb]
(let [fd file.fileno]
(doto (GLib.unix_fd_source_new fd GLib.IOCondition.IN)
(: :set_callback cb))))
2022-03-23 23:35:27 +00:00
(fn ready-to-update? [indicator now update-times]
(if indicator.interval
(> now (or (. update-times indicator) 0))))
2022-03-23 23:35:27 +00:00
(fn hcf [a b]
(let [remainder (% a b)]
(if (= remainder 0)
b
(hcf b remainder))))
(assert (= (hcf 198 360) 18))
(assert (= (hcf 10 15) 5))
(fn minimum-interval [intervals]
(accumulate [min (. intervals 1)
_ interval (ipairs intervals)]
(hcf min interval)))
(assert (= (minimum-interval [ 350 1000 5000 ]) 50))
2022-03-23 22:58:00 +00:00
(fn run []
(var intervals [])
(each [_ bar (ipairs bars)]
(each [_ indicator (ipairs bar.indicators)]
(if indicator.interval
(table.insert intervals indicator.interval))
(each [_ file (ipairs indicator.inputs)]
(GLib.Source.attach
(gsource-for-file-input
file
#(or (indicator:update) true))))))
(let [update-times {}
interval (minimum-interval intervals)]
(when (< interval 100)
(print (.. "required refresh interval is " interval "ms")))
(GLib.timeout_add
2022-03-23 22:58:00 +00:00
0
(minimum-interval intervals)
2022-03-23 22:58:00 +00:00
(fn []
2022-03-23 23:35:27 +00:00
(let [now (/ (GLib.get_monotonic_time) 1000)]
(each [_ bar (ipairs bars)]
(each [_ indicator (ipairs bar.indicators)]
(when (ready-to-update? indicator now update-times)
(indicator:update)
(tset update-times indicator (+ now indicator.interval))))))
true)))
2022-03-23 22:58:00 +00:00
(each [_ b (ipairs bars)]
2022-03-23 23:20:53 +00:00
(make-layer-shell b.window :top true
(collect [_ edge (ipairs b.anchor)]
2022-04-05 20:23:17 +00:00
edge 0))
2022-03-23 22:58:00 +00:00
(b.window:show_all))
(Gtk.main))
{
: bar
: indicator
: run
2022-04-05 20:23:17 +00:00
:stylesheet watch-stylesheet
: file-monitor ;don't let this get GCed
2022-03-23 22:58:00 +00:00
}