From 99abaa70bf99de7a2f150ac9bb1e62ca6ea4d6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marks?= Date: Tue, 27 Jan 2026 10:23:34 +0100 Subject: [PATCH] Document frame id related commands and tweak a return value (Bug#80192) * doc/lispref/frames.texi (Input Focus): Document the commands 'select-frame-by-id' and 'undelete-frame-by-id'. * lisp/frame.el (select-frame-by-id): Clarify return value and add missing optional argument 'noerror' in sympathy with 'undelete-frame-by-id'. --- doc/lispref/frames.texi | 24 ++++++++++++++++++++++++ lisp/frame.el | 25 +++++++++++++++---------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 5bf0bfc8c10..bdd79528cac 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -109,6 +109,7 @@ must be a root frame, which means it cannot be a child frame itself descending from it. @end defun +@cindex frame identifier @defun frame-id &optional frame This function returns the unique identifier of a frame, an integer, assigned to @var{frame}. If @var{frame} is @code{nil} or unspecified, @@ -3187,6 +3188,29 @@ could switch to a different terminal without switching back when you're done. @end deffn +@deffn Command select-frame-by-id id &optional noerror +This function searches open and undeletable frames for a matching frame +identifier @var{id} (@pxref{Frames}). If found, its frame is undeleted, +if necessary, then raised, given focus, and made the selected frame. On +a text terminal, raising a frame causes it to occupy the entire terminal +display. + +This function returns the selected frame or signals an error if @var{id} +is not found, unless @var{noerror} is non-@code{nil}, in which case it +returns @code{nil}. +@end deffn + +@deffn Command undelete-frame-by-id id &optional noerror +This function searches undeletable frames for a matching frame +identifier @var{id} (@pxref{Frames}). If found, its frame is undeleted, +raised, given focus, and made the selected frame. On a text terminal, +raising a frame causes it to occupy the entire terminal display. + +This function returns the undeleted frame or signals an error if +@var{id} is not found, unless @var{noerror} is non-@code{nil}, in which +case it returns @code{nil}. +@end deffn + @cindex text-terminal focus notification Emacs cooperates with the window system by arranging to select frames as the server and window manager request. When a window system diff --git a/lisp/frame.el b/lisp/frame.el index 1e2ae5ae73c..54502837bf6 100644 --- a/lisp/frame.el +++ b/lisp/frame.el @@ -1440,13 +1440,14 @@ This is useful when you have a frame ID and a potentially dead frame reference that may have been resurrected. Also see `frame-live-p'." (frame-live-p (frame-by-id id))) -(defun select-frame-by-id (id) +(defun select-frame-by-id (id &optional noerror) "Select the frame whose identifier is ID and raise it. If the frame is undeletable, undelete it. Frames on the current terminal are checked first. Raise the frame and give it input focus. On a text terminal, the frame will occupy the entire terminal screen after the next redisplay. -If there is no frame with that ID, signal an error." +Return the selected frame or signal an error if no frame matching ID +was found. If NOERROR is non-nil, return nil instead." (interactive (let* ((frame-ids-alist (frame--make-frame-ids-alist)) (default (car (car frame-ids-alist))) @@ -1455,15 +1456,19 @@ If there is no frame with that ID, signal an error." frame-ids-alist nil t))) (list (string-to-number (if (zerop (length input)) default input))))) + ;; `undelete-frame-by-id' returns the undeleted frame, or nil. (unless (undelete-frame-by-id id 'noerror) - (select-frame-set-input-focus - ;; Prefer frames on the current display. - (or (cdr (assq id (frame--make-frame-ids-alist))) - (catch 'done - (dolist (frame (frame-list)) - (when (eq (frame-id frame) id) - (throw 'done frame)))) - (error "There is no frame with identifier `%S'" id))))) + ;; Prefer frames on the current display. + (if-let* ((found (or (cdr (assq id (frame--make-frame-ids-alist))) + (catch 'done + (dolist (frame (frame-list)) + (when (eq (frame-id frame) id) + (throw 'done frame))))))) + (progn + (select-frame-set-input-focus found) + found) + (unless noerror + (error "There is no frame with identifier `%S'" id))))) ;;;; Background mode.