commit d99e32436d7ec671cf1b29e9b16fcaf39e963ad5 (HEAD, refs/remotes/origin/master) Author: Eli Zaretskii Date: Fri Jan 7 09:57:43 2022 +0200 ; * doc/emacs/xresources.texi (Table of Resources): Use @table. diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi index c27fb8ad03..7c5ce101b1 100644 --- a/doc/emacs/xresources.texi +++ b/doc/emacs/xresources.texi @@ -336,19 +336,24 @@ might be useful to turn off XIM on slow X client/server links. @cindex inputStyle (X resource) @cindex input method style, X This resource controls how preview text generated by X input methods -is displayed. If its value is @samp{callback}, input methods will -direct Emacs to display the contents of their preview text in the -current buffer. +is displayed. Its value can be on of the following: -If it is @samp{offthespot}, input methods will display their preview -text inside a separate area of the display provided by Emacs. +@table @samp +@item callback +Display the contents of the preview text in the current buffer. + +@item offthespot +Display the preview text inside a separate area of the display +provided by Emacs. -If it is @samp{overthespot}, input methods will display their preview -text inside a popup window at the location of the point in the current -window. +@item overthespot +Display the preview text inside a popup window at the location of +point in the current window. -If it is @samp{root}, input methods will display their preview text -inside a portion of the display specific to each input method. +@item root +Use some location on display specific to the input method for +displaying the preview text. +@end table @item @code{verticalScrollBars} (class @code{ScrollBars}) Give frames scroll bars on the left if @samp{left}, on the right if commit 1229bd811867cc2ba5f569aa08e798b17ac76daf Author: Po Lu Date: Fri Jan 7 15:38:12 2022 +0800 Allow controlling the X input method style * doc/emacs/xresources.texi (Table of Resources): Document new resource `inputStyle'. * etc/NEWS: Announce new resource. * src/xfns.c (create_frame_xic): Give the display info to `best_xim_style'. (best_xim_style): Take the display's preferred style into account. * src/xterm.c (x_term_init): Parse the preferred style if inputStyle is set. * src/xterm.h (struct x_display_info): New field `preferred_xim_style'. (STYLE_OFFTHESPOT, STYLE_OVERTHESPOT, STYLE_ROOT): (STYLE_CALLBACK, STYLE_NONE): New macros. diff --git a/doc/emacs/xresources.texi b/doc/emacs/xresources.texi index ef3d4c768c..c27fb8ad03 100644 --- a/doc/emacs/xresources.texi +++ b/doc/emacs/xresources.texi @@ -332,6 +332,24 @@ Disable use of X input methods (XIM) if @samp{false} or @samp{off}. This is only relevant if your Emacs is built with XIM support. It might be useful to turn off XIM on slow X client/server links. +@item @code{inputStyle} (class @code{InputStyle}) +@cindex inputStyle (X resource) +@cindex input method style, X +This resource controls how preview text generated by X input methods +is displayed. If its value is @samp{callback}, input methods will +direct Emacs to display the contents of their preview text in the +current buffer. + +If it is @samp{offthespot}, input methods will display their preview +text inside a separate area of the display provided by Emacs. + +If it is @samp{overthespot}, input methods will display their preview +text inside a popup window at the location of the point in the current +window. + +If it is @samp{root}, input methods will display their preview text +inside a portion of the display specific to each input method. + @item @code{verticalScrollBars} (class @code{ScrollBars}) Give frames scroll bars on the left if @samp{left}, on the right if @samp{right}; don't have scroll bars if @samp{off} (@pxref{Scroll Bars}). diff --git a/etc/NEWS b/etc/NEWS index 2e6ba9da21..ea08f7f3de 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -144,6 +144,11 @@ buffer isn't displayed. This controls the thickness of the external borders of the menu bars and pop-up menus. ++++ +** New X resource: "inputStyle". +This controls the style of the pre-edit and status areas of X input +methods. + --- ** New minor mode 'pixel-scroll-precision-mode'. When enabled, and if your mouse supports it, you can scroll the diff --git a/src/xfns.c b/src/xfns.c index d87e67f95b..dbba374d75 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -2622,13 +2622,6 @@ xic_free_xfontset (struct frame *f) /* Create XIC for frame F. */ - -#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea) -#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing) -#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing) -#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing) -#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing) - static const XIMStyle supported_xim_styles[] = { STYLE_CALLBACK, @@ -2643,11 +2636,19 @@ static const XIMStyle supported_xim_styles[] = input method XIM. */ static XIMStyle -best_xim_style (XIMStyles *xim) +best_xim_style (struct x_display_info *dpyinfo, + XIMStyles *xim) { int i, j; int nr_supported = ARRAYELTS (supported_xim_styles); + if (dpyinfo->preferred_xim_style) + { + for (j = 0; j < xim->count_styles; ++j) + if (dpyinfo->preferred_xim_style == xim->supported_styles[j]) + return dpyinfo->preferred_xim_style; + } + for (i = 0; i < nr_supported; ++i) for (j = 0; j < xim->count_styles; ++j) if (supported_xim_styles[i] == xim->supported_styles[j]) @@ -2679,7 +2680,8 @@ create_frame_xic (struct frame *f) goto out; /* Determine XIC style. */ - xic_style = best_xim_style (FRAME_X_XIM_STYLES (f)); + xic_style = best_xim_style (FRAME_DISPLAY_INFO (f), + FRAME_X_XIM_STYLES (f)); /* Create X fontset. */ if (xic_style & (XIMPreeditPosition | XIMStatusArea)) diff --git a/src/xterm.c b/src/xterm.c index 73c0bcf89e..b284fdd312 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -15280,6 +15280,29 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name) #endif } + { + AUTO_STRING (inputStyle, "inputStyle"); + AUTO_STRING (InputStyle, "InputStyle"); + Lisp_Object value = gui_display_get_resource (dpyinfo, inputStyle, InputStyle, + Qnil, Qnil); + +#ifdef HAVE_X_I18N + if (STRINGP (value)) + { + if (!strcmp (SSDATA (value), "callback")) + dpyinfo->preferred_xim_style = STYLE_CALLBACK; + else if (!strcmp (SSDATA (value), "none")) + dpyinfo->preferred_xim_style = STYLE_NONE; + else if (!strcmp (SSDATA (value), "overthespot")) + dpyinfo->preferred_xim_style = STYLE_OVERTHESPOT; + else if (!strcmp (SSDATA (value), "offthespot")) + dpyinfo->preferred_xim_style = STYLE_OFFTHESPOT; + else if (!strcmp (SSDATA (value), "root")) + dpyinfo->preferred_xim_style = STYLE_ROOT; + } +#endif + } + #ifdef HAVE_X_SM /* Only do this for the very first display in the Emacs session. Ignore X session management when Emacs was first started on a diff --git a/src/xterm.h b/src/xterm.h index dcac573252..a796f69ddc 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -434,6 +434,7 @@ struct x_display_info XIM xim; XIMStyles *xim_styles; struct xim_inst_t *xim_callback_data; + XIMStyle preferred_xim_style; #endif /* A cache mapping color names to RGB values. */ @@ -1331,6 +1332,13 @@ extern bool x_session_have_connection (void); extern void x_session_close (void); #endif +#ifdef HAVE_X_I18N +#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea) +#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing) +#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing) +#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing) +#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing) +#endif /* Is the frame embedded into another application? */ commit 808f69bf7a4e7c5cc58762786fd856f7a138a2f3 Author: Po Lu Date: Fri Jan 7 06:52:52 2022 +0000 * src/haikuselect.c: Fix implicit declaration of free. diff --git a/src/haikuselect.c b/src/haikuselect.c index 1b94fb97e6..2e619c69f7 100644 --- a/src/haikuselect.c +++ b/src/haikuselect.c @@ -24,6 +24,8 @@ along with GNU Emacs. If not, see . */ #include "haikuselect.h" #include "haikuterm.h" +#include + static Lisp_Object haiku_selection_data_1 (Lisp_Object clipboard) { commit 751789471cf04916bcfad358472625f382e596d8 Author: Po Lu Date: Fri Jan 7 14:35:29 2022 +0800 Display pre-edit information from X input methods This also repurposes the `pgtk-preedit-text' event to be meaningful on X, renames it `preedit-text', and documents it. * doc/lispref/commands.texi (Misc Events): Document `preedit-text'. * lisp/term/pgtk-win.el (pgtk-preedit-text): Bind to `preedit-text' instead. * lisp/term/x-win.el (x-preedit-overlay): New variable. (x-preedit-text): New command, bound as a special event to `preedit-text'. * src/keyboard.c (kbd_buffer_get_event): (make_lispy_event): Rename PGTK_PREEDIT_TEXT_EVENT PREEDIT_TEXT_EVENT. (syms_of_keyboard): New defsym `preedit-text'. * src/pgtkterm.c (pgtk_enqueue_preedit): Use PREEDIT_TEXT_EVENT instead. * src/termhooks.h (enum event_kind): Rename `PGTK_PREEDIT_TEXT_EVENT' `PREEDIT_TEXT_EVENT'. * src/xfns.c (Xxic_preedit_draw_callback): (Xxic_preedit_caret_callback): (Xxic_preedit_done_callback): (Xxic_preedit_start_callback): New callback variables. (STYLE_OFFTHESPOT, STYLE_OVERTHESPOT): (STYLE_ROOT, STYLE_CALLBACK, STYLE_NONE): New macros. (supported_xim_styles): Use reasonable values. This also serves as a better fix for bug#10867. (best_xim_style): Restore code deleted as part of the original fix for bug#10867. (create_frame_xic): Add preedit callbacks. (xic_set_preeditarea): Add preedit callbacks. (x_xic_to_frame): (xic_preedit_start_callback): (xic_preedit_caret_callback): (xic_preedit_done_callback): (x_xim_text_to_utf8_unix): (xic_preedit_draw_callback): New functions. * src/xterm.c (x_detect_focus_change): Fix type of XI event. (x_free_frame_resources): Free preedit text buffer if still present. * src/xterm.h (struct x_output): New fields `preedit_size', `preedit_chars' and `preedit_active'. diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 0f12fa7241..855b371cac 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2129,6 +2129,19 @@ which @code{1.0} is the width and height of the touchpad respectively. They are usually interpreted as being relative to the size of the object beneath the gesture: image, window, etc. +@cindex @code{preedit-text} event +@item (preedit-text @var{arg}) +This kind of event is sent when a system input method tells Emacs to +display some text to indicate to the user what will be inserted. The +contents of @var{arg} are dependent on the window system being used. + +On X, @var{arg} is a string describing some text to place behind the +cursor. It can be @code{nil}, which means to remove any text +previously displayed. @c FIXME: what is the value of ARG on PGTK? + +It is a special event (@xref{Special Events}), which should normally +not be bound by the user. + @cindex @code{drag-n-drop} event @item (drag-n-drop @var{position} @var{files}) This kind of event is generated when a group of files is diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 0f5b9031db..9bcf3eac64 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -325,8 +325,7 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.") (defun pgtk-preedit-text (event) "An internal function to display preedit text from input method. -EVENT is an event of PGTK_PREEDIT_TEXT_EVENT. -It contains colors and texts." +EVENT is a `preedit-text-event'." (interactive "e") (when pgtk-preedit-overlay (delete-overlay pgtk-preedit-overlay)) @@ -356,6 +355,7 @@ It contains colors and texts." (overlay-put ov 'before-string ovstr) (setq pgtk-preedit-overlay ov))) +(define-key special-event-map [preedit-text] 'pgtk-preedit-text) (add-hook 'after-init-hook (function diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 62cd984866..6b5e396419 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1517,6 +1517,24 @@ This uses `icon-map-list' to map icon file names to stock icon names." (global-set-key [XF86WakeUp] 'ignore) + +(defvar x-preedit-overlay nil + "The overlay currently used to display preedit text from a compose sequence.") + +(defun x-preedit-text (event) + "Display preedit text from a compose sequence in EVENT. +EVENT is a preedit-text event." + (interactive "e") + (when x-preedit-overlay + (delete-overlay x-preedit-overlay) + (setq x-preedit-overlay nil)) + (when (nth 1 event) + (setq x-preedit-overlay (make-overlay (point) (point))) + (overlay-put x-preedit-overlay 'before-string + (propertize (nth 1 event) 'face '(:underline t))))) + +(define-key special-event-map [preedit-text] 'x-preedit-text) + (provide 'x-win) (provide 'term/x-win) diff --git a/src/keyboard.c b/src/keyboard.c index ec1b7cd85d..a9f3257282 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -3973,9 +3973,7 @@ kbd_buffer_get_event (KBOARD **kbp, *used_mouse_menu = true; FALLTHROUGH; #endif -#ifdef HAVE_PGTK - case PGTK_PREEDIT_TEXT_EVENT: -#endif + case PREEDIT_TEXT_EVENT: #ifdef HAVE_NTGUI case END_SESSION_EVENT: case LANGUAGE_CHANGE_EVENT: @@ -6289,10 +6287,8 @@ make_lispy_event (struct input_event *event) return list3 (Qconfig_changed_event, event->arg, event->frame_or_window); -#ifdef HAVE_PGTK - case PGTK_PREEDIT_TEXT_EVENT: - return list2 (intern ("pgtk-preedit-text"), event->arg); -#endif + case PREEDIT_TEXT_EVENT: + return list2 (Qpreedit_text, event->arg); /* The 'kind' field of the event is something we don't recognize. */ default: @@ -12003,6 +11999,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); @@ -12771,8 +12769,6 @@ keys_of_keyboard (void) "ns-put-working-text"); initial_define_lispy_key (Vspecial_event_map, "ns-unput-working-text", "ns-unput-working-text"); - initial_define_lispy_key (Vspecial_event_map, "pgtk-preedit-text", - "pgtk-preedit-text"); /* Here we used to use `ignore-event' which would simple set prefix-arg to current-prefix-arg, as is done in `handle-switch-frame'. But `handle-switch-frame is not run from the special-map. diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 736fce09c4..1d301d11f6 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -5259,7 +5259,7 @@ pgtk_enqueue_preedit (struct frame *f, Lisp_Object preedit) { union buffered_input_event inev; EVENT_INIT (inev.ie); - inev.ie.kind = PGTK_PREEDIT_TEXT_EVENT; + inev.ie.kind = PREEDIT_TEXT_EVENT; inev.ie.arg = preedit; inev.ie.code = 0; XSETFRAME (inev.ie.frame_or_window, f); diff --git a/src/termhooks.h b/src/termhooks.h index 55f7aa5d1a..518e855eae 100644 --- a/src/termhooks.h +++ b/src/termhooks.h @@ -269,10 +269,8 @@ enum event_kind , FILE_NOTIFY_EVENT #endif -#ifdef HAVE_PGTK /* Pre-edit text was changed. */ - , PGTK_PREEDIT_TEXT_EVENT -#endif + , PREEDIT_TEXT_EVENT /* Either the mouse wheel has been released without it being clicked, or the user has lifted his finger from a touchpad. diff --git a/src/xfns.c b/src/xfns.c index b94fe17922..d87e67f95b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -24,6 +24,7 @@ along with GNU Emacs. If not, see . */ #include #include "lisp.h" +#include "character.h" #include "xterm.h" #include "frame.h" #include "window.h" @@ -2330,8 +2331,19 @@ hack_wm_protocols (struct frame *f, Widget widget) #ifdef HAVE_X_I18N -static XFontSet xic_create_xfontset (struct frame *); -static XIMStyle best_xim_style (XIMStyles *); +static void xic_preedit_draw_callback (XIC, XPointer, XIMPreeditDrawCallbackStruct *); +static void xic_preedit_caret_callback (XIC, XPointer, XIMPreeditCaretCallbackStruct *); +static void xic_preedit_done_callback (XIC, XPointer, XPointer); +static int xic_preedit_start_callback (XIC, XPointer, XPointer); + +static XIMCallback Xxic_preedit_draw_callback = { NULL, + (XIMProc) xic_preedit_draw_callback }; +static XIMCallback Xxic_preedit_caret_callback = { NULL, + (XIMProc) xic_preedit_caret_callback }; +static XIMCallback Xxic_preedit_done_callback = { NULL, + (XIMProc) xic_preedit_done_callback }; +static XIMCallback Xxic_preedit_start_callback = { NULL, + (void *) xic_preedit_start_callback }; #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT /* Create an X fontset on frame F with base font name BASE_FONTNAME. */ @@ -2608,6 +2620,23 @@ xic_free_xfontset (struct frame *f) FRAME_XIC_FONTSET (f) = NULL; } +/* Create XIC for frame F. */ + + +#define STYLE_OFFTHESPOT (XIMPreeditArea | XIMStatusArea) +#define STYLE_OVERTHESPOT (XIMPreeditPosition | XIMStatusNothing) +#define STYLE_ROOT (XIMPreeditNothing | XIMStatusNothing) +#define STYLE_CALLBACK (XIMPreeditCallbacks | XIMStatusNothing) +#define STYLE_NONE (XIMPreeditNothing | XIMStatusNothing) + +static const XIMStyle supported_xim_styles[] = + { + STYLE_CALLBACK, + STYLE_NONE, + STYLE_OVERTHESPOT, + STYLE_OFFTHESPOT, + STYLE_ROOT + }; /* Value is the best input style, given user preferences USER (already checked to be supported by Emacs), and styles supported by the @@ -2616,8 +2645,15 @@ xic_free_xfontset (struct frame *f) static XIMStyle best_xim_style (XIMStyles *xim) { - /* Return the default style. This is what GTK3 uses and - should work fine with all modern input methods. */ + int i, j; + int nr_supported = ARRAYELTS (supported_xim_styles); + + for (i = 0; i < nr_supported; ++i) + for (j = 0; j < xim->count_styles; ++j) + if (supported_xim_styles[i] == xim->supported_styles[j]) + return supported_xim_styles[i]; + + /* Return the default style. */ return XIMPreeditNothing | XIMStatusNothing; } @@ -2692,6 +2728,22 @@ create_frame_xic (struct frame *f) goto out; } + if (xic_style & XIMPreeditCallbacks) + { + spot.x = 0; + spot.y = 0; + preedit_attr = XVaCreateNestedList (0, + XNSpotLocation, &spot, + XNPreeditStartCallback, &Xxic_preedit_start_callback, + XNPreeditDoneCallback, &Xxic_preedit_done_callback, + XNPreeditDrawCallback, &Xxic_preedit_draw_callback, + XNPreeditCaretCallback, &Xxic_preedit_caret_callback, + NULL); + + if (!preedit_attr) + goto out; + } + if (preedit_attr && status_attr) xic = XCreateIC (xim, XNInputStyle, xic_style, @@ -2768,7 +2820,12 @@ xic_set_preeditarea (struct window *w, int x, int y) spot.x = WINDOW_TO_FRAME_PIXEL_X (w, x) + WINDOW_LEFT_FRINGE_WIDTH (w) + WINDOW_LEFT_MARGIN_WIDTH(w); spot.y = WINDOW_TO_FRAME_PIXEL_Y (w, y) + FONT_BASE (FRAME_FONT (f)); - attr = XVaCreateNestedList (0, XNSpotLocation, &spot, NULL); + attr = XVaCreateNestedList (0, XNSpotLocation, &spot, + XNPreeditStartCallback, &Xxic_preedit_start_callback, + XNPreeditDoneCallback, &Xxic_preedit_done_callback, + XNPreeditDrawCallback, &Xxic_preedit_draw_callback, + XNPreeditCaretCallback, &Xxic_preedit_caret_callback, + NULL); XSetICValues (FRAME_XIC (f), XNPreeditAttributes, attr, NULL); XFree (attr); } @@ -2816,9 +2873,273 @@ xic_set_statusarea (struct frame *f) XFree (attr); } +static struct frame * +x_xic_to_frame (XIC xic) +{ + Lisp_Object tail, tem; + struct frame *f; + + FOR_EACH_FRAME (tail, tem) + { + f = XFRAME (tem); + + if (FRAME_X_P (f) && FRAME_XIC (f) == xic) + return f; + } + + return NULL; +} + +static int +xic_preedit_start_callback (XIC xic, XPointer client_data, + XPointer call_data) +{ + struct frame *f = x_xic_to_frame (xic); + struct x_output *output; + + if (f) + { + output = FRAME_X_OUTPUT (f); + + output->preedit_size = 0; + output->preedit_active = true; + + if (output->preedit_chars) + xfree (output->preedit_chars); + + output->preedit_chars = NULL; + } + + return -1; +} + +static void +xic_preedit_caret_callback (XIC xic, XPointer client_data, + XIMPreeditCaretCallbackStruct *call_data) +{ + +} + + +static void +xic_preedit_done_callback (XIC xic, XPointer client_data, + XPointer call_data) +{ + struct frame *f = x_xic_to_frame (xic); + struct x_output *output; + struct input_event ie; + + if (f) + { + ie.kind = PREEDIT_TEXT_EVENT; + ie.arg = Qnil; + XSETFRAME (ie.frame_or_window, f); + XSETINT (ie.x, 0); + XSETINT (ie.y, 0); + kbd_buffer_store_event (&ie); + + output = FRAME_X_OUTPUT (f); + + if (output->preedit_chars) + xfree (output->preedit_chars); + + output->preedit_size = 0; + output->preedit_active = false; + output->preedit_chars = NULL; + } +} + +/* 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; + + if (text->encoding_is_wchar) + { + wchar_buf = xmalloc ((text->length + 1) * MAX_MULTIBYTE_LENGTH); + wchar_actual_length = 0; + + for (i = 0; i < text->length; ++i) + wchar_actual_length += CHAR_STRING (text->string.wide_char[i], + wchar_buf + wchar_actual_length); + *length = wchar_actual_length; + + return (char *) wchar_buf; + } + + nbytes = strlen (text->string.multi_byte); + setup_coding_system (Qutf_8_unix, &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); + + /* coding.destination has either been allocated by us, or + reallocated by decode_coding_object. */ + + *length = coding.produced; + return (char *) coding.destination; +} + +static void +xic_preedit_draw_callback (XIC xic, XPointer client_data, + XIMPreeditDrawCallbackStruct *call_data) +{ + struct frame *f = x_xic_to_frame (xic); + struct x_output *output; + ptrdiff_t text_length; + ptrdiff_t charpos; + ptrdiff_t original_size; + char *text; + char *chg_start, *chg_end; + struct input_event ie; + + if (f) + { + output = FRAME_X_OUTPUT (f); + + if (!output->preedit_active) + return; + + if (call_data->text) + text = x_xim_text_to_utf8_unix (call_data->text, &text_length); + else + text = NULL; + + original_size = output->preedit_size; + + /* This is an ordinary insertion: reallocate the buffer to hold + enough for TEXT. */ + if (!call_data->chg_length) + { + if (!text) + goto im_abort; + + if (output->preedit_chars) + output->preedit_chars = xrealloc (output->preedit_chars, + output->preedit_size += text_length); + else + output->preedit_chars = xmalloc (output->preedit_size += text_length); + } + + chg_start = output->preedit_chars; + + /* The IM sent bad data: the buffer is empty, but the change + position is more than 0. */ + if (!output->preedit_chars && call_data->chg_first) + goto im_abort; + + /* Find the byte position for the character position where the + first change is to be made. */ + if (call_data->chg_first) + { + charpos = 0; + + while (charpos < call_data->chg_first) + { + chg_start += BYTES_BY_CHAR_HEAD (*chg_start); + + if ((chg_start - output->preedit_chars) > output->preedit_size) + /* The IM sent bad data: chg_start is larger than the + current buffer. */ + goto im_abort; + ++charpos; + } + } + + if (!call_data->chg_length) + { + if (!text) + goto im_abort; + + memmove (chg_start + text_length, chg_start, + original_size - (chg_start - output->preedit_chars)); + memcpy (chg_start, text, text_length); + } + else + { + if (call_data->chg_length < 1) + goto im_abort; + + charpos = 0; + chg_end = chg_start; + + while (charpos < call_data->chg_length) + { + chg_end += BYTES_BY_CHAR_HEAD (*chg_end); + + if ((chg_end - output->preedit_chars) > output->preedit_size) + /* The IM sent bad data: chg_end ends someplace outside + the current buffer. */ + goto im_abort; + ++charpos; + } + + memmove (chg_start, chg_end, ((output->preedit_chars + + output->preedit_size) - chg_end)); + output->preedit_size -= (chg_end - chg_start); + + if (text) + { + original_size = output->preedit_size; + output->preedit_chars = xrealloc (output->preedit_chars, + output->preedit_size += text_length); + + /* Find chg_start again, since preedit_chars was reallocated. */ + + chg_start = output->preedit_chars; + charpos = 0; -/* Set X fontset for XIC of frame F, using base font name - BASE_FONTNAME. Called when a new Emacs fontset is chosen. */ + while (charpos < call_data->chg_first) + { + chg_start += BYTES_BY_CHAR_HEAD (*chg_start); + + if ((chg_start - output->preedit_chars) > output->preedit_size) + /* The IM sent bad data: chg_start is larger than the + current buffer. */ + goto im_abort; + ++charpos; + } + + memmove (chg_start + text_length, chg_start, + original_size - (chg_start - output->preedit_chars)); + memcpy (chg_start, text, text_length); + } + } + + if (text) + xfree (text); + + /* This is okay because this callback is called from the big XIM + event filter, which runs inside XTread_socket. */ + + ie.kind = PREEDIT_TEXT_EVENT; + XSETFRAME (ie.frame_or_window, f); + ie.arg = make_string_from_utf8 (output->preedit_chars, + output->preedit_size); + XSETINT (ie.x, 0); + XSETINT (ie.y, 0); + + kbd_buffer_store_event (&ie); + } + + return; + + im_abort: + if (text) + xfree (text); + if (output->preedit_chars) + xfree (output->preedit_chars); + output->preedit_chars = NULL; + output->preedit_size = 0; + output->preedit_active = false; +} void xic_set_xfontset (struct frame *f, const char *base_fontname) diff --git a/src/xterm.c b/src/xterm.c index 1d4c775753..73c0bcf89e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -5198,7 +5198,7 @@ x_detect_focus_change (struct x_display_info *dpyinfo, struct frame *frame, #ifdef HAVE_XINPUT2 case GenericEvent: { - XIEvent *xi_event = (XIEvent *) event; + XIEvent *xi_event = (XIEvent *) event->xcookie.data; struct frame *focus_frame = dpyinfo->x_focus_event_frame; int focus_state @@ -14046,6 +14046,9 @@ x_free_frame_resources (struct frame *f) #ifdef HAVE_X_I18N if (FRAME_XIC (f)) free_frame_xic (f); + + if (f->output_data.x->preedit_chars) + xfree (f->output_data.x->preedit_chars); #endif #ifdef USE_CAIRO diff --git a/src/xterm.h b/src/xterm.h index d4600bdf80..dcac573252 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -788,6 +788,12 @@ struct x_output They are used when creating the cairo surface next time. */ int cr_surface_desired_width, cr_surface_desired_height; #endif + +#ifdef HAVE_X_I18N + ptrdiff_t preedit_size; + char *preedit_chars; + bool preedit_active; +#endif }; enum commit 48038cb2b2191980b3862be2c7d408e6ba6ee0d8 Author: Po Lu Date: Fri Jan 7 09:00:59 2022 +0800 * admin/MAINTAINERS: Add myself for some things. diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index f0a3c22059..0258eab93d 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -138,6 +138,27 @@ Andrea Corallo Stefan Kangas admin/automerge +Po Lu + The Haiku port: + src/haikuterm.c + src/haikufns.c + src/haikuimage.c + src/haikuselect.c + src/haiku_io.c + src/haiku.c + src/haiku_select.cc + src/haiku_support.cc + src/haiku_font_support.cc + src/haiku_draw_support.cc + src/haikugui.h + src/haikuterm.h + src/haikuselect.h + src/haiku_support.h + lisp/term/haiku-win.el + doc/emacs/haiku.texi + + Haiku battery support in lisp/battery.el + ============================================================================== 2. Areas that someone is willing to maintain, although he would not necessarily mind if someone else was the official maintainer. @@ -267,6 +288,13 @@ Amin Bandali lisp/eshell/* doc/misc/eshell.texi +Po Lu + The X port + src/xterm.c + src/xfns.c + X11 and GTK xwidget support in src/xwidget.c + Precision pixel scrolling in lisp/pixel-scroll.el + ============================================================================== 3. Externally maintained packages. ============================================================================== commit 7945d86829d89066f082f0086047fae34cf932f1 Author: Eli Zaretskii Date: Thu Jan 6 18:53:45 2022 +0200 ; Fix recent changes in rcirc documentation * doc/misc/rcirc.texi (Changing the time stamp format): * lisp/net/rcirc.el (rcirc-when): Fix documentation wording. diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi index 6217781e2b..b18ab2a6b2 100644 --- a/doc/misc/rcirc.texi +++ b/doc/misc/rcirc.texi @@ -935,7 +935,7 @@ how to include the date in the time stamp: @findex rcirc-when If you don't wish to use verbose time formatting all the time, you can -use the @code{rcirc-when} command to printing a complete timestamp for +use the @code{rcirc-when} command to display a complete timestamp for the message at point. @node Defining a new command diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index dda72a2a7f..9a1153b3c6 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -2048,7 +2048,7 @@ connection." process sender response target text))))) (defun rcirc-when () - "Print a message when the message at point was received." + "Show the time of reception of the message at point." (interactive) (if-let (time (get-text-property (point) 'rcirc-time)) (message (format-time-string "%c" time)) commit 0ae38ec94a77f29beb225568b7785f707ae3a4d2 Author: Philip Kaludercic Date: Thu Jan 6 14:59:41 2022 +0100 ; * NEWS: Revert typo from last commit diff --git a/etc/NEWS b/etc/NEWS index 463c39315d..2e6ba9da21 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -210,7 +210,7 @@ inserted. +++ *** New command 'emoji-describe' (bound to 'C-x 8 e d'). -nThis command will tell you the name of the Emoji at point. (This +This command will tell you the name of the Emoji at point. (This command also works for non-Emoji characters.) ** Help commit 0d46683202e2bf4d7ae88efa0fc65ddd26a5e5fd Author: Philip Kaludercic Date: Thu Jan 6 14:55:59 2022 +0100 Add rcirc-when command * doc/misc/rcirc.texi: Document rcirc-when. * etc/NEWS: Document rcirc-when. * lisp/net/rcirc.el (rcirc-when): Add command. diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi index f13ecc7d28..6217781e2b 100644 --- a/doc/misc/rcirc.texi +++ b/doc/misc/rcirc.texi @@ -933,6 +933,11 @@ how to include the date in the time stamp: (setq rcirc-time-format "%Y-%m-%d %H:%M ") @end example +@findex rcirc-when +If you don't wish to use verbose time formatting all the time, you can +use the @code{rcirc-when} command to printing a complete timestamp for +the message at point. + @node Defining a new command @section Defining a new command @cindex defining commands diff --git a/etc/NEWS b/etc/NEWS index 9c892b285d..463c39315d 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -210,7 +210,7 @@ inserted. +++ *** New command 'emoji-describe' (bound to 'C-x 8 e d'). -This command will tell you the name of the Emoji at point. (This +nThis command will tell you the name of the Emoji at point. (This command also works for non-Emoji characters.) ** Help @@ -259,6 +259,11 @@ For example, a 'display-buffer-alist' entry of will make the body of the chosen window 40 columns wide. For the height use 'window-height' in combination with 'body-lines'. +** Rcirc + ++++ +*** New command 'rcirc-when'. + ** Tab Bars and Tab Lines --- diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index 62e6281e03..dda72a2a7f 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -2047,6 +2047,13 @@ connection." (run-hook-with-args 'rcirc-print-functions process sender response target text))))) +(defun rcirc-when () + "Print a message when the message at point was received." + (interactive) + (if-let (time (get-text-property (point) 'rcirc-time)) + (message (format-time-string "%c" time)) + (message "No time information at point."))) + (defun rcirc-generate-log-filename (process target) "Return filename for log file based on PROCESS and TARGET." (if target commit daedbb2f5bb25e102624dd4694b3d3b64d5e5bca Author: Eli Zaretskii Date: Thu Jan 6 15:47:21 2022 +0200 Improve documentation of font-related face attributes * lisp/faces.el (set-face-attribute): Mention aliases of face attributes. (Bug#53050) diff --git a/lisp/faces.el b/lisp/faces.el index c69603af4d..df09978769 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -686,8 +686,10 @@ and `?' are allowed. VALUE specifies the relative proportionate width of the font to use. It must be one of the symbols `ultra-condensed', `extra-condensed', -`condensed', `semi-condensed', `normal', `semi-expanded', `expanded', -`extra-expanded', or `ultra-expanded'. +`condensed' (a.k.a. `compressed', a.k.a. `narrow'), +`semi-condensed' (a.k.a. `demi-condensed'), `normal' (a.k.a. `medium', +a.k.a. `regular'), `semi-expanded' (a.k.a. `demi-expanded'), +`expanded', `extra-expanded', or `ultra-expanded' (a.k.a. `wide'). `:height' @@ -703,9 +705,11 @@ for it to be relative to). `:weight' VALUE specifies the weight of the font to use. It must be one of -the symbols `ultra-heavy', `heavy', `ultra-bold', `extra-bold', -`bold', `semi-bold', `medium', `normal', `book', `semi-light', -`light', `extra-light', `ultra-light', or `thin'. +the symbols `ultra-heavy', `heavy' (a.k.a. `black'), +`ultra-bold' (a.k.a. `extra-bold'), `bold', +`semi-bold' (a.k.a. `demi-bold'), `medium', `normal' (a.k.a. `regular', +a.k.a. `book'), `semi-light' (a.k.a. `demi-light'), +`light', `extra-light' (a.k.a. `ultra-light'), or `thin'. `:slant' commit 66e50562e818ae181f98f139e07bd56d0d6aadb3 Merge: ca25fde951 b4e709c41f Author: Eli Zaretskii Date: Thu Jan 6 15:47:17 2022 +0200 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs commit b4e709c41f90c644952fe7e9a8b932c6367e495a Author: Michael Albinus Date: Thu Jan 6 13:38:50 2022 +0100 * admin/MAINTAINERS: Describe Tramp as externally maintained package diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 33aeb52865..f0a3c22059 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -58,10 +58,7 @@ Artur Malabarba Michael Albinus Tramp - lisp/net/tramp*.el lisp/url/url-tramp.el - doc/misc/tramp*.texi - test/lisp/net/tramp*-tests.el test/lisp/url/url-tramp-tests.el D-Bus @@ -270,6 +267,20 @@ Amin Bandali lisp/eshell/* doc/misc/eshell.texi +============================================================================== +3. Externally maintained packages. +============================================================================== + +Tramp + Maintainer: Michael Albinus + Repository: git://git.savannah.gnu.org/tramp.git + Mailing List: tramp-devel@gnu.org + Bug Reports: M-x tramp-bug + + lisp/net/tramp*.el + doc/misc/tramp*.texi + test/lisp/net/tramp*-tests.el + ;;; Local Variables: ;;; coding: utf-8 commit ca25fde951f906f6236875234e318b48a9feaa63 Author: Eli Zaretskii Date: Thu Jan 6 14:16:53 2022 +0200 Revert "Fix selection of fonts that don't have regular weight" This reverts commit 1b2511fa2aed460120a36765ba16c14e355eef1d. That commit caused unintended regressions which are worse than the problem it attempted to fix. See the discussion at https://lists.gnu.org/archive/html/emacs-devel/2021-12/msg01643.html for the details. diff --git a/src/font.c b/src/font.c index 58ff1a7981..266e5bc75c 100644 --- a/src/font.c +++ b/src/font.c @@ -2768,6 +2768,7 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size) int candidate = XFIXNUM (AREF (entity, prop)) >> 8; if (candidate != required +#ifdef HAVE_NTGUI /* A kludge for w32 font search, where listing a family returns only 4 standard weights: regular, italic, bold, bold-italic. For other values one @@ -2777,14 +2778,10 @@ font_delete_unmatched (Lisp_Object vec, Lisp_Object spec, int size) weight, so if we require exact match, the non-regular font will be rejected. So we relax the accuracy of the match here, and let - font_sort_entities find the best match. - - Similar things happen on Posix platforms, when - people use font families that don't have the - regular weight, only the medium weight: these - families get rejected if we require an exact match. */ + font_sort_entities find the best match. */ && (prop != FONT_WEIGHT_INDEX || eabs (candidate - required) > 100) +#endif ) prop = FONT_SPEC_MAX; } commit cbe10f37533bc8dc21f7eb9a86bc5f31b3b2c884 Author: Po Lu Date: Thu Jan 6 12:05:47 2022 +0000 Remove some more useless clipping stack calls on Haiku * src/haikuterm.c (haiku_draw_box_rect): (haiku_draw_relief_rect): (haiku_draw_text_decoration): Get rid of calls to BView_StartClip and BView_EndClip. diff --git a/src/haikuterm.c b/src/haikuterm.c index 928b571855..2239770de9 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -428,8 +428,6 @@ haiku_draw_box_rect (struct glyph_string *s, void *view = FRAME_HAIKU_VIEW (s->f); struct face *face = s->face; - BView_StartClip (view); - haiku_clip_to_string (s); BView_SetHighColor (view, face->box_color); if (clip_rect) BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width, @@ -443,7 +441,6 @@ haiku_draw_box_rect (struct glyph_string *s, if (right_p) BView_FillRectangle (view, right_x - vwidth + 1, top_y, vwidth, bottom_y - top_y + 1); - BView_EndClip (view); } static void @@ -484,8 +481,6 @@ haiku_draw_relief_rect (struct glyph_string *s, &color_corner); void *view = FRAME_HAIKU_VIEW (s->f); - BView_StartClip (view); - haiku_clip_to_string (s); BView_SetHighColor (view, raised_p ? color_white : color_black); if (clip_rect) BView_ClipToRect (view, clip_rect->x, clip_rect->y, clip_rect->width, @@ -548,8 +543,6 @@ haiku_draw_relief_rect (struct glyph_string *s, if (right_p && bot_p) BView_FillRectangle (view, right_x, bottom_y, 1, 1); } - - BView_EndClip (view); } static void @@ -598,8 +591,6 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, void *view = FRAME_HAIKU_VIEW (s->f); BView_draw_lock (view); - BView_StartClip (view); - haiku_clip_to_string (s); if (face->underline) { @@ -734,7 +725,6 @@ haiku_draw_text_decoration (struct glyph_string *s, struct face *face, BView_FillRectangle (view, s->x, glyph_y + dy, s->width, h); } - BView_EndClip (view); BView_draw_unlock (view); } commit b3ceeb3f2a4240736840422c272204030d113083 Author: Po Lu Date: Thu Jan 6 19:35:18 2022 +0800 Generate TOUCH_END_EVENTs on NS when mwheel momentum is disabled * src/nsterm.m ([EmacsView mouseDown:]): Generate TOUCH_END_EVENTs on the first event whose momentum phase is not NSEventPhaseNone. diff --git a/src/nsterm.m b/src/nsterm.m index 428d1a2fe2..a15dc47a22 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -6519,6 +6519,22 @@ - (void)mouseDown: (NSEvent *)theEvent int x = 0, y = 0; int scrollUp = NO; + static bool end_flag = false; + + if (!ns_use_mwheel_momentum && !end_flag + && [theEvent momentumPhase] != NSEventPhaseNone) + { + emacs_event->kind = TOUCH_END_EVENT; + emacs_event->arg = Qnil; + end_flag = [theEvent momentumPhase] != NSEventPhaseNone; + XSETINT (emacs_event->x, lrint (p.x)); + XSETINT (emacs_event->y, lrint (p.y)); + EV_TRAILER (theEvent); + return; + } + + end_flag = [theEvent momentumPhase] != NSEventPhaseNone; + /* FIXME: At the top or bottom of the buffer we should * ignore momentum-phase events. */ if (! ns_use_mwheel_momentum commit 9fc20ad35c8dd1814ba097a0ec20c0230c467729 Author: Po Lu Date: Thu Jan 6 19:11:56 2022 +0800 Make sure touch end events aren't sent too many times * src/xterm.c (handle_one_xevent): Don't send touch end events twice if two valuators have their masks set without a change in value. diff --git a/src/xterm.c b/src/xterm.c index ff6c71283e..1d4c775753 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10156,6 +10156,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, case XI_Motion: { struct xi_device_t *device; + bool touch_end_event_seen = false; states = &xev->valuators; values = states->values; @@ -10294,7 +10295,12 @@ handle_one_xevent (struct x_display_info *dpyinfo, inev.ie.arg = Qnil; } - kbd_buffer_store_event_hold (&inev.ie, hold_quit); + if (inev.ie.kind != TOUCH_END_EVENT + || !touch_end_event_seen) + { + kbd_buffer_store_event_hold (&inev.ie, hold_quit); + touch_end_event_seen = inev.ie.kind == TOUCH_END_EVENT; + } val->emacs_value = 0; }