diff options
| author | Juanma Barranquero | 2013-08-05 00:12:18 +0200 |
|---|---|---|
| committer | Juanma Barranquero | 2013-08-05 00:12:18 +0200 |
| commit | d5671a82b8b78b5fd8d83cfc15642d2c0eff6de2 (patch) | |
| tree | b77fc2966aca90b9ac1e72dbd73d86ea652374df | |
| parent | 016d3f7ddcc9afd60c455cbf4dd79277080c4d4e (diff) | |
| download | emacs-d5671a82b8b78b5fd8d83cfc15642d2c0eff6de2.tar.gz emacs-d5671a82b8b78b5fd8d83cfc15642d2c0eff6de2.zip | |
* lisp/frameset.el: Add new predicate values for frameset-restore args.
(frameset-live-filter-alist, frameset-persistent-filter-alist):
New variables.
(frameset-filter-alist): Use them. Add autoload cookie.
(frameset-filter-tty-to-GUI): Move from desktop.el and rename.
(frameset--set-id, frameset--reuse-frame): Rename `frame-id' to
`frameset--id' (it's supposed to be internal to frameset.el).
(frameset--process-minibuffer-frames): Ditto. Doc fix.
(frameset--initial-params): New function.
(frameset--get-frame): Use it. Doc fix.
(frameset--move-onscreen): Accept new PRED value for FORCE-ONSCREEN.
Accept :all, not 'all.
(frameset-restore): Add new predicate values for FORCE-ONSCREEN and
FORCE-DISPLAY. Use :keywords for constant arguments to avoid collision
with fbound symbols. Fix frame id matching, and remove matching ids if
the frame being restored is deleted. Obey :delete.
* lisp/desktop.el (desktop-restore-forces-onscreen)
(desktop-restore-reuses-frames): Document :keyword constant values.
(desktop-filter-parameters-alist): Remove, now identical to
frameset-filter-alist.
(desktop--filter-tty*): Remove, moved to frameset.el.
(desktop-save-frameset, desktop-restore-frameset):
Do not pass :filters argument.
| -rw-r--r-- | lisp/ChangeLog | 26 | ||||
| -rw-r--r-- | lisp/desktop.el | 29 | ||||
| -rw-r--r-- | lisp/frameset.el | 289 |
3 files changed, 202 insertions, 142 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 66bf7422b0d..de1da73bbb1 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,29 @@ | |||
| 1 | 2013-08-04 Juanma Barranquero <lekktu@gmail.com> | ||
| 2 | |||
| 3 | * desktop.el (desktop-restore-forces-onscreen) | ||
| 4 | (desktop-restore-reuses-frames): Document :keyword constant values. | ||
| 5 | (desktop-filter-parameters-alist): Remove, now identical to | ||
| 6 | frameset-filter-alist. | ||
| 7 | (desktop--filter-tty*): Remove, moved to frameset.el. | ||
| 8 | (desktop-save-frameset, desktop-restore-frameset): | ||
| 9 | Do not pass :filters argument. | ||
| 10 | |||
| 11 | * frameset.el (frameset-live-filter-alist) | ||
| 12 | (frameset-persistent-filter-alist): New variables. | ||
| 13 | (frameset-filter-alist): Use them. Add autoload cookie. | ||
| 14 | (frameset-filter-tty-to-GUI): Move from desktop.el and rename. | ||
| 15 | (frameset--set-id, frameset--reuse-frame): Rename `frame-id' to | ||
| 16 | `frameset--id' (it's supposed to be internal to frameset.el). | ||
| 17 | (frameset--process-minibuffer-frames): Ditto. Doc fix. | ||
| 18 | (frameset--initial-params): New function. | ||
| 19 | (frameset--get-frame): Use it. Doc fix. | ||
| 20 | (frameset--move-onscreen): Accept new PRED value for FORCE-ONSCREEN. | ||
| 21 | Accept :all, not 'all. | ||
| 22 | (frameset-restore): Add new predicate values for FORCE-ONSCREEN and | ||
| 23 | FORCE-DISPLAY. Use :keywords for constant arguments to avoid collision | ||
| 24 | with fbound symbols. Fix frame id matching, and remove matching ids if | ||
| 25 | the frame being restored is deleted. Obey :delete. | ||
| 26 | |||
| 1 | 2013-08-04 Stefan Monnier <monnier@iro.umontreal.ca> | 27 | 2013-08-04 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 28 | ||
| 3 | * subr.el (macrop): New function. | 29 | * subr.el (macrop): New function. |
diff --git a/lisp/desktop.el b/lisp/desktop.el index 778c37484e1..ab78663c3d0 100644 --- a/lisp/desktop.el +++ b/lisp/desktop.el | |||
| @@ -390,12 +390,12 @@ If `delete', frames on other displays are deleted instead of restored." | |||
| 390 | 390 | ||
| 391 | (defcustom desktop-restore-forces-onscreen t | 391 | (defcustom desktop-restore-forces-onscreen t |
| 392 | "If t, offscreen frames are restored onscreen instead. | 392 | "If t, offscreen frames are restored onscreen instead. |
| 393 | If `all', frames that are partially offscreen are also forced onscren. | 393 | If `:all', frames that are partially offscreen are also forced onscren. |
| 394 | NOTE: Checking of frame boundaries is only approximate and can fail | 394 | NOTE: Checking of frame boundaries is only approximate and can fail |
| 395 | to reliably detect frames whose onscreen/offscreen state depends on a | 395 | to reliably detect frames whose onscreen/offscreen state depends on a |
| 396 | few pixels, especially near the right / bottom borders of the screen." | 396 | few pixels, especially near the right / bottom borders of the screen." |
| 397 | :type '(choice (const :tag "Only fully offscreen frames" t) | 397 | :type '(choice (const :tag "Only fully offscreen frames" t) |
| 398 | (const :tag "Also partially offscreen frames" 'all) | 398 | (const :tag "Also partially offscreen frames" :all) |
| 399 | (const :tag "Do not force frames onscreen" nil)) | 399 | (const :tag "Do not force frames onscreen" nil)) |
| 400 | :group 'desktop | 400 | :group 'desktop |
| 401 | :version "24.4") | 401 | :version "24.4") |
| @@ -403,10 +403,10 @@ few pixels, especially near the right / bottom borders of the screen." | |||
| 403 | (defcustom desktop-restore-reuses-frames t | 403 | (defcustom desktop-restore-reuses-frames t |
| 404 | "If t, restoring frames reuses existing frames. | 404 | "If t, restoring frames reuses existing frames. |
| 405 | If nil, existing frames are deleted. | 405 | If nil, existing frames are deleted. |
| 406 | If `keep', existing frames are kept and not reused." | 406 | If `:keep', existing frames are kept and not reused." |
| 407 | :type '(choice (const :tag "Reuse existing frames" t) | 407 | :type '(choice (const :tag "Reuse existing frames" t) |
| 408 | (const :tag "Delete existing frames" nil) | 408 | (const :tag "Delete existing frames" nil) |
| 409 | (const :tag "Keep existing frames" 'keep)) | 409 | (const :tag "Keep existing frames" :keep)) |
| 410 | :group 'desktop | 410 | :group 'desktop |
| 411 | :version "24.4") | 411 | :version "24.4") |
| 412 | 412 | ||
| @@ -900,25 +900,6 @@ DIRNAME must be the directory in which the desktop file will be saved." | |||
| 900 | 900 | ||
| 901 | 901 | ||
| 902 | ;; ---------------------------------------------------------------------------- | 902 | ;; ---------------------------------------------------------------------------- |
| 903 | (defvar desktop-filter-parameters-alist | ||
| 904 | (append '((font-backend . t) | ||
| 905 | (name . t) | ||
| 906 | (outer-window-id . t) | ||
| 907 | (parent-id . t) | ||
| 908 | (tty . desktop--filter-tty*) | ||
| 909 | (tty-type . desktop--filter-tty*) | ||
| 910 | (window-id . t) | ||
| 911 | (window-system . t)) | ||
| 912 | frameset-filter-alist) | ||
| 913 | "Alist of frame parameters and filtering functions. | ||
| 914 | Its format is identical to `frameset-filter-alist' (which see).") | ||
| 915 | |||
| 916 | (defun desktop--filter-tty* (_current parameters saving) | ||
| 917 | ;; Remove tty and tty-type parameters when switching | ||
| 918 | ;; to a GUI frame. | ||
| 919 | (or saving | ||
| 920 | (not (frameset-switch-to-gui-p parameters)))) | ||
| 921 | |||
| 922 | (defun desktop--check-dont-save (frame) | 903 | (defun desktop--check-dont-save (frame) |
| 923 | (not (frame-parameter frame 'desktop-dont-save))) | 904 | (not (frame-parameter frame 'desktop-dont-save))) |
| 924 | 905 | ||
| @@ -932,7 +913,6 @@ Frames with a non-nil `desktop-dont-save' parameter are not saved." | |||
| 932 | (let ((name (concat user-login-name "@" system-name | 913 | (let ((name (concat user-login-name "@" system-name |
| 933 | (format-time-string " %Y-%m-%d %T")))) | 914 | (format-time-string " %Y-%m-%d %T")))) |
| 934 | (frameset-save nil | 915 | (frameset-save nil |
| 935 | :filters desktop-filter-parameters-alist | ||
| 936 | :predicate #'desktop--check-dont-save | 916 | :predicate #'desktop--check-dont-save |
| 937 | :properties (list :app desktop--app-id | 917 | :properties (list :app desktop--app-id |
| 938 | :name name)))))) | 918 | :name name)))))) |
| @@ -1049,7 +1029,6 @@ This function depends on the value of `desktop-saved-frameset' | |||
| 1049 | being set (usually, by reading it from the desktop)." | 1029 | being set (usually, by reading it from the desktop)." |
| 1050 | (when (desktop-restoring-frameset-p) | 1030 | (when (desktop-restoring-frameset-p) |
| 1051 | (frameset-restore desktop-saved-frameset | 1031 | (frameset-restore desktop-saved-frameset |
| 1052 | :filters desktop-filter-parameters-alist | ||
| 1053 | :reuse-frames desktop-restore-reuses-frames | 1032 | :reuse-frames desktop-restore-reuses-frames |
| 1054 | :force-display desktop-restore-in-current-display | 1033 | :force-display desktop-restore-in-current-display |
| 1055 | :force-onscreen desktop-restore-forces-onscreen))) | 1034 | :force-onscreen desktop-restore-forces-onscreen))) |
diff --git a/lisp/frameset.el b/lisp/frameset.el index 2a6a0d2dfb8..b24e4ed9362 100644 --- a/lisp/frameset.el +++ b/lisp/frameset.el | |||
| @@ -46,16 +46,16 @@ | |||
| 46 | ;; user-defined serializable data. Currently defined properties | 46 | ;; user-defined serializable data. Currently defined properties |
| 47 | ;; include: | 47 | ;; include: |
| 48 | ;; :version ID - Identifies the version of the frameset struct; | 48 | ;; :version ID - Identifies the version of the frameset struct; |
| 49 | ;; this is the only property always present and | 49 | ;; this is the only property always present and |
| 50 | ;; must not be modified. | 50 | ;; must not be modified. |
| 51 | ;; :app APPINFO - Freeform. Can be used by applications and | 51 | ;; :app APPINFO - Freeform. Can be used by applications and |
| 52 | ;; packages to indicate the intended (but by no | 52 | ;; packages to indicate the intended (but by no |
| 53 | ;; means exclusive) use of the frameset. For | 53 | ;; means exclusive) use of the frameset. For |
| 54 | ;; example, currently desktop.el sets :app to | 54 | ;; example, currently desktop.el sets :app to |
| 55 | ;; `(desktop . ,desktop-file-version). | 55 | ;; `(desktop . ,desktop-file-version). |
| 56 | ;; :name NAME - The name of the frameset instance; a string. | 56 | ;; :name NAME - The name of the frameset instance; a string. |
| 57 | ;; :desc TEXT - A description for user consumption (to choose | 57 | ;; :desc TEXT - A description for user consumption (to choose |
| 58 | ;; among framesets, etc.); a string. | 58 | ;; among framesets, etc.); a string. |
| 59 | ;; - states: an alist of items (FRAME-PARAMETERS . WINDOW-STATE) in | 59 | ;; - states: an alist of items (FRAME-PARAMETERS . WINDOW-STATE) in |
| 60 | ;; no particular order. Each item represents a frame to be | 60 | ;; no particular order. Each item represents a frame to be |
| 61 | ;; restored. | 61 | ;; restored. |
| @@ -98,46 +98,66 @@ Properties other than :version can be set with | |||
| 98 | 98 | ||
| 99 | ;; Filtering | 99 | ;; Filtering |
| 100 | 100 | ||
| 101 | (defvar frameset-filter-alist | 101 | ;;;###autoload |
| 102 | '((background-color . frameset-filter-sanitize-color) | 102 | (defvar frameset-live-filter-alist |
| 103 | (buffer-list . t) | 103 | '((name . t) |
| 104 | (buffer-predicate . t) | 104 | (minibuffer . frameset-filter-minibuffer) |
| 105 | (buried-buffer-list . t) | 105 | (top . frameset-filter-iconified)) |
| 106 | (font . frameset-filter-save-parm) | 106 | "Minimum set of parameters to filter for live (on-session) framesets. |
| 107 | (foreground-color . frameset-filter-sanitize-color) | 107 | See `frameset-filter-alist' for a full description.") |
| 108 | (fullscreen . frameset-filter-save-parm) | 108 | |
| 109 | (GUI:font . frameset-filter-restore-parm) | 109 | ;;;###autoload |
| 110 | (GUI:fullscreen . frameset-filter-restore-parm) | 110 | (defvar frameset-persistent-filter-alist |
| 111 | (GUI:height . frameset-filter-restore-parm) | 111 | (nconc |
| 112 | (GUI:width . frameset-filter-restore-parm) | 112 | '((background-color . frameset-filter-sanitize-color) |
| 113 | (height . frameset-filter-save-parm) | 113 | (buffer-list . t) |
| 114 | (left . frameset-filter-iconified) | 114 | (buffer-predicate . t) |
| 115 | (minibuffer . frameset-filter-minibuffer) | 115 | (buried-buffer-list . t) |
| 116 | (top . frameset-filter-iconified) | 116 | (font . frameset-filter-save-parm) |
| 117 | (width . frameset-filter-save-parm)) | 117 | (foreground-color . frameset-filter-sanitize-color) |
| 118 | (fullscreen . frameset-filter-save-parm) | ||
| 119 | (GUI:font . frameset-filter-restore-parm) | ||
| 120 | (GUI:fullscreen . frameset-filter-restore-parm) | ||
| 121 | (GUI:height . frameset-filter-restore-parm) | ||
| 122 | (GUI:width . frameset-filter-restore-parm) | ||
| 123 | (height . frameset-filter-save-parm) | ||
| 124 | (left . frameset-filter-iconified) | ||
| 125 | (outer-window-id . t) | ||
| 126 | (parent-id . t) | ||
| 127 | (tty . frameset-filter-tty-to-GUI) | ||
| 128 | (tty-type . frameset-filter-tty-to-GUI) | ||
| 129 | (width . frameset-filter-save-parm) | ||
| 130 | (window-id . t) | ||
| 131 | (window-system . t)) | ||
| 132 | frameset-live-filter-alist) | ||
| 133 | "Recommended set of parameters to filter for persistent framesets. | ||
| 134 | See `frameset-filter-alist' for a full description.") | ||
| 135 | |||
| 136 | ;;;###autoload | ||
| 137 | (defvar frameset-filter-alist frameset-persistent-filter-alist | ||
| 118 | "Alist of frame parameters and filtering functions. | 138 | "Alist of frame parameters and filtering functions. |
| 119 | 139 | ||
| 120 | Each element is a cons (PARAM . ACTION), where PARAM is a parameter | 140 | Each element is a cons (PARAM . ACTION), where PARAM is a parameter |
| 121 | name (a symbol identifying a frame parameter), and ACTION can be: | 141 | name (a symbol identifying a frame parameter), and ACTION can be: |
| 122 | 142 | ||
| 123 | t The parameter is always removed from the parameter list. | 143 | t The parameter is always removed from the parameter list. |
| 124 | :save The parameter is removed when saving the frame. | 144 | :save The parameter is removed when saving the frame. |
| 125 | :restore The parameter is removed when restoring the frame. | 145 | :restore The parameter is removed when restoring the frame. |
| 126 | FILTER A filter function. | 146 | FILTER A filter function. |
| 127 | 147 | ||
| 128 | FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...). | 148 | FILTER can be a symbol FILTER-FUN, or a list (FILTER-FUN ARGS...). |
| 129 | It will be called with four arguments CURRENT, FILTERED, PARAMETERS | 149 | It will be called with four arguments CURRENT, FILTERED, PARAMETERS |
| 130 | and SAVING, plus any additional ARGS: | 150 | and SAVING, plus any additional ARGS: |
| 131 | 151 | ||
| 132 | CURRENT A cons (PARAM . VALUE), where PARAM is the one being | 152 | CURRENT A cons (PARAM . VALUE), where PARAM is the one being |
| 133 | filtered and VALUE is its current value. | 153 | filtered and VALUE is its current value. |
| 134 | FILTERED The alist of parameters filtered so far. | 154 | FILTERED The alist of parameters filtered so far. |
| 135 | PARAMETERS The complete alist of parameters being filtered, | 155 | PARAMETERS The complete alist of parameters being filtered, |
| 136 | SAVING Non-nil if filtering before saving state, nil otherwise. | 156 | SAVING Non-nil if filtering before saving state, nil otherwise. |
| 137 | 157 | ||
| 138 | The FILTER-FUN function must return: | 158 | The FILTER-FUN function must return: |
| 139 | nil CURRENT is removed from the list. | 159 | nil CURRENT is removed from the list. |
| 140 | t CURRENT is left as is. | 160 | t CURRENT is left as is. |
| 141 | (PARAM' . VALUE') Replace CURRENT with this. | 161 | (PARAM' . VALUE') Replace CURRENT with this. |
| 142 | 162 | ||
| 143 | Frame parameters not on this list are passed intact.") | 163 | Frame parameters not on this list are passed intact.") |
| @@ -156,9 +176,9 @@ Return t if PARAMETERS describes a text-only terminal and | |||
| 156 | the target is a graphic display; otherwise return nil. | 176 | the target is a graphic display; otherwise return nil. |
| 157 | Only meaningful when called from a filtering function in | 177 | Only meaningful when called from a filtering function in |
| 158 | `frameset-filter-alist'." | 178 | `frameset-filter-alist'." |
| 159 | (and frameset--target-display ; we're switching | 179 | (and frameset--target-display ; we're switching |
| 160 | (null (cdr (assq 'display parameters))) ; from a tty | 180 | (null (cdr (assq 'display parameters))) ; from a tty |
| 161 | (cdr frameset--target-display))) ; to a GUI display | 181 | (cdr frameset--target-display))) ; to a GUI display |
| 162 | 182 | ||
| 163 | (defun frameset-switch-to-tty-p (parameters) | 183 | (defun frameset-switch-to-tty-p (parameters) |
| 164 | "True when switching to a text-only terminal. | 184 | "True when switching to a text-only terminal. |
| @@ -167,9 +187,14 @@ the target is a text-only terminal; otherwise return nil. | |||
| 167 | Only meaningful when called from a filtering function in | 187 | Only meaningful when called from a filtering function in |
| 168 | `frameset-filter-alist'." | 188 | `frameset-filter-alist'." |
| 169 | (and frameset--target-display ; we're switching | 189 | (and frameset--target-display ; we're switching |
| 170 | (cdr (assq 'display parameters)) ; from a GUI display | 190 | (cdr (assq 'display parameters)) ; from a GUI display |
| 171 | (null (cdr frameset--target-display)))) ; to a tty | 191 | (null (cdr frameset--target-display)))) ; to a tty |
| 172 | 192 | ||
| 193 | (defun frameset-filter-tty-to-GUI (_current _filtered parameters saving) | ||
| 194 | "Remove CURRENT when switching from tty to a graphic display." | ||
| 195 | (or saving | ||
| 196 | (not (frameset-switch-to-gui-p parameters)))) | ||
| 197 | |||
| 173 | (defun frameset-filter-sanitize-color (current _filtered parameters saving) | 198 | (defun frameset-filter-sanitize-color (current _filtered parameters saving) |
| 174 | "When switching to a GUI frame, remove \"unspecified\" colors. | 199 | "When switching to a GUI frame, remove \"unspecified\" colors. |
| 175 | Useful as a filter function for tty-specific parameters." | 200 | Useful as a filter function for tty-specific parameters." |
| @@ -223,12 +248,6 @@ meaningless in an iconified frame, so the frame is restored in a | |||
| 223 | default position." | 248 | default position." |
| 224 | (not (and saving (eq (cdr (assq 'visibility parameters)) 'icon)))) | 249 | (not (and saving (eq (cdr (assq 'visibility parameters)) 'icon)))) |
| 225 | 250 | ||
| 226 | (defun frameset-keep-original-display-p (force-display) | ||
| 227 | "True if saved frames' displays should be honored." | ||
| 228 | (cond ((daemonp) t) | ||
| 229 | ((eq system-type 'windows-nt) nil) | ||
| 230 | (t (null force-display)))) | ||
| 231 | |||
| 232 | (defun frameset-filter-params (parameters filter-alist saving) | 251 | (defun frameset-filter-params (parameters filter-alist saving) |
| 233 | "Filter parameter list PARAMETERS and return a filtered list. | 252 | "Filter parameter list PARAMETERS and return a filtered list. |
| 234 | FILTER-ALIST is an alist of parameter filters, in the format of | 253 | FILTER-ALIST is an alist of parameter filters, in the format of |
| @@ -265,18 +284,18 @@ nil while the filtering is done to restore it." | |||
| 265 | ;; Saving framesets | 284 | ;; Saving framesets |
| 266 | 285 | ||
| 267 | (defun frameset--set-id (frame) | 286 | (defun frameset--set-id (frame) |
| 268 | "Set FRAME's `frame-id' if not yet set. | 287 | "Set FRAME's `frameset--id' if not yet set. |
| 269 | Internal use only." | 288 | Internal use only." |
| 270 | (unless (frame-parameter frame 'frame-id) | 289 | (unless (frame-parameter frame 'frameset--id) |
| 271 | (set-frame-parameter frame | 290 | (set-frame-parameter frame |
| 272 | 'frame-id | 291 | 'frameset--id |
| 273 | (mapconcat (lambda (n) (format "%04X" n)) | 292 | (mapconcat (lambda (n) (format "%04X" n)) |
| 274 | (cl-loop repeat 4 collect (random 65536)) | 293 | (cl-loop repeat 4 collect (random 65536)) |
| 275 | "-")))) | 294 | "-")))) |
| 276 | 295 | ||
| 277 | (defun frameset--process-minibuffer-frames (frame-list) | 296 | (defun frameset--process-minibuffer-frames (frame-list) |
| 278 | "Process FRAME-LIST and record minibuffer relationships. | 297 | "Process FRAME-LIST and record minibuffer relationships. |
| 279 | FRAME-LIST is a list of frames." | 298 | FRAME-LIST is a list of frames. Internal use only." |
| 280 | ;; Record frames with their own minibuffer | 299 | ;; Record frames with their own minibuffer |
| 281 | (dolist (frame (minibuffer-frame-list)) | 300 | (dolist (frame (minibuffer-frame-list)) |
| 282 | (when (memq frame frame-list) | 301 | (when (memq frame frame-list) |
| @@ -292,12 +311,12 @@ FRAME-LIST is a list of frames." | |||
| 292 | (unless (frame-parameter frame 'frameset--mini) | 311 | (unless (frame-parameter frame 'frameset--mini) |
| 293 | (frameset--set-id frame) | 312 | (frameset--set-id frame) |
| 294 | (let* ((mb-frame (window-frame (minibuffer-window frame))) | 313 | (let* ((mb-frame (window-frame (minibuffer-window frame))) |
| 295 | (id (and mb-frame (frame-parameter mb-frame 'frame-id)))) | 314 | (id (and mb-frame (frame-parameter mb-frame 'frameset--id)))) |
| 296 | (if (null id) | 315 | (if (null id) |
| 297 | (error "Minibuffer frame %S for %S is excluded" mb-frame frame) | 316 | (error "Minibuffer frame %S for %S is excluded" mb-frame frame) |
| 298 | ;; For minibufferless frames, frameset--mini is a cons | 317 | ;; For minibufferless frames, frameset--mini is a cons |
| 299 | ;; (nil . FRAME-ID), where FRAME-ID is the frame-id of | 318 | ;; (nil . FRAME-ID), where FRAME-ID is the frameset--id |
| 300 | ;; the frame containing its minibuffer window. | 319 | ;; of the frame containing its minibuffer window. |
| 301 | (set-frame-parameter frame | 320 | (set-frame-parameter frame |
| 302 | 'frameset--mini | 321 | 'frameset--mini |
| 303 | (cons nil id))))))) | 322 | (cons nil id))))))) |
| @@ -345,26 +364,32 @@ When forced onscreen, frames wider than the monitor's workarea are converted | |||
| 345 | to fullwidth, and frames taller than the workarea are converted to fullheight. | 364 | to fullwidth, and frames taller than the workarea are converted to fullheight. |
| 346 | NOTE: This only works for non-iconified frames. Internal use only." | 365 | NOTE: This only works for non-iconified frames. Internal use only." |
| 347 | (pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr (frame-monitor-attributes frame))) | 366 | (pcase-let* ((`(,left ,top ,width ,height) (cl-cdadr (frame-monitor-attributes frame))) |
| 348 | (right (+ left width -1)) | 367 | (right (+ left width -1)) |
| 349 | (bottom (+ top height -1)) | 368 | (bottom (+ top height -1)) |
| 350 | (fr-left (frameset--compute-pos (frame-parameter frame 'left) left right)) | 369 | (fr-left (frameset--compute-pos (frame-parameter frame 'left) left right)) |
| 351 | (fr-top (frameset--compute-pos (frame-parameter frame 'top) top bottom)) | 370 | (fr-top (frameset--compute-pos (frame-parameter frame 'top) top bottom)) |
| 352 | (ch-width (frame-char-width frame)) | 371 | (ch-width (frame-char-width frame)) |
| 353 | (ch-height (frame-char-height frame)) | 372 | (ch-height (frame-char-height frame)) |
| 354 | (fr-width (max (frame-pixel-width frame) (* ch-width (frame-width frame)))) | 373 | (fr-width (max (frame-pixel-width frame) (* ch-width (frame-width frame)))) |
| 355 | (fr-height (max (frame-pixel-height frame) (* ch-height (frame-height frame)))) | 374 | (fr-height (max (frame-pixel-height frame) (* ch-height (frame-height frame)))) |
| 356 | (fr-right (+ fr-left fr-width -1)) | 375 | (fr-right (+ fr-left fr-width -1)) |
| 357 | (fr-bottom (+ fr-top fr-height -1))) | 376 | (fr-bottom (+ fr-top fr-height -1))) |
| 358 | (when (pcase force-onscreen | 377 | (when (pcase force-onscreen |
| 378 | ;; A predicate. | ||
| 379 | ((pred functionp) | ||
| 380 | (funcall force-onscreen | ||
| 381 | frame | ||
| 382 | (list fr-left fr-top fr-width fr-height) | ||
| 383 | (list left top width height))) | ||
| 359 | ;; Any corner is outside the screen. | 384 | ;; Any corner is outside the screen. |
| 360 | (`all (or (< fr-bottom top) (> fr-bottom bottom) | 385 | (:all (or (< fr-bottom top) (> fr-bottom bottom) |
| 361 | (< fr-left left) (> fr-left right) | 386 | (< fr-left left) (> fr-left right) |
| 362 | (< fr-right left) (> fr-right right) | 387 | (< fr-right left) (> fr-right right) |
| 363 | (< fr-top top) (> fr-top bottom))) | 388 | (< fr-top top) (> fr-top bottom))) |
| 364 | ;; Displaced to the left, right, above or below the screen. | 389 | ;; Displaced to the left, right, above or below the screen. |
| 365 | (`t (or (> fr-left right) | 390 | (`t (or (> fr-left right) |
| 366 | (< fr-right left) | 391 | (< fr-right left) |
| 367 | (> fr-top bottom) | 392 | (> fr-top bottom) |
| 368 | (< fr-bottom top))) | 393 | (< fr-bottom top))) |
| 369 | ;; Fully inside, no need to do anything. | 394 | ;; Fully inside, no need to do anything. |
| 370 | (_ nil)) | 395 | (_ nil)) |
| @@ -430,8 +455,8 @@ is the parameter list of the frame being restored. Internal use only." | |||
| 430 | ;; M-x desktop-read). | 455 | ;; M-x desktop-read). |
| 431 | (setq frame (frameset--find-frame | 456 | (setq frame (frameset--find-frame |
| 432 | (lambda (f id) | 457 | (lambda (f id) |
| 433 | (string= (frame-parameter f 'frame-id) id)) | 458 | (string= (frame-parameter f 'frameset--id) id)) |
| 434 | display (cdr (assq 'frame-id frame-cfg)))) | 459 | display (cdr (assq 'frameset--id frame-cfg)))) |
| 435 | ;; If it has not been loaded, and it is not a minibuffer-only frame, | 460 | ;; If it has not been loaded, and it is not a minibuffer-only frame, |
| 436 | ;; let's look for an existing non-minibuffer-only frame to reuse. | 461 | ;; let's look for an existing non-minibuffer-only frame to reuse. |
| 437 | (unless (or frame (eq (cdr (assq 'minibuffer frame-cfg)) 'only)) | 462 | (unless (or frame (eq (cdr (assq 'minibuffer frame-cfg)) 'only)) |
| @@ -447,11 +472,11 @@ is the parameter list of the frame being restored. Internal use only." | |||
| 447 | ;; and that they are linked to the right minibuffer frame. | 472 | ;; and that they are linked to the right minibuffer frame. |
| 448 | (setq frame (frameset--find-frame | 473 | (setq frame (frameset--find-frame |
| 449 | (lambda (f id mini-id) | 474 | (lambda (f id mini-id) |
| 450 | (and (string= (frame-parameter f 'frame-id) id) | 475 | (and (string= (frame-parameter f 'frameset--id) id) |
| 451 | (string= (frame-parameter (window-frame (minibuffer-window f)) | 476 | (string= (frame-parameter (window-frame (minibuffer-window f)) |
| 452 | 'frame-id) | 477 | 'frameset--id) |
| 453 | mini-id))) | 478 | mini-id))) |
| 454 | display (cdr (assq 'frame-id frame-cfg)) (cdr mini)))) | 479 | display (cdr (assq 'frameset--id frame-cfg)) (cdr mini)))) |
| 455 | (t | 480 | (t |
| 456 | ;; Default to just finding a frame in the same display. | 481 | ;; Default to just finding a frame in the same display. |
| 457 | (setq frame (frameset--find-frame nil display)))) | 482 | (setq frame (frameset--find-frame nil display)))) |
| @@ -460,11 +485,21 @@ is the parameter list of the frame being restored. Internal use only." | |||
| 460 | (setq frameset--reuse-list (delq frame frameset--reuse-list))) | 485 | (setq frameset--reuse-list (delq frame frameset--reuse-list))) |
| 461 | frame)) | 486 | frame)) |
| 462 | 487 | ||
| 488 | (defun frameset--initial-params (frame-cfg) | ||
| 489 | "Return parameters from FRAME-CFG that should not be changed later. | ||
| 490 | Setting position and size parameters as soon as possible helps reducing | ||
| 491 | flickering; other parameters, like `minibuffer' and `border-width', must | ||
| 492 | be set when creating the frame because they can not be changed later. | ||
| 493 | Internal use only." | ||
| 494 | (cl-loop for param in '(left top with height border-width minibuffer) | ||
| 495 | collect (assq param frame-cfg))) | ||
| 496 | |||
| 463 | (defun frameset--get-frame (frame-cfg window-cfg filters force-onscreen) | 497 | (defun frameset--get-frame (frame-cfg window-cfg filters force-onscreen) |
| 464 | "Set up and return a frame according to its saved state. | 498 | "Set up and return a frame according to its saved state. |
| 465 | That means either reusing an existing frame or creating one anew. | 499 | That means either reusing an existing frame or creating one anew. |
| 466 | FRAME-CFG is the frame's parameter list; WINDOW-CFG is its window state. | 500 | FRAME-CFG is the frame's parameter list; WINDOW-CFG is its window state. |
| 467 | For the meaning of FORCE-ONSCREEN, see `frameset-restore'." | 501 | For the meaning of FORCE-ONSCREEN, see `frameset-restore'. |
| 502 | Internal use only." | ||
| 468 | (let* ((fullscreen (cdr (assq 'fullscreen frame-cfg))) | 503 | (let* ((fullscreen (cdr (assq 'fullscreen frame-cfg))) |
| 469 | (lines (assq 'tool-bar-lines frame-cfg)) | 504 | (lines (assq 'tool-bar-lines frame-cfg)) |
| 470 | (filtered-cfg (frameset-filter-params frame-cfg filters nil)) | 505 | (filtered-cfg (frameset-filter-params frame-cfg filters nil)) |
| @@ -507,9 +542,7 @@ For the meaning of FORCE-ONSCREEN, see `frameset-restore'." | |||
| 507 | (frameset--reuse-frame display filtered-cfg)) | 542 | (frameset--reuse-frame display filtered-cfg)) |
| 508 | (make-frame-on-display display | 543 | (make-frame-on-display display |
| 509 | (cons '(visibility) | 544 | (cons '(visibility) |
| 510 | (cl-loop | 545 | (frameset--initial-params filtered-cfg))))) |
| 511 | for param in '(left top width height minibuffer) | ||
| 512 | collect (assq param filtered-cfg)))))) | ||
| 513 | (modify-frame-parameters frame | 546 | (modify-frame-parameters frame |
| 514 | (if (eq (frame-parameter frame 'fullscreen) fullscreen) | 547 | (if (eq (frame-parameter frame 'fullscreen) fullscreen) |
| 515 | ;; Workaround for bug#14949 | 548 | ;; Workaround for bug#14949 |
| @@ -541,6 +574,12 @@ It sorts minibuffer-owning frames before minibufferless ones." | |||
| 541 | ((eq hasmini1 nil) (string< id-def1 id-def2)) | 574 | ((eq hasmini1 nil) (string< id-def1 id-def2)) |
| 542 | (t t)))) | 575 | (t t)))) |
| 543 | 576 | ||
| 577 | (defun frameset-keep-original-display-p (force-display) | ||
| 578 | "True if saved frames' displays should be honored." | ||
| 579 | (cond ((daemonp) t) | ||
| 580 | ((eq system-type 'windows-nt) nil) | ||
| 581 | (t (not force-display)))) | ||
| 582 | |||
| 544 | (defun frameset-sort-frames-for-deletion (frame1 _frame2) | 583 | (defun frameset-sort-frames-for-deletion (frame1 _frame2) |
| 545 | "Predicate to sort live frames for deletion. | 584 | "Predicate to sort live frames for deletion. |
| 546 | Minibufferless frames must go first to avoid errors when attempting | 585 | Minibufferless frames must go first to avoid errors when attempting |
| @@ -548,42 +587,53 @@ to delete a frame whose minibuffer window is used by another frame." | |||
| 548 | (not (frame-parameter frame1 'minibuffer))) | 587 | (not (frame-parameter frame1 'minibuffer))) |
| 549 | 588 | ||
| 550 | ;;;###autoload | 589 | ;;;###autoload |
| 551 | (cl-defun frameset-restore (frameset &key filters reuse-frames force-display force-onscreen) | 590 | (cl-defun frameset-restore (frameset |
| 591 | &key filters reuse-frames force-display force-onscreen) | ||
| 552 | "Restore a FRAMESET into the current display(s). | 592 | "Restore a FRAMESET into the current display(s). |
| 553 | 593 | ||
| 554 | FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'. | 594 | FILTERS is an alist of parameter filters; defaults to `frameset-filter-alist'. |
| 555 | 595 | ||
| 556 | REUSE-FRAMES describes how to reuse existing frames while restoring a frameset: | 596 | REUSE-FRAMES describes how to reuse existing frames while restoring a frameset: |
| 557 | t Reuse any existing frame if possible; delete leftover frames. | 597 | t Reuse any existing frame if possible; delete leftover frames. |
| 558 | nil Restore frameset in new frames and delete existing frames. | 598 | nil Restore frameset in new frames and delete existing frames. |
| 559 | keep Restore frameset in new frames and keep the existing ones. | 599 | :keep Restore frameset in new frames and keep the existing ones. |
| 560 | LIST A list of frames to reuse; only these will be reused, if possible, | 600 | LIST A list of frames to reuse; only these will be reused, if possible, |
| 561 | and any leftover one will be deleted; other frames not on this | 601 | and any leftover one will be deleted; other frames not on this |
| 562 | list will be kept. | 602 | list will be kept. |
| 563 | 603 | ||
| 564 | FORCE-DISPLAY can be: | 604 | FORCE-DISPLAY can be: |
| 565 | t Frames will be restored in the current display. | 605 | t Frames will be restored in the current display. |
| 566 | nil Frames will be restored, if possible, in their original displays. | 606 | nil Frames will be restored, if possible, in their original displays. |
| 567 | delete Frames in other displays will be deleted instead of restored. | 607 | :delete Frames in other displays will be deleted instead of restored. |
| 608 | PRED A function which will be called with one argument, the parameter | ||
| 609 | list, and must return t, nil or `:delete', as above but affecting | ||
| 610 | only the frame that will be created from that parameter list. | ||
| 568 | 611 | ||
| 569 | FORCE-ONSCREEN can be: | 612 | FORCE-ONSCREEN can be: |
| 570 | all Force onscreen any frame fully or partially offscreen. | 613 | :all Force onscreen any frame fully or partially offscreen. |
| 571 | t Force onscreen only those frames that are fully offscreen. | 614 | t Force onscreen only those frames that are fully offscreen. |
| 572 | nil Do not force any frame back onscreen. | 615 | nil Do not force any frame back onscreen. |
| 616 | PRED A function which will be called with three arguments, | ||
| 617 | - the live frame just restored, | ||
| 618 | - a list (LEFT TOP WIDTH HEIGHT), describing the frame, | ||
| 619 | - a list (LEFT TOP WIDTH HEIGHT), describing the workarea, | ||
| 620 | and must return non-nil to force the frame onscreen, nil otherwise. | ||
| 621 | |||
| 622 | Note the timing and scope of the operations described above: REUSE-FRAMES | ||
| 623 | affects existing frames, FILTERS and FORCE-DISPLAY affect the frame being | ||
| 624 | restored before that happens, and FORCE-ONSCREEN affects the frame once | ||
| 625 | it has been restored. | ||
| 573 | 626 | ||
| 574 | All keywords default to nil." | 627 | All keywords default to nil." |
| 575 | 628 | ||
| 576 | (cl-assert (frameset-p frameset)) | 629 | (cl-assert (frameset-p frameset)) |
| 577 | 630 | ||
| 578 | (let* ((delete-saved (eq force-display 'delete)) | 631 | (let (other-frames) |
| 579 | (forcing (not (frameset-keep-original-display-p force-display))) | ||
| 580 | (target (and forcing (cons 'display (frame-parameter nil 'display)))) | ||
| 581 | other-frames) | ||
| 582 | 632 | ||
| 583 | ;; frameset--reuse-list is a list of frames potentially reusable. Later we | 633 | ;; frameset--reuse-list is a list of frames potentially reusable. Later we |
| 584 | ;; will decide which ones can be reused, and how to deal with any leftover. | 634 | ;; will decide which ones can be reused, and how to deal with any leftover. |
| 585 | (pcase reuse-frames | 635 | (pcase reuse-frames |
| 586 | ((or `nil `keep) | 636 | ((or `nil `:keep) |
| 587 | (setq frameset--reuse-list nil | 637 | (setq frameset--reuse-list nil |
| 588 | other-frames (frame-list))) | 638 | other-frames (frame-list))) |
| 589 | ((pred consp) | 639 | ((pred consp) |
| @@ -604,35 +654,40 @@ All keywords default to nil." | |||
| 604 | ((and d-mini `(,hasmini . ,mb-id)) | 654 | ((and d-mini `(,hasmini . ,mb-id)) |
| 605 | (cdr (assq 'frameset--mini frame-cfg))) | 655 | (cdr (assq 'frameset--mini frame-cfg))) |
| 606 | (default (and (booleanp mb-id) mb-id)) | 656 | (default (and (booleanp mb-id) mb-id)) |
| 657 | (force-display (if (functionp force-display) | ||
| 658 | (funcall force-display frame-cfg) | ||
| 659 | force-display)) | ||
| 607 | (frame nil) (to-tty nil)) | 660 | (frame nil) (to-tty nil)) |
| 608 | ;; Only set target if forcing displays and the target display is different. | 661 | ;; Only set target if forcing displays and the target display is different. |
| 609 | (if (or (not forcing) | 662 | (cond ((frameset-keep-original-display-p force-display) |
| 610 | (equal target (or (assq 'display frame-cfg) '(display . nil)))) | 663 | (setq frameset--target-display nil)) |
| 611 | (setq frameset--target-display nil) | 664 | ((eq (frame-parameter nil 'display) (cdr (assq 'display frame-cfg))) |
| 612 | (setq frameset--target-display target | 665 | (setq frameset--target-display nil)) |
| 613 | to-tty (null (cdr target)))) | 666 | (t |
| 614 | ;; If keeping non-reusable frames, and the frame-id of one of them | 667 | (setq frameset--target-display (cons 'display |
| 615 | ;; matches the frame-id of a frame being restored (because, for example, | 668 | (frame-parameter nil 'display)) |
| 616 | ;; the frameset has already been read in the same session), remove the | 669 | to-tty (null (cdr frameset--target-display))))) |
| 617 | ;; frame-id from the non-reusable frame, which is not useful anymore. | ||
| 618 | (when (and other-frames | ||
| 619 | (or (eq reuse-frames 'keep) (consp reuse-frames))) | ||
| 620 | (let ((dup (cl-find (cdr (assq 'frameset-frame-id frame-cfg)) | ||
| 621 | other-frames | ||
| 622 | :key (lambda (frame) | ||
| 623 | (frame-parameter frame 'frameset-frame-id)) | ||
| 624 | :test #'string=))) | ||
| 625 | (when dup | ||
| 626 | (set-frame-parameter dup 'frameset-frame-id nil)))) | ||
| 627 | ;; Time to restore frames and set up their minibuffers as they were. | 670 | ;; Time to restore frames and set up their minibuffers as they were. |
| 628 | ;; We only skip a frame (thus deleting it) if either: | 671 | ;; We only skip a frame (thus deleting it) if either: |
| 629 | ;; - we're switching displays, and the user chose the option to delete, or | 672 | ;; - we're switching displays, and the user chose the option to delete, or |
| 630 | ;; - we're switching to tty, and the frame to restore is minibuffer-only. | 673 | ;; - we're switching to tty, and the frame to restore is minibuffer-only. |
| 631 | (unless (and frameset--target-display | 674 | (unless (and frameset--target-display |
| 632 | (or delete-saved | 675 | (or (eq force-display :delete) |
| 633 | (and to-tty | 676 | (and to-tty |
| 634 | (eq (cdr (assq 'minibuffer frame-cfg)) 'only)))) | 677 | (eq (cdr (assq 'minibuffer frame-cfg)) 'only)))) |
| 635 | 678 | ;; If keeping non-reusable frames, and the frameset--id of one of them | |
| 679 | ;; matches the id of a frame being restored (because, for example, the | ||
| 680 | ;; frameset has already been read in the same session), remove the | ||
| 681 | ;; frameset--id from the non-reusable frame, which is not useful anymore. | ||
| 682 | (when (and other-frames | ||
| 683 | (or (eq reuse-frames :keep) (consp reuse-frames))) | ||
| 684 | (let ((dup (cl-find (cdr (assq 'frameset--id frame-cfg)) | ||
| 685 | other-frames | ||
| 686 | :key (lambda (frame) | ||
| 687 | (frame-parameter frame 'frameset--id)) | ||
| 688 | :test #'string=))) | ||
| 689 | (when dup | ||
| 690 | (set-frame-parameter dup 'frameset--id nil)))) | ||
| 636 | ;; Restore minibuffers. Some of this stuff could be done in a filter | 691 | ;; Restore minibuffers. Some of this stuff could be done in a filter |
| 637 | ;; function, but it would be messy because restoring minibuffers affects | 692 | ;; function, but it would be messy because restoring minibuffers affects |
| 638 | ;; global state; it's best to do it here than add a bunch of global | 693 | ;; global state; it's best to do it here than add a bunch of global |
| @@ -647,7 +702,7 @@ All keywords default to nil." | |||
| 647 | (t ;; Frame depends on other frame's minibuffer window. | 702 | (t ;; Frame depends on other frame's minibuffer window. |
| 648 | (let* ((mb-frame (or (cl-find-if | 703 | (let* ((mb-frame (or (cl-find-if |
| 649 | (lambda (f) | 704 | (lambda (f) |
| 650 | (string= (frame-parameter f 'frame-id) | 705 | (string= (frame-parameter f 'frameset--id) |
| 651 | mb-id)) | 706 | mb-id)) |
| 652 | (frame-list)) | 707 | (frame-list)) |
| 653 | (error "Minibuffer frame %S not found" mb-id))) | 708 | (error "Minibuffer frame %S not found" mb-id))) |
| @@ -658,14 +713,14 @@ All keywords default to nil." | |||
| 658 | (error "Not a minibuffer window %s" mb-window)) | 713 | (error "Not a minibuffer window %s" mb-window)) |
| 659 | (if mb-param | 714 | (if mb-param |
| 660 | (setcdr mb-param mb-window) | 715 | (setcdr mb-param mb-window) |
| 661 | (push (cons 'minibuffer mb-window) frame-cfg)))))) | 716 | (push (cons 'minibuffer mb-window) frame-cfg))))) |
| 662 | ;; OK, we're ready at last to create (or reuse) a frame and | 717 | ;; OK, we're ready at last to create (or reuse) a frame and |
| 663 | ;; restore the window config. | 718 | ;; restore the window config. |
| 664 | (setq frame (frameset--get-frame frame-cfg window-cfg | 719 | (setq frame (frameset--get-frame frame-cfg window-cfg |
| 665 | (or filters frameset-filter-alist) | 720 | (or filters frameset-filter-alist) |
| 666 | force-onscreen)) | 721 | force-onscreen)) |
| 667 | ;; Set default-minibuffer if required. | 722 | ;; Set default-minibuffer if required. |
| 668 | (when default (setq default-minibuffer-frame frame))) | 723 | (when default (setq default-minibuffer-frame frame)))) |
| 669 | (error | 724 | (error |
| 670 | (delay-warning 'frameset (error-message-string err) :error)))) | 725 | (delay-warning 'frameset (error-message-string err) :error)))) |
| 671 | 726 | ||
| @@ -674,7 +729,7 @@ All keywords default to nil." | |||
| 674 | (sit-for 0 t) | 729 | (sit-for 0 t) |
| 675 | 730 | ||
| 676 | ;; Delete remaining frames, but do not fail if some resist being deleted. | 731 | ;; Delete remaining frames, but do not fail if some resist being deleted. |
| 677 | (unless (eq reuse-frames 'keep) | 732 | (unless (eq reuse-frames :keep) |
| 678 | (dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames) | 733 | (dolist (frame (sort (nconc (if (listp reuse-frames) nil other-frames) |
| 679 | frameset--reuse-list) | 734 | frameset--reuse-list) |
| 680 | #'frameset-sort-frames-for-deletion)) | 735 | #'frameset-sort-frames-for-deletion)) |