commit fd2252294b679b1e50ed1aedf4c1a076fbae60e3 (HEAD, refs/remotes/origin/master) Author: Po Lu Date: Wed Feb 16 15:40:39 2022 +0800 Fix frame focus handling with native input * lisp/term/x-win.el (x-gtk-use-native-input-watcher): Stop passing frame parameter to `x-internal-focus-input-context'. * src/xfns.c (Fx_internal_focus_input_context): Focus all focus frames from all displays. diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 298c23566e..9ae238661e 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1567,11 +1567,11 @@ EVENT is a preedit-text event." (defun x-gtk-use-native-input-watcher (_symbol newval &rest _ignored) "Variable watcher for `x-gtk-use-native-input'. -If NEWVAL is non-nil and the selected frame is displayed through X, -focus the GTK input context." +If NEWVAL is non-nil, focus the GTK input context of focused +frames on all displays." (when (and (featurep 'gtk) (eq (framep (selected-frame)) 'x)) - (x-internal-focus-input-context newval (selected-frame)))) + (x-internal-focus-input-context newval))) (add-variable-watcher 'x-gtk-use-native-input #'x-gtk-use-native-input-watcher) diff --git a/src/xfns.c b/src/xfns.c index f00b738908..0a8d18d918 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -8772,28 +8772,41 @@ DEFUN ("x-gtk-debug", Fx_gtk_debug, Sx_gtk_debug, 1, 1, 0, #endif /* USE_GTK */ DEFUN ("x-internal-focus-input-context", Fx_internal_focus_input_context, - Sx_internal_focus_input_context, 2, 2, 0, - doc: /* Focus and set the client window of FRAME's GTK input context. + Sx_internal_focus_input_context, 1, 1, 0, + doc: /* Focus and set the client window of all focused frames' GTK input context. If FOCUS is nil, focus out and remove the client window instead. This should be called from a variable watcher for `x-gtk-use-native-input'. */) - (Lisp_Object focus, Lisp_Object frame) + (Lisp_Object focus) { #ifdef USE_GTK - struct frame *f = decode_window_system_frame (frame); - GtkWidget *widget = FRAME_GTK_OUTER_WIDGET (f); + struct x_display_info *dpyinfo; + struct frame *f; + GtkWidget *widget; - if (!NILP (focus)) - { - gtk_im_context_focus_in (FRAME_X_OUTPUT (f)->im_context); - gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context, - gtk_widget_get_window (widget)); - } - else + block_input (); + for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next) { - gtk_im_context_focus_out (FRAME_X_OUTPUT (f)->im_context); - gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context, - NULL); + f = dpyinfo->x_focus_frame; + + if (f) + { + widget = FRAME_GTK_OUTER_WIDGET (f); + + if (!NILP (focus)) + { + gtk_im_context_focus_in (FRAME_X_OUTPUT (f)->im_context); + gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context, + gtk_widget_get_window (widget)); + } + else + { + gtk_im_context_focus_out (FRAME_X_OUTPUT (f)->im_context); + gtk_im_context_set_client_window (FRAME_X_OUTPUT (f)->im_context, + NULL); + } + } } + unblock_input (); #endif return Qnil; commit db5d2a4407d9016b09155477ccb6eafe5a17a0dd Author: Po Lu Date: Wed Feb 16 14:38:06 2022 +0800 Resolve xwidget scrolling mysteries * src/xterm.c (x_any_window_to_frame): Handle xwidget views. (handle_one_xevent): Always increment values array when handling motion events. diff --git a/src/xterm.c b/src/xterm.c index bd8d5f892f..57e06f6c7e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5681,6 +5681,13 @@ x_any_window_to_frame (struct x_display_info *dpyinfo, int wdesc) if (wdesc == None) return NULL; +#ifdef HAVE_XWIDGETS + struct xwidget_view *xv = xwidget_view_from_window (wdesc); + + if (xv) + return xv->frame; +#endif + FOR_EACH_FRAME (tail, frame) { if (found) @@ -10997,19 +11004,21 @@ handle_one_xevent (struct x_display_info *dpyinfo, scroll wheel movement is reported on XInput 2. */ delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid, i, *values, &val); + values++; if (delta != DBL_MAX) { + if (!f) + { + f = x_any_window_to_frame (dpyinfo, xev->event); + + if (!f) + goto XI_OTHER; + } + #ifdef HAVE_XWIDGETS if (xv) { - /* FIXME: figure out what in GTK is - causing interval values to jump by - >100 at the end of a touch sequence - when an xwidget gets a scroll event - where is_stop is TRUE. */ - if (fabs (delta) > 100) - continue; if (val->horizontal) xv_total_x += delta; else @@ -11019,13 +11028,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, continue; } #endif - if (!f) - { - f = x_any_window_to_frame (dpyinfo, xev->event); - - if (!f) - goto XI_OTHER; - } found_valuator = true; @@ -11107,7 +11109,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, val->emacs_value = 0; } - values++; } inev.ie.kind = NO_EVENT; commit a654e373499c0182e5e0f031fc0bbf4721f8f2bb Author: Po Lu Date: Wed Feb 16 11:28:08 2022 +0800 * etc/NEWS: Improve the PGTK entry. diff --git a/etc/NEWS b/etc/NEWS index 1e1b574c7c..d02e7dcb8a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -68,8 +68,12 @@ XInput 2 support from Lisp programs. To use this option, make sure the GTK 3 and Cairo development files are installed, and configure Emacs with the option '--with-pgtk'. Unlike the default X and GTK build, the resulting Emacs binary will -work on any underlying window system supported by GDK, such as -Wayland and Broadway. +work on any underlying window system supported by GDK, such as Wayland +and Broadway. We do not recommend that you use this configuration, +unless you are running a window system that's supported by GDK other +than X. Running this configuration on X is known to have problems, +such as undesirable frame positioning and keyboard input of sequences +such as "C-;" and "C-S-u". --- ** The docstrings of preloaded files are not in "etc/DOC" any more. commit f1d535da1ed2e7a70c6cf28fdcdca31d3f86a3f5 Author: Po Lu Date: Wed Feb 16 10:53:00 2022 +0800 Decode keyboard input as latin-1 whenever appropriate * src/keyboard.c (kbd_buffer_get_event_1): Use `coding' property if present. * src/termhooks.h (enum event_kind): Document meaning of `coding' property on text strings. * src/xterm.c (handle_one_xevent): Set coding property on text to latin-1 if it was obtained with XLookupString. diff --git a/src/keyboard.c b/src/keyboard.c index 800632aa25..0747ab4820 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3838,7 +3838,12 @@ clear_event (struct input_event *event) static Lisp_Object kbd_buffer_get_event_1 (Lisp_Object arg) { - return code_convert_string (arg, Vlocale_coding_system, + Lisp_Object coding_system = Fget_text_property (make_fixnum (0), + Qcoding, arg); + + return code_convert_string (arg, (!NILP (coding_system) + ? coding_system + : Vlocale_coding_system), Qnil, 0, false, 0); } @@ -12477,6 +12482,9 @@ See also `pre-command-hook'. */); 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, diff --git a/src/termhooks.h b/src/termhooks.h index 4276d8ac2f..0a9ab61afa 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -90,7 +90,17 @@ enum event_kind decoded and the decoded string's characters will be used as .code - individually. */ + individually. + + The string can have a + property `coding', which + should be a symbol + describing a coding system + to use to decode the string. + + If it is nil, then the + locale coding system will + be used. */ NON_ASCII_KEYSTROKE_EVENT, /* .code is a number identifying the function key. A code N represents a key whose name is diff --git a/src/xterm.c b/src/xterm.c index 568351d2e3..bd8d5f892f 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9132,6 +9132,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, static XComposeStatus compose_status; XEvent configureEvent; XEvent next_event; + Lisp_Object coding; *finish = X_EVENT_NORMAL; @@ -9784,6 +9785,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case KeyPress: x_display_set_last_user_time (dpyinfo, event->xkey.time); ignore_next_mouse_click_timeout = 0; + coding = Qlatin_1; #if defined (USE_X_TOOLKIT) || defined (USE_GTK) /* Dispatch KeyPress events when in menu. */ @@ -9884,6 +9886,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, &xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &status_return); + coding = Qnil; if (status_return == XBufferOverflow) { copy_bufsiz = nbytes + 1; @@ -10053,6 +10056,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes); + Fput_text_property (make_fixnum (0), make_fixnum (nbytes), + Qcoding, coding, inev.ie.arg); + if (keysym == NoSymbol) break; } @@ -11444,6 +11450,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, ptrdiff_t i; struct xi_device_t *device; + coding = Qlatin_1; + device = xi_device_from_id (dpyinfo, xev->deviceid); if (!device || !device->master_p) @@ -11571,6 +11579,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, &xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, &status_return); + coding = Qnil; if (status_return == XBufferOverflow) { @@ -11617,6 +11626,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (overflow) nbytes = 0; } + + coding = Qnil; } else #endif @@ -11748,6 +11759,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes); + + Fput_text_property (make_fixnum (0), make_fixnum (nbytes), + Qcoding, coding, inev.ie.arg); goto xi_done_keysym; } commit 0a9c8855b0ce9618219ef70bb489107ce7194ba1 Author: Po Lu Date: Wed Feb 16 10:10:13 2022 +0800 Don't decode text within XIM callbacks or handle_one_xevent * src/keyboard.c (kbd_buffer_get_event_1): (kbd_buffer_get_event_2): New functions. (kbd_buffer_get_event): Accept a new meaning of MULTIBYTE_CHAR_KEYSTROKE_EVENT where .arg can be a unibyte string to be decoded in the locale coding system. * src/termhooks.h (enum event_kind): Document new meaning of .arg in a multibyte keystroke event. * src/xfns.c (struct x_xim_text_conversion_data): New struct. (x_xim_text_to_utf8_unix_1): (x_xim_text_to_utf8_unix_2): New functions. (x_xim_text_to_utf8_unix): Handle decode failure correctly. (xic_preedit_draw_callback): Abort IM context if text could not be decoded correctly. * src/xterm.c (handle_one_xevent): Utilize new meaning of MULTIBYTE_CHAR_KEYSTROKE_EVENT. diff --git a/src/keyboard.c b/src/keyboard.c index be9fb665d7..800632aa25 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3835,6 +3835,18 @@ clear_event (struct input_event *event) event->kind = NO_EVENT; } +static Lisp_Object +kbd_buffer_get_event_1 (Lisp_Object arg) +{ + return code_convert_string (arg, 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. @@ -3847,7 +3859,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) @@ -4120,6 +4132,47 @@ kbd_buffer_get_event (KBOARD **kbp, } } + 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 @@ -4142,9 +4195,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); + } } } } diff --git a/src/termhooks.h b/src/termhooks.h index 518e855eae..4276d8ac2f 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -80,10 +80,17 @@ enum event_kind which the key was typed. .timestamp gives a timestamp (in milliseconds) for the keystroke. */ - MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is in .code, - perhaps with modifiers applied. - The others are the same as - ASCII_KEYSTROKE_EVENT. */ + MULTIBYTE_CHAR_KEYSTROKE_EVENT, /* The multibyte char code is + in .code, perhaps with + modifiers applied. The + others are the same as + ASCII_KEYSTROKE_EVENT, + except when ARG is a + string, which will be + decoded and the decoded + string's characters will be + used as .code + individually. */ NON_ASCII_KEYSTROKE_EVENT, /* .code is a number identifying the function key. A code N represents a key whose name is diff --git a/src/xfns.c b/src/xfns.c index 0f8d6933b3..f00b738908 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3139,14 +3139,64 @@ xic_preedit_done_callback (XIC xic, XPointer client_data, } } +struct x_xim_text_conversion_data +{ + struct coding_system *coding; + char *source; +}; + +static Lisp_Object +x_xim_text_to_utf8_unix_1 (ptrdiff_t nargs, + Lisp_Object *args) +{ + struct x_xim_text_conversion_data *data; + ptrdiff_t nbytes; + + data = xmint_pointer (args[0]); + nbytes = strlen (data->source); + + data->coding->destination = NULL; + + setup_coding_system (Vlocale_coding_system, + data->coding); + data->coding->mode |= (CODING_MODE_LAST_BLOCK + | CODING_MODE_SAFE_ENCODING); + data->coding->source = (const unsigned char *) data->source; + data->coding->dst_bytes = 2048; + data->coding->destination = xmalloc (2048); + decode_coding_object (data->coding, Qnil, 0, 0, + nbytes, nbytes, Qnil); + + return Qnil; +} + +static Lisp_Object +x_xim_text_to_utf8_unix_2 (Lisp_Object val, + ptrdiff_t nargs, + Lisp_Object *args) +{ + struct x_xim_text_conversion_data *data; + + data = xmint_pointer (args[0]); + + if (data->coding->destination) + xfree (data->coding->destination); + + data->coding->destination = NULL; + + return Qnil; +} + /* The string returned is not null-terminated. */ static char * x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length) { unsigned char *wchar_buf; ptrdiff_t wchar_actual_length, i; - ptrdiff_t nbytes; struct coding_system coding; + struct x_xim_text_conversion_data data; + bool was_waiting_for_input_p; + Lisp_Object arg; if (text->encoding_is_wchar) { @@ -3161,17 +3211,16 @@ x_xim_text_to_utf8_unix (XIMText *text, ptrdiff_t *length) return (char *) wchar_buf; } - nbytes = strlen (text->string.multi_byte); - setup_coding_system (Vlocale_coding_system, &coding); - coding.mode |= (CODING_MODE_LAST_BLOCK - | CODING_MODE_SAFE_ENCODING); - coding.source = (const unsigned char *) text->string.multi_byte; - coding.dst_bytes = 2048; - coding.destination = xmalloc (2048); - decode_coding_object (&coding, Qnil, 0, 0, nbytes, nbytes, Qnil); + data.coding = &coding; + data.source = text->string.multi_byte; - /* coding.destination has either been allocated by us, or - reallocated by decode_coding_object. */ + was_waiting_for_input_p = waiting_for_input; + /* Otherwise Fsignal will crash. */ + waiting_for_input = false; + arg = make_mint_ptr (&data); + internal_condition_case_n (x_xim_text_to_utf8_unix_1, 1, &arg, + Qt, x_xim_text_to_utf8_unix_2); + waiting_for_input = was_waiting_for_input_p; *length = coding.produced; return (char *) coding.destination; @@ -3198,16 +3247,14 @@ xic_preedit_draw_callback (XIC xic, XPointer client_data, if (!output->preedit_active) return; - /* If we don't bail out here then GTK can crash - from the resulting signal in `setup_coding_system'. */ - if (NILP (Fcoding_system_p (Vlocale_coding_system))) + if (call_data->text) { - text = NULL; - goto im_abort; - } + text = x_xim_text_to_utf8_unix (call_data->text, &text_length); - if (call_data->text) - text = x_xim_text_to_utf8_unix (call_data->text, &text_length); + if (!text) + /* Decoding the IM text failed. */ + goto im_abort; + } else text = NULL; diff --git a/src/xterm.c b/src/xterm.c index 23317bf695..568351d2e3 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -9124,7 +9124,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, int do_help = 0; ptrdiff_t nbytes = 0; struct frame *any, *f = NULL; - struct coding_system coding; Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; /* This holds the state XLookupString needs to implement dead keys and other tricks known as "compose processing". _X Window System_ @@ -9134,8 +9133,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, XEvent configureEvent; XEvent next_event; - USE_SAFE_ALLOCA; - *finish = X_EVENT_NORMAL; EVENT_INIT (inev.ie); @@ -9843,7 +9840,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, unsigned char *copy_bufptr = copy_buffer; int copy_bufsiz = sizeof (copy_buffer); int modifiers; - Lisp_Object coding_system = Qlatin_1; Lisp_Object c; /* `xkey' will be modified, but it's not important to modify `event' itself. */ @@ -9884,7 +9880,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, { Status status_return; - coding_system = Vlocale_coding_system; nbytes = XmbLookupString (FRAME_XIC (f), &xkey, (char *) copy_bufptr, copy_bufsiz, &keysym, @@ -10051,64 +10046,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, { /* Raw bytes, not keysym. */ ptrdiff_t i; - int nchars, len; - - for (i = 0, nchars = 0; i < nbytes; i++) - { - if (ASCII_CHAR_P (copy_bufptr[i])) - nchars++; - STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - } - - if (nchars < nbytes) - { - /* If we don't bail out here then GTK can crash - from the resulting signal in `setup_coding_system'. */ - if (NILP (Fcoding_system_p (coding_system))) - goto done_keysym; - - /* Decode the input data. */ - - /* The input should be decoded with `coding_system' - which depends on which X*LookupString function - we used just above and the locale. */ - setup_coding_system (coding_system, &coding); - coding.src_multibyte = false; - coding.dst_multibyte = true; - /* The input is converted to events, thus we can't - handle composition. Anyway, there's no XIM that - gives us composition information. */ - coding.common_flags &= ~CODING_ANNOTATION_MASK; - - SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, - nbytes); - coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes; - coding.mode |= CODING_MODE_LAST_BLOCK; - decode_coding_c_string (&coding, copy_bufptr, nbytes, Qnil); - nbytes = coding.produced; - nchars = coding.produced_char; - copy_bufptr = coding.destination; - } - /* Convert the input data to a sequence of - character events. */ - for (i = 0; i < nbytes; i += len) - { - int ch; - if (nchars == nbytes) - ch = copy_bufptr[i], len = 1; - else - ch = string_char_and_length (copy_bufptr + i, &len); - inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.ie.code = ch; - kbd_buffer_store_buffered_event (&inev, hold_quit); - } - - count += nchars; + for (i = 0; i < nbytes; i++) + STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - inev.ie.kind = NO_EVENT; /* Already stored above. */ + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.arg = make_unibyte_string ((char *) copy_bufptr, nbytes); if (keysym == NoSymbol) break; @@ -11497,10 +11440,8 @@ handle_one_xevent (struct x_display_info *dpyinfo, KeySym keysym; char copy_buffer[81]; char *copy_bufptr = copy_buffer; - unsigned char *copy_ubufptr; int copy_bufsiz = sizeof (copy_buffer); ptrdiff_t i; - int nchars, len; struct xi_device_t *device; device = xi_device_from_id (dpyinfo, xev->deviceid); @@ -11802,62 +11743,14 @@ handle_one_xevent (struct x_display_info *dpyinfo, goto xi_done_keysym; } - for (i = 0, nchars = 0; i < nbytes; i++) - { - if (ASCII_CHAR_P (copy_bufptr[i])) - nchars++; - STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - } + for (i = 0; i < nbytes; i++) + STORE_KEYSYM_FOR_DEBUG (copy_bufptr[i]); - if (nchars < nbytes) - { - /* If we don't bail out here then GTK can crash - from the resulting signal in `setup_coding_system'. */ - if (NILP (Fcoding_system_p (Vlocale_coding_system))) - goto xi_done_keysym; - - /* Decode the input data. */ - - setup_coding_system (Vlocale_coding_system, &coding); - coding.src_multibyte = false; - coding.dst_multibyte = true; - /* The input is converted to events, thus we can't - handle composition. Anyway, there's no XIM that - gives us composition information. */ - coding.common_flags &= ~CODING_ANNOTATION_MASK; - - SAFE_NALLOCA (coding.destination, MAX_MULTIBYTE_LENGTH, - nbytes); - coding.dst_bytes = MAX_MULTIBYTE_LENGTH * nbytes; - coding.mode |= CODING_MODE_LAST_BLOCK; - decode_coding_c_string (&coding, (unsigned char *) copy_bufptr, - nbytes, Qnil); - nbytes = coding.produced; - nchars = coding.produced_char; - copy_bufptr = (char *) coding.destination; - } - - copy_ubufptr = (unsigned char *) copy_bufptr; - - /* Convert the input data to a sequence of - character events. */ - for (i = 0; i < nbytes; i += len) - { - int ch; - if (nchars == nbytes) - ch = copy_ubufptr[i], len = 1; - else - ch = string_char_and_length (copy_ubufptr + i, &len); - inev.ie.kind = (SINGLE_BYTE_CHAR_P (ch) - ? ASCII_KEYSTROKE_EVENT - : MULTIBYTE_CHAR_KEYSTROKE_EVENT); - inev.ie.code = ch; - kbd_buffer_store_buffered_event (&inev, hold_quit); - } - - inev.ie.kind = NO_EVENT; + inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; + inev.ie.arg = make_unibyte_string (copy_bufptr, nbytes); goto xi_done_keysym; } + goto XI_OTHER; } @@ -12352,7 +12245,6 @@ handle_one_xevent (struct x_display_info *dpyinfo, /* Sometimes event processing draws to the frame outside redisplay. To ensure that these changes become visible, draw them here. */ flush_dirty_back_buffers (); - SAFE_FREE (); return count; } commit 2d573afecb69c7638991c49dad39e414585db13f Merge: 8415a9d58f 8931cca135 Author: Michael Albinus Date: Tue Feb 15 16:16:50 2022 +0100 Merge branch 'master' of git.sv.gnu.org:/srv/git/emacs commit 8415a9d58fe90431a599f6f935141885319c40dc Author: Michael Albinus Date: Tue Feb 15 16:15:55 2022 +0100 Some Tramp cleanup * doc/misc/tramp.texi (Remote processes): Add also tramp-sshfs.el. * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): Error-out for multi-byte `default-directory'. * lisp/net/tramp.el (tramp-tolerate-tilde): Move it up. (tramp-handle-abbreviate-file-name): Use it. (tramp-read-passwd): Show literal passphrase prompt. diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 8ee4ab24cd..ec9f07dc9e 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -3960,8 +3960,8 @@ Furthermore, this approach has the following limitations: @itemize @item -It works only for connection methods defined in @file{tramp-sh.el} and -@file{tramp-adb.el}. +It works only for connection methods defined in @file{tramp-adb.el}, +@file{tramp-sh.el} and @file{tramp-sshfs.el}. @item It does not support interactive user authentication. With diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index c683f4c6e8..a61179958c 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -986,6 +986,10 @@ implementation will be used." (name1 name) (i 0)) + (when (string-match-p "[[:multibyte:]]" command) + (tramp-error + v 'file-error "Cannot apply multi-byte command `%s'" command)) + (while (get-process name1) ;; NAME must be unique as process name. (setq i (1+ i) @@ -1264,7 +1268,7 @@ connection if a previous connection has died for some reason." (if (zerop (length device)) (tramp-error vec 'file-error "Device %s not connected" host)) (with-tramp-progress-reporter vec 3 "Opening adb shell connection" - (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct? + (let* ((coding-system-for-read 'utf-8-dos) ; Is this correct? (process-connection-type tramp-process-connection-type) (args (if (> (length host) 0) (list "-s" device "shell") diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el index 3f23b1a878..40c02ccea0 100644 --- a/lisp/net/tramp-sshfs.el +++ b/lisp/net/tramp-sshfs.el @@ -240,7 +240,7 @@ arguments to pass to the OPERATION." (error "Implementation does not handle immediate return")) (with-parsed-tramp-file-name (expand-file-name default-directory) nil - (let ((coding-system-for-read 'utf-8-dos) ; Is this correct? + (let ((coding-system-for-read 'utf-8-dos) ; Is this correct? (command (format "cd %s && exec %s" diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 3c06ad1630..91c0efb482 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -3335,6 +3335,10 @@ User is always nil." (defvar tramp-handle-write-region-hook nil "Normal hook to be run at the end of `tramp-*-handle-write-region'.") +(defvar tramp-tolerate-tilde nil + "Indicator, that not expandable tilde shall be tolerated. +Let-bind it when necessary.") + ;; `directory-abbrev-apply' and `directory-abbrev-make-regexp' exists ;; since Emacs 29.1. Since this handler isn't called for older ;; Emacsen, it is save to invoke them via `tramp-compat-funcall'. @@ -3342,6 +3346,7 @@ User is always nil." "Like `abbreviate-file-name' for Tramp files." (let* ((case-fold-search (file-name-case-insensitive-p filename)) (vec (tramp-dissect-file-name filename)) + (tramp-tolerate-tilde t) (home-dir (if (let ((non-essential t)) (tramp-connectable-p vec)) ;; If a connection has already been established, make @@ -3466,10 +3471,6 @@ User is always nil." (if (file-directory-p dir) dir (file-name-directory dir)) nil (tramp-flush-directory-properties v localname))) -(defvar tramp-tolerate-tilde nil - "Indicator, that not expandable tilde shall be tolerated. -Let-bind it when necessary.") - (defun tramp-handle-expand-file-name (name &optional dir) "Like `expand-file-name' for Tramp files." ;; If DIR is not given, use DEFAULT-DIRECTORY or "/". @@ -5756,7 +5757,9 @@ Consults the auth-source package." (or prompt (with-current-buffer (process-buffer proc) (tramp-check-for-regexp proc tramp-password-prompt-regexp) - (format "%s for %s " (capitalize (match-string 1)) key)))) + (if (string-match-p "passphrase" (match-string 1)) + (match-string 0) + (format "%s for %s " (capitalize (match-string 1)) key))))) (auth-source-creation-prompts `((secret . ,pw-prompt))) ;; Use connection-local value. (auth-sources (buffer-local-value 'auth-sources (process-buffer proc))) commit 8931cca1356eb85c5ebcfc5956b39a04109bbd20 Author: Eli Zaretskii Date: Tue Feb 15 16:33:42 2022 +0200 ; * etc/NEWS: Improve wording of savehist.el's entry. diff --git a/etc/NEWS b/etc/NEWS index 1b4eaca00b..1e1b574c7c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -514,9 +514,11 @@ to edit such sequences by allowing point to "enter" the sequence. * Changes in Specialized Modes and Packages in Emacs 29.1 --- -** 'savehist-additional-variables' can now specify variable lengths. -Lists that are longer than the specified length will be truncated -before saving. +** 'savehist.el' can now truncate variables that are too long. +An element of 'savehist-additional-variables' can now be of the form +(VARIABLE . MAX-ELTS), which means to truncate the VARIABLE's value to +at most MAX-ELTS elements (if the value is a list) before saving the +value. ** Minibuffer and Completions commit a4dd94de8018e75fc5c000cff5f57b4a53f05042 Author: Jim Porter Date: Mon Feb 14 13:16:05 2022 -0800 Don't attempt to connect to a remote server during 'abbreviate-file-name' * lisp/net/tramp.el (tramp-handle-abbreviate-file-name): Only use the "home-directory" when a connection has been established. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 32712efb3e..3c06ad1630 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -3343,16 +3343,24 @@ User is always nil." (let* ((case-fold-search (file-name-case-insensitive-p filename)) (vec (tramp-dissect-file-name filename)) (home-dir - (with-tramp-connection-property vec "home-directory" - (tramp-compat-funcall - 'directory-abbrev-apply - (expand-file-name (tramp-make-tramp-file-name vec "~")))))) + (if (let ((non-essential t)) (tramp-connectable-p vec)) + ;; If a connection has already been established, make + ;; sure the "home-directory" connection property is + ;; properly set. + (with-tramp-connection-property vec "home-directory" + (tramp-compat-funcall + 'directory-abbrev-apply + (expand-file-name (tramp-make-tramp-file-name vec "~")))) + ;; Otherwise, just use the cached value. + (tramp-get-connection-property vec "home-directory" nil)))) ;; If any elt of `directory-abbrev-alist' matches this name, ;; abbreviate accordingly. (setq filename (tramp-compat-funcall 'directory-abbrev-apply filename)) ;; Abbreviate home directory. - (if (string-match - (tramp-compat-funcall 'directory-abbrev-make-regexp home-dir) filename) + (if (and home-dir + (string-match + (tramp-compat-funcall 'directory-abbrev-make-regexp home-dir) + filename)) (tramp-make-tramp-file-name vec (concat "~" (substring filename (match-beginning 1)))) (tramp-make-tramp-file-name (tramp-dissect-file-name filename))))) commit 8a2f73f12aaec40d9ef56faba00d4a7545b0cf0d Author: Lars Ingebrigtsen Date: Tue Feb 15 11:29:43 2022 +0100 Allow savehist-additional-variables to truncate lists * lisp/savehist.el (savehist-save): Allow truncating values (bug#30943). diff --git a/etc/NEWS b/etc/NEWS index c7aa46395d..1b4eaca00b 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -513,6 +513,11 @@ to edit such sequences by allowing point to "enter" the sequence. * Changes in Specialized Modes and Packages in Emacs 29.1 +--- +** 'savehist-additional-variables' can now specify variable lengths. +Lists that are longer than the specified length will be truncated +before saving. + ** Minibuffer and Completions *** The "*Completions*" buffer can now be automatically selected. diff --git a/lisp/savehist.el b/lisp/savehist.el index aab304007b..172acaa4e8 100644 --- a/lisp/savehist.el +++ b/lisp/savehist.el @@ -60,14 +60,19 @@ If you want to save only specific histories, use `savehist-save-hook' to modify the value of `savehist-minibuffer-history-variables'." :type 'boolean) -(defcustom savehist-additional-variables () +(defcustom savehist-additional-variables nil "List of additional variables to save. -Each element is a symbol whose value will be persisted across Emacs -sessions that use Savehist. The contents of variables should be -printable with the Lisp printer. You don't need to add minibuffer -history variables to this list, all minibuffer histories will be -saved automatically as long as `savehist-save-minibuffer-history' is -non-nil. +Each element is a variable that will be persisted across Emacs +sessions that use Savehist. + +An element may be variable name (a symbol) or a cons cell of the form +\(VAR . MAX-SIZE), which means to truncate VAR's value to at most +MAX-SIZE elements (if the value is a list) before saving the value. + +The contents of variables should be printable with the Lisp +printer. You don't need to add minibuffer history variables to +this list, all minibuffer histories will be saved automatically +as long as `savehist-save-minibuffer-history' is non-nil. User options should be saved with the Customize interface. This list is useful for saving automatically updated variables that are not @@ -278,12 +283,21 @@ If AUTO-SAVE is non-nil, compare the saved contents to the one last saved, (delete-region (point) (1+ (point))))) (insert "))\n")))))) ;; Save the additional variables. - (dolist (symbol savehist-additional-variables) - (when (boundp symbol) - (let ((value (symbol-value symbol))) - (when (savehist-printable value) - (prin1 `(setq ,symbol ',value) (current-buffer)) - (insert ?\n)))))) + (dolist (elem savehist-additional-variables) + (let ((symbol (if (consp elem) + (car elem) + elem))) + (when (boundp symbol) + (let ((value (symbol-value symbol))) + (when (savehist-printable value) + ;; When we have a max-size, chop off the last elements. + (when (and (consp elem) + (listp value) + (length> value (cdr elem))) + (setq value (copy-sequence value)) + (setcdr (nthcdr (cdr elem) value) nil)) + (prin1 `(setq ,symbol ',value) (current-buffer)) + (insert ?\n))))))) ;; If autosaving, avoid writing if nothing has changed since the ;; last write. (let ((checksum (md5 (current-buffer) nil nil savehist-coding-system))) commit f84f686ec9ce18fcb766a278970f4a81c8fe027c Author: Lars Ingebrigtsen Date: Tue Feb 15 10:59:56 2022 +0100 Adjust files-test-file-size-human-readable test * test/lisp/files-tests.el (files-test-file-size-human-readable): Fix test after recent change. diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el index 57d1ef1682..5d0a1bc2f3 100644 --- a/test/lisp/files-tests.el +++ b/test/lisp/files-tests.el @@ -1457,7 +1457,7 @@ renaming only, rather than modified in-place." (should (equal (file-size-human-readable-iec 0) "0 B")) (should (equal (file-size-human-readable-iec 1) "1 B")) (should (equal (file-size-human-readable-iec 9621) "9.4 KiB")) - (should (equal (file-size-human-readable-iec 72528034765) "67.5 GiB"))) + (should (equal (file-size-human-readable-iec 72528034765) "68 GiB"))) (ert-deftest files-test-magic-mode-alist-re-baseline () "Test magic-mode-alist with RE, expected behavior for match." commit 5c9d34cdf8ff3259831a12f19553880c5348de76 Author: Lars Ingebrigtsen Date: Tue Feb 15 10:54:30 2022 +0100 Make autoarg obsolete * lisp/obsolete/autoarg.el: Make obsolete. diff --git a/etc/NEWS b/etc/NEWS index b4acdf0e4f..c7aa46395d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -983,6 +983,12 @@ Enabling this minor mode turns on hiding header material, like 'elide-head' does; disabling it shows the header. The commands 'elide-head' and 'elide-head-show' are now obsolete. +--- +** The autoarg.el library is now marked obsolete. +This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor +modes to emulate the behavior of the historical editor Twenex Emacs. +It is believed to no longer be useful. + * New Modes and Packages in Emacs 29.1 diff --git a/lisp/autoarg.el b/lisp/obsolete/autoarg.el similarity index 99% rename from lisp/autoarg.el rename to lisp/obsolete/autoarg.el index b0d6abe020..8d5ded9342 100644 --- a/lisp/autoarg.el +++ b/lisp/obsolete/autoarg.el @@ -5,6 +5,7 @@ ;; Author: Dave Love ;; Created: 1998-09-04 ;; Keywords: abbrev, emulations +;; Obsolete-since: 29.1 ;; This file is part of GNU Emacs. commit ac824600d2630217a6f03511574b52f22bcebd99 Author: Arash Esbati Date: Tue Feb 15 10:00:57 2022 +0100 ; Fix commit d6fba624e6 * doc/misc/gnus.texi (Gravatars): Adjust vindex entries. diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index eb675234f6..a3def495c4 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -24146,13 +24146,13 @@ If you want to see them in the Cc and To fields, set: @table @code @item gnus-group-tool-bar -@vindex gnus-group-toolbar +@vindex gnus-group-tool-bar Specifies the tool bar in the group buffer. It can be either a list or a symbol referring to a list. Pre-defined symbols include @code{gnus-group-tool-bar-gnome} and @code{gnus-group-tool-bar-retro}. @item gnus-summary-tool-bar -@vindex gnus-summary-toolbar +@vindex gnus-summary-tool-bar Specifies the tool bar in the summary buffer. It can be either a list or a symbol referring to a list. Pre-defined symbols include @code{gnus-summary-tool-bar-gnome} and