Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In daemon mode, Spacemacs does not set the font correctly #6197

Closed
pfmoore opened this issue Jun 2, 2016 · 34 comments
Closed

In daemon mode, Spacemacs does not set the font correctly #6197

pfmoore opened this issue Jun 2, 2016 · 34 comments
Labels

Comments

@pfmoore
Copy link
Contributor

pfmoore commented Jun 2, 2016

In my ~/.spacemacs.d/init.el I have:

   dotspacemacs-default-font '("DejaVu Sans Mono-12"
                              ; Size etc, don't work in Windows
                              ; :size 13
                              ; :weight normal
                              ; :width normal
                               :powerline-scale 1.1)

This works fine if I start Emacs normally. However, if I do emacs.exe --daemon I see the following in the output:

>emacs.exe -daemon
Loading c:/Users/UK03306/.emacs.d/core/core-load-paths.el (source)...
Loading c:/Users/UK03306/.emacs.d/core/core-load-paths.el (source)...done
Loading c:/Users/UK03306/.spacemacs.d/init.el (source)...
Loading c:/Users/UK03306/.spacemacs.d/init.el (source)...done
Setting the font...
(Spacemacs) Warning: Cannot find font "DejaVu Sans Mono-12"! Font settings may not be correct.

... and when I open a frame via emacsclient -c the default font (Courier New) is used rather than my configured font. Checking default-frame-alist, my font preference has not been set.

The problem seems to lie in this code in core-spacemacs.el:

  (spacemacs|do-after-display-system-init
   ;; If you are thinking to remove this call to `message', think twice. You'll
   ;; break the life of several Spacemacser using Emacs in daemon mode. Without
   ;; this, their chosen font will not be set on the *first* instance of
   ;; emacsclient, at least if different than their system font. You don't
   ;; believe me? Go ahead, try it. After you'll have notice that this was true,
   ;; increase the counter bellow so next people will give it more confidence.
   ;; Counter = 1
   (message "Setting the font...")
   (if (find-font (font-spec :name (car dotspacemacs-default-font)))
       (spacemacs/set-default-font dotspacemacs-default-font)
     (spacemacs-buffer/warning
      "Cannot find font \"%s\"! Font settings may not be correct."
      (car dotspacemacs-default-font))))

I know that find-font will not find GUI fonts when called early in the initialisation in Daemon mode on Windows. At that point, there's no GUI frame and so the "current frame" used by default by find-font doesn't have access to the fonts available on the GUI display for some reason. However, I'm not sure that's everything that is going on here, as I checked find-font on a Linux machine and got a similar result.

System Info 💻

  • OS: windows-nt
  • Emacs: 25.0.93.1
  • Spacemacs: 0.105.20
  • Spacemacs branch: develop (rev. 8f45a94)
  • Graphic display: t
  • Distribution: spacemacs
  • Editing style: vim
  • Completion: helm
  • Layers:
(windows-scripts python helm auto-completion emacs-lisp)
@syl20bnr
Copy link
Owner

syl20bnr commented Jun 2, 2016

I thought it was fixed but apparently it is not the case, @StreakyCobra it seems that the magic message call is not working :-D

@syl20bnr
Copy link
Owner

syl20bnr commented Jun 2, 2016

Flag as duplicate of #1894

@StreakyCobra
Copy link
Contributor

@syl20bnr The magic message is there to solve the specific problem when the really first emacsclient instance has the wrong font but subsequent ones use the correct font. It was not meant to solve all font-setup issue :-)

@pfmoore Is it only the first emacsclient instance that has the wrong font?

I would suspect this being a problem with windows, but I'm not really sure. @pfmoore Can you try to replicate your config in your linux VM and see if happens there too? Also can you try emacs 24.5 to see if there is a difference?

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 3, 2016

@StreakyCobra It happens for every emacsclient instance - there's no font setting in initial-frame-alist.

I can't test in 24.5.1, as I get "This platform does not support the -daemon flag" - daemon mode is new in version 25 for Windows.

As far as trying on Linux is concerned, I'll see what I can do. My Linux VM is a bit of a mess (running on a PC but has no internet access, and apparently sshd isn't installed by default, so I can't transfer files to it). My spacemacs config is little more than setting dotspacemacs-default-font to something clearly different from the "lowest common denominator" (which on Windows is Courier New), then do emacs --daemon, followed by emacsclient -c. The emacs --daemon command gets the "Font not found" message quoted above, and then all emacsclient windows show up in Courier New, rather than what I asked for.

I'll report back on Linux once I get something set up.

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 3, 2016

OK, found a PC with proper internet access...

Everything works as I expected it to on Linux (ie, the bug I'm reporting here doesn't occur). The emacsclient window comes up with DehaVu Sans Mono. Strangely, though, if I set the font to one that doesn't exist ("DejaVux Sans Mono") I still don't get the "could not find font" message on startup of the daemon. But now the font in an emacsclient window is the standard Ubuntu font (which presumably means that spacemacs failed to find the font at some point, and fell back to that).

I'm not sure what I can conclude from this, but if you need me to do any more experiments, let me know.

@StreakyCobra
Copy link
Contributor

So it's probably a windows related issue.

The error message not being showed if the font don't exist is expected (IIRC) as we are delaying the configuration of the font after the display has been initiated (spacemacs|do-after-display-system-init) so that font can be setup correctly. If you look in the *Messages* buffer of the first graphical instance you'll probably have the warning there.

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 3, 2016

Ha. Found the issue, w32-initialized is set right at the start of the daemon startup process. I added a simple (message w32-initialized) at the start of .emacs.d/init.el and emacs --daemon showed Wrong type argument: stringp, t (yeah, I know :-)). So it looks like w32-initialized is true long before it's OK to set the font.

Whether that's a bug, I'm not sure. I'll report it as such and see what happens.

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 4, 2016

I've just submitted PR #6227 to work around this issue. The initial response from the emacs bugs list was

It looks like this is an internal variable whose purpose is to make sure the w32 GUI initialization code is called only once per session; it shouldn't be used for any other purpose. I guess we could make this more explicit in the doc string, but other than that I see no bug here.

I'm still discussing the situation, so that may change, but even so the PR seems to work on current versions of emacs 25 on Windows, so it'll save people having to upgrade their Emacs to get fixed behaviour, at least.

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 4, 2016

Response from Eli Zaretskii (and my reply) on the emacs bugs list:

On 4 June 2016 at 16:01, Eli Zaretskii eliz@gnu.org wrote:

If spacemacs has a way to run code when the first GUI frame is
created, why cannot it do everything at that time? Why does it have
to test the above conditions on top of that?
[...]
I think spacemacs should not rely on the other FOO-initialized
variables, either, even if they appear to work for now. They are not
intended to serve as evidence or trigger for any application-level
logic. Instead, it should do this in a hook function (make-frame
provides at least 2).
[...]
That "window-system initialized" automatically implies that find-font
will work is IMO an invalid assumption. Exactly what parts of the
initialization are run in FOO-initialize functions is implementation
detail. I recommend to stay away of such assumption and instead use
the hooks we provide during startup. Even if you come to the
conclusion that no existing hook serves spacemacs well enough, and we
then (say) add yet another hook, the result will be cleaner than
relying on semi-documented variables and undocumented assumptions.

OK. Thanks for the explanation. I'll report back to the spacemacs people. For now, I have a functioning workaround (checking if (font-family-list) is non-nil) that will do for the moment. Longer term, I can't judge why spacemacs splits the initialisation like this, but I'll ask the question.

@syl20bnr
Copy link
Owner

syl20bnr commented Jun 5, 2016

If we can get a hook for this we would be really happy :-)
cc @travisbhartwell

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 6, 2016

I still seem to be getting odd issues with this. I've put some log messages in, and I can see that my chosen font is now getting selected, but frames are being opened which don't use that font.

I can't yet see any pattern to this. I'm opening Emacs using emacsclientw -c -a "" (which uses the GUI version of emacsclient, and the -a "" flag to open the server in the background. What's really odd is that if I do that, then issue kill-emacs, then do it again, sometimes I'm getting the frame with the right font and sometimes not - even though I haven't made any changes. That makes me suspect there's a race condition in there somewhere.

One question - it doesn't look like spacemacs uses default-frame-alist to specify the font for new frames. Is that correct, and if so why doesn't it do so? From what I'd seen reading various postings on the internet, setting default-frame-alist (rather than say just setting the font for the default face) is the most reliable way to set the font for all new frames. (Although I'm very new to Emacs, so I may easily be misreading things).

@TheBB
Copy link
Contributor

TheBB commented Jun 6, 2016

One question - it doesn't look like spacemacs uses default-frame-alist to specify the font for new frames. Is that correct, and if so why doesn't it do so?

That seems to be a bug. I was able to open frames with incorrect fonts but if I set it in default-frame-alist that doesn't happen.

@TheBB
Copy link
Contributor

TheBB commented Jun 6, 2016

#6240

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 6, 2016

Hmm, I added the change, and I still sometimes get the incorrect font. Checking default-frame-alist, it's got the wrong font in there. And yet, my logging shows 'Found "DejaVu Sans Mono-12"'.

This definitely looks like some sort of race condition, with the font getting selected after the frame has been created somehow.

I wonder if hooking spacemacs|do-after-display-system-init off server-create-window-system-frame is the problem here, and that function is being called too late. Before I switched to spacemacs, I had some font setting code from StackOverflow that set up the font on focus-in-hook. That's pretty late, but definitely worked for me.

Maybe the real answer is to get a new hook specifically for this, but that would presumably not work for people on older versions of Emacs, so we'd end up needing to support both methods...

I'll keep digging when I have the time.

@syl20bnr
Copy link
Owner

syl20bnr commented Jun 6, 2016

Thank you for the investigation, this is a dark corner of Spacemacs where we try to make GUI related config to work with emacs --daemon. I would love a hook upstream for this kind of task (not just for the font but a safe place to initialize GUI stuff for the first GUI client). When we look at the macro this is exactly what we try to achieve with the advice. This is not pretty but allow us to fix multiple issues with GUI clients.

The minimum version supported by Spacemacs is now 24.4 so we could try the focus-in-hook hook and see if we get more chance. I'm open for a font specific solution too (spacemacs|do-after-display-system-init is our generic solution for everything GUI related).

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 7, 2016

OK. Here's an update on my investigations.

The issue basically seems to be that spacemacs/set-default-font uses find-font with no frame argument - so it gets the currently selected frame. As far as I can see, it's not deterministic whether the function ends up using the (non-GUI) daemon frame, or the (GUI) user frame when the hook gets called. As a result, sometimes we get fonts selected correctly, but sometimes we don't. From the evidence, this appears to only be an issue on Windows, but I've no idea why that would be the case. It's possible that the magic message call in the code somehow ensures that a GUI frame is selected on non-Windows systems...

I'm currently looking at two changes - first, change spacemacs/set-default-font to take an explicit frame parameter, so that we're not relying on what's selected. Second, find a better place to hook into the display system initialisation where we can hunt for a proper GUI frame, and when one exists, call spacemacs/set-default-font with that frame explicitly set. So far, though, I'm seeing weird side effects (the spacemacs logo isn't displayed as an image but as text, and the powerline data is messed up). So I'm still looking.

It may be that a more radical change (such as forcibly selecting a GUI frame) would work, but I'm concerned I'd break something else (this is all very low level, and I'm very new to elisp/emacs internals).

On the other hand, there's a pretty good user-level solution. In .spacemacs.d/init.el you can just put

(defun reset-default-font ()
  (unless (spacemacs/set-default-font dotspacemacs-default-font)
    (spacemacs-buffer/warning
     "Cannot find any of the specified fonts (%s)! Font settings may not be correct."
     (mapconcat 'car dotspacemacs-default-font ", ")))
  (remove-hook 'focus-in-hook #'reset-default-font))

Then, in dotspacemacs/user-init just add a line (add-hook 'focus-in-hook #'reset-default-font). There's a bit of flicker on the first frame (because the frame is initially shown with the fallback font, and then reset) but otherwise this seems to work fine. I've not been able to fit it cleanly into the core code, though.

@StreakyCobra
Copy link
Contributor

It's possible that the magic message call in the code somehow ensures that a GUI frame is selected on non-Windows systems...

Interesting hypothesis, would make sense!

this is all very low level, and I'm very new to elisp/emacs internals

You already went far further than me!

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 7, 2016

You already went far further than me!

I'm stubborn :-)

@asteroidcow
Copy link

Not sure if I am seeing the same bug or not - but after I updated all packages a couple of days back and installed the themes-megapack, and now my font settings are completely ignored. I run emacs in daemon mode, and am running debian unstable.

I tried the workaround suggested by @pfmoore , but while my font settings while applied, the size is quite off - it's really small! Any hints on how to analyze this problem further will be much appreciated!

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 7, 2016

I find size handling is very odd. If I use "DejaVu Sans Mono-12" it looks way bigger than 12 points (12 C-X = shows it as 16-point). If I use "DejaVu Sans Mono" :size 12 it looks too small (but it's probably what shows as 12-point). The Windows font dialog on shift mouse 1 shows 12 point DejaVu Sans Mono as being the same size as the big one. This may be a Windows thing, though.

I just play with the numbers till I get something I like...

@asteroidcow
Copy link

Seeing this on Linux too - the "<font>-<size>" syntax did stick, but the "<font>" :<size> did not! Thanks for the tip!

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 7, 2016

I should have read the docs:

The font size- either a non-negative integer that specifies the pixel size, or a floating-point number that specifies the point size.

:size 12.0 gives 12-point font. :size 12 gives 12 pixel font.

@pfmoore
Copy link
Contributor Author

pfmoore commented Jun 8, 2016

I might have an improved version of the font-setting code that works properly in daemon mode on Windows. At the moment it's just sitting in a branch on my fork, at https://github.com/pfmoore/spacemacs/tree/font_test. I'll do some more testing before submitting it as a PR, but if anyone feels like trying it out and reporting any issues (especially on non-Windows systems) that'd be great.

One thing that bothers me is that I'm seeing occasional odd messages in the *Messages* buffer. I don't know if they have been introduced by my code, or even if they were there before, but I want to investigate a little more (the most common one is " is undefined" which looks like the messages you get when you use an undefined key sequence).

Anyway - any feedback would be gratefully accepted, otherwise I'll put a PR together when I've tested the change out a little more.

@shankmittal
Copy link

I have observed same issue on ubuntu too. Following comments helped #6197 (comment)

@webframp
Copy link

webframp commented Jul 5, 2016

Was trying to use the hack font and just got the message mapconcat: Wrong type argument: listp, "Hack"

The fix from #6197 (comment) worked in my case on Windows as well.

Emacs version: GNU Emacs 25.0.50.1 (x86_64-w64-mingw32)

@magiccookie
Copy link

For me font goes back to normal, when cycling themes SPC T n.

@dlukes
Copy link

dlukes commented Jan 25, 2017

FWIW, I've recently started experiencing this issue as well (under Arch Linux + Gnome3), regardless of whether I start Emacs in daemon mode or not. As far as I'm aware, this wasn't tied to any update either of Emacs or Spacemacs. I think it started manifesting itself after a Wayland crash, but it may very well be that the two are only tangentially related (at any rate, the behavior is now the same when using either of Wayland or Xorg as the window server). Running (spacemacs/set-default-font dotspacemacs-default-font) at a later point of the init process or in a hook (cf. #6197 (comment)) sets the font correctly.

@dlukes
Copy link

dlukes commented Jan 25, 2017

OK, and now the issue disappeared as mysteriously as it appeared, huh? The only thing I did was log in with a new user to see if the problem would persist on a fresh clone of Spacemacs + package install (it didn't), then I switch back to my normal user's session, restart Spacemacs, and the issue's gone. Go figure.

(I realize this is not terribly useful, but just to illustrate the heisenbug nature of the issue.)

@longtomjr
Copy link

Still have this issue. The workaround fix above works for me aswell. If it is at all possible, we can consider only loading the font when a client is launched. Having a separate config for the client can add other functionality aswell. I dont know if this is possible at the level spacemacs operate.

@jrmiller82
Copy link

Still have this issue on Ubuntu 17.10.

@c02y
Copy link

c02y commented May 18, 2019

This occurs to me on CentOS7 and openSUSE Tumbleweed, it worked fine well, and then it just suddenly doesn't load my own font correctly anymore, and no other warning or error message in Message buffer or anywhere. #6197 (comment) works for me.

And I found a simpler solution, put something like

(setq default-frame-alist '((font . "Inconsolata-dz-15")))

in dotspacemacs/user-init, and I don't have to touch dotspacemacs-default-font at all.

@danielstaleiny
Copy link

danielstaleiny commented Oct 26, 2019

Confirming that this is an issue NixOS unstable (19).

To find your current font which you are using with all the setting call describe-font function

Space + Space(M-x); describe-font

copy the full name

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Please let us know if this issue is still valid!

@github-actions github-actions bot added the stale marked as a stale issue/pr (usually by a bot) label Oct 25, 2020
@debnath-d
Copy link

The issue still exists. Please reopen this bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests