aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPip Cet2026-04-10 11:35:22 +0000
committerPip Cet2026-04-10 18:16:54 +0000
commit2edcc6d4223a2837e594ff83c13832533b5e3ef8 (patch)
treea998857293d3bdbd78dcf7525fa7abc49331bb43 /src
parent708759324e2314eb912ddb9758cabecd16469ffe (diff)
downloademacs-2edcc6d4223a2837e594ff83c13832533b5e3ef8.tar.gz
emacs-2edcc6d4223a2837e594ff83c13832533b5e3ef8.zip
Ensure selected_frame isn't the deleted frame (bug#80789)
The previous code would sometimes exit the loop with frame1 set to the last considered frame, even if that wasn't a suitable frame to switch to. * src/frame.c (delete_frame): Reset 'frame1' in the loops if we don't match the break condition, so we don't think we've found a suitable replacement frame if we haven't. Error if, for some reason, that fails.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/src/frame.c b/src/frame.c
index d0d02eaeb1f..2c0a27cf47c 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2733,8 +2733,6 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2733 error ("Attempt to delete the only frame"); 2733 error ("Attempt to delete the only frame");
2734 } 2734 }
2735 2735
2736 /* At this point, we are committed to deleting the frame.
2737 There is no more chance for errors to prevent it. */
2738 sf = SELECTED_FRAME (); 2736 sf = SELECTED_FRAME ();
2739 /* Don't let the frame remain selected. */ 2737 /* Don't let the frame remain selected. */
2740 if (f == sf) 2738 if (f == sf)
@@ -2754,7 +2752,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2754 frames on the same terminal as FRAME, excluding FRAME 2752 frames on the same terminal as FRAME, excluding FRAME
2755 which we are about to delete. */ 2753 which we are about to delete. */
2756 frame1 = safe_calln (Qget_mru_frame, Qvisible, Qnil, frame); 2754 frame1 = safe_calln (Qget_mru_frame, Qvisible, Qnil, frame);
2757 if (!NILP (frame1)) 2755 if (FRAMEP (frame1))
2758 { 2756 {
2759 struct frame *f1 = XFRAME (frame1); 2757 struct frame *f1 = XFRAME (frame1);
2760 2758
@@ -2764,6 +2762,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2764 || EQ (frame1, frame)) 2762 || EQ (frame1, frame))
2765 frame1 = Qnil; 2763 frame1 = Qnil;
2766 } 2764 }
2765 else
2766 frame1 = Qnil;
2767 } 2767 }
2768 2768
2769 if (NILP (frame1)) 2769 if (NILP (frame1))
@@ -2783,6 +2783,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2783 && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1) 2783 && FRAME_TERMINAL (f) == FRAME_TERMINAL (f1)
2784 && FRAME_VISIBLE_P (f1)) 2784 && FRAME_VISIBLE_P (f1))
2785 break; 2785 break;
2786 frame1 = Qnil;
2786 } 2787 }
2787 2788
2788 /* If there is none, find *some* other frame. */ 2789 /* If there is none, find *some* other frame. */
@@ -2805,6 +2806,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2805 } 2806 }
2806 break; 2807 break;
2807 } 2808 }
2809 frame1 = Qnil;
2808 } 2810 }
2809 } 2811 }
2810#ifdef NS_IMPL_COCOA 2812#ifdef NS_IMPL_COCOA
@@ -2821,8 +2823,18 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2821#endif 2823#endif
2822 } 2824 }
2823 2825
2824 do_switch_frame (frame1, 0, 1, Qnil); 2826 if (FRAMEP (frame1) && XFRAME (frame1) != f)
2827 do_switch_frame (frame1, 0, 1, Qnil);
2828 else if (EQ (force, Qnoelisp))
2829 {
2830 /* This is the last frame, and it's being forcibly
2831 deleted. There's no way to recover from this. */
2832 Fkill_emacs (make_fixnum (70), Qnil);
2833 }
2834 else
2835 emacs_abort ();
2825 sf = SELECTED_FRAME (); 2836 sf = SELECTED_FRAME ();
2837 eassert (sf != f);
2826 } 2838 }
2827 } 2839 }
2828 else 2840 else
@@ -2830,6 +2842,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
2830 frame. */ 2842 frame. */
2831 move_minibuffers_onto_frame (f, selected_frame, true); 2843 move_minibuffers_onto_frame (f, selected_frame, true);
2832 2844
2845 /* At this point, we are committed to deleting the frame.
2846 There is no more chance for errors to prevent it. */
2833 /* Don't let echo_area_window to remain on a deleted frame. */ 2847 /* Don't let echo_area_window to remain on a deleted frame. */
2834 if (EQ (f->minibuffer_window, echo_area_window)) 2848 if (EQ (f->minibuffer_window, echo_area_window))
2835 echo_area_window = sf->minibuffer_window; 2849 echo_area_window = sf->minibuffer_window;