;;; jao-wayland.el --- interacting with wayland compositors -*- lexical-binding: t; -*- ;; Copyright (C) 2022, 2023 jao ;; Author: jao ;; Keywords: convenience ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . (require 'jao-shell) (require 'jao-pdf) (require 'jao-tracking) ;;; wayland (defvar jao-wayland-enabled (string= "wayland" (or (getenv "XDG_SESSION_TYPE") ""))) (defsubst jao-wayland-type (&rest args) (apply #'jao-shell-exec* t "wtype" args)) ;;; river (defvar jao-river-enabled (jao-shell-running-p "river")) (defun jao-river-enabled-p () jao-river-enabled) (defsubst jao-river-to-ws (n) (jao-wayland-type "-M" "win" (format "%s" n))) (defsubst jao-river-window-list () (alist-get 'toplevels (jao-shell-output "lswt -j" (lambda () (let ((json-false nil)) (json-read)))))) (defun jao-river-focused () (seq-some (lambda (w) (and (alist-get 'activated w) w)) (jao-river-window-list))) (defsubst jao-river-get-focused-title () (alist-get 'title (jao-river-focused))) (defsubst jao-river-get-focused-app-id () (alist-get 'app-id (jao-river-focused))) (defun jao-river-focus-window (title &optional rx) (let* ((ws (jao-river-window-list)) (fltr (if rx #'string-match-p #'string=)) (w (seq-find (lambda (w) (or (funcall fltr title (alist-get 'app_id w "")) (funcall fltr title (alist-get 'title w "")))) ws))) (or (alist-get 'activated w) (seq-some (lambda (_ignored) (jao-shell-exec "riverctl focus-view next" t) (or (funcall fltr title (jao-river-get-focused-app-id)) (funcall fltr title (jao-river-get-focused-title)))) (and w ws))))) (defun jao-river-zathura-to-org () (let ((title (jao-river-get-focused-title))) (jao-river-to-ws 1) (jao-org-open-from-zathura title t))) (defun jao-river-zathura-kill-link () (when-let* ((title (jao-river-get-focused-title)) (lnk (jao-pdf-zathura-org-link title))) (jao-river-to-ws 1) (kill-new lnk) (message "Link to %s killed" title))) (defun jao-river-find-zathura-window (file) (let ((frx (regexp-quote (file-name-nondirectory file)))) (seq-some (lambda (w) (and (string-suffix-p ".zathura" (alist-get 'app_id w "")) (string-match-p frx (alist-get 'title w "")) w)) (jao-river-window-list)))) (defun jao-river-open-with-zathura (file page) (let ((wd (jao-river-find-zathura-window file))) (jao-river-to-ws 3) (or (and wd (jao-river-focus-window (alist-get 'title wd))) (jao-shell-exec* "riverctl" "spawn" (jao-pdf-zathura-open-cmd file page))) (when page (sit-for 0.2) (jao-wayland-type (format "%dg" page))))) (defun jao-river-set-wallpaper (f) (jao-shell-kill-p "swaybg") (jao-shell-exec* "riverctl" "spawn" (concat "swaybg -m fill -i " f))) (defun jao-river-restart-i3bar () (interactive) (jao-shell-kill-p "i3bar-river") (jao-shell-exec "riverctl spawn i3bar-river") (sit-for 0.2) (jao-tracking-set-log "")) (defun jao-river-toggle-emacs () (let ((erx "^p?emacs\\(client\\)?\\|\\(.* - emacs\\)")) (if (or (string-match-p erx (jao-river-get-focused-title)) (string-match-p erx (jao-river-get-focused-app-id))) (jao-shell-exec "riverctl focus-previous-tags") (jao-river-to-ws 1) (unless (jao-river-focus-window erx t) (jao-shell-exec* "riverctl" "spawn" "efoot"))))) (defun jao-river-toggle-firefox () (if (string-match-p "Firefox" (or (jao-river-get-focused-app-id) "")) (jao-river-to-ws 1) (jao-river-to-ws 2) (unless (jao-river-focus-window "Firefox") (jao-shell-exec* "riverctl" "spawn" "firefox")))) ;;; sway (defun jao-sway-msg (msg) (shell-command (format "swaymsg '%s' >/dev/null" msg))) (defmacro jao-def-swaymsg (name msg) `(defun ,(intern (format "jao-sway-%s" name)) () (interactive) (jao-sway-msg ,msg))) (jao-def-swaymsg firefox "[app_id=Firefox] focus") (jao-def-swaymsg pemacs "[app_id=pemacs] focus") (defvar jao-sway-enabled (jao-shell-running-p "sway")) (defconst jao-sway-get-active-title "swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).name'") (defconst jao-sway-get-active-app "swaymsg -t get_tree | jq '.. | select(.type?) | select(.focused==true).app_id'") (defun jao-sway-get-active-title () (let ((tl (jao-shell-string jao-sway-get-active-title))) (and (string-match "\"\\(.+\\)\"" tl) (match-string 1 tl)))) (defun jao-sway-get-active-app () (let ((tl (jao-shell-string jao-sway-get-active-app))) (and (string-match "\"\\(.+\\)\"" tl) (match-string 1 tl)))) (defun jao-sway-zathura-org () (jao-org-open-from-zathura (jao-sway-get-active-title) t)) (defun jao-sway-open-with-zathura (file page) (let* ((n (file-name-nondirectory file)) (m (format "[title=\"%s\" app_id=\".*zathura\"] focus" n))) (jao-sway-msg "workspace number 3") (unless (= 0 (jao-sway-msg m)) (jao-shell-exec (jao-pdf-zathura-open-cmd file page))) (when page (sit-for 0.2) (jao-wayland-type (format "%dg" page))))) (defun jao-sway-set-wallpaper (f) (jao-sway-msg (format "output * bg %s fill" f))) (defun jao-sway-run-or-focus (cmd &optional ws) (if (jao-shell-running-p "firefox") (jao-sway-msg (format "[app_id=%s] focus" cmd)) (jao-sway-msg (format "workspace %s" (or ws 2))) (start-process-shell-command cmd nil cmd))) (defun jao-sway-run-or-focus-firefox () (interactive) (jao-sway-run-or-focus "firefox")) (defun jao-sway-toggle-emacs () (if (string-match-p "p?emacs" (jao-sway-get-active-app)) (jao-sway-firefox) (jao-sway-pemacs))) (provide 'jao-wayland) ;;; jao-wayland.el ends here