Subject: Re: bug#50440: Emacs does not rescale fonts when display changes DPI

From: Eli Zaretskii <[email-masked]>
Date: Tue, 07 Sep 2021 08:24:36 +0300

> From: Radon Rosborough <[email-masked]>
> Date: Mon, 6 Sep 2021 13:04:27 -0700
> 
> I run Emacs either on my laptop (1920x1080, 96 DPI) or on my external monitor (3840x2160, 192 DPI,
> configured with 200% display scaling so that applications display identically on both displays, and with my
> laptop display disabled).
> 
> What I observe is that if I start Emacs on my external monitor and unplug it (so the display DPI decreases
> from 192 to 96), the fonts in Emacs appear to be twice as large, although the window title bar is sized
> normally and all other applications scale correctly. Similarly, when I start Emacs on my laptop screen and
> then plug in my monitor, the fonts in Emacs appear to be twice as small, although all other applications scale
> correctly.
> 
> I observed that when I start Emacs on my external monitor, M-x list-fontsets returns "-CTDB-Fira
> Mono-normal-normal-normal-*-29-*-*-*-m-0-fontset-startup", whereas when I start it on my laptop screen, it
> returns "-CTDB-Fira Mono-normal-normal-normal-*-15-*-*-*-m-0-fontset-startup". The fontset does not
> change when the underlying display DPI changes, which is presumably part of the issue.
> 
> By inserting some debugging code into Emacs, I saw that x_term_init is only called once, when Emacs
> initially starts up. This appears to be where the DPI is set in the x_display_info struct, and then it is never
> updated again. I tried manually invoking x-open-connection from Lisp after switching displays, which did call
> x_display_info again and set a new DPI value. However, this value didn't seem to propagate to
> FRAME_RES_Y which is called from font_pixel_size when initializing the fonts, for some reason. Moreover,
> it seems like additional changes would be required to get the default font to be reinitialized even if the
> underlying x_display_info is updated.

We call x_term_init each time a frame is created for the first time on
a new display.  So potentially make-frame-on-display could call it.

One other thing to try is to start Emacs as a daemon, and when you
switch displays, close all the client frames and make new ones via
emacsclient.

Does any of the above allow you to solve the issue?