(use-package exwm ; emacs x window manager :demand nil :config (require 'exwm-randr) (require 'exwm-xim) (require 'exwm-systemtray) (require 'exwm-manage) (add-to-list 'exwm-manage-configurations '((equal exwm-class-name "Slack") managed t)) (use-package exwm-modeline) ;;(exwm-xim-mode 1) (defun my/exwm-auto-workspace-montior () "Autopopulate exwm-randr-workspace-monitor-plist and attempt to have a workspace on each monitor. Try to keep up with xrandr changes." (let ((buf (generate-new-buffer "*xrandr-output*")) (out-plist nil)) (call-process-shell-command "xrandr --listmonitors -q" nil buf nil) (with-current-buffer buf (keep-lines "[^[:word:]]connected" (point-min) (point-max) nil) ;; (goto-char (point-min)) ;; (while (re-search-forward "^\\([a-zA-Z\\-0-9]+\\) .*$" nil t nil) ;; (replace-match "\\1")) ;; (goto-char (point-min)) (let ((num-monitors (count-lines (point-min) (point-max))) (i 0)) (setq exwm-workspace-number num-monitors) (goto-char (point-min)) (while (< i num-monitors) (move-beginning-of-line 1) (push-mark) (search-forward-regexp " ") (backward-char) (push (buffer-substring (mark) (point)) out-plist) (if (> i 0) (let ((prev (caddr out-plist)) (cur (car out-plist))) (call-process-shell-command (format "xrandr --output %s --auto --right-of %s" cur prev) nil nil nil)) (call-process-shell-command (format "xrandr --output %s --auto" (car out-plist)) nil nil nil)) (push i out-plist) (setq i (+ i 1)) (pop-mark) (forward-line)))) (kill-buffer buf) (setq exwm-randr-workspace-monitor-plist out-plist)) (while (> exwm-workspace-number (length exwm-workspace--list)) (exwm-workspace-add))) (add-hook 'exwm-randr-screen-change-hook #'my/exwm-auto-workspace-montior) (defun my/exwm-set-buffer-name () (if exwm-title (let* ((shortened-title (replace-regexp-in-string " - Mozilla Firefox" "" exwm-title)) (class-and-title (concat exwm-class-name "<" shortened-title ">"))) (setq-local exwm-title class-and-title) (exwm-workspace-rename-buffer exwm-title)))) (defun my/exwm-other-workspace (arg) "Focus other monitor's workspace." (interactive "p") ;; based on other-frame (let ((filter-f (function (lambda (f) (and (exwm-workspace--active-p f) (not (eq (selected-frame) f)))))) (sframe (selected-frame)) (frame (selected-frame))) (while (> arg 0) (setq frame (next-frame frame)) (while (and (not (eq frame sframe)) (not (eq (frame-visible-p frame) t)) (funcall filter-f frame)) (setq frame (next-frame frame))) (setq arg (1- arg))) (while (< arg 0) (setq frame (previous-frame frame)) (while (and (not (eq frame sframe)) (not (eq (frame-visible-p frame) t)) (filter-f frame)) (setq frame (previous-frame frame))) (setq arg (1+ arg))) (exwm-workspace-switch frame))) (defun my/dmenu (command) (interactive (list (read-shell-command "$ "))) (start-process-shell-command command nil command)) (defun my/browser () (interactive) (start-process-shell-command "glide" nil "glide")) (defun my/brightnessdown () (interactive) (start-process "" nil "brightnessdown")) (defun my/brightnessup () (interactive) (start-process "" nil "brightnessup")) (defun my/mute () (interactive) (start-process "" nil "pactl" "set-sink-mute" "@DEFAULT_SINK@" "toggle")) (defun my/voldown () (interactive) (start-process "" nil "pactl" "set-sink-volume" "@DEFAULT_SINK@" "-5%")) (defun my/volup () (interactive) (start-process "" nil "pactl" "set-sink-volume" "@DEFAULT_SINK@" "+5%")) (push ?\C-\\ exwm-input-prefix-keys) ;;C-\ to switch input method (push ?\C-u exwm-input-prefix-keys) ;; send C-u to all windows too (push ?\M-L exwm-input-prefix-keys) (progn ;; (exwm-enable) ;; (exwm-randr-mode) ;; (ednc-mode 1) ;; (exwm-systemtray-mode) ;; (add-hook 'after-init-hook #'exwm-randr-refresh) ) :hook (exwm-update-class . my/exwm-set-buffer-name) (exwm-update-title . my/exwm-set-buffer-name) ;; (after-init . exwm-randr-refresh) ;; (after-init . display-time-mode) ;; (after-init . ednc-mode) ;; (after-init . display-battery-mode) :custom (exwm-replace nil) (exwm-title-length 50) (exwm-workspace-show-all-buffers t) (exwm-layout-show-all-buffers t) (exwm-modeline-randr t) (exwm-modeline-short nil) (exwm-modeline-urgent t) (exwm-manage-force-tiling t) (exwm-input-global-keys `( ([?\M-r] . exwm-reset) ;; Bind "s-w" to window switcher ([?\M-W] . consult-buffer) ([?\M-o] . other-window) ([?\M-O] . my/exwm-other-workspace) ([?\M-D] . my/dmenu) ([?\M-E] . my/browser) (,(kbd "M-C-m") . my/eshell) ([?\M-K] . kill-current-buffer) ,@(mapcar (lambda (n) (let* ((from (concat "C-x " (format "%d" n))) (to (concat "M-" (format "%d" n))) (bind (keymap-lookup global-map from))) (cons (kbd to) bind))) (number-sequence 0 9)) ([XF86MonBrightnessDown] . my/brightnessdown) ([XF86MonBrightnessUp] . my/brightnessup) ([XF86AudioMute] . my/mute) ([XF86AudioLowerVolume] . my/voldown) ([XF86AudioRaiseVolume] . my/volup))) (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]) ;; edit, copy, paste ([?\C-d] . [delete]) ([?\C-k] . [S-end delete]) ([M-backspace] . [C-backspace]) ([?\M-w] . [?\C-c]) ([?\C-y] . [?\C-v]) ([?\C-s] . [?\C-f]))) (exwm-input-move-event 'M-down-mouse-1) (exwm-input-resize-event 'M-down-mouse-3) :bind (:map exwm-mode-map ("C-q" . 'exwm-input-send-next-key) ("M-!" . 'shell-command)))