Commit cd21b839 authored by Jim Blandy's avatar Jim Blandy

* keyboard.c (Vlast_event_frame): Make this variable exist even

	when MULTI_FRAME isn't #defined.  People might find it
	necessary for writing correct programs, even when the programs
	don't explicitly use multiple frames.
	(read_char, kbd_buffer_store_event, kbd_buffer_get_event): No need
	to test MULTI_FRAME before setting Vlast_event_frame.
	(syms_of_keyboard): DEFVAR Vlast_event_frame whether or not
	MULTI_FRAME is defined.

        * keyboard.c: Add switch-frame events.
	(Qswitch_frame): New event header symbol.
	(head_table): Include Qswitch_frame in the table of event heads.
	(kbd_buffer_get_event): Detect when a frame switch has occurred,
	and return a frame switch event before the enqueued event.
	(make_lispy_switch_frame): New function.
	(unread_switch_frame): New variable.
	(read_key_sequence): Don't throw away the key sequence if the user
	switches frames in the middle of the sequence.  Instead, when we
	receive a switch-frame event in the middle of a key sequence, save
	it, and stuff it into unread_switch_frame when the sequence
	is complete.
	(read_char): If unread_switch_frame is set, return that value.
	(command_loop_1): No need to check Vlast_event_frame and select
	new frames here; that's taken care of by switch-frame events now.
	(syms_of_keyboard): Initialize and staticpro unread_switch_frame.

	* keyboard.c (follow_key, read_key_sequence): Call access_keymap
	with T_OK true.

	* keyboard.c (apply_modifiers): Copy the value of BASE's
	Qevent_kind property to the new symbol.

	* keyboard.c (syms_of_keyboard): Qevent_kind should be initialized
	to intern ("event-kind"), not intern ("event-type").
parent 2f0b07e0
......@@ -151,6 +151,11 @@ Lisp_Object last_input_char;
/* If not Qnil, an object to be read as the next command input. */
Lisp_Object unread_command_char;
/* If not Qnil, this is a switch-frame event which we decided to put
off until the end of a key sequence. This should be read as the
next command input, after any unread_command_char. */
Lisp_Object unread_switch_frame;
/* Char to use as prefix when a meta character is typed in.
This is bound on entry to minibuffer in case ESC is changed there. */
......@@ -187,15 +192,16 @@ Lisp_Object last_command;
instead of the actual command. */
Lisp_Object this_command;
#ifdef MULTI_FRAME
/* The frame in which the last input event occurred, or Qmacro if the
last event came from a macro.
command_loop_1 will select this frame before running the
command bound to an event sequence, and read_key_sequence will
toss the existing prefix if the user starts typing at a
new frame. */
new frame.
On a non-multi-frame Emacs, this will be either Qmacro or
selected_frame. */
Lisp_Object Vlast_event_frame;
#endif
/* The timestamp of the last input event we received from the X server.
X Windows wants this for selection ownership. */
......@@ -285,6 +291,8 @@ Lisp_Object Qhslider_part;
Lisp_Object Qhthumbleft_part;
Lisp_Object Qhthumbright_part;
Lisp_Object Qswitch_frame;
/* Symbols to denote kinds of events. */
Lisp_Object Qfunction_key;
Lisp_Object Qmouse_click;
......@@ -842,11 +850,13 @@ command_loop_1 ()
++num_input_keys;
#if 0 /* This shouldn't be necessary, now that we have switch-frame events. */
#ifdef MULTI_FRAME
/* Select the frame that the key sequence came from. */
if (XTYPE (Vlast_event_frame) == Lisp_Frame
&& XFRAME (Vlast_event_frame) != selected_frame)
Fselect_frame (Vlast_event_frame, Qnil);
#endif
#endif
/* Now we have read a key sequence of length I,
......@@ -1136,6 +1146,16 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
goto from_macro;
}
if (!NILP (unread_switch_frame))
{
c = unread_switch_frame;
unread_switch_frame = Qnil;
/* This event should make it into this_command_keys, and get echoed
again, so we go to reread, rather than reread_first. */
goto reread;
}
/* Save outer setjmp data, in case called recursively. */
save_getcjmp (save_jump);
......@@ -1147,9 +1167,7 @@ read_char (commandflag, nmaps, maps, prev_event, used_mouse_menu)
if (_setjmp (getcjmp))
{
XSET (c, Lisp_Int, quit_char);
#ifdef MULTI_FRAME
XSET (Vlast_event_frame, Lisp_Frame, selected_frame);
#endif
goto non_reread;
}
......@@ -1462,13 +1480,11 @@ kbd_buffer_store_event (event)
{
extern SIGTYPE interrupt_signal ();
#ifdef MULTI_FRAME
/* If this results in a quit_char being returned to Emacs as
input, set last-event-frame properly. If this doesn't
get returned to Emacs as an event, the next event read
will set Vlast_event_frame again, so this is safe to do. */
Vlast_event_frame = FRAME_FOCUS_FRAME (event->frame);
#endif
last_event_timestamp = event->timestamp;
interrupt_signal ();
......@@ -1509,6 +1525,7 @@ kbd_buffer_store_event (event)
static Lisp_Object make_lispy_event ();
static Lisp_Object make_lispy_movement ();
static Lisp_Object modify_event_symbol ();
static Lisp_Object make_lispy_switch_frame ();
static Lisp_Object
kbd_buffer_get_event ()
......@@ -1564,20 +1581,34 @@ kbd_buffer_get_event ()
mouse movement enabled and available. */
if (kbd_fetch_ptr != kbd_store_ptr)
{
if (kbd_fetch_ptr == kbd_buffer + KBD_BUFFER_SIZE)
kbd_fetch_ptr = kbd_buffer;
struct input_event *event;
Lisp_Object frame;
#ifdef MULTI_FRAME
XSET (Vlast_event_frame, Lisp_Frame,
XFRAME (FRAME_FOCUS_FRAME (kbd_fetch_ptr->frame)));
#endif
event = ((kbd_fetch_ptr <= kbd_buffer + KBD_BUFFER_SIZE)
? kbd_fetch_ptr
: kbd_buffer);
last_event_timestamp = kbd_fetch_ptr->timestamp;
obj = make_lispy_event (kbd_fetch_ptr);
kbd_fetch_ptr->kind = no_event;
kbd_fetch_ptr++;
if (XTYPE (obj) == Lisp_Int)
XSET (obj, Lisp_Int, XINT (obj) & (meta_key ? 0377 : 0177));
last_event_timestamp = event->timestamp;
XSET (frame, Lisp_Frame, XFRAME (FRAME_FOCUS_FRAME (event->frame)));
/* 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, Vlast_event_frame))
{
Vlast_event_frame = frame;
obj = make_lispy_switch_frame (frame);
}
else
{
obj = make_lispy_event (event);
if (XTYPE (obj) == Lisp_Int)
XSET (obj, Lisp_Int, XINT (obj) & (meta_key ? 0377 : 0177));
/* Wipe out this event, to catch bugs. */
event->kind = no_event;
kbd_fetch_ptr = event + 1;
}
}
else if (do_mouse_tracking && mouse_moved)
{
......@@ -1586,11 +1617,14 @@ kbd_buffer_get_event ()
unsigned long time;
(*mouse_position_hook) (&frame, &x, &y, &time);
#ifdef MULTI_FRAME
XSET (Vlast_event_frame, Lisp_Frame, frame);
#endif
obj = make_lispy_movement (frame, x, y, time);
if (frame != XFRAME (Vlast_event_frame))
{
XSET (Vlast_event_frame, Lisp_Frame, frame);
obj = make_lispy_switch_frame (Vlast_event_frame);
}
else
obj = make_lispy_movement (frame, x, y, time);
}
else
/* We were promised by the above while loop that there was
......@@ -1898,6 +1932,14 @@ make_lispy_movement (frame, x, y, time)
}
/* Construct a switch frame event. */
static Lisp_Object
make_lispy_switch_frame (frame)
Lisp_Object frame;
{
return Fcons (Qswitch_frame, Fcons (frame, Qnil));
}
/* Manipulating modifiers. */
......@@ -2122,7 +2164,10 @@ parse_modifiers (symbol)
This is like apply_modifiers_uncached, but uses BASE's
Qmodifier_cache property, if present. It also builds
Qevent_symbol_elements properties, since it has that info anyway. */
Qevent_symbol_elements properties, since it has that info anyway.
apply_modifiers copies the value of BASE's Qevent_kind property to
the modified symbol. */
static Lisp_Object
apply_modifiers (modifiers, base)
int modifiers;
......@@ -2131,8 +2176,8 @@ apply_modifiers (modifiers, base)
Lisp_Object cache, index, entry;
/* The click modifier never figures into cache indices. */
XFASTINT (index) = (modifiers & ~click_modifier);
cache = Fget (base, Qmodifier_cache);
XFASTINT (index) = (modifiers & ~click_modifier);
entry = Fassq (index, cache);
if (CONSP (entry))
......@@ -2156,6 +2201,9 @@ apply_modifiers (modifiers, base)
Fput (new_symbol, Qevent_symbol_elements,
Fcons (base, lispy_modifier_list (modifiers)));
/* This symbol is of the same kind as BASE. */
Fput (new_symbol, Qevent_kind, Fget (new_symbol, Qevent_kind));
return new_symbol;
}
}
......@@ -2710,8 +2758,8 @@ follow_key (key, nmaps, current, defs, next)
for (i = 0; i < nmaps; i++)
if (! NILP (current[i]))
{
next[i] = get_keyelt (access_keymap (current[i],
meta_prefix_char));
next[i] =
get_keyelt (access_keymap (current[i], meta_prefix_char, 1));
/* Note that since we pass the resulting bindings through
get_keymap_1, non-prefix bindings for meta-prefix-char
......@@ -2730,7 +2778,7 @@ follow_key (key, nmaps, current, defs, next)
{
if (! NILP (current[i]))
{
defs[i] = get_keyelt (access_keymap (current[i], key));
defs[i] = get_keyelt (access_keymap (current[i], key, 1));
if (! NILP (defs[i]))
first_binding = i;
}
......@@ -2752,7 +2800,7 @@ follow_key (key, nmaps, current, defs, next)
{
if (! NILP (current[i]))
{
defs[i] = get_keyelt (access_keymap (current[i], key));
defs[i] = get_keyelt (access_keymap (current[i], key, 1));
if (! NILP (defs[i]))
first_binding = i;
}
......@@ -2843,6 +2891,10 @@ read_key_sequence (keybuf, bufsize, prompt)
int fkey_start = 0, fkey_end = 0;
Lisp_Object fkey_map = Vfunction_key_map;
/* If we receive a ``switch-frame'' event in the middle of a key sequence,
we put it off for later. While we're reading, we keep the event here. */
Lisp_Object delayed_switch_frame = Qnil;
last_nonmenu_event = Qnil;
if (INTERACTIVE)
......@@ -2935,30 +2987,49 @@ read_key_sequence (keybuf, bufsize, prompt)
Emacs 18 handles this by returning immediately with a
zero, so that's what we'll do. */
if (XTYPE (key) == Lisp_Int && XINT (key) < 0)
return 0;
{
unread_switch_frame = delayed_switch_frame;
return 0;
}
Vquit_flag = Qnil;
/* Clicks in non-text areas get prefixed by the symbol
in their CHAR-ADDRESS field. For example, a click on
the mode line is prefixed by the symbol `mode-line'. */
if (EVENT_HAS_PARAMETERS (key)
&& EQ (EVENT_HEAD_KIND (EVENT_HEAD (key)), Qmouse_click))
if (EVENT_HAS_PARAMETERS (key))
{
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
if (XTYPE (posn) == Lisp_Symbol)
Lisp_Object kind = EVENT_HEAD_KIND (EVENT_HEAD (key));
if (EQ (kind, Qmouse_click))
{
if (t + 1 >= bufsize)
error ("key sequence too long");
keybuf[t] = posn;
keybuf[t+1] = key;
mock_input = t + 2;
Lisp_Object posn = POSN_BUFFER_POSN (EVENT_START (key));
goto retry_key;
if (XTYPE (posn) == Lisp_Symbol)
{
if (t + 1 >= bufsize)
error ("key sequence too long");
keybuf[t] = posn;
keybuf[t+1] = key;
mock_input = t + 2;
goto retry_key;
}
}
else if (EQ (kind, Qswitch_frame))
{
/* If we're at the beginning of a key sequence, go
ahead and return this event. If we're in the
midst of a key sequence, delay it until the end. */
if (t > 0)
{
delayed_switch_frame = key;
goto retry_key;
}
}
}
#if 0 /* This shouldn't be necessary any more, now that we have
switch-frame events. */
#ifdef MULTI_FRAME
/* What buffer was this event typed/moused at? */
if (used_mouse_menu)
......@@ -2999,7 +3070,8 @@ read_key_sequence (keybuf, bufsize, prompt)
goto restart;
}
#endif
#endif /* MULTI_FRAME */
#endif /* 0 */
}
first_binding = (follow_key (key,
......@@ -3087,15 +3159,16 @@ read_key_sequence (keybuf, bufsize, prompt)
with meta_prefix_char. I hate this. */
if (keybuf[fkey_end] & 0x80)
fkey_next =
get_keymap_1 (get_keyelt
(access_keymap (fkey_map, meta_prefix_char)),
0);
get_keymap_1
((get_keyelt
(access_keymap (fkey_map, meta_prefix_char, 1))),
0);
else
fkey_next = fkey_map;
fkey_next =
get_keyelt (access_keymap
(fkey_next, keybuf[fkey_end++] & 0x7f));
(fkey_next, keybuf[fkey_end++] & 0x7f, 1));
/* If keybuf[fkey_start..fkey_end] is bound in the
function key map and it's a suffix of the current
......@@ -3135,6 +3208,7 @@ read_key_sequence (keybuf, bufsize, prompt)
? defs[first_binding]
: Qnil);
unread_switch_frame = delayed_switch_frame;
return t;
}
......@@ -3773,7 +3847,8 @@ struct event_head head_table[] = {
&Qhscrollbar_part, "hscrollbar-part", &Qscrollbar_click,
&Qhslider_part, "hslider-part", &Qscrollbar_click,
&Qhthumbleft_part, "hthumbleft-part", &Qscrollbar_click,
&Qhthumbright_part,"hthumbright-part", &Qscrollbar_click
&Qhthumbright_part,"hthumbright-part", &Qscrollbar_click,
&Qswitch_frame, "switch-frame", &Qswitch_frame
};
syms_of_keyboard ()
......@@ -3802,7 +3877,7 @@ syms_of_keyboard ()
Qvertical_line = intern ("vertical-line");
staticpro (&Qvertical_line);
Qevent_kind = intern ("event-type");
Qevent_kind = intern ("event-kind");
staticpro (&Qevent_kind);
Qevent_symbol_elements = intern ("event-symbol-elements");
staticpro (&Qevent_symbol_elements);
......@@ -3851,6 +3926,9 @@ syms_of_keyboard ()
mouse_syms = Qnil;
staticpro (&mouse_syms);
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
defsubr (&Sread_key_sequence);
defsubr (&Srecursive_edit);
defsubr (&Strack_mouse);
......@@ -3932,12 +4010,10 @@ Polling is automatically disabled in all other cases.");
"*Number of complete keys read from the keyboard so far.");
num_input_keys = 0;
#ifdef MULTI_FRAME
DEFVAR_LISP ("last-event-frame", &Vlast_event_frame,
"*The frame in which the most recently read event occurred.\n\
If the last event came from a keyboard macro, this is set to `macro'.");
Vlast_event_frame = Qnil;
#endif
DEFVAR_LISP ("help-char", &help_char,
"Character to recognize as meaning Help.\n\
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment