diff --git a/config.el b/config.el index 9d55071..62ee3f9 100644 --- a/config.el +++ b/config.el @@ -698,79 +698,96 @@ Skips past the TODO keyword and optional priority indicator [#A]." ;;; ============================================================ ;;; ACCESSIBILITY — GLOBAL TEXT SCALING (SPC z) ;;; ============================================================ -;; Uses `default-text-scale` for true global scaling (face remapping on all -;; frames). Unlike `text-scale-mode` this affects every buffer, minibuffer, -;; popup, which-key, corfu, and transient menu uniformly. +;; Uses per-buffer `text-scale-mode' applied to ALL buffers simultaneously. +;; Unlike `default-text-scale', this scales ONLY buffer text. +;; Modeline, minibuffer, which-key, corfu popups stay at base size +;; and remain fully visible and usable even at very high zoom levels. +;; +;; Step: ×1.5 per step (multiplicative). From 14pt base: +;; +1 → ×1.5 ≈ 21pt +2 → ×2.25 ≈ 32pt +;; +3 → ×3.4 ≈ 47pt +4 → ×5.1 ≈ 71pt +;; +5 → ×7.6 ≈ 106pt +;; +;; SPC z + / SPC z = zoom in +;; SPC z - zoom out +;; SPC z 0 reset to default (saves for restore) +;; SPC z z restore previous zoom -(use-package! default-text-scale - :config - (setq default-text-scale-amount 10)) ; 10 units = 1pt +(setq text-scale-mode-step 1.5) -(defvar my/zoom-total-delta 0 - "Cumulative face-height delta applied by global zoom (in face units).") +(defvar my/zoom-steps 0 + "Current global zoom step count. 0 = default, positive = bigger.") -(defvar my/zoom-saved-delta nil - "Saved delta before last reset, used by `my/zoom-restore'.") +(defvar my/zoom-saved-steps nil + "Step count saved before last `my/zoom-reset', for restore.") -(defvar my/zoom-min-height 80 - "Minimum face height (in units, 80 = 8pt). Zoom out stops here.") +(defun my/zoom--apply-all (steps) + "Apply text-scale of STEPS to every live buffer." + (dolist (buf (buffer-list)) + (when (buffer-live-p buf) + (with-current-buffer buf + (text-scale-set steps))))) -(defun my/zoom--current-height () - "Return the current default face height including zoom delta." - (face-attribute 'default :height)) +(defun my/zoom--auto-apply () + "Apply current zoom to newly opened/switched buffers." + (unless (= my/zoom-steps 0) + (text-scale-set my/zoom-steps))) -(defun my/zoom--msg () - "Display current effective font size in pt." - (let ((h (my/zoom--current-height))) - (message "Zoom: %s pt (delta %+d)" - (/ h 10) - my/zoom-total-delta))) +;; Hook: apply zoom when a new buffer gets a major mode (covers find-file, +;; new scratch buffers, magit, org-agenda, help, etc.) +(add-hook 'after-change-major-mode-hook #'my/zoom--auto-apply) (defun my/zoom-in () - "Increase global font size by 1 pt." + "Zoom in one step (×1.5) across all buffers." (interactive) - (default-text-scale-increase) - (cl-incf my/zoom-total-delta default-text-scale-amount) - (my/zoom--msg)) + (cl-incf my/zoom-steps) + (my/zoom--apply-all my/zoom-steps) + (message "Zoom +%d (×%.2f ≈%dpt)" + my/zoom-steps + (expt text-scale-mode-step my/zoom-steps) + (round (* 14 (expt text-scale-mode-step my/zoom-steps))))) (defun my/zoom-out () - "Decrease global font size by 1 pt (respects minimum)." + "Zoom out one step (÷1.5) across all buffers." (interactive) - (let ((new-height (- (my/zoom--current-height) default-text-scale-amount))) - (if (< new-height my/zoom-min-height) - (message "Zoom: already at minimum (%d pt)" (/ (my/zoom--current-height) 10)) - (default-text-scale-decrease) - (cl-decf my/zoom-total-delta default-text-scale-amount) - (my/zoom--msg)))) + (cl-decf my/zoom-steps) + (my/zoom--apply-all my/zoom-steps) + (message "Zoom %d (×%.2f ≈%dpt)" + my/zoom-steps + (expt text-scale-mode-step my/zoom-steps) + (round (* 14 (expt text-scale-mode-step my/zoom-steps))))) (defun my/zoom-reset () - "Reset zoom to default size. Saves current delta for restore." + "Reset all buffers to default text size. Saves current step for restore." (interactive) - (if (= my/zoom-total-delta 0) - (message "Zoom: already at default size") - (setq my/zoom-saved-delta my/zoom-total-delta) - (default-text-scale-reset) - (setq my/zoom-total-delta 0) - (message "Zoom: reset to default (saved %+d for restore)" - my/zoom-saved-delta))) + (if (= my/zoom-steps 0) + (message "Zoom: already at default") + (setq my/zoom-saved-steps my/zoom-steps) + (my/zoom--apply-all 0) + (setq my/zoom-steps 0) + (message "Zoom reset to default (was %+d — SPC z z to restore)" + my/zoom-saved-steps))) (defun my/zoom-restore () - "Restore the zoom level saved before last reset." + "Restore zoom level saved before last reset." (interactive) - (if (null my/zoom-saved-delta) + (if (null my/zoom-saved-steps) (message "Zoom: nothing to restore") - (default-text-scale-adjust my/zoom-saved-delta) - (setq my/zoom-total-delta my/zoom-saved-delta) - (setq my/zoom-saved-delta nil) - (my/zoom--msg))) + (my/zoom--apply-all my/zoom-saved-steps) + (setq my/zoom-steps my/zoom-saved-steps + my/zoom-saved-steps nil) + (message "Zoom restored: %+d (×%.2f ≈%dpt)" + my/zoom-steps + (expt text-scale-mode-step my/zoom-steps) + (round (* 14 (expt text-scale-mode-step my/zoom-steps)))))) (map! :leader (:prefix ("z" . "zoom") - :desc "Zoom in" "+" #'my/zoom-in - :desc "Zoom in" "=" #'my/zoom-in - :desc "Zoom out" "-" #'my/zoom-out - :desc "Reset zoom" "0" #'my/zoom-reset - :desc "Restore zoom" "z" #'my/zoom-restore)) + :desc "Zoom in (×1.5/krok)" "+" #'my/zoom-in + :desc "Zoom in (×1.5/krok)" "=" #'my/zoom-in + :desc "Zoom out (÷1.5/krok)" "-" #'my/zoom-out + :desc "Reset na výchozí" "0" #'my/zoom-reset + :desc "Restore předchozí zoom" "z" #'my/zoom-restore)) ;;; ============================================================ diff --git a/packages.el b/packages.el index 9da0ab8..19f8d3f 100644 --- a/packages.el +++ b/packages.el @@ -74,5 +74,3 @@ (package! org-pandoc-import :recipe (:host github :repo "tecosaur/org-pandoc-import")) -;; Global text scaling for accessibility -(package! default-text-scale)