THINGS TO DO
------------
-** Let-binding `overriding-terminal-local-map' on a brand new frame
- does not seem to work correctly. (See `fancy-splash-screens'.)
- The keymap seems to be set up right, but events go to another
- terminal. Or is it `unread-command-events' that gets Emacs
- confused? Investigate.
-
** `delete-frame' events are handled by `special-event-map'
immediately when read by `read_char'. This is fine but it prevents
higher-level keymaps from binding that event to get notified of the
Emacs with GTK support. If you want to play around with GTK
multidisplay (and don't mind core dumps), you can edit src/config.h
and define HAVE_GTK_MULTIDISPLAY there by hand.
+
+ Update: Han reports that GTK+ version 2.8.9 almost gets display
+ disconnects right. GTK will probably be fully fixed by the time
+ multi-tty gets into the trunk.
** Audit `face-valid-attribute-values' usage in customize and
elsewhere. Its return value depends on the current window system.
** frames-on-display-list should also accept frames.
-** I smell something funny around pop_kboard's "deleted kboard" case.
- Determine what are the circumstances of this case, and fix any
- bug that comes to light.
-
** Consider the `tty-type' frame parameter and the `display-tty-type'
function. They serve the exact same purpose. I think it may be
a good idea to eliminate one of them, preferably `tty-type'.
instead of delete-frame-functions),
after-delete-terminal-functions, after-create-terminal-functions.
-** Fix set-input-mode for multi-tty. It's a truly horrible interface;
- what if we'd blow it up into several separate functions (with a
- compatibility definition)?
-
** BULK RENAME: The `display-' prefix of new Lisp-level functions
conflicts with stuff like `display-time-mode'. Use `device-'
or `terminal-' instead. I think I prefer `terminal-'.
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:
terminals in xterm and konsole. The screen does flicker a bit,
but it's so quick it isn't noticable.
+ (Update: This is probably some problem with padding or whatnot on
+ the secondary terminals.)
+
** Move baud_rate to struct display.
** Implement support for starting an interactive Emacs session without
against `delete-frame-functions' throwing an error and preventing a
frame delete. (patch-475)
+-- Fix set-input-mode for multi-tty. It's a truly horrible interface;
+ what if we'd blow it up into several separate functions (with a
+ compatibility definition)?
+
+ (Done. See `set-input-interrupt-mode', `set-output-flow-control',
+ `set-input-meta-mode' and `set-quit-char'.) (patch-457)
+
+-- Let-binding `overriding-terminal-local-map' on a brand new frame
+ does not seem to work correctly. (See `fancy-splash-screens'.)
+ The keymap seems to be set up right, but events go to another
+ terminal. Or is it `unread-command-events' that gets Emacs
+ confused? Investigate.
+
+ (Emacs was confused because a process filter entered
+ `recursive-edit' while Emacs was reading input. I added support
+ for this in the input system.) (patch-489)
+
+-- I smell something funny around pop_kboard's "deleted kboard" case.
+ Determine what are the circumstances of this case, and fix any
+ bug that comes to light.
+
+ (It happens simply because single_kboard's terminal is sometimes
+ deleted while executing a command on it, for example the one that
+ kills the terminal. There was no bug here, but I rewrote the whole
+ single_kboard mess anyway.) (patch-489)
+
;;; arch-tag: 8da1619e-2e79-41a8-9ac9-a0485daad17d
static void restore_getcjmp P_ ((jmp_buf));
static Lisp_Object apply_modifiers P_ ((int, Lisp_Object));
static void clear_event P_ ((struct input_event *));
-static void any_kboard_state P_ ((void));
static Lisp_Object restore_kboard_configuration P_ ((Lisp_Object));
static SIGTYPE interrupt_signal P_ ((int signalnum));
static void handle_interrupt P_ ((void));
like it is done in the splash screen display, we have to
make sure that we restore single_kboard as command_loop_1
would have done if it were left normally. */
- temporarily_switch_to_single_kboard (FRAME_KBOARD (SELECTED_FRAME ()));
+ if (command_loop_level > 0)
+ temporarily_switch_to_single_kboard (SELECTED_FRAME ());
record_unwind_protect (recursive_edit_unwind, buffer);
recursive_edit_1 ();
}
\f
+#if 0 /* These two functions are now replaced with
+ temporarily_switch_to_single_kboard. */
static void
any_kboard_state ()
{
single_kboard = 1;
#endif
}
+#endif
/* If we're in single_kboard state for kboard KBOARD,
get out of it. */
#endif
}
-void
-push_frame_kboard (f)
- FRAME_PTR f;
-{
- push_kboard (f->terminal->kboard);
-}
-
void
pop_kboard ()
{
{
/* The terminal we remembered has been deleted. */
current_kboard = FRAME_KBOARD (SELECTED_FRAME ());
+ single_kboard = 0;
}
kboard_stack = p->next;
xfree (p);
#endif
}
-/* Switch to single_kboard mode. If K is non-nil, set it as the
- current keyboard. Use record_unwind_protect to return to the
- previous state later. */
+/* Switch to single_kboard mode, making current_kboard the only KBOARD
+ from which further input is accepted. If F is non-nil, set its
+ KBOARD as the current keyboard.
+
+ This function uses record_unwind_protect to return to the previous
+ state later.
+
+ If Emacs is already in single_kboard mode, and F's keyboard is
+ locked, then this function will throw an errow. */
void
-temporarily_switch_to_single_kboard (k)
- struct kboard *k;
+temporarily_switch_to_single_kboard (f)
+ struct frame *f;
{
#ifdef MULTI_KBOARD
int was_locked = single_kboard;
if (was_locked)
{
- if (k != NULL)
- push_kboard (k);
+ if (f != NULL && FRAME_KBOARD (f) != current_kboard)
+ /* We can not switch keyboards while in single_kboard mode.
+ This can legally happen when Lisp code calls
+ `recursive-edit' (or `read-minibuffer' or `y-or-n-p') after
+ it switched to a locked frame. This kind of situation is
+ likely to happen when server.el connects to a new
+ terminal. */
+ error ("Terminal %d is locked, cannot read from it",
+ FRAME_TERMINAL (f)->id);
else
+ /* This call is unnecessary, but helps
+ `restore_kboard_configuration' discover if somebody changed
+ `current_kboard' behind our back. */
push_kboard (current_kboard);
}
- else if (k != NULL)
- current_kboard = k;
- single_kboard_state ();
+ else if (f != NULL)
+ current_kboard = FRAME_KBOARD (f);
+ single_kboard = 1;
record_unwind_protect (restore_kboard_configuration,
(was_locked ? Qt : Qnil));
#endif
}
+#if 0 /* This function is not needed anymore. */
void
record_single_kboard_state ()
{
record_unwind_protect (restore_kboard_configuration,
(single_kboard ? Qt : Qnil));
}
+#endif
static Lisp_Object
restore_kboard_configuration (was_locked)
Lisp_Object was_locked;
{
if (NILP (was_locked))
- any_kboard_state ();
+ single_kboard = 0;
else
{
- single_kboard_state ();
+ struct kboard *prev = current_kboard;
+ single_kboard = 1;
pop_kboard ();
+ /* The pop should not change the kboard. */
+ if (single_kboard && current_kboard != prev)
+ abort ();
}
return Qnil;
}
Vquit_flag = Qnil;
Vinhibit_quit = Qnil;
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
#ifdef MULTI_KBOARD
if (command_loop_level == 0 && minibuf_level == 0)
any_kboard_state ();
+#endif
#endif
return make_number (0);
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
/* Reset single_kboard in case top-level set it while
evaluating an -f option, or we are stuck there for some
other reason. */
any_kboard_state ();
+#endif
internal_catch (Qtop_level, command_loop_2, Qnil);
executing_kbd_macro = Qnil;
int no_direct;
int prev_modiff = 0;
struct buffer *prev_buffer = NULL;
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
#ifdef MULTI_KBOARD
int was_locked = single_kboard;
#endif
+#endif
int already_adjusted = 0;
current_kboard->Vprefix_arg = Qnil;
if (!NILP (current_kboard->defining_kbd_macro)
&& NILP (current_kboard->Vprefix_arg))
finalize_kbd_macro_chars ();
-
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
#ifdef MULTI_KBOARD
if (!was_locked)
- any_kboard_state ();
+ any_kboard_state ();
+#endif
#endif
}
}
static Lisp_Object kbd_buffer_get_event ();
static void record_char ();
-#ifdef MULTI_KBOARD
-static jmp_buf wrong_kboard_jmpbuf;
-#endif
-
#define STOP_POLLING \
do { if (! polling_stopped_here) stop_polling (); \
polling_stopped_here = 1; } while (0)
if we used a mouse menu to read the input, or zero otherwise. If
USED_MOUSE_MENU is null, we don't dereference it.
+ WRONG_KBOARD_JMPBUF should be a stack context to longjmp to in case
+ we find input on another keyboard.
+
Value is t if we showed a menu and the user rejected it. */
Lisp_Object
-read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
+read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu, wrong_kboard_jmpbuf)
int commandflag;
int nmaps;
Lisp_Object *maps;
Lisp_Object prev_event;
int *used_mouse_menu;
+ jmp_buf *wrong_kboard_jmpbuf;
{
volatile Lisp_Object c;
int count;
volatile int reread;
struct gcpro gcpro1, gcpro2;
int polling_stopped_here = 0;
+ struct kboard *orig_kboard = current_kboard;
also_record = Qnil;
/* This is going to exit from read_char
so we had better get rid of this frame's stuff. */
UNGCPRO;
- longjmp (wrong_kboard_jmpbuf, 1);
+ if (wrong_kboard_jmpbuf == NULL)
+ abort ();
+ longjmp (*wrong_kboard_jmpbuf, 1);
}
}
#endif
}
}
+ /* Notify the caller if a timer or sentinel or filter in the sit_for
+ calls above have changed the current kboard. This could happen
+ if they start a recursive edit, like the fancy splash screen in
+ server.el's filter. If this longjmp wasn't here,
+ read_key_sequence would interpret the next key sequence using the
+ wrong translation tables and function keymaps. */
+ if (NILP (c) && current_kboard != orig_kboard)
+ {
+ UNGCPRO;
+ if (wrong_kboard_jmpbuf == NULL)
+ abort ();
+ longjmp (*wrong_kboard_jmpbuf, 1);
+ }
+
/* If this has become non-nil here, it has been set by a timer
or sentinel or filter. */
if (CONSP (Vunread_command_events))
/* This is going to exit from read_char
so we had better get rid of this frame's stuff. */
UNGCPRO;
- longjmp (wrong_kboard_jmpbuf, 1);
+ if (wrong_kboard_jmpbuf == NULL)
+ abort ();
+ longjmp (*wrong_kboard_jmpbuf, 1);
}
}
#endif
/* This is going to exit from read_char
so we had better get rid of this frame's stuff. */
UNGCPRO;
- longjmp (wrong_kboard_jmpbuf, 1);
+ if (wrong_kboard_jmpbuf == NULL)
+ abort ();
+ longjmp (*wrong_kboard_jmpbuf, 1);
}
#endif
}
if (!NILP (tem))
{
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
int was_locked = single_kboard;
-
+ int count = SPECPDL_INDEX ();
+ record_single_kboard_state ();
+#endif
+
last_input_char = c;
Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt);
example banishing the mouse under mouse-avoidance-mode. */
timer_resume_idle ();
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
/* Resume allowing input from any kboard, if that was true before. */
if (!was_locked)
any_kboard_state ();
+ unbind_to (count, Qnil);
+#endif
goto retry;
}
cancel_echoing ();
do
- c = read_char (0, 0, 0, Qnil, 0);
+ c = read_char (0, 0, 0, Qnil, 0, &wrong_kboard_jmpbuf);
while (BUFFERP (c));
/* Remove the help from the frame */
unbind_to (count, Qnil);
{
cancel_echoing ();
do
- c = read_char (0, 0, 0, Qnil, 0);
+ c = read_char (0, 0, 0, Qnil, 0, &wrong_kboard_jmpbuf);
while (BUFFERP (c));
}
}
int count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
+#if 0 /* This shouldn't be necessary anymore. --lorentey */
/* On unbind_to, resume allowing input from any kboard, if that
was true before. */
record_single_kboard_state ();
-
+#endif
/* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */
vector[0] = Qt;
int junk;
#endif
+ jmp_buf *volatile wrong_kboard_jmpbuf = alloca (sizeof (jmp_buf));
+
struct gcpro gcpro1;
GCPRO1 (fake_prefixed_keys);
/* Read the first char of the sequence specially, before setting
up any keymaps, in case a filter runs and switches buffers on us. */
first_event = read_char (NILP (prompt), 0, submaps, last_nonmenu_event,
- &junk);
+ &junk, NULL);
#endif /* GOBBLE_FIRST_EVENT */
orig_local_map = get_local_map (PT, current_buffer, Qlocal_map);
#ifdef MULTI_KBOARD
KBOARD *interrupted_kboard = current_kboard;
struct frame *interrupted_frame = SELECTED_FRAME ();
- if (setjmp (wrong_kboard_jmpbuf))
+ if (setjmp (*wrong_kboard_jmpbuf))
{
+ int found = 0;
+ struct kboard *k;
+
+ for (k = all_kboards; k; k = k->next_kboard)
+ if (k == interrupted_kboard)
+ found = 1;
+ if (!found)
+ abort ();
+
if (!NILP (delayed_switch_frame))
{
interrupted_kboard->kbd_queue
#endif
key = read_char (NILP (prompt), nmaps,
(Lisp_Object *) submaps, last_nonmenu_event,
- &used_mouse_menu);
+ &used_mouse_menu, wrong_kboard_jmpbuf);
}
/* read_char returns t when it shows a menu and the user rejects it.
{
/* If there are no frames there, let's pretend that we are a
well-behaving UN*X program and quit. */
- fatal_error_signal (SIGTERM);
+ Fkill_emacs (Qnil);
}
else
{
&& FRAMEP (selected_frame)
&& FRAME_LIVE_P (XFRAME (selected_frame)))
{
- current_kboard = XFRAME (selected_frame)->terminal->kboard;
+ current_kboard = FRAME_KBOARD (XFRAME (selected_frame));
+ single_kboard = 0;
if (current_kboard == kb)
abort ();
}