[mutter/wip/carlosg/text-input: 15/24] clutter: Add ClutterInputMethod and ClutterInputFocus



commit 6e3b0eb4302ba83780888499d5db6c7048128cea
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Dec 6 12:43:14 2017 +0100

    clutter: Add ClutterInputMethod and ClutterInputFocus

 clutter/clutter/Makefile.am            |    4 +
 clutter/clutter/clutter-enums.h        |   35 +++
 clutter/clutter/clutter-input-focus.c  |  229 ++++++++++++++++++++
 clutter/clutter/clutter-input-focus.h  |   86 ++++++++
 clutter/clutter/clutter-input-method.c |  359 ++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-input-method.h |   89 ++++++++
 clutter/clutter/clutter-types.h        |    3 +
 clutter/clutter/clutter.h              |    2 +
 8 files changed, 807 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter/Makefile.am b/clutter/clutter/Makefile.am
index 8fbd993..c96d743 100644
--- a/clutter/clutter/Makefile.am
+++ b/clutter/clutter/Makefile.am
@@ -87,6 +87,8 @@ source_h =                                    \
        clutter-image.h         \
        clutter-input-device.h  \
        clutter-input-device-tool.h     \
+       clutter-input-focus.h   \
+       clutter-input-method.h  \
         clutter-interval.h            \
        clutter-keyframe-transition.h   \
        clutter-keysyms.h               \
@@ -169,6 +171,8 @@ source_c = \
        clutter-image.c         \
        clutter-input-device.c  \
        clutter-input-device-tool.c     \
+       clutter-input-focus.c   \
+       clutter-input-method.c  \
        clutter-virtual-input-device.c  \
        clutter-interval.c            \
        clutter-keyframe-transition.c   \
diff --git a/clutter/clutter/clutter-enums.h b/clutter/clutter/clutter-enums.h
index a0450a5..b9987d8 100644
--- a/clutter/clutter/clutter-enums.h
+++ b/clutter/clutter/clutter-enums.h
@@ -1574,6 +1574,41 @@ typedef enum {
   CLUTTER_INPUT_DEVICE_MAPPING_RELATIVE,
 } ClutterInputDeviceMapping;
 
+typedef enum {
+  CLUTTER_INPUT_CONTENT_HINT_COMPLETION          = 1 << 0,
+  CLUTTER_INPUT_CONTENT_HINT_SPELLCHECK          = 1 << 1,
+  CLUTTER_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION = 1 << 2,
+  CLUTTER_INPUT_CONTENT_HINT_LOWERCASE           = 1 << 3,
+  CLUTTER_INPUT_CONTENT_HINT_UPPERCASE           = 1 << 4,
+  CLUTTER_INPUT_CONTENT_HINT_TITLECASE           = 1 << 5,
+  CLUTTER_INPUT_CONTENT_HINT_HIDDEN_TEXT         = 1 << 6,
+  CLUTTER_INPUT_CONTENT_HINT_SENSITIVE_DATA      = 1 << 7,
+  CLUTTER_INPUT_CONTENT_HINT_LATIN               = 1 << 8,
+  CLUTTER_INPUT_CONTENT_HINT_MULTILINE           = 1 << 9,
+} ClutterInputContentHintFlags;
+
+typedef enum {
+  CLUTTER_INPUT_CONTENT_PURPOSE_NORMAL,
+  CLUTTER_INPUT_CONTENT_PURPOSE_ALPHA,
+  CLUTTER_INPUT_CONTENT_PURPOSE_DIGITS,
+  CLUTTER_INPUT_CONTENT_PURPOSE_NUMBER,
+  CLUTTER_INPUT_CONTENT_PURPOSE_PHONE,
+  CLUTTER_INPUT_CONTENT_PURPOSE_URL,
+  CLUTTER_INPUT_CONTENT_PURPOSE_EMAIL,
+  CLUTTER_INPUT_CONTENT_PURPOSE_NAME,
+  CLUTTER_INPUT_CONTENT_PURPOSE_PASSWORD,
+  CLUTTER_INPUT_CONTENT_PURPOSE_DATE,
+  CLUTTER_INPUT_CONTENT_PURPOSE_TIME,
+  CLUTTER_INPUT_CONTENT_PURPOSE_DATETIME,
+  CLUTTER_INPUT_CONTENT_PURPOSE_TERMINAL,
+} ClutterInputContentPurpose;
+
+typedef enum {
+  CLUTTER_INPUT_PANEL_STATE_OFF,
+  CLUTTER_INPUT_PANEL_STATE_ON,
+  CLUTTER_INPUT_PANEL_STATE_TOGGLE,
+} ClutterInputPanelState;
+
 G_END_DECLS
 
 #endif /* __CLUTTER_ENUMS_H__ */
diff --git a/clutter/clutter/clutter-input-focus.c b/clutter/clutter/clutter-input-focus.c
new file mode 100644
index 0000000..5088f08
--- /dev/null
+++ b/clutter/clutter/clutter-input-focus.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "clutter-build-config.h"
+
+#include "clutter/clutter-input-focus.h"
+
+enum {
+  FOCUS_IN,
+  FOCUS_OUT,
+  COMMIT,
+  DELETE_SURROUNDING,
+  REQUEST_SURROUNDING,
+  SET_PREEDIT_TEXT,
+  N_SIGNALS,
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
+G_DEFINE_INTERFACE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT)
+
+static void
+clutter_input_focus_default_init (ClutterInputFocusInterface *iface)
+{
+  signals[FOCUS_IN] =
+    g_signal_new ("focus-in",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, focus_in),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, CLUTTER_TYPE_INPUT_METHOD);
+  signals[FOCUS_OUT] =
+    g_signal_new ("focus-out",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, focus_out),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+  signals[COMMIT] =
+    g_signal_new ("commit",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, commit_text),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, G_TYPE_STRING);
+  signals[DELETE_SURROUNDING] =
+    g_signal_new ("delete-surrounding",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, delete_surrounding),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+  signals[REQUEST_SURROUNDING] =
+    g_signal_new ("request-surrounding",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, request_surrounding),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+  signals[SET_PREEDIT_TEXT] =
+    g_signal_new ("set-preedit-text",
+                  CLUTTER_TYPE_INPUT_FOCUS,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterInputFocusInterface, set_preedit_text),
+                  NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_UINT);
+}
+
+void
+clutter_input_focus_reset (ClutterInputFocus *focus)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) != focus)
+    return;
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (method)->reset (method);
+}
+
+void
+clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
+                                         const ClutterRect *rect)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) != focus)
+    return;
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (method)->set_cursor_location (method, rect);
+}
+
+void
+clutter_input_focus_set_surrounding (ClutterInputFocus *focus,
+                                     const gchar       *text,
+                                     guint              cursor,
+                                     guint              anchor)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) != focus)
+    return;
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (method)->set_surrounding (method, text, cursor, anchor);
+}
+
+void
+clutter_input_focus_set_content_hints (ClutterInputFocus            *focus,
+                                       ClutterInputContentHintFlags  hints)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) != focus)
+    return;
+
+  g_object_set (G_OBJECT (method), "content-hints", hints, NULL);
+}
+
+void
+clutter_input_focus_set_content_purpose (ClutterInputFocus          *focus,
+                                         ClutterInputContentPurpose  purpose)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) != focus)
+    return;
+
+  g_object_set (G_OBJECT (method), "content-purpose", purpose, NULL);
+}
+
+void
+clutter_input_focus_focus_in (ClutterInputFocus *focus)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  clutter_input_method_focus_in (method, focus);
+}
+
+void
+clutter_input_focus_focus_out (ClutterInputFocus *focus)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  if (clutter_input_method_get_focus (method) == focus)
+    clutter_input_method_focus_out (method);
+}
+
+gboolean
+clutter_input_focus_filter_key_event (ClutterInputFocus     *focus,
+                                      const ClutterKeyEvent *key)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  g_return_val_if_fail (CLUTTER_IS_INPUT_METHOD (method), FALSE);
+
+  if (clutter_event_get_flags ((ClutterEvent *) key) & CLUTTER_EVENT_FLAG_INPUT_METHOD)
+    return FALSE;
+
+  if (clutter_input_method_get_focus (method) == focus)
+    {
+      ClutterInputMethodClass *im_class = CLUTTER_INPUT_METHOD_GET_CLASS (method);
+
+      if (im_class->filter_key_event)
+        return im_class->filter_key_event (method, (const ClutterEvent *) key);
+    }
+
+  return FALSE;
+}
+
+void
+clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
+                                          gboolean           can_show_preedit)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  if (clutter_input_method_get_focus (method) == focus)
+    g_object_set (G_OBJECT (method), "can-show-preedit", can_show_preedit, NULL);
+}
+
+void
+clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus)
+{
+  ClutterBackend *backend = clutter_get_default_backend ();
+  ClutterInputMethod *method = clutter_backend_get_input_method (backend);
+
+  if (clutter_input_method_get_focus (method) == focus)
+    {
+      g_signal_emit_by_name (method, "input-panel-state",
+                             CLUTTER_INPUT_PANEL_STATE_TOGGLE);
+    }
+}
diff --git a/clutter/clutter/clutter-input-focus.h b/clutter/clutter/clutter-input-focus.h
new file mode 100644
index 0000000..dd5b140
--- /dev/null
+++ b/clutter/clutter/clutter-input-focus.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __CLUTTER_INPUT_FOCUS_H__
+#define __CLUTTER_INPUT_FOCUS_H__
+
+#include <clutter/clutter.h>
+
+#define CLUTTER_TYPE_INPUT_FOCUS (clutter_input_focus_get_type ())
+
+CLUTTER_AVAILABLE_IN_MUTTER
+G_DECLARE_INTERFACE (ClutterInputFocus, clutter_input_focus,
+                     CLUTTER, INPUT_FOCUS, GObject)
+
+typedef struct _ClutterInputFocusInterface ClutterInputFocusInterface;
+
+struct _ClutterInputFocusInterface
+{
+  GTypeInterface iface;
+
+  void (* focus_in)  (ClutterInputFocus  *focus,
+                      ClutterInputMethod *input_method);
+  void (* focus_out) (ClutterInputFocus  *focus);
+
+  void (* request_surrounding) (ClutterInputFocus *focus);
+  void (* delete_surrounding)  (ClutterInputFocus *focus,
+                                guint              offset,
+                                guint              len);
+  void (* commit_text) (ClutterInputFocus *focus,
+                        const gchar       *text);
+
+  void (* set_preedit_text) (ClutterInputFocus *focus,
+                             const gchar       *preedit,
+                             guint              cursor);
+};
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_focus_in  (ClutterInputFocus *focus);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_focus_out (ClutterInputFocus *focus);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_reset (ClutterInputFocus *focus);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
+                                              const ClutterRect *rect);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_set_surrounding (ClutterInputFocus *focus,
+                                          const gchar       *text,
+                                          guint              cursor,
+                                          guint              anchor);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_set_content_hints (ClutterInputFocus            *focus,
+                                            ClutterInputContentHintFlags  hint);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_set_content_purpose (ClutterInputFocus          *focus,
+                                              ClutterInputContentPurpose  purpose);
+CLUTTER_AVAILABLE_IN_MUTTER
+gboolean clutter_input_focus_filter_key_event (ClutterInputFocus     *focus,
+                                               const ClutterKeyEvent *key);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
+                                               gboolean           can_show_preedit);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus);
+
+#endif /* __CLUTTER_INPUT_FOCUS_H__ */
diff --git a/clutter/clutter/clutter-input-method.c b/clutter/clutter/clutter-input-method.c
new file mode 100644
index 0000000..a73d520
--- /dev/null
+++ b/clutter/clutter/clutter-input-method.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#include "clutter-build-config.h"
+
+#include "clutter-private.h"
+#include "clutter/clutter-input-method.h"
+
+typedef struct _ClutterInputMethodPrivate ClutterInputMethodPrivate;
+
+struct _ClutterInputMethodPrivate
+{
+  ClutterInputFocus *focus;
+  ClutterInputContentHintFlags content_hints;
+  ClutterInputContentPurpose content_purpose;
+  gboolean can_show_preedit;
+};
+
+enum {
+  COMMIT,
+  DELETE_SURROUNDING,
+  REQUEST_SURROUNDING,
+  INPUT_PANEL_STATE,
+  N_SIGNALS,
+};
+
+enum {
+  PROP_0,
+  PROP_CONTENT_HINTS,
+  PROP_CONTENT_PURPOSE,
+  PROP_CAN_SHOW_PREEDIT,
+  N_PROPS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+static GParamSpec *pspecs[N_PROPS] = { 0 };
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputMethod, clutter_input_method, G_TYPE_OBJECT)
+
+static void
+set_content_hints (ClutterInputMethod           *method,
+                   ClutterInputContentHintFlags  content_hints)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (method);
+  priv->content_hints = content_hints;
+  CLUTTER_INPUT_METHOD_GET_CLASS (method)->update_content_hints (method,
+                                                                 content_hints);
+}
+
+static void
+set_content_purpose (ClutterInputMethod         *method,
+                     ClutterInputContentPurpose  content_purpose)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (method);
+  priv->content_purpose = content_purpose;
+  CLUTTER_INPUT_METHOD_GET_CLASS (method)->update_content_purpose (method,
+                                                                   content_purpose);
+}
+
+static void
+set_can_show_preedit (ClutterInputMethod *method,
+                      gboolean            can_show_preedit)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (method);
+  priv->can_show_preedit = can_show_preedit;
+}
+
+static void
+clutter_input_method_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+                                   GParamSpec   *pspec)
+{
+  switch (prop_id)
+    {
+    case PROP_CONTENT_HINTS:
+      set_content_hints (CLUTTER_INPUT_METHOD (object),
+                         g_value_get_flags (value));
+      break;
+    case PROP_CONTENT_PURPOSE:
+      set_content_purpose (CLUTTER_INPUT_METHOD (object),
+                           g_value_get_enum (value));
+      break;
+    case PROP_CAN_SHOW_PREEDIT:
+      set_can_show_preedit (CLUTTER_INPUT_METHOD (object),
+                            g_value_get_boolean (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+clutter_input_method_get_property (GObject    *object,
+                                   guint       prop_id,
+                                   GValue     *value,
+                                   GParamSpec *pspec)
+{
+  ClutterInputMethodPrivate *priv;
+  ClutterInputMethod *method;
+
+  method = CLUTTER_INPUT_METHOD (object);
+  priv = clutter_input_method_get_instance_private (method);
+
+  switch (prop_id)
+    {
+    case PROP_CONTENT_HINTS:
+      g_value_set_flags (value, priv->content_hints);
+      break;
+    case PROP_CONTENT_PURPOSE:
+      g_value_set_enum (value, priv->content_purpose);
+      break;
+    case PROP_CAN_SHOW_PREEDIT:
+      g_value_set_boolean (value, priv->can_show_preedit);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+clutter_input_method_class_init (ClutterInputMethodClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = clutter_input_method_set_property;
+  object_class->get_property = clutter_input_method_get_property;
+
+  signals[COMMIT] =
+    g_signal_new ("commit",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, G_TYPE_STRING);
+  signals[DELETE_SURROUNDING] =
+    g_signal_new ("delete-surrounding",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
+  signals[REQUEST_SURROUNDING] =
+    g_signal_new ("request-surrounding",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 0);
+  signals[INPUT_PANEL_STATE] =
+    g_signal_new ("input-panel-state",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1,
+                  CLUTTER_TYPE_INPUT_PANEL_STATE);
+
+  pspecs[PROP_CONTENT_HINTS] =
+    g_param_spec_flags ("content-hints",
+                        P_("Content hints"),
+                        P_("Content hints"),
+                        CLUTTER_TYPE_INPUT_CONTENT_HINT_FLAGS, 0,
+                        G_PARAM_READWRITE |
+                        G_PARAM_STATIC_STRINGS);
+  pspecs[PROP_CONTENT_PURPOSE] =
+    g_param_spec_enum ("content-purpose",
+                       P_("Content purpose"),
+                       P_("Content purpose"),
+                       CLUTTER_TYPE_INPUT_CONTENT_PURPOSE, 0,
+                       G_PARAM_READWRITE |
+                       G_PARAM_STATIC_STRINGS);
+  pspecs[PROP_CAN_SHOW_PREEDIT] =
+    g_param_spec_boolean ("can-show-preedit",
+                          P_("Can show preedit"),
+                          P_("Can show preedit"),
+                          FALSE,
+                          G_PARAM_READWRITE |
+                          G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, N_PROPS, pspecs);
+}
+
+static void
+clutter_input_method_init (ClutterInputMethod *method)
+{
+}
+
+void
+clutter_input_method_focus_in (ClutterInputMethod *method,
+                               ClutterInputFocus  *focus)
+{
+  ClutterInputMethodPrivate *priv;
+  ClutterInputMethodClass *klass;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  priv = clutter_input_method_get_instance_private (method);
+
+  if (priv->focus == focus)
+    return;
+
+  if (priv->focus)
+    clutter_input_method_focus_out (method);
+
+  g_set_object (&priv->focus, focus);
+
+  if (focus)
+    {
+      klass = CLUTTER_INPUT_METHOD_GET_CLASS (method);
+      klass->focus_in (method, focus);
+
+      g_signal_emit_by_name (priv->focus, "focus-in", method);
+    }
+}
+
+void
+clutter_input_method_focus_out (ClutterInputMethod *method)
+{
+  ClutterInputMethodPrivate *priv;
+  ClutterInputMethodClass *klass;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  priv = clutter_input_method_get_instance_private (method);
+
+  if (!priv->focus)
+    return;
+
+  g_signal_emit_by_name (priv->focus, "focus-out");
+  g_clear_object (&priv->focus);
+
+  klass = CLUTTER_INPUT_METHOD_GET_CLASS (method);
+  klass->focus_out (method);
+
+  g_signal_emit (method, signals[INPUT_PANEL_STATE],
+                 0, CLUTTER_INPUT_PANEL_STATE_OFF);
+}
+
+/**
+ * clutter_input_method_get_focus:
+ * @method: the #ClutterInputMethod
+ *
+ * Retrieves the current focus of the input method, or %NULL
+ * if there is none.
+ *
+ * Returns: (transfer none) (nullable): the current focus
+ **/
+ClutterInputFocus *
+clutter_input_method_get_focus (ClutterInputMethod *method)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (method);
+  return priv->focus;
+}
+
+void
+clutter_input_method_commit (ClutterInputMethod *method,
+                             const gchar        *text)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  priv = clutter_input_method_get_instance_private (method);
+  if (priv->focus)
+    g_signal_emit_by_name (priv->focus, "commit", text);
+}
+
+void
+clutter_input_method_delete_surrounding (ClutterInputMethod *method,
+                                         guint               offset,
+                                         guint               len)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  priv = clutter_input_method_get_instance_private (method);
+  if (priv->focus)
+    g_signal_emit_by_name (priv->focus, "delete-surrounding", offset, len);
+}
+
+void
+clutter_input_method_request_surrounding (ClutterInputMethod *method)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  priv = clutter_input_method_get_instance_private (method);
+  if (priv->focus)
+    g_signal_emit_by_name (priv->focus, "request-surrounding");
+}
+
+/**
+ * clutter_input_method_set_preedit_text:
+ * @method: a #ClutterInputMethod
+ * @preedit: (nullable): the preedit text, or %NULL
+ *
+ * Sets the preedit text on the current input focus.
+ **/
+void
+clutter_input_method_set_preedit_text (ClutterInputMethod *method,
+                                       const gchar        *preedit,
+                                       guint               cursor)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (method));
+
+  priv = clutter_input_method_get_instance_private (method);
+  if (priv->focus)
+    g_signal_emit_by_name (priv->focus, "set-preedit-text", preedit, cursor);
+}
+
+void
+clutter_input_method_notify_key_event (ClutterInputMethod *method,
+                                       const ClutterEvent *event,
+                                       gboolean            filtered)
+{
+  if (!filtered)
+    {
+      ClutterEvent *copy;
+
+      /* XXX: we rely on the IM implementation to notify back of
+       * key events in the exact same order they were given.
+       */
+      copy = clutter_event_copy (event);
+      clutter_event_set_flags (copy, clutter_event_get_flags (event) |
+                               CLUTTER_EVENT_FLAG_INPUT_METHOD);
+      clutter_event_put (copy);
+      clutter_event_free (copy);
+    }
+}
diff --git a/clutter/clutter/clutter-input-method.h b/clutter/clutter/clutter-input-method.h
new file mode 100644
index 0000000..5c39810
--- /dev/null
+++ b/clutter/clutter/clutter-input-method.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef __CLUTTER_INPUT_METHOD_H__
+#define __CLUTTER_INPUT_METHOD_H__
+
+#include <clutter/clutter.h>
+
+#define CLUTTER_TYPE_INPUT_METHOD (clutter_input_method_get_type ())
+
+CLUTTER_AVAILABLE_IN_MUTTER
+G_DECLARE_DERIVABLE_TYPE (ClutterInputMethod, clutter_input_method,
+                          CLUTTER, INPUT_METHOD, GObject)
+
+typedef struct _ClutterInputMethodClass ClutterInputMethodClass;
+
+struct _ClutterInputMethodClass
+{
+  GObjectClass parent_class;
+
+  void (* focus_in) (ClutterInputMethod *method,
+                     ClutterInputFocus  *actor);
+  void (* focus_out) (ClutterInputMethod *method);
+
+  void (* reset) (ClutterInputMethod *method);
+
+  void (* set_cursor_location) (ClutterInputMethod          *method,
+                                const ClutterRect           *rect);
+  void (* set_surrounding) (ClutterInputMethod *method,
+                            const gchar        *text,
+                            guint               cursor,
+                            guint               anchor);
+  void (* update_content_hints) (ClutterInputMethod           *method,
+                                 ClutterInputContentHintFlags  hint);
+  void (* update_content_purpose) (ClutterInputMethod         *method,
+                                   ClutterInputContentPurpose  purpose);
+
+  gboolean (* filter_key_event) (ClutterInputMethod *method,
+                                 const ClutterEvent *key);
+};
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_focus_in  (ClutterInputMethod *method,
+                                     ClutterInputFocus  *focus);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_focus_out (ClutterInputMethod *method);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+ClutterInputFocus * clutter_input_method_get_focus (ClutterInputMethod *method);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_commit (ClutterInputMethod *method,
+                                  const gchar        *text);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_delete_surrounding (ClutterInputMethod *method,
+                                              guint               offset,
+                                              guint               len);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_request_surrounding (ClutterInputMethod *method);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_set_preedit_text (ClutterInputMethod *method,
+                                            const gchar        *preedit,
+                                            guint               cursor);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_notify_key_event (ClutterInputMethod *method,
+                                            const ClutterEvent *event,
+                                            gboolean            filtered);
+
+#endif /* __CLUTTER_INPUT_METHOD_H__ */
diff --git a/clutter/clutter/clutter-types.h b/clutter/clutter/clutter-types.h
index bc71c7d..d7f3dfb 100644
--- a/clutter/clutter/clutter-types.h
+++ b/clutter/clutter/clutter-types.h
@@ -97,6 +97,9 @@ typedef struct _ClutterInputDeviceTool          ClutterInputDeviceTool;
 typedef struct _ClutterInputDevice              ClutterInputDevice;
 typedef struct _ClutterVirtualInputDevice       ClutterVirtualInputDevice;
 
+typedef struct _ClutterInputMethod              ClutterInputMethod;
+typedef struct _ClutterInputFocus               ClutterInputFocus;
+
 typedef CoglMatrix                              ClutterMatrix;
 
 typedef union _ClutterEvent                     ClutterEvent;
diff --git a/clutter/clutter/clutter.h b/clutter/clutter/clutter.h
index cdf54ac..721e30e 100644
--- a/clutter/clutter/clutter.h
+++ b/clutter/clutter/clutter.h
@@ -72,6 +72,8 @@
 #include "clutter-image.h"
 #include "clutter-input-device.h"
 #include "clutter-input-device-tool.h"
+#include "clutter-input-method.h"
+#include "clutter-input-focus.h"
 #include "clutter-interval.h"
 #include "clutter-keyframe-transition.h"
 #include "clutter-keysyms.h"


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