I have a snippet that I use to determine what font size to set based on the resolution of the display, for when my laptop has an external monitor set or not:

(defconst prefs/font-size                  14)
(defconst prefs/font-size/display-laptop   12)
(defconst prefs/font-size/display-external 18)

(defun prefs/use-font-size ()
  (let ((px (display-pixel-width)))
     ((eq px 7040) prefs/font-size/display-external)
     ((eq px 3200) prefs/font-size/display-laptop)
     (t prefs/font-size))))

This works great when emacs is started normally; however I'm trying to daemon-ify my configuration. Based on that, I now have a function to set UI-related things on default-frame-alist parameters in a before-make-frame as well as initial-frame-alist at startup:

(defun jl/set-frame-params (frame-alist)
  (add-to-list frame-alist
               `(font .
                      ,(concat (prefs/use-font) "-"
                               (number-to-string (prefs/use-font-size)))))
  ; ... more frame parameters

(jl/set-frame-params 'initial-frame-alist)
(add-hook 'before-make-frame-hook ; configure new frames
          #'(lambda ()
              (jl/set-frame-params 'default-frame-alist)))

However, here's the behavior I'm seeing:

  • initial daemon load: (display-pixel-width) returns nonsense (10) and the initial emacsclient frame has the font size set incorrectly
  • creating a new frame after that via make-frame,(display-pixel-width) returns the correct value, but the font size is still incorrect.
  • creating a second new frame with make-frame, the font size is finally correct.

What am I doing wrong here, and how can I get my font size set correctly both for the first frame created on a server, and subsequent frames?

  • I guess the problem is that the current display only point to the X display after you create the first frame, and changing default-frame-alist only affects things if you set it before make-frame.
    – npostavs
    Commented Oct 13, 2018 at 22:57
  • I know this is late, but I use after-make-frame-functions for this, and in that case you get valid results for the display size etc.
    – GaryO
    Commented Oct 31, 2019 at 14:54

1 Answer 1


After a little digging and experimentation, I discovered that display-pixel-width takes an optional argument which is the name of the display to test; I wasn't able to get that to work.

However, x-display-pixel-width also takes an optional name, and passing the X Display name (:0) returns the correct value even on daemon startup:

(message "display-pixel-width %d or x-display-pixel-width %d"
  (x-display-pixel-width ":0"))

display-pixel-width 10 or x-display-pixel-width 3200

This seems to work fine under XWayland as well.

  • Logged in just to upvote this one. I was also banging my head with this one. Thanks!
    – gusbrs
    Commented Nov 10, 2019 at 20:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.