Say there're 3 frames Fa Fb Fc.

Then I closed Fa Fc, Emacs needs to remember nothing;
instead, Fb is the one that needs to be saved its parameters, because it's the only frame on the desktop.
Then I close Fb; now Fb is the last closed frame and there's no frame on the desktop.

Next time I create a new frame Fd, it will use the size and position parameters of Fb.

When there're already other frame(s) on the desktop, the newly created frame uses default parameters instead.

Any way to implement that?

  • 1
    Are you aware of burly ? https://github.com/alphapapa/burly.el
    – gigiair
    Commented Mar 4, 2023 at 10:19
  • 1
    @gigiair: Thanks! I will try it soon. BTW, there's no need to use code-block to wrap a URL; Just leave it as it is, so that one can click on it :-)
    – shynur
    Commented Mar 4, 2023 at 10:25

3 Answers 3


I've been using the following code from this reddit post. worksforme

(Note, I've changed the file location from the original.)

;; https://www.reddit.com/r/emacs/comments/4ermj9/comment/d237n0i/?utm_source=share&utm_medium=web2x&context=3
;; Custom functions/hooks for persisting/loading frame geometry upon save/load

(defun save-frameg ()
  "Gets the current frame's geometry and saves to ~/.emacs.frameg."
  (let ((frameg-font (frame-parameter (selected-frame) 'font))
    (frameg-left (frame-parameter (selected-frame) 'left))
    (frameg-top (frame-parameter (selected-frame) 'top))
    (frameg-width (frame-parameter (selected-frame) 'width))
    (frameg-height (frame-parameter (selected-frame) 'height))
    (frameg-file (expand-file-name ".emacs.frameg" user-emacs-directory)))
      ;; Turn off backup for this file
      (make-local-variable 'make-backup-files)
      (setq make-backup-files nil)
       ";;; This file stores the previous emacs frame's geometry.\n"
       ";;; Last generated " (current-time-string) ".\n"
       "(setq initial-frame-alist\n"
       ;; " '((font . \"" frameg-font "\")\n"
       " '("
       (format " (top . %d)\n" (max frameg-top 0))
       (format " (left . %d)\n" (max frameg-left 0))
       (format " (width . %d)\n" (max frameg-width 0))
       (format " (height . %d)))\n" (max frameg-height 0)))
      (when (file-writable-p frameg-file)
    (write-file frameg-file)))))

(defun load-frameg ()
  "Loads ~/.emacs.frameg which should load the previous frame's geometry."
  (let ((frameg-file (expand-file-name ".emacs.frameg" user-emacs-directory)))
    (when (file-readable-p frameg-file)
      (load-file frameg-file))))

;; Special work to do ONLY when there is a window system being used
(if window-system
      (add-hook 'after-init-hook 'load-frameg)
      (add-hook 'kill-emacs-hook 'save-frameg)))

I have found out how Portacle implements this feature.

I edited its source code, and added them to my .emacs:

(when (display-graphic-p)

  ;; This is the `some-specific-file` mentioned in my question.
  ;; You just need to customize it.
  (defconst shynur/frame-save-position-size-file

  (add-hook 'emacs-startup-hook
            #'(lambda ()
                (when (file-exists-p shynur/frame-save-position-size-file)
                  (load-file shynur/frame-save-position-size-file))))
  (add-hook 'kill-emacs-hook
            #'(lambda ()
                (let* ((props
                        '(left top width height))
                        (mapcar #'(lambda (parameter)
                                    (let ((value
                                           (frame-parameter (selected-frame) parameter)))
                                      (if (number-or-marker-p value)
                                          (max value 0)
                                        0))) props)))
                    (cl-loop for prop in props
                             for val in values
                             do (insert
                                 (format "(add-to-list 'initial-frame-alist '(%s . %d))\n"
                                         prop val))))
                  (write-file shynur/frame-save-position-size-file)))))

I wrote a new piece of code for when running Emacs as daemon-clients. It's really nice; hope you'll like it!

;; -*- lexical-binding: t; -*-
(let ((size&position-saver `(,(cons 'top 0) ,(cons 'left 0)  ,(cons 'width 0) ,(cons 'height 0))))
  (put 'size&position-saver :saving? nil)
  (letrec ((get-size&position (lambda ()
                                (when (get 'size&position-saver :saving?)
                                  (dolist (parameter-value size&position-saver)
                                    (set-frame-parameter nil (car parameter-value) (cdr parameter-value))))
                                (remove-hook 'server-after-make-frame-hook get-size&position)
                                (   add-hook 'delete-frame-functions       put-size&position)))
           (put-size&position (lambda (frame-to-be-deleted)
                                (when (length= (frames-on-display-list) 1)
                                  (dolist (parameter-value size&position-saver)
                                    (setcdr parameter-value (frame-parameter frame-to-be-deleted (car parameter-value))))
                                  (put 'size&position-saver :saving? t)
                                  (remove-hook 'delete-frame-functions       put-size&position)
                                  (   add-hook 'server-after-make-frame-hook get-size&position)))))
    (add-hook 'server-after-make-frame-hook get-size&position)))

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.