jao-wayland.el 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. ;;; jao-wayland.el --- interacting with wayland compositors -*- lexical-binding: t; -*-
  2. ;; Copyright (C) 2022, 2023 jao
  3. ;; Author: jao <mail@jao.io>
  4. ;; Keywords: convenience
  5. ;; This program is free software; you can redistribute it and/or modify
  6. ;; it under the terms of the GNU General Public License as published by
  7. ;; the Free Software Foundation, either version 3 of the License, or
  8. ;; (at your option) any later version.
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. (require 'jao-shell)
  16. (require 'jao-pdf)
  17. (require 'jao-tracking)
  18. ;;; wayland
  19. (defvar jao-wayland-enabled
  20. (string= "wayland" (or (getenv "XDG_SESSION_TYPE") "")))
  21. (defsubst jao-wayland-type (&rest args)
  22. (apply #'jao-shell-exec* t "wtype" args))
  23. ;;; river
  24. (defvar jao-river-enabled (jao-shell-running-p "river"))
  25. (defun jao-river-enabled-p () jao-river-enabled)
  26. (defsubst jao-river-to-ws (n)
  27. (jao-wayland-type "-M" "win" (format "%s" n)))
  28. (defsubst jao-river-window-list ()
  29. (alist-get 'toplevels
  30. (jao-shell-output "lswt -j"
  31. (lambda ()
  32. (let ((json-false nil)) (json-read))))))
  33. (defun jao-river-focused ()
  34. (seq-some (lambda (w) (and (alist-get 'activated w) w))
  35. (jao-river-window-list)))
  36. (defsubst jao-river-get-focused-title ()
  37. (alist-get 'title (jao-river-focused)))
  38. (defsubst jao-river-get-focused-app-id ()
  39. (alist-get 'app-id (jao-river-focused)))
  40. (defun jao-river-focus-window (title &optional rx)
  41. (let* ((ws (jao-river-window-list))
  42. (fltr (if rx #'string-match-p #'string=))
  43. (w (seq-find (lambda (w)
  44. (or (funcall fltr title (alist-get 'app_id w ""))
  45. (funcall fltr title (alist-get 'title w ""))))
  46. ws)))
  47. (or (alist-get 'activated w)
  48. (seq-some (lambda (_ignored)
  49. (jao-shell-exec "riverctl focus-view next" t)
  50. (or (funcall fltr title (jao-river-get-focused-app-id))
  51. (funcall fltr title (jao-river-get-focused-title))))
  52. (and w ws)))))
  53. (defun jao-river-zathura-to-org ()
  54. (let ((title (jao-river-get-focused-title)))
  55. (jao-river-to-ws 1)
  56. (jao-org-open-from-zathura title t)))
  57. (defun jao-river-zathura-kill-link ()
  58. (when-let* ((title (jao-river-get-focused-title))
  59. (lnk (jao-pdf-zathura-org-link title)))
  60. (jao-river-to-ws 1)
  61. (kill-new lnk)
  62. (message "Link to %s killed" title)))
  63. (defun jao-river-find-zathura-window (file)
  64. (let ((frx (regexp-quote (file-name-nondirectory file))))
  65. (seq-some (lambda (w)
  66. (and (string-suffix-p ".zathura" (alist-get 'app_id w ""))
  67. (string-match-p frx (alist-get 'title w ""))
  68. w))
  69. (jao-river-window-list))))
  70. (defun jao-river-open-with-zathura (file page)
  71. (let ((wd (jao-river-find-zathura-window file)))
  72. (jao-river-to-ws 3)
  73. (or (and wd (jao-river-focus-window (alist-get 'title wd)))
  74. (jao-shell-exec* "riverctl" "spawn" (jao-pdf-zathura-open-cmd file page)))
  75. (when page (sit-for 0.2) (jao-wayland-type (format "%dg" page)))))
  76. (defun jao-river-set-wallpaper (f)
  77. (jao-shell-kill-p "swaybg")
  78. (jao-shell-exec* "riverctl" "spawn" (concat "swaybg -m fill -i " f)))
  79. (defun jao-river-restart-i3bar ()
  80. (interactive)
  81. (jao-shell-kill-p "i3bar-river")
  82. (jao-shell-exec "riverctl spawn i3bar-river")
  83. (sit-for 0.2)
  84. (jao-tracking-set-log ""))
  85. (defun jao-river-toggle-emacs ()
  86. (let ((erx "^p?emacs\\(client\\)?\\|\\(.* - emacs\\)"))
  87. (if (or (string-match-p erx (jao-river-get-focused-title))
  88. (string-match-p erx (jao-river-get-focused-app-id)))
  89. (jao-shell-exec "riverctl focus-previous-tags")
  90. (jao-river-to-ws 1)
  91. (unless (jao-river-focus-window erx t)
  92. (jao-shell-exec* "riverctl" "spawn" "efoot")))))
  93. (defun jao-river-toggle-firefox ()
  94. (if (string-match-p "Firefox" (or (jao-river-get-focused-app-id) ""))
  95. (jao-river-to-ws 1)
  96. (jao-river-to-ws 2)
  97. (unless (jao-river-focus-window "Firefox")
  98. (jao-shell-exec* "riverctl" "spawn" "firefox"))))
  99. ;;; sway
  100. (defun jao-sway-msg (msg)
  101. (shell-command (format "swaymsg '%s' >/dev/null" msg)))
  102. (defmacro jao-def-swaymsg (name msg)
  103. `(defun ,(intern (format "jao-sway-%s" name)) ()
  104. (interactive)
  105. (jao-sway-msg ,msg)))
  106. (jao-def-swaymsg firefox "[app_id=Firefox] focus")
  107. (jao-def-swaymsg pemacs "[app_id=pemacs] focus")
  108. (defvar jao-sway-enabled (jao-shell-running-p "sway"))
  109. (defconst jao-sway-get-active-title
  110. "swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).name'")
  111. (defconst jao-sway-get-active-app
  112. "swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).app_id'")
  113. (defun jao-sway-get-active-title ()
  114. (let ((tl (jao-shell-string jao-sway-get-active-title)))
  115. (and (string-match "\"\\(.+\\)\"" tl) (match-string 1 tl))))
  116. (defun jao-sway-get-active-app ()
  117. (let ((tl (jao-shell-string jao-sway-get-active-app)))
  118. (and (string-match "\"\\(.+\\)\"" tl) (match-string 1 tl))))
  119. (defun jao-sway-zathura-org ()
  120. (jao-org-open-from-zathura (jao-sway-get-active-title) t))
  121. (defun jao-sway-open-with-zathura (file page)
  122. (let* ((n (file-name-nondirectory file))
  123. (m (format "[title=\"%s\" app_id=\".*zathura\"] focus" n)))
  124. (jao-sway-msg "workspace number 3")
  125. (unless (= 0 (jao-sway-msg m))
  126. (jao-shell-exec (jao-pdf-zathura-open-cmd file page)))
  127. (when page (sit-for 0.2) (jao-wayland-type (format "%dg" page)))))
  128. (defun jao-sway-set-wallpaper (f)
  129. (jao-sway-msg (format "output * bg %s fill" f)))
  130. (defun jao-sway-run-or-focus (cmd &optional ws)
  131. (if (jao-shell-running-p "firefox")
  132. (jao-sway-msg (format "[app_id=%s] focus" cmd))
  133. (jao-sway-msg (format "workspace %s" (or ws 2)))
  134. (start-process-shell-command cmd nil cmd)))
  135. (defun jao-sway-run-or-focus-firefox ()
  136. (interactive)
  137. (jao-sway-run-or-focus "firefox"))
  138. (defun jao-sway-toggle-emacs ()
  139. (if (string-match-p "p?emacs" (jao-sway-get-active-app))
  140. (jao-sway-firefox)
  141. (jao-sway-pemacs)))
  142. (provide 'jao-wayland)
  143. ;;; jao-wayland.el ends here