Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
This implements what I call "pseudo-daemon" mode for Emacs on OS X. Emacs doesn't work properly with the OS X GUI unless there is at least one GUI frame at all times, so normal daemon mode isn't ideal. Instead, this code simply ensures that every time you close the last GUI frame, a new hidden one is created.
(defun frame-is-last-ns-frame (frame)
"Returns t if FRAME is the only NS frame."
;; Frame is ns frame
(eq (framep frame) 'ns)
;; No other frames on same terminal
(>= 1 (length (filtered-frame-list
(lambda (frm) (eq (frame-terminal frm)
(frame-terminal frame))))))))
(defun keep-at-least-one-ns-frame (frame)
"If FRAME is the last NS frame, open a new hidden NS frame.
This is called immediately prior to FRAME being closed."
(let ((frame (or frame (selected-frame))))
(message "FRAME: %s" frame)
(when (frame-is-last-ns-frame frame)
;; If FRAME is fullscreen, un-fullscreen it.
(when (eq (frame-parameter frame 'fullscreen)
(set-frame-parameter frame 'fullscreen nil)
;; Wait for fullscreen animation
(sit-for 1.5))
;; Create a new frame on same terminal as FRAME, then restore
;; selected frame.
(let ((sf (selected-frame)))
(select-frame frame)
(switch-to-buffer "*scratch*")
(select-frame sf))
;; Making a frame might unhide emacs, so hide again
(sit-for 0.1)
(ns-hide-emacs t)
(defadvice delete-frame (before keep-at-least-one-ns-frame activate)
(keep-at-least-one-ns-frame frame))
(defadvice handle-delete-frame (around never-quit-emacs activate)
"Never invoke `save-buffers-kill-emacs' when deleting NS frame."
(let ((frame (posn-window (event-start event))))
(if (eq 'ns (framep frame))
(delete-frame frame t)
(defadvice save-buffers-kill-terminal (around ns-pseudodaemon activate)
(let ((frame (selected-frame)))
(if (eq 'ns (framep frame))
;; For NS GUI, just delete all frames. A new hidden one will
;; be spawned by the advice to `delete-frame'.
(mapc 'delete-frame
(lambda (frm) (eq (frame-terminal frm)
(frame-terminal frame)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment