summaryrefslogtreecommitdiff
path: root/src/keyboard.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/keyboard.c')
-rw-r--r--src/keyboard.c567
1 files changed, 448 insertions, 119 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 9865bc9add3..218f9a86c86 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -65,6 +65,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
+#include <math.h>
#include <ignore-value.h>
@@ -375,6 +376,7 @@ static void timer_resume_idle (void);
static void deliver_user_signal (int);
static char *find_user_signal_name (int);
static void store_user_signal_events (void);
+static bool is_ignored_event (union buffered_input_event *);
/* Advance or retreat a buffered input event pointer. */
@@ -680,13 +682,15 @@ add_command_key (Lisp_Object key)
Lisp_Object
recursive_edit_1 (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
if (command_loop_level > 0)
{
specbind (Qstandard_output, Qt);
specbind (Qstandard_input, Qt);
+ specbind (Qsymbols_with_pos_enabled, Qnil);
+ specbind (Qprint_symbols_bare, Qnil);
}
#ifdef HAVE_WINDOW_SYSTEM
@@ -772,7 +776,7 @@ throwing to \\='exit:
This function is called by the editor initialization to begin editing. */)
(void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object buffer;
/* If we enter while input is blocked, don't lock up here.
@@ -935,7 +939,7 @@ static Lisp_Object
cmd_error (Lisp_Object data)
{
Lisp_Object old_level, old_length;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object conditions;
char macroerror[sizeof "After..kbd macro iterations: "
+ INT_STRLEN_BOUND (EMACS_INT)];
@@ -1228,7 +1232,7 @@ DEFUN ("internal--track-mouse", Finternal_track_mouse, Sinternal_track_mouse,
doc: /* Call BODYFUN with mouse movement events enabled. */)
(Lisp_Object bodyfun)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
record_unwind_protect (tracking_off, track_mouse);
@@ -1351,7 +1355,7 @@ command_loop_1 (void)
{
/* Bind inhibit-quit to t so that C-g gets read in
rather than quitting back to the minibuffer. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
sit_for (Vminibuffer_message_timeout, 0, 2);
@@ -1483,7 +1487,7 @@ command_loop_1 (void)
/* Here for a command that isn't executed directly. */
#ifdef HAVE_WINDOW_SYSTEM
- ptrdiff_t scount = SPECPDL_INDEX ();
+ specpdl_ref scount = SPECPDL_INDEX ();
if (display_hourglass_p
&& NILP (Vexecuting_kbd_macro))
@@ -1599,23 +1603,33 @@ command_loop_1 (void)
if (current_buffer == prev_buffer
&& XBUFFER (XWINDOW (selected_window)->contents) == current_buffer
- && last_point_position != PT
- && NILP (Vdisable_point_adjustment)
- && NILP (Vglobal_disable_point_adjustment))
+ && last_point_position != PT)
{
- if (last_point_position > BEGV
- && last_point_position < ZV
- && (composition_adjust_point (last_point_position,
- last_point_position)
- != last_point_position))
- /* The last point was temporarily set within a grapheme
- cluster to prevent automatic composition. To recover
- the automatic composition, we must update the
- display. */
- windows_or_buffers_changed = 21;
- if (!already_adjusted)
- adjust_point_for_property (last_point_position,
- MODIFF != prev_modiff);
+ if (NILP (Vdisable_point_adjustment)
+ && NILP (Vglobal_disable_point_adjustment)
+ && !composition_break_at_point)
+ {
+ if (last_point_position > BEGV
+ && last_point_position < ZV
+ && (composition_adjust_point (last_point_position,
+ last_point_position)
+ != last_point_position))
+ /* The last point was temporarily set within a grapheme
+ cluster to prevent automatic composition. To recover
+ the automatic composition, we must update the
+ display. */
+ windows_or_buffers_changed = 21;
+ if (!already_adjusted)
+ adjust_point_for_property (last_point_position,
+ MODIFF != prev_modiff);
+ }
+ else if (PT > BEGV && PT < ZV
+ && (composition_adjust_point (last_point_position, PT)
+ != PT))
+ /* Now point is within a grapheme cluster. We must update
+ the display so that this cluster is de-composed on the
+ screen and the cursor is correctly placed at point. */
+ windows_or_buffers_changed = 39;
}
/* Install chars successfully executed in kbd macro. */
@@ -1629,7 +1643,7 @@ command_loop_1 (void)
Lisp_Object
read_menu_command (void)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* We don't want to echo the keystrokes while navigating the
menus. */
@@ -1874,7 +1888,7 @@ safe_run_hook_funcall (ptrdiff_t nargs, Lisp_Object *args)
void
safe_run_hooks (Lisp_Object hook)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
run_hook_with_args (2, ((Lisp_Object []) {hook, hook}), safe_run_hook_funcall);
@@ -1893,6 +1907,9 @@ int poll_suppress_count;
static struct atimer *poll_timer;
+/* The poll period that constructed this timer. */
+static Lisp_Object poll_timer_time;
+
#if defined CYGWIN || defined DOS_NT
/* Poll for input, so that we catch a C-g if it comes in. */
void
@@ -1934,17 +1951,18 @@ start_polling (void)
/* If poll timer doesn't exist, or we need one with
a different interval, start a new one. */
- if (poll_timer == NULL
- || poll_timer->interval.tv_sec != polling_period)
+ if (NUMBERP (Vpolling_period)
+ && (poll_timer == NULL
+ || NILP (Fequal (Vpolling_period, poll_timer_time))))
{
- time_t period = max (1, min (polling_period, TYPE_MAXIMUM (time_t)));
- struct timespec interval = make_timespec (period, 0);
+ struct timespec interval = dtotimespec (XFLOATINT (Vpolling_period));
if (poll_timer)
cancel_atimer (poll_timer);
poll_timer = start_atimer (ATIMER_CONTINUOUS, interval,
poll_for_input, NULL);
+ poll_timer_time = Vpolling_period;
}
/* Let the timer's callback function poll for input
@@ -2012,14 +2030,28 @@ void
bind_polling_period (int n)
{
#ifdef POLL_FOR_INPUT
- intmax_t new = polling_period;
+ if (FIXNUMP (Vpolling_period))
+ {
+ intmax_t new = XFIXNUM (Vpolling_period);
+
+ if (n > new)
+ new = n;
- if (n > new)
- new = n;
+ stop_other_atimers (poll_timer);
+ stop_polling ();
+ specbind (Qpolling_period, make_int (new));
+ }
+ else if (FLOATP (Vpolling_period))
+ {
+ double new = XFLOAT_DATA (Vpolling_period);
+
+ stop_other_atimers (poll_timer);
+ stop_polling ();
+ specbind (Qpolling_period, (n > new
+ ? make_int (n)
+ : Vpolling_period));
+ }
- stop_other_atimers (poll_timer);
- stop_polling ();
- specbind (Qpolling_period, make_int (new));
/* Start a new alarm with the new period. */
start_polling ();
#endif
@@ -2189,7 +2221,7 @@ read_event_from_main_queue (struct timespec *end_time,
return c;
/* Actually read a character, waiting if necessary. */
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2391,7 +2423,6 @@ read_char (int commandflag, Lisp_Object map,
bool *used_mouse_menu, struct timespec *end_time)
{
Lisp_Object c;
- ptrdiff_t jmpcount;
sys_jmp_buf local_getcjmp;
sys_jmp_buf save_jump;
Lisp_Object tem, save;
@@ -2633,7 +2664,7 @@ read_char (int commandflag, Lisp_Object map,
around any call to sit_for or kbd_buffer_get_event;
it *must not* be in effect when we call redisplay. */
- jmpcount = SPECPDL_INDEX ();
+ specpdl_ref jmpcount = SPECPDL_INDEX ();
if (sys_setjmp (local_getcjmp))
{
/* Handle quits while reading the keyboard. */
@@ -2716,7 +2747,7 @@ read_char (int commandflag, Lisp_Object map,
{
Lisp_Object tem0;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2793,7 +2824,7 @@ read_char (int commandflag, Lisp_Object map,
timeout = min (timeout, MOST_POSITIVE_FIXNUM / delay_level * 4);
timeout = delay_level * timeout / 4;
- ptrdiff_t count1 = SPECPDL_INDEX ();
+ specpdl_ref count1 = SPECPDL_INDEX ();
save_getcjmp (save_jump);
record_unwind_protect_ptr (restore_getcjmp, save_jump);
restore_getcjmp (local_getcjmp);
@@ -2943,20 +2974,8 @@ read_char (int commandflag, Lisp_Object map,
last_input_event = c;
call4 (Qcommand_execute, tem, Qnil, Fvector (1, &last_input_event), Qt);
- if (CONSP (c)
- && (EQ (XCAR (c), Qselect_window)
- || EQ (XCAR (c), Qfocus_out)
-#ifdef HAVE_DBUS
- || EQ (XCAR (c), Qdbus_event)
-#endif
-#ifdef USE_FILE_NOTIFY
- || EQ (XCAR (c), Qfile_notify)
-#endif
-#ifdef THREADS_ENABLED
- || EQ (XCAR (c), Qthread_event)
-#endif
- || EQ (XCAR (c), Qconfig_changed_event))
- && !end_time)
+ if (CONSP (c) && !NILP (Fmemq (XCAR (c), Vwhile_no_input_ignore_events))
+ && !end_time)
/* We stopped being idle for this event; undo that. This
prevents automatic window selection (under
mouse-autoselect-window) from acting as a real input event, for
@@ -3088,7 +3107,7 @@ read_char (int commandflag, Lisp_Object map,
Lisp_Object keys;
ptrdiff_t key_count;
ptrdiff_t command_key_start;
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* Save the echo status. */
bool saved_immediate_echo = current_kboard->immediate_echo;
@@ -3213,7 +3232,7 @@ read_char (int commandflag, Lisp_Object map,
/* Process the help character specially if enabled. */
if (!NILP (Vhelp_form) && help_char_p (c))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
help_form_saved_window_configs
= Fcons (Fcurrent_window_configuration (Qnil),
@@ -3458,8 +3477,13 @@ readable_events (int flags)
if (flags & READABLE_EVENTS_DO_TIMERS_NOW)
timer_check ();
- /* If the buffer contains only FOCUS_IN/OUT_EVENT events, and
- READABLE_EVENTS_FILTER_EVENTS is set, report it as empty. */
+ /* READABLE_EVENTS_FILTER_EVENTS is meant to be used only by
+ input-pending-p and similar callers, which aren't interested in
+ some input events. If this flag is set, and
+ input-pending-p-filter-events is non-nil, ignore events in
+ while-no-input-ignore-events. If the flag is set and
+ input-pending-p-filter-events is nil, ignore only
+ FOCUS_IN/OUT_EVENT events. */
if (kbd_fetch_ptr != kbd_store_ptr)
{
/* See https://lists.gnu.org/r/emacs-devel/2005-05/msg00297.html
@@ -3478,8 +3502,11 @@ readable_events (int flags)
#ifdef USE_TOOLKIT_SCROLL_BARS
(flags & READABLE_EVENTS_FILTER_EVENTS) &&
#endif
- (event->kind == FOCUS_IN_EVENT
- || event->kind == FOCUS_OUT_EVENT))
+ ((!input_pending_p_filter_events
+ && (event->kind == FOCUS_IN_EVENT
+ || event->kind == FOCUS_OUT_EVENT))
+ || (input_pending_p_filter_events
+ && is_ignored_event (event))))
#ifdef USE_TOOLKIT_SCROLL_BARS
&& !((flags & READABLE_EVENTS_IGNORE_SQUEEZABLES)
&& (event->kind == SCROLL_BAR_CLICK_EVENT
@@ -3661,29 +3688,10 @@ kbd_buffer_store_buffered_event (union buffered_input_event *event,
#endif /* subprocesses */
}
- Lisp_Object ignore_event;
-
- switch (event->kind)
- {
- case FOCUS_IN_EVENT: ignore_event = Qfocus_in; break;
- case FOCUS_OUT_EVENT: ignore_event = Qfocus_out; break;
- case HELP_EVENT: ignore_event = Qhelp_echo; break;
- 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;
- }
-
/* If we're inside while-no-input, and this event qualifies
as input, set quit-flag to cause an interrupt. */
if (!NILP (Vthrow_on_input)
- && NILP (Fmemq (ignore_event, Vwhile_no_input_ignore_events)))
+ && !is_ignored_event (event))
Vquit_flag = Vthrow_on_input;
}
@@ -3827,6 +3835,26 @@ clear_event (struct input_event *event)
event->kind = NO_EVENT;
}
+static Lisp_Object
+kbd_buffer_get_event_1 (Lisp_Object arg)
+{
+ Lisp_Object coding_system = Fget_text_property (make_fixnum (0),
+ Qcoding, arg);
+
+ if (EQ (coding_system, Qt))
+ return arg;
+
+ return code_convert_string (arg, (!NILP (coding_system)
+ ? coding_system
+ : Vlocale_coding_system),
+ Qnil, 0, false, 0);
+}
+
+static Lisp_Object
+kbd_buffer_get_event_2 (Lisp_Object val)
+{
+ return Qnil;
+}
/* Read one event from the event buffer, waiting if necessary.
The value is a Lisp object representing the event.
@@ -3839,7 +3867,7 @@ kbd_buffer_get_event (KBOARD **kbp,
bool *used_mouse_menu,
struct timespec *end_time)
{
- Lisp_Object obj;
+ Lisp_Object obj, str;
#ifdef subprocesses
if (kbd_on_hold_p () && kbd_buffer_nr_stored () < KBD_BUFFER_SIZE / 4)
@@ -3865,6 +3893,8 @@ kbd_buffer_get_event (KBOARD **kbp,
}
#endif /* !defined HAVE_DBUS && !defined USE_FILE_NOTIFY && !defined THREADS_ENABLED */
+ *kbp = current_kboard;
+
/* Wait until there is input available. */
for (;;)
{
@@ -3887,7 +3917,7 @@ kbd_buffer_get_event (KBOARD **kbp,
/* One way or another, wait until input is available; then, if
interrupt handlers have not read it, read it now. */
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
gobble_input ();
#endif
if (kbd_fetch_ptr != kbd_store_ptr)
@@ -3994,6 +4024,7 @@ kbd_buffer_get_event (KBOARD **kbp,
*used_mouse_menu = true;
FALLTHROUGH;
#endif
+ case PREEDIT_TEXT_EVENT:
#ifdef HAVE_NTGUI
case END_SESSION_EVENT:
case LANGUAGE_CHANGE_EVENT:
@@ -4015,6 +4046,7 @@ kbd_buffer_get_event (KBOARD **kbp,
#endif
#ifdef HAVE_XWIDGETS
case XWIDGET_EVENT:
+ case XWIDGET_DISPLAY_EVENT:
#endif
case SAVE_SESSION_EVENT:
case NO_EVENT:
@@ -4055,6 +4087,102 @@ kbd_buffer_get_event (KBOARD **kbp,
and build a real event from the queue entry. */
if (NILP (obj))
{
+ double pinch_dx, pinch_dy, pinch_angle;
+
+ /* Pinch events are often sent in rapid succession, so
+ large amounts of such events have the potential to
+ queue up inside the keyboard buffer. In that case,
+ find the last pinch event in succession on the same
+ frame with the same modifiers, and send that instead. */
+
+ if (event->ie.kind == PINCH_EVENT
+ /* Ignore if this is the start of a pinch sequence.
+ These events should always be sent so that we
+ never miss a sequence starting, and they don't
+ have the potential to queue up. */
+ && ((pinch_dx
+ = XFLOAT_DATA (XCAR (event->ie.arg))) != 0.0
+ || XFLOAT_DATA (XCAR (XCDR (event->ie.arg))) != 0.0
+ || XFLOAT_DATA (Fnth (make_fixnum (3), event->ie.arg)) != 0.0))
+ {
+ union buffered_input_event *maybe_event = next_kbd_event (event);
+
+ pinch_dy = XFLOAT_DATA (XCAR (XCDR (event->ie.arg)));
+ pinch_angle = XFLOAT_DATA (Fnth (make_fixnum (3), event->ie.arg));
+
+ while (maybe_event != kbd_store_ptr
+ && maybe_event->ie.kind == PINCH_EVENT
+ /* Make sure we never miss an event that has
+ different modifiers. */
+ && maybe_event->ie.modifiers == event->ie.modifiers
+ /* Make sure that the event is for the same
+ frame. */
+ && EQ (maybe_event->ie.frame_or_window,
+ event->ie.frame_or_window)
+ /* Make sure that the event isn't the start
+ of a new pinch gesture sequence. */
+ && (XFLOAT_DATA (XCAR (maybe_event->ie.arg)) != 0.0
+ || XFLOAT_DATA (XCAR (XCDR (maybe_event->ie.arg))) != 0.0
+ || XFLOAT_DATA (Fnth (make_fixnum (3),
+ maybe_event->ie.arg)) != 0.0))
+ {
+ event = maybe_event;
+ /* Add up relative deltas inside events we skip. */
+ pinch_dx += XFLOAT_DATA (XCAR (maybe_event->ie.arg));
+ pinch_dy += XFLOAT_DATA (XCAR (XCDR (maybe_event->ie.arg)));
+ pinch_angle += XFLOAT_DATA (Fnth (make_fixnum (3),
+ maybe_event->ie.arg));
+
+ XSETCAR (maybe_event->ie.arg, make_float (pinch_dx));
+ XSETCAR (XCDR (maybe_event->ie.arg), make_float (pinch_dy));
+ XSETCAR (Fnthcdr (make_fixnum (3),
+ maybe_event->ie.arg),
+ make_float (fmod (pinch_angle, 360.0)));
+ maybe_event = next_kbd_event (event);
+ }
+ }
+
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ /* This string has to be decoded. */
+ && STRINGP (event->ie.arg))
+ {
+ str = internal_condition_case_1 (kbd_buffer_get_event_1,
+ event->ie.arg, Qt,
+ kbd_buffer_get_event_2);
+
+ /* Decoding the string failed, so use the original,
+ where at least ASCII text will work. */
+ if (NILP (str))
+ str = event->ie.arg;
+
+ if (!SCHARS (str))
+ {
+ kbd_fetch_ptr = next_kbd_event (event);
+ obj = Qnil;
+ break;
+ }
+
+ /* car is the index of the next character in the
+ string that will be sent and cdr is the string
+ itself. */
+ event->ie.arg = Fcons (make_fixnum (0), str);
+ }
+
+ if (event->kind == MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ && CONSP (event->ie.arg))
+ {
+ eassert (FIXNUMP (XCAR (event->ie.arg)));
+ eassert (STRINGP (XCDR (event->ie.arg)));
+ eassert (XFIXNUM (XCAR (event->ie.arg))
+ < SCHARS (XCDR (event->ie.arg)));
+
+ event->ie.code = XFIXNUM (Faref (XCDR (event->ie.arg),
+ XCAR (event->ie.arg)));
+
+ XSETCAR (event->ie.arg,
+ make_fixnum (XFIXNUM (XCAR (event->ie.arg)) + 1));
+ }
+
obj = make_lispy_event (&event->ie);
#ifdef HAVE_EXT_MENU_BAR
@@ -4077,9 +4205,15 @@ kbd_buffer_get_event (KBOARD **kbp,
*used_mouse_menu = true;
#endif
- /* Wipe out this event, to catch bugs. */
- clear_event (&event->ie);
- kbd_fetch_ptr = next_kbd_event (event);
+ if (event->kind != MULTIBYTE_CHAR_KEYSTROKE_EVENT
+ || !CONSP (event->ie.arg)
+ || (XFIXNUM (XCAR (event->ie.arg))
+ >= SCHARS (XCDR (event->ie.arg))))
+ {
+ /* Wipe out this event, to catch bugs. */
+ clear_event (&event->ie);
+ kbd_fetch_ptr = next_kbd_event (event);
+ }
}
}
}
@@ -4383,7 +4517,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
if (NILP (AREF (chosen_timer, 0)))
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark;
/* Mark the timer as triggered to prevent problems if the lisp
@@ -4484,6 +4618,7 @@ static Lisp_Object func_key_syms;
static Lisp_Object mouse_syms;
static Lisp_Object wheel_syms;
static Lisp_Object drag_n_drop_syms;
+static Lisp_Object pinch_syms;
/* This is a list of keysym codes for special "accent" characters.
It parallels lispy_accent_keys. */
@@ -4919,7 +5054,7 @@ static const char *const lispy_kana_keys[] =
/* You'll notice that this table is arranged to be conveniently
indexed by X Windows keysym values. */
-static const char *const lispy_function_keys[] =
+const char *const lispy_function_keys[] =
{
/* X Keysym value */
@@ -5112,6 +5247,8 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
Lisp_Object window_or_frame = f
? window_from_coordinates (f, mx, my, &part, true, true)
: Qnil;
+ bool tool_bar_p = false;
+ bool menu_bar_p = false;
/* Report mouse events on the tab bar and (on GUI frames) on the
tool bar. */
@@ -5145,6 +5282,20 @@ make_lispy_position (struct frame *f, Lisp_Object x, Lisp_Object y,
coordinates. FIXME! */
window_or_frame = Qnil;
}
+
+ if (FRAME_TERMINAL (f)->toolkit_position_hook)
+ {
+ FRAME_TERMINAL (f)->toolkit_position_hook (f, mx, my, &menu_bar_p,
+ &tool_bar_p);
+
+ if (NILP (track_mouse) || EQ (track_mouse, Qt))
+ {
+ if (menu_bar_p)
+ posn = Qmenu_bar;
+ else if (tool_bar_p)
+ posn = Qtool_bar;
+ }
+ }
#endif
if (f
&& !FRAME_WINDOW_P (f)
@@ -6002,7 +6153,11 @@ make_lispy_event (struct input_event *event)
ASIZE (wheel_syms));
}
- if (NUMBERP (event->arg))
+ if (CONSP (event->arg))
+ return list5 (head, position, make_fixnum (double_click_count),
+ XCAR (event->arg), Fcons (XCAR (XCDR (event->arg)),
+ XCAR (XCDR (XCDR (event->arg)))));
+ else if (NUMBERP (event->arg))
return list4 (head, position, make_fixnum (double_click_count),
event->arg);
else if (event->modifiers & (double_modifier | triple_modifier))
@@ -6011,6 +6166,77 @@ make_lispy_event (struct input_event *event)
return list2 (head, position);
}
+ case TOUCH_END_EVENT:
+ {
+ Lisp_Object position;
+
+ /* Build the position as appropriate for this mouse click. */
+ struct frame *f = XFRAME (event->frame_or_window);
+
+ if (! FRAME_LIVE_P (f))
+ return Qnil;
+
+ position = make_lispy_position (f, event->x, event->y,
+ event->timestamp);
+
+ return list2 (Qtouch_end, position);
+ }
+
+ case TOUCHSCREEN_BEGIN_EVENT:
+ case TOUCHSCREEN_END_EVENT:
+ {
+ Lisp_Object x, y, id, position;
+ struct frame *f = XFRAME (event->frame_or_window);
+
+ id = event->arg;
+ x = event->x;
+ y = event->y;
+
+ position = make_lispy_position (f, x, y, event->timestamp);
+
+ return list2 (((event->kind
+ == TOUCHSCREEN_BEGIN_EVENT)
+ ? Qtouchscreen_begin
+ : Qtouchscreen_end),
+ Fcons (id, position));
+ }
+
+ case PINCH_EVENT:
+ {
+ Lisp_Object x, y, position;
+ struct frame *f = XFRAME (event->frame_or_window);
+
+ x = event->x;
+ y = event->y;
+
+ position = make_lispy_position (f, x, y, event->timestamp);
+
+ return Fcons (modify_event_symbol (0, event->modifiers, Qpinch,
+ Qnil, (const char *[]) {"pinch"},
+ &pinch_syms, 1),
+ Fcons (position, event->arg));
+ }
+
+ case TOUCHSCREEN_UPDATE_EVENT:
+ {
+ Lisp_Object x, y, id, position, tem, it, evt;
+ struct frame *f = XFRAME (event->frame_or_window);
+ evt = Qnil;
+
+ for (tem = event->arg; CONSP (tem); tem = XCDR (tem))
+ {
+ it = XCAR (tem);
+
+ x = XCAR (it);
+ y = XCAR (XCDR (it));
+ id = XCAR (XCDR (XCDR (it)));
+
+ position = make_lispy_position (f, x, y, event->timestamp);
+ evt = Fcons (Fcons (id, position), evt);
+ }
+
+ return list2 (Qtouchscreen_update, evt);
+ }
#ifdef USE_TOOLKIT_SCROLL_BARS
@@ -6145,23 +6371,20 @@ make_lispy_event (struct input_event *event)
#ifdef HAVE_DBUS
case DBUS_EVENT:
- {
- return Fcons (Qdbus_event, event->arg);
- }
+ return Fcons (Qdbus_event, event->arg);
#endif /* HAVE_DBUS */
#ifdef THREADS_ENABLED
case THREAD_EVENT:
- {
- return Fcons (Qthread_event, event->arg);
- }
+ return Fcons (Qthread_event, event->arg);
#endif /* THREADS_ENABLED */
#ifdef HAVE_XWIDGETS
case XWIDGET_EVENT:
- {
- return Fcons (Qxwidget_event, event->arg);
- }
+ return Fcons (Qxwidget_event, event->arg);
+
+ case XWIDGET_DISPLAY_EVENT:
+ return Fcons (Qxwidget_display_event, event->arg);
#endif
#ifdef USE_FILE_NOTIFY
@@ -6178,6 +6401,9 @@ make_lispy_event (struct input_event *event)
return list3 (Qconfig_changed_event,
event->arg, event->frame_or_window);
+ case PREEDIT_TEXT_EVENT:
+ return list2 (Qpreedit_text, event->arg);
+
/* The 'kind' field of the event is something we don't recognize. */
default:
emacs_abort ();
@@ -7205,7 +7431,7 @@ tty_read_avail_input (struct terminal *terminal,
static void
handle_async_input (void)
{
-#ifdef USABLE_SIGIO
+#ifndef DOS_NT
while (1)
{
int nread = gobble_input ();
@@ -7268,7 +7494,7 @@ totally_unblock_input (void)
unblock_input_to (0);
}
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
void
handle_input_available_signal (int sig)
@@ -7284,7 +7510,7 @@ deliver_input_available_signal (int sig)
{
deliver_process_signal (sig, handle_input_available_signal);
}
-#endif /* USABLE_SIGIO */
+#endif /* defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) */
/* User signal events. */
@@ -7354,7 +7580,7 @@ handle_user_signal (int sig)
}
p->npending++;
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
if (interrupt_input)
handle_input_available_signal (sig);
else
@@ -7720,7 +7946,7 @@ eval_dyn (Lisp_Object form)
Lisp_Object
menu_item_eval_property (Lisp_Object sexpr)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object val;
specbind (Qinhibit_redisplay, Qt);
val = internal_condition_case_1 (eval_dyn, sexpr, Qerror,
@@ -7857,7 +8083,9 @@ parse_menu_item (Lisp_Object item, int inmenubar)
else if (EQ (tem, QCkeys))
{
tem = XCAR (item);
- if (CONSP (tem) || STRINGP (tem))
+ if (FUNCTIONP (tem))
+ ASET (item_properties, ITEM_PROPERTY_KEYEQ, call0 (tem));
+ else if (CONSP (tem) || STRINGP (tem))
ASET (item_properties, ITEM_PROPERTY_KEYEQ, tem);
}
else if (EQ (tem, QCbutton) && CONSP (XCAR (item)))
@@ -9385,7 +9613,7 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
bool dont_downcase_last, bool can_return_switch_frame,
bool fix_current_buffer, bool prevent_redisplay)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
/* How many keys there are in the current key sequence. */
int t;
@@ -10185,7 +10413,8 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
use the corresponding lower-case letter instead. */
if (NILP (current_binding)
&& /* indec.start >= t && fkey.start >= t && */ keytran.start >= t
- && FIXNUMP (key))
+ && FIXNUMP (key)
+ && translate_upper_case_key_bindings)
{
Lisp_Object new_key;
EMACS_INT k = XFIXNUM (key);
@@ -10237,12 +10466,14 @@ read_key_sequence (Lisp_Object *keybuf, Lisp_Object prompt,
int modifiers
= CONSP (breakdown) ? (XFIXNUM (XCAR (XCDR (breakdown)))) : 0;
- if (modifiers & shift_modifier
- /* Treat uppercase keys as shifted. */
- || (FIXNUMP (key)
- && (KEY_TO_CHAR (key)
- < XCHAR_TABLE (BVAR (current_buffer, downcase_table))->header.size)
- && uppercasep (KEY_TO_CHAR (key))))
+ if (translate_upper_case_key_bindings
+ && (modifiers & shift_modifier
+ /* Treat uppercase keys as shifted. */
+ || (FIXNUMP (key)
+ && (KEY_TO_CHAR (key)
+ < XCHAR_TABLE (BVAR (current_buffer,
+ downcase_table))->header.size)
+ && uppercasep (KEY_TO_CHAR (key)))))
{
Lisp_Object new_key
= (modifiers & shift_modifier
@@ -10318,7 +10549,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo,
Lisp_Object can_return_switch_frame,
Lisp_Object cmd_loop, bool allow_string)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
if (!NILP (prompt))
CHECK_STRING (prompt);
@@ -10786,7 +11017,7 @@ Some operating systems cannot stop the Emacs process and resume it later.
On such systems, Emacs starts a subshell instead of suspending. */)
(Lisp_Object stuffstring)
{
- ptrdiff_t count = SPECPDL_INDEX ();
+ specpdl_ref count = SPECPDL_INDEX ();
int old_height, old_width;
int width, height;
@@ -11119,7 +11350,7 @@ See also `current-input-mode'. */)
(Lisp_Object interrupt)
{
bool new_interrupt_input;
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
#ifdef HAVE_X_WINDOWS
if (x_display_list != NULL)
{
@@ -11130,9 +11361,9 @@ See also `current-input-mode'. */)
else
#endif /* HAVE_X_WINDOWS */
new_interrupt_input = !NILP (interrupt);
-#else /* not USABLE_SIGIO */
+#else /* not USABLE_SIGIO || USABLE_SIGPOLL */
new_interrupt_input = false;
-#endif /* not USABLE_SIGIO */
+#endif /* not USABLE_SIGIO || USABLE_SIGPOLL */
if (new_interrupt_input != interrupt_input)
{
@@ -11561,12 +11792,16 @@ init_keyboard (void)
sigaction (SIGQUIT, &action, 0);
#endif /* not DOS_NT */
}
-#ifdef USABLE_SIGIO
+#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
if (!noninteractive)
{
struct sigaction action;
emacs_sigaction_init (&action, deliver_input_available_signal);
+#ifdef USABLE_SIGIO
sigaction (SIGIO, &action, 0);
+#else
+ sigaction (SIGPOLL, &action, 0);
+#endif
}
#endif
@@ -11618,6 +11853,52 @@ static const struct event_head head_table[] = {
{SYMBOL_INDEX (Qselect_window), SYMBOL_INDEX (Qswitch_frame)}
};
+static Lisp_Object
+init_while_no_input_ignore_events (void)
+{
+ Lisp_Object events = listn (9, Qselect_window, Qhelp_echo, Qmove_frame,
+ Qiconify_frame, Qmake_frame_visible,
+ Qfocus_in, Qfocus_out, Qconfig_changed_event,
+ Qselection_request);
+
+#ifdef HAVE_DBUS
+ events = Fcons (Qdbus_event, events);
+#endif
+#ifdef USE_FILE_NOTIFY
+ events = Fcons (Qfile_notify, events);
+#endif
+#ifdef THREADS_ENABLED
+ events = Fcons (Qthread_event, events);
+#endif
+
+ return events;
+}
+
+static bool
+is_ignored_event (union buffered_input_event *event)
+{
+ Lisp_Object ignore_event;
+
+ switch (event->kind)
+ {
+ case FOCUS_IN_EVENT: ignore_event = Qfocus_in; break;
+ case FOCUS_OUT_EVENT: ignore_event = Qfocus_out; break;
+ case HELP_EVENT: ignore_event = Qhelp_echo; break;
+ 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;
+ }
+
+ return !NILP (Fmemq (ignore_event, Vwhile_no_input_ignore_events));
+}
+
static void syms_of_keyboard_for_pdumper (void);
void
@@ -11704,12 +11985,15 @@ syms_of_keyboard (void)
#ifdef HAVE_XWIDGETS
DEFSYM (Qxwidget_event, "xwidget-event");
+ DEFSYM (Qxwidget_display_event, "xwidget-display-event");
#endif
#ifdef USE_FILE_NOTIFY
DEFSYM (Qfile_notify, "file-notify");
#endif /* USE_FILE_NOTIFY */
+ DEFSYM (Qtouch_end, "touch-end");
+
/* Menu and tool bar item parts. */
DEFSYM (QCenable, ":enable");
DEFSYM (QCvisible, ":visible");
@@ -11829,6 +12113,8 @@ syms_of_keyboard (void)
DEFSYM (Qno_record, "no-record");
DEFSYM (Qencoded, "encoded");
+ DEFSYM (Qpreedit_text, "preedit-text");
+
button_down_location = make_nil_vector (5);
staticpro (&button_down_location);
staticpro (&frame_relative_event_pos);
@@ -11869,6 +12155,9 @@ syms_of_keyboard (void)
drag_n_drop_syms = Qnil;
staticpro (&drag_n_drop_syms);
+ pinch_syms = Qnil;
+ staticpro (&pinch_syms);
+
unread_switch_frame = Qnil;
staticpro (&unread_switch_frame);
@@ -11889,6 +12178,11 @@ syms_of_keyboard (void)
help_form_saved_window_configs = Qnil;
staticpro (&help_form_saved_window_configs);
+#ifdef POLL_FOR_INPUT
+ poll_timer_time = Qnil;
+ staticpro (&poll_timer_time);
+#endif
+
defsubr (&Scurrent_idle_time);
defsubr (&Sevent_symbol_parse_modifiers);
defsubr (&Sevent_convert_list);
@@ -12046,12 +12340,12 @@ The value may be integer or floating point.
If the value is zero, don't echo at all. */);
Vecho_keystrokes = make_fixnum (1);
- DEFVAR_INT ("polling-period", polling_period,
+ DEFVAR_LISP ("polling-period", Vpolling_period,
doc: /* Interval between polling for input during Lisp execution.
The reason for polling is to make C-g work to stop a running program.
Polling is needed only when using X windows and SIGIO does not work.
Polling is automatically disabled in all other cases. */);
- polling_period = 2;
+ Vpolling_period = make_float (2.0);
DEFVAR_LISP ("double-click-time", Vdouble_click_time,
doc: /* Maximum time between mouse clicks to make a double-click.
@@ -12205,6 +12499,13 @@ See also `pre-command-hook'. */);
doc: /* Normal hook run when clearing the echo area. */);
#endif
DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook");
+ DEFSYM (Qtouchscreen_begin, "touchscreen-begin");
+ DEFSYM (Qtouchscreen_end, "touchscreen-end");
+ DEFSYM (Qtouchscreen_update, "touchscreen-update");
+ DEFSYM (Qpinch, "pinch");
+
+ DEFSYM (Qcoding, "coding");
+
Fset (Qecho_area_clear_hook, Qnil);
DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,
@@ -12512,7 +12813,35 @@ If nil, Emacs crashes immediately in response to fatal signals. */);
DEFVAR_LISP ("while-no-input-ignore-events",
Vwhile_no_input_ignore_events,
- doc: /* Ignored events from while-no-input. */);
+ doc: /* Ignored events from `while-no-input'.
+Events in this list do not count as pending input while running
+`while-no-input' and do not cause any idle timers to get reset when they
+occur. */);
+ Vwhile_no_input_ignore_events = init_while_no_input_ignore_events ();
+
+ DEFVAR_BOOL ("translate-upper-case-key-bindings",
+ translate_upper_case_key_bindings,
+ doc: /* If non-nil, interpret upper case keys as lower case (when applicable).
+Emacs allows binding both upper and lower case key sequences to
+commands. However, if there is a lower case key sequence bound to a
+command, and the user enters an upper case key sequence that is not
+bound to a command, Emacs will use the lower case binding. Setting
+this variable to nil inhibits this behaviour. */);
+ translate_upper_case_key_bindings = true;
+
+ DEFVAR_BOOL ("input-pending-p-filter-events",
+ input_pending_p_filter_events,
+ doc: /* If non-nil, `input-pending-p' ignores some input events.
+If this variable is non-nil (the default), `input-pending-p' and
+other similar functions ignore input events in `while-no-input-ignore-events'.
+This flag may eventually be removed once this behavior is deemed safe. */);
+ input_pending_p_filter_events = true;
+
+ DEFVAR_BOOL ("mwheel-coalesce-scroll-events", mwheel_coalesce_scroll_events,
+ doc: /* Non-nil means send a wheel event only for scrolling at least one screen line.
+Otherwise, a wheel event will be sent every time the mouse wheel is
+moved. */);
+ mwheel_coalesce_scroll_events = true;
pdumper_do_now_and_after_load (syms_of_keyboard_for_pdumper);
}