aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuanma Barranquero2013-08-05 06:45:17 +0200
committerJuanma Barranquero2013-08-05 06:45:17 +0200
commit063233c357f823efc7abd61469725a42da90a1a6 (patch)
treef2f422781966236d2123ca89b8e8ddf74df4fb1c
parent8f3a2c2659ddee1ae84b4b8bb28f6c388f87fd0f (diff)
downloademacs-063233c357f823efc7abd61469725a42da90a1a6.tar.gz
emacs-063233c357f823efc7abd61469725a42da90a1a6.zip
* lisp/frameset.el: Miscellaneous cleanups.
(frameset): Add docstring. Move :version property to its own `version' slot. (frameset-copy): Rename from copy-frameset. (frameset-p): Check more thoroughly. (frameset-prop): Do not check for :version, which is no longer a prop. (frameset-live-filter-alist, frameset-persistent-filter-alist): Use new :never value instead of t. (frameset-filter-alist): Expand and clarify docstring. (frameset-filter-tty-to-GUI, frameset-filter-sanitize-color) (frameset-filter-minibuffer, frameset-filter-save-param) (frameset-filter-restore-param, frameset-filter-iconified): Add pointer to docstring of frameset-filter-alist. (frameset-filter-params): Rename filter values to be more meaningful: :never instead of t, and reverse the meanings of :save and :restore. (frameset--process-minibuffer-frames): Clarify error message. (frameset-save): Avoid unnecessary and confusing call to framep. Use new BOA constructor for framesets. (frameset--reuse-list): Doc fix. (frameset--restore-frame): Rename from frameset--get-frame. Doc fix. (frameset--minibufferless-last-p): Rename from frameset--sort-states. (frameset-minibufferless-first-p): Doc fix. Rename from frameset-sort-frames-for-deletion. (frameset-restore): Doc fixes. Use new function names. Most changes suggested by Drew Adams <drew.adams@oracle.com>. * lisp/desktop.el (desktop-clear): Use new name of sort predicate.
-rw-r--r--lisp/ChangeLog29
-rw-r--r--lisp/desktop.el2
-rw-r--r--lisp/frameset.el294
3 files changed, 208 insertions, 117 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index de1da73bbb1..0c4240c9075 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,32 @@
12013-08-05 Juanma Barranquero <lekktu@gmail.com>
2
3 * desktop.el (desktop-clear): Use new name of sort predicate.
4
5 * frameset.el (frameset): Add docstring. Move :version property to its
6 own `version' slot.
7 (frameset-copy): Rename from copy-frameset.
8 (frameset-p): Check more thoroughly.
9 (frameset-prop): Do not check for :version, which is no longer a prop.
10 (frameset-live-filter-alist, frameset-persistent-filter-alist):
11 Use new :never value instead of t.
12 (frameset-filter-alist): Expand and clarify docstring.
13 (frameset-filter-tty-to-GUI, frameset-filter-sanitize-color)
14 (frameset-filter-minibuffer, frameset-filter-save-param)
15 (frameset-filter-restore-param, frameset-filter-iconified):
16 Add pointer to docstring of frameset-filter-alist.
17 (frameset-filter-params): Rename filter values to be more meaningful:
18 :never instead of t, and reverse the meanings of :save and :restore.
19 (frameset--process-minibuffer-frames): Clarify error message.
20 (frameset-save): Avoid unnecessary and confusing call to framep.
21 Use new BOA constructor for framesets.
22 (frameset--reuse-list): Doc fix.
23 (frameset--restore-frame): Rename from frameset--get-frame. Doc fix.
24 (frameset--minibufferless-last-p): Rename from frameset--sort-states.
25 (frameset-minibufferless-first-p): Doc fix.
26 Rename from frameset-sort-frames-for-deletion.
27 (frameset-restore): Doc fixes. Use new function names.
28 Most changes suggested by Drew Adams <drew.adams@oracle.com>.
29
12013-08-04 Juanma Barranquero <lekktu@gmail.com> 302013-08-04 Juanma Barranquero <lekktu@gmail.com>
2 31
3 * desktop.el (desktop-restore-forces-onscreen) 32 * desktop.el (desktop-restore-forces-onscreen)
diff --git a/lisp/desktop.el b/lisp/desktop.el
index ab78663c3d0..76aa30e4090 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -671,7 +671,7 @@ if different)."
671 (called-interactively-p 'any)) 671 (called-interactively-p 'any))
672 (let* ((this (selected-frame)) 672 (let* ((this (selected-frame))
673 (mini (window-frame (minibuffer-window this)))) ; in case they difer 673 (mini (window-frame (minibuffer-window this)))) ; in case they difer
674 (dolist (frame (sort (frame-list) #'frameset-sort-frames-for-deletion)) 674 (dolist (frame (sort (frame-list) #'frameset-minibufferless-first-p))
675 (condition-case err 675 (condition-case err
676 (unless (or (eq frame this) 676 (unless (or (eq frame this)
677 (eq frame mini) 677 (eq frame mini)
diff --git a/lisp/frameset.el b/lisp/frameset.el
index b24e4ed9362..c22d71b7d79 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -41,48 +41,77 @@
41(require 'cl-lib) 41(require 'cl-lib)
42 42
43 43
44;; Framesets have two fields:
45;; - properties: a property list to store both frameset-specific and
46;; user-defined serializable data. Currently defined properties
47;; include:
48;; :version ID - Identifies the version of the frameset struct;
49;; this is the only property always present and
50;; must not be modified.
51;; :app APPINFO - Freeform. Can be used by applications and
52;; packages to indicate the intended (but by no
53;; means exclusive) use of the frameset. For
54;; example, currently desktop.el sets :app to
55;; `(desktop . ,desktop-file-version).
56;; :name NAME - The name of the frameset instance; a string.
57;; :desc TEXT - A description for user consumption (to choose
58;; among framesets, etc.); a string.
59;; - states: an alist of items (FRAME-PARAMETERS . WINDOW-STATE) in
60;; no particular order. Each item represents a frame to be
61;; restored.
62
63(cl-defstruct (frameset (:type list) :named 44(cl-defstruct (frameset (:type list) :named
64 (:copier nil) 45 (:copier nil)
65 (:predicate nil)) 46 (:predicate nil)
66 properties ;; property list 47 ;; A BOA constructor, not the default "keywordy" one.
67 states) ;; list of conses (frame-state . window-state) 48 (:constructor make-frameset (properties states)))
68 49
69(defun copy-frameset (frameset) 50 "A frameset encapsulates a serializable view of a set of frames and windows.
51
52It contains the following slots, which can be accessed with
53\(frameset-SLOT fs) and set with (setf (frameset-SLOT fs) VALUE):
54
55 version A non-modifiable version number, identifying the format
56 of the frameset struct. Currently its value is 1.
57 properties A property list, to store both frameset-specific and
58 user-defined serializable data (some suggested properties
59 are described below).
60 states An alist of items (FRAME-PARAMETERS . WINDOW-STATE), in no
61 particular order. Each item represents a frame to be
62 restored. FRAME-PARAMETERS is a frame's parameter list,
63 extracted with (frame-parameters FRAME) and filtered through
64 `frame-parameters-alist' or a similar filter alist.
65 WINDOW-STATE is the output of `window-state-get', when
66 applied to the root window of the frame.
67
68Some suggested properties:
69
70 :app APPINFO Can be used by applications and packages to indicate the
71 intended (but by no means exclusive) use of the frameset.
72 Freeform. For example, currently desktop.el framesets set
73 :app to `(desktop . ,desktop-file-version).
74 :name NAME The name of the frameset instance; a string.
75 :desc TEXT A description for user consumption (to show in a menu to
76 choose among framesets, etc.); a string.
77
78A frameset is intended to be used through the following simple API:
79
80 - `frameset-save' captures all or a subset of the live frames, and returns
81 a serializable snapshot of them (a frameset).
82 - `frameset-restore' takes a frameset, and restores the frames and windows
83 it describes, as faithfully as possible.
84 - `frameset-p' is the predicate for the frameset type. It returns nil
85 for non-frameset objects, and the frameset version number (see below)
86 for frameset objects.
87 - `frameset-copy' returns a deep copy of a frameset.
88 - `frameset-prop' is a `setf'able accessor for the contents of the
89 `properties' slot.
90 - The `frameset-SLOT' accessors described above."
91
92 (version 1 :read-only t)
93 properties states)
94
95(defun frameset-copy (frameset)
70 "Return a copy of FRAMESET. 96 "Return a copy of FRAMESET.
71This is a deep copy done with `copy-tree'." 97This is a deep copy done with `copy-tree'."
72 (copy-tree frameset t)) 98 (copy-tree frameset t))
73 99
74;;;###autoload 100;;;###autoload
75(defun frameset-p (frameset) 101(defun frameset-p (frameset)
76 "If FRAMESET is a frameset, return its :version. 102 "If FRAMESET is a frameset, return its version number.
77Else return nil." 103Else return nil."
78 (and (eq (car-safe frameset) 'frameset) 104 (and (eq (car-safe frameset) 'frameset) ; is a list
79 (plist-get (cl-second frameset) :version))) 105 (integerp (nth 1 frameset)) ; version is an int
106 (nth 2 frameset) ; properties is non-null
107 (nth 3 frameset) ; states is non-null
108 (nth 1 frameset))) ; return version
80 109
81;; A setf'able accessor to the frameset's properties 110;; A setf'able accessor to the frameset's properties
82(defun frameset-prop (frameset prop) 111(defun frameset-prop (frameset prop)
83 "Return the value of the PROP property of FRAMESET. 112 "Return the value of the PROP property of FRAMESET.
84 113
85Properties other than :version can be set with 114Properties can be set with
86 115
87 (setf (frameset-prop FRAMESET PROP) NEW-VALUE)" 116 (setf (frameset-prop FRAMESET PROP) NEW-VALUE)"
88 (plist-get (frameset-properties frameset) prop)) 117 (plist-get (frameset-properties frameset) prop))
@@ -90,7 +119,6 @@ Properties other than :version can be set with
90(gv-define-setter frameset-prop (val fs prop) 119(gv-define-setter frameset-prop (val fs prop)
91 (macroexp-let2 nil v val 120 (macroexp-let2 nil v val
92 `(progn 121 `(progn
93 (cl-assert (not (eq ,prop :version)) t ":version can not be set")
94 (setf (frameset-properties ,fs) 122 (setf (frameset-properties ,fs)
95 (plist-put (frameset-properties ,fs) ,prop ,v)) 123 (plist-put (frameset-properties ,fs) ,prop ,v))
96 ,v))) 124 ,v)))
@@ -100,7 +128,7 @@ Properties other than :version can be set with
100 128
101;;;###autoload 129;;;###autoload
102(defvar frameset-live-filter-alist 130(defvar frameset-live-filter-alist
103 '((name . t) 131 '((name . :never)
104 (minibuffer . frameset-filter-minibuffer) 132 (minibuffer . frameset-filter-minibuffer)
105 (top . frameset-filter-iconified)) 133 (top . frameset-filter-iconified))
106 "Minimum set of parameters to filter for live (on-session) framesets. 134 "Minimum set of parameters to filter for live (on-session) framesets.
@@ -110,25 +138,25 @@ See `frameset-filter-alist' for a full description.")
110(defvar frameset-persistent-filter-alist 138(defvar frameset-persistent-filter-alist
111 (nconc 139 (nconc
112 '((background-color . frameset-filter-sanitize-color) 140 '((background-color . frameset-filter-sanitize-color)
113 (buffer-list . t) 141 (buffer-list . :never)
114 (buffer-predicate . t) 142 (buffer-predicate . :never)
115 (buried-buffer-list . t) 143 (buried-buffer-list . :never)
116 (font . frameset-filter-save-parm) 144 (font . frameset-filter-save-param)
117 (foreground-color . frameset-filter-sanitize-color) 145 (foreground-color . frameset-filter-sanitize-color)
118 (fullscreen . frameset-filter-save-parm) 146 (fullscreen . frameset-filter-save-param)
119 (GUI:font . frameset-filter-restore-parm) 147 (GUI:font . frameset-filter-restore-param)
120 (GUI:fullscreen . frameset-filter-restore-parm) 148 (GUI:fullscreen . frameset-filter-restore-param)
121 (GUI:height . frameset-filter-restore-parm) 149 (GUI:height . frameset-filter-restore-param)
122 (GUI:width . frameset-filter-restore-parm) 150 (GUI:width . frameset-filter-restore-param)
123 (height . frameset-filter-save-parm) 151 (height . frameset-filter-save-param)
124 (left . frameset-filter-iconified) 152 (left . frameset-filter-iconified)
125 (outer-window-id . t) 153 (outer-window-id . :never)
126 (parent-id . t) 154 (parent-id . :never)
127 (tty . frameset-filter-tty-to-GUI) 155 (tty . frameset-filter-tty-to-GUI)
128 (tty-type . frameset-filter-tty-to-GUI) 156 (tty-type . frameset-filter-tty-to-GUI)
129 (width . frameset-filter-save-parm) 157 (width . frameset-filter-save-param)
130 (window-id . t) 158 (window-id . :never)
131 (window-system . t)) 159 (window-system . :never))
132 frameset-live-filter-alist) 160 frameset-live-filter-alist)
133 "Recommended set of parameters to filter for persistent framesets. 161 "Recommended set of parameters to filter for persistent framesets.
134See `frameset-filter-alist' for a full description.") 162See `frameset-filter-alist' for a full description.")
@@ -137,35 +165,48 @@ See `frameset-filter-alist' for a full description.")
137(defvar frameset-filter-alist frameset-persistent-filter-alist 165(defvar frameset-filter-alist frameset-persistent-filter-alist
138 "Alist of frame parameters and filtering functions. 166 "Alist of frame parameters and filtering functions.
139 167
140Each element is a cons (PARAM . ACTION), where PARAM is a parameter 168This alist is the default value of the :filters arguments of
141name (a symbol identifying a frame parameter), and ACTION can be: 169`frameset-save' and `frameset-restore' (which see). On saving,
142 170PARAMETERS is the parameter list of each frame processed, and
143 t The parameter is always removed from the parameter list. 171FILTERED is the parameter list that gets saved to the frameset.
144 :save The parameter is removed when saving the frame. 172On restoring, PARAMETERS is the parameter list extracted from the
145 :restore The parameter is removed when restoring the frame. 173frameset, and FILTERED is the resulting frame parameter list used
174to restore the frame.
175
176Elements of this alist are conses (PARAM . ACTION), where PARAM
177is a parameter name (a symbol identifying a frame parameter), and
178ACTION can be:
179
180 nil The parameter is copied to FILTERED.
181 :never The parameter is never copied to FILTERED.
182 :save The parameter is copied only when saving the frame.
183 :restore The parameter is copied only when restoring the frame.
146 FILTER A filter function. 184 FILTER A filter function.
147 185
148FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...). 186FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...).
149It will be called with four arguments CURRENT, FILTERED, PARAMETERS 187FILTER-FUN is called with four arguments CURRENT, FILTERED, PARAMETERS and
150and SAVING, plus any additional ARGS: 188SAVING, plus any additional ARGS:
151 189
152 CURRENT A cons (PARAM . VALUE), where PARAM is the one being 190 CURRENT A cons (PARAM . VALUE), where PARAM is the one being
153 filtered and VALUE is its current value. 191 filtered and VALUE is its current value.
154 FILTERED The alist of parameters filtered so far. 192 FILTERED The resulting alist (so far).
155 PARAMETERS The complete alist of parameters being filtered, 193 PARAMETERS The complete alist of parameters being filtered,
156 SAVING Non-nil if filtering before saving state, nil otherwise. 194 SAVING Non-nil if filtering before saving state, nil if filtering
195 before restoring it.
157 196
158The FILTER-FUN function must return: 197FILTER-FUN must return:
159 nil CURRENT is removed from the list. 198 nil Skip CURRENT (do not add it to FILTERED).
160 t CURRENT is left as is. 199 t Add CURRENT to FILTERED as is.
161 (PARAM' . VALUE') Replace CURRENT with this. 200 (NEW-PARAM . NEW-VALUE) Add this to FILTERED instead of CURRENT.
201
202Frame parameters not on this alist are passed intact, as if they were
203defined with ACTION = nil.")
162 204
163Frame parameters not on this list are passed intact.")
164 205
165(defvar frameset--target-display nil 206(defvar frameset--target-display nil
166 ;; Either (minibuffer . VALUE) or nil. 207 ;; Either (minibuffer . VALUE) or nil.
167 ;; This refers to the current frame config being processed inside 208 ;; This refers to the current frame config being processed inside
168 ;; `frame--restore-frames' and its auxiliary functions (like filtering). 209 ;; `frameset-restore' and its auxiliary functions (like filtering).
169 ;; If nil, there is no need to change the display. 210 ;; If nil, there is no need to change the display.
170 ;; If non-nil, display parameter to use when creating the frame. 211 ;; If non-nil, display parameter to use when creating the frame.
171 "Internal use only.") 212 "Internal use only.")
@@ -191,30 +232,42 @@ Only meaningful when called from a filtering function in
191 (null (cdr frameset--target-display)))) ; to a tty 232 (null (cdr frameset--target-display)))) ; to a tty
192 233
193(defun frameset-filter-tty-to-GUI (_current _filtered parameters saving) 234(defun frameset-filter-tty-to-GUI (_current _filtered parameters saving)
194 "Remove CURRENT when switching from tty to a graphic display." 235 "Remove CURRENT when switching from tty to a graphic display.
236
237For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
238see the docstring of `frameset-filter-alist'."
195 (or saving 239 (or saving
196 (not (frameset-switch-to-gui-p parameters)))) 240 (not (frameset-switch-to-gui-p parameters))))
197 241
198(defun frameset-filter-sanitize-color (current _filtered parameters saving) 242(defun frameset-filter-sanitize-color (current _filtered parameters saving)
199 "When switching to a GUI frame, remove \"unspecified\" colors. 243 "When switching to a GUI frame, remove \"unspecified\" colors.
200Useful as a filter function for tty-specific parameters." 244Useful as a filter function for tty-specific parameters.
245
246For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
247see the docstring of `frameset-filter-alist'."
201 (or saving 248 (or saving
202 (not (frameset-switch-to-gui-p parameters)) 249 (not (frameset-switch-to-gui-p parameters))
203 (not (stringp (cdr current))) 250 (not (stringp (cdr current)))
204 (not (string-match-p "^unspecified-[fb]g$" (cdr current))))) 251 (not (string-match-p "^unspecified-[fb]g$" (cdr current)))))
205 252
206(defun frameset-filter-minibuffer (current _filtered _parameters saving) 253(defun frameset-filter-minibuffer (current _filtered _parameters saving)
207 "When saving, convert (minibuffer . #<window>) parameter to (minibuffer . t)." 254 "When saving, convert (minibuffer . #<window>) parameter to (minibuffer . t).
255
256For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
257see the docstring of `frameset-filter-alist'."
208 (or (not saving) 258 (or (not saving)
209 (if (windowp (cdr current)) 259 (if (windowp (cdr current))
210 '(minibuffer . t) 260 '(minibuffer . t)
211 t))) 261 t)))
212 262
213(defun frameset-filter-save-parm (current _filtered parameters saving 263(defun frameset-filter-save-param (current _filtered parameters saving
214 &optional prefix) 264 &optional prefix)
215 "When switching to a tty frame, save parameter P as PREFIX:P. 265 "When switching to a tty frame, save parameter P as PREFIX:P.
216The parameter can be later restored with `frameset-filter-restore-parm'. 266The parameter can be later restored with `frameset-filter-restore-param'.
217PREFIX defaults to `GUI'." 267PREFIX defaults to `GUI'.
268
269For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
270see the docstring of `frameset-filter-alist'."
218 (unless prefix (setq prefix 'GUI)) 271 (unless prefix (setq prefix 'GUI))
219 (cond (saving t) 272 (cond (saving t)
220 ((frameset-switch-to-tty-p parameters) 273 ((frameset-switch-to-tty-p parameters)
@@ -226,9 +279,12 @@ PREFIX defaults to `GUI'."
226 (not (assq (intern (format "%s:%s" prefix (car current))) parameters))) 279 (not (assq (intern (format "%s:%s" prefix (car current))) parameters)))
227 (t t))) 280 (t t)))
228 281
229(defun frameset-filter-restore-parm (current filtered parameters saving) 282(defun frameset-filter-restore-param (current filtered parameters saving)
230 "When switching to a GUI frame, restore PREFIX:P parameter as P. 283 "When switching to a GUI frame, restore PREFIX:P parameter as P.
231CURRENT must be of the form (PREFIX:P . value)." 284CURRENT must be of the form (PREFIX:P . value).
285
286For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
287see the docstring of `frameset-filter-alist'."
232 (or saving 288 (or saving
233 (not (frameset-switch-to-gui-p parameters)) 289 (not (frameset-switch-to-gui-p parameters))
234 (let* ((prefix:p (symbol-name (car current))) 290 (let* ((prefix:p (symbol-name (car current)))
@@ -243,9 +299,12 @@ CURRENT must be of the form (PREFIX:P . value)."
243 299
244(defun frameset-filter-iconified (_current _filtered parameters saving) 300(defun frameset-filter-iconified (_current _filtered parameters saving)
245 "Remove CURRENT when saving an iconified frame. 301 "Remove CURRENT when saving an iconified frame.
246This is used for positions parameters `left' and `top', which are 302This is used for positional parameters `left' and `top', which are
247meaningless in an iconified frame, so the frame is restored in a 303meaningless in an iconified frame, so the frame is restored in a
248default position." 304default position.
305
306For the meaning of CURRENT, FILTERED, PARAMETERS and SAVING,
307see the docstring of `frameset-filter-alist'."
249 (not (and saving (eq (cdr (assq 'visibility parameters)) 'icon)))) 308 (not (and saving (eq (cdr (assq 'visibility parameters)) 'icon))))
250 309
251(defun frameset-filter-params (parameters filter-alist saving) 310(defun frameset-filter-params (parameters filter-alist saving)
@@ -259,11 +318,11 @@ nil while the filtering is done to restore it."
259 (pcase (cdr (assq (car current) filter-alist)) 318 (pcase (cdr (assq (car current) filter-alist))
260 (`nil 319 (`nil
261 (push current filtered)) 320 (push current filtered))
262 (`t 321 (:never
263 nil) 322 nil)
264 (:save
265 (unless saving (push current filtered)))
266 (:restore 323 (:restore
324 (unless saving (push current filtered)))
325 (:save
267 (when saving (push current filtered))) 326 (when saving (push current filtered)))
268 ((or `(,fun . ,args) (and fun (pred fboundp))) 327 ((or `(,fun . ,args) (and fun (pred fboundp)))
269 (let ((this (apply fun current filtered parameters saving args))) 328 (let ((this (apply fun current filtered parameters saving args)))
@@ -313,7 +372,7 @@ FRAME-LIST is a list of frames. Internal use only."
313 (let* ((mb-frame (window-frame (minibuffer-window frame))) 372 (let* ((mb-frame (window-frame (minibuffer-window frame)))
314 (id (and mb-frame (frame-parameter mb-frame 'frameset--id)))) 373 (id (and mb-frame (frame-parameter mb-frame 'frameset--id))))
315 (if (null id) 374 (if (null id)
316 (error "Minibuffer frame %S for %S is excluded" mb-frame frame) 375 (error "Minibuffer frame %S for %S is not being saved" mb-frame frame)
317 ;; For minibufferless frames, frameset--mini is a cons 376 ;; For minibufferless frames, frameset--mini is a cons
318 ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id 377 ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id
319 ;; of the frame containing its minibuffer window. 378 ;; of the frame containing its minibuffer window.
@@ -329,27 +388,29 @@ FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'.
329PREDICATE is a predicate function, which must return non-nil for frames that 388PREDICATE is a predicate function, which must return non-nil for frames that
330should be saved; it defaults to saving all frames from FRAME-LIST. 389should be saved; it defaults to saving all frames from FRAME-LIST.
331PROPERTIES is a user-defined property list to add to the frameset." 390PROPERTIES is a user-defined property list to add to the frameset."
332 (let ((frames (cl-delete-if-not #'frame-live-p 391 (let* ((list (or (copy-sequence frame-list) (frame-list)))
333 (cl-delete-if-not (or predicate #'framep) 392 (frames (cl-delete-if-not #'frame-live-p
334 (or (copy-sequence frame-list) 393 (if predicate
335 (frame-list)))))) 394 (cl-delete-if-not predicate list)
395 list))))
336 (frameset--process-minibuffer-frames frames) 396 (frameset--process-minibuffer-frames frames)
337 (make-frameset :properties (append '(:version 1) properties) 397 (make-frameset properties
338 :states (mapcar 398 (mapcar
339 (lambda (frame) 399 (lambda (frame)
340 (cons 400 (cons
341 (frameset-filter-params (frame-parameters frame) 401 (frameset-filter-params (frame-parameters frame)
342 (or filters 402 (or filters frameset-filter-alist)
343 frameset-filter-alist) 403 t)
344 t) 404 (window-state-get (frame-root-window frame) t)))
345 (window-state-get (frame-root-window frame) t))) 405 frames))))
346 frames))))
347 406
348 407
349;; Restoring framesets 408;; Restoring framesets
350 409
351(defvar frameset--reuse-list nil 410(defvar frameset--reuse-list nil
352 "Internal use only.") 411 "The list of frames potentially reusable.
412Its value is only meaningful during execution of `frameset-restore'.
413Internal use only.")
353 414
354(defun frameset--compute-pos (value left/top right/bottom) 415(defun frameset--compute-pos (value left/top right/bottom)
355 (pcase value 416 (pcase value
@@ -494,11 +555,11 @@ Internal use only."
494 (cl-loop for param in '(left top with height border-width minibuffer) 555 (cl-loop for param in '(left top with height border-width minibuffer)
495 collect (assq param frame-cfg))) 556 collect (assq param frame-cfg)))
496 557
497(defun frameset--get-frame (frame-cfg window-cfg filters force-onscreen) 558(defun frameset--restore-frame (frame-cfg window-cfg filters force-onscreen)
498 "Set up and return a frame according to its saved state. 559 "Set up and return a frame according to its saved state.
499That means either reusing an existing frame or creating one anew. 560That means either reusing an existing frame or creating one anew.
500FRAME-CFG is the frame's parameter list; WINDOW-CFG is its window state. 561FRAME-CFG is the frame's parameter list; WINDOW-CFG is its window state.
501For the meaning of FORCE-ONSCREEN, see `frameset-restore'. 562For the meaning of FILTERS and FORCE-ONSCREEN, see `frameset-restore'.
502Internal use only." 563Internal use only."
503 (let* ((fullscreen (cdr (assq 'fullscreen frame-cfg))) 564 (let* ((fullscreen (cdr (assq 'fullscreen frame-cfg)))
504 (lines (assq 'tool-bar-lines frame-cfg)) 565 (lines (assq 'tool-bar-lines frame-cfg))
@@ -563,7 +624,7 @@ Internal use only."
563 (window-state-put window-cfg (frame-root-window frame) 'safe) 624 (window-state-put window-cfg (frame-root-window frame) 'safe)
564 frame)) 625 frame))
565 626
566(defun frameset--sort-states (state1 state2) 627(defun frameset--minibufferless-last-p (state1 state2)
567 "Predicate to sort frame states in a suitable order to be created. 628 "Predicate to sort frame states in a suitable order to be created.
568It sorts minibuffer-owning frames before minibufferless ones." 629It sorts minibuffer-owning frames before minibufferless ones."
569 (pcase-let ((`(,hasmini1 ,id-def1) (assq 'frameset--mini (car state1))) 630 (pcase-let ((`(,hasmini1 ,id-def1) (assq 'frameset--mini (car state1)))
@@ -580,10 +641,8 @@ It sorts minibuffer-owning frames before minibufferless ones."
580 ((eq system-type 'windows-nt) nil) 641 ((eq system-type 'windows-nt) nil)
581 (t (not force-display)))) 642 (t (not force-display))))
582 643
583(defun frameset-sort-frames-for-deletion (frame1 _frame2) 644(defun frameset-minibufferless-first-p (frame1 _frame2)
584 "Predicate to sort live frames for deletion. 645 "Predicate to sort minibufferless frames before other frames."
585Minibufferless frames must go first to avoid errors when attempting
586to delete a frame whose minibuffer window is used by another frame."
587 (not (frame-parameter frame1 'minibuffer))) 646 (not (frame-parameter frame1 'minibuffer)))
588 647
589;;;###autoload 648;;;###autoload
@@ -593,31 +652,31 @@ to delete a frame whose minibuffer window is used by another frame."
593 652
594FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'. 653FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'.
595 654
596REUSE-FRAMES describes how to reuse existing frames while restoring a frameset: 655REUSE-FRAMES selects the policy to use to reuse frames when restoring:
597 t Reuse any existing frame if possible; delete leftover frames. 656 t Reuse any existing frame if possible; delete leftover frames.
598 nil Restore frameset in new frames and delete existing frames. 657 nil Restore frameset in new frames and delete existing frames.
599 :keep Restore frameset in new frames and keep the existing ones. 658 :keep Restore frameset in new frames and keep the existing ones.
600 LIST A list of frames to reuse; only these will be reused, if possible, 659 LIST A list of frames to reuse; only these are reused (if possible),
601 and any leftover one will be deleted; other frames not on this 660 and any leftover ones are deleted; other frames not on this
602 list will be kept. 661 list are left untouched.
603 662
604FORCE-DISPLAY can be: 663FORCE-DISPLAY can be:
605 t Frames will be restored in the current display. 664 t Frames are restored in the current display.
606 nil Frames will be restored, if possible, in their original displays. 665 nil Frames are restored, if possible, in their original displays.
607 :delete Frames in other displays will be deleted instead of restored. 666 :delete Frames in other displays are deleted instead of restored.
608 PRED A function which will be called with one argument, the parameter 667 PRED A function called with one argument, the parameter list;
609 list, and must return t, nil or `:delete', as above but affecting 668 it must return t, nil or `:delete', as above but affecting
610 only the frame that will be created from that parameter list. 669 only the frame that will be created from that parameter list.
611 670
612FORCE-ONSCREEN can be: 671FORCE-ONSCREEN can be:
613 :all Force onscreen any frame fully or partially offscreen.
614 t Force onscreen only those frames that are fully offscreen. 672 t Force onscreen only those frames that are fully offscreen.
615 nil Do not force any frame back onscreen. 673 nil Do not force any frame back onscreen.
616 PRED A function which will be called with three arguments, 674 :all Force onscreen any frame fully or partially offscreen.
675 PRED A function called with three arguments,
617 - the live frame just restored, 676 - the live frame just restored,
618 - a list (LEFT TOP WIDTH HEIGHT), describing the frame, 677 - a list (LEFT TOP WIDTH HEIGHT), describing the frame,
619 - a list (LEFT TOP WIDTH HEIGHT), describing the workarea, 678 - a list (LEFT TOP WIDTH HEIGHT), describing the workarea.
620 and must return non-nil to force the frame onscreen, nil otherwise. 679 It must return non-nil to force the frame onscreen, nil otherwise.
621 680
622Note the timing and scope of the operations described above: REUSE-FRAMES 681Note the timing and scope of the operations described above: REUSE-FRAMES
623affects existing frames, FILTERS and FORCE-DISPLAY affect the frame being 682affects existing frames, FILTERS and FORCE-DISPLAY affect the frame being
@@ -648,7 +707,7 @@ All keywords default to nil."
648 ;; Sort saved states to guarantee that minibufferless frames will be created 707 ;; Sort saved states to guarantee that minibufferless frames will be created
649 ;; after the frames that contain their minibuffer windows. 708 ;; after the frames that contain their minibuffer windows.
650 (dolist (state (sort (copy-sequence (frameset-states frameset)) 709 (dolist (state (sort (copy-sequence (frameset-states frameset))
651 #'frameset--sort-states)) 710 #'frameset--minibufferless-last-p))
652 (condition-case-unless-debug err 711 (condition-case-unless-debug err
653 (pcase-let* ((`(,frame-cfg . ,window-cfg) state) 712 (pcase-let* ((`(,frame-cfg . ,window-cfg) state)
654 ((and d-mini `(,hasmini . ,mb-id)) 713 ((and d-mini `(,hasmini . ,mb-id))
@@ -716,9 +775,9 @@ All keywords default to nil."
716 (push (cons 'minibuffer mb-window) frame-cfg))))) 775 (push (cons 'minibuffer mb-window) frame-cfg)))))
717 ;; OK, we're ready at last to create (or reuse) a frame and 776 ;; OK, we're ready at last to create (or reuse) a frame and
718 ;; restore the window config. 777 ;; restore the window config.
719 (setq frame (frameset--get-frame frame-cfg window-cfg 778 (setq frame (frameset--restore-frame frame-cfg window-cfg
720 (or filters frameset-filter-alist) 779 (or filters frameset-filter-alist)
721 force-onscreen)) 780 force-onscreen))
722 ;; Set default-minibuffer if required. 781 ;; Set default-minibuffer if required.
723 (when default (setq default-minibuffer-frame frame)))) 782 (when default (setq default-minibuffer-frame frame))))
724 (error 783 (error
@@ -732,7 +791,10 @@ All keywords default to nil."
732 (unless (eq reuse-frames :keep) 791 (unless (eq reuse-frames :keep)
733 (dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames) 792 (dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames)
734 frameset--reuse-list) 793 frameset--reuse-list)
735 #'frameset-sort-frames-for-deletion)) 794 ;; Minibufferless frames must go first to avoid
795 ;; errors when attempting to delete a frame whose
796 ;; minibuffer window is used by another frame.
797 #'frameset-minibufferless-first-p))
736 (condition-case err 798 (condition-case err
737 (delete-frame frame) 799 (delete-frame frame)
738 (error 800 (error