chore: remove split-screen magnifier (blind alley)

This commit is contained in:
2026-02-22 23:17:10 +01:00
parent b8889cfa06
commit 21c7142d07

239
config.el
View File

@@ -814,237 +814,6 @@ Keeps the status bar and tab bar fully visible at any zoom level.")
my/zoom-saved-steps nil)))
;;; ============================================================
;;; ACCESSIBILITY — SPLIT-SCREEN MAGNIFIER (SPC z m)
;;; ============================================================
;; Pure Emacs-native split-screen magnifier. Žádné externí procesy, žádné macOS API.
;;
;; Architektura:
;; LEFT pane (40%): normální editace — zde pracuješ
;; RIGHT pane (60%): zvětšený pohled — indirect buffer, sleduje cursor
;;
;; Funkce:
;; - Sleduje cursor v aktivním okně (post-command-hook + buffer-list-update-hook)
;; - Přepíná automaticky při změně bufferu/okna
;; - SPC z + / SPC z = zoom in (jen magnifier, ne globálně)
;; - SPC z - zoom out (jen magnifier)
;; - SPC z 0 reset zoom magnifieru na výchozí
;; - SPC z m toggle on/off
;; - Kurzor v magnifier pane viditelný (hollow cursor v non-selected windows)
;; - Magnifier pane je dedicated — Emacs do něj neotevírá jiné buffery
;; - Správné cleanup při window close, buffer kill, workspace switch
(defvar my/mag--active nil "Non-nil when split magnifier is enabled.")
(defvar my/mag--window nil "The magnified (right) window.")
(defvar my/mag--buffer nil "Current indirect buffer for magnification.")
(defvar my/mag--source nil "Buffer currently being magnified.")
(defvar my/mag--zoom-level 4 "Current text-scale-set value for magnifier (4 ≈ 2× default).")
(defvar my/mag--zoom-default 4 "Default zoom level for reset.")
(defun my/mag--kill-indirect ()
"Kill the current magnifier indirect buffer if it exists."
(when (and my/mag--buffer (buffer-live-p my/mag--buffer))
(kill-buffer my/mag--buffer))
(setq my/mag--buffer nil))
(defun my/mag--setup-mag-window ()
"Configure magnifier window display settings.
Call after `set-window-buffer' on `my/mag--window'."
(when (and my/mag--window (window-live-p my/mag--window))
(set-window-dedicated-p my/mag--window t)
(set-window-parameter my/mag--window 'no-other-window t)
(with-selected-window my/mag--window
(text-scale-set my/mag--zoom-level)
(setq-local cursor-type 'box)
(setq-local cursor-in-non-selected-windows 'hollow)
(setq-local scroll-margin 0)
(when (bound-and-true-p display-line-numbers-mode)
(display-line-numbers-mode -1))
(when (bound-and-true-p hl-line-mode)
(hl-line-mode -1)))))
(defun my/mag--valid-source-p (buf)
"Return non-nil if BUF is a valid magnifier source buffer."
(and (buffer-live-p buf)
(not (minibufferp buf))
(not (string-prefix-p " " (buffer-name buf)))
(not (string-prefix-p "*mag:" (buffer-name buf)))))
(defun my/mag--switch-source ()
"Switch magnifier to track the current buffer."
(let ((new-source (window-buffer (selected-window))))
(when (my/mag--valid-source-p new-source)
(my/mag--kill-indirect)
(setq my/mag--source new-source)
(let ((mag-name (format "*mag:%s*" (buffer-name new-source))))
;; Clean up stale buffer with same name
(when-let ((old (get-buffer mag-name)))
(kill-buffer old))
(setq my/mag--buffer (make-indirect-buffer new-source mag-name t)))
(when (and my/mag--window (window-live-p my/mag--window))
(set-window-dedicated-p my/mag--window nil) ; temporarily un-dedicate
(set-window-buffer my/mag--window my/mag--buffer)
(my/mag--setup-mag-window)))))
(defun my/mag--sync ()
"Sync magnified pane to current cursor position."
(when (and my/mag--active
my/mag--window (window-live-p my/mag--window)
(not (active-minibuffer-window))
(not (window-minibuffer-p))
(not (eq (selected-window) my/mag--window))
(not (window-parameter (selected-window) 'window-side)))
(let ((cur-buf (window-buffer (selected-window))))
;; Switch source if buffer changed (only for valid buffers)
(when (and (not (eq cur-buf my/mag--source))
(my/mag--valid-source-p cur-buf))
(my/mag--switch-source))
;; Sync point + recenter
(when (and my/mag--buffer (buffer-live-p my/mag--buffer))
(let ((pt (window-point (selected-window))))
(with-selected-window my/mag--window
(goto-char pt)
(recenter)))))))
(defun my/mag--on-window-change ()
"Clean up if magnifier window was closed by user."
(when (and my/mag--active
(not (active-minibuffer-window))
(not (and my/mag--window (window-live-p my/mag--window))))
(my/mag--disable)))
(defun my/mag--on-source-killed ()
"Handle source buffer being killed."
(when (and my/mag--active
(eq (current-buffer) my/mag--source))
;; Try to switch to another visible buffer, or disable
(let ((alt (cl-find-if
(lambda (b)
(and (not (eq b (current-buffer)))
(my/mag--valid-source-p b)))
(buffer-list))))
(if alt
(progn
(set-window-buffer (selected-window) alt)
(setq my/mag--source nil) ; force switch
(my/mag--switch-source))
(my/mag--disable)))))
(defun my/mag--enable ()
"Enable split-screen magnifier."
(delete-other-windows)
(setq my/mag--source (current-buffer))
(let ((mag-name (format "*mag:%s*" (buffer-name my/mag--source))))
;; Clean up stale buffer
(when-let ((old (get-buffer mag-name)))
(kill-buffer old))
(setq my/mag--buffer (make-indirect-buffer my/mag--source mag-name t)))
;; Split: left 40%, right 60%
(setq my/mag--window
(split-window (selected-window)
(floor (* 0.4 (window-total-width)))
'right))
(set-window-buffer my/mag--window my/mag--buffer)
(my/mag--setup-mag-window)
(setq my/mag--active t)
(add-hook 'post-command-hook #'my/mag--sync)
(add-hook 'buffer-list-update-hook #'my/mag--sync)
(add-hook 'window-configuration-change-hook #'my/mag--on-window-change)
(add-hook 'kill-buffer-hook #'my/mag--on-source-killed)
(when (boundp 'persp-activated-functions)
(add-hook 'persp-activated-functions #'my/mag--on-persp-change))
(message "Split magnifier ON (zoom %+d)" my/mag--zoom-level))
(defun my/mag--on-persp-change (&rest _)
"Disable magnifier if window is dead after workspace switch."
(when (and my/mag--active
(not (window-live-p my/mag--window)))
(my/mag--disable)))
(defun my/mag--disable ()
"Disable split-screen magnifier."
(remove-hook 'post-command-hook #'my/mag--sync)
(remove-hook 'buffer-list-update-hook #'my/mag--sync)
(remove-hook 'window-configuration-change-hook #'my/mag--on-window-change)
(remove-hook 'kill-buffer-hook #'my/mag--on-source-killed)
(when (boundp 'persp-activated-functions)
(remove-hook 'persp-activated-functions #'my/mag--on-persp-change))
(when (and my/mag--window (window-live-p my/mag--window))
(set-window-dedicated-p my/mag--window nil)
(delete-window my/mag--window))
;; Kill all *mag:* buffers
(dolist (buf (buffer-list))
(when (string-prefix-p "*mag:" (buffer-name buf))
(kill-buffer buf)))
(setq my/mag--active nil
my/mag--window nil
my/mag--buffer nil
my/mag--source nil)
(message "Split magnifier OFF"))
(defun my/mag-toggle ()
"Toggle split-screen magnifier on/off."
(interactive)
(if my/mag--active
(my/mag--disable)
(my/mag--enable)))
(defun my/mag-zoom-in ()
"Increase magnifier zoom level."
(interactive)
(when my/mag--active
(cl-incf my/mag--zoom-level)
(when (and my/mag--window (window-live-p my/mag--window))
(with-selected-window my/mag--window
(text-scale-set my/mag--zoom-level)))
(message "Magnifier zoom %+d" my/mag--zoom-level)))
(defun my/mag-zoom-out ()
"Decrease magnifier zoom level."
(interactive)
(when my/mag--active
(cl-decf my/mag--zoom-level)
(when (and my/mag--window (window-live-p my/mag--window))
(with-selected-window my/mag--window
(text-scale-set my/mag--zoom-level)))
(message "Magnifier zoom %+d" my/mag--zoom-level)))
(defun my/mag-zoom-reset ()
"Reset magnifier zoom to default."
(interactive)
(when my/mag--active
(setq my/mag--zoom-level my/mag--zoom-default)
(when (and my/mag--window (window-live-p my/mag--window))
(with-selected-window my/mag--window
(text-scale-set my/mag--zoom-level)))
(message "Magnifier zoom reset to %+d" my/mag--zoom-level)))
(defun my/mag-or-global-zoom-in ()
"Zoom in: magnifier if active, otherwise global."
(interactive)
(if my/mag--active (my/mag-zoom-in) (my/zoom-in)))
(defun my/mag-or-global-zoom-out ()
"Zoom out: magnifier if active, otherwise global."
(interactive)
(if my/mag--active (my/mag-zoom-out) (my/zoom-out)))
(defun my/mag-or-global-zoom-reset ()
"Reset zoom: magnifier if active, otherwise global."
(interactive)
(if my/mag--active (my/mag-zoom-reset) (my/zoom-reset)))
;; --------------- keybindings ---------------
(map! :leader
(:prefix ("z" . "zoom")
:desc "Zoom in (global ×1.5)" "+" #'my/mag-or-global-zoom-in
:desc "Zoom in (global ×1.5)" "=" #'my/mag-or-global-zoom-in
:desc "Zoom out (global ÷1.5)" "-" #'my/mag-or-global-zoom-out
:desc "Reset zoom" "0" #'my/mag-or-global-zoom-reset
:desc "Restore global zoom" "z" #'my/zoom-restore
:desc "Split magnifier" "m" #'my/mag-toggle))
;;; ============================================================
;;; KEYBINDINGS
@@ -1053,3 +822,11 @@ Call after `set-window-buffer' on `my/mag--window'."
(map! :leader
(:prefix ("h" . "help")
:desc "Describe bindings (buffer-local)" "B" #'describe-bindings))
(map! :leader
(:prefix ("z" . "zoom")
:desc "Zoom in (×1.5)" "+" #'my/zoom-in
:desc "Zoom in (×1.5)" "=" #'my/zoom-in
:desc "Zoom out (÷1.5)" "-" #'my/zoom-out
:desc "Reset na výchozí" "0" #'my/zoom-reset
:desc "Restore předchozí" "z" #'my/zoom-restore))