cashmere

cashmere

EXWM Configuration

EXWM Configuration

Package Requirements

(require 'exwm)
(require 'exwm-randr)
;; (require 'exwm-systemtray)

Helper Functions

System Integration

(defun efs/run-in-background (command)
  "Execute shell command in background"
  (let ((command-parts (split-string command "[ ]+")))
    (apply 'call-process `(,(car command-parts) nil 0 nil ,@(cdr command-parts)))))

(defun efs/set-wallpaper ()
  "Set desktop wallpaper using feh"
  (interactive)
  (start-process-shell-command
   "feh" nil "feh --bg-scale ~/Pictures/lain_wallpaper/lain_bear_frappe.png"))

Window Management

(defun efs/configure-window-by-class ()
  "Automatically configure windows based on class"
  (interactive)
  (pcase exwm-class-name
    ("Firefox" (exwm-workspace-move-window 2))
    ("Sol" (exwm-workspace-move-window 3))
    ("mpv" (exwm-floating-toggle-floating)
           (exwm-layout-toggle-mode-line))))

(defun efs/exwm-update-class ()
  "Update buffer name to window class"
  (exwm-workspace-rename-buffer exwm-class-name))

(defun efs/exwm-update-title ()
  "Update buffer name with window title for specific apps"
  (pcase exwm-class-name
    ("Firefox" (exwm-workspace-rename-buffer (format "Firefox: %s" exwm-title)))))

Polybar Integration

(defvar efs/polybar-process nil "Polybar process handle")

(defun efs/kill-panel ()
  "Stop Polybar process"
  (interactive)
  (when efs/polybar-process
    (kill-process efs/polybar-process))
  (setq efs/polybar-process nil))

(defun efs/start-panel ()
  "Start Polybar panel"
  (interactive)
  (efs/kill-panel)
  (setq efs/polybar-process (start-process-shell-command "polybar" nil "polybar panel")))

(defun efs/send-polybar-exwm-workspace ()
  "Update Polybar workspace indicator"
  (start-process-shell-command
   "polybar-msg" nil "polybar-msg hook exwm-workspace 1"))

(defun efs/polybar-exwm-workspace ()
  "Get workspace icons for Polybar"
  (pcase exwm-workspace-current-index
    (0 "") (1 "") (2 "") (3 "") (4 "")))

(add-hook 'exwm-workspace-switch-hook 'efs/send-polybar-exwm-workspace)

Perspective EXWM Integration

 ;; First, ensure perspective.el is loaded
 ;; (use-package! perspective
 ;;   :init
 ;;   (setq persp-mode-prefix-key (kbd "C-c M-p"))
 ;;   :config
 ;;   (persp-mode))

 ;; Then load perspective-exwm before exwm-init
 ;; (use-package! perspective-exwm
 ;;   :after (perspective exwm)
 ;;   :config
 ;;   (perspective-exwm-mode)
 ;;   (setq perspective-exwm-override-initial-name
 ;;     '((0 . "misc")
 ;;       (1 . "core")
 ;;       (2 . "browser")
 ;;       (3 . "comms")
 ;;       (4 . "dev")
 ;;       (5 . "five")
 ;;       (6 . "six")
 ;;       (7 . "seven")
 ;;       (8 . "eight")
 ;;       (9 . "nine"))))
 ;; Hooks configuration
;; (add-hook 'exwm-update-class-hook 'efs/exwm-update-class)
;; (add-hook 'exwm-update-title-hook 'efs/exwm-update-title)
;; (add-hook 'exwm-manage-finish-hook 'efs/configure-window-by-class)

Keybindings

(setq exwm-input-prefix-keys '(?\M-x
                               ?\M-:)
      exwm-input-simulation-keys '(([?\s-F] . [?\C-f])
                                   )
      exwm-input-global-keys '(([?\M-\s-7] . (lambda (command)
                                               (interactive (list (read-shell-command "$ ")))
                                               (start-process-shell-command command nil command)))
                               ;; splits
                               ([?\s-v] . evil-window-vsplit)
                               ([?\s-z] . evil-window-split)
                               ;; managing workspaces
                               ([?\s-w] . exwm-workspace-switch)
                               ([?\s-W] . exwm-workspace-swap)
                               ([?\s-\C-w] . exwm-workspace-move)
                               ;; essential programs
                               ([?\s-d] . dirvish)
                               ([?\s-e] . eshell)
                               ([s-return] . dmenu)
                               ;; killing buffers and windows
                               ([?\s-b] . ibuffer)
                               ([?\s-B] . kill-current-buffer)
                               ([?\s-C] .#+workspace/close-window-or-workspace)
                               ;; change window focus with super+h,j,k,l
                               ([?\s-h] . evil-window-left)
                               ([?\s-j] . evil-window-next)
                               ([?\s-k] . evil-window-prev)
                               ([?\s-l] . evil-window-right)
                               ;; move windows around using SUPER+SHIFT+h,j,k,l
                               ([?\s-H] .#+evil/window-move-left)
                               ([?\s-J] .#+evil/window-move-down)
                               ([?\s-K] .#+evil/window-move-up)
                               ([?\s-L] .#+evil/window-move-right)
                               ;; move window to far left or far right with SUPER+CTRL+h,l
                               ([?\s-\C-h] . side-left-window)
                               ([?\s-\C-j] . side-bottom-window)
                               ([?\s-\C-l] . side-right-window)
                               ([?\s-\C-d] . side-window-delete-all)
                               ([?\s-\C-r] . resize-window)
                               ;; switch workspace with SUPER+{0-9}
                               ([?\s-0] . (lambda () (interactive) (exwm-workspace-switch-create 0)))
                               ([?\s-1] . (lambda () (interactive) (exwm-workspace-switch-create 1)))
                               ([?\s-2] . (lambda () (interactive) (exwm-workspace-switch-create 2)))
                               ([?\s-3] . (lambda () (interactive) (exwm-workspace-switch-create 3)))
                               ([?\s-4] . (lambda () (interactive) (exwm-workspace-switch-create 4)))
                               ([?\s-5] . (lambda () (interactive) (exwm-workspace-switch-create 5)))
                               ([?\s-6] . (lambda () (interactive) (exwm-workspace-switch-create 6)))
                               ([?\s-7] . (lambda () (interactive) (exwm-workspace-switch-create 7)))
                               ([?\s-8] . (lambda () (interactive) (exwm-workspace-switch-create 8)))
                               ([?\s-9] . (lambda () (interactive) (exwm-workspace-switch-create 9)))
                               ;; move window workspace with SUPER+SHIFT+{0-9}
                               ([?\s-\)] . (lambda () (interactive) (exwm-workspace-move-window 0)))
                               ([?\s-!] . (lambda () (interactive) (exwm-workspace-move-window 1)))
                               ([?\s-@] . (lambda () (interactive) (exwm-workspace-move-window 2)))
                               ([?\s-] . (lambda () (interactive) (exwm-workspace-move-window 3)))
                               ([?\s-$] . (lambda () (interactive) (exwm-workspace-move-window 4)))
                               ([?\s-%] . (lambda () (interactive) (exwm-workspace-move-window 5)))
                               ([?\s-^] . (lambda () (interactive) (exwm-workspace-move-window 6)))
                               ([?\s-&] . (lambda () (interactive) (exwm-workspace-move-window 7)))
                               ([?\s-*] . (lambda () (interactive) (exwm-workspace-move-window 8)))
                               ([?\s-\(] . (lambda () (interactive) (exwm-workspace-move-window 9)))
                               ;; SUPER+/ switches to char-mode (needed to pass commands in XWindows sometimes)
                               ;; SUPER+? switches us back to line-mode
                               ([?\s-/] . exwm-input-release-keyboard)
                               ([?\s-?] . exwm-reset)
                               ;; setting some toggle commands
                               ([?\s-f] . exwm-floating-toggle-floating)
                               ([?\s-m] . exwm-layout-toggle-mode-line)
                               ([f11] . exwm-layout-toggle-fullscreen)))

Multi-Monitor Configuration

(defun dw/apply-screen-layout ()
  "Configure multi-monitor setup"
  (start-process-shell-command
   "xrandr" nil
   "xrandr --output HDMI-1 --mode 1920x1080 --pos 0x0 --rotate normal \
    --output DP-1 --primary --mode 1920x1080 --rate 144 --pos 1920x0 --rotate normal \
    --output DP-2 --mode 1920x1080 --pos 3840x0 --rotate normal"))

(setq exwm-randr-workspace-monitor-plist
      '(1 "DP-1" 2 "DP-1" 3 "DP-1" 4 "DP-1" 5 "DP-1"
        6 "DP-2" 7 "DP-2" 8 "HDMI-1" 9 "HDMI-1"))

(add-hook 'exwm-randr-screen-change-hook 'dw/apply-screen-layout)
(run-with-timer 2 nil 'dw/apply-screen-layout)
(exwm-randr-mode 1)

Visual Customization

;; Frame transparency
(set-frame-parameter (selected-frame) 'alpha '(90 . 90))
(add-to-list 'default-frame-alist '(alpha . (90 . 90)))

;; Frame size
(set-frame-parameter (selected-frame) 'fullscreen 'maximized)
(add-to-list 'default-frame-alist '(fullscreen . maximized))

;; Initial setup
(defun dw/exwm-init-hook ()
  "Initialization hook for EXWM"
  ;; (exwm-workspace-switch-create 1)
  ;; (efs/start-panel)
  ;; (efs/run-in-background "pasystray")
  ;; (efs/run-in-background "blueman-applet")
  ;; (efs/run-in-background "flameshot")
  ;; (efs/set-wallpaper)
  )

(add-hook 'exwm-init-hook 'dw/exwm-init-hook)

System Integration

;; Enable system tray (optional)
;; (exwm-systemtray-mode 1)
;; (setq exwm-systemtray-height 28)
;; (perspective-exwm-mode)
;; Start EXWM
(exwm-enable)

multi monitor code suggestion fix

(defun get-focused-monitor-geometry ()
  "Get the geometry of the monitor displaying the selected frame in EXWM."
  (let* ((monitor-attrs (frame-monitor-attributes))
         (workarea (assoc 'workarea monitor-attrs))
         (geometry (cdr workarea)))
    (list (nth 0 geometry) ; X
          (nth 1 geometry) ; Y
          (nth 2 geometry) ; Width
          (nth 3 geometry) ; Height
          )))

(defun advise-corfu-make-frame-with-monitor-awareness (orig-fun frame x y width height buffer)
  "Advise `corfu--make-frame` to be monitor-aware, adjusting X and Y according to the focused monitor."
  ;; Get the geometry of the currently focused monitor
  (let* ((monitor-geometry (get-focused-monitor-geometry))
         (monitor-x (nth 0 monitor-geometry))
         (monitor-y (nth 1 monitor-geometry))
         (selected-frame-position (frame-position))
         (selected-frame-x (car selected-frame-position))
         (selected-frame-y (cdr selected-frame-position))
         (new-x (+ monitor-x selected-frame-x x))
         (new-y (+ monitor-y selected-frame-y y)))
    ;; Call the original function with potentially adjusted coordinates
    (funcall orig-fun frame new-x new-y width height buffer)))

;; Entferne zuerst alle vorhandenen Advices für diese Funktion
(advice-remove 'corfu--make-frame 'advise-corfu-make-frame-with-monitor-awareness)

;; Füge die neue Advice hinzu
(advice-add 'corfu--make-frame :around 'advise-corfu-make-frame-with-monitor-awareness)