(define-module (sigils home services wayland) #:use-module (gnu home services) #:use-module (gnu home services shepherd) #:use-module (gnu packages wm) #:use-module (gnu services configuration) #:use-module (guix packages) #:use-module (guix gexp) #:use-module (guix diagnostics) #:use-module (guix ui) #:use-module (sigils home services desktop) #:use-module (srfi srfi-1) #:use-module (srfi srfi-26) #:use-module (srfi srfi-43) #:use-module (ice-9 match) #:use-module (ice-9 receive) #:export (home-kanshi-service-type home-kanshi-configuration home-swww-service-type home-swww-configuration swww-wallpaper)) ;;; ;;; kanshi. ;;; (define kanshi-config? list?) (define (serialize-kanshi-config config) (define serialize-term (match-lambda ((? symbol? e) `(" " ,(symbol->string e))) ((? number? e) `(" " ,(number->string e))) ((? string? e) `(" " ,(format #f "~s" e))) (e `(" " ,e)))) (define serialize-statement (match-lambda ((cmd . lst) `(,(symbol->string cmd) ,@(append-map serialize-term lst))))) (define serialize-profile (match-lambda ((name ((expressions ...) ...)) `("profile " ,(symbol->string name) " {\n" ,@(append-map (lambda (expr) `(" " ,@(serialize-statement expr) "\n")) expressions) "}\n")))) (append-map serialize-profile config)) (define-configuration home-kanshi-configuration (kanshi (file-like kanshi) "kanshi package to use.") (config (kanshi-config `()) "The kanshi configuration is a list of profiles with output and exec fields. @lisp '((static ((output LVDS-1 disable) (output \"Some Company ASDF 4242\" mode 1600x900 position 0,0))) (portable ((output LVDS-1 enable scale 2)))) @end lisp serializes to @code profile static { output LVDS-1 disable output \"Some Company ASDF 4242\" mode 1600x900 position 0,0 } profile portable { output LVDS-1 enable scale 2 } @end code ")) (define (add-kanshi-packages config) (list (home-kanshi-configuration-kanshi config))) (define (add-kanshi-configuration config) `(("kanshi/config" ,(apply mixed-text-file "kanshi-config" (serialize-kanshi-config (home-kanshi-configuration-config config)))))) (define (home-kanshi-shepherd-service config) (let ((kanshi (home-kanshi-configuration-kanshi config))) (list (shepherd-service (provision '(kanshi)) (requirement '(wayland-display)) (modules '((srfi srfi-1) (srfi srfi-26))) (start #~(lambda _ ;; This is not optimal. (fork+exec-command (list #$(file-append kanshi "/bin/kanshi")) #:log-file (string-append (getenv "XDG_STATE_HOME") "/log" "/kanshi.log") #:environment-variables (cons (string-append "WAYLAND_DISPLAY=" (getenv "WAYLAND_DISPLAY")) (remove (cut string-prefix? "WAYLAND_DISPLAY=" <>) (default-environment-variables)))))) (stop #~(make-kill-destructor)) (documentation "Run Kanshi"))))) (define (home-kanshi-extensions cfg extensions) (home-kanshi-configuration (inherit cfg) (config (append (home-kanshi-configuration-config cfg) (append-map identity (reverse extensions)))))) (define home-kanshi-service-type (service-type (name 'home-kanshi) (extensions (list (service-extension home-profile-service-type add-kanshi-packages) (service-extension home-shepherd-service-type home-kanshi-shepherd-service) (service-extension home-xdg-configuration-files-service-type add-kanshi-configuration))) (compose identity) (extend home-kanshi-extensions) (default-value (home-kanshi-configuration)) (description "\ Install and configure kanshi, output profile manager."))) ;;; ;;; swww. ;;; (define (string-or-false? x) (or (string? x) (not x))) (define-configuration/no-serialization swww-wallpaper (img file-like "Wallpaper to apply.") (output (string-or-false #f) "Output to apply the wallpaper to.")) (define list-of-swww-wallpaper? (list-of swww-wallpaper?)) (define-configuration/no-serialization home-swww-configuration (swww (file-like swww) "swww package to use.") (wallpapers (list-of-swww-wallpaper '()) "List of wallpapers to apply.")) (define (swww-img-gexp config) (receive (with-outputs without-outputs) (partition swww-wallpaper-output (home-swww-configuration-wallpapers config)) (let ((swww (home-swww-configuration-swww config)) (sorted-imgs (map swww-wallpaper-img (append with-outputs without-outputs))) (sorted-outputs (map swww-wallpaper-output (append with-outputs without-outputs)))) #~(begin (use-modules (ice-9 threads)) (par-for-each (lambda (img output) (apply system* (string-append #+swww "/bin/swww") "img" img (if output `("-o" ,output) '()))) '#$sorted-imgs '#$sorted-outputs))))) (define (home-swww-shepherd-service config) (let ((swww (home-swww-configuration-swww config))) (list (shepherd-service (provision '(swww)) (requirement '(wayland-display)) (modules '((srfi srfi-1) (srfi srfi-26))) (start #~(lambda _ ;; This is not optimal. (fork+exec-command (list #$(file-append swww "/bin/swww-daemon")) #:log-file (string-append (getenv "XDG_STATE_HOME") "/log" "/swww.log") #:environment-variables (cons (string-append "WAYLAND_DISPLAY=" (getenv "WAYLAND_DISPLAY")) (remove (cut string-prefix? "WAYLAND_DISPLAY=" <>) (default-environment-variables)))))) (stop #~(make-kill-destructor)) (documentation "Run the Swww daemon."))))) (define home-swww-service-type (service-type (name 'home-swww) (extensions (list (service-extension home-profile-service-type (lambda (config) (list (home-swww-configuration-swww config)))) (service-extension home-shepherd-service-type home-swww-shepherd-service) (service-extension home-activation-service-type swww-img-gexp))) (compose identity) (default-value (home-swww-configuration)) (description "Install and configure swww, animated wallpaper daemon.")))