1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-30 12:21:25 -08:00

Handle invalid frame_or_window slots in tty input events (Bug#78966)

* src/frame.c (make_terminal_frame): Initialize terminal's
top_frame slot if it has not been set up yet (Bug#78966).
* src/keyboard.c (kbd_buffer_get_event): Do not assume that the
event's frame_or_window slot always produces a valid frame
(Bug#78966).
(tty_read_avail_input): Try to make sure that the input event we
create has a valid frame_or_window slot (Bug#78966).  Add assertion
to that purpose.
This commit is contained in:
Martin Rudalics 2025-07-09 09:52:01 +02:00
parent 280d6f70a3
commit 2fc402cb0b
2 changed files with 34 additions and 10 deletions

View file

@ -1449,6 +1449,15 @@ make_terminal_frame (struct terminal *terminal, Lisp_Object parent,
FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR;
#endif /* not MSDOS */
struct tty_display_info *tty = terminal->display_info.tty;
if (NILP (tty->top_frame))
/* If this frame's terminal's top frame has not been set up yet,
make the new frame its top frame so the top frame has been set up
before the first do_switch_frame on this terminal happens. See
Bug#78966. */
tty->top_frame = frame;
#ifdef HAVE_WINDOW_SYSTEM
f->vertical_scroll_bar_type = vertical_scroll_bar_none;
f->horizontal_scroll_bars = false;

View file

@ -4281,22 +4281,29 @@ kbd_buffer_get_event (KBOARD **kbp,
break;
default:
{
/* If this event is on a different frame, return a
switch-frame this time, and leave the event in the queue
for next time. */
Lisp_Object frame;
Lisp_Object focus;
/* It's not safe to assume that the following will always
produce a valid, live frame (Bug#78966). */
frame = event->ie.frame_or_window;
if (CONSP (frame))
frame = XCAR (frame);
else if (WINDOWP (frame))
frame = WINDOW_FRAME (XWINDOW (frame));
focus = FRAME_FOCUS_FRAME (XFRAME (frame));
if (! NILP (focus))
frame = focus;
/* If the input focus of this frame is on another frame,
continue with that frame. */
if (FRAMEP (frame))
{
focus = FRAME_FOCUS_FRAME (XFRAME (frame));
if (! NILP (focus))
frame = focus;
}
/* If this event is on a different frame, return a
switch-frame this time, and leave the event in the queue
for next time. */
if (!EQ (frame, internal_last_event_frame)
&& !EQ (frame, selected_frame))
obj = make_lispy_switch_frame (frame);
@ -8245,13 +8252,21 @@ tty_read_avail_input (struct terminal *terminal,
value of selected_frame is not reliable here, redisplay tends
to temporarily change it. However, if the selected frame is a
child frame, don't do that since it will cause switch frame
events to switch to the root frame instead. */
if (FRAME_PARENT_FRAME (XFRAME (selected_frame))
&& (root_frame (XFRAME (selected_frame))
== XFRAME (tty->top_frame)))
events to switch to the root frame instead. If the tty's top
frame has not been set up yet, always use the selected frame
(Bug#78966). */
if (!FRAMEP (tty->top_frame)
|| (FRAME_PARENT_FRAME (XFRAME (selected_frame))
&& (root_frame (XFRAME (selected_frame))
== XFRAME (tty->top_frame))))
buf.frame_or_window = selected_frame;
else
buf.frame_or_window = tty->top_frame;
/* If neither the selected frame nor the top frame were set,
something must have gone really wrong. */
eassert (FRAMEP (buf.frame_or_window));
buf.arg = Qnil;
kbd_buffer_store_event (&buf);