Menyesuaikan Teks dengan Cepat ke Perubahan DPI

9

Laptop saya memiliki layar 4K sehingga DPI sangat tinggi, jauh lebih tinggi daripada monitor eksternal saya. Jadi ketika saya beralih dari menggunakan monitor eksternal ke layar laptop bawaan saya ingin dengan cepat skala teks dan, jika mungkin, semua widget GUI di Emacs untuk melengkapi DPI baru. Saya mengetahui set-frame-font tapi saya belum menemukan fungsi yang sesuai yang menyesuaikan skala juga. Dan penyesuaian skala teks hanya berfungsi pada buffer secara lokal.

Nordlöw
sumber

Jawaban:

7
  1. Anda dapat mengatur nilai default-frame-alist, termasuk fontparameternya, secara kondisional, tergantung pada monitor / tampilan saat ini. (Anda dapat menggunakan fungsi display-monitor-attributes-listuntuk memberi Anda informasi monitor / tampilan.) Ini memungkinkan Anda menggunakan ukuran font default yang berbeda untuk monitor yang berbeda atau konteks yang berbeda.

  2. Anda juga dapat mengubah ukuran font secara dinamis, untuk semua jendela dan buffer yang ditampilkan dalam bingkai apapun, menggunakan perintah zoom-in, zoom-outatau zoom-in/out, dari perpustakaan zoom-frm.el.

    Perintah yang sama ini dapat memperbesar buffer (di semua jendela, pada bingkai apa pun) atau bingkai (semua jendela, apa pun buffernya). Lihat halaman Wiki Emacs Set Font .

Drew
sumber
4

Saya menggunakan sesuatu yang mirip dengan @gavenkoa (kebetulan murni juga dengan penolong bernama my-dpi!) Untuk membuat bingkai baru mendapatkan ukuran yang tepat, tetapi memanggil zoom-frmsejak saya menggunakan paket itu pula. Ini juga berfungsi pada pengaturan multiheaded, dengan menggunakan frame-monitor-attributesalih-alih 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)
tidak tahu malu
sumber
Jika ada cara untuk memicu ini secara otomatis ketika frame pertama kali ditampilkan di layar yang berbeda dan DPI telah berubah?
krokodil
(add-hook 'after-make-frame-functions #'my-zoom-frm-by-dpi)akan membuatnya berjalan saat membuat bingkai. Saya tidak tahu apakah ada kait untuk memindahkan bingkai yang ada di display, jika itu yang Anda maksud.
Unhammer
2
Ditemukan ini: github.com/mnp/dispwatch
krokodil
2
Saya menemukan bahwa di Windows, fungsi my-dpi sedikit lebih akurat jika Anda menggunakan atribut 'workarea' alih-alih atribut 'geometri'. Ini karena atribut 'mm-size' adalah ukuran area yang tidak dikaburkan oleh taskbar dan sebagainya.
Glmorous
Setelah diedit, displaytidakkah digunakan dengan my-dpibenar?
KevinOrr
2

Saya membuat config portable di berbagai laptop / desktop dengan:

(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)))

Meskipun saya belum mencoba membuatnya bekerja dalam pengaturan multiheaded. Tidak tahu apakah itu mungkin.

gavenkoa
sumber
1
Ini sebenarnya bekerja lebih baik bagi saya ketika memperbaiki faktor penskalaan dalam my-dpi dari 25,4 menjadi 17,2 (karena emacs menggunakan xrandr untuk dimensi monitor, bukan xdpyinfo)
Greg B