diff options
Diffstat (limited to 'src/keyboard.c')
-rw-r--r-- | src/keyboard.c | 386 |
1 files changed, 189 insertions, 197 deletions
diff --git a/src/keyboard.c b/src/keyboard.c index e62dd0ec489..9b8d275d0fd 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -43,6 +43,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include "systime.h" #include "atimer.h" #include "process.h" +#include "menu.h" #include <errno.h> #ifdef HAVE_PTHREAD @@ -1365,6 +1366,7 @@ command_loop_1 (void) Vthis_command_keys_shift_translated = Qnil; /* Read next key sequence; i gets its length. */ + raw_keybuf_count = 0; i = read_key_sequence (keybuf, ARRAYELTS (keybuf), Qnil, 0, 1, 1, 0); @@ -1869,6 +1871,7 @@ int poll_suppress_count; static struct atimer *poll_timer; +#if defined CYGWIN || defined DOS_NT /* Poll for input, so that we catch a C-g if it comes in. */ void poll_for_input_1 (void) @@ -1877,6 +1880,7 @@ poll_for_input_1 (void) && !waiting_for_input) gobble_input (); } +#endif /* Timer callback function for poll_timer. TIMER is equal to poll_timer. */ @@ -1928,20 +1932,22 @@ start_polling (void) #endif } +#if defined CYGWIN || defined DOS_NT /* True if we are using polling to handle input asynchronously. */ bool input_polling_used (void) { -#ifdef POLL_FOR_INPUT +# ifdef POLL_FOR_INPUT /* XXX This condition was (read_socket_hook && !interrupt_input), but read_socket_hook is not global anymore. Let's pretend that it's always set. */ return !interrupt_input; -#else - return 0; -#endif +# else + return false; +# endif } +#endif /* Turn off polling. */ @@ -2809,6 +2815,9 @@ read_char (int commandflag, Lisp_Object map, if (EQ (c, make_number (-2))) return c; + + if (CONSP (c) && EQ (XCAR (c), Qt)) + c = XCDR (c); } non_reread: @@ -3727,7 +3736,7 @@ kbd_buffer_events_waiting (void) /* Clear input event EVENT. */ static void -clear_event (union buffered_input_event *event) +clear_event (struct input_event *event) { event->kind = NO_EVENT; } @@ -3864,8 +3873,10 @@ kbd_buffer_get_event (KBOARD **kbp, /* These two kinds of events get special handling and don't actually appear to the command loop. We return nil for them. */ - if (event->kind == SELECTION_REQUEST_EVENT - || event->kind == SELECTION_CLEAR_EVENT) + switch (event->kind) + { + case SELECTION_REQUEST_EVENT: + case SELECTION_CLEAR_EVENT: { #ifdef HAVE_X11 /* Remove it from the buffer before processing it, @@ -3881,202 +3892,58 @@ kbd_buffer_get_event (KBOARD **kbp, emacs_abort (); #endif } + break; -#if defined (HAVE_NS) - else if (event->kind == NS_TEXT_EVENT) - { - if (event->ie.code == KEY_NS_PUT_WORKING_TEXT) - obj = list1 (intern ("ns-put-working-text")); - else - obj = list1 (intern ("ns-unput-working-text")); - kbd_fetch_ptr = event + 1; - if (used_mouse_menu) - *used_mouse_menu = true; - } -#endif - -#if defined (HAVE_X11) || defined (HAVE_NTGUI) \ - || defined (HAVE_NS) - else if (event->kind == DELETE_WINDOW_EVENT) - { - /* Make an event (delete-frame (FRAME)). */ - obj = list2 (Qdelete_frame, list1 (event->ie.frame_or_window)); - kbd_fetch_ptr = event + 1; - } -#endif - -#ifdef HAVE_NTGUI - else if (event->kind == END_SESSION_EVENT) - { - /* Make an event (end-session). */ - obj = list1 (Qend_session); - kbd_fetch_ptr = event + 1; - } -#endif - -#if defined (HAVE_X11) || defined (HAVE_NTGUI) \ - || defined (HAVE_NS) - else if (event->kind == ICONIFY_EVENT) - { - /* Make an event (iconify-frame (FRAME)). */ - obj = list2 (Qiconify_frame, list1 (event->ie.frame_or_window)); - kbd_fetch_ptr = event + 1; - } - else if (event->kind == DEICONIFY_EVENT) - { - /* Make an event (make-frame-visible (FRAME)). */ - obj = list2 (Qmake_frame_visible, list1 (event->ie.frame_or_window)); - kbd_fetch_ptr = event + 1; - } -#endif - else if (event->kind == BUFFER_SWITCH_EVENT) - { - /* The value doesn't matter here; only the type is tested. */ - XSETBUFFER (obj, current_buffer); - kbd_fetch_ptr = event + 1; - } #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ || defined (HAVE_NS) || defined (USE_GTK) - else if (event->kind == MENU_BAR_ACTIVATE_EVENT) + case MENU_BAR_ACTIVATE_EVENT: { kbd_fetch_ptr = event + 1; input_pending = readable_events (0); if (FRAME_LIVE_P (XFRAME (event->ie.frame_or_window))) x_activate_menubar (XFRAME (event->ie.frame_or_window)); } + break; +#endif +#if defined (HAVE_NS) + case NS_TEXT_EVENT: + if (used_mouse_menu) + *used_mouse_menu = true; + FALLTHROUGH; #endif #ifdef HAVE_NTGUI - else if (event->kind == LANGUAGE_CHANGE_EVENT) - { - /* Make an event (language-change FRAME CODEPAGE LANGUAGE-ID). */ - obj = list4 (Qlanguage_change, - event->ie.frame_or_window, - make_number (event->ie.code), - make_number (event->ie.modifiers)); - kbd_fetch_ptr = event + 1; - } + case END_SESSION_EVENT: + case LANGUAGE_CHANGE_EVENT: #endif -#ifdef USE_FILE_NOTIFY - else if (event->kind == FILE_NOTIFY_EVENT) - { -#ifdef HAVE_W32NOTIFY - /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */ - obj = list3 (Qfile_notify, event->ie.arg, event->ie.frame_or_window); -#else - obj = make_lispy_event (&event->ie); +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (HAVE_NS) + case DELETE_WINDOW_EVENT: + case ICONIFY_EVENT: + case DEICONIFY_EVENT: + case MOVE_FRAME_EVENT: #endif - kbd_fetch_ptr = event + 1; - } -#endif /* USE_FILE_NOTIFY */ - else if (event->kind == SAVE_SESSION_EVENT) - { - obj = list2 (Qsave_session, event->ie.arg); - kbd_fetch_ptr = event + 1; - } - /* Just discard these, by returning nil. - With MULTI_KBOARD, these events are used as placeholders - when we need to randomly delete events from the queue. - (They shouldn't otherwise be found in the buffer, - but on some machines it appears they do show up - even without MULTI_KBOARD.) */ - /* On Windows NT/9X, NO_EVENT is used to delete extraneous - mouse events during a popup-menu call. */ - else if (event->kind == NO_EVENT) - kbd_fetch_ptr = event + 1; - else if (event->kind == HELP_EVENT) - { - Lisp_Object object, position, help, frame, window; - - frame = event->ie.frame_or_window; - object = event->ie.arg; - position = make_number (Time_to_position (event->ie.timestamp)); - window = event->ie.x; - help = event->ie.y; - clear_event (event); - - kbd_fetch_ptr = event + 1; - if (!WINDOWP (window)) - window = Qnil; - obj = Fcons (Qhelp_echo, - list5 (frame, help, window, object, position)); - } - else if (event->kind == FOCUS_IN_EVENT) - { - /* Notification of a FocusIn event. The frame receiving the - focus is in event->frame_or_window. Generate a - switch-frame event if necessary. */ - Lisp_Object frame, focus; - - frame = event->ie.frame_or_window; - focus = FRAME_FOCUS_FRAME (XFRAME (frame)); - if (FRAMEP (focus)) - frame = focus; - - if ( -#ifdef HAVE_X11 - ! NILP (event->ie.arg) - && +#ifdef USE_FILE_NOTIFY + case FILE_NOTIFY_EVENT: #endif - !EQ (frame, internal_last_event_frame) - && !EQ (frame, selected_frame)) - obj = make_lispy_switch_frame (frame); - else - obj = make_lispy_focus_in (frame); - - internal_last_event_frame = frame; - kbd_fetch_ptr = event + 1; - } - else if (event->kind == FOCUS_OUT_EVENT) - { -#ifdef HAVE_WINDOW_SYSTEM - - Display_Info *di; - Lisp_Object frame = event->ie.frame_or_window; - bool focused = false; - - for (di = x_display_list; di && ! focused; di = di->next) - focused = di->x_highlight_frame != 0; - - if (!focused) - obj = make_lispy_focus_out (frame); - -#endif /* HAVE_WINDOW_SYSTEM */ - - kbd_fetch_ptr = event + 1; - } #ifdef HAVE_DBUS - else if (event->kind == DBUS_EVENT) - { - obj = make_lispy_event (&event->ie); - kbd_fetch_ptr = event + 1; - } -#endif -#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (HAVE_NS) - else if (event->kind == MOVE_FRAME_EVENT) - { - /* Make an event (move-frame (FRAME)). */ - obj = list2 (Qmove_frame, list1 (event->ie.frame_or_window)); - kbd_fetch_ptr = event + 1; - } + case DBUS_EVENT: #endif #ifdef HAVE_XWIDGETS - else if (event->kind == XWIDGET_EVENT) - { - obj = make_lispy_event (&event->ie); - kbd_fetch_ptr = event + 1; - } + case XWIDGET_EVENT: #endif - else if (event->kind == CONFIG_CHANGED_EVENT) - { - obj = make_lispy_event (&event->ie); - kbd_fetch_ptr = event + 1; - } - else if (event->kind == SELECT_WINDOW_EVENT) - { - obj = list2 (Qselect_window, list1 (event->ie.frame_or_window)); - kbd_fetch_ptr = event + 1; - } - else + case BUFFER_SWITCH_EVENT: + case SAVE_SESSION_EVENT: + case NO_EVENT: + case HELP_EVENT: + case FOCUS_IN_EVENT: + case CONFIG_CHANGED_EVENT: + case FOCUS_OUT_EVENT: + case SELECT_WINDOW_EVENT: + { + obj = make_lispy_event (&event->ie); + kbd_fetch_ptr = event + 1; + } + break; + default: { /* If this event is on a different frame, return a switch-frame this time, and leave the event in the queue for next time. */ @@ -4126,10 +3993,11 @@ kbd_buffer_get_event (KBOARD **kbp, #endif /* Wipe out this event, to catch bugs. */ - clear_event (event); + clear_event (&event->ie); kbd_fetch_ptr = event + 1; } } + } } /* Try generating a mouse motion event. */ else if (!NILP (do_mouse_tracking) && some_mouse_moved ()) @@ -5439,7 +5307,101 @@ make_lispy_event (struct input_event *event) switch (event->kind) { - /* A simple keystroke. */ +#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (HAVE_NS) + case DELETE_WINDOW_EVENT: + /* Make an event (delete-frame (FRAME)). */ + return list2 (Qdelete_frame, list1 (event->frame_or_window)); + + case ICONIFY_EVENT: + /* Make an event (iconify-frame (FRAME)). */ + return list2 (Qiconify_frame, list1 (event->frame_or_window)); + + case DEICONIFY_EVENT: + /* Make an event (make-frame-visible (FRAME)). */ + return list2 (Qmake_frame_visible, list1 (event->frame_or_window)); + + case MOVE_FRAME_EVENT: + /* Make an event (move-frame (FRAME)). */ + return list2 (Qmove_frame, list1 (event->frame_or_window)); +#endif + + case BUFFER_SWITCH_EVENT: + { + /* The value doesn't matter here; only the type is tested. */ + Lisp_Object obj; + XSETBUFFER (obj, current_buffer); + return obj; + } + + /* Just discard these, by returning nil. + With MULTI_KBOARD, these events are used as placeholders + when we need to randomly delete events from the queue. + (They shouldn't otherwise be found in the buffer, + but on some machines it appears they do show up + even without MULTI_KBOARD.) */ + /* On Windows NT/9X, NO_EVENT is used to delete extraneous + mouse events during a popup-menu call. */ + case NO_EVENT: + return Qnil; + + case HELP_EVENT: + { + Lisp_Object frame = event->frame_or_window; + Lisp_Object object = event->arg; + Lisp_Object position + = make_number (Time_to_position (event->timestamp)); + Lisp_Object window = event->x; + Lisp_Object help = event->y; + clear_event (event); + + if (!WINDOWP (window)) + window = Qnil; + return Fcons (Qhelp_echo, + list5 (frame, help, window, object, position)); + } + + case FOCUS_IN_EVENT: + { + /* Notification of a FocusIn event. The frame receiving the + focus is in event->frame_or_window. Generate a + switch-frame event if necessary. */ + + Lisp_Object frame = event->frame_or_window; + Lisp_Object focus = FRAME_FOCUS_FRAME (XFRAME (frame)); + if (FRAMEP (focus)) + frame = focus; + bool switching + = ( +#ifdef HAVE_X11 + ! NILP (event->arg) + && +#endif + !EQ (frame, internal_last_event_frame) + && !EQ (frame, selected_frame)); + internal_last_event_frame = frame; + + return (switching ? make_lispy_switch_frame (frame) + : make_lispy_focus_in (frame)); + } + + case FOCUS_OUT_EVENT: + { +#ifdef HAVE_WINDOW_SYSTEM + + Display_Info *di; + Lisp_Object frame = event->frame_or_window; + bool focused = false; + + for (di = x_display_list; di && ! focused; di = di->next) + focused = di->x_highlight_frame != 0; + + return focused ? Qnil + : make_lispy_focus_out (frame); + +#endif /* HAVE_WINDOW_SYSTEM */ + } + + /* A simple keystroke. */ case ASCII_KEYSTROKE_EVENT: case MULTIBYTE_CHAR_KEYSTROKE_EVENT: { @@ -5503,6 +5465,11 @@ make_lispy_event (struct input_event *event) } #ifdef HAVE_NS + case NS_TEXT_EVENT: + return list1 (intern (event->code == KEY_NS_PUT_WORKING_TEXT + ? "ns-put-working-text" + : "ns-unput-working-text")); + /* NS_NONKEY_EVENTs are just like NON_ASCII_KEYSTROKE_EVENTs, except that they are non-key events (last-nonmenu-event is nil). */ case NS_NONKEY_EVENT: @@ -5565,6 +5532,17 @@ make_lispy_event (struct input_event *event) PTRDIFF_MAX); #ifdef HAVE_NTGUI + case END_SESSION_EVENT: + /* Make an event (end-session). */ + return list1 (Qend_session); + + case LANGUAGE_CHANGE_EVENT: + /* Make an event (language-change FRAME CODEPAGE LANGUAGE-ID). */ + return list4 (Qlanguage_change, + event->frame_or_window, + make_number (event->code), + make_number (event->modifiers)); + case MULTIMEDIA_KEY_EVENT: if (event->code < ARRAYELTS (lispy_multimedia_keys) && event->code > 0 && lispy_multimedia_keys[event->code]) @@ -6058,7 +6036,7 @@ make_lispy_event (struct input_event *event) } case SAVE_SESSION_EVENT: - return Qsave_session; + return list2 (Qsave_session, event->arg); #ifdef HAVE_DBUS case DBUS_EVENT: @@ -6074,12 +6052,15 @@ make_lispy_event (struct input_event *event) } #endif -#if defined HAVE_INOTIFY || defined HAVE_KQUEUE || defined HAVE_GFILENOTIFY +#ifdef USE_FILE_NOTIFY case FILE_NOTIFY_EVENT: - { - return Fcons (Qfile_notify, event->arg); - } -#endif /* HAVE_INOTIFY || HAVE_KQUEUE || HAVE_GFILENOTIFY */ +#ifdef HAVE_W32NOTIFY + /* Make an event (file-notify (DESCRIPTOR ACTION FILE) CALLBACK). */ + return list3 (Qfile_notify, event->arg, event->frame_or_window); +#else + return Fcons (Qfile_notify, event->arg); +#endif +#endif /* USE_FILE_NOTIFY */ case CONFIG_CHANGED_EVENT: return list3 (Qconfig_changed_event, @@ -8450,7 +8431,7 @@ read_char_x_menu_prompt (Lisp_Object map, /* Display the menu and get the selection. */ Lisp_Object value; - value = Fx_popup_menu (prev_event, get_keymap (map, 0, 1)); + value = x_popup_menu_1 (prev_event, get_keymap (map, 0, 1)); if (CONSP (value)) { Lisp_Object tem; @@ -8860,6 +8841,11 @@ test_undefined (Lisp_Object binding) && EQ (Fcommand_remapping (binding, Qnil, Qnil), Qundefined))); } +void init_raw_keybuf_count (void) +{ + raw_keybuf_count = 0; +} + /* Read a sequence of keys that ends with a non prefix character, storing it in KEYBUF, a buffer of size BUFSIZE. Prompt with PROMPT. @@ -8916,7 +8902,6 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, ptrdiff_t keys_start; Lisp_Object current_binding = Qnil; - Lisp_Object first_event = Qnil; /* Index of the first key that has no binding. It is useless to try fkey.start larger than that. */ @@ -8971,7 +8956,11 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, /* List of events for which a fake prefix key has been generated. */ Lisp_Object fake_prefixed_keys = Qnil; - raw_keybuf_count = 0; + /* raw_keybuf_count is now initialized in (most of) the callers of + read_key_sequence. This is so that in a recursive call (for + mouse menus) a spurious initialization doesn't erase the contents + of raw_keybuf created by the outer call. */ + /* raw_keybuf_count = 0; */ last_nonmenu_event = Qnil; @@ -9026,6 +9015,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, starting_buffer = current_buffer; first_unbound = bufsize + 1; + Lisp_Object first_event = mock_input > 0 ? keybuf[0] : Qnil; /* Build our list of keymaps. If we recognize a function key and replace its escape sequence in @@ -9343,6 +9333,7 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, Lisp_Object prompt, && BUFFERP (XWINDOW (window)->contents) && XBUFFER (XWINDOW (window)->contents) != current_buffer) { + GROW_RAW_KEYBUF; ASET (raw_keybuf, raw_keybuf_count, key); raw_keybuf_count++; keybuf[t] = key; @@ -9837,6 +9828,7 @@ read_key_sequence_vs (Lisp_Object prompt, Lisp_Object continue_echo, cancel_hourglass (); #endif + raw_keybuf_count = 0; i = read_key_sequence (keybuf, ARRAYELTS (keybuf), prompt, ! NILP (dont_downcase_last), ! NILP (can_return_switch_frame), 0, 0); @@ -10294,7 +10286,7 @@ stuff_buffered_input (Lisp_Object stuffstring) if (kbd_fetch_ptr->kind == ASCII_KEYSTROKE_EVENT) stuff_char (kbd_fetch_ptr->ie.code); - clear_event (kbd_fetch_ptr); + clear_event (&kbd_fetch_ptr->ie); } input_pending = false; |