summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Blandy <jimb@redhat.com>1992-10-11 06:42:03 +0000
committerJim Blandy <jimb@redhat.com>1992-10-11 06:42:03 +0000
commitcd21b83986f5d0f68ba8228f0aeca901677be8be (patch)
treee4609f5078b4c15814d1647abc805cccabaac36a
parent2f0b07e06c9b2c9bc62f615e471e2dcb04406d38 (diff)
downloademacs-cd21b83986f5d0f68ba8228f0aeca901677be8be.tar.gz
* 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").
-rw-r--r--src/keyboard.c176
1 files changed, 126 insertions, 50 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 9afcb951a1b..bd76b4cd966 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -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,12 +850,14 @@ 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,
or else I is 0 and we found end of file. */
@@ -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\