From: Po Lu <luangruo@yahoo.com>
Date: Fri, 7 Jan 2022 07:38:12 +0000 (+0800)
Subject: Allow controlling the X input method style
X-Git-Tag: emacs-29.0.90~3221
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=1229bd811867cc2ba5f569aa08e798b17ac76daf;p=emacs.git

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 ef3d4c768ca..c27fb8ad03e 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 2e6ba9da21c..ea08f7f3de7 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 d87e67f95b1..dbba374d751 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 73c0bcf89ea..b284fdd3123 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 dcac5732527..a796f69ddc1 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? */