--- a/src/frame.c +++ b/src/frame.c @@ -1843,6 +1843,36 @@ other_frames (struct frame *f, bool invisible, bool force) return false; } + +/** Select some live frame. */ +bool +select_some_frame (void) +{ + Lisp_Object tail; + Lisp_Object frame UNINIT; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + + if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f)) + { + /* Select FRAME without switching to it. This sets up the + selected frame and the selected window and avoids aborting + as when redisplay selects a dead frame (Bug#39977). */ + selected_frame = frame; + if (!WINDOW_LIVE_P (FRAME_SELECTED_WINDOW (f))) + FRAME_SELECTED_WINDOW (f) = Fframe_first_window (frame); + selected_window = FRAME_SELECTED_WINDOW (f); + + return true; + } + } + + return false; +} + + /* Make sure that minibuf_window doesn't refer to FRAME's minibuffer window. Preferably use the selected frame's minibuffer window instead. If the selected frame doesn't have one, get some other diff --git a/src/frame.h b/src/frame.h index a54b8623e5..807938fd9f 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1363,14 +1363,17 @@ window_system_available (struct frame *f) extern Lisp_Object Vframe_list; +bool select_some_frame (void); + /* Value is a pointer to the selected frame. If the selected frame isn't live, abort. */ #define SELECTED_FRAME() \ - ((FRAMEP (selected_frame) \ - && FRAME_LIVE_P (XFRAME (selected_frame))) \ - ? XFRAME (selected_frame) \ - : (emacs_abort (), (struct frame *) 0)) + (((FRAMEP (selected_frame) \ + && FRAME_LIVE_P (XFRAME (selected_frame))) \ + || select_some_frame ()) \ + ? XFRAME (selected_frame) \ + : (emacs_abort (), (struct frame *) 0)) /***********************************************************************