aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuanma Barranquero2014-03-11 01:46:07 +0100
committerJuanma Barranquero2014-03-11 01:46:07 +0100
commit4538c058d073cedeff92a50211b415a2e57c3469 (patch)
treee7c8b9beaa515042c850052ab37a789e21ba26f4
parentf38145ba81691d60f3a8e3198e4754359c8b8a55 (diff)
downloademacs-4538c058d073cedeff92a50211b415a2e57c3469.tar.gz
emacs-4538c058d073cedeff92a50211b415a2e57c3469.zip
lisp/frameset.el: Separate frame reusing from cleaning up.
* lisp/desktop.el (desktop-restore-forces-onscreen) (desktop-restore-reuses-frames): Use non-keyword values. (desktop-restore-frameset): Use CLEANUP-FRAMES arg of frameset-restore. * lisp/frameset.el: Separate options for reusing frames and cleaning up. (frameset--reuse-list): Remove definition; declare. (frameset--action-map): Declare. (frameset--find-frame-if): Doc fix. (frameset--restore-frame): Cache frame action. (frameset-restore): New keyword arg CLEANUP-FRAMES, allows to select how to clean up the frame list after restoring. Remove cleaning options from REUSE-FRAMES. Change all keyword values to symbols. (frameset--jump-to-register): Simplify by using CLEANUP-FRAMES.
-rw-r--r--lisp/ChangeLog16
-rw-r--r--lisp/desktop.el11
-rw-r--r--lisp/frameset.el188
3 files changed, 130 insertions, 85 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index e17872e2347..81f70435627 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,19 @@
12014-03-11 Juanma Barranquero <lekktu@gmail.com>
2
3 * frameset.el: Separate options for reusing frames and cleaning up.
4 (frameset--reuse-list): Remove definition; declare.
5 (frameset--action-map): Declare.
6 (frameset--find-frame-if): Doc fix.
7 (frameset--restore-frame): Cache frame action.
8 (frameset-restore): New keyword arg CLEANUP-FRAMES, allows to select
9 how to clean up the frame list after restoring. Remove cleaning
10 options from REUSE-FRAMES. Change all keyword values to symbols.
11 (frameset--jump-to-register): Simplify by using CLEANUP-FRAMES.
12
13 * desktop.el (desktop-restore-forces-onscreen)
14 (desktop-restore-reuses-frames): Use non-keyword values.
15 (desktop-restore-frameset): Use CLEANUP-FRAMES arg of frameset-restore.
16
12014-03-10 Glenn Morris <rgm@gnu.org> 172014-03-10 Glenn Morris <rgm@gnu.org>
2 18
3 * files.el (find-file): Doc fix: update info node name. 19 * files.el (find-file): Doc fix: update info node name.
diff --git a/lisp/desktop.el b/lisp/desktop.el
index 0677b8c85dd..dbddfb7c1d3 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -404,12 +404,12 @@ If `delete', frames on other displays are deleted instead of restored."
404 404
405(defcustom desktop-restore-forces-onscreen t 405(defcustom desktop-restore-forces-onscreen t
406 "If t, offscreen frames are restored onscreen instead. 406 "If t, offscreen frames are restored onscreen instead.
407If `:all', frames that are partially offscreen are also forced onscreen. 407If `all', frames that are partially offscreen are also forced onscreen.
408NOTE: Checking of frame boundaries is only approximate and can fail 408NOTE: Checking of frame boundaries is only approximate and can fail
409to reliably detect frames whose onscreen/offscreen state depends on a 409to reliably detect frames whose onscreen/offscreen state depends on a
410few pixels, especially near the right / bottom borders of the screen." 410few pixels, especially near the right / bottom borders of the screen."
411 :type '(choice (const :tag "Only fully offscreen frames" t) 411 :type '(choice (const :tag "Only fully offscreen frames" t)
412 (const :tag "Also partially offscreen frames" :all) 412 (const :tag "Also partially offscreen frames" all)
413 (const :tag "Do not force frames onscreen" nil)) 413 (const :tag "Do not force frames onscreen" nil))
414 :group 'desktop 414 :group 'desktop
415 :version "24.4") 415 :version "24.4")
@@ -417,7 +417,7 @@ few pixels, especially near the right / bottom borders of the screen."
417(defcustom desktop-restore-reuses-frames t 417(defcustom desktop-restore-reuses-frames t
418 "If t, restoring frames reuses existing frames. 418 "If t, restoring frames reuses existing frames.
419If nil, existing frames are deleted. 419If nil, existing frames are deleted.
420If `:keep', existing frames are kept and not reused." 420If `keep', existing frames are kept and not reused."
421 :type '(choice (const :tag "Reuse existing frames" t) 421 :type '(choice (const :tag "Reuse existing frames" t)
422 (const :tag "Delete existing frames" nil) 422 (const :tag "Delete existing frames" nil)
423 (const :tag "Keep existing frames" :keep)) 423 (const :tag "Keep existing frames" :keep))
@@ -692,7 +692,7 @@ if different)."
692 (frame-parameter frame 'desktop-dont-clear)) 692 (frame-parameter frame 'desktop-dont-clear))
693 (delete-frame frame)) 693 (delete-frame frame))
694 (error 694 (error
695 (delay-warning 'desktop (error-message-string err)))))))) 695 (delay-warning 'desktop (error-message-string err))))))))
696 696
697;; ---------------------------------------------------------------------------- 697;; ----------------------------------------------------------------------------
698(unless noninteractive 698(unless noninteractive
@@ -1058,7 +1058,8 @@ This function depends on the value of `desktop-saved-frameset'
1058being set (usually, by reading it from the desktop)." 1058being set (usually, by reading it from the desktop)."
1059 (when (desktop-restoring-frameset-p) 1059 (when (desktop-restoring-frameset-p)
1060 (frameset-restore desktop-saved-frameset 1060 (frameset-restore desktop-saved-frameset
1061 :reuse-frames desktop-restore-reuses-frames 1061 :reuse-frames (eq desktop-restore-reuses-frames t)
1062 :cleanup-frames (not (eq desktop-restore-reuses-frames 'keep))
1062 :force-display desktop-restore-in-current-display 1063 :force-display desktop-restore-in-current-display
1063 :force-onscreen desktop-restore-forces-onscreen))) 1064 :force-onscreen desktop-restore-forces-onscreen)))
1064 1065
diff --git a/lisp/frameset.el b/lisp/frameset.el
index d6742d89632..5cd921d5f17 100644
--- a/lisp/frameset.el
+++ b/lisp/frameset.el
@@ -786,10 +786,9 @@ PROPERTIES is a user-defined property list to add to the frameset."
786 786
787;; Restoring framesets 787;; Restoring framesets
788 788
789(defvar frameset--reuse-list nil 789;; Dynamically bound in `frameset-restore'.
790 "The list of frames potentially reusable. 790(defvar frameset--reuse-list)
791Its value is only meaningful during execution of `frameset-restore'. 791(defvar frameset--action-map)
792Internal use only.")
793 792
794(defun frameset-compute-pos (value left/top right/bottom) 793(defun frameset-compute-pos (value left/top right/bottom)
795 "Return an absolute positioning value for a frame. 794 "Return an absolute positioning value for a frame.
@@ -871,7 +870,7 @@ NOTE: This only works for non-iconified frames."
871 (modify-frame-parameters frame params)))))) 870 (modify-frame-parameters frame params))))))
872 871
873(defun frameset--find-frame-if (predicate display &rest args) 872(defun frameset--find-frame-if (predicate display &rest args)
874 "Find a frame in `frameset--reuse-list' satisfying PREDICATE. 873 "Find a reusable frame satisfying PREDICATE.
875Look through available frames whose display property matches DISPLAY 874Look through available frames whose display property matches DISPLAY
876and return the first one for which (PREDICATE frame ARGS) returns t. 875and return the first one for which (PREDICATE frame ARGS) returns t.
877If PREDICATE is nil, it is always satisfied. Internal use only." 876If PREDICATE is nil, it is always satisfied. Internal use only."
@@ -982,16 +981,20 @@ Internal use only."
982 (push visible alt-cfg) 981 (push visible alt-cfg)
983 (push (cons 'fullscreen fullscreen) alt-cfg))) 982 (push (cons 'fullscreen fullscreen) alt-cfg)))
984 983
985 ;; Time to find or create a frame an apply the big bunch of parameters. 984 ;; Time to find or create a frame and apply the big bunch of parameters.
986 ;; If a frame needs to be created and it falls partially or fully offscreen, 985 (setq frame (and frameset--reuse-list
987 ;; sometimes it gets "pushed back" onscreen; however, moving it afterwards is 986 (frameset--reuse-frame display filtered-cfg)))
988 ;; allowed. So we create the frame as invisible and then reapply the full 987 (if frame
989 ;; parameter alist (including position and size parameters). 988 (puthash frame :reused frameset--action-map)
990 (setq frame (or (and frameset--reuse-list 989 ;; If a frame needs to be created and it falls partially or fully offscreen,
991 (frameset--reuse-frame display filtered-cfg)) 990 ;; sometimes it gets "pushed back" onscreen; however, moving it afterwards is
992 (make-frame-on-display display 991 ;; allowed. So we create the frame as invisible and then reapply the full
993 (cons '(visibility) 992 ;; parameter alist (including position and size parameters).
994 (frameset--initial-params filtered-cfg))))) 993 (setq frame (make-frame-on-display display
994 (cons '(visibility)
995 (frameset--initial-params filtered-cfg))))
996 (puthash frame :created frameset--action-map))
997
995 (modify-frame-parameters frame 998 (modify-frame-parameters frame
996 (if (eq (frame-parameter frame 'fullscreen) fullscreen) 999 (if (eq (frame-parameter frame 'fullscreen) fullscreen)
997 ;; Workaround for bug#14949 1000 ;; Workaround for bug#14949
@@ -1038,7 +1041,8 @@ For the meaning of FORCE-DISPLAY, see `frameset-restore'."
1038;;;###autoload 1041;;;###autoload
1039(cl-defun frameset-restore (frameset 1042(cl-defun frameset-restore (frameset
1040 &key predicate filters reuse-frames 1043 &key predicate filters reuse-frames
1041 force-display force-onscreen) 1044 force-display force-onscreen
1045 cleanup-frames)
1042 "Restore a FRAMESET into the current display(s). 1046 "Restore a FRAMESET into the current display(s).
1043 1047
1044PREDICATE is a function called with two arguments, the parameter alist 1048PREDICATE is a function called with two arguments, the parameter alist
@@ -1050,58 +1054,79 @@ and window-state is not restored.
1050FILTERS is an alist of parameter filters; if nil, the value of 1054FILTERS is an alist of parameter filters; if nil, the value of
1051`frameset-filter-alist' is used instead. 1055`frameset-filter-alist' is used instead.
1052 1056
1053REUSE-FRAMES selects the policy to use to reuse frames when restoring: 1057REUSE-FRAMES selects the policy to reuse frames when restoring:
1054 t Reuse existing frames if possible, and delete those not reused. 1058 t All existing frames can be reused.
1055 nil Restore frameset in new frames and delete existing frames. 1059 nil No existing frame can be reused.
1056 :keep Restore frameset in new frames and keep the existing ones. 1060 match Only frames with matching frame ids can be reused.
1057 LIST A list of frames to reuse; only these are reused (if possible). 1061 PRED A predicate function; it receives as argument a live frame,
1058 Remaining frames in this list are deleted; other frames not 1062 and must return non-nil to allow reusing it, nil otherwise.
1059 included on the list are left untouched.
1060 1063
1061FORCE-DISPLAY can be: 1064FORCE-DISPLAY can be:
1062 t Frames are restored in the current display. 1065 t Frames are restored in the current display.
1063 nil Frames are restored, if possible, in their original displays. 1066 nil Frames are restored, if possible, in their original displays.
1064 :delete Frames in other displays are deleted instead of restored. 1067 delete Frames in other displays are deleted instead of restored.
1065 PRED A function called with two arguments, the parameter alist and 1068 PRED A function called with two arguments, the parameter alist and
1066 the window state (in that order). It must return t, nil or 1069 the window state (in that order). It must return t, nil or
1067 `:delete', as above but affecting only the frame that will 1070 `delete', as above but affecting only the frame that will
1068 be created from that parameter alist. 1071 be created from that parameter alist.
1069 1072
1070FORCE-ONSCREEN can be: 1073FORCE-ONSCREEN can be:
1071 t Force onscreen only those frames that are fully offscreen. 1074 t Force onscreen only those frames that are fully offscreen.
1072 nil Do not force any frame back onscreen. 1075 nil Do not force any frame back onscreen.
1073 :all Force onscreen any frame fully or partially offscreen. 1076 all Force onscreen any frame fully or partially offscreen.
1074 PRED A function called with three arguments, 1077 PRED A function called with three arguments,
1075 - the live frame just restored, 1078 - the live frame just restored,
1076 - a list (LEFT TOP WIDTH HEIGHT), describing the frame, 1079 - a list (LEFT TOP WIDTH HEIGHT), describing the frame,
1077 - a list (LEFT TOP WIDTH HEIGHT), describing the workarea. 1080 - a list (LEFT TOP WIDTH HEIGHT), describing the workarea.
1078 It must return non-nil to force the frame onscreen, nil otherwise. 1081 It must return non-nil to force the frame onscreen, nil otherwise.
1079 1082
1083CLEANUP-FRAMES allows to \"clean up\" the frame list after restoring a frameset:
1084 t Delete all frames that were not created or restored upon.
1085 nil Keep all frames.
1086 FUNC A function called with two arguments:
1087 - FRAME, a live frame.
1088 - ACTION, which can be one of
1089 :rejected Frame existed, but was not a candidate for reuse.
1090 :ignored Frame existed, was a candidate, but wasn't reused.
1091 :reused Frame existed, was a candidate, and restored upon.
1092 :created Frame didn't exist, was created and restored upon.
1093 Return value is ignored.
1094
1080Note the timing and scope of the operations described above: REUSE-FRAMES 1095Note the timing and scope of the operations described above: REUSE-FRAMES
1081affects existing frames; PREDICATE, FILTERS and FORCE-DISPLAY affect the frame 1096affects existing frames; PREDICATE, FILTERS and FORCE-DISPLAY affect the frame
1082being restored before that happens; and FORCE-ONSCREEN affects the frame once 1097being restored before that happens; FORCE-ONSCREEN affects the frame once
1083it has been restored. 1098it has been restored; and CLEANUP-FRAMES affects all frames alive after the
1099restoration, including those that have been reused or created anew.
1084 1100
1085All keyword parameters default to nil." 1101All keyword parameters default to nil."
1086 1102
1087 (cl-assert (frameset-valid-p frameset)) 1103 (cl-assert (frameset-valid-p frameset))
1088 1104
1089 (let (other-frames) 1105 (let* ((frames (frame-list))
1090 1106 (frameset--action-map (make-hash-table :test #'eq))
1091 ;; frameset--reuse-list is a list of frames potentially reusable. Later we 1107 ;; frameset--reuse-list is a list of frames potentially reusable. Later we
1092 ;; will decide which ones can be reused, and how to deal with any leftover. 1108 ;; will decide which ones can be reused, and how to deal with any leftover.
1093 (pcase reuse-frames 1109 (frameset--reuse-list
1094 ((or `nil `:keep) 1110 (pcase reuse-frames
1095 (setq frameset--reuse-list nil 1111 (`t
1096 other-frames (frame-list))) 1112 frames)
1097 ((pred consp) 1113 (`nil
1098 (setq frameset--reuse-list (copy-sequence reuse-frames) 1114 nil)
1099 other-frames (cl-delete-if (lambda (frame) 1115 (`match
1100 (memq frame frameset--reuse-list)) 1116 (cl-loop for (state) in (frameset-states frameset)
1101 (frame-list)))) 1117 when (frameset-frame-with-id (frameset-cfg-id state) frames)
1102 (_ 1118 collect it))
1103 (setq frameset--reuse-list (frame-list) 1119 ((pred functionp)
1104 other-frames nil))) 1120 (cl-remove-if-not reuse-frames frames))
1121 (_
1122 (error "Invalid arg :reuse-frames %s" reuse-frames)))))
1123
1124 ;; Mark existing frames in the map; candidates to reuse are marked as :ignored;
1125 ;; they will be reassigned later, if chosen.
1126 (dolist (frame frames)
1127 (puthash frame
1128 (if (memq frame frameset--reuse-list) :ignored :rejected)
1129 frameset--action-map))
1105 1130
1106 ;; Sort saved states to guarantee that minibufferless frames will be created 1131 ;; Sort saved states to guarantee that minibufferless frames will be created
1107 ;; after the frames that contain their minibuffer windows. 1132 ;; after the frames that contain their minibuffer windows.
@@ -1131,17 +1156,15 @@ All keyword parameters default to nil."
1131 ;; - we're switching displays, and the user chose the option to delete, or 1156 ;; - we're switching displays, and the user chose the option to delete, or
1132 ;; - we're switching to tty, and the frame to restore is minibuffer-only. 1157 ;; - we're switching to tty, and the frame to restore is minibuffer-only.
1133 (unless (and frameset--target-display 1158 (unless (and frameset--target-display
1134 (or (eq force-display :delete) 1159 (or (eq force-display 'delete)
1135 (and to-tty 1160 (and to-tty
1136 (eq (cdr (assq 'minibuffer frame-cfg)) 'only)))) 1161 (eq (cdr (assq 'minibuffer frame-cfg)) 'only))))
1137 ;; To avoid duplicating frame ids after restoration, we note any 1162 ;; To avoid duplicating frame ids after restoration, we note any
1138 ;; existing frame whose id matches a frame configuration in the 1163 ;; existing frame whose id matches a frame configuration in the
1139 ;; frameset. Once the frame config is properly restored, we can 1164 ;; frameset. Once the frame config is properly restored, we can
1140 ;; reset the old frame's id to nil. 1165 ;; reset the old frame's id to nil.
1141 (setq duplicate (and other-frames 1166 (setq duplicate (frameset-frame-with-id (frameset-cfg-id frame-cfg)
1142 (or (eq reuse-frames :keep) (consp reuse-frames)) 1167 frames))
1143 (frameset-frame-with-id (frameset-cfg-id frame-cfg)
1144 other-frames)))
1145 ;; Restore minibuffers. Some of this stuff could be done in a filter 1168 ;; Restore minibuffers. Some of this stuff could be done in a filter
1146 ;; function, but it would be messy because restoring minibuffers affects 1169 ;; function, but it would be messy because restoring minibuffers affects
1147 ;; global state; it's best to do it here than add a bunch of global 1170 ;; global state; it's best to do it here than add a bunch of global
@@ -1187,20 +1210,27 @@ All keyword parameters default to nil."
1187 ;; other frames are already visible (discussed in thread for bug#14841). 1210 ;; other frames are already visible (discussed in thread for bug#14841).
1188 (sit-for 0 t) 1211 (sit-for 0 t)
1189 1212
1190 ;; Delete remaining frames, but do not fail if some resist being deleted. 1213 ;; Clean temporary caches
1191 (unless (eq reuse-frames :keep) 1214 (setq frameset--target-display nil)
1192 (dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames) 1215
1193 frameset--reuse-list) 1216 ;; Clean up the frame list
1194 ;; Minibufferless frames must go first to avoid 1217 (when cleanup-frames
1195 ;; errors when attempting to delete a frame whose 1218 (let ((map nil)
1196 ;; minibuffer window is used by another frame. 1219 (cleanup (if (eq cleanup-frames t)
1197 #'frameset-minibufferless-first-p)) 1220 (lambda (frame action)
1198 (condition-case err 1221 (when (memq action '(:rejected :ignored))
1199 (delete-frame frame) 1222 (delete-frame frame)))
1200 (error 1223 cleanup-frames)))
1201 (delay-warning 'frameset (error-message-string err)))))) 1224 (maphash (lambda (frame _action) (push frame map)) frameset--action-map)
1202 (setq frameset--reuse-list nil 1225 (dolist (frame (sort map
1203 frameset--target-display nil) 1226 ;; Minibufferless frames must go first to avoid
1227 ;; errors when attempting to delete a frame whose
1228 ;; minibuffer window is used by another frame.
1229 #'frameset-minibufferless-first-p))
1230 (condition-case-unless-debug err
1231 (funcall cleanup frame (gethash frame frameset--action-map))
1232 (error
1233 (delay-warning 'frameset (error-message-string err) :warning))))))
1204 1234
1205 ;; Make sure there's at least one visible frame. 1235 ;; Make sure there's at least one visible frame.
1206 (unless (or (daemonp) (visible-frame-list)) 1236 (unless (or (daemonp) (visible-frame-list))
@@ -1212,23 +1242,21 @@ All keyword parameters default to nil."
1212(defun frameset--jump-to-register (data) 1242(defun frameset--jump-to-register (data)
1213 "Restore frameset from DATA stored in register. 1243 "Restore frameset from DATA stored in register.
1214Called from `jump-to-register'. Internal use only." 1244Called from `jump-to-register'. Internal use only."
1215 (let ((fs (aref data 0)) 1245 (frameset-restore
1216 reuse-frames iconify-list) 1246 (aref data 0)
1217 (if current-prefix-arg 1247 :filters frameset-session-filter-alist
1218 ;; Reuse all frames and delete any left unused 1248 :reuse-frames (if current-prefix-arg t 'match)
1219 (setq reuse-frames t) 1249 :cleanup-frames (if current-prefix-arg
1220 ;; Reuse matching frames and leave others to be iconified 1250 ;; delete frames
1221 (setq iconify-list (frame-list)) 1251 nil
1222 (dolist (state (frameset-states fs)) 1252 ;; iconify frames
1223 (let ((frame (frameset-frame-with-id (frameset-cfg-id (car state)) 1253 (lambda (frame action)
1224 iconify-list))) 1254 (pcase action
1225 (when frame 1255 (`rejected (iconify-frame frame))
1226 (push frame reuse-frames) 1256 ;; In the unexpected case that a frame was a candidate
1227 (setq iconify-list (delq frame iconify-list)))))) 1257 ;; (matching frame id) and yet not restored, remove it
1228 (frameset-restore fs 1258 ;; because it is in fact a duplicate.
1229 :filters frameset-session-filter-alist 1259 (`ignored (delete-frame frame))))))
1230 :reuse-frames reuse-frames)
1231 (mapc #'iconify-frame iconify-list))
1232 1260
1233 ;; Restore selected frame, buffer and point. 1261 ;; Restore selected frame, buffer and point.
1234 (let ((frame (frameset-frame-with-id (aref data 1))) 1262 (let ((frame (frameset-frame-with-id (aref data 1)))