EWM - Emacs Wayland Manager setup, dynamic tabs setup v1
This commit is contained in:
parent
dc38d0dec3
commit
c52e577181
196
init.el
196
init.el
|
|
@ -865,6 +865,202 @@
|
|||
:config
|
||||
(setq prettier-js-use-modules-bin t))
|
||||
|
||||
;; Emacs desktop environment
|
||||
; Emacs Wayland Manager (EWM)
|
||||
(when (and (executable-find "ewm-launch") (string= (getenv "XDG_SESSION_DESKTOP") "ewm"))
|
||||
; Dynamic Tab (Workspace) Setup
|
||||
(use-package tab-line
|
||||
:ensure nil)
|
||||
(setq tab-bar-show 1) ; Hide the bar if only 1 tab exists
|
||||
(setq tab-bar-new-tab-choice "*scratch*")
|
||||
|
||||
(defun dynamic-tab-ensure-scratch-tab ()
|
||||
"Ensures there is always a tab dedicated to *scratch*."
|
||||
(let* ((tabs (funcall tab-bar-tabs-function))
|
||||
(tab-names (mapcar (lambda (tab) (alist-get 'name tab)) tabs))
|
||||
(spare-exists (member "dynamic *scratch*" tab-names))
|
||||
(is-child-frame (frame-parent)))
|
||||
|
||||
;; If we are currently IN the spare tab and it's not *scratch* anymore,
|
||||
;; or if we just want to ensure it exists at the end:
|
||||
(unless (or spare-exists is-child-frame)
|
||||
(let ((current-tab (tab-bar--current-tab-index)))
|
||||
(tab-bar-new-tab 999)
|
||||
(tab-bar-rename-tab "dynamic *scratch*")
|
||||
;; Return to original tab if we were just initializing
|
||||
(tab-bar-select-tab (1+ current-tab))))))
|
||||
|
||||
(defun dynamic-tab-handle-tab-persistence ()
|
||||
"Create new tab if current scratch tab is being used."
|
||||
(when (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*")
|
||||
(unless (or (string= (buffer-name) "*scratch*") (minibufferp))
|
||||
;; User switched away from scratch in the spare tab, rename it
|
||||
(tab-bar-rename-tab "")))
|
||||
;; and create a new spare.
|
||||
(dynamic-tab-ensure-scratch-tab))
|
||||
|
||||
(defvar already-redirecting-p nil)
|
||||
(defun dynamic-tab-redirect-to-scratch-tab (&rest _)
|
||||
"Redirect to dedicated scratch tab if scratch buffer accessed on other tab."
|
||||
(when (and (not already-redirecting-p)
|
||||
(string= (buffer-name) "*scratch*")
|
||||
(not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*")))
|
||||
(setq already-redirecting-p t)
|
||||
(unwind-protect
|
||||
(switch-to-buffer nil)
|
||||
(tab-bar-select-tab-by-name "dynamic *scratch*")
|
||||
(setq already-redirecting-p nil))))
|
||||
|
||||
(defun dynamic-tab-handle-buffer-check-and-close-tab ()
|
||||
"Check if we need to close the tab and action accordingly."
|
||||
(let* ((is-last-tab (<= (length (tab-bar-tabs)) 2))
|
||||
(is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2)))
|
||||
(when (and (not is-last-tab) is-last-buffer)
|
||||
(tab-close))))
|
||||
|
||||
(defun dynamic-tab-handle-tab-cleanup-kill (orig-fun &rest args)
|
||||
"Free tab if all reserved in use buffers for that tab killed."
|
||||
(let* ((is-last-tab (<= (length (tab-bar-tabs)) 2))
|
||||
(is-child-buffer (frame-parent))
|
||||
(is-mini-buffer (minibufferp))
|
||||
(is-dynamic-buffer (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*"))
|
||||
(is-scratch-buffer (string= (alist-get 'name (tab-bar--current-tab)) "*scratch*"))
|
||||
(is-last-buffer (<= (length (tab-line-tabs-window-buffers)) 2))
|
||||
(is-overriden (nth 1 args))
|
||||
(is-target-focused (and (eq (current-buffer) (car args))))
|
||||
(is-called-interactively (called-interactively-p 'any)))
|
||||
|
||||
(cond
|
||||
((and (not is-overriden) (not is-called-interactively)) (apply orig-fun args))
|
||||
(is-child-buffer nil)
|
||||
(is-mini-buffer nil)
|
||||
(is-dynamic-buffer nil)
|
||||
(is-scratch-buffer nil)
|
||||
((and (not is-overriden) is-called-interactively) (apply orig-fun (nbutlast args)))
|
||||
|
||||
((and is-last-tab is-last-buffer) (apply orig-fun (nbutlast args)))
|
||||
((and is-last-tab (not is-last-buffer)) (apply orig-fun (nbutlast args)))
|
||||
;((and is-last-tab (not is-last-buffer) (bury-buffer)))
|
||||
|
||||
((and (not is-last-tab) (not is-last-buffer) (bury-buffer)))
|
||||
|
||||
(t nil))
|
||||
|
||||
(when (and (not is-overriden) is-target-focused)
|
||||
(dynamic-tab-handle-buffer-check-and-close-tab))))
|
||||
|
||||
(defun dynamic-tab-handle-tab-cleanup-close (&rest _)
|
||||
"Free tab if last window open is attempted to be closed."
|
||||
(if (and (> (length (tab-bar-tabs)) 2)
|
||||
(= (length (window-list)) 1)
|
||||
(not (string= (alist-get 'name (tab-bar--current-tab)) "dynamic *scratch*")))
|
||||
(tab-close)
|
||||
t))
|
||||
|
||||
;; Helper functions for EWM
|
||||
; Switch monitor
|
||||
(defun ewm-switch-to-monitor (target)
|
||||
(interactive)
|
||||
(select-frame-set-input-focus (car (last (seq-filter (lambda (f)
|
||||
(string= target
|
||||
(cdr (assq 'name (frame-monitor-attributes f)))))
|
||||
(frame-list))))))
|
||||
|
||||
; EWM - Emacs Wayland Manager
|
||||
(use-package ewm
|
||||
:ensure nil
|
||||
:custom
|
||||
(ewm-output-config
|
||||
'(("DP-1"
|
||||
:width 1920
|
||||
:height 1080
|
||||
:scale 1.0
|
||||
:x 0
|
||||
:y 0
|
||||
:refresh 240)
|
||||
("HDMI-A-1"
|
||||
:width 1920
|
||||
:height 1080
|
||||
:scale 1.0
|
||||
:x 1920
|
||||
:y 0
|
||||
:transform 3
|
||||
:refresh 75)))
|
||||
(ewm-input-config
|
||||
'((touchpad :natural-scroll t :tap t :dwt t)
|
||||
(mouse :accel-profile "flat")
|
||||
(keyboard :repeat-delay 150 :repeat-rate 35
|
||||
:xkb-layouts "gb")))
|
||||
;; Per-device override (exact name from libinput)
|
||||
;("ELAN0676:00 04F3:3195 Touchpad" :tap nil :accel-speed -0.2)))
|
||||
:bind (:map ewm-mode-map
|
||||
("M-d" . ewm-launch-app)
|
||||
("s-l" . ewm-lock-session)
|
||||
("M-<return>" . eshell)
|
||||
("<print>" . (lambda ()
|
||||
(interactive)
|
||||
(start-process-shell-command
|
||||
"screenshot-process"
|
||||
nil
|
||||
"grim -g \"$(slurp)\" - | wl-copy")))
|
||||
("M-w" . (lambda ()
|
||||
(interactive)
|
||||
(kill-buffer)))
|
||||
|
||||
; Monitor switching, find current focused monitor name via
|
||||
;(cdr (assq 'name (frame-monitor-attributes))
|
||||
("M-o" . (lambda ()
|
||||
(interactive)
|
||||
(ewm-switch-to-monitor "XG2431")))
|
||||
("M-p" . (lambda ()
|
||||
(interactive)
|
||||
(ewm-switch-to-monitor "24B2W1G5")))
|
||||
|
||||
;;("M-f" . (lambda ()
|
||||
;; (interactive)
|
||||
;; (start-process-shell-command
|
||||
;; "wlkbptr-process"
|
||||
;; nil
|
||||
;; "wl-kbptr -o modes=floating,click -o mode_floating.source=detect"))
|
||||
|
||||
("M-h" . tab-bar-switch-to-prev-tab)
|
||||
("M-l" . tab-bar-switch-to-next-tab)
|
||||
("M-k" . windmove-up)
|
||||
("M-j" . windmove-down))
|
||||
:config
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-d)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-w)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-o)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-p)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-h)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-j)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-k)
|
||||
(add-to-list 'ewm-intercept-prefixes ?\M-l)
|
||||
:init
|
||||
;; Dynamic Tabs/Workspaces setup
|
||||
; Hooks
|
||||
(advice-add 'consult-buffer
|
||||
:after (lambda (&rest _)
|
||||
(dynamic-tab-handle-tab-persistence)
|
||||
(dynamic-tab-redirect-to-scratch-tab)))
|
||||
(advice-add 'delete-window :before-while #'dynamic-tab-handle-tab-cleanup-close)
|
||||
(advice-add 'kill-buffer :around #'dynamic-tab-handle-tab-cleanup-kill)
|
||||
;(add-hook 'buffer-list-update-hook #'dynamic-tab-redirect-to-scratch-tab)
|
||||
(add-hook 'window-configuration-change-hook #'dynamic-tab-handle-tab-persistence)
|
||||
; Initialize on startup
|
||||
(dynamic-tab-ensure-scratch-tab))
|
||||
|
||||
; Desktop notifications in Emacs
|
||||
(use-package ednc
|
||||
:ensure t
|
||||
:init
|
||||
(ednc-mode)))
|
||||
;(use-package ednc-popup
|
||||
; :ensure (:host git :repo "https://codeberg.org/akib/emacs-ednc-popup.git")
|
||||
; :after ednc
|
||||
; :config
|
||||
; (add-hook 'ednc-notification-presentation-functions
|
||||
; #'ednc-popup-presentation-function))
|
||||
|
||||
(custom-set-variables
|
||||
;; custom-set-variables was added by Custom.
|
||||
|
|
|
|||
Loading…
Reference in New Issue