(define-module (ruther home services gtk) #:use-module (gnu services configuration) #:use-module (gnu services) #:use-module (guix packages) #:use-module (guix gexp) #:use-module (guix build-system trivial) #:use-module (gnu home services) #:use-module (ruther home services dconf) #:export (home-gtk-configuration gtk-theme-configuration home-gtk-service-type)) (define (maybe-string? str) (or (nil? str) (string? str))) (define (maybe-package? pkg) (or (nil? pkg) (package? pkg))) (define-configuration/no-serialization gtk-theme-configuration (package (maybe-package #f) "The package to add to profile, including theme {name}") (name (maybe-string #f) "Name of the theme") (size (integer 16) "Size of the pointer. Applies only for cursor-theme")) (define-configuration/no-serialization home-gtk-configuration (gtk-theme (gtk-theme-configuration (gtk-theme-configuration)) "The theme") (icon-theme (gtk-theme-configuration (gtk-theme-configuration)) "The icon theme") (cursor-theme (gtk-theme-configuration (gtk-theme-configuration)) "The cursor theme") (font-name (maybe-string #f) "Name of the font to use")) (define* (serialize-field name value #:key (gtk2? #f)) (if gtk2? (format #f "~a = \"~a\"~%" name value) (format #f "~a = ~a~%" name value))) (define* (serialize-cons field #:key (gtk2? #f)) (serialize-field (car field) (cdr field) #:gtk2? gtk2?)) (define (gtk4-css-import-file theme-package theme-name) `("gtk.css" "@import url(\"file://" ,theme-package "/share/themes/" ,theme-name "/gtk-4.0/gtk.css\");")) (define (map-gtk-configuration-to-gtk-config config) (filter (lambda (x) (not (nil? (cdr x)))) `((gtk-theme-name . ,(gtk-theme-configuration-name (home-gtk-configuration-gtk-theme config))) (gtk-icon-theme-name . ,(gtk-theme-configuration-name (home-gtk-configuration-icon-theme config))) (gtk-cursor-theme-name . ,(gtk-theme-configuration-name (home-gtk-configuration-cursor-theme config))) (gtk-cursor-theme-size . ,(gtk-theme-configuration-size (home-gtk-configuration-cursor-theme config))) (gtk-font-name . ,(home-gtk-configuration-font-name config))))) (define* (serialize-gtk-config config #:key (gtk2? #f)) (let* ((mapped (map-gtk-configuration-to-gtk-config config)) (serialized (map (lambda (x) (serialize-cons x #:gtk2? gtk2?)) mapped))) (if gtk2? serialized (cons* "[Settings]\n" serialized)))) (define (add-gtk-theme-packages config) (filter (lambda (x) (not (nil? x))) (list (gtk-theme-configuration-package (home-gtk-configuration-gtk-theme config)) (gtk-theme-configuration-package (home-gtk-configuration-icon-theme config)) (gtk-theme-configuration-package (home-gtk-configuration-cursor-theme config)) (if (nil? (gtk-theme-configuration-name (home-gtk-configuration-cursor-theme config))) '() (package (name "default-icon-inherits") (version "0.0.0") (source #f) (build-system trivial-build-system) (home-page #f) (synopsis #f) (description #f) (license #f) (arguments (list #:builder (with-imported-modules '((guix build utils)) #~(begin (use-modules (guix build utils)) (mkdir-p (string-append #$output "/share/icons/default")) (call-with-output-file (string-append #$output "/share/icons/default/index.theme") (lambda (port) (format port "[Icon Theme]~%Name=Default~%Comment=Default cursor theme~%Inherits=~a~%" #$(gtk-theme-configuration-name (home-gtk-configuration-cursor-theme config)))))))))))))) (define (add-xcursor-environment config) (let* ((cursor-theme (home-gtk-configuration-cursor-theme config)) (cursor-name (gtk-theme-configuration-name cursor-theme)) (cursor-package (gtk-theme-configuration-package cursor-theme)) (cursor-size (gtk-theme-configuration-size cursor-theme))) (if (nil? cursor-name) '() `(("GTK2_RC_FILES" . "$HOME/.gtkrc-2.0") ("XCURSOR_THEME" . ,cursor-name) ("XCURSOR_SIZE" . ,(format #f "~a" cursor-size)))))) ;; TODO: this path should not be hardcoded here (define (add-gtk-config-file config) (append `((".gtkrc-2.0" ,(apply mixed-text-file (cons* "gtkrc-2.0" (serialize-gtk-config config #:gtk2? #t)))) (".config/gtk-3.0/settings.ini" ,(apply mixed-text-file (cons* "settings.ini" (serialize-gtk-config config)))) (".config/gtk-4.0/settings.ini" ,(apply mixed-text-file (cons* "settings.ini" (serialize-gtk-config config))))) (if (nil? (gtk-theme-configuration-package (home-gtk-configuration-gtk-theme config))) '() `((".config/gtk-4.0/gtk.css" ,(apply mixed-text-file (gtk4-css-import-file (gtk-theme-configuration-package (home-gtk-configuration-gtk-theme config)) (gtk-theme-configuration-name (home-gtk-configuration-gtk-theme config))))))))) (define (add-gtk-dconf-config config) (let* ((data `((font-name . ,(home-gtk-configuration-font-name config)) (gtk-theme . ,(gtk-theme-configuration-name (home-gtk-configuration-gtk-theme config))) (cursor-theme . ,(gtk-theme-configuration-name (home-gtk-configuration-cursor-theme config))) (icon-theme . ,(gtk-theme-configuration-name (home-gtk-configuration-icon-theme config))))) (filtered-data (filter (lambda (x) (not (nil? (cdr x)))) data))) `((org/gnome/desktop/interface ,filtered-data)))) (define-public home-gtk-service-type (service-type (name 'home-gtk) (extensions (list (service-extension home-files-service-type add-gtk-config-file) (service-extension home-dconf-service-type add-gtk-dconf-config) (service-extension home-profile-service-type add-gtk-theme-packages) (service-extension home-environment-variables-service-type add-xcursor-environment))) (description "Create gtk theme configuration files for gtk2 and gtk3")))