aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSean Whitton2026-02-28 15:34:16 +0000
committerSean Whitton2026-02-28 15:34:16 +0000
commit342e002c879329e89bdec3a9d82c28ab06e6fce9 (patch)
tree51bbf420cffecdc0176991f9efe1cc67bfd8fb29 /src
parentfe2fdf7c82e5efc3350061233d3f0aed54915876 (diff)
downloademacs-342e002c879329e89bdec3a9d82c28ab06e6fce9.tar.gz
emacs-342e002c879329e89bdec3a9d82c28ab06e6fce9.zip
Show a message in locked frames in single-kboard mode
* src/keyboard.c (kbd_buffer_get_event): Pass the event's frame up to the caller by means of a new 'struct frame **' argument. (read_event_from_main_queue): Show a message in locked frames in single-kboard mode (bug#79892). * src/xdisp.c (log_message): Factor out of message3. (message3): Call it. (message3_nolog): Rename to ... (message3_frame_nolog): ... this. New 'struct frame *' argument which causes temporarily switching to another frame when displaying the message. (message3_frame, message3_nolog): New functions. * src/lisp.h: Declare message3_frame and message3_frame_nolog. * admin/notes/multi-tty: Remove notes on showing a message.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c40
-rw-r--r--src/lisp.h2
-rw-r--r--src/xdisp.c100
3 files changed, 110 insertions, 32 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index ffe47460528..648dd81660a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -2297,6 +2297,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
2297/* Input of single characters from keyboard. */ 2297/* Input of single characters from keyboard. */
2298 2298
2299static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu, 2299static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
2300 struct frame **event_frame,
2300 struct timespec *end_time); 2301 struct timespec *end_time);
2301static void record_char (Lisp_Object c); 2302static void record_char (Lisp_Object c);
2302 2303
@@ -2342,7 +2343,8 @@ read_event_from_main_queue (struct timespec *end_time,
2342 restore_getcjmp (local_getcjmp); 2343 restore_getcjmp (local_getcjmp);
2343 if (!end_time) 2344 if (!end_time)
2344 timer_start_idle (); 2345 timer_start_idle ();
2345 c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time); 2346 struct frame *frame;
2347 c = kbd_buffer_get_event (&kb, used_mouse_menu, &frame, end_time);
2346 unbind_to (count, Qnil); 2348 unbind_to (count, Qnil);
2347 2349
2348 if (! NILP (c) && (kb != current_kboard)) 2350 if (! NILP (c) && (kb != current_kboard))
@@ -2360,9 +2362,26 @@ read_event_from_main_queue (struct timespec *end_time,
2360 else 2362 else
2361 XSETCDR (last, list1 (c)); 2363 XSETCDR (last, list1 (c));
2362 kb->kbd_queue_has_data = true; 2364 kb->kbd_queue_has_data = true;
2363 c = Qnil;
2364 if (single_kboard) 2365 if (single_kboard)
2365 goto start; 2366 {
2367 /* Typing and clicking in a locked frame is confusing because
2368 it seems like Emacs has completely locked up (bug#79892).
2369 Show a message about what's happening. */
2370 /* FIXME: We also display the message in the unlocked frame.
2371 Can we avoid that? */
2372 if (frame
2373 && (FIXNUMP (c) || (EVENT_HAS_PARAMETERS (c)
2374 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)),
2375 Qmouse_click))))
2376 {
2377 AUTO_STRING (locked, "Frame is locked while another"
2378 " waits for input"
2379 " or is otherwise in a recursive edit");
2380 message3_frame (locked, frame);
2381 }
2382 c = Qnil;
2383 goto start;
2384 }
2366 current_kboard = kb; 2385 current_kboard = kb;
2367 return make_fixnum (-2); 2386 return make_fixnum (-2);
2368 } 2387 }
@@ -4005,6 +4024,7 @@ kbd_buffer_get_event_2 (Lisp_Object val)
4005static Lisp_Object 4024static Lisp_Object
4006kbd_buffer_get_event (KBOARD **kbp, 4025kbd_buffer_get_event (KBOARD **kbp,
4007 bool *used_mouse_menu, 4026 bool *used_mouse_menu,
4027 struct frame **event_frame,
4008 struct timespec *end_time) 4028 struct timespec *end_time)
4009{ 4029{
4010 Lisp_Object obj, str; 4030 Lisp_Object obj, str;
@@ -4019,6 +4039,8 @@ kbd_buffer_get_event (KBOARD **kbp,
4019 had_pending_conversion_events = false; 4039 had_pending_conversion_events = false;
4020#endif 4040#endif
4021 4041
4042 *event_frame = NULL;
4043
4022#ifdef subprocesses 4044#ifdef subprocesses
4023 if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4) 4045 if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
4024 { 4046 {
@@ -4179,6 +4201,9 @@ kbd_buffer_get_event (KBOARD **kbp,
4179 if (*kbp == 0) 4201 if (*kbp == 0)
4180 *kbp = current_kboard; /* Better than returning null ptr? */ 4202 *kbp = current_kboard; /* Better than returning null ptr? */
4181 4203
4204 if (FRAMEP (event->ie.frame_or_window))
4205 *event_frame = XFRAME (event->ie.frame_or_window);
4206
4182 obj = Qnil; 4207 obj = Qnil;
4183 4208
4184 /* These two kinds of events get special handling 4209 /* These two kinds of events get special handling
@@ -4492,13 +4517,14 @@ kbd_buffer_get_event (KBOARD **kbp,
4492 /* Try generating a mouse motion event. */ 4517 /* Try generating a mouse motion event. */
4493 else if (some_mouse_moved ()) 4518 else if (some_mouse_moved ())
4494 { 4519 {
4495 struct frame *f, *movement_frame = some_mouse_moved (); 4520 struct frame *f;
4496 Lisp_Object bar_window; 4521 Lisp_Object bar_window;
4497 enum scroll_bar_part part; 4522 enum scroll_bar_part part;
4498 Lisp_Object x, y; 4523 Lisp_Object x, y;
4499 Time t; 4524 Time t;
4500 4525
4501 f = movement_frame; 4526 *event_frame = some_mouse_moved ();
4527 f = *event_frame;
4502 *kbp = current_kboard; 4528 *kbp = current_kboard;
4503 /* Note that this uses F to determine which terminal to look at. 4529 /* Note that this uses F to determine which terminal to look at.
4504 If there is no valid info, it does not store anything 4530 If there is no valid info, it does not store anything
@@ -4535,8 +4561,8 @@ kbd_buffer_get_event (KBOARD **kbp,
4535 obj = make_lispy_movement (f, bar_window, part, x, y, t); 4561 obj = make_lispy_movement (f, bar_window, part, x, y, t);
4536 4562
4537 if (!NILP (obj)) 4563 if (!NILP (obj))
4538 Vlast_event_device = (STRINGP (movement_frame->last_mouse_device) 4564 Vlast_event_device = (STRINGP ((*event_frame)->last_mouse_device)
4539 ? movement_frame->last_mouse_device 4565 ? (*event_frame)->last_mouse_device
4540 : virtual_core_pointer_name); 4566 : virtual_core_pointer_name);
4541 } 4567 }
4542#ifdef HAVE_X_WINDOWS 4568#ifdef HAVE_X_WINDOWS
diff --git a/src/lisp.h b/src/lisp.h
index c7afb07576b..cefca3d6fbb 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4390,6 +4390,8 @@ extern void message1 (const char *);
4390extern void message1_nolog (const char *); 4390extern void message1_nolog (const char *);
4391extern void message3 (Lisp_Object); 4391extern void message3 (Lisp_Object);
4392extern void message3_nolog (Lisp_Object); 4392extern void message3_nolog (Lisp_Object);
4393extern void message3_frame (Lisp_Object, struct frame *);
4394extern void message3_frame_nolog (Lisp_Object, struct frame *);
4393extern void message_dolog (const char *, ptrdiff_t, bool, bool); 4395extern void message_dolog (const char *, ptrdiff_t, bool, bool);
4394extern void message_with_string (const char *, Lisp_Object, bool); 4396extern void message_with_string (const char *, Lisp_Object, bool);
4395extern void message_log_maybe_newline (void); 4397extern void message_log_maybe_newline (void);
diff --git a/src/xdisp.c b/src/xdisp.c
index f5e2b6e2d24..c8e4bf0cf10 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -510,6 +510,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
510/* Holds the list (error). */ 510/* Holds the list (error). */
511static Lisp_Object list_of_error; 511static Lisp_Object list_of_error;
512 512
513/* Forward declarations. */
514static void restore_selected_window (Lisp_Object);
515static void restore_frame_selected_window (Lisp_Object);
516
513#ifdef HAVE_WINDOW_SYSTEM 517#ifdef HAVE_WINDOW_SYSTEM
514 518
515/* Test if overflow newline into fringe. Called with iterator IT 519/* Test if overflow newline into fringe. Called with iterator IT
@@ -12481,15 +12485,8 @@ message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
12481} 12485}
12482 12486
12483 12487
12484/* Display an echo area message M with a specified length of NBYTES 12488static void
12485 bytes. The string may include null characters. If M is not a 12489log_message (Lisp_Object m)
12486 string, clear out any existing message, and let the mini-buffer
12487 text show through.
12488
12489 This function cancels echoing. */
12490
12491void
12492message3 (Lisp_Object m)
12493{ 12490{
12494 clear_message (true, true); 12491 clear_message (true, true);
12495 cancel_echoing (); 12492 cancel_echoing ();
@@ -12506,10 +12503,34 @@ message3 (Lisp_Object m)
12506 message_dolog (buffer, nbytes, true, multibyte); 12503 message_dolog (buffer, nbytes, true, multibyte);
12507 SAFE_FREE (); 12504 SAFE_FREE ();
12508 } 12505 }
12506}
12507
12508/* Display an echo area message M with a specified length of NBYTES
12509 bytes. The string may include null characters. If M is not a
12510 string, clear out any existing message, and let the mini-buffer
12511 text show through.
12512
12513 This function cancels echoing. */
12514
12515void
12516message3 (Lisp_Object m)
12517{
12518 log_message (m);
12509 if (! inhibit_message) 12519 if (! inhibit_message)
12510 message3_nolog (m); 12520 message3_nolog (m);
12511} 12521}
12512 12522
12523/* Display an echo area message M on frame F, which may not be the
12524 selected frame. */
12525
12526void
12527message3_frame (Lisp_Object m, struct frame *f)
12528{
12529 log_message (m);
12530 if (! inhibit_message)
12531 message3_frame_nolog (m, f);
12532}
12533
12513/* Log the message M to stderr. Log an empty line if M is not a string. */ 12534/* Log the message M to stderr. Log an empty line if M is not a string. */
12514 12535
12515static void 12536static void
@@ -12538,7 +12559,7 @@ message_to_stderr (Lisp_Object m)
12538 errputc ('\n'); 12559 errputc ('\n');
12539} 12560}
12540 12561
12541/* The non-logging version of message3. 12562/* The non-logging versions of message3 & message3_frame.
12542 This does not cancel echoing, because it is used for echoing. 12563 This does not cancel echoing, because it is used for echoing.
12543 Perhaps we need to make a separate function for echoing 12564 Perhaps we need to make a separate function for echoing
12544 and make this cancel echoing. */ 12565 and make this cancel echoing. */
@@ -12546,28 +12567,55 @@ message_to_stderr (Lisp_Object m)
12546void 12567void
12547message3_nolog (Lisp_Object m) 12568message3_nolog (Lisp_Object m)
12548{ 12569{
12570 message3_frame_nolog (m, NULL);
12571}
12572
12573void
12574message3_frame_nolog (Lisp_Object m, struct frame *f)
12575{
12549 struct frame *sf = SELECTED_FRAME (); 12576 struct frame *sf = SELECTED_FRAME ();
12577 if (!f) f = sf;
12550 12578
12551 if (FRAME_INITIAL_P (sf)) 12579 if (FRAME_INITIAL_P (f))
12552 message_to_stderr (m); 12580 message_to_stderr (m);
12553 /* Error messages get reported properly by cmd_error, so this must be just an 12581 /* Error messages get reported properly by cmd_error, so this must be
12554 informative message; if the frame hasn't really been initialized yet, just 12582 just an informative message; therefore if the frame hasn't really
12555 toss it. */ 12583 been initialized yet, just toss it. */
12556 else if (INTERACTIVE && sf->glyphs_initialized_p) 12584 else if (INTERACTIVE && f->glyphs_initialized_p)
12557 { 12585 {
12558 /* Get the frame containing the mini-buffer 12586 Lisp_Object frame = Qnil;
12559 that the selected frame is using. */ 12587 struct frame *mbf = NULL;
12560 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf); 12588 specpdl_ref count = SPECPDL_INDEX ();
12561 Lisp_Object frame = XWINDOW (mini_window)->frame; 12589
12562 struct frame *f = XFRAME (frame); 12590 if (f == sf)
12591 {
12592 /* Get the frame containing the mini-buffer that the selected
12593 frame is using. */
12594 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (f);
12595 frame = XWINDOW (mini_window)->frame;
12596 mbf = XFRAME (frame);
12563 12597
12564 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f)) 12598 if (FRAME_VISIBLE_P (f) && !FRAME_VISIBLE_P (mbf))
12565 Fmake_frame_visible (frame); 12599 Fmake_frame_visible (frame);
12600 }
12601 else
12602 {
12603 /* We temporarily switch frame, show the message, and then
12604 when we unwind the message will normally still be visible
12605 in the other frame, at least for a few seconds. */
12606 record_unwind_protect
12607 (restore_selected_window, selected_window);
12608 record_unwind_protect
12609 (restore_frame_selected_window, f->selected_window);
12610 XSETFRAME (frame, f);
12611 selected_frame = frame;
12612 selected_window = FRAME_SELECTED_WINDOW (f);
12613 }
12566 12614
12567 if (STRINGP (m) && SCHARS (m) > 0) 12615 if (STRINGP (m) && SCHARS (m) > 0)
12568 { 12616 {
12569 set_message (m); 12617 set_message (m);
12570 if (minibuffer_auto_raise) 12618 if (minibuffer_auto_raise && !NILP (frame))
12571 Fraise_frame (frame); 12619 Fraise_frame (frame);
12572 /* Assume we are not echoing. 12620 /* Assume we are not echoing.
12573 (If we are, echo_now will override this.) */ 12621 (If we are, echo_now will override this.) */
@@ -12579,8 +12627,10 @@ message3_nolog (Lisp_Object m)
12579 do_pending_window_change (false); 12627 do_pending_window_change (false);
12580 echo_area_display (true); 12628 echo_area_display (true);
12581 do_pending_window_change (false); 12629 do_pending_window_change (false);
12582 if (FRAME_TERMINAL (f)->frame_up_to_date_hook) 12630 if (mbf && FRAME_TERMINAL (mbf)->frame_up_to_date_hook)
12583 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f); 12631 (*FRAME_TERMINAL (mbf)->frame_up_to_date_hook) (mbf);
12632
12633 unbind_to (count, Qnil);
12584 } 12634 }
12585} 12635}
12586 12636