Fellow Emacs-user Göktuğ Kayaalp condensed my frame centering stuff into one function as I mentioned one could do, and then improved it by adding a condition for full-screen frames. This is probably the last post on this topic, ever, because what else could be said. Right?!
It’s so nice, I want to share the code, reformatted a bit. And Göktuğ didn’t add the binding of
selected-frame as a fallback, so I added that back in, plus longer docs.
(defun my/frame-recenter (&optional frame) "Center FRAME on the screen. FRAME can be a frame name, a terminal name, or a frame. If FRAME is omitted or nil, use currently selected frame." (interactive) (unless (eq 'maximised (frame-parameter nil 'fullscreen)) (let* ((frame (or (and (boundp 'frame) frame) (selected-frame))) (frame-w (frame-pixel-width frame)) (frame-h (frame-pixel-height frame)) ;; frame-monitor-workarea returns (x y width height) for the monitor (monitor-w (nth 2 (frame-monitor-workarea frame))) (monitor-h (nth 3 (frame-monitor-workarea frame))) (center (list (/ (- monitor-w frame-w) 2) (/ (- monitor-h frame-h) 2)))) (apply 'set-frame-position (flatten-list (list frame center)))))) (add-hook 'after-init-hook #'my/frame-recenter) (add-hook 'after-make-frame-functions #'my/frame-recenter)
Update 2021-11-06: I noticed that some time after I began using Emacs 28,
(and (boundp 'frame) frame) caused trouble and would fall-back to
selected-frame too often. A working solution to auto-center a frame after making it is to omit the
boundp check and just write this:
(let* ((frame (or frame (selected-frame))) ...; this will fall-back to the selected frame if the
frame parameter is not passed.
I wasn’t aware that instead of
add-to-list a hook for
after-make-frame-functions would do the job, too. That’s what you get from following some of the docs on the web to the letter. The
after-init-hook is a great addition, too.
Since I have this auto-centering functionality in place, I find myself opening and closing new frames quite a lot. For most of 2020, I have been using a single frame, often in full-screen mode, and then have been splitting panes and experimenting with workspaces and tabs. Using the macOS windowing system instead integrates much easier with the rest of my computer life. (Though I still envy the Linux folks with their tiling window managers who use multiple tabs in emacs. Looks so tidy!)
You can also run this function in the terminal no problem. It will just exit with
t and you won’t see any effect. The important part is that there are no errors when you’re not in a GUI.