From 39c0e36f24cb09de612d07ed7e0bbe7e67a7a4ff Mon Sep 17 00:00:00 2001 From: Juanma Barranquero Date: Thu, 27 Jun 2013 11:08:14 +0200 Subject: [PATCH] New experimental feature to save&restore window and frame setup. * etc/NEWS: Document new Desktop option `desktop-save-windows'. * lisp/desktop.el (desktop-save-windows): New defcustom. (desktop--saved-states): New var. (desktop--excluded-frame-parameters): New defconst. (desktop--filter-frame-parms, desktop--find-frame-in-display) (desktop--restore-windows, desktop--save-windows): New functions. (desktop-save): Call `desktop--save-windows'. (desktop-read): Call `desktop--restore-windows'. --- etc/ChangeLog | 4 +++ etc/NEWS | 3 ++ lisp/ChangeLog | 11 +++++++ lisp/desktop.el | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 98 insertions(+) diff --git a/etc/ChangeLog b/etc/ChangeLog index c8748396f60..93ba05bc377 100644 --- a/etc/ChangeLog +++ b/etc/ChangeLog @@ -1,3 +1,7 @@ +2013-06-27 Juanma Barranquero + + * NEWS: Document new Desktop option `desktop-save-windows'. + 2013-06-27 Stephen Berman * NEWS: Mention new version of todo-mode.el and obsoleting and diff --git a/etc/NEWS b/etc/NEWS index 85cf3b80acd..f5ab7c60ce5 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -237,6 +237,9 @@ on the given date. *** `desktop-auto-save-timeout' defines the number of seconds between auto-saves of the desktop. +*** `desktop-save-windows' enables saving and restoring the window/frame +configuration. + ** Dired *** New minor mode `dired-hide-details-mode' hides details. diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4c0952f88f5..2c36162b017 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,14 @@ +2013-06-27 Juanma Barranquero + + New experimental feature to save&restore window and frame setup. + * desktop.el (desktop-save-windows): New defcustom. + (desktop--saved-states): New var. + (desktop--excluded-frame-parameters): New defconst. + (desktop--filter-frame-parms, desktop--find-frame-in-display) + (desktop--restore-windows, desktop--save-windows): New functions. + (desktop-save): Call `desktop--save-windows'. + (desktop-read): Call `desktop--restore-windows'. + 2013-06-27 Lars Magne Ingebrigtsen * net/shr.el (add-face-text-property): Removed compat definition. diff --git a/lisp/desktop.el b/lisp/desktop.el index 8e66a9b81a3..68c2b26b5d7 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el @@ -371,6 +371,12 @@ modes are restored automatically; they should not be listed here." :type '(repeat symbol) :group 'desktop) +(defcustom desktop-save-windows nil + "When non-nil, save window/frame configuration to desktop file." + :type 'boolean + :group 'desktop + :version "24.4") + (defcustom desktop-file-name-format 'absolute "Format in which desktop file names should be saved. Possible values are: @@ -556,6 +562,9 @@ DIRNAME omitted or nil means use `desktop-dirname'." "Checksum of the last auto-saved contents of the desktop file. Used to avoid writing contents unchanged between auto-saves.") +(defvar desktop--saved-states nil + "Internal use only.") + ;; ---------------------------------------------------------------------------- ;; Desktop file conflict detection (defvar desktop-file-modtime nil @@ -858,6 +867,42 @@ DIRNAME must be the directory in which the desktop file will be saved." ;; ---------------------------------------------------------------------------- +(defconst desktop--excluded-frame-parameters + '(buffer-list + buffer-predicate + buried-buffer-list + explicit-name + font-backend + minibuffer + name + outer-window-id + parent-id + window-id + window-system) + "Frame parameters not saved or restored.") + +(defun desktop--filter-frame-parms (frame) + "Return frame parameters of FRAME. +Parameters in `desktop--excluded-frame-parameters' are excluded. +Internal use only." + (let (params) + (dolist (param (frame-parameters frame)) + (unless (memq (car param) desktop--excluded-frame-parameters) + (push param params))) + params)) + +(defun desktop--save-windows () + "Save window/frame state, as a global variable. +Intended to be called from `desktop-save'. +Internal use only." + (setq desktop--saved-states + (and desktop-save-windows + (mapcar (lambda (frame) + (cons (desktop--filter-frame-parms frame) + (window-state-get (frame-root-window frame) t))) + (frame-list)))) + (desktop-outvar 'desktop--saved-states)) + ;;;###autoload (defun desktop-save (dirname &optional release auto-save) "Save the desktop in a desktop file. @@ -896,6 +941,9 @@ and don't save the buffer if they are the same." (save-excursion (run-hooks 'desktop-save-hook)) (goto-char (point-max)) (insert "\n;; Global section:\n") + ;; Called here because we save the window/frame state as a global + ;; variable for compatibility with previous Emacsen. + (desktop--save-windows) (mapc (function desktop-outvar) desktop-globals-to-save) (when (memq 'kill-ring desktop-globals-to-save) (insert @@ -954,6 +1002,37 @@ This function also sets `desktop-dirname' to nil." (defvar desktop-lazy-timer nil) ;; ---------------------------------------------------------------------------- +(defun desktop--find-frame-in-display (frames display) + (let (result) + (while (and frames (not result)) + (if (equal display (frame-parameter (car frames) 'display)) + (setq result (car frames)) + (setq frames (cdr frames)))) + result)) + +(defun desktop--restore-windows () + "Restore window/frame configuration. +Internal use only." + (when (and desktop-save-windows desktop--saved-states) + (condition-case nil + (let ((frames (frame-list))) + (dolist (state desktop--saved-states) + (let* ((fconfig (car state)) + (display (cdr (assq 'display fconfig))) + (frame (desktop--find-frame-in-display frames display))) + (if (not frame) + ;; no frames in the display -- make a new one + (setq frame (make-frame-on-display display fconfig)) + ;; found one -- reuse and remove from list + (setq frames (delq frame frames)) + (modify-frame-parameters frame fconfig)) + ;; restore windows + (window-state-put (cdr state) (frame-root-window frame) 'safe))) + ;; delete any remaining frames + (mapc #'delete-frame frames)) + (error + (message "Error loading window configuration from desktop file"))))) + ;;;###autoload (defun desktop-read (&optional dirname) "Read and process the desktop file in directory DIRNAME. @@ -1022,6 +1101,7 @@ Using it may cause conflicts. Use it anyway? " owner))))) (switch-to-buffer (car (buffer-list))) (run-hooks 'desktop-delay-hook) (setq desktop-delay-hook nil) + (desktop--restore-windows) (run-hooks 'desktop-after-read-hook) (message "Desktop: %d buffer%s restored%s%s." desktop-buffer-ok-count -- 2.39.2