summaryrefslogtreecommitdiffhomepage
path: root/exwm.org
diff options
context:
space:
mode:
Diffstat (limited to 'exwm.org')
-rw-r--r--exwm.org506
1 files changed, 506 insertions, 0 deletions
diff --git a/exwm.org b/exwm.org
new file mode 100644
index 0000000..3450a69
--- /dev/null
+++ b/exwm.org
@@ -0,0 +1,506 @@
+#+title: exwm configuration
+
+* Load and basic config
+ #+begin_src emacs-lisp
+ (use-package exwm
+ :ensure t
+ :init (setq exwm-workspace-number 1
+ exwm-workspace-show-all-buffers t
+ exwm-workspace-warp-cursor nil
+ exwm-layout-show-all-buffers t
+ exwm-floating-border-color
+ (if (jao-colors-scheme-dark-p) "black" "grey90")))
+
+ (use-package exwm-edit :ensure t)
+ (require 'exwm)
+ #+end_src
+* Frames as workspaces
+ #+begin_src emacs-lisp
+ (defun jao-exwm--new-frame-p ()
+ (not (frame-parameter nil 'jao-frames-initialized)))
+
+ (defun jao-exwm--mark-frame (force)
+ (prog1 (or force (jao-exwm--new-frame-p))
+ (set-frame-parameter nil 'jao-frames-initialized t)))
+
+ (defun jao-exwm--goto-main (&optional init)
+ (interactive "P")
+ (exwm-workspace-switch-create 1)
+ (when (jao-exwm--mark-frame init) (jao-trisect)))
+
+ (defun jao-exwm--goto-mail (&optional init)
+ (interactive "P")
+ (exwm-workspace-switch-create 2)
+ (when (jao-exwm--mark-frame init)
+ (jao-afio-open-gnus)))
+
+ (defun jao-exwm--goto-w3m (&optional init)
+ (interactive "P")
+ (exwm-workspace-switch-create 5)
+ (when (jao-exwm--mark-frame init)
+ (jao-afio-open-w3m)
+ (let ((scroll-bar-mode 'left))
+ (toggle-scroll-bar 1)
+ (set-frame-parameter (window-frame) 'scroll-bar-width 12))
+ (jao-toggle-inactive-mode-line)))
+
+ (defun jao-exwm--goto-docs (&optional init)
+ (interactive "P")
+ (exwm-workspace-switch-create 4)
+ (when (jao-exwm--mark-frame init)
+ (jao-afio-open-doc)))
+
+ (defun jao-exwm-open-doc (file)
+ (jao-exwm--goto-docs)
+ (jao-find-or-open file))
+
+ (defun jao-exwm-no-afio-setup ()
+ (interactive)
+ (defalias 'jao-open-gnus-frame 'jao-exwm--goto-mail)
+ (defalias 'jao-goto-w3m-frame 'jao-exwm--goto-w3m)
+ (setq jao-open-doc-fun #'jao-exwm-open-doc)
+ (setq minibuffer-follows-selected-frame t)
+ (global-set-key "\C-cf" 'jao-exwm--goto-main)
+ (global-set-key "\C-cg" 'jao-exwm--goto-mail)
+ (global-set-key "\C-cw" 'jao-exwm--goto-w3m)
+ (global-set-key "\C-cz" 'jao-exwm--goto-docs))
+
+ (if jao-exwm--use-afio
+ (setq minibuffer-follows-selected-frame nil)
+ (jao-exwm-no-afio-setup))
+ #+end_src
+* Tracking
+ #+begin_src emacs-lisp
+ (add-hook 'exwm-workspace-switch-hook 'tracking-remove-visible-buffers)
+ #+end_src
+* Buffer titles
+ #+BEGIN_SRC emacs-lisp
+ (defun jao-exwm--use-title-p ()
+ (or (string-prefix-p "sun-awt-X11-" exwm-instance-name)
+ (string= "Navigator" exwm-instance-name)
+ (string= "Spotify" exwm-class-name)
+ (string= "XTerm" exwm-class-name)
+ (string= "Zathura" exwm-class-name)))
+
+ (defun jao-exwm-rename-buffer/class ()
+ (unless (jao-exwm--use-title-p)
+ (exwm-workspace-rename-buffer exwm-class-name)))
+
+ (defun jao-exwm-rename-buffer/title ()
+ (cond ((or (not exwm-instance-name)
+ (jao-exwm--use-title-p))
+ (exwm-workspace-rename-buffer exwm-title))
+ ((string= "Zathura" exwm-class-name)
+ (exwm-workspace-rename-buffer
+ (format "zathura: %s" (file-name-nondirectory exwm-title))))))
+
+ (defun jao-exwm--set-exwm-name ()
+ (when (not jao-exwm--name)
+ (setq jao-exwm--name jao-exwm--current-name
+ jao-exwm--current-name nil)))
+
+ (add-hook 'exwm-mode-hook 'jao-exwm--set-exwm-name)
+ (add-hook 'exwm-update-class-hook 'jao-exwm-rename-buffer/class)
+ (add-hook 'exwm-update-title-hook 'jao-exwm-rename-buffer/title)
+ #+END_SRC
+* Float windows
+ #+begin_src emacs-lisp
+ (defvar jao-exwm-max-x (x-display-pixel-width))
+ (defvar jao-exwm-max-y (x-display-pixel-height))
+
+ (defun jao-exwm--float-to (x y &optional w h)
+ (let* ((w (or w (frame-pixel-width)))
+ (h (or h (frame-pixel-height)))
+ (x (if (< x 0) (- jao-exwm-max-x (- x) w) x))
+ (y (if (< y 0) (- jao-exwm-max-y (- y) h) y))
+ (p (or (frame-parameter nil 'jao-position) (frame-position))))
+ (exwm-floating-move (- x (car p)) (- y (cdr p)))
+ (exwm-layout-enlarge-window-horizontally (- w (frame-pixel-width)))
+ (exwm-layout-enlarge-window (- h (frame-pixel-height)))
+ (set-frame-parameter nil 'jao-position (cons x y))))
+
+ (defun jao-exwm--center-float (&optional w h)
+ (interactive)
+ (let* ((mx jao-exwm-max-x)
+ (my jao-exwm-max-y)
+ (w (or w (frame-pixel-width)))
+ (h (or h (/ (* w my) mx))))
+ (jao-exwm--float-to (/ (- mx w) 2) (/ (- my h) 2) w h)))
+
+ (defun jao-exwm--setup-float ()
+ (set-frame-parameter nil 'jao-position nil)
+ (cond ((string= "Firefox" exwm-class-name)
+ (jao-exwm--center-float 900 600))
+ ((member exwm-class-name '("mpv" "vlc"))
+ (jao-exwm--center-float 1200))))
+
+ (defvar jao-exwm-floating-classes '("mpv" "vlc"))
+
+ (defun jao-exwm--maybe-float ()
+ (when (member exwm-class-name jao-exwm-floating-classes)
+ (when (not exwm--floating-frame)
+ (exwm-floating-toggle-floating))))
+
+ (add-hook 'exwm-floating-setup-hook #'jao-exwm--setup-float)
+ (add-hook 'exwm-manage-finish-hook #'jao-exwm--maybe-float)
+
+#+end_src
+* Minibuffer and system tray
+ #+BEGIN_SRC emacs-lisp
+ (require 'exwm-systemtray)
+ (setq exwm-systemtray-height 14)
+ (exwm-systemtray-enable)
+
+ (setq jao-minibuffer-frame-width 271)
+ (add-hook 'exwm-workspace-switch-hook #'jao-minibuffer-refresh)
+
+ (defun jao-exwm--watch-tray (sym newval op where)
+ (setq jao-minibuffer-right-margin (* 2 (length newval)))
+ (jao-minibuffer-refresh))
+ (add-variable-watcher 'exwm-systemtray--list #'jao-exwm--watch-tray)
+#+END_SRC
+* Switch to buffer / app
+ #+begin_src emacs-lisp
+ (defvar-local jao-exwm--name nil)
+ (defvar jao-exwm--current-name nil)
+
+ (defun jao-exwm--check-name (name)
+ (or (equalp jao-exwm--name name)
+ (equalp (buffer-name) name)
+ (equalp exwm-class-name name)
+ (equalp exwm-title name)))
+
+ (defun jao-exwm-switch-to-class/title (cln)
+ (interactive)
+ (when cln
+ (if (jao-exwm--check-name cln)
+ (current-buffer)
+ (let ((bfs (seq-filter `(lambda (b)
+ (and (not (eq b ,(current-buffer)))
+ (with-current-buffer b
+ (jao-exwm--check-name ,cln))))
+ (buffer-list))))
+ (when (car bfs) (pop-to-buffer (car (reverse bfs))))))))
+
+ (defun jao-exwm-switch-to-next-class ()
+ (interactive)
+ (jao-exwm-switch-to-class/title exwm-class-name))
+
+ (defun jao-exwm-switch-to-next-x ()
+ (interactive)
+ (let ((bfs (seq-filter (lambda (b) (buffer-local-value 'exwm-class-name b))
+ (buffer-list (window-frame)))))
+ (when (car bfs) (switch-to-buffer (car (reverse bfs))))))
+
+ #+end_src
+* App runners
+ #+BEGIN_SRC emacs-lisp
+ (defun jao-exwm-run (command)
+ (interactive
+ (list (read-shell-command "$ "
+ (if current-prefix-arg
+ (cons (concat " " (buffer-file-name)) 0)
+ ""))))
+ (setq jao-exwm--current-name nil)
+ (start-process-shell-command command nil command))
+
+ (defmacro jao-exwm-runner (&rest args)
+ `(lambda () (interactive) (start-process "" nil ,@args)))
+
+ (defun jao-exwm-workspace (n)
+ (if jao-exwm--use-afio
+ (cl-case n
+ ((1) (jao-afio--goto-main))
+ ((2) (jao-afio--goto-gnus))
+ ((3) (jao-afio--goto-w3m))
+ ((4) (jao-afio--goto-docs))
+ ((5) (jao-afio--goto-scratch-1))
+ ((0) (jao-afio--goto-scratch)))
+ (exwm-workspace-switch-create n)))
+
+ (defmacro jao-def-runner (name ws class &rest args)
+ `(defun ,name (&rest other-args)
+ (interactive)
+ ,@(when ws `((jao-exwm-workspace ,ws)))
+ (if (jao-exwm-switch-to-class/title ,class)
+ ,(or (stringp (car args)) args)
+ (setq jao-exwm--current-name ,class)
+ ,(if (stringp (car args))
+ `(start-process-shell-command ,(car args)
+ "* exwm - console *"
+ (string-join (append (list ,@args)
+ other-args)
+ " "))
+ args))))
+
+ (jao-def-runner jao-exwm-spotify 6 "Spotify" "spotify")
+ (jao-def-runner jao-exwm-spt 6 "spt" "xterm" "-e" "spt")
+
+ (jao-def-runner jao-exwm-firefox 5 "Firefox" "firefox")
+
+ (defun jao-exwm-firefox-1 ()
+ (interactive)
+ (jao-exwm-firefox)
+ (delete-other-windows))
+
+ (jao-def-runner jao-exwm-vlc 4 "VLC" "vlc")
+
+ (jao-def-runner jao-exwm-slack 0 "Slack" "slack")
+ (jao-def-runner jao-exwm-signal 0 "Signal" "signal-desktop")
+
+ (jao-def-runner jao-exwm-proton-bridge 0 "*proton-bridge*" "protonmail-bridge")
+ (jao-def-runner jao-exwm-htop 0 "htop-xterm"
+ "xterm" "-title" "htop-xterm" "-e" "htop")
+
+ (jao-def-runner jao-exwm-aptitude 0 "aptitude-xterm"
+ "xterm" "-title" "aptitude-xterm" "-e" "aptitude")
+ (jao-def-runner jao-exwm-blueman 0 "Blueman-manager" "blueman-manager")
+ (jao-def-runner jao-exwm-ncmpcpp 0 "ncmpcpp" "xterm" "-e" "ncmpcpp" "-p" "6669")
+
+ (jao-def-runner jao-exwm-proton-vpn 0 "*pvpn*" proton-vpn-status)
+ (jao-def-runner jao-exwm-enwc 0 "*ENWC*" enwc)
+ (jao-def-runner jao-exwm-bluetooth 0 "*Bluetooth*" bluetooth-list-devices)
+ (jao-def-runner jao-exwm-paradox 0 "*Packages*" paradox-list-packages nil)
+ (jao-def-runner jao-exwm-proced 0 "*Proced*" proced)
+
+ (defun jao-exwm-kill-xmobar ()
+ (interactive)
+ (shell-command "killall xmobar-exwm"))
+
+ (defun jao-exwm-xmobar ()
+ (interactive)
+ (jao-exwm-kill-xmobar)
+ (start-process "" nil "xmobar-exwm" "-d"))
+
+ (jao-def-runner jao-exwm-open-with-zathura nil nil "zathura" (buffer-file-name))
+ (jao-def-runner jao-exwm-open-with-mupdf nil nil "mupdf" (buffer-file-name))
+ (jao-def-runner jao-exwm-xterm 0 nil "xterm")
+
+ (defun jao-exwm-import-screen (&optional area)
+ (interactive "P")
+ (when (not (file-directory-p "/tmp/screenshot"))
+ (make-directory "/tmp/screenshot"))
+ (let ((c (format "import %s %s"
+ (if area "" "-window root")
+ "/tmp/screenshot/$(date +'%g%m%d-%H%M%S').png")))
+ (start-process-shell-command "import" "* exwm - console *" c)))
+
+ #+END_SRC
+* Zathura support
+ #+begin_src emacs-lisp
+ (defun jao-zathura--buffers ()
+ (seq-filter (lambda (b)
+ (string= "Zathura"
+ (or (buffer-local-value 'exwm-class-name b) "")))
+ (buffer-list)))
+
+ (defun jao-zathura--file-info (b)
+ (with-current-buffer b
+ (when (string-match "\\(.+\\) \\[\\(.+\\) (\\([0-9]+\\)/\\([0-9]+\\))\\]"
+ (or exwm-title ""))
+ (list (expand-file-name (match-string 1 exwm-title))
+ (string-to-number (match-string 3 exwm-title))
+ (string-to-number (match-string 4 exwm-title))
+ (match-string 2 exwm-title)))))
+
+ (defun jao-exwm--send-str (str)
+ (dolist (k (string-to-list (kbd str)))
+ (exwm-input--fake-key k)))
+
+ (defun jao-zathura-open-doc (file-name &optional page-no height)
+ (let* ((file-name (expand-file-name file-name))
+ (buffer (seq-find `(lambda (b)
+ (string= ,file-name
+ (car (jao-zathura--file-info b))))
+ (jao-zathura--buffers))))
+ (if jao-exwm--use-afio (jao-afio--goto-docs) (jao-exwm--goto-docs))
+ (if (not buffer)
+ (jao-exwm-run (if page-no
+ (format "zathura -P %s %s" page-no file-name)
+ (format "zathura %s" file-name)))
+ (pop-to-buffer buffer)
+ (jao-exwm--send-str (format "%sg" page-no)))))
+
+ (defun jao-exwm-pdf-zathura-close-all ()
+ (interactive)
+ (dolist (b (jao-zathura--buffers))
+ (ignore-errors (with-current-buffer b (jao-exwm--send-str "q"))))
+ t)
+
+ (defun jao-exwm-pdf-goto-org (&optional arg)
+ (interactive "P")
+ (when-let ((info (jao-zathura--file-info (current-buffer))))
+ (when-let ((file (jao-org-pdf-to-org-file (car info))))
+ (let ((newp (not (file-exists-p file))))
+ (when (or arg newp) (org-store-link nil t))
+ (find-file-other-window file)
+ (when newp
+ (jao-org-insert-doc-skeleton)
+ (org-insert-link))))))
+
+ (defun jao-exwm-pdf-goto-org* ()
+ (interactive)
+ (jao-exwm-pdf-goto-org t))
+
+ (defun jao-exwm-org-store-zathura-link ()
+ (when-let ((info (jao-zathura--file-info (current-buffer))))
+ (jao-org-links-store-pdf-link (car info)
+ (cadr info)
+ (jao-org--pdf-title (car info)))))
+
+ (defun jao-exwm-pdf-enable-zathura ()
+ (interactive)
+ (add-hook 'kill-emacs-query-functions #'jao-exwm-pdf-zathura-close-all)
+ (setq jao-org-open-pdf-fun #'jao-zathura-open-doc)
+ (setq jao-org-links-pdf-store-fun #'jao-exwm-org-store-zathura-link)
+ (setq jao-open-doc-fun #'jao-zathura-open-doc))
+
+ (defun jao-exwm-pdf-disable-zathura ()
+ (interactive)
+ (remove-hook 'kill-emacs-query-functions #'jao-exwm-pdf-zathura-close-all)
+ (setq jao-org-open-pdf-fun nil)
+ (setq jao-org-links-pdf-store-fun nil)
+ (setq jao-open-doc-fun #'jao-find-or-open))
+
+ (when (not jao-browse-doc-use-emacs-p)
+ (jao-exwm-pdf-enable-zathura))
+
+ #+end_src
+* Hydras
+ #+begin_src emacs-lisp
+ (major-mode-hydra-define pdf-view-mode nil
+ ("Elsewhere"
+ (("b" (jao-buffer-same-mode 'pdf-view-mode) "other PDFs")
+ ("o" jao-org-pdf-goto-org "notes file")
+ ("O" (jao-org-pdf-goto-org 4) "notes file, linking"))
+ "External"
+ (("p" doc-view-presentation "presentation")
+ ("z" jao-exwm-open-with-zathura "open with zathura")
+ ("m" jao-exwm-open-with-mupdf "open with mupdf"))))
+
+ (defhydra jao-hydra-float (:color blue)
+ "Float"
+ ("f" exwm-floating-toggle-floating "float")
+ ("F" exwm-layout-toggle-fullscreen "full")
+ ("tl" (jao-exwm--float-to 20 20))
+ ("tr" (jao-exwm--float-to -20 20))
+ ("bl" (jao-exwm--float-to 20 -20))
+ ("br" (jao-exwm--float-to -20 -20))
+ ("c" jao-exwm--center-float)
+ ("k" (exwm-floating-move 0 -5) :color red)
+ ("j" (exwm-floating-move 0 5) :color red)
+ ("h" (exwm-floating-move -5 0) :color red)
+ ("l" (exwm-floating-move 5 0) :color red)
+ ("K" (exwm-layout-enlarge-window 5) :color red)
+ ("J" (exwm-layout-enlarge-window -5) :color red)
+ ("H" (exwm-layout-enlarge-window 5 t) :color red)
+ ("L" (exwm-layout-enlarge-window -5 t) :color red)
+ ("q" nil ""))
+
+ (pretty-hydra-define jao-hydra-exwm-misc (:color blue :quit-key "q")
+ ("Jump around"
+ (("s" jao-slack-download "slack downloads")
+ ("h" (jao-buffer-same-mode 'helpful) "helpful buffer")
+ ("g" exwm-workspace-switch nil))
+ "X-Windows"
+ (("f" exwm-floating-toggle-floating "toggle floating window")
+ ("F" exwm-layout-toggle-fullscreen "toggle fullscreen mode")
+ ("m" exwm-workspace-move-window nil))
+ "Zathura"
+ (("o" jao-exwm-pdf-goto-org "Go to org notes")
+ ("O" (jao-exwm-pdf-goto-org t) "Go to org notes, linking"))
+ "Exwm utilities"
+ (("k" exwm-input-release-keyboard "release keyboard")
+ ("x" exwm-reset "reset exwm"))))
+
+ (pretty-hydra-define jao-hydra-exwm
+ (global-map "s-w" :color blue :quit-key "q")
+ ("Notes"
+ (("n" org-roam-capture "capture note")
+ ("N" org-roam-find-file-immediate "go to note"))
+ "Packages"
+ (("a" jao-vterm-aptitude "aptitude")
+ ("l" jao-exwm-paradox "package list")
+ ("s-w" jao-hydra-exwm/body nil))
+ "Network"
+ (("s" jao-ssh "ssh")
+ ("b" jao-exwm-bluetooth "bluetooth")
+ ;; ("N" jao-exwm-enwc "networks")
+ )
+ "Proton"
+ (("v" jao-exwm-proton-vpn "proton vpn")
+ ("m" run-proton-bridge "proton bridge"))
+ "Monitors"
+ (("p" jao-vterm-htop "htop")
+ ("P" jao-exwm-proced "proced")
+ ("t" jao-time-echo-times "current time"))
+ "Apps"
+ (("f" jao-exwm-firefox-1 "firefox")
+ ("x" jao-exwm-xmobar "restart xmobar")
+ ("X" jao-exwm-kill-xmobar "kill xmobar"))
+ "Looks"
+ (("T" jao-toggle-transparency "toggle transparency"
+ :toggle (jao-transparent-p) :color red)
+ ("w" jao-set-wallpaper "set wallpaper")
+ ("W" jao-set-random-wallpaper "set radom wallpaper"))
+ "Helpers"
+ (("r" org-reveal "org reveal")
+ ("k" jao-kb-toggle "toggle keyboard"
+ :toggle (jao-kb-toggled-p) :color red)
+ ("M" jao-minibuffer-toggle "toggle minibuffer"
+ :toggle jao-minibuffer-enabled-p))))
+ #+end_src
+* Keybindings
+ #+BEGIN_SRC emacs-lisp
+ (defun jao-exwm-x-kbs ()
+ (when (and exwm-class-name (string= exwm-class-name "XTerm"))
+ (exwm-input-set-local-simulation-keys '(([?\C-c ?\C-c] . [?\C-c])
+ ([?\C-x ?\C-c] . [?\C-c])))))
+
+ ;; (add-hook 'exwm-manage-finish-hook #'jao-exwm-x-kbs)
+
+ ;; To add a key binding only available in line-mode, simply define it in
+ ;; `exwm-mode-map'. The following example shortens 'C-c q' to 'C-q'.
+ (define-key exwm-mode-map [?\C-q] #'exwm-input-send-next-key)
+ (define-key exwm-mode-map [?\s-k] #'exwm-input-release-keyboard)
+ (define-key exwm-mode-map [?\s-f] #'jao-hydra-float/body)
+ (define-key exwm-mode-map [?\s-m] #'jao-hydra-media/body)
+ (define-key exwm-mode-map [?\s-s] #'jao-hydra-spotify/body)
+ (define-key exwm-mode-map [?\s-w] #'jao-hydra-exwm/body)
+ (define-key exwm-mode-map [?\s-p] #'jao-exwm-pdf-goto-org)
+ (define-key exwm-mode-map [?\s-P] #'jao-exwm-pdf-goto-org*)
+ ;; (define-key exwm-mode-map [?\s-w] #'jao-hydra-exwm/body)
+ (setq
+ exwm-input-global-keys
+ '(([?\s-0] . jao-afio--goto-scratch)
+ ([?\s-1] . jao-afio--goto-main)
+ ([?\s-2] . jao-afio--goto-gnus)
+ ([?\s-3] . jao-afio--goto-w3m)
+ ([?\s-4] . jao-afio--goto-docs)
+ ([?\s-A] . org-agenda-list)
+ ([?\s-a] . jao-first-window)
+ ([?\s-b] . jao-hydra-org-blog/body)
+ ([?\s-c] . jao-hydra-chats/body)
+ ([?\s-r] . counsel-linux-app)
+ ([?\s-t] . jao-vterm-here-toggle)
+ ([?\s-n] . jao-hydra-ednc/body)
+ ([?\s-O] . ace-swap-window)
+ ([?\s-o] . ace-window)
+ ([?\s-x] . jao-hydra-exwm-misc/body)
+ ([?\s-z] . jao-hydra-sleep/body)
+ ([XF86AudioMute] . jao-mixer-master-toogle)
+ ([XF86AudioPlay] . jao-player-toggle)
+ ([XF86AudioPause] . jao-player-toggle)
+ ([XF86AudioNext] . jao-player-next)
+ ([XF86AudioPrev] . jao-player-previous)
+ ([XF86AudioRaiseVolume] . jao-mixer-master-up)
+ ([XF86AudioLowerVolume] . jao-mixer-master-dow)
+ ([XF86MonBrightnessUp] . jao-bright-up)
+ ([XF86MonBrightnessDown] . jao-bright-down)
+ ([?\s-\`] . jao-exwm-switch-to-next-x)
+ ([s-tab] . jao-exwm-switch-to-next-class)
+ ([print] . jao-exwm-import-screen)))
+
+ ;; (customize-set-variable 'exwm-input-global-keys exwm-input-global-keys)
+
+ #+END_SRC