commit 32e78a24dbdaf25e2afe470d2ba246df0785d480
parent 4c4bd9e99706d45dcf220f1df2d65e31f63a0e06
Author: Daniel Barlow <dan@telent.net>
Date: Sun, 14 Aug 2022 14:59:39 +0100
fudging to make it work as buildable derivation
a bit too much path shenanigans going on here to be entirely happy
Diffstat:
10 files changed, 486 insertions(+), 478 deletions(-)
diff --git a/crier/crier.fnl b/crier/crier.fnl
@@ -1,273 +0,0 @@
-(local lgi (require :lgi))
-(local dbus (require :dbus_proxy))
-(local Gio lgi.Gio)
-(local GLib lgi.GLib)
-(local GV lgi.GLib.Variant)
-(local GtkLayerShell lgi.GtkLayerShell)
-(local variant dbus.variant)
-(local Gtk lgi.Gtk)
-
-(fn relpath [filename]
- (.. "crier/" filename))
-
-(local dbus-service-attrs
- {
- :bus dbus.Bus.SESSION
- :name "org.freedesktop.Notifications"
- :interface "org.freedesktop.Notifications"
- :path "/org/freedesktop/Notifications"
- })
-
-(local bus (dbus.Proxy:new
- {
- :bus dbus.Bus.SESSION
- :name "org.freedesktop.DBus"
- :interface "org.freedesktop.DBus"
- :path "/org/freedesktop/DBus"
- }))
-
-
-(local DBUS_NAME_FLAG_DO_NOT_QUEUE 4)
-(local DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1)
-(local DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2)
-(local DBUS_REQUEST_NAME_REPLY_EXISTS 3)
-(local DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4)
-
-
-(let [ret (bus:RequestName dbus-service-attrs.name
- DBUS_NAME_FLAG_DO_NOT_QUEUE)]
- (match ret
- DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
- true
-
- DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
- true
-
- DBUS_REQUEST_NAME_REPLY_IN_QUEUE
- (error "unexpected DBUS_REQUEST_NAME_REPLY_IN_QUEUE")
-
- DBUS_REQUEST_NAME_REPLY_EXISTS
- (error "already running")))
-
-(let [css (: (io.open (relpath "styles.css")) :read "*a")
- style_provider (Gtk.CssProvider)]
- (style_provider:load_from_data css)
- (Gtk.StyleContext.add_provider_for_screen
- (lgi.Gdk.Screen.get_default)
- style_provider
- Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
- ))
-
-;; for each open message there is a widget
-;; when a message is closed, we need to find its widget
-;; and remove it from the container
-;; if there are no messages left, hide the windox
-
-(fn make-window []
- (let [window (Gtk.Window {:on_destroy Gtk.main_quit})
- box (Gtk.Box {
- :orientation Gtk.Orientation.VERTICAL
- })]
- (window:add box)
- (when true
- (GtkLayerShell.init_for_window window)
- (GtkLayerShell.set_layer window GtkLayerShell.Layer.TOP)
- (GtkLayerShell.auto_exclusive_zone_enable window)
-
- (GtkLayerShell.set_margin window GtkLayerShell.Edge.TOP 1)
- (GtkLayerShell.set_margin window GtkLayerShell.Edge.BOTTOM 10)
-
- (GtkLayerShell.set_anchor window GtkLayerShell.Edge.TOP 1)
- (GtkLayerShell.set_anchor window GtkLayerShell.Edge.LEFT 1)
- (GtkLayerShell.set_anchor window GtkLayerShell.Edge.RIGHT 1))
- (window:hide)
- {:window window :box box}))
-
-(local window (make-window))
-
-(local notifications {})
-
-(fn update-window []
- (each [id widget (pairs notifications)]
- (if (not (widget.widget:get_parent))
- (window.box:pack_start widget.widget false false 5)))
- (if (next notifications)
- (window.window:show_all)
- (window.window:hide)))
-
-(var notification-id 10)
-(fn next-notification-id []
- (set notification-id (+ notification-id 1))
- notification-id)
-
-(fn delete-notification [id]
- (let [widget (. notifications id)]
- (if widget
- (do
- (tset notifications id nil)
- (window.box:remove widget.widget)
- (update-window)
- true)
- (values nil "no notification with that id"))))
-
-
-(fn update-notification-widget [widget noti]
- (doto widget
- (: :set-summary noti.summary)
- (: :set-body noti.body)
- (: :set-icon noti.app-icon)
- (: :set-buttons noti.actions)))
-
-(fn emit-action [id action]
- (bus.connection:emit_signal
- nil ; destination
- dbus-service-attrs.path
- dbus-service-attrs.interface
- "ActionInvoked"
- (GV "(us)" [id action])))
-
-(fn make-notification-widget [id]
- (let [summary (Gtk.Label { :name "summary" })
- body (Gtk.Label)
- icon (Gtk.Image)
- event-box (Gtk.EventBox {
- :on_button_press_event #(emit-action id "default")
- })
- messages (Gtk.Box { :orientation Gtk.Orientation.VERTICAL})
- icon-and-messages (Gtk.Box {
- :name "notification"
- :orientation Gtk.Orientation.HORIZONTAL
- })
- buttons (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL})
- with-buttons (Gtk.Box { :orientation Gtk.Orientation.VERTICAL})
- ]
- (messages:pack_start summary false false 0)
- (messages:pack_start body true false 0)
- (icon-and-messages:pack_start icon false false 0)
- (icon-and-messages:pack_start messages true true 0)
- (with-buttons:pack_start icon-and-messages false false 0)
- (with-buttons:pack_start buttons false false 0)
- (event-box:add with-buttons)
- {
- :set-summary (fn [self value]
- (set summary.label value))
- :set-body (fn [self value]
- (set body.label value))
- :set-buttons (fn [self actions]
- (each [_ child (ipairs (buttons:get_children))]
- (print child)
- (child:destroy))
- (when actions
- (each [key label (pairs actions)]
- (if (not (= key "default"))
- (buttons:pack_start (Gtk.Button {
- :on_clicked
- #(emit-action id key)
- :label label })
- true false 0)))))
- :set-icon (fn [self value]
- (when value
- (icon:set_from_icon_name
- value
- Gtk.IconSize.DND
- )))
- :widget event-box
- }))
-
-(fn timeout-ms [noti]
- (if (or (not noti.timeout) (= noti.timeout -1))
- 5000
- (> noti.timeout 0)
- noti.timeout
- (= noti.timeout 0)
- nil))
-
-(fn add-notification [noti]
- (let [id (if (= noti.id 0) (next-notification-id) noti.id)
- widget (or (. notifications id) (make-notification-widget id))
- timeout (timeout-ms noti)]
- (when timeout
- (lgi.GLib.timeout_add
- lgi.GLib.PRIORITY_DEFAULT timeout #(do (delete-notification id) nil)))
-
- (update-notification-widget widget noti)
- (tset notifications id widget)
- (update-window)
- id))
-
-(fn parse-actions [list]
- (let [out {}]
- (for [i 1 (# list) 2]
- (tset out (. list i) (. list (+ 1 i))))
- out))
-
-(fn make-notification [sender id icon summary body actions hints timeout]
- {
- :sender sender
- :id id
- :app-icon icon
- :summary summary
- :body body
- :actions (parse-actions actions)
- :hints hints
- :timeout timeout
- })
-
-
-(local interface-info
- (let [xml (: (io.open (relpath "interface.xml") "r") :read "*a")
- node-info (Gio.DBusNodeInfo.new_for_xml xml)]
- (. node-info.interfaces 1)))
-
-(local dbus-methods
- {
- "GetCapabilities" #["actions" "body" "persistence"]
- "GetServerInformation" #(values "crier" "telent" "0.1" "1.2")
- "Notify" #(add-notification (make-notification $...))
- "CloseNotification" (fn [id]
- (let [(won err) (delete-notification id)]
- (if won (values) (error err))))
- })
-
-(fn args-signature [args]
- (var sig "")
- (each [_ v (ipairs args)]
- (set sig (.. sig v.signature)))
- sig)
-
-(fn handle-dbus-method-call [conn sender path interface method params invocation]
- (when (and (= path dbus-service-attrs.path)
- (= interface dbus-service-attrs.interface))
- (let [p (dbus.variant.strip params)
- info (interface-info:lookup_method method)
- sig (args-signature info.out_args)]
- (match (table.pack (pcall (. dbus-methods method) (table.unpack p)))
- [true & vals]
- (invocation:return_value (GV (.. "(" sig ")") vals))
- _
- (invocation:return_value nil)))))
-
-(fn handle-dbus-get [conn sender path interface name]
- (when (and (= path dbus-service-attrs.path)
- (= interface dbus-service-attrs.interface)
- (= name "Visible"))
- (lgi.GLib.Variant "b" true)))
-
-(Gio.DBusConnection.register_object
- bus.connection
- dbus-service-attrs.path
- interface-info
- (lgi.GObject.Closure handle-dbus-method-call)
- (lgi.GObject.Closure handle-dbus-get)
- (lgi.GObject.Closure (fn [a] (print "set"))))
-
-
-(add-notification {
- :app-icon "dialog-information"
- :body "This is an example notifiddcation."
- :id 3
- :sender "notify-send"
- :summary "Hello world!"
- })
-
-(Gtk:main)
diff --git a/crier/init.fnl b/crier/init.fnl
@@ -0,0 +1,273 @@
+(local lgi (require :lgi))
+(local dbus (require :dbus_proxy))
+(local Gio lgi.Gio)
+(local GLib lgi.GLib)
+(local GV lgi.GLib.Variant)
+(local GtkLayerShell lgi.GtkLayerShell)
+(local variant dbus.variant)
+(local Gtk lgi.Gtk)
+
+(fn relpath [filename]
+ (.. (os.getenv "EUFON_PATH") "/crier/" filename))
+
+(local dbus-service-attrs
+ {
+ :bus dbus.Bus.SESSION
+ :name "org.freedesktop.Notifications"
+ :interface "org.freedesktop.Notifications"
+ :path "/org/freedesktop/Notifications"
+ })
+
+(local bus (dbus.Proxy:new
+ {
+ :bus dbus.Bus.SESSION
+ :name "org.freedesktop.DBus"
+ :interface "org.freedesktop.DBus"
+ :path "/org/freedesktop/DBus"
+ }))
+
+
+(local DBUS_NAME_FLAG_DO_NOT_QUEUE 4)
+(local DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER 1)
+(local DBUS_REQUEST_NAME_REPLY_IN_QUEUE 2)
+(local DBUS_REQUEST_NAME_REPLY_EXISTS 3)
+(local DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER 4)
+
+
+(let [ret (bus:RequestName dbus-service-attrs.name
+ DBUS_NAME_FLAG_DO_NOT_QUEUE)]
+ (match ret
+ DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER
+ true
+
+ DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER
+ true
+
+ DBUS_REQUEST_NAME_REPLY_IN_QUEUE
+ (error "unexpected DBUS_REQUEST_NAME_REPLY_IN_QUEUE")
+
+ DBUS_REQUEST_NAME_REPLY_EXISTS
+ (error "already running")))
+
+(let [css (: (io.open (relpath "styles.css")) :read "*a")
+ style_provider (Gtk.CssProvider)]
+ (style_provider:load_from_data css)
+ (Gtk.StyleContext.add_provider_for_screen
+ (lgi.Gdk.Screen.get_default)
+ style_provider
+ Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
+ ))
+
+;; for each open message there is a widget
+;; when a message is closed, we need to find its widget
+;; and remove it from the container
+;; if there are no messages left, hide the windox
+
+(fn make-window []
+ (let [window (Gtk.Window {:on_destroy Gtk.main_quit})
+ box (Gtk.Box {
+ :orientation Gtk.Orientation.VERTICAL
+ })]
+ (window:add box)
+ (when true
+ (GtkLayerShell.init_for_window window)
+ (GtkLayerShell.set_layer window GtkLayerShell.Layer.TOP)
+ (GtkLayerShell.auto_exclusive_zone_enable window)
+
+ (GtkLayerShell.set_margin window GtkLayerShell.Edge.TOP 1)
+ (GtkLayerShell.set_margin window GtkLayerShell.Edge.BOTTOM 10)
+
+ (GtkLayerShell.set_anchor window GtkLayerShell.Edge.TOP 1)
+ (GtkLayerShell.set_anchor window GtkLayerShell.Edge.LEFT 1)
+ (GtkLayerShell.set_anchor window GtkLayerShell.Edge.RIGHT 1))
+ (window:hide)
+ {:window window :box box}))
+
+(local window (make-window))
+
+(local notifications {})
+
+(fn update-window []
+ (each [id widget (pairs notifications)]
+ (if (not (widget.widget:get_parent))
+ (window.box:pack_start widget.widget false false 5)))
+ (if (next notifications)
+ (window.window:show_all)
+ (window.window:hide)))
+
+(var notification-id 10)
+(fn next-notification-id []
+ (set notification-id (+ notification-id 1))
+ notification-id)
+
+(fn delete-notification [id]
+ (let [widget (. notifications id)]
+ (if widget
+ (do
+ (tset notifications id nil)
+ (window.box:remove widget.widget)
+ (update-window)
+ true)
+ (values nil "no notification with that id"))))
+
+
+(fn update-notification-widget [widget noti]
+ (doto widget
+ (: :set-summary noti.summary)
+ (: :set-body noti.body)
+ (: :set-icon noti.app-icon)
+ (: :set-buttons noti.actions)))
+
+(fn emit-action [id action]
+ (bus.connection:emit_signal
+ nil ; destination
+ dbus-service-attrs.path
+ dbus-service-attrs.interface
+ "ActionInvoked"
+ (GV "(us)" [id action])))
+
+(fn make-notification-widget [id]
+ (let [summary (Gtk.Label { :name "summary" })
+ body (Gtk.Label)
+ icon (Gtk.Image)
+ event-box (Gtk.EventBox {
+ :on_button_press_event #(emit-action id "default")
+ })
+ messages (Gtk.Box { :orientation Gtk.Orientation.VERTICAL})
+ icon-and-messages (Gtk.Box {
+ :name "notification"
+ :orientation Gtk.Orientation.HORIZONTAL
+ })
+ buttons (Gtk.Box { :orientation Gtk.Orientation.HORIZONTAL})
+ with-buttons (Gtk.Box { :orientation Gtk.Orientation.VERTICAL})
+ ]
+ (messages:pack_start summary false false 0)
+ (messages:pack_start body true false 0)
+ (icon-and-messages:pack_start icon false false 0)
+ (icon-and-messages:pack_start messages true true 0)
+ (with-buttons:pack_start icon-and-messages false false 0)
+ (with-buttons:pack_start buttons false false 0)
+ (event-box:add with-buttons)
+ {
+ :set-summary (fn [self value]
+ (set summary.label value))
+ :set-body (fn [self value]
+ (set body.label value))
+ :set-buttons (fn [self actions]
+ (each [_ child (ipairs (buttons:get_children))]
+ (print child)
+ (child:destroy))
+ (when actions
+ (each [key label (pairs actions)]
+ (if (not (= key "default"))
+ (buttons:pack_start (Gtk.Button {
+ :on_clicked
+ #(emit-action id key)
+ :label label })
+ true false 0)))))
+ :set-icon (fn [self value]
+ (when value
+ (icon:set_from_icon_name
+ value
+ Gtk.IconSize.DND
+ )))
+ :widget event-box
+ }))
+
+(fn timeout-ms [noti]
+ (if (or (not noti.timeout) (= noti.timeout -1))
+ 5000
+ (> noti.timeout 0)
+ noti.timeout
+ (= noti.timeout 0)
+ nil))
+
+(fn add-notification [noti]
+ (let [id (if (= noti.id 0) (next-notification-id) noti.id)
+ widget (or (. notifications id) (make-notification-widget id))
+ timeout (timeout-ms noti)]
+ (when timeout
+ (lgi.GLib.timeout_add
+ lgi.GLib.PRIORITY_DEFAULT timeout #(do (delete-notification id) nil)))
+
+ (update-notification-widget widget noti)
+ (tset notifications id widget)
+ (update-window)
+ id))
+
+(fn parse-actions [list]
+ (let [out {}]
+ (for [i 1 (# list) 2]
+ (tset out (. list i) (. list (+ 1 i))))
+ out))
+
+(fn make-notification [sender id icon summary body actions hints timeout]
+ {
+ :sender sender
+ :id id
+ :app-icon icon
+ :summary summary
+ :body body
+ :actions (parse-actions actions)
+ :hints hints
+ :timeout timeout
+ })
+
+
+(local interface-info
+ (let [xml (: (io.open (relpath "interface.xml") "r") :read "*a")
+ node-info (Gio.DBusNodeInfo.new_for_xml xml)]
+ (. node-info.interfaces 1)))
+
+(local dbus-methods
+ {
+ "GetCapabilities" #["actions" "body" "persistence"]
+ "GetServerInformation" #(values "crier" "telent" "0.1" "1.2")
+ "Notify" #(add-notification (make-notification $...))
+ "CloseNotification" (fn [id]
+ (let [(won err) (delete-notification id)]
+ (if won (values) (error err))))
+ })
+
+(fn args-signature [args]
+ (var sig "")
+ (each [_ v (ipairs args)]
+ (set sig (.. sig v.signature)))
+ sig)
+
+(fn handle-dbus-method-call [conn sender path interface method params invocation]
+ (when (and (= path dbus-service-attrs.path)
+ (= interface dbus-service-attrs.interface))
+ (let [p (dbus.variant.strip params)
+ info (interface-info:lookup_method method)
+ sig (args-signature info.out_args)]
+ (match (table.pack (pcall (. dbus-methods method) (table.unpack p)))
+ [true & vals]
+ (invocation:return_value (GV (.. "(" sig ")") vals))
+ _
+ (invocation:return_value nil)))))
+
+(fn handle-dbus-get [conn sender path interface name]
+ (when (and (= path dbus-service-attrs.path)
+ (= interface dbus-service-attrs.interface)
+ (= name "Visible"))
+ (lgi.GLib.Variant "b" true)))
+
+(Gio.DBusConnection.register_object
+ bus.connection
+ dbus-service-attrs.path
+ interface-info
+ (lgi.GObject.Closure handle-dbus-method-call)
+ (lgi.GObject.Closure handle-dbus-get)
+ (lgi.GObject.Closure (fn [a] (print "set"))))
+
+
+(add-notification {
+ :app-icon "dialog-information"
+ :body "This is an example notifiddcation."
+ :id 3
+ :sender "notify-send"
+ :summary "Hello world!"
+ })
+
+(Gtk:main)
diff --git a/default.nix b/default.nix
@@ -76,9 +76,12 @@ stdenv.mkDerivation {
substitute bin/eufonctl.sh $out/bin/eufonctl \
--replace SOCAT=socat SOCAT=${socat}/bin/socat
makeWrapper ${kiwmi}/bin/kiwmi $out/bin/eufon \
- --set LUA_PATH ".;$out/?.fnl;$LUA_PATH" \
- --set LUA_CPATH ".;$out/?.so;$LUA_CPATH" \
- --prefix PATH : ${kiwmi}/bin \
+ --set LUA_PATH "$out/?.lua;$LUA_PATH" \
+ --set LUA_CPATH "$LUA_CPATH" \
+ --prefix PATH : ${kiwmi}/bin:${luaWithPackages}/bin \
+ --set EUFON_PATH "$out" \
+ --set GIO_EXTRA_MODULES "${glib-networking}/lib/gio/modules" \
+ --set GI_TYPELIB_PATH "$GI_TYPELIB_PATH" \
--add-flags "-c $out/init.lua"
chmod +x $out/bin/eufon
diff --git a/eufon.fnl b/eufon.fnl
@@ -0,0 +1,200 @@
+;; -*- mode: Fennel;
+
+(local { : view } (require :fennel))
+
+(local texture (require :texture))
+(local matrix (require :matrix))
+(local socket-repl (require :socket-repl))
+
+(local app-state
+ {
+ :in-overview false
+ :focus-view nil
+ :views []
+ })
+
+(let [repl-socket-name
+ (..
+ (: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "")
+ "/kiwmi-repl."
+ (os.getenv "WAYLAND_DISPLAY")
+ ".socket"
+ )]
+ (socket-repl.start repl-socket-name))
+
+(fn resize-wayland-backend [output]
+ (when (string.find (output:name) "^WL-")
+ (output:set_mode 360 720 0)))
+
+(fn kill-window []
+ (print "DIE")
+ true)
+
+(fn launch []
+ (print "WHOOSH")
+ true)
+
+(fn eufon-path [f]
+ (.. (os.getenv "EUFON_PATH") "/" f))
+
+(fn show-overview []
+ (let [facets 64
+ angle (/ (* 2 math.pi) facets)
+ scale 0.6
+ y-offset (+ (* 1 680)
+ (/ (* 360 facets) (* 2 math.pi)))
+ ]
+ (each [i view (ipairs app-state.views)]
+ (doto view
+ (: :set_matrix
+ (-> matrix.identity
+ (matrix.scale scale scale)
+ (matrix.translate (* 2 180) (+ y-offset))
+ (matrix.rotate (/ (* (- i 2
+ ) angle) 1))
+ (matrix.translate (* -2 180) (- y-offset))
+ (matrix.translate 120 150)
+ ))
+ (: :show)))))
+
+
+(fn hide-overview []
+ (each [k view (pairs app-state.views)]
+ (view:set_matrix matrix.identity)
+ (if (= (view:id) (app-state.focus-view:id))
+ (doto view
+ (: :show)
+ (: :focus))
+ (view:hide))))
+
+(fn carousel []
+ (let [was app-state.in-overview]
+ (if was
+ (hide-overview)
+ (show-overview))
+ (: (kiwmi:active_output) :redraw)
+ (tset app-state :in-overview (not was))))
+
+(fn placements [output]
+ (let [(width height) (output:size)
+ bar-height (/ height 15)]
+ {
+
+ :application {
+ :x 0
+ :y 0
+ :w width
+ :h (- height (* bar-height 1.1))
+ }
+ :bar {
+ :x 0
+ :y (- height (* bar-height 1.1))
+ :w width
+ :h (* bar-height 1.1)
+ }
+ :kill {
+ :x (- (* width 0.25) (/ bar-height 2))
+ :y (- height bar-height)
+ :w bar-height
+ :h bar-height
+ :on-press kill-window
+ }
+ :launch {
+ :x (- (* width 0.5) (/ bar-height 2))
+ :y (- height bar-height)
+ :w bar-height
+ :h bar-height
+ :on-press launch
+ }
+ :overview {
+ :x (- (* width 0.75) (/ bar-height 2))
+ :y (- height bar-height)
+ :w bar-height
+ :h bar-height
+ :on-press carousel
+ }
+ }))
+
+(fn choose-view-at [x y]
+ (let [view (kiwmi:view_at x y)]
+ (tset app-state :focus-view view)
+ (tset app-state :in-overview false)
+ (hide-overview)
+ true))
+
+(let [cursor (kiwmi:cursor)]
+ (cursor:on "button_up"
+ (fn [button-id]
+ (when app-state.in-overview
+ (let [geom (placements (kiwmi:active_output))
+ (x y) (cursor:pos)]
+ (if (< y geom.application.h)
+ (choose-view-at x y)
+ false))))))
+
+(kiwmi:on
+ "output"
+ (fn [output]
+ (resize-wayland-backend output)
+ (let [(width height) (output:size)
+ r (output:renderer)
+ kill (texture.from-file r (eufon-path "close-window.png"))
+ launch (texture.from-file r (eufon-path "launcher.png"))
+ overview (texture.from-file r (eufon-path "carousel.png"))]
+ (output:on "render"
+ (fn [{: output : renderer}]
+ (let [buttons (placements output)]
+ (renderer:draw_rect :#77000077
+ buttons.bar.x buttons.bar.y
+ buttons.bar.w buttons.bar.h)
+ (renderer:draw_texture
+ kill
+ matrix.identity
+ buttons.kill.x buttons.kill.y
+ 0.7)
+ (renderer:draw_texture
+ launch
+ matrix.identity
+ buttons.launch.x buttons.launch.y
+ 0.7)
+ (renderer:draw_texture
+ overview
+ matrix.identity
+ buttons.overview.x buttons.overview.y
+ 0.7)))))))
+
+
+(let [cursor (kiwmi:cursor)]
+ (cursor:on "button_down"
+ (fn [button]
+ (let [(x y) (cursor:pos)]
+ (each [name attribs (pairs (placements (kiwmi:active_output)))]
+ (if (and
+ (<= attribs.x x)
+ (< x (+ attribs.x attribs.w))
+ (<= attribs.y y)
+ (< y (+ attribs.y attribs.h)))
+ (if attribs.on-press (attribs.on-press))))))))
+
+(kiwmi:on "view"
+ (fn [view]
+ (let [geom (placements (kiwmi:active_output))]
+ (view:resize geom.application.w geom.application.h)
+ (view:move geom.application.x geom.application.y))
+ (view:focus)
+ (view:show)
+ (tset app-state :focus-view view)
+ (table.insert app-state.views view)
+ (view:on "request_move" #(view:imove))
+ (view:on "request_resize" (fn [ev] (view:iresize ev.edges)))))
+
+(kiwmi:spawn "swaybg -c '#ff00ff'")
+(kiwmi:spawn "lua -l fennelrun modeline")
+;(kiwmi:spawn "lua -l fennelrun saturn")
+(kiwmi:spawn "lua -l fennelrun crier")
+(kiwmi:spawn "lua -l fennelrun just https://brvt.telent.net")
+;(kiwmi:spawn "foot")
+
+;; Local Variables:
+;; inferior-lisp-program: "eufonctl"
+;; End:
diff --git a/fennelrun.lua b/fennelrun.lua
@@ -1,4 +1,6 @@
local fennel = require("fennel")
table.insert(package.loaders or package.searchers, fennel.searcher)
--- print(fennel.view(arg))
-fennel.dofile(arg[0], { correlate = true })
+fennel.path = os.getenv("EUFON_PATH") .. "/?.fnl;" ..
+ os.getenv("EUFON_PATH") .. "/?/init.fnl;"
+
+require(arg[0])
diff --git a/init.lua b/init.lua
@@ -3,4 +3,5 @@ print(os.getenv("LUA_CPATH"))
local fennel = require("fennel")
table.insert(package.loaders or package.searchers, fennel.searcher)
-fennel.dofile("rc.fnl")
+fennel.path = fennel.path .. ";" .. os.getenv("EUFON_PATH") .. "/?.fnl"
+require("eufon")
diff --git a/just/just.fnl b/just/init.fnl
diff --git a/modeline.fnl b/modeline.fnl
@@ -9,7 +9,7 @@
;(local battery (require :blinkenlicht.metric.battery))
(local cpustat (require :blinkenlicht.metric.cpustat))
-(stylesheet "modeline.css")
+(stylesheet (.. (os.getenv "EUFON_PATH") "/modeline.css"))
(fn battery-icon-codepoint [status percent]
(if (= status "Charging") 0xf0e7
diff --git a/rc.fnl b/rc.fnl
@@ -1,198 +0,0 @@
-;; -*- mode: Fennel;
-
-(local { : view } (require :fennel))
-
-(local texture (require :texture))
-(local matrix (require :matrix))
-(local socket-repl (require :socket-repl))
-
-(local app-state
- {
- :in-overview false
- :focus-view nil
- :views []
- })
-
-(let [repl-socket-name
- (..
- (: (os.getenv "XDG_RUNTIME_DIR") :gsub "/$" "")
- "/kiwmi-repl."
- (os.getenv "WAYLAND_DISPLAY")
- ".socket"
- )]
- (socket-repl.start repl-socket-name))
-
-(fn resize-wayland-backend [output]
- (when (string.find (output:name) "^WL-")
- (output:set_mode 360 720 0)))
-
-(fn kill-window []
- (print "DIE")
- true)
-
-(fn launch []
- (print "WHOOSH")
- true)
-
-(fn show-overview []
- (let [facets 64
- angle (/ (* 2 math.pi) facets)
- scale 0.6
- y-offset (+ (* 1 680)
- (/ (* 360 facets) (* 2 math.pi)))
- ]
- (each [i view (ipairs app-state.views)]
- (doto view
- (: :set_matrix
- (-> matrix.identity
- (matrix.scale scale scale)
- (matrix.translate (* 2 180) (+ y-offset))
- (matrix.rotate (/ (* (- i 2
- ) angle) 1))
- (matrix.translate (* -2 180) (- y-offset))
- (matrix.translate 120 150)
- ))
- (: :show)))))
-
-
-(fn hide-overview []
- (each [k view (pairs app-state.views)]
- (view:set_matrix matrix.identity)
- (if (= (view:id) (app-state.focus-view:id))
- (doto view
- (: :show)
- (: :focus))
- (view:hide))))
-
-(fn carousel []
- (let [was app-state.in-overview]
- (if was
- (hide-overview)
- (show-overview))
- (: (kiwmi:active_output) :redraw)
- (tset app-state :in-overview (not was))))
-
-(fn placements [output]
- (let [(width height) (output:size)
- bar-height (/ height 15)]
- {
-
- :application {
- :x 0
- :y 0
- :w width
- :h (- height (* bar-height 1.1))
- }
- :bar {
- :x 0
- :y (- height (* bar-height 1.1))
- :w width
- :h (* bar-height 1.1)
- }
- :kill {
- :x (- (* width 0.25) (/ bar-height 2))
- :y (- height bar-height)
- :w bar-height
- :h bar-height
- :on-press kill-window
- }
- :launch {
- :x (- (* width 0.5) (/ bar-height 2))
- :y (- height bar-height)
- :w bar-height
- :h bar-height
- :on-press launch
- }
- :overview {
- :x (- (* width 0.75) (/ bar-height 2))
- :y (- height bar-height)
- :w bar-height
- :h bar-height
- :on-press carousel
- }
- }))
-
-(fn choose-view-at [x y]
- (let [view (kiwmi:view_at x y)]
- (tset app-state :focus-view view)
- (tset app-state :in-overview false)
- (hide-overview)
- true))
-
-(let [cursor (kiwmi:cursor)]
- (cursor:on "button_up"
- (fn [button-id]
- (when app-state.in-overview
- (let [geom (placements (kiwmi:active_output))
- (x y) (cursor:pos)]
- (if (< y geom.application.h)
- (choose-view-at x y)
- false))))))
-
-(kiwmi:on
- "output"
- (fn [output]
- (resize-wayland-backend output)
- (let [(width height) (output:size)
- r (output:renderer)
- kill (texture.from-file r "close-window.png")
- launch (texture.from-file r "launcher.png")
- overview (texture.from-file r "carousel.png")]
- (output:on "render"
- (fn [{: output : renderer}]
- (let [buttons (placements output)]
- (renderer:draw_rect :#77000077
- buttons.bar.x buttons.bar.y
- buttons.bar.w buttons.bar.h)
- (renderer:draw_texture
- kill
- matrix.identity
- buttons.kill.x buttons.kill.y
- 0.7)
- (renderer:draw_texture
- launch
- matrix.identity
- buttons.launch.x buttons.launch.y
- 0.7)
- (renderer:draw_texture
- overview
- matrix.identity
- buttons.overview.x buttons.overview.y
- 0.7)))))))
-
-
-(let [cursor (kiwmi:cursor)]
- (cursor:on "button_down"
- (fn [button]
- (let [(x y) (cursor:pos)]
- (each [name attribs (pairs (placements (kiwmi:active_output)))]
- (if (and
- (<= attribs.x x)
- (< x (+ attribs.x attribs.w))
- (<= attribs.y y)
- (< y (+ attribs.y attribs.h)))
- (if attribs.on-press (attribs.on-press))))))))
-
-(kiwmi:on "view"
- (fn [view]
- (let [geom (placements (kiwmi:active_output))]
- (view:resize geom.application.w geom.application.h)
- (view:move geom.application.x geom.application.y))
- (view:focus)
- (view:show)
- (tset app-state :focus-view view)
- (table.insert app-state.views view)
- (view:on "request_move" #(view:imove))
- (view:on "request_resize" (fn [ev] (view:iresize ev.edges)))))
-
-
-;(kiwmi:spawn "swaybg -c '#ff00ff'")
-(kiwmi:spawn "lua -l fennelrun modeline.fnl")
-(kiwmi:spawn "lua -l fennelrun saturn/main.fnl")
-(kiwmi:spawn "lua -l fennelrun crier/crier.fnl")
-(kiwmi:spawn "lua -l fennelrun just/just.fnl")
-;(kiwmi:spawn "foot")
-
-;; Local Variables:
-;; inferior-lisp-program: "eufonctl"
-;; End:
diff --git a/saturn/main.fnl b/saturn/init.fnl