#+title: Desktop Configuration #+author: jdlugosz963 #+PROPERTY: header-args:emacs-lisp :tangle .config/emacs/exwm/desktop.el * EXWM ** Config #+begin_src emacs-lisp (defun jd/exwm-update-class () (exwm-workspace-rename-buffer exwm-class-name)) (defun jd-exwm/run-in-background (command) (let ((command-parts (split-string command "[ ]+"))) (apply #'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts))))) (defun jd-exwm/restart-process (program-name) (call-process "killall" nil nil nil program-name) (jd-exwm/run-in-background program-name)) (defun jd-exwm/exwm-init-hook () (jd-exwm/run-in-background "nitrogen --restore") (start-process-shell-command "xinput" nil "xinput set-prop 'ETPS/2 Elantech Touchpad' 'Synaptics Tap Action' 1 1 1 2 1") (start-process-shell-command "syndaemon" nil "syndaemon -i 0.8 -K -R -d") (jd-exwm/restart-process "polybar") (jd-exwm/restart-process "nm-applet") (jd-exwm/restart-process "redshift-gtk -l 54.37:18.6") (jd-exwm/restart-process "blueman-applet")) (defun jd-exwm/exwm-update-title () (exwm-workspace-rename-buffer exwm-title)) (defun jd-exwm/configure-window-by-class () (interactive) (pcase exwm-class-name ("firefox" (exwm-workspace-move-window 2)) ("Brave" (exwm-workspace-move-window 2)) ("qutebrowser" (exwm-workspace-move-window 2)) ("discord" (exwm-workspace-move-window 5)) ("obs" (exwm-workspace-move-window 5)) ("Virt-manager" (exwm-workspace-move-window 4)))) (use-package exwm :config (setq exwm-workspace-number 10) (add-hook 'exwm-init-hook #'jd-exwm/exwm-init-hook) (add-hook 'exwm-update-class-hook #'jd/exwm-update-class) (add-hook 'exwm-update-title-hook #'jd-exwm/exwm-update-title) (add-hook 'exwm-manage-finish-hook #'jd-exwm/configure-window-by-class) (require 'exwm-randr) (setq exwm-randr-workspace-monitor-plist '(9 "eDP-1" 0 "eDP-1")) (exwm-randr-enable) (setq exwm-input-simulation-keys '(([?\C-h] . [left]) ([?\C-l] . [right]) ([?\C-k] . [up]) ([?\C-j] . [down]))) (setq exwm-input-prefix-keys '(?\C-x ?\C-u ?\C-h ?\M-x ?\M-` ?\M-& ?\M-: ?\C-\M-j ?\C-\ )) (define-key exwm-mode-map [?\C-q] 'exwm-input-send-next-key) (exwm-input-set-key (kbd "s-p") 'counsel-linux-app) (setq exwm-input-global-keys `(([?\s-R] . exwm-reset) ([?\s-r] . (lambda (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command))) ([?\s-W] . exwm-workspace-move-window) ([?\s-w] . exwm-workspace-switch) ,@(mapcar (lambda (i) `(,(kbd (format "s-%d" i)) . (lambda () (interactive) (exwm-workspace-switch-create ,i)))) (number-sequence 0 9)))) (exwm-enable)) #+end_src ** Desktop mode #+begin_src emacs-lisp (use-package desktop-environment :after exwm :config (desktop-environment-mode) :custom (desktop-environment-brightness-small-increment "2%+") (desktop-environment-brightness-small-decrement "2%-") (desktop-environment-brightness-normal-increment "5%+") (desktop-environment-brightness-normal-decrement "5%-")) #+end_src ** Transparency #+begin_src emacs-lisp (set-frame-parameter (selected-frame) 'alpha '(90 . 90)) (add-to-list 'default-frame-alist `(alpha . (90 . 90))) (set-frame-parameter (selected-frame) 'fullscreen 'maximized) (add-to-list 'default-frame-alist '(fullscreen . maximized)) #+end_src ** Update colorsheme #+begin_src emacs-lisp (defun jd-exwm/get-color (ATTRIBUTE) (face-attribute 'default ATTRIBUTE)) (defun theme-to-xresources () (interactive) (require 'term) (with-temp-buffer (insert "! Generated by theme-to-xresources\n") (dolist (spec '(("emacs.background" :background "E6") ("emacs.foreground" :foreground ""))) (let ((color (jd-exwm/get-color (cadr spec)))) (insert (format "%s: #%s%s\n" (car spec) (caddr spec) (string-remove-prefix "#" color)))) (write-region (point-min) (point-max) "~/.Xresources"))) (call-process "xrdb" nil nil nil "-merge" (expand-file-name "~/.Xresources"))) (defun jd/theme-sync () (interactive) (theme-to-xresources) (setq org-confirm-babel-evaluate nil) (org-babel-tangle-file "~/dotfiles/Desktop.org") (setq org-confirm-babel-evaluate 't) (call-process "killall" nil nil nil "dunst") ;; TODO: prevent clear notification history (jd-exwm/restart-process "polybar")) (add-hook 'jd/load-theme-hook #'jd/theme-sync) (add-hook 'exwm-init-hook #'jd/theme-sync) #+end_src ** Start emacs #+begin_src sh :tangle ~/.config/emacs/exwm/start.sh #!/bin/sh picom & xss-lock -- slock & export VISUAL="emacsclient -a vim" export EDITOR="$VISUAL" export GTK_THEME="Adwaita:dark" export CALIBRE_USE_DARK_PALETTE=1 gentoo-pipewire-launcher & exec dbus-launch --exit-with-session emacs -mm --debug-init -l ~/.config/emacs/exwm/desktop.el #+end_src * Dunst *Dunst keybinds in Emacs* #+begin_src emacs-lisp (defun jd/dunst-show-history () (interactive) (start-process-shell-command "dunstctl" nil "dunstctl history-pop")) (defun jd/dunst-close () (interactive) (start-process-shell-command "dunstctl" nil "dunstctl close")) (defun jd/dunst-close-all () (interactive) (start-process-shell-command "dunstctl" nil "dunstctl close-all")) (jd/leader-key-def "d" '(nil :which-key "dunst") "dh" '(jd/dunst-show-history :which-key "show history") "dc" '(jd/dunst-close :which-key "close") "da" '(jd/dunst-close-all :which-key "close all")) #+end_src *Get emacs colors* #+NAME: get-color #+BEGIN_SRC elisp :var ATTR="" :tangle no :eval yes (if (and (stringp ATTR) (s-prefix-p ":" ATTR)) (jd-exwm/get-color (intern ATTR)) "") #+END_SRC *dunstrc* #+begin_src conf :tangle .config/dunst/dunstrc :noweb yes :eval yes [global] frame_width = 2 frame_color = "<>" font = sourcecodepro # Allow a small subset of html markup: # bold # italic # strikethrough # underline # # For a complete reference see # . # If markup is not allowed, those tags will be stripped out of the # message. markup = yes # The format of the message. Possible variables are: # %a appname # %s summary # %b body # %i iconname (including its path) # %I iconname (without its path) # %p progress value if set ([ 0%] to [100%]) or nothing # Markup is allowed format = "%s %p\n%b" # Sort messages by urgency. sort = yes # Show how many messages are currently hidden (because of geometry). indicate_hidden = yes # Alignment of message text. # Possible values are "left", "center" and "right". alignment = left # The frequency with wich text that is longer than the notification # window allows bounces back and forth. # This option conflicts with "word_wrap". # Set to 0 to disable. bounce_freq = 5 # Show age of message if message is older than show_age_threshold # seconds. # Set to -1 to disable. show_age_threshold = 60 # Split notifications into multiple lines if they don't fit into # geometry. word_wrap = no # Ignore newlines '\n' in notifications. ignore_newline = no # The geometry of the window: # [{width}]x{height}[+/-{x}+/-{y}] # The geometry of the message window. # The height is measured in number of notifications everything else # in pixels. If the width is omitted but the height is given # ("-geometry x2"), the message window expands over the whole screen # (dmenu-like). If width is 0, the window expands to the longest # message displayed. A positive x is measured from the left, a # negative from the right side of the screen. Y is measured from # the top and down respectevly. # The width can be negative. In this case the actual width is the # screen width minus the width defined in within the geometry option. geometry = "500x10-10+50" # Shrink window if it's smaller than the width. Will be ignored if # width is 0. shrink = yes # The transparency of the window. Range: [0; 100]. # This option will only work if a compositing windowmanager is # present (e.g. xcompmgr, compiz, etc.). transparency = 15 # Don't remove messages, if the user is idle (no mouse or keyboard input) # for longer than idle_threshold seconds. # Set to 0 to disable. # default 120 idle_threshold = 120 # Which monitor should the notifications be displayed on. monitor = 0 # Display notification on focused monitor. Possible modes are: # mouse: follow mouse pointer # keyboard: follow window with keyboard focus # none: don't follow anything # # "keyboard" needs a windowmanager that exports the # _NET_ACTIVE_WINDOW property. # This should be the case for almost all modern windowmanagers. # # If this option is set to mouse or keyboard, the monitor option # will be ignored. follow = mouse # Should a notification popped up from history be sticky or timeout # as if it would normally do. sticky_history = yes # Maximum amount of notifications kept in history history_length = 20 # Display indicators for URLs (U) and actions (A). show_indicators = yes # The height of a single line. If the height is smaller than the # font height, it will get raised to the font height. # This adds empty space above and under the text. line_height = 0 # Draw a line of "separator_height" pixel height between two # notifications. # Set to 0 to disable. separator_height = 1 # Padding between text and separator. # padding = 8 padding = 8 # Horizontal padding. horizontal_padding = 10 # Define a color for the separator. # possible values are: # * auto: dunst tries to find a color fitting to the background; # * foreground: use the same color as the foreground; # * frame: use the same color as the frame; # * anything else will be interpreted as a X color. separator_color = #263238 # Print a notification on startup. # This is mainly for error detection, since dbus (re-)starts dunst # automatically after a crash. startup_notification = false # dmenu path. dmenu = /usr/bin/dmenu -p dunst: # Browser for opening urls in context menu. browser = palemoon # Align icons left/right/off icon_position = left # Limit icons size. max_icon_size=128 [urgency_low] # IMPORTANT: colors have to be defined in quotation marks. # Otherwise the "#" and following would be interpreted as a comment. background = "<>" foreground = "#888888" timeout = 10 # Icon for notifications with low urgency, uncomment to enable #icon = /path/to/icon [urgency_normal] background = "<>" foreground = "<>" timeout = 10 # Icon for notifications with normal urgency, uncomment to enable #icon = /path/to/icon [urgency_critical] background = "#900000" foreground = "#ffffff" frame_color = "#ff0000" timeout = 0 # Icon for notifications with critical urgency, uncomment to enable #icon = /path/to/icon #+end_src * Polybar #+begin_src conf :tangle .config/polybar/config.ini [settings] screenchange-reload = true pseudo-transparency = true [colors] background = ${xrdb:emacs.background} foreground = ${xrdb:emacs.foreground} primary = #7fd962 disabled = #707880 [bar/example] width = 100% height = 18pt background = ${colors.background} foreground = ${colors.foreground} line-size = 1.5pt padding-left = 0 padding-right = 1 module-margin = 1 separator = | separator-foreground = ${colors.disabled} font-0 = "sourcecodepro:size=11" font-1 = "FontAwesome" modules-left = xworkspaces modules-right = memory cpu battery date cursor-click = pointer cursor-scroll = ns-resize enable-ipc = true tray-position = right [module/xworkspaces] type = internal/xworkspaces icon-0 = 1;0 icon-1 = 2;1 icon-2 = 3;2 icon-3 = 4;3 icon-4 = 5;4 icon-5 = 6;5 icon-6 = 7;6 icon-7 = 8;7 icon-8 = 9;8 icon-9 = 10;9 label-active = %icon% label-active-background = ${colors.background-alt} label-active-underline= ${colors.primary} label-active-padding = 1 label-occupied = %icon% label-occupied-padding = 1 label-urgent = %icon% label-urgent-background = ${colors.alert} label-urgent-padding = 1 label-empty = %icon% label-empty-foreground = ${colors.disabled} label-empty-padding = 1 [module/battery] type = internal/battery battery = BAT0 adapter = ADP1 format-charging = format-discharging = format-low = format-full = label-charging = %percentage%% label-discharging = %percentage%% label-low = LOW %percentage%% label-full = FULL %percentage%% ramp-capacity-0 =  ramp-capacity-1 =  ramp-capacity-2 =  ramp-capacity-3 =  ramp-capacity-4 =  ramp-capacity-foreground = ${colors.primary} animation-charging-0 =  animation-charging-1 =  animation-charging-2 =  animation-charging-3 =  animation-charging-4 =  animation-charging-foreground = ${colors.primary} animation-charging-framerate = 750 [module/memory] type = internal/memory interval = 2 format-prefix = "RAM " format-prefix-foreground = ${colors.primary} label = %percentage_used:2%% [module/cpu] type = internal/cpu interval = 2 format-prefix = "CPU " format-prefix-foreground = ${colors.primary} label = %percentage:2%% [module/date] type = internal/date interval = 1 date = %H:%M date-alt = %Y-%m-%d %H:%M:%S label = %date% label-foreground = ${colors.primary} #+end_src