aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-08-25 10:47:12 +0800
committerPo Lu2023-08-25 10:47:12 +0800
commitd913b3d82d8efcd3b561a768daf8231b19daf376 (patch)
tree6a5551876e531655abc0e841aaef095d0cc377fa /src
parent2835b9a1d43813f205f87c2850c2049fe7fb7ab9 (diff)
downloademacs-d913b3d82d8efcd3b561a768daf8231b19daf376.tar.gz
emacs-d913b3d82d8efcd3b561a768daf8231b19daf376.zip
Attempt to fix bug#65068
* src/xterm.c (handle_one_xevent) <KeyPress>: Prevent calls to XkbTranslateKeysym with a modified keysym if overflow happens. <XI_KeyPress>: Expound upon the different forms of key event lookup and the chaotic code beneath within the commentary. Discontinue separating keycode lookup from key translation. Supply the effective group within the modifier mask provided to both XKB translation functions. (bug#65068)
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c247
1 files changed, 186 insertions, 61 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 6a1642ff56e..01b9e3f1c1f 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20198,15 +20198,24 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20198#ifdef HAVE_XKB 20198#ifdef HAVE_XKB
20199 int overflow; 20199 int overflow;
20200 unsigned int consumed; 20200 unsigned int consumed;
20201 KeySym sym;
20201 20202
20202 if (dpyinfo->xkb_desc) 20203 if (dpyinfo->xkb_desc)
20203 { 20204 {
20205 /* Translate the keycode into the keysym it
20206 represents, using STATE. CONSUMED is set to the
20207 modifier bits consumed while undertaking this
20208 translation and should be subsequently ignored
20209 during keysym translation. */
20210
20204 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, 20211 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
20205 xkey.keycode, xkey.state, 20212 xkey.keycode, xkey.state,
20206 &consumed, &keysym)) 20213 &consumed, &keysym))
20207 goto done_keysym; 20214 goto done_keysym;
20208 20215
20209 overflow = 0; 20216 /* Save the original keysym in case
20217 XkbTranslateKeysym overflows. */
20218 sym = keysym, overflow = 0;
20210 20219
20211 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym, 20220 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym,
20212 xkey.state & ~consumed, 20221 xkey.state & ~consumed,
@@ -20218,7 +20227,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
20218 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow) 20227 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow)
20219 * sizeof *copy_bufptr); 20228 * sizeof *copy_bufptr);
20220 overflow = 0; 20229 overflow = 0;
20221 nbytes = XkbTranslateKeySym (dpyinfo->display, &keysym, 20230
20231 /* Use the original keysym derived from the
20232 keycode translation in this second call to
20233 XkbTranslateKeysym. */
20234 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym,
20222 xkey.state & ~consumed, 20235 xkey.state & ~consumed,
20223 (char *) copy_bufptr, 20236 (char *) copy_bufptr,
20224 copy_bufsiz, &overflow); 20237 copy_bufsiz, &overflow);
@@ -23725,7 +23738,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23725 Lisp_Object c; 23738 Lisp_Object c;
23726#ifdef HAVE_XKB 23739#ifdef HAVE_XKB
23727 unsigned int mods_rtrn; 23740 unsigned int mods_rtrn;
23728#endif 23741#endif /* HAVE_XKB */
23729 int keycode = xev->detail; 23742 int keycode = xev->detail;
23730 KeySym keysym; 23743 KeySym keysym;
23731 char copy_buffer[81]; 23744 char copy_buffer[81];
@@ -23734,15 +23747,122 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23734 ptrdiff_t i; 23747 ptrdiff_t i;
23735 unsigned int old_state; 23748 unsigned int old_state;
23736 struct xi_device_t *device, *source; 23749 struct xi_device_t *device, *source;
23750 XKeyPressedEvent xkey;
23737 23751
23738 coding = Qlatin_1; 23752 coding = Qlatin_1;
23739 23753
23754 /* The code under this label is quite desultory. There
23755 are also several important discrepancies with the
23756 core KeyPress code to mind.
23757
23758 There are three principal objectives:
23759
23760 The first is to produce a core or GDK translation of
23761 this XI_KeyPress event, which is relayed to the
23762 toolkit. This transpires by setting `copy' to a
23763 close copy of XEV, which is later copied or
23764 dispatched to the toolkit by the code beneath the
23765 OTHER label.
23766
23767 The second objective is to filter the event through
23768 an input method, by generating a second copy of the
23769 event expressly tailored for such a purpose. The
23770 core KeyPress code does not endeavor to do so;
23771 instead, this action is taken prior to calling
23772 handle_one_xevent. Calls to `x_filter_event' or
23773 `xg_filter_key' serve to implement this objective.
23774
23775 If the event is not removed by the input method's
23776 filter, the third objective is to establish either a
23777 keysym or a sequence of characters to insert, using
23778 the information supplied within the key event.
23779
23780 When an input method connection is available, this
23781 responsibility is vested in the hands of the input
23782 method -- yet another copy of XEV as a core event is
23783 produced, and the input method is responsible for
23784 deriving a keysym or text to insert.
23785
23786 Otherwise, if the XKB extension is available, calls
23787 are made to XkbLookupKeycode and XkbTranslateKeysym.
23788
23789 And if all else fails, XEV is transformed into a core
23790 event and provided to XLookupString, in a manner
23791 analogous to the core event processing under the
23792 KeyPress label.
23793
23794 A wide number of variables are employed during this
23795 translation process. The most pertinent ones are:
23796
23797 `copy'
23798
23799 This variable is defined when an X toolkit
23800 incognizant of input extension events is being
23801 employed. If a popup is active, Emacs copies
23802 fields of interest from the extension event to
23803 COPY, sets the `use_copy' flag, and jumps to the
23804 XI_OTHER label. `copy' is then relayed to the
23805 toolkit.
23806
23807 `xkey'
23808
23809 This variable is defined to a copy of the event
23810 used by input methods or XLookupString at various
23811 points during the execution of this label.
23812
23813 `coding'
23814
23815 This variable is consulted at the conclusion of
23816 event generation, and holds the coding system
23817 for any generated string.
23818
23819 `keysym'
23820
23821 This variable is eventually set to the keysym tied
23822 to the event, which may be directly provided within
23823 a generated struct input_event, should it bear a
23824 direct relation to an ASCII or Unicode character,
23825 or if it is a control key.
23826
23827 `copy_buffer', `copy_bufptr', `copy_bufsiz'
23828
23829 These variables hold the buffer that incorporates
23830 characters generated during the keycode-to-keysym
23831 conversion process.
23832
23833 `nbytes'
23834
23835 Holds the number of characters within that buffer,
23836 in bytes. These characters are encoded using the
23837 coding system in `coding'.
23838
23839 If greater than 0 and KEYSYM does not immediately
23840 relate to a function key, control key or character,
23841 it is provided as the string to insert within a
23842 MULTIBYTE_CHAR_KEYSTROKE_EVENT.
23843
23844 `state'
23845
23846 Holds the keyboard and group (but not button)
23847 state. After event filtering concludes, modifier
23848 bits within `extra_keyboard_modifiers' are also
23849 introduced.
23850
23851 This illustration may reflect the treatment taken
23852 towards core key events to some degree. */
23853
23740 device = xi_device_from_id (dpyinfo, xev->deviceid); 23854 device = xi_device_from_id (dpyinfo, xev->deviceid);
23741 source = xi_device_from_id (dpyinfo, xev->sourceid); 23855 source = xi_device_from_id (dpyinfo, xev->sourceid);
23742 23856
23743 if (!device) 23857 if (!device)
23744 goto XI_OTHER; 23858 goto XI_OTHER;
23745 23859
23860 /* Convert the keyboard state within XEV to a core
23861 modifier mask, later supplied as arguments to XKB and
23862 core functions. This encompasses the keyboard group
23863 and effective modifiers but not the button state. */
23864 state = xi_convert_event_keyboard_state (xev);
23865
23746#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 23866#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
23747 /* Dispatch XI_KeyPress events when in menu. */ 23867 /* Dispatch XI_KeyPress events when in menu. */
23748 if (popup_activated ()) 23868 if (popup_activated ())
@@ -23758,7 +23878,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23758 copy.xkey.root = xev->root; 23878 copy.xkey.root = xev->root;
23759 copy.xkey.subwindow = xev->child; 23879 copy.xkey.subwindow = xev->child;
23760 copy.xkey.time = xev->time; 23880 copy.xkey.time = xev->time;
23761 copy.xkey.state = xi_convert_event_keyboard_state (xev); 23881 copy.xkey.state = state;
23762 xi_convert_button_state (&xev->buttons, &copy.xkey.state); 23882 xi_convert_button_state (&xev->buttons, &copy.xkey.state);
23763 23883
23764 copy.xkey.x = lrint (xev->event_x); 23884 copy.xkey.x = lrint (xev->event_x);
@@ -23767,10 +23887,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23767 copy.xkey.y_root = lrint (xev->root_y); 23887 copy.xkey.y_root = lrint (xev->root_y);
23768 copy.xkey.keycode = xev->detail; 23888 copy.xkey.keycode = xev->detail;
23769 copy.xkey.same_screen = True; 23889 copy.xkey.same_screen = True;
23770#endif 23890#endif /* USE_LUCID */
23771 goto XI_OTHER; 23891 goto XI_OTHER;
23772 } 23892 }
23773#endif 23893#endif /* USE_X_TOOLKIT || USE_GTK */
23774 23894
23775 x_display_set_last_user_time (dpyinfo, xev->time, 23895 x_display_set_last_user_time (dpyinfo, xev->time,
23776 xev->send_event, true); 23896 xev->send_event, true);
@@ -23790,7 +23910,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23790#ifdef USE_GTK 23910#ifdef USE_GTK
23791 if (f) 23911 if (f)
23792 x_set_gtk_user_time (f, xev->time); 23912 x_set_gtk_user_time (f, xev->time);
23793#endif 23913#endif /* USE_GTK */
23794 23914
23795 if (f) 23915 if (f)
23796 { 23916 {
@@ -23802,7 +23922,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23802 xev->time); 23922 xev->time);
23803 } 23923 }
23804 23924
23805 XKeyPressedEvent xkey; 23925 /* Convert the XI event into a core event structure
23926 provided to old Xlib functions and input method
23927 filter functions. */
23806 23928
23807 memset (&xkey, 0, sizeof xkey); 23929 memset (&xkey, 0, sizeof xkey);
23808 23930
@@ -23814,8 +23936,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23814 xkey.root = xev->root; 23936 xkey.root = xev->root;
23815 xkey.subwindow = xev->child; 23937 xkey.subwindow = xev->child;
23816 xkey.time = xev->time; 23938 xkey.time = xev->time;
23817 xkey.state = xi_convert_event_keyboard_state (xev); 23939 xkey.state = state;
23818
23819 xkey.x = lrint (xev->event_x); 23940 xkey.x = lrint (xev->event_x);
23820 xkey.y = lrint (xev->event_y); 23941 xkey.y = lrint (xev->event_y);
23821 xkey.x_root = lrint (xev->root_x); 23942 xkey.x_root = lrint (xev->root_x);
@@ -23844,7 +23965,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23844 *finish = X_EVENT_DROP; 23965 *finish = X_EVENT_DROP;
23845 goto XI_OTHER; 23966 goto XI_OTHER;
23846 } 23967 }
23847#else 23968#else /* !USE_GTK */
23848 if (x_filter_event (dpyinfo, (XEvent *) &xkey)) 23969 if (x_filter_event (dpyinfo, (XEvent *) &xkey))
23849 { 23970 {
23850 /* Try to attribute core key events from the input 23971 /* Try to attribute core key events from the input
@@ -23856,8 +23977,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23856 *finish = X_EVENT_DROP; 23977 *finish = X_EVENT_DROP;
23857 goto XI_OTHER; 23978 goto XI_OTHER;
23858 } 23979 }
23859#endif 23980#endif /* HAVE_X_I18N */
23860#elif USE_GTK 23981#elif USE_GTK /* && !HAVE_X_I18N */
23861 if ((x_gtk_use_native_input 23982 if ((x_gtk_use_native_input
23862 || dpyinfo->prefer_native_input) 23983 || dpyinfo->prefer_native_input)
23863 && xg_filter_key (any, event)) 23984 && xg_filter_key (any, event))
@@ -23871,48 +23992,17 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23871 *finish = X_EVENT_DROP; 23992 *finish = X_EVENT_DROP;
23872 goto XI_OTHER; 23993 goto XI_OTHER;
23873 } 23994 }
23874#endif 23995#endif /* HAVE_X_I18N || USE_GTK */
23875 23996
23876 state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers); 23997 state |= x_emacs_to_x_modifiers (dpyinfo, extra_keyboard_modifiers);
23877 23998
23878#ifdef HAVE_XKB
23879 if (dpyinfo->xkb_desc)
23880 {
23881 unsigned int xkb_state;
23882
23883 xkb_state = state & ~(1 << 13 | 1 << 14);
23884 xkb_state |= xev->group.effective << 13;
23885
23886 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc, keycode,
23887 xkb_state, &mods_rtrn, &keysym))
23888 goto XI_OTHER;
23889 }
23890 else
23891 {
23892#endif
23893 int keysyms_per_keycode_return;
23894 KeySym *ksms = XGetKeyboardMapping (dpyinfo->display, keycode, 1,
23895 &keysyms_per_keycode_return);
23896 if (!(keysym = ksms[0]))
23897 {
23898 XFree (ksms);
23899 goto XI_OTHER;
23900 }
23901 XFree (ksms);
23902#ifdef HAVE_XKB
23903 }
23904#endif
23905
23906 if (keysym == NoSymbol)
23907 goto XI_OTHER;
23908
23909 /* If mouse-highlight is an integer, input clears out 23999 /* If mouse-highlight is an integer, input clears out
23910 mouse highlighting. */ 24000 mouse highlighting. */
23911 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight) 24001 if (!hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)
23912 && (f == 0 24002 && (f == 0
23913#if ! defined (USE_GTK) 24003#if ! defined (USE_GTK)
23914 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window) 24004 || !EQ (f->tool_bar_window, hlinfo->mouse_face_window)
23915#endif 24005#endif /* !USE_GTK */
23916 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window)) 24006 || !EQ (f->tab_bar_window, hlinfo->mouse_face_window))
23917 ) 24007 )
23918 { 24008 {
@@ -23933,7 +24023,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23933 dialogs because in that case popup_activated is nonzero 24023 dialogs because in that case popup_activated is nonzero
23934 (see above). */ 24024 (see above). */
23935 *finish = X_EVENT_DROP; 24025 *finish = X_EVENT_DROP;
23936#endif 24026#endif /* USE_GTK */
23937 24027
23938 XSETFRAME (inev.ie.frame_or_window, f); 24028 XSETFRAME (inev.ie.frame_or_window, f);
23939 inev.ie.timestamp = xev->time; 24029 inev.ie.timestamp = xev->time;
@@ -23970,25 +24060,54 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23970 emacs_abort (); 24060 emacs_abort ();
23971 } 24061 }
23972 else 24062 else
23973#endif 24063#endif /* HAVE_X_I18N */
23974 { 24064 {
23975#ifdef HAVE_XKB 24065#ifdef HAVE_XKB
23976 int overflow = 0;
23977 KeySym sym = keysym;
23978
23979 if (dpyinfo->xkb_desc) 24066 if (dpyinfo->xkb_desc)
23980 { 24067 {
23981 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym, 24068 KeySym sym;
23982 state & ~mods_rtrn, copy_bufptr, 24069 int overflow;
23983 copy_bufsiz, &overflow); 24070
24071 /* Translate the keycode into the keysym it
24072 represents, using STATE. MODS_RTRN is
24073 set to the modifier bits consumed while
24074 undertaking this translation and should
24075 be subsequently ignored during keysym
24076 translation. */
24077
24078 if (!XkbTranslateKeyCode (dpyinfo->xkb_desc,
24079 keycode, state,
24080 &mods_rtrn, &keysym))
24081 goto xi_done_keysym;
24082
24083 /* Save the original keysym in case
24084 XkbTranslateKeysym overflows. */
24085 sym = keysym, overflow = 0;
24086
24087 /* Translate this keysym and its modifier
24088 state into the actual symbol and string
24089 it represents. */
24090 nbytes = XkbTranslateKeySym (dpyinfo->display,
24091 &keysym,
24092 state & ~mods_rtrn,
24093 copy_bufptr,
24094 copy_bufsiz,
24095 &overflow);
23984 if (overflow) 24096 if (overflow)
23985 { 24097 {
23986 copy_bufptr = SAFE_ALLOCA ((copy_bufsiz += overflow) 24098 copy_bufptr
23987 * sizeof *copy_bufptr); 24099 = SAFE_ALLOCA ((copy_bufsiz += overflow)
24100 * sizeof *copy_bufptr);
23988 overflow = 0; 24101 overflow = 0;
23989 nbytes = XkbTranslateKeySym (dpyinfo->display, &sym, 24102
23990 state & ~mods_rtrn, copy_bufptr, 24103 /* Use the original keysym derived from
23991 copy_bufsiz, &overflow); 24104 the keycode translation. */
24105 nbytes = XkbTranslateKeySym (dpyinfo->display,
24106 &sym,
24107 state & ~mods_rtrn,
24108 copy_bufptr,
24109 copy_bufsiz,
24110 &overflow);
23992 24111
23993 if (overflow) 24112 if (overflow)
23994 nbytes = 0; 24113 nbytes = 0;
@@ -23997,8 +24116,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
23997 coding = Qnil; 24116 coding = Qnil;
23998 } 24117 }
23999 else 24118 else
24000#endif 24119#endif /* HAVE_XKB */
24001 { 24120 {
24121 /* Save the state within XKEY, then remove
24122 all modifier keys Emacs understands from
24123 it, forestalling any attempt by
24124 XLookupString to introduce control
24125 characters. */
24126
24002 old_state = xkey.state; 24127 old_state = xkey.state;
24003 xkey.state &= ~ControlMask; 24128 xkey.state &= ~ControlMask;
24004 xkey.state &= ~(dpyinfo->meta_mod_mask 24129 xkey.state &= ~(dpyinfo->meta_mod_mask
@@ -24024,7 +24149,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24024 x_dnd_xm_use_help = true; 24149 x_dnd_xm_use_help = true;
24025 goto xi_done_keysym; 24150 goto xi_done_keysym;
24026 } 24151 }
24027#endif 24152#endif /* XK_F1 */
24028 24153
24029 /* See if keysym should make Emacs quit. */ 24154 /* See if keysym should make Emacs quit. */
24030 24155