mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-03-11 09:21:23 -07:00
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.
This commit is contained in:
parent
fe2fdf7c82
commit
342e002c87
4 changed files with 112 additions and 48 deletions
|
|
@ -402,29 +402,15 @@ THINGS TO DO
|
|||
|
||||
** The single-keyboard mode of MULTI_KBOARD is extremely confusing
|
||||
sometimes; Emacs does not respond to stimuli from other keyboards.
|
||||
At least a beep or a message would be important, if the single-mode
|
||||
is still required to prevent interference. (Reported by Dan
|
||||
Nicolaescu.)
|
||||
(Reported by Dan Nicolaescu.)
|
||||
|
||||
Update: selecting a region with the mouse enables single_kboard
|
||||
under X. This is very confusing.
|
||||
|
||||
Update: After discussions with Richard Stallman, this will be
|
||||
resolved by having locked displays warn the user to wait, and
|
||||
introducing a complex protocol to remotely bail out of
|
||||
resolved introducing a complex protocol to remotely bail out of
|
||||
single-kboard mode by pressing C-g.
|
||||
|
||||
Update: Warning the user is not trivial to implement, as Emacs has
|
||||
only one echo area, shared by all frames. Ideally the warning
|
||||
should not be displayed on the display that is locking the others.
|
||||
Perhaps the high probability of user confusion caused by
|
||||
single_kboard mode deserves a special case in the display code.
|
||||
Alternatively, it might be good enough to signal single_kboard mode
|
||||
by changing the modelines or some other frame-local display element
|
||||
on the locked out displays.
|
||||
|
||||
Update: In fact struct kboard does have an echo_string slot.
|
||||
|
||||
** The session management module is prone to crashes when the X
|
||||
connection is closed and then later I try to connect to a new X
|
||||
session:
|
||||
|
|
|
|||
|
|
@ -2297,6 +2297,7 @@ show_help_echo (Lisp_Object help, Lisp_Object window, Lisp_Object object,
|
|||
/* Input of single characters from keyboard. */
|
||||
|
||||
static Lisp_Object kbd_buffer_get_event (KBOARD **kbp, bool *used_mouse_menu,
|
||||
struct frame **event_frame,
|
||||
struct timespec *end_time);
|
||||
static void record_char (Lisp_Object c);
|
||||
|
||||
|
|
@ -2342,7 +2343,8 @@ read_event_from_main_queue (struct timespec *end_time,
|
|||
restore_getcjmp (local_getcjmp);
|
||||
if (!end_time)
|
||||
timer_start_idle ();
|
||||
c = kbd_buffer_get_event (&kb, used_mouse_menu, end_time);
|
||||
struct frame *frame;
|
||||
c = kbd_buffer_get_event (&kb, used_mouse_menu, &frame, end_time);
|
||||
unbind_to (count, Qnil);
|
||||
|
||||
if (! NILP (c) && (kb != current_kboard))
|
||||
|
|
@ -2360,9 +2362,26 @@ read_event_from_main_queue (struct timespec *end_time,
|
|||
else
|
||||
XSETCDR (last, list1 (c));
|
||||
kb->kbd_queue_has_data = true;
|
||||
c = Qnil;
|
||||
if (single_kboard)
|
||||
goto start;
|
||||
{
|
||||
/* Typing and clicking in a locked frame is confusing because
|
||||
it seems like Emacs has completely locked up (bug#79892).
|
||||
Show a message about what's happening. */
|
||||
/* FIXME: We also display the message in the unlocked frame.
|
||||
Can we avoid that? */
|
||||
if (frame
|
||||
&& (FIXNUMP (c) || (EVENT_HAS_PARAMETERS (c)
|
||||
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)),
|
||||
Qmouse_click))))
|
||||
{
|
||||
AUTO_STRING (locked, "Frame is locked while another"
|
||||
" waits for input"
|
||||
" or is otherwise in a recursive edit");
|
||||
message3_frame (locked, frame);
|
||||
}
|
||||
c = Qnil;
|
||||
goto start;
|
||||
}
|
||||
current_kboard = kb;
|
||||
return make_fixnum (-2);
|
||||
}
|
||||
|
|
@ -4005,6 +4024,7 @@ kbd_buffer_get_event_2 (Lisp_Object val)
|
|||
static Lisp_Object
|
||||
kbd_buffer_get_event (KBOARD **kbp,
|
||||
bool *used_mouse_menu,
|
||||
struct frame **event_frame,
|
||||
struct timespec *end_time)
|
||||
{
|
||||
Lisp_Object obj, str;
|
||||
|
|
@ -4019,6 +4039,8 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
had_pending_conversion_events = false;
|
||||
#endif
|
||||
|
||||
*event_frame = NULL;
|
||||
|
||||
#ifdef subprocesses
|
||||
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
|
||||
{
|
||||
|
|
@ -4179,6 +4201,9 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
if (*kbp == 0)
|
||||
*kbp = current_kboard; /* Better than returning null ptr? */
|
||||
|
||||
if (FRAMEP (event->ie.frame_or_window))
|
||||
*event_frame = XFRAME (event->ie.frame_or_window);
|
||||
|
||||
obj = Qnil;
|
||||
|
||||
/* These two kinds of events get special handling
|
||||
|
|
@ -4492,13 +4517,14 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
/* Try generating a mouse motion event. */
|
||||
else if (some_mouse_moved ())
|
||||
{
|
||||
struct frame *f, *movement_frame = some_mouse_moved ();
|
||||
struct frame *f;
|
||||
Lisp_Object bar_window;
|
||||
enum scroll_bar_part part;
|
||||
Lisp_Object x, y;
|
||||
Time t;
|
||||
|
||||
f = movement_frame;
|
||||
*event_frame = some_mouse_moved ();
|
||||
f = *event_frame;
|
||||
*kbp = current_kboard;
|
||||
/* Note that this uses F to determine which terminal to look at.
|
||||
If there is no valid info, it does not store anything
|
||||
|
|
@ -4535,8 +4561,8 @@ kbd_buffer_get_event (KBOARD **kbp,
|
|||
obj = make_lispy_movement (f, bar_window, part, x, y, t);
|
||||
|
||||
if (!NILP (obj))
|
||||
Vlast_event_device = (STRINGP (movement_frame->last_mouse_device)
|
||||
? movement_frame->last_mouse_device
|
||||
Vlast_event_device = (STRINGP ((*event_frame)->last_mouse_device)
|
||||
? (*event_frame)->last_mouse_device
|
||||
: virtual_core_pointer_name);
|
||||
}
|
||||
#ifdef HAVE_X_WINDOWS
|
||||
|
|
|
|||
|
|
@ -4390,6 +4390,8 @@ extern void message1 (const char *);
|
|||
extern void message1_nolog (const char *);
|
||||
extern void message3 (Lisp_Object);
|
||||
extern void message3_nolog (Lisp_Object);
|
||||
extern void message3_frame (Lisp_Object, struct frame *);
|
||||
extern void message3_frame_nolog (Lisp_Object, struct frame *);
|
||||
extern void message_dolog (const char *, ptrdiff_t, bool, bool);
|
||||
extern void message_with_string (const char *, Lisp_Object, bool);
|
||||
extern void message_log_maybe_newline (void);
|
||||
|
|
|
|||
100
src/xdisp.c
100
src/xdisp.c
|
|
@ -510,6 +510,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
|
|||
/* Holds the list (error). */
|
||||
static Lisp_Object list_of_error;
|
||||
|
||||
/* Forward declarations. */
|
||||
static void restore_selected_window (Lisp_Object);
|
||||
static void restore_frame_selected_window (Lisp_Object);
|
||||
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
|
||||
/* 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)
|
|||
}
|
||||
|
||||
|
||||
/* Display an echo area message M with a specified length of NBYTES
|
||||
bytes. The string may include null characters. If M is not a
|
||||
string, clear out any existing message, and let the mini-buffer
|
||||
text show through.
|
||||
|
||||
This function cancels echoing. */
|
||||
|
||||
void
|
||||
message3 (Lisp_Object m)
|
||||
static void
|
||||
log_message (Lisp_Object m)
|
||||
{
|
||||
clear_message (true, true);
|
||||
cancel_echoing ();
|
||||
|
|
@ -12506,10 +12503,34 @@ message3 (Lisp_Object m)
|
|||
message_dolog (buffer, nbytes, true, multibyte);
|
||||
SAFE_FREE ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Display an echo area message M with a specified length of NBYTES
|
||||
bytes. The string may include null characters. If M is not a
|
||||
string, clear out any existing message, and let the mini-buffer
|
||||
text show through.
|
||||
|
||||
This function cancels echoing. */
|
||||
|
||||
void
|
||||
message3 (Lisp_Object m)
|
||||
{
|
||||
log_message (m);
|
||||
if (! inhibit_message)
|
||||
message3_nolog (m);
|
||||
}
|
||||
|
||||
/* Display an echo area message M on frame F, which may not be the
|
||||
selected frame. */
|
||||
|
||||
void
|
||||
message3_frame (Lisp_Object m, struct frame *f)
|
||||
{
|
||||
log_message (m);
|
||||
if (! inhibit_message)
|
||||
message3_frame_nolog (m, f);
|
||||
}
|
||||
|
||||
/* Log the message M to stderr. Log an empty line if M is not a string. */
|
||||
|
||||
static void
|
||||
|
|
@ -12538,36 +12559,63 @@ message_to_stderr (Lisp_Object m)
|
|||
errputc ('\n');
|
||||
}
|
||||
|
||||
/* The non-logging version of message3.
|
||||
/* The non-logging versions of message3 & message3_frame.
|
||||
This does not cancel echoing, because it is used for echoing.
|
||||
Perhaps we need to make a separate function for echoing
|
||||
and make this cancel echoing. */
|
||||
|
||||
void
|
||||
message3_nolog (Lisp_Object m)
|
||||
{
|
||||
message3_frame_nolog (m, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
message3_frame_nolog (Lisp_Object m, struct frame *f)
|
||||
{
|
||||
struct frame *sf = SELECTED_FRAME ();
|
||||
if (!f) f = sf;
|
||||
|
||||
if (FRAME_INITIAL_P (sf))
|
||||
if (FRAME_INITIAL_P (f))
|
||||
message_to_stderr (m);
|
||||
/* Error messages get reported properly by cmd_error, so this must be just an
|
||||
informative message; if the frame hasn't really been initialized yet, just
|
||||
toss it. */
|
||||
else if (INTERACTIVE && sf->glyphs_initialized_p)
|
||||
/* Error messages get reported properly by cmd_error, so this must be
|
||||
just an informative message; therefore if the frame hasn't really
|
||||
been initialized yet, just toss it. */
|
||||
else if (INTERACTIVE && f->glyphs_initialized_p)
|
||||
{
|
||||
/* Get the frame containing the mini-buffer
|
||||
that the selected frame is using. */
|
||||
Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
|
||||
Lisp_Object frame = XWINDOW (mini_window)->frame;
|
||||
struct frame *f = XFRAME (frame);
|
||||
Lisp_Object frame = Qnil;
|
||||
struct frame *mbf = NULL;
|
||||
specpdl_ref count = SPECPDL_INDEX ();
|
||||
|
||||
if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
|
||||
Fmake_frame_visible (frame);
|
||||
if (f == sf)
|
||||
{
|
||||
/* Get the frame containing the mini-buffer that the selected
|
||||
frame is using. */
|
||||
Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (f);
|
||||
frame = XWINDOW (mini_window)->frame;
|
||||
mbf = XFRAME (frame);
|
||||
|
||||
if (FRAME_VISIBLE_P (f) && !FRAME_VISIBLE_P (mbf))
|
||||
Fmake_frame_visible (frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We temporarily switch frame, show the message, and then
|
||||
when we unwind the message will normally still be visible
|
||||
in the other frame, at least for a few seconds. */
|
||||
record_unwind_protect
|
||||
(restore_selected_window, selected_window);
|
||||
record_unwind_protect
|
||||
(restore_frame_selected_window, f->selected_window);
|
||||
XSETFRAME (frame, f);
|
||||
selected_frame = frame;
|
||||
selected_window = FRAME_SELECTED_WINDOW (f);
|
||||
}
|
||||
|
||||
if (STRINGP (m) && SCHARS (m) > 0)
|
||||
{
|
||||
set_message (m);
|
||||
if (minibuffer_auto_raise)
|
||||
if (minibuffer_auto_raise && !NILP (frame))
|
||||
Fraise_frame (frame);
|
||||
/* Assume we are not echoing.
|
||||
(If we are, echo_now will override this.) */
|
||||
|
|
@ -12579,8 +12627,10 @@ message3_nolog (Lisp_Object m)
|
|||
do_pending_window_change (false);
|
||||
echo_area_display (true);
|
||||
do_pending_window_change (false);
|
||||
if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
|
||||
(*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
|
||||
if (mbf && FRAME_TERMINAL (mbf)->frame_up_to_date_hook)
|
||||
(*FRAME_TERMINAL (mbf)->frame_up_to_date_hook) (mbf);
|
||||
|
||||
unbind_to (count, Qnil);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue