unicode-fonts
unicode-fonts copied to clipboard
Initializing under daemon?
The readme says use (unicode-fonts-setup)
in the init file. When starting Emacs as daemon, this is executed but has no effect. Afterwards, running an emacsclient -c .
opens an X frame, with fonts at their defaults.
What do I need to hook so that (unicode-fonts-setup)
is run for X frames created for emacsclient
?
I have tried:
-
window-setup-hook
; -
before-make-frame-hook
; -
after-make-frame-hook
.
When I start the first client frame, they run with (window-system)
returning nil
, so calling (unicode-fonts-setup)
has no effect.
It's probably not the most elegent solution, but I use an after-make-frame-functions
hook that removes itself after it runs successfully (on a graphical frame where fonts are available)
(defun my/init-fonts (&optional f)
(when (display-graphic-p f)
(unicode-fonts-setup)
;; anything else that needs fonts to be available
(remove-hook 'after-make-frame-functions 'my/init-fonts))))
(add-hook 'after-init-hook
(lambda ()
(if initial-window-system
(my/init-fonts)
(add-hook 'after-make-frame-functions 'my/init-fonts))))
the after-init-hook
is there is there in case emacs was not started as a daemon -- the after-frame-functions
are not run on the first frame, so this just says run my/init-fonts
explicitly instead of adding it as a frame hook.
Nice. I wonder if it’s worthwhile deferring until after-init-hook
. The initial frame is already created when init files are parsed, so I’m inclined to try running the hook right then.
Some more observations.
- On my machine, the
my/init-fonts
hook runs with the daemon’s text frame as the selected one (but with the newly created X frame as the parameter). - The
(display-graphic-p f)
test in the hook passes. -
unicode-fonts-setup
runs, notices it has not yet been run, records that it has been run, and callsunicode-fonts--setup-1
. -
unicode-fonts--setup-1
runs and checks for(display-multi-font-p)
. This test fails because by defaultdisplay-multi-font-p
uses the selected frame, which is the daemon’s initial text frame. Sounicode-fonts--setup-1
returns without doing anything. - Any further attempt to run
(unicode-fonts-setup)
is a no-op because it has already recorded that it has run.
I worked around this by sticking a (select-frame f)
immediately before (unicode-fonts-setup)
.
The resulting snippet looks like this:
(defun my/init-fonts (&optional frame)
(when (display-graphic-p frame)
(select-frame frame)
(unicode-fonts-setup)
(remove-hook 'after-make-frame-functions 'my/init-fonts)))
(add-hook 'after-init-hook
(lambda ()
(if initial-window-system
(my/init-fonts)
(add-hook 'after-make-frame-functions 'my/init-fonts))))
Ah, good catch! I've just started trying out unicode-fonts
and hadn't actually put it in the hook when I posted (just what I was using previously for set-fontset-font
commands). I ran into the same problem when I did, and your fix solves it perfectly.
Is there a proposed patch?
So far, we were just discussing workarounds. But I can prepare a patch that (a) fixes the “record that we have run but actually do nothing”, and/or (b) passes the frame as a parameter to unicode-fonts-setup
, and/or (c) puts this whole snippet into the library, exposing it under the original name of unicode-fonts-setup
(with appropriate renaming). Which way would you like?
One quick note: since frame
is an optional argument, the call should be wrapped to accommodate non-daemon startup: (when frame (select-frame frame))
I don't use daemon startup, so I'm inclined to take the advice of those that do so on how the fix should be implemented. The purpose of the library is purely convenience, so the goal should be that (unicode-fonts-setup)
would work as documented even if the user uses --daemon.
Hello,
another user is now in the same position as I was a year and a half ago.
I have updated the pull request #4 to the current master.
Hi!
Thanks for reviving. I forgot about this issue as I don't use --daemon startup and never got around to trying it. I will try out #4.
Reading that Google Plus thread, I want to note that unicode-fonts startup is much faster now. If the user is seeing a five-second cost, he should upgrade.
I have emacs 24.4.1 with unicode-fonts 20150223.1059 from melpa. I still have the problem that unicode-fonts-setup. to solve it I used the solution inspired by the G+ post:
(defun my-hook-unicode-fonts-setup (frame)
"Run unicode-fonts-setup, then remove the hook."
(progn
(select-frame frame)
(unicode-fonts-setup)
(message "Removing unicode-fonts-setup to after-make-frame-functions hook")
(remove-hook 'after-make-frame-functions 'my-hook-unicode-fonts-setup)
))
(add-hook 'after-make-frame-functions 'my-hook-unicode-fonts-setup nil)
Otherwise it does not work.
I’ve run into the same issue, five years later. @guraltsev’s code snippet solved the problem for me. I suggest this should be integrated into the package somehow.
Is there any news on this. I have tried using the comment from @guraltsev and I have also installed used the 'fix-daemon-startup' branch from @yurikhan and that hasn't helped. This may be todo with the org-superstar plugin though
(use-package unicode-fonts
:init (unicode-fonts//setup-fonts (selected-frame)))
(defun unicode-fonts//setup-fonts (frame)
"Setup `unicode-fonts' package for FRAME.
This functions setups `unicode-fonts' right away when starting a GUI Emacs.
But if Emacs is running in a daemon, it postpone the setup until a GUI frame
is opened."
(if (and frame (display-graphic-p frame))
(with-selected-frame frame
(require 'unicode-fonts)
(unicode-fonts-setup)
(remove-hook 'after-make-frame-functions #'unicode-fonts//setup-fonts))
(add-hook 'after-make-frame-functions #'unicode-fonts//setup-fonts)))
I've come up with this solution. If people can verify it I will make a PR.
Based on the info in this thread, I've implemented the following macro in my config, which seems to work:
(require 'cl)
(setq my/run-once-after-first-frame-counter 0)
(defmacro my/run-once-after-first-frame (&rest body)
`(lexical-let* (target-hook
(count my/run-once-after-first-frame-counter)
(fnsymb (make-symbol (format "my/run-once-after-first-frame-%d" count))))
(setq target-hook (if (daemonp)
'after-make-frame-functions
'after-init-hook))
(fset fnsymb (lambda (&optional frame)
(remove-hook target-hook fnsymb)
(when frame (select-frame frame))
,@body))
(add-hook target-hook fnsymb)
(cl-incf my/run-once-after-first-frame-counter)))
Usage example:
(my/run-once-after-first-frame
(unicode-fonts-setup)
;; Other commands go here, such as load-theme, etc...
)
Also solves other problems such as this one.