[gtk/preedit-selection-fix: 1/8] imcontext: Add [gs]et_surrounding_with_selection




commit 4b9aeaf9e38ef787cadd81149683c9e9416cc605
Author: Matthias Clasen <mclasen redhat com>
Date:   Thu Mar 4 13:27:38 2021 -0500

    imcontext: Add [gs]et_surrounding_with_selection
    
    The Wayland text protocol expects to get both ends
    of the selection with its surrounding call, so make
    that available via GtkIMContext. We add this as new
    api and vfuncs, and fall back, so that existing
    implementations keep working.

 docs/reference/gtk/gtk4-sections.txt |   2 +
 gtk/gtkimcontext.c                   | 172 ++++++++++++++++++++++++++++-------
 gtk/gtkimcontext.h                   |  40 ++++++--
 3 files changed, 173 insertions(+), 41 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 302d1ad0be..7f20d98ae2 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -1812,6 +1812,8 @@ gtk_im_context_set_cursor_location
 gtk_im_context_set_use_preedit
 gtk_im_context_set_surrounding
 gtk_im_context_get_surrounding
+gtk_im_context_set_surrounding_with_selection
+gtk_im_context_get_surrounding_with_selection
 gtk_im_context_delete_surrounding
 <SUBSECTION Standard>
 GTK_IM_CONTEXT
diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c
index 3080699379..13a8c3bb31 100644
--- a/gtk/gtkimcontext.c
+++ b/gtk/gtkimcontext.c
@@ -128,13 +128,18 @@ static void     gtk_im_context_real_get_preedit_string (GtkIMContext   *context,
                                                        int            *cursor_pos);
 static gboolean gtk_im_context_real_filter_keypress    (GtkIMContext   *context,
                                                        GdkEvent       *event);
-static gboolean gtk_im_context_real_get_surrounding    (GtkIMContext   *context,
-                                                       char          **text,
-                                                       int            *cursor_index);
-static void     gtk_im_context_real_set_surrounding    (GtkIMContext   *context,
-                                                       const char     *text,
-                                                       int             len,
-                                                       int             cursor_index);
+
+static gboolean gtk_im_context_real_get_surrounding_with_selection
+                                                       (GtkIMContext   *context,
+                                                        char          **text,
+                                                        int            *cursor_index,
+                                                        int            *selection_bound);
+static void     gtk_im_context_real_set_surrounding_with_selection
+                                                       (GtkIMContext   *context,
+                                                        const char     *text,
+                                                        int             len,
+                                                        int             cursor_index,
+                                                        int             selection_bound);
 
 static void     gtk_im_context_get_property            (GObject        *obj,
                                                         guint           property_id,
@@ -204,6 +209,18 @@ G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT
  *   behavior. The base implementation emits
  *   #GtkIMContext::retrieve-surrounding and records the context received
  *   by the subsequent invocation of @get_surrounding.
+ * @set_surrounding_with_selection: Called via gtk_im_context_set_surrounding_with_selection()
+ *   in response to signal #GtkIMContext::retrieve-surrounding to update the input
+ *   method’s idea of the context around the cursor. It is not necessary to
+ *   override this method even with input methods which implement
+ *   context-dependent behavior. The base implementation is sufficient for
+ *   gtk_im_context_get_surrounding() to work.
+ * @get_surrounding_with_selection: Called via gtk_im_context_get_surrounding_with_selection()
+ *   to update the context around the cursor location. It is not necessary to override
+ *   this method even with input methods which implement context-dependent
+ *   behavior. The base implementation emits
+ *   #GtkIMContext::retrieve-surrounding and records the context received
+ *   by the subsequent invocation of @get_surrounding.
  */
 static void
 gtk_im_context_class_init (GtkIMContextClass *klass)
@@ -215,8 +232,8 @@ gtk_im_context_class_init (GtkIMContextClass *klass)
 
   klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
   klass->filter_keypress = gtk_im_context_real_filter_keypress;
-  klass->get_surrounding = gtk_im_context_real_get_surrounding;
-  klass->set_surrounding = gtk_im_context_real_set_surrounding;
+  klass->get_surrounding_with_selection = gtk_im_context_real_get_surrounding_with_selection;
+  klass->set_surrounding_with_selection = gtk_im_context_real_set_surrounding_with_selection;
 
   /**
    * GtkIMContext::preedit-start:
@@ -381,13 +398,15 @@ typedef struct
 {
   char *text;
   int cursor_index;
+  int selection_bound;
 } SurroundingInfo;
 
 static void
-gtk_im_context_real_set_surrounding (GtkIMContext  *context,
-                                    const char    *text,
-                                    int            len,
-                                    int            cursor_index)
+gtk_im_context_real_set_surrounding_with_selection (GtkIMContext  *context,
+                                                    const char    *text,
+                                                    int            len,
+                                                    int            cursor_index,
+                                                    int            selection_bound)
 {
   SurroundingInfo *info = g_object_get_data (G_OBJECT (context),
                                              "gtk-im-surrounding-info");
@@ -397,13 +416,15 @@ gtk_im_context_real_set_surrounding (GtkIMContext  *context,
       g_free (info->text);
       info->text = g_strndup (text, len);
       info->cursor_index = cursor_index;
+      info->selection_bound = selection_bound;
     }
 }
 
 static gboolean
-gtk_im_context_real_get_surrounding (GtkIMContext *context,
-                                    char        **text,
-                                    int          *cursor_index)
+gtk_im_context_real_get_surrounding_with_selection (GtkIMContext *context,
+                                                    char        **text,
+                                                    int          *cursor_index,
+                                                    int          *selection_bound)
 {
   gboolean result;
   gboolean info_is_local = FALSE;
@@ -426,11 +447,13 @@ gtk_im_context_real_get_surrounding (GtkIMContext *context,
     {
       *text = g_strdup (info->text ? info->text : "");
       *cursor_index = info->cursor_index;
+      *selection_bound = info->selection_bound;
     }
   else
     {
       *text = NULL;
       *cursor_index = 0;
+      *selection_bound = 0;
     }
 
   if (info_is_local)
@@ -722,20 +745,47 @@ gtk_im_context_set_use_preedit (GtkIMContext *context,
  *        @text.
  * @len: the length of @text, or -1 if @text is nul-terminated
  * @cursor_index: the byte index of the insertion cursor within @text.
- * 
+ *
  * Sets surrounding context around the insertion point and preedit
  * string. This function is expected to be called in response to the
  * GtkIMContext::retrieve_surrounding signal, and will likely have no
  * effect if called at other times.
- **/
+ *
+ * Deprecated: 4.2: Use gtk_im_context_set_surrounding_with_selection() instead
+ */
 void
 gtk_im_context_set_surrounding (GtkIMContext  *context,
-                               const char    *text,
-                               int            len,
-                               int            cursor_index)
+                                const char    *text,
+                                int            len,
+                                int            cursor_index)
+{
+  gtk_im_context_set_surrounding_with_selection (context, text, len, cursor_index, cursor_index);
+}
+
+/**
+ * gtk_im_context_set_surrounding_with_selection:
+ * @context: a #GtkIMContext
+ * @text: text surrounding the insertion point, as UTF-8.
+ *        the preedit string should not be included within
+ *        @text.
+ * @len: the length of @text, or -1 if @text is nul-terminated
+ * @cursor_index: the byte index of the insertion cursor within @text.
+ * @anchor_index: the byte index of the selection bound within @text
+ *
+ * Sets surrounding context around the insertion point and preedit
+ * string. This function is expected to be called in response to the
+ * GtkIMContext::retrieve_surrounding signal, and will likely have no
+ * effect if called at other times.
+ */
+void
+gtk_im_context_set_surrounding_with_selection (GtkIMContext  *context,
+                                               const char    *text,
+                                               int            len,
+                                               int            cursor_index,
+                                               int            anchor_index)
 {
   GtkIMContextClass *klass;
-  
+
   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
   g_return_if_fail (text != NULL || len == 0);
 
@@ -747,7 +797,9 @@ gtk_im_context_set_surrounding (GtkIMContext  *context,
   g_return_if_fail (cursor_index >= 0 && cursor_index <= len);
 
   klass = GTK_IM_CONTEXT_GET_CLASS (context);
-  if (klass->set_surrounding)
+  if (klass->set_surrounding_with_selection)
+    klass->set_surrounding_with_selection (context, text, len, cursor_index, anchor_index);
+  else if (klass->set_surrounding)
     klass->set_surrounding (context, text, len, cursor_index);
 }
 
@@ -760,7 +812,7 @@ gtk_im_context_set_surrounding (GtkIMContext  *context,
  *        stored in this location with g_free().
  * @cursor_index: (out): location to store byte index of the insertion
  *        cursor within @text.
- * 
+ *
  * Retrieves context around the insertion point. Input methods
  * typically want context in order to constrain input text based on
  * existing text; this is important for languages such as Thai where
@@ -776,24 +828,78 @@ gtk_im_context_set_surrounding (GtkIMContext  *context,
  *
  * Returns: %TRUE if surrounding text was provided; in this case
  *    you must free the result stored in *text.
- **/
+ *
+ * Deprecated: 4.2: Use gtk_im_context_get_surrounding_with_selection() instead.
+ */
+gboolean
+gtk_im_context_get_surrounding (GtkIMContext  *context,
+                                char         **text,
+                                int           *cursor_index)
+{
+  return gtk_im_context_get_surrounding_with_selection (context,
+                                                        text,
+                                                        cursor_index,
+                                                        NULL);
+}
+
+/**
+ * gtk_im_context_get_surrounding:
+ * @context: a #GtkIMContext
+ * @text: (out) (transfer full): location to store a UTF-8 encoded
+ *        string of text holding context around the insertion point.
+ *        If the function returns %TRUE, then you must free the result
+ *        stored in this location with g_free().
+ * @cursor_index: (out): location to store byte index of the insertion
+ *        cursor within @text.
+ * @anchor_index: (out): location to store byte index of the selection
+ *        bound within @text
+ *
+ * Retrieves context around the insertion point. Input methods
+ * typically want context in order to constrain input text based on
+ * existing text; this is important for languages such as Thai where
+ * only some sequences of characters are allowed.
+ *
+ * This function is implemented by emitting the
+ * GtkIMContext::retrieve_surrounding signal on the input method; in
+ * response to this signal, a widget should provide as much context as
+ * is available, up to an entire paragraph, by calling
+ * gtk_im_context_set_surrounding(). Note that there is no obligation
+ * for a widget to respond to the ::retrieve_surrounding signal, so input
+ * methods must be prepared to function without context.
+ *
+ * Returns: %TRUE if surrounding text was provided; in this case
+ *    you must free the result stored in *text.
+ */
 gboolean
-gtk_im_context_get_surrounding (GtkIMContext *context,
-                               char        **text,
-                               int          *cursor_index)
+gtk_im_context_get_surrounding_with_selection (GtkIMContext  *context,
+                                               char         **text,
+                                               int           *cursor_index,
+                                               int           *anchor_index)
 {
   GtkIMContextClass *klass;
   char *local_text = NULL;
   int local_index;
   gboolean result = FALSE;
-  
+
   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
 
   klass = GTK_IM_CONTEXT_GET_CLASS (context);
-  if (klass->get_surrounding)
-    result = klass->get_surrounding (context,
-                                    text ? text : &local_text,
-                                    cursor_index ? cursor_index : &local_index);
+  if (klass->get_surrounding_with_selection)
+    result = klass->get_surrounding_with_selection
+                                    (context,
+                                     text ? text : &local_text,
+                                     cursor_index ? cursor_index : &local_index,
+                                     anchor_index ? anchor_index : &local_index);
+  else if (klass->get_surrounding)
+    {
+      result = klass->get_surrounding (context,
+                                       text ? text : &local_text,
+                                       &local_index);
+      if (cursor_index)
+        *cursor_index = local_index;
+      if (anchor_index)
+        *anchor_index = local_index;
+    }
 
   if (result)
     g_free (local_text);
diff --git a/gtk/gtkimcontext.h b/gtk/gtkimcontext.h
index 17419eb180..c9558f2ba3 100644
--- a/gtk/gtkimcontext.h
+++ b/gtk/gtkimcontext.h
@@ -83,6 +83,18 @@ struct _GtkIMContextClass
   gboolean (*get_surrounding)     (GtkIMContext   *context,
                                   char          **text,
                                   int            *cursor_index);
+  void     (*set_surrounding_with_selection)
+                                  (GtkIMContext   *context,
+                                  const char     *text,
+                                  int             len,
+                                  int             cursor_index,
+                                   int             anchor_index);
+  gboolean (*get_surrounding_with_selection)
+                                  (GtkIMContext   *context,
+                                  char          **text,
+                                  int            *cursor_index,
+                                   int            *anchor_index);
+
   /*< private >*/
   /* Padding for future expansion */
   void (*_gtk_reserved1) (void);
@@ -90,7 +102,6 @@ struct _GtkIMContextClass
   void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
   void (*_gtk_reserved5) (void);
-  void (*_gtk_reserved6) (void);
 };
 
 GDK_AVAILABLE_IN_ALL
@@ -130,15 +141,28 @@ void     gtk_im_context_set_cursor_location (GtkIMContext       *context,
 GDK_AVAILABLE_IN_ALL
 void     gtk_im_context_set_use_preedit     (GtkIMContext       *context,
                                             gboolean            use_preedit);
-GDK_AVAILABLE_IN_ALL
+GDK_DEPRECATED_IN_4_2_FOR(gtk_im_context_set_surrounding_with_selection)
 void     gtk_im_context_set_surrounding     (GtkIMContext       *context,
-                                            const char         *text,
-                                            int                 len,
-                                            int                 cursor_index);
-GDK_AVAILABLE_IN_ALL
+                                             const char         *text,
+                                             int                 len,
+                                             int                 cursor_index);
+GDK_DEPRECATED_IN_4_2_FOR(gtk_im_context_get_surrounding_with_selection)
 gboolean gtk_im_context_get_surrounding     (GtkIMContext       *context,
-                                            char              **text,
-                                            int                *cursor_index);
+                                             char              **text,
+                                             int                *cursor_index);
+GDK_AVAILABLE_IN_ALL
+void     gtk_im_context_set_surrounding_with_selection
+                                            (GtkIMContext       *context,
+                                             const char         *text,
+                                             int                 len,
+                                             int                 cursor_index,
+                                             int                 anchor_index);
+GDK_AVAILABLE_IN_ALL
+gboolean gtk_im_context_get_surrounding_with_selection
+                                            (GtkIMContext       *context,
+                                             char              **text,
+                                             int                *cursor_index,
+                                             int                *anchor_index);
 GDK_AVAILABLE_IN_ALL
 gboolean gtk_im_context_delete_surrounding  (GtkIMContext       *context,
                                             int                 offset,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]