diff options
| author | Martin Rudalics | 2025-07-09 09:52:01 +0200 |
|---|---|---|
| committer | Martin Rudalics | 2025-07-09 09:52:01 +0200 |
| commit | 2fc402cb0bb62f3c401528246742501a8d42bf14 (patch) | |
| tree | f6fcb1c057926cd4b9cb0e5637a159b3ea0acf0d | |
| parent | 280d6f70a356dc24a7026c00cbcbd116c2f7c7ed (diff) | |
| download | emacs-2fc402cb0bb62f3c401528246742501a8d42bf14.tar.gz emacs-2fc402cb0bb62f3c401528246742501a8d42bf14.zip | |
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.
| -rw-r--r-- | src/frame.c | 9 | ||||
| -rw-r--r-- | src/keyboard.c | 35 |
2 files changed, 34 insertions, 10 deletions
diff --git a/src/frame.c b/src/frame.c index 95fcb9ca7ff..70e200d9219 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -1449,6 +1449,15 @@ make_terminal_frame (struct terminal *terminal, Lisp_Object parent, | |||
| 1449 | FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; | 1449 | FRAME_BACKGROUND_PIXEL (f) = FACE_TTY_DEFAULT_BG_COLOR; |
| 1450 | #endif /* not MSDOS */ | 1450 | #endif /* not MSDOS */ |
| 1451 | 1451 | ||
| 1452 | struct tty_display_info *tty = terminal->display_info.tty; | ||
| 1453 | |||
| 1454 | if (NILP (tty->top_frame)) | ||
| 1455 | /* If this frame's terminal's top frame has not been set up yet, | ||
| 1456 | make the new frame its top frame so the top frame has been set up | ||
| 1457 | before the first do_switch_frame on this terminal happens. See | ||
| 1458 | Bug#78966. */ | ||
| 1459 | tty->top_frame = frame; | ||
| 1460 | |||
| 1452 | #ifdef HAVE_WINDOW_SYSTEM | 1461 | #ifdef HAVE_WINDOW_SYSTEM |
| 1453 | f->vertical_scroll_bar_type = vertical_scroll_bar_none; | 1462 | f->vertical_scroll_bar_type = vertical_scroll_bar_none; |
| 1454 | f->horizontal_scroll_bars = false; | 1463 | f->horizontal_scroll_bars = false; |
diff --git a/src/keyboard.c b/src/keyboard.c index fcb66f4c58a..b389d98feaa 100644 --- a/src/keyboard.c +++ b/src/keyboard.c | |||
| @@ -4281,22 +4281,29 @@ kbd_buffer_get_event (KBOARD **kbp, | |||
| 4281 | break; | 4281 | break; |
| 4282 | default: | 4282 | default: |
| 4283 | { | 4283 | { |
| 4284 | /* If this event is on a different frame, return a | ||
| 4285 | switch-frame this time, and leave the event in the queue | ||
| 4286 | for next time. */ | ||
| 4287 | Lisp_Object frame; | 4284 | Lisp_Object frame; |
| 4288 | Lisp_Object focus; | 4285 | Lisp_Object focus; |
| 4289 | 4286 | ||
| 4287 | /* It's not safe to assume that the following will always | ||
| 4288 | produce a valid, live frame (Bug#78966). */ | ||
| 4290 | frame = event->ie.frame_or_window; | 4289 | frame = event->ie.frame_or_window; |
| 4291 | if (CONSP (frame)) | 4290 | if (CONSP (frame)) |
| 4292 | frame = XCAR (frame); | 4291 | frame = XCAR (frame); |
| 4293 | else if (WINDOWP (frame)) | 4292 | else if (WINDOWP (frame)) |
| 4294 | frame = WINDOW_FRAME (XWINDOW (frame)); | 4293 | frame = WINDOW_FRAME (XWINDOW (frame)); |
| 4295 | 4294 | ||
| 4296 | focus = FRAME_FOCUS_FRAME (XFRAME (frame)); | 4295 | /* If the input focus of this frame is on another frame, |
| 4297 | if (! NILP (focus)) | 4296 | continue with that frame. */ |
| 4298 | frame = focus; | 4297 | if (FRAMEP (frame)) |
| 4298 | { | ||
| 4299 | focus = FRAME_FOCUS_FRAME (XFRAME (frame)); | ||
| 4300 | if (! NILP (focus)) | ||
| 4301 | frame = focus; | ||
| 4302 | } | ||
| 4299 | 4303 | ||
| 4304 | /* If this event is on a different frame, return a | ||
| 4305 | switch-frame this time, and leave the event in the queue | ||
| 4306 | for next time. */ | ||
| 4300 | if (!EQ (frame, internal_last_event_frame) | 4307 | if (!EQ (frame, internal_last_event_frame) |
| 4301 | && !EQ (frame, selected_frame)) | 4308 | && !EQ (frame, selected_frame)) |
| 4302 | obj = make_lispy_switch_frame (frame); | 4309 | obj = make_lispy_switch_frame (frame); |
| @@ -8245,13 +8252,21 @@ tty_read_avail_input (struct terminal *terminal, | |||
| 8245 | value of selected_frame is not reliable here, redisplay tends | 8252 | value of selected_frame is not reliable here, redisplay tends |
| 8246 | to temporarily change it. However, if the selected frame is a | 8253 | to temporarily change it. However, if the selected frame is a |
| 8247 | child frame, don't do that since it will cause switch frame | 8254 | child frame, don't do that since it will cause switch frame |
| 8248 | events to switch to the root frame instead. */ | 8255 | events to switch to the root frame instead. If the tty's top |
| 8249 | if (FRAME_PARENT_FRAME (XFRAME (selected_frame)) | 8256 | frame has not been set up yet, always use the selected frame |
| 8250 | && (root_frame (XFRAME (selected_frame)) | 8257 | (Bug#78966). */ |
| 8251 | == XFRAME (tty->top_frame))) | 8258 | if (!FRAMEP (tty->top_frame) |
| 8259 | || (FRAME_PARENT_FRAME (XFRAME (selected_frame)) | ||
| 8260 | && (root_frame (XFRAME (selected_frame)) | ||
| 8261 | == XFRAME (tty->top_frame)))) | ||
| 8252 | buf.frame_or_window = selected_frame; | 8262 | buf.frame_or_window = selected_frame; |
| 8253 | else | 8263 | else |
| 8254 | buf.frame_or_window = tty->top_frame; | 8264 | buf.frame_or_window = tty->top_frame; |
| 8265 | |||
| 8266 | /* If neither the selected frame nor the top frame were set, | ||
| 8267 | something must have gone really wrong. */ | ||
| 8268 | eassert (FRAMEP (buf.frame_or_window)); | ||
| 8269 | |||
| 8255 | buf.arg = Qnil; | 8270 | buf.arg = Qnil; |
| 8256 | 8271 | ||
| 8257 | kbd_buffer_store_event (&buf); | 8272 | kbd_buffer_store_event (&buf); |