diff options
| author | Stefan Monnier | 2022-10-12 17:06:33 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2022-10-12 17:06:33 -0400 |
| commit | da752c04664c0e22a2f6b4a41dfa1fed4d5276ff (patch) | |
| tree | 927f868b9b1d5bc1be370e3195082503fc3d83e7 | |
| parent | 5a94a2e5b054f6866762f6eb7f7bbafd24bf02de (diff) | |
| download | emacs-da752c04664c0e22a2f6b4a41dfa1fed4d5276ff.tar.gz emacs-da752c04664c0e22a2f6b4a41dfa1fed4d5276ff.zip | |
src/frame.c (do_switch_frame): Fix bug#58343
* src/frame.c (do_switch_frame): Move call to `get-mru-window` outside
of the "critical region" where (selected-window) != (frame-selected-window).
* src/minibuf.c (move_minibuffers_onto_frame): Add arg `frame`.
Use it instead of `selected_frame`. Adjust all callers.
* src/lisp.h (move_minibuffers_onto_frame): Adjust declaration.
| -rw-r--r-- | src/frame.c | 28 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/minibuf.c | 12 |
3 files changed, 24 insertions, 18 deletions
diff --git a/src/frame.c b/src/frame.c index 91b9bec82c3..f076a5ba54e 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -1503,17 +1503,7 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) | |||
| 1503 | 1503 | ||
| 1504 | sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); | 1504 | sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); |
| 1505 | 1505 | ||
| 1506 | selected_frame = frame; | 1506 | move_minibuffers_onto_frame (sf, frame, for_deletion); |
| 1507 | |||
| 1508 | move_minibuffers_onto_frame (sf, for_deletion); | ||
| 1509 | |||
| 1510 | if (f->select_mini_window_flag | ||
| 1511 | && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) | ||
| 1512 | f->selected_window = f->minibuffer_window; | ||
| 1513 | f->select_mini_window_flag = false; | ||
| 1514 | |||
| 1515 | if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) | ||
| 1516 | last_nonminibuf_frame = XFRAME (selected_frame); | ||
| 1517 | 1507 | ||
| 1518 | /* If the selected window in the target frame is its mini-window, we move | 1508 | /* If the selected window in the target frame is its mini-window, we move |
| 1519 | to a different window, the most recently used one, unless there is a | 1509 | to a different window, the most recently used one, unless there is a |
| @@ -1528,6 +1518,20 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) | |||
| 1528 | Fset_frame_selected_window (frame, w, Qnil); | 1518 | Fset_frame_selected_window (frame, w, Qnil); |
| 1529 | } | 1519 | } |
| 1530 | 1520 | ||
| 1521 | /* After setting `selected_frame`, we're temporarily in an inconsistent | ||
| 1522 | state where (selected-window) != (frame-selected-window). Until this | ||
| 1523 | invariant is restored we should be very careful not to run ELisp code. | ||
| 1524 | (bug#58343) */ | ||
| 1525 | selected_frame = frame; | ||
| 1526 | |||
| 1527 | if (f->select_mini_window_flag | ||
| 1528 | && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) | ||
| 1529 | f->selected_window = f->minibuffer_window; | ||
| 1530 | f->select_mini_window_flag = false; | ||
| 1531 | |||
| 1532 | if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) | ||
| 1533 | last_nonminibuf_frame = XFRAME (selected_frame); | ||
| 1534 | |||
| 1531 | Fselect_window (f->selected_window, norecord); | 1535 | Fselect_window (f->selected_window, norecord); |
| 1532 | 1536 | ||
| 1533 | /* We want to make sure that the next event generates a frame-switch | 1537 | /* We want to make sure that the next event generates a frame-switch |
| @@ -2110,7 +2114,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) | |||
| 2110 | else | 2114 | else |
| 2111 | /* Ensure any minibuffers on FRAME are moved onto the selected | 2115 | /* Ensure any minibuffers on FRAME are moved onto the selected |
| 2112 | frame. */ | 2116 | frame. */ |
| 2113 | move_minibuffers_onto_frame (f, true); | 2117 | move_minibuffers_onto_frame (f, selected_frame, true); |
| 2114 | 2118 | ||
| 2115 | /* Don't let echo_area_window to remain on a deleted frame. */ | 2119 | /* Don't let echo_area_window to remain on a deleted frame. */ |
| 2116 | if (EQ (f->minibuffer_window, echo_area_window)) | 2120 | if (EQ (f->minibuffer_window, echo_area_window)) |
diff --git a/src/lisp.h b/src/lisp.h index 56f24d82810..5f6721595c0 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -4792,7 +4792,7 @@ extern void clear_regexp_cache (void); | |||
| 4792 | 4792 | ||
| 4793 | extern Lisp_Object Vminibuffer_list; | 4793 | extern Lisp_Object Vminibuffer_list; |
| 4794 | extern Lisp_Object last_minibuf_string; | 4794 | extern Lisp_Object last_minibuf_string; |
| 4795 | extern void move_minibuffers_onto_frame (struct frame *, bool); | 4795 | extern void move_minibuffers_onto_frame (struct frame *, Lisp_Object, bool); |
| 4796 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); | 4796 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); |
| 4797 | extern EMACS_INT this_minibuffer_depth (Lisp_Object); | 4797 | extern EMACS_INT this_minibuffer_depth (Lisp_Object); |
| 4798 | extern EMACS_INT minibuf_level; | 4798 | extern EMACS_INT minibuf_level; |
diff --git a/src/minibuf.c b/src/minibuf.c index bedc5644807..3f34b1b0834 100644 --- a/src/minibuf.c +++ b/src/minibuf.c | |||
| @@ -187,13 +187,15 @@ zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window) | |||
| 187 | 187 | ||
| 188 | /* If `minibuffer_follows_selected_frame' is t, or we're about to | 188 | /* If `minibuffer_follows_selected_frame' is t, or we're about to |
| 189 | delete a frame which potentially "contains" minibuffers, move them | 189 | delete a frame which potentially "contains" minibuffers, move them |
| 190 | from the old frame to the selected frame. This function is | 190 | from the old frame to the to-be-selected frame. This function is |
| 191 | intended to be called from `do_switch_frame' in frame.c. OF is the | 191 | intended to be called from `do_switch_frame' in frame.c. OF is the |
| 192 | old frame, FOR_DELETION is true if OF is about to be deleted. */ | 192 | old frame, FRAME is the to-be-selected frame, and FOR_DELETION is true |
| 193 | if OF is about to be deleted. */ | ||
| 193 | void | 194 | void |
| 194 | move_minibuffers_onto_frame (struct frame *of, bool for_deletion) | 195 | move_minibuffers_onto_frame (struct frame *of, Lisp_Object frame, |
| 196 | bool for_deletion) | ||
| 195 | { | 197 | { |
| 196 | struct frame *f = XFRAME (selected_frame); | 198 | struct frame *f = XFRAME (frame); |
| 197 | 199 | ||
| 198 | minibuf_window = f->minibuffer_window; | 200 | minibuf_window = f->minibuffer_window; |
| 199 | if (!(minibuf_level | 201 | if (!(minibuf_level |
| @@ -206,7 +208,7 @@ move_minibuffers_onto_frame (struct frame *of, bool for_deletion) | |||
| 206 | { | 208 | { |
| 207 | zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); | 209 | zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window); |
| 208 | if (for_deletion && XFRAME (MB_frame) != of) | 210 | if (for_deletion && XFRAME (MB_frame) != of) |
| 209 | MB_frame = selected_frame; | 211 | MB_frame = frame; |
| 210 | } | 212 | } |
| 211 | } | 213 | } |
| 212 | 214 | ||