Rosenthal/modules/rosenthal/services/desktop.scm
Hilton Chain a47d340a20
services: Add %rosenthal-set-keymap.
* modules/rosenthal/services/desktop.scm (%rosenthal-set-keymap): New variable.
(%rosenthal-set-keymap-script): Unexport.
2025-06-27 23:10:30 +08:00

692 lines
21 KiB
Scheme
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; SPDX-FileCopyrightText: 2025 Hilton Chain <hako@ultrarare.space>
;;;
;;; SPDX-License-Identifier: GPL-3.0-or-later
(define-module (rosenthal services desktop)
#:use-module (guix gexp)
#:use-module (guix modules)
#:use-module (guix packages)
#:use-module (guix records)
#:use-module (guix utils)
#:use-module (rosenthal utils file)
#:use-module (rosenthal utils packages)
#:use-module (guix build-system copy)
#:use-module (gnu system)
#:use-module (gnu system shadow)
#:use-module (gnu services)
#:use-module (gnu services base)
#:use-module (gnu services configuration)
#:use-module (gnu services desktop)
#:use-module (gnu services sddm)
#:use-module (gnu services xorg)
#:use-module (rosenthal services base)
#:use-module (gnu home)
#:use-module (gnu home services)
#:use-module (gnu home services desktop)
#:use-module (gnu home services shepherd)
#:use-module (gnu home services sound)
#:use-module (rosenthal packages xorg)
#:export (home-blueman-applet-configuration
home-blueman-applet-service-type
home-fcitx5-configuration
home-fcitx5-service-type
home-mako-configuration
home-mako-service-type
home-network-manager-applet-configuration
home-network-manager-applet-service-type
home-niri-configuration
home-niri-service-type
home-rofi-configuration
home-rofi-service-type
home-swaybg-configuration
home-swaybg-service-type
home-theme-configuration
home-theme-service-type
home-waybar-configuration
home-waybar-service-type
%rosenthal-set-keymap
%rosenthal-skeletons
%rosenthal-desktop-services
%rosenthal-desktop-home-services))
;;;
;;; Blueman
;;;
(define-configuration/no-serialization home-blueman-applet-configuration
(blueman
(file-like (spec->pkg+out "blueman"))
""))
(define %home-blueman-applet-shepherd
(match-record-lambda <home-blueman-applet-configuration>
(blueman)
(list (shepherd-service
(documentation "Start blueman applet.")
(provision '(blueman-applet))
(start
#~(make-forkexec-constructor
(list #$(file-append blueman "/bin/blueman-applet"))))
(stop #~(make-kill-destructor))))))
(define home-blueman-applet-service-type
(service-type
(name 'blueman-applet)
(extensions
(list (service-extension home-profile-service-type
(compose list home-blueman-applet-configuration-blueman))
(service-extension home-shepherd-service-type
%home-blueman-applet-shepherd)))
(default-value (home-blueman-applet-configuration))
(description "Run blueman applet, a tray applet for managing bluetooth.")))
;;;
;;; Fcitx5
;;;
(define list-of-file-likes?
(list-of file-like?))
(define-maybe file-like)
(define-configuration/no-serialization home-fcitx5-configuration
(fcitx5
(file-like (spec->pkg "fcitx5"))
"")
(utilities
(list-of-file-likes (specs->pkgs "fcitx5-configtool"))
"")
(themes
(list-of-file-likes '())
"")
(input-method-editors
(list-of-file-likes '())
"")
(gtk-im-module?
(boolean #f)
"")
(qt-im-module?
(boolean #f)
"")
(xim?
(boolean #t)
""))
(define %home-fcitx5-environment-variables
(match-record-lambda <home-fcitx5-configuration>
(gtk-im-module? qt-im-module? xim?)
`(,@(if gtk-im-module?
'(("GTK_IM_MODULE" . "fcitx"))
'())
,@(if qt-im-module?
'(("QT_IM_MODULE" . "fcitx"))
'())
,@(if xim?
'(("XMODIFIERS" . "@im=fcitx"))
'()))))
(define %home-fcitx5-profile
(match-record-lambda <home-fcitx5-configuration>
(fcitx5 utilities themes input-method-editors gtk-im-module? qt-im-module?)
(append (list fcitx5)
utilities
themes
input-method-editors
(if gtk-im-module?
(list (spec->pkg "fcitx5-gtk"))
'())
(if qt-im-module?
(list (spec->pkg "fcitx5-qt"))
'()))))
(define %home-fcitx5-shepherd
(match-record-lambda <home-fcitx5-configuration>
(fcitx5)
(list (shepherd-service
(documentation "Start fcitx5.")
(provision '(fcitx5))
(requirement '(dbus))
(start
#~(make-forkexec-constructor
(list #$(file-append fcitx5 "/bin/fcitx5"))))
(stop #~(make-kill-destructor))))))
(define home-fcitx5-service-type
(service-type
(name 'fcitx5)
(extensions
(list (service-extension home-environment-variables-service-type
%home-fcitx5-environment-variables)
(service-extension home-profile-service-type
%home-fcitx5-profile)
(service-extension home-shepherd-service-type
%home-fcitx5-shepherd)))
(default-value (home-fcitx5-configuration))
(description "Run fcitx5, an input method framework.")))
;;;
;;; mako
;;;
(define-configuration/no-serialization home-mako-configuration
(mako
(file-like (spec->pkg "mako"))
"")
(config
maybe-file-like
"")
)
(define %home-mako-xdg-config
(match-record-lambda <home-mako-configuration>
(config)
(if (maybe-value-set? config)
`(("mako/config" ,config))
'())))
(define %home-mako-shepherd
(match-record-lambda <home-mako-configuration>
(mako)
(list (shepherd-service
(documentation "Start mako.")
(provision '(mako))
(start
#~(make-forkexec-constructor
(list #$(file-append mako "/bin/mako"))))
(stop #~(make-kill-destructor))))))
(define home-mako-service-type
(service-type
(name 'mako)
(extensions
(list (service-extension home-xdg-configuration-files-service-type
%home-mako-xdg-config)
(service-extension home-shepherd-service-type
%home-mako-shepherd)))
(default-value (home-mako-configuration))
(description "Run mako, a notification daemon.")))
;;;
;;; network-manager-applet
;;;
(define-configuration/no-serialization home-network-manager-applet-configuration
(network-manager-applet
(file-like (spec->pkg "network-manager-applet"))
""))
(define %home-network-manager-applet-shepherd
(match-record-lambda <home-network-manager-applet-configuration>
(network-manager-applet)
(list (shepherd-service
(documentation "Start network manager applet.")
(provision '(network-manager-applet))
(start
#~(make-forkexec-constructor
(list #$(file-append network-manager-applet "/bin/nm-applet"))))
(stop #~(make-kill-destructor))))))
(define home-network-manager-applet-service-type
(service-type
(name 'network-manager-applet)
(extensions
(list (service-extension home-profile-service-type
(compose list home-network-manager-applet-configuration-network-manager-applet))
(service-extension home-shepherd-service-type
%home-network-manager-applet-shepherd)))
(default-value (home-network-manager-applet-configuration))
(description "Run nm-applet, a tray applet for managing networks.")))
;;;
;;; niri
;;;
(define-configuration/no-serialization home-niri-configuration
(config
maybe-file-like
""))
(define %home-niri-xdg-config
(match-record-lambda <home-niri-configuration>
(config)
(if (maybe-value-set? config)
`(("niri/config.kdl" ,config))
'())))
(define home-niri-service-type
(service-type
(name 'niri)
(extensions
(list (service-extension home-xdg-configuration-files-service-type
%home-niri-xdg-config)))
(default-value (home-niri-configuration))
(description
"Set up configuration file for niri, a scrollable-tiling Wayland
compositor.")))
;;;
;;; rofi
;;;
(define-configuration/no-serialization home-rofi-configuration
(config
maybe-file-like
""))
(define %home-rofi-xdg-config
(match-record-lambda <home-rofi-configuration>
(config)
(if (maybe-value-set? config)
`(("rofi/config.rasi" ,config))
'())))
(define home-rofi-service-type
(service-type
(name 'rofi)
(extensions
(list (service-extension home-xdg-configuration-files-service-type
%home-rofi-xdg-config)))
(default-value (home-rofi-configuration))
(description
"Set up configuration file for rofi, an application launcher.")))
;;;
;;; swaybg
;;;
(define-configuration/no-serialization home-swaybg-configuration
(swaybg
(file-like (spec->pkg "swaybg"))
"")
(background
(file-like (local-file "../examples/wallpaper.jpg"))
""))
(define %home-swaybg-shepherd
(match-record-lambda <home-swaybg-configuration>
(swaybg background)
(list (shepherd-service
(documentation "Start swaybg.")
(provision '(swaybg))
(start
#~(make-forkexec-constructor
(list #$(file-append swaybg "/bin/swaybg") "--mode" "fill"
"--image" #$background)))
(stop #~(make-kill-destructor))))))
(define home-swaybg-service-type
(service-type
(name 'swaybg)
(extensions
(list (service-extension home-shepherd-service-type
%home-swaybg-shepherd)))
(default-value (home-swaybg-configuration))
(description
"Run swaybg, a screen wallpaper utility for Wayland compositors.")))
;;;
;;; theme
;;;
(define-configuration/no-serialization home-theme-configuration
(packages
(list-of-file-likes '())
"")
(icon-theme
(string "Adwaita")
"")
(cursor-theme
(string "Adwaita")
"")
(cursor-size
(number 24)
"")
(key-theme
(string "Default")
""))
(define (%home-theme-environment-variables _)
'(("QT_QPA_PLATFORMTHEME" . "gtk3")
("QT_WAYLAND_DECORATION" . "adwaita")))
(define %home-theme-profile
(match-record-lambda <home-theme-configuration>
(packages)
(append (specs->pkgs "adwaita-icon-theme"
"hicolor-icon-theme"
"qtwayland")
packages)))
(define %home-theme-files
(match-record-lambda <home-theme-configuration>
(icon-theme)
`((".icons/default/index.theme"
,(plain-file "index.theme"
(format #f "\
[icon theme]
Inherits = ~a~%"
icon-theme))))))
(define %home-theme-xdg-config
(match-record-lambda <home-theme-configuration>
(icon-theme cursor-theme cursor-size key-theme)
`(("gtk-3.0/settings.ini"
,(plain-file "settings.ini"
(format #f "\
[Settings]
gtk-theme-name = Adwaita
gtk-icon-theme-name = ~a
gtk-font-name = Sans
gtk-cursor-theme-name = ~a
gtk-cursor-theme-size = ~a
gtk-key-theme-name = ~a~%"
icon-theme cursor-theme cursor-size key-theme))))))
(define home-theme-service-type
(service-type
(name 'theme)
(extensions
(list (service-extension home-environment-variables-service-type
%home-theme-environment-variables)
(service-extension home-profile-service-type
%home-theme-profile)
(service-extension home-files-service-type
%home-theme-files)
(service-extension home-xdg-configuration-files-service-type
%home-theme-xdg-config)))
(default-value (home-theme-configuration))
(description "Set up desktop themes.")))
;;;
;;; waybar
;;;
(define-configuration/no-serialization home-waybar-configuration
(waybar
(file-like (spec->pkg "waybar"))
"")
(config
maybe-file-like
"")
(style
maybe-file-like
""))
(define %home-waybar-xdg-config
(match-record-lambda <home-waybar-configuration>
(config style)
`(,@(if (maybe-value-set? config)
`(("waybar/config.jsonc" ,config))
'())
,@(if (maybe-value-set? style)
`(("waybar/style.css" ,style))
'()))))
(define %home-waybar-shepherd
(match-record-lambda <home-waybar-configuration>
(waybar)
(list (shepherd-service
(documentation "Start waybar.")
(provision '(waybar))
(start
#~(make-forkexec-constructor
(list #$(file-append waybar "/bin/waybar"))))
(stop #~(make-kill-destructor))))))
(define home-waybar-service-type
(service-type
(name 'waybar)
(extensions
(list (service-extension home-xdg-configuration-files-service-type
%home-waybar-xdg-config)
(service-extension home-shepherd-service-type
%home-waybar-shepherd)))
(default-value (home-waybar-configuration))
(description "Run waybar, a status bar for Wayland compositors.")))
;;;
;;; Configuration file presets.
;;;
(define %rosenthal-set-keymap-script
(program-file "set-keymap"
(with-imported-modules (source-module-closure '((guix build utils)))
#~(begin
(use-modules (srfi srfi-1)
(srfi srfi-26)
(srfi srfi-37)
(ice-9 match)
(ice-9 popen)
(guix build utils))
(define* (build-keyboard-layout file layout #:optional variant #:key model options)
(define pipe
(apply open-pipe* OPEN_READ
#$(file-append (spec->pkg "console-setup") "/bin/ckbcomp")
(string-append "-I" #$(spec->pkg "xkeyboard-config") "/share/X11/xkb")
"-rules" "base"
`(,@(if model
'("-model" ,model)
'())
,layout
,(or variant "")
,(string-join options ","))))
(mkdir-p (dirname file))
(call-with-output-file file
(lambda (output)
(dump-port pipe output))))
(define* (set-keyboard-layout layout #:optional variant #:key model options)
(define file-name "/tmp/keymaps/console-keymap")
(build-keyboard-layout file-name layout variant #:model model #:options options)
(invoke "sudo" #$(file-append (spec->pkg "kbd") "/bin/loadkeys") file-name)
(when (getenv "WAYLAND_DISPLAY")
(substitute* (in-vicinity (getenv "XDG_CONFIG_HOME") "niri/config.kdl")
(("^ (layout|variant|model|options) .*") "")
(("^ xkb \\{.*" line)
(string-append
line
(format #f " layout ~s~%" layout)
(if variant (format #f " variant ~s~%" variant) "")
(if model (format #f " model ~s~%" model) "")
(format #f " options ~s~%" (string-join options ",")))))))
(define (show-help-and-exit)
(display "\
Usage: set-keymap LAYOUT [VARIANT] [-m MODEL] [-o OPTIONS]
OPTIONS are comma-separated e.g. \"ctrl:nocaps,grp:alt_shift_toggle\"
Examples:
set-keymap us
set-keymap us dvorak
set-keymap us dvorak -o ctrl:nocaps\n")
(quit))
(define (parse-options)
(args-fold (cdr (program-arguments))
(list (option '(#\m "model") #t #f
(lambda (opt name arg result)
(alist-cons 'model arg result)))
(option '(#\o "options") #t #f
(lambda (opt name arg result)
(alist-cons 'options (string-split arg #\,)
result)))
(option '("help") #f #f
(lambda _
(show-help-and-exit))))
(lambda (opt name arg loads)
(error "Unrecognized option `~A'" name))
(lambda (opt loads) (cons opt loads))
'()))
(let* ((opts (parse-options))
(model (assoc-ref opts 'model))
(options (or (assoc-ref opts 'options) '()))
(args (remove pair? (reverse opts))))
(match args
((layout)
(set-keyboard-layout layout #:model model #:options options))
((layout variant)
(set-keyboard-layout layout variant #:model model #:options options))
(_
(show-help-and-exit))))))))
(define %rosenthal-set-keymap
(hidden-package
(package
(name "rosenthal-set-keymap")
(version "0.0.0")
(source %rosenthal-set-keymap-script)
(build-system copy-build-system)
(arguments
(list
#:phases
#~(modify-phases %standard-phases
(replace 'install
(lambda _
(install-file "set-keymap" (in-vicinity #$output "bin")))))))
(home-page "")
(synopsis "")
(description "")
(license #f))))
(define %rosenthal-skeletons
`((".config/emacs/fonts.el"
,(local-file "../examples/emacs/fonts.el"))
(".config/emacs/init.el"
,(local-file "../examples/emacs/init.el"))
(".config/foot/foot.ini"
,(plain-file "foot.ini" "font=monospace:size=12\n"))
(".config/mako/config"
,(local-file "../examples/mako.conf"))
(".config/niri/config.kdl"
,(local-file "../examples/niri.kdl"))
(".config/rofi/config.rasi"
,(plain-file "rofi.rasi" "\
configuration {
icon-theme: \"Qogir\";
}
@theme \"/run/current-system/profile/share/rofi/themes/fullscreen-preview.rasi\"\n"))
(".config/waybar/config.jsonc"
,(local-file "../examples/waybar/config.jsonc"))
(".config/waybar/style.css"
,(local-file "../examples/waybar/style.css"))
(".config/xfce4/helpers.rc"
,(plain-file "helpers.rc" "TerminalEmulator=rofi-sensible-terminal\n"))
;; Selected from the default skeletons.
(".config/gdb/gdbinit" ,%default-gdbinit)
(".config/nano/nanorc" ,%default-nanorc)
(".guile" ,%default-dotguile)))
;;;
;;; Service presets.
;;;
(define* (rosenthal-desktop-services-for-system
#:optional (system (or (%current-target-system)
(%current-system))))
(define %display-manager-service-type
(if (string-prefix? "x86_64" system)
gdm-service-type
sddm-service-type))
(define %term-font
(file-append (spec->pkg "font-terminus") "/share/consolefonts/ter-132n"))
(cons* (service greetd-service-type
(greetd-configuration
(greeter-supplementary-groups '("video" "input"))
(terminals
(map (lambda (x)
(greetd-terminal-configuration
(terminal-vt (number->string x))
(terminal-switch (eqv? 1 x))
(default-session-command
(cond
((eqv? 1 x)
(greetd-tuigreet-session))
(else
(greetd-agreety-session
(command
(greetd-user-session
(command #~(getenv "SHELL"))))))))))
(iota 6 1)))))
(service bluetooth-service-type
(bluetooth-configuration
(auto-enable? #t)))
(service gvfs-service-type)
;; Screen lockers for Wayland environment. No dependencies are pulled
;; in since we're using empty files.
(service screen-locker-service-type
(screen-locker-configuration
(name "swaylock")
(program (plain-file "empty" "")) ;Not used.
(using-setuid? #f)))
(service screen-locker-service-type
(screen-locker-configuration
(name "waylock")
(program (plain-file "empty" "")) ;Not used.
(using-setuid? #f)))
;; Add udev rules for backlight control.
(simple-service 'backlight udev-service-type (specs->pkgs "light"))
(modify-services %desktop-services
(delete mingetty-service-type)
(delete %display-manager-service-type)
(delete screen-locker-service-type)
;; Use a font suitable for HiDPI monitors.
(console-font-service-type
_ => (map (lambda (num)
(cons (string-append "tty" (number->string num))
%term-font))
(iota 6 1))))))
(define-syntax %rosenthal-desktop-services
(identifier-syntax (rosenthal-desktop-services-for-system)))
(define %rosenthal-desktop-home-services
(cons* (service home-shepherd-service-type
(home-shepherd-configuration
;; Start by WM to inherit environment variables for graphical session.
(auto-start? #f)
(daemonize? #f)))
(service home-dbus-service-type)
(service home-pipewire-service-type)
(service home-blueman-applet-service-type)
(service home-network-manager-applet-service-type)
%base-home-services))