summaryrefslogtreecommitdiff
path: root/src/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keyboard.c')
-rw-r--r--src/keyboard.c250
1 files changed, 173 insertions, 77 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 9ee4c4f6d68..2e4c4e6aabf 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -725,6 +725,9 @@ recursive_edit_1 (void)
if (STRINGP (val))
xsignal1 (Qerror, val);
+ if (FUNCTIONP (val))
+ call0 (val);
+
return unbind_to (count, Qnil);
}
@@ -921,6 +924,8 @@ static Lisp_Object
cmd_error (Lisp_Object data)
{
Lisp_Object old_level, old_length;
+ ptrdiff_t count = SPECPDL_INDEX ();
+ Lisp_Object conditions;
char macroerror[sizeof "After..kbd macro iterations: "
+ INT_STRLEN_BOUND (EMACS_INT)];
@@ -940,10 +945,15 @@ cmd_error (Lisp_Object data)
else
*macroerror = 0;
- Vstandard_output = Qt;
- Vstandard_input = Qt;
- Vexecuting_kbd_macro = Qnil;
- executing_kbd_macro = Qnil;
+ conditions = Fget (XCAR (data), Qerror_conditions);
+ if (NILP (Fmemq (Qminibuffer_quit, conditions)))
+ {
+ Vexecuting_kbd_macro = Qnil;
+ executing_kbd_macro = Qnil;
+ }
+
+ specbind (Qstandard_output, Qt);
+ specbind (Qstandard_input, Qt);
kset_prefix_arg (current_kboard, Qnil);
kset_last_prefix_arg (current_kboard, Qnil);
cancel_echoing ();
@@ -960,6 +970,7 @@ cmd_error (Lisp_Object data)
Vquit_flag = Qnil;
Vinhibit_quit = Qnil;
+ unbind_to (count, Qnil);
return make_fixnum (0);
}
@@ -976,7 +987,7 @@ cmd_error_internal (Lisp_Object data, const char *context)
{
/* The immediate context is not interesting for Quits,
since they are asynchronous. */
- if (EQ (XCAR (data), Qquit))
+ if (signal_quit_p (XCAR (data)))
Vsignaling_function = Qnil;
Vquit_flag = Qnil;
@@ -998,6 +1009,7 @@ Default value of `command-error-function'. */)
(Lisp_Object data, Lisp_Object context, Lisp_Object signal)
{
struct frame *sf = SELECTED_FRAME ();
+ Lisp_Object conditions;
CHECK_STRING (context);
@@ -1024,17 +1036,27 @@ Default value of `command-error-function'. */)
}
else
{
+ conditions = Fget (XCAR (data), Qerror_conditions);
+
clear_message (1, 0);
- Fdiscard_input ();
message_log_maybe_newline ();
- bitch_at_user ();
+
+ if (!NILP (Fmemq (Qminibuffer_quit, conditions)))
+ {
+ Fding (Qt);
+ }
+ else
+ {
+ Fdiscard_input ();
+ bitch_at_user ();
+ }
print_error_message (data, Qt, SSDATA (context), signal);
}
return Qnil;
}
-static Lisp_Object command_loop_2 (Lisp_Object);
+static Lisp_Object command_loop_1 (void);
static Lisp_Object top_level_1 (Lisp_Object);
/* Entry to editor-command-loop.
@@ -1062,7 +1084,7 @@ command_loop (void)
if (command_loop_level > 0 || minibuf_level > 0)
{
Lisp_Object val;
- val = internal_catch (Qexit, command_loop_2, Qnil);
+ val = internal_catch (Qexit, command_loop_2, Qerror);
executing_kbd_macro = Qnil;
return val;
}
@@ -1070,7 +1092,7 @@ command_loop (void)
while (1)
{
internal_catch (Qtop_level, top_level_1, Qnil);
- internal_catch (Qtop_level, command_loop_2, Qnil);
+ internal_catch (Qtop_level, command_loop_2, Qerror);
executing_kbd_macro = Qnil;
/* End of file in -batch run causes exit here. */
@@ -1083,15 +1105,16 @@ command_loop (void)
editing loop, and reenter the editing loop.
When there is an error, cmd_error runs and returns a non-nil
value to us. A value of nil means that command_loop_1 itself
- returned due to end of file (or end of kbd macro). */
+ returned due to end of file (or end of kbd macro). HANDLERS is a
+ list of condition names, passed to internal_condition_case. */
-static Lisp_Object
-command_loop_2 (Lisp_Object ignore)
+Lisp_Object
+command_loop_2 (Lisp_Object handlers)
{
register Lisp_Object val;
do
- val = internal_condition_case (command_loop_1, Qerror, cmd_error);
+ val = internal_condition_case (command_loop_1, handlers, cmd_error);
while (!NILP (val));
return Qnil;
@@ -1234,7 +1257,7 @@ static int read_key_sequence (Lisp_Object *, Lisp_Object,
bool, bool, bool, bool);
static void adjust_point_for_property (ptrdiff_t, bool);
-Lisp_Object
+static Lisp_Object
command_loop_1 (void)
{
modiff_count prev_modiff = 0;
@@ -2121,7 +2144,7 @@ read_char_help_form_unwind (void)
Lisp_Object window_config = XCAR (help_form_saved_window_configs);
help_form_saved_window_configs = XCDR (help_form_saved_window_configs);
if (!NILP (window_config))
- Fset_window_configuration (window_config, Qnil);
+ Fset_window_configuration (window_config, Qnil, Qnil);
}
#define STOP_POLLING \
@@ -2254,8 +2277,17 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
{
int i;
if (meta_key != 2)
- for (i = 0; i < n; i++)
- events[i] = make_fixnum (XFIXNUM (events[i]) & ~0x80);
+ {
+ for (i = 0; i < n; i++)
+ {
+ int c = XFIXNUM (events[i]);
+ int modifier =
+ (meta_key == 3 && c < 0x100 && (c & 0x80))
+ ? meta_modifier
+ : 0;
+ events[i] = make_fixnum ((c & ~0x80) | modifier);
+ }
+ }
}
else
{
@@ -2264,7 +2296,7 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
int i;
for (i = 0; i < n; i++)
src[i] = XFIXNUM (events[i]);
- if (meta_key != 2)
+ if (meta_key < 2) /* input-meta-mode is t or nil */
for (i = 0; i < n; i++)
src[i] &= ~0x80;
coding->destination = dest;
@@ -2282,7 +2314,18 @@ read_decoded_event_from_main_queue (struct timespec *end_time,
eassert (coding->carryover_bytes == 0);
n = 0;
while (n < coding->produced_char)
- events[n++] = make_fixnum (string_char_advance (&p));
+ {
+ int c = string_char_advance (&p);
+ if (meta_key == 3)
+ {
+ int modifier
+ = (c < 0x100 && (c & 0x80)
+ ? meta_modifier
+ : 0);
+ c = (c & ~0x80) | modifier;
+ }
+ events[n++] = make_fixnum (c);
+ }
}
}
}
@@ -3233,10 +3276,6 @@ help_char_p (Lisp_Object c)
static void
record_char (Lisp_Object c)
{
- /* quail.el binds this to avoid recording keys twice. */
- if (inhibit_record_char)
- return;
-
int recorded = 0;
if (CONSP (c) && (EQ (XCAR (c), Qhelp_echo) || EQ (XCAR (c), Qmouse_movement)))
@@ -3614,6 +3653,12 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
case ICONIFY_EVENT: ignore_event = Qiconify_frame; break;
case DEICONIFY_EVENT: ignore_event = Qmake_frame_visible; break;
case SELECTION_REQUEST_EVENT: ignore_event = Qselection_request; break;
+#ifdef USE_FILE_NOTIFY
+ case FILE_NOTIFY_EVENT: ignore_event = Qfile_notify; break;
+#endif
+#ifdef HAVE_DBUS
+ case DBUS_EVENT: ignore_event = Qdbus_event; break;
+#endif
default: ignore_event = Qnil; break;
}
@@ -5016,6 +5061,10 @@ static short const internal_border_parts[] = {
static Lisp_Object button_down_location;
+/* A cons recording the original frame-relative x and y coordinates of
+ the down mouse event. */
+static Lisp_Object frame_relative_event_pos;
+
/* Information about the most recent up-going button event: Which
button, what location, and what time. */
@@ -5667,6 +5716,7 @@ make_lispy_event (struct input_event *event)
double_click_count = 1;
button_down_time = event->timestamp;
*start_pos_ptr = Fcopy_alist (position);
+ frame_relative_event_pos = Fcons (event->x, event->y);
ignore_mouse_drag_p = false;
}
@@ -5689,20 +5739,12 @@ make_lispy_event (struct input_event *event)
ignore_mouse_drag_p = false;
else
{
- Lisp_Object new_down, down;
intmax_t xdiff = double_click_fuzz, ydiff = double_click_fuzz;
- /* The third element of every position
- should be the (x,y) pair. */
- down = Fcar (Fcdr (Fcdr (start_pos)));
- new_down = Fcar (Fcdr (Fcdr (position)));
-
- if (CONSP (down)
- && FIXNUMP (XCAR (down)) && FIXNUMP (XCDR (down)))
- {
- xdiff = XFIXNUM (XCAR (new_down)) - XFIXNUM (XCAR (down));
- ydiff = XFIXNUM (XCDR (new_down)) - XFIXNUM (XCDR (down));
- }
+ xdiff = XFIXNUM (event->x)
+ - XFIXNUM (XCAR (frame_relative_event_pos));
+ ydiff = XFIXNUM (event->y)
+ - XFIXNUM (XCDR (frame_relative_event_pos));
if (! (0 < double_click_fuzz
&& - double_click_fuzz < xdiff
@@ -5719,12 +5761,51 @@ make_lispy_event (struct input_event *event)
a click. But mouse-drag-region completely ignores
this case and it hasn't caused any real problem, so
it's probably OK to ignore it as well. */
- && EQ (Fcar (Fcdr (start_pos)), Fcar (Fcdr (position)))))
+ && (EQ (Fcar (Fcdr (start_pos)),
+ Fcar (Fcdr (position))) /* Same buffer pos */
+ || !EQ (Fcar (start_pos),
+ Fcar (position))))) /* Different window */
{
/* Mouse has moved enough. */
button_down_time = 0;
click_or_drag_modifier = drag_modifier;
}
+ else if (((!EQ (Fcar (start_pos), Fcar (position)))
+ || (!EQ (Fcar (Fcdr (start_pos)),
+ Fcar (Fcdr (position)))))
+ /* Was the down event in a window body? */
+ && FIXNUMP (Fcar (Fcdr (start_pos)))
+ && WINDOW_LIVE_P (Fcar (start_pos))
+ && !NILP (Ffboundp (Qwindow_edges)))
+ /* If the window (etc.) at the mouse position has
+ changed between the down event and the up event,
+ we assume there's been a redisplay between the
+ two events, and we pretend the mouse is still in
+ the old window to prevent a spurious drag event
+ being generated. */
+ {
+ Lisp_Object edges
+ = call4 (Qwindow_edges, Fcar (start_pos), Qt, Qnil, Qt);
+ int new_x = XFIXNUM (Fcar (frame_relative_event_pos));
+ int new_y = XFIXNUM (Fcdr (frame_relative_event_pos));
+
+ /* If the up-event is outside the down-event's
+ window, use coordinates that are within it. */
+ if (new_x < XFIXNUM (Fcar (edges)))
+ new_x = XFIXNUM (Fcar (edges));
+ else if (new_x >= XFIXNUM (Fcar (Fcdr (Fcdr (edges)))))
+ new_x = XFIXNUM (Fcar (Fcdr (Fcdr (edges)))) - 1;
+ if (new_y < XFIXNUM (Fcar (Fcdr (edges))))
+ new_y = XFIXNUM (Fcar (Fcdr (edges)));
+ else if (new_y
+ >= XFIXNUM (Fcar (Fcdr (Fcdr (Fcdr (edges))))))
+ new_y = XFIXNUM (Fcar (Fcdr (Fcdr (Fcdr (edges))))) - 1;
+
+ position = make_lispy_position
+ (XFRAME (event->frame_or_window),
+ make_fixnum (new_x), make_fixnum (new_y),
+ event->timestamp);
+ }
}
/* Don't check is_double; treat this as multiple if the
@@ -6564,8 +6645,11 @@ DEFUN ("event-convert-list", Fevent_convert_list, Sevent_convert_list, 1, 1, 0,
EVENT-DESC should contain one base event type (a character or symbol)
and zero or more modifier names (control, meta, hyper, super, shift, alt,
drag, down, double or triple). The base must be last.
-The return value is an event type (a character or symbol) which
-has the same base event type and all the specified modifiers. */)
+
+The return value is an event type (a character or symbol) which has
+essentially the same base event type and all the specified modifiers.
+(Some compatibility base types, like symbols that represent a
+character, are not returned verbatim.) */)
(Lisp_Object event_desc)
{
Lisp_Object base = Qnil;
@@ -6679,6 +6763,7 @@ parse_solitary_modifier (Lisp_Object symbol)
case 'c':
MULTI_LETTER_MOD (ctrl_modifier, "ctrl", 4);
MULTI_LETTER_MOD (ctrl_modifier, "control", 7);
+ MULTI_LETTER_MOD (click_modifier, "click", 5);
break;
case 'H':
@@ -7029,7 +7114,7 @@ tty_read_avail_input (struct terminal *terminal,
buf.modifiers = 0;
if (tty->meta_key == 1 && (cbuf[i] & 0x80))
buf.modifiers = meta_modifier;
- if (tty->meta_key != 2)
+ if (tty->meta_key < 2)
cbuf[i] &= ~0x80;
buf.code = cbuf[i];
@@ -7551,7 +7636,7 @@ menu_item_eval_property_1 (Lisp_Object arg)
{
/* If we got a quit from within the menu computation,
quit all the way out of it. This takes care of C-] in the debugger. */
- if (CONSP (arg) && EQ (XCAR (arg), Qquit))
+ if (CONSP (arg) && signal_quit_p (XCAR (arg)))
quit ();
return Qnil;
@@ -9536,17 +9621,23 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
(interrupted_kboard,
Fcons (make_lispy_switch_frame (frame),
KVAR (interrupted_kboard, kbd_queue)));
+ mock_input = 0;
+ }
+ else
+ {
+ if (FIXNUMP (key) && XFIXNUM (key) != -2)
+ {
+ /* If interrupted while initializing terminal, we
+ need to replay the interrupting key. See
+ Bug#5095 and Bug#37782. */
+ mock_input = 1;
+ keybuf[0] = key;
+ }
+ else
+ {
+ mock_input = 0;
+ }
}
- if (FIXNUMP (key) && XFIXNUM (key) != -2)
- {
- /* If interrupted while initializing terminal, we
- need to replay the interrupting key. See
- Bug#5095 and Bug#37782. */
- mock_input = 1;
- keybuf[0] = key;
- }
- else
- mock_input = 0;
goto replay_entire_sequence;
}
}
@@ -10372,7 +10463,7 @@ update_recent_keys (int new_size, int kept_keys)
}
DEFUN ("lossage-size", Flossage_size, Slossage_size, 0, 1,
- "(list (read-number \"new-size: \" (lossage-size)))",
+ "(list (read-number \"Set maximum keystrokes to: \" (lossage-size)))",
doc: /* Return or set the maximum number of keystrokes to save.
If called with a non-nil ARG, set the limit to ARG and return it.
Otherwise, return the current limit.
@@ -10658,10 +10749,7 @@ On such systems, Emacs starts a subshell instead of suspending. */)
with a window system; but suspend should be disabled in that case. */
get_tty_size (fileno (CURTTY ()->input), &width, &height);
if (width != old_width || height != old_height)
- change_frame_size (SELECTED_FRAME (), width,
- height - FRAME_MENU_BAR_LINES (SELECTED_FRAME ())
- - FRAME_TAB_BAR_LINES (SELECTED_FRAME ()),
- 0, 0, 0, 0);
+ change_frame_size (SELECTED_FRAME (), width, height, false, false, false);
run_hook (intern ("suspend-resume-hook"));
@@ -11039,7 +11127,10 @@ See also `current-input-mode'. */)
DEFUN ("set-input-meta-mode", Fset_input_meta_mode, Sset_input_meta_mode, 1, 2, 0,
doc: /* Enable or disable 8-bit input on TERMINAL.
If META is t, Emacs will accept 8-bit input, and interpret the 8th
-bit as the Meta modifier.
+bit as the Meta modifier before it decodes the characters.
+
+If META is `encoded', Emacs will interpret the 8th bit of single-byte
+characters after decoding the characters.
If META is nil, Emacs will ignore the top bit, on the assumption it is
parity.
@@ -11068,6 +11159,8 @@ See also `current-input-mode'. */)
new_meta = 0;
else if (EQ (meta, Qt))
new_meta = 1;
+ else if (EQ (meta, Qencoded))
+ new_meta = 3;
else
new_meta = 2;
@@ -11130,6 +11223,8 @@ Second arg FLOW non-nil means use ^S/^Q flow control for output to terminal
(no effect except in CBREAK mode).
Third arg META t means accept 8-bit input (for a Meta key).
META nil means ignore the top bit, on the assumption it is parity.
+ META `encoded' means accept 8-bit input and interpret Meta after
+ decoding the input characters.
Otherwise, accept 8-bit input and don't use the top bit for Meta.
Optional fourth arg QUIT if non-nil specifies character to use for quitting.
See also `current-input-mode'. */)
@@ -11150,9 +11245,12 @@ The value is a list of the form (INTERRUPT FLOW META QUIT), where
nil, Emacs is using CBREAK mode.
FLOW is non-nil if Emacs uses ^S/^Q flow control for output to the
terminal; this does not apply if Emacs uses interrupt-driven input.
- META is t if accepting 8-bit input with 8th bit as Meta flag.
- META nil means ignoring the top bit, on the assumption it is parity.
- META is neither t nor nil if accepting 8-bit input and using
+ META is t if accepting 8-bit unencoded input with 8th bit as Meta flag.
+ META is `encoded' if accepting 8-bit encoded input with 8th bit as
+ Meta flag which has to be interpreted after decoding the input.
+ META is nil if ignoring the top bit of input, on the assumption that
+ it is a parity bit.
+ META is neither t nor nil if accepting 8-bit input and using
all 8 bits as the character code.
QUIT is the character Emacs currently uses to quit.
The elements of this list correspond to the arguments of
@@ -11168,7 +11266,9 @@ The elements of this list correspond to the arguments of
flow = FRAME_TTY (sf)->flow_control ? Qt : Qnil;
meta = (FRAME_TTY (sf)->meta_key == 2
? make_fixnum (0)
- : (CURTTY ()->meta_key == 1 ? Qt : Qnil));
+ : (CURTTY ()->meta_key == 1
+ ? Qt
+ : (CURTTY ()->meta_key == 3 ? Qencoded : Qnil)));
}
else
{
@@ -11645,6 +11745,7 @@ syms_of_keyboard (void)
DEFSYM (Qmake_frame_visible, "make-frame-visible");
DEFSYM (Qselect_window, "select-window");
DEFSYM (Qselection_request, "selection-request");
+ DEFSYM (Qwindow_edges, "window-edges");
{
int i;
@@ -11658,9 +11759,11 @@ syms_of_keyboard (void)
}
}
DEFSYM (Qno_record, "no-record");
+ DEFSYM (Qencoded, "encoded");
button_down_location = make_nil_vector (5);
staticpro (&button_down_location);
+ staticpro (&frame_relative_event_pos);
mouse_syms = make_nil_vector (5);
staticpro (&mouse_syms);
wheel_syms = make_nil_vector (ARRAYELTS (lispy_wheel_names));
@@ -12070,10 +12173,11 @@ terminal device. See Info node `(elisp)Multiple Terminals'. */);
DEFVAR_LISP ("overriding-local-map", Voverriding_local_map,
doc: /* Keymap that replaces (overrides) local keymaps.
If this variable is non-nil, Emacs looks up key bindings in this
-keymap INSTEAD OF the keymap char property, minor mode maps, and the
-buffer's local map. Hence, the only active keymaps would be
-`overriding-terminal-local-map', this keymap, and `global-keymap', in
-order of precedence. */);
+keymap INSTEAD OF `keymap' text properties, `local-map' and `keymap'
+overlay properties, minor mode maps, and the buffer's local map.
+
+Hence, the only active keymaps would be `overriding-terminal-local-map',
+this keymap, and `global-keymap', in order of precedence. */);
Voverriding_local_map = Qnil;
DEFVAR_LISP ("overriding-local-map-menu-flag", Voverriding_local_map_menu_flag,
@@ -12265,7 +12369,10 @@ Called with three arguments:
- the error data, a list of the form (SIGNALED-CONDITION . SIGNAL-DATA)
such as what `condition-case' would bind its variable to,
- the context (a string which normally goes at the start of the message),
-- the Lisp function within which the error was signaled. */);
+- the Lisp function within which the error was signaled.
+
+Also see `set-message-function' (which controls how non-error messages
+are displayed). */);
Vcommand_error_function = intern ("command-error-default-function");
DEFVAR_LISP ("enable-disabled-menus-and-buttons",
@@ -12339,13 +12446,6 @@ If nil, Emacs crashes immediately in response to fatal signals. */);
Vwhile_no_input_ignore_events,
doc: /* Ignored events from while-no-input. */);
- DEFVAR_BOOL ("inhibit--record-char",
- inhibit_record_char,
- doc: /* If non-nil, don't record input events.
-This inhibits recording input events for the purposes of keyboard
-macros, dribble file, and `recent-keys'.
-Internal use only. */);
-
pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
}
@@ -12379,10 +12479,6 @@ syms_of_keyboard_for_pdumper (void)
/* Create the initial keyboard. Qt means 'unset'. */
eassert (initial_kboard == NULL);
initial_kboard = allocate_kboard (Qt);
-
- Vwhile_no_input_ignore_events = Qnil;
-
- inhibit_record_char = false;
}
void