Schnelles Anpassen von Text an DPI-Änderungen

9

Mein Laptop hat einen 4K-Bildschirm und daher eine sehr hohe DPI, viel höher als meine externen Monitore. Wenn ich von der Verwendung externer Monitore zum eingebauten Laptop-Bildschirm wechsle, möchte ich den Text und, wenn möglich, alle GUI-Widgets in Emacs schnell skalieren, um sie an die neue DPI anzupassen. Ich kenne die Set-Frame-Schriftart, habe aber keine entsprechende Funktion gefunden, mit der auch die Skalierung angepasst werden kann. Und die Anpassung der Textskala funktioniert nur lokal für einen Puffer.

Nordlöw
quelle

Antworten:

7
  1. Sie können den Wert default-frame-alisteinschließlich einschließlich des fontParameters abhängig vom aktuellen Monitor / der aktuellen Anzeige bedingt einstellen . (Sie können die Funktion verwenden display-monitor-attributes-list, um die Monitor- / Anzeigeinformationen anzuzeigen.) Auf diese Weise können Sie unterschiedliche Standardschriftgrößen für verschiedene Monitore oder andere unterschiedliche Kontexte verwenden.

  2. Sie können auch Schriftgröße dynamisch ändern, für alle Fenster und Puffer in jedem Frame gezeigt, Befehl zoom-in, zoom-outoder zoom-in/out, aus der Bibliothek zoom-frm.el.

    Dieselben Befehle können entweder einen Puffer (in allen Fenstern, in einem beliebigen Frame) oder einen Frame (in allen Fenstern, unabhängig von ihrem Puffer) zoomen . Siehe Emacs-Wiki-Seite Schriftarten festlegen .

Drew
quelle
4

Ich verwende etwas Ähnliches wie @gavenkoa (rein zufällig auch mit einem Helfer namens my-dpi!), Um neue Frames auf die richtige Größe zu bringen, aber zoom-frmich rufe an, da ich dieses Paket trotzdem verwende. Es funktioniert auch bei Setups mit mehreren Köpfen, indem frame-monitor-attributesanstelle von display-monitor-attributes-list:

(defun my-dpi (&optional frame)
  "Get the DPI of FRAME (or current if nil)."
  (cl-flet ((pyth (lambda (w h)
                    (sqrt (+ (* w w)
                             (* h h)))))
            (mm2in (lambda (mm)
                     (/ mm 25.4))))
    (let* ((atts (frame-monitor-attributes frame))
           (pix-w (cl-fourth (assoc 'geometry atts)))
           (pix-h (cl-fifth (assoc 'geometry atts)))
           (pix-d (pyth pix-w pix-h))
           (mm-w (cl-second (assoc 'mm-size atts)))
           (mm-h (cl-third (assoc 'mm-size atts)))
           (mm-d (pyth mm-w mm-h)))
      (/ pix-d (mm2in mm-d)))))

(defvar my-zoom-frm-wanted-dpi 70
  "The DPI I want to achieve when using `my-zoom-frm-by-dpi'.")

(defun my-zoom-frm-by-dpi (&optional frame)
  "Zoom FRAME so the DPI is closer to `my-zoom-frm-wanted-dpi'."
  (interactive)
  (let ((frame (or frame (selected-frame))))
    (when (frame-parameter frame 'zoomed)
      (zoom-frm-unzoom frame))
    (let ((frame-zoom-font-difference (1- (round (/ (my-dpi frame)
                                                    my-zoom-frm-wanted-dpi)))))
      (when (called-interactively-p 'interactive)
        (message "Zooming by %S" frame-zoom-font-difference))
      (zoom-frm-in frame))))

;; Apply the scaling I want to each newly created frame:
(add-hook 'after-make-frame-functions #'my-zoom-frm-by-dpi)
Unhammer
quelle
Gibt es eine Möglichkeit, dies automatisch auszulösen, wenn das Bild zum ersten Mal auf einer anderen Anzeige angezeigt wird und sich die DPI geändert hat?
Krokodil
(add-hook 'after-make-frame-functions #'my-zoom-frm-by-dpi)wird es beim Erstellen des Rahmens laufen lassen. Ich weiß nicht, ob es einen Haken zum Verschieben eines vorhandenen Rahmens über Displays gibt, wenn Sie das gemeint haben.
Unhammer
2
Gefunden dies: github.com/mnp/dispwatch
krokodil
2
Ich habe festgestellt, dass unter my die Funktion "my-dpi" etwas genauer ist, wenn Sie das Attribut "workarea" anstelle des Attributs "geometr" verwenden. Dies liegt daran, dass das Attribut "mm-Größe" die Größe des Bereichs ist, der nicht durch Taskleisten usw. verdeckt wird.
herrlicher
Wird nach der Bearbeitung displaynicht my-dpirichtig verwendet?
KevinOrr
2

Ich habe meine Konfiguration auf verschiedene Laptops / Desktops portierbar gemacht mit:

(defun my-dpi ()
  (let* ((attrs (car (display-monitor-attributes-list)))
         (size (assoc 'mm-size attrs))
         (sizex (cadr size))
         (res (cdr (assoc 'geometry attrs)))
         (resx (- (caddr res) (car res)))
         dpi)
    (catch 'exit
      ;; in terminal
      (unless sizex
        (throw 'exit 10))
      ;; on big screen
      (when (> sizex 1000)
        (throw 'exit 10))
      ;; DPI
      (* (/ (float resx) sizex) 25.4))))

(defun my-preferred-font-size ()
  (let ( (dpi (my-dpi)) )
  (cond
    ((< dpi 110) 10)
    ((< dpi 130) 11)
    ((< dpi 160) 12)
    (t 12))))

(defvar my-preferred-font-size (my-preferred-font-size))

(defvar my-regular-font
  (cond
   ((eq window-system 'x) (format "DejaVu Sans Mono-%d:weight=normal" my-preferred-font-size))
   ((eq window-system 'w32) (format "Courier New-%d:antialias=none" my-preferred-font-size))))
(defvar my-symbol-font
  (cond
   ((eq window-system 'x) (format "DejaVu Sans Mono-%d:weight=normal" my-preferred-font-size))
   ((eq window-system 'w32) (format "DejaVu Sans Mono-%d:antialias=none" my-preferred-font-size))))

(cond
 ((eq window-system 'x)
  (if (and (fboundp 'find-font) (find-font (font-spec :name my-regular-font)))
      (set-frame-font my-regular-font)
    (set-frame-font "7x14")))
 ((eq window-system 'w32)
  (set-frame-font my-regular-font)
  (set-fontset-font nil 'cyrillic my-regular-font)
  (set-fontset-font nil 'greek my-regular-font)
  (set-fontset-font nil 'phonetic my-regular-font)
  (set-fontset-font nil 'symbol my-symbol-font)))

Obwohl ich nicht versucht habe, es in einem mehrköpfigen Setup zum Laufen zu bringen. Ich weiß nicht, ob es jemals möglich ist.

Gavenkoa
quelle
Dies funktioniert für mich tatsächlich besser, wenn der Skalierungsfaktor in my-dpi von 25,4 auf 17,2 festgelegt wird (da Emacs xrandr für Monitorabmessungen verwenden, nicht xdpyinfo)
Greg B vor