+(use-package exwm
+ :demand
+ :config
+ (require 'exwm-config)
+
+ (setq
+ exwm-workspace-number 4
+ exwm-workspace-index-map (lambda (i) (number-to-string (1+ i))))
+
+ ;; Make class name the buffer name, truncating beyond 60 characters
+ (defun exwm-rename-buffer ()
+ (interactive)
+ (exwm-workspace-rename-buffer
+ (concat exwm-class-name ":"
+ (if (<= (length exwm-title) 60) exwm-title
+ (concat (substring exwm-title 0 59) "...")))))
+ (add-hook 'exwm-update-class-hook 'exwm-rename-buffer)
+ (add-hook 'exwm-update-title-hook 'exwm-rename-buffer)
+
+ (defun b/exwm-ws-prev-index ()
+ "Return the index for the previous EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index 0)
+ (1- exwm-workspace-number)
+ (1- exwm-workspace-current-index)))
+
+ (defun b/exwm-ws-next-index ()
+ "Return the index for the next EXWM workspace, wrapping
+around if needed."
+ (if (= exwm-workspace-current-index
+ (1- exwm-workspace-number))
+ 0
+ (1+ exwm-workspace-current-index)))
+
+ ;; 's-R': Reset
+ (exwm-input-set-key (kbd "s-R") #'exwm-reset)
+ ;; 's-\': Switch workspace
+ (exwm-input-set-key (kbd "s-\\") #'exwm-workspace-switch)
+ ;; 's-N': Switch to certain workspace
+ (dotimes (i exwm-workspace-number)
+ (exwm-input-set-key
+ (kbd (format "s-%d" i))
+ (lambda ()
+ (interactive)
+ (exwm-workspace-switch-create (1- i)))))
+ ;; 's-[': Switch to previous workspace
+ (defun b/exwm-ws-prev ()
+ "Switch to previous EXWM workspace, wrapping around if needed."
+ (interactive)
+ (exwm-workspace-switch-create (b/exwm-ws-prev-index)))
+ (exwm-input-set-key (kbd "s-[") #'b/exwm-ws-prev)
+ ;; 's-]': Switch to next workspace
+ (defun b/exwm-ws-next ()
+ "Switch to next EXWM workspace, wrapping around if needed."
+ (interactive)
+ (exwm-workspace-switch-create (b/exwm-ws-next-index)))
+ (exwm-input-set-key (kbd "s-]") #'b/exwm-ws-next)
+ ;; 's-{': Move window to previous workspace
+ (defun b/exwm-move-window-to-prev-ws ()
+ "Move window to previous EXWM workspace, wrapping around if
+needed."
+ (interactive)
+ (exwm-workspace-move-window (b/exwm-ws-prev-index)))
+ (exwm-input-set-key (kbd "s-{") #'b/exwm-move-window-to-prev-ws)
+ ;; 's-}': Move window to next workspace
+ (defun b/exwm-move-window-to-next-ws ()
+ "Move window to next EXWM workspace, wrapping around if
+needed."
+ (interactive)
+ (exwm-workspace-move-window (b/exwm-ws-next-index)))
+ (exwm-input-set-key (kbd "s-}") #'b/exwm-move-window-to-next-ws)
+ ;; 's-SPC': Launch application
+ ;; (exwm-input-set-key
+ ;; (kbd "s-SPC")
+ ;; (lambda (command)
+ ;; (interactive (list (read-shell-command "➜ ")))
+ ;; (start-process-shell-command command nil command)))
+
+ (exwm-input-set-key (kbd "M-s-SPC") #'counsel-linux-app)
+
+ (exwm-input-set-key
+ (kbd "s-<return>") (lambda ()
+ (interactive)
+ (b/start-process "urxvt")))
+
+ (exwm-input-set-key
+ (kbd "s-t")
+ (lambda ()
+ (interactive)
+ (exwm-floating-toggle-floating)))
+
+ (exwm-input-set-key
+ (kbd "s-f")
+ (lambda ()
+ (interactive)
+ (exwm-layout-toggle-fullscreen)))
+
+ (exwm-input-set-key
+ (kbd "s-w")
+ (lambda ()
+ (interactive)
+ (kill-buffer (current-buffer))))
+
+ (exwm-input-set-key
+ (kbd "s-q")
+ (lambda ()
+ (interactive)
+ (exwm-manage--kill-client)))
+
+ ;; (exwm-input-set-key
+ ;; (kbd "s-SPC") ;; rofi doesn't properly launch programs when started from emacs
+ ;; (lambda ()
+ ;; (interactive)
+ ;; (start-process-shell-command "rofi-run" nil "rofi -show run -display-run '> ' -display-window ' 🗔 '")))
+
+ ;; (exwm-input-set-key
+ ;; (kbd "s-/")
+ ;; (lambda ()
+ ;; (interactive)
+ ;; (start-process-shell-command "rofi-win" nil "rofi -show window -display-run '> ' -display-window ' 🗔 '")))
+
+ ;; (exwm-input-set-key
+ ;; (kbd "M-SPC")
+ ;; (lambda ()
+ ;; (interactive)
+ ;; (start-process "rofi-pass" nil "rofi-pass")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioMute>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "pamixer" nil "pamixer --toggle-mute")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioLowerVolume>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "pamixer" nil "pamixer --allow-boost --decrease 5")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioRaiseVolume>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "pamixer" nil "pamixer --allow-boost --increase 5")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioPlay>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "mpc" nil "mpc toggle")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioPrev>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "mpc" nil "mpc prev")))
+
+ (exwm-input-set-key
+ (kbd "<XF86AudioNext>")
+ (lambda ()
+ (interactive)
+ (start-process-shell-command "mpc" nil "mpc next")))
+
+ ;; Shorten 'C-c C-q' to 'C-q'
+ (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
+
+ ;; Line-editing shortcuts
+ (setq exwm-input-simulation-keys
+ '(;; movement
+ ([?\C-b] . [left])
+ ([?\M-b] . [C-left])
+ ([?\C-f] . [right])
+ ([?\M-f] . [C-right])
+ ([?\C-p] . [up])
+ ([?\C-n] . [down])
+ ([?\C-a] . [home])
+ ([?\C-e] . [end])
+ ([?\M-v] . [prior])
+ ([?\C-v] . [next])
+ ([?\C-d] . [delete])
+ ([?\C-k] . [S-end ?\C-x])
+ ;; cut/copy/paste
+ ([?\C-w] . [?\C-x])
+ ([?\M-w] . [?\C-c])
+ ([?\C-y] . [?\C-v])
+ ([?\M-d] . [C-S-right ?\C-x])
+ ([?\M-\d] . [C-S-left ?\C-x])
+ ;; search
+ ([?\C-s] . [?\C-f])
+ ;; escape
+ ([?\C-g] . [escape])))
+
+ ;; Enable EXWM
+ (exwm-enable)
+
+ (add-hook 'exwm-init-hook #'exwm-config--fix/ido-buffer-window-other-frame)
+
+ (require 'exwm-systemtray)
+ (exwm-systemtray-enable)
+
+ (require 'exwm-randr)
+ (exwm-randr-enable))
+