[mutter] clutter: Add ClutterInputMethod and ClutterInputFocus



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

    clutter: Add ClutterInputMethod and ClutterInputFocus
    
    ClutterInputFocus is an abstract object to be subclassed by UI actors and
    the wayland interface and represents the user of an input method. It
    represents the current focus of the input method, so all emitted signals
    and public API hooks are expected to be called when the input method is
    currently interfacing with the input focus.
    
    ClutterInputMethod is an abstract class (to be implemented in the upper
    layers) that represents the input method itself. Besides focus management
    itself, all public API calls that would be called by the subclasses are
    delivered through the current input focus.

 clutter/clutter/Makefile.am                    |    6 +
 clutter/clutter/clutter-enums.h                |   35 ++
 clutter/clutter/clutter-input-focus-private.h  |   40 +++
 clutter/clutter/clutter-input-focus.c          |  243 +++++++++++++
 clutter/clutter/clutter-input-focus.h          |   83 +++++
 clutter/clutter/clutter-input-method-private.h |   46 +++
 clutter/clutter/clutter-input-method.c         |  442 ++++++++++++++++++++++++
 clutter/clutter/clutter-input-method.h         |   88 +++++
 clutter/clutter/clutter-types.h                |    1 +
 clutter/clutter/clutter.h                      |    2 +
 10 files changed, 986 insertions(+), 0 deletions(-)
---
diff --git a/clutter/clutter/Makefile.am b/clutter/clutter/Makefile.am
index 8fbd993..c4576c0 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   \
@@ -229,6 +233,8 @@ source_h_priv = \
        clutter-flatten-effect.h                \
        clutter-gesture-action-private.h        \
        clutter-id-pool.h                       \
+       clutter-input-focus-private.h           \
+       clutter-input-method-private.h          \
        clutter-master-clock.h                  \
        clutter-master-clock-default.h          \
        clutter-offscreen-effect-private.h      \
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-private.h b/clutter/clutter/clutter-input-focus-private.h
new file mode 100644
index 0000000..563e589
--- /dev/null
+++ b/clutter/clutter/clutter-input-focus-private.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2017,2018 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_PRIVATE_H__
+#define __CLUTTER_INPUT_FOCUS_PRIVATE_H__
+
+void clutter_input_focus_focus_in  (ClutterInputFocus  *focus,
+                                    ClutterInputMethod *method);
+void clutter_input_focus_focus_out (ClutterInputFocus  *focus);
+
+void clutter_input_focus_commit (ClutterInputFocus *focus,
+                                 const gchar       *text);
+void clutter_input_focus_delete_surrounding (ClutterInputFocus *focus,
+                                             guint              offset,
+                                             guint              len);
+void clutter_input_focus_request_surrounding (ClutterInputFocus *focus);
+
+void clutter_input_focus_set_preedit_text (ClutterInputFocus *focus,
+                                           const gchar       *preedit,
+                                           guint              cursor);
+
+#endif /* __CLUTTER_INPUT_FOCUS_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-input-focus.c b/clutter/clutter/clutter-input-focus.c
new file mode 100644
index 0000000..51381ac
--- /dev/null
+++ b/clutter/clutter/clutter-input-focus.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (C) 2017,2018 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"
+#include "clutter/clutter-input-focus-private.h"
+#include "clutter/clutter-input-method-private.h"
+
+typedef struct _ClutterInputFocusPrivate ClutterInputFocusPrivate;
+
+struct _ClutterInputFocusPrivate
+{
+  ClutterInputMethod *im;
+};
+
+G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (ClutterInputFocus, clutter_input_focus, G_TYPE_OBJECT)
+
+static void
+clutter_input_focus_real_focus_in (ClutterInputFocus  *focus,
+                                   ClutterInputMethod *im)
+{
+  ClutterInputFocusPrivate *priv;
+
+  priv = clutter_input_focus_get_instance_private (focus);
+  priv->im = im;
+}
+
+static void
+clutter_input_focus_real_focus_out (ClutterInputFocus  *focus)
+{
+  ClutterInputFocusPrivate *priv;
+
+  priv = clutter_input_focus_get_instance_private (focus);
+  priv->im = NULL;
+}
+
+static void
+clutter_input_focus_class_init (ClutterInputFocusClass *klass)
+{
+  klass->focus_in = clutter_input_focus_real_focus_in;
+  klass->focus_out = clutter_input_focus_real_focus_out;
+}
+
+static void
+clutter_input_focus_init (ClutterInputFocus *focus)
+{
+}
+
+gboolean
+clutter_input_focus_is_focused (ClutterInputFocus *focus)
+{
+  ClutterInputFocusPrivate *priv;
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  return !!priv->im;
+}
+
+void
+clutter_input_focus_reset (ClutterInputFocus *focus)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_reset (priv->im);
+}
+
+void
+clutter_input_focus_set_cursor_location (ClutterInputFocus *focus,
+                                         const ClutterRect *rect)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_set_cursor_location (priv->im, rect);
+}
+
+void
+clutter_input_focus_set_surrounding (ClutterInputFocus *focus,
+                                     const gchar       *text,
+                                     guint              cursor,
+                                     guint              anchor)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_set_surrounding (priv->im, text, cursor, anchor);
+}
+
+void
+clutter_input_focus_set_content_hints (ClutterInputFocus            *focus,
+                                       ClutterInputContentHintFlags  hints)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_set_content_hints (priv->im, hints);
+}
+
+void
+clutter_input_focus_set_content_purpose (ClutterInputFocus          *focus,
+                                         ClutterInputContentPurpose  purpose)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_set_content_purpose (priv->im, purpose);
+}
+
+gboolean
+clutter_input_focus_filter_key_event (ClutterInputFocus     *focus,
+                                      const ClutterKeyEvent *key)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_val_if_fail (CLUTTER_IS_INPUT_FOCUS (focus), FALSE);
+  g_return_val_if_fail (clutter_input_focus_is_focused (focus), FALSE);
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  return clutter_input_method_filter_key_event (priv->im, key);
+}
+
+void
+clutter_input_focus_set_can_show_preedit (ClutterInputFocus *focus,
+                                          gboolean           can_show_preedit)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_set_can_show_preedit (priv->im, can_show_preedit);
+}
+
+void
+clutter_input_focus_request_toggle_input_panel (ClutterInputFocus *focus)
+{
+  ClutterInputFocusPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (clutter_input_focus_is_focused (focus));
+
+  priv = clutter_input_focus_get_instance_private (focus);
+
+  clutter_input_method_toggle_input_panel (priv->im);
+}
+
+void
+clutter_input_focus_focus_in (ClutterInputFocus  *focus,
+                              ClutterInputMethod *im)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->focus_in (focus, im);
+}
+
+void
+clutter_input_focus_focus_out (ClutterInputFocus  *focus)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->focus_out (focus);
+}
+
+void
+clutter_input_focus_commit (ClutterInputFocus *focus,
+                            const gchar       *text)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->commit_text (focus, text);
+}
+
+void
+clutter_input_focus_delete_surrounding (ClutterInputFocus *focus,
+                                        guint              offset,
+                                        guint              len)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->delete_surrounding (focus, offset, len);
+}
+
+void
+clutter_input_focus_request_surrounding (ClutterInputFocus *focus)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->request_surrounding (focus);
+}
+
+void
+clutter_input_focus_set_preedit_text (ClutterInputFocus *focus,
+                                      const gchar       *preedit,
+                                      guint              cursor)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  CLUTTER_INPUT_FOCUS_GET_CLASS (focus)->set_preedit_text (focus, preedit, cursor);
+}
diff --git a/clutter/clutter/clutter-input-focus.h b/clutter/clutter/clutter-input-focus.h
new file mode 100644
index 0000000..a31521f
--- /dev/null
+++ b/clutter/clutter/clutter-input-focus.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017,2018 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_DERIVABLE_TYPE (ClutterInputFocus, clutter_input_focus,
+                          CLUTTER, INPUT_FOCUS, GObject)
+
+struct _ClutterInputFocusClass
+{
+  GObjectClass parent_class;
+  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
+gboolean clutter_input_focus_is_focused (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-private.h b/clutter/clutter/clutter-input-method-private.h
new file mode 100644
index 0000000..e8ab2ca
--- /dev/null
+++ b/clutter/clutter/clutter-input-method-private.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017,2018 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_PRIVATE_H__
+#define __CLUTTER_INPUT_METHOD_PRIVATE_H__
+
+ClutterInputFocus * clutter_input_method_get_focus (ClutterInputMethod *method);
+
+void clutter_input_method_reset               (ClutterInputMethod *method);
+
+void clutter_input_method_set_cursor_location (ClutterInputMethod *method,
+                                               const ClutterRect  *rect);
+void clutter_input_method_set_surrounding     (ClutterInputMethod *method,
+                                               const gchar        *text,
+                                               guint               cursor,
+                                               guint               anchor);
+void clutter_input_method_set_content_hints   (ClutterInputMethod           *method,
+                                               ClutterInputContentHintFlags  hints);
+void clutter_input_method_set_content_purpose (ClutterInputMethod         *method,
+                                               ClutterInputContentPurpose  purpose);
+void clutter_input_method_set_can_show_preedit (ClutterInputMethod *method,
+                                                gboolean            can_show_preedit);
+gboolean clutter_input_method_filter_key_event (ClutterInputMethod    *method,
+                                                const ClutterKeyEvent *key);
+
+void clutter_input_method_toggle_input_panel (ClutterInputMethod *method);
+
+#endif /* __CLUTTER_INPUT_METHOD_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-input-method.c b/clutter/clutter/clutter-input-method.c
new file mode 100644
index 0000000..5c14620
--- /dev/null
+++ b/clutter/clutter/clutter-input-method.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright (C) 2017,2018 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"
+#include "clutter/clutter-input-method-private.h"
+#include "clutter/clutter-input-focus-private.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,
+  CURSOR_LOCATION_CHANGED,
+  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           *im,
+                   ClutterInputContentHintFlags  content_hints)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (im);
+  priv->content_hints = content_hints;
+  CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_hints (im, content_hints);
+}
+
+static void
+set_content_purpose (ClutterInputMethod         *im,
+                     ClutterInputContentPurpose  content_purpose)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (im);
+  priv->content_purpose = content_purpose;
+  CLUTTER_INPUT_METHOD_GET_CLASS (im)->update_content_purpose (im,
+                                                               content_purpose);
+}
+
+static void
+set_can_show_preedit (ClutterInputMethod *im,
+                      gboolean            can_show_preedit)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (im);
+  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 *im;
+
+  im = CLUTTER_INPUT_METHOD (object);
+  priv = clutter_input_method_get_instance_private (im);
+
+  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);
+  signals[CURSOR_LOCATION_CHANGED] =
+    g_signal_new ("cursor-location-changed",
+                  G_TYPE_FROM_CLASS (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  0, NULL, NULL, NULL,
+                  G_TYPE_NONE, 1, CLUTTER_TYPE_RECT);
+
+  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 *im)
+{
+}
+
+void
+clutter_input_method_focus_in (ClutterInputMethod *im,
+                               ClutterInputFocus  *focus)
+{
+  ClutterInputMethodPrivate *priv;
+  ClutterInputMethodClass *klass;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+  g_return_if_fail (CLUTTER_IS_INPUT_FOCUS (focus));
+
+  priv = clutter_input_method_get_instance_private (im);
+
+  if (priv->focus == focus)
+    return;
+
+  if (priv->focus)
+    clutter_input_method_focus_out (im);
+
+  g_set_object (&priv->focus, focus);
+
+  if (focus)
+    {
+      klass = CLUTTER_INPUT_METHOD_GET_CLASS (im);
+      klass->focus_in (im, focus);
+
+      clutter_input_focus_focus_in (priv->focus, im);
+    }
+}
+
+void
+clutter_input_method_focus_out (ClutterInputMethod *im)
+{
+  ClutterInputMethodPrivate *priv;
+  ClutterInputMethodClass *klass;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  priv = clutter_input_method_get_instance_private (im);
+
+  if (!priv->focus)
+    return;
+
+  clutter_input_focus_focus_out (priv->focus);
+  g_clear_object (&priv->focus);
+
+  klass = CLUTTER_INPUT_METHOD_GET_CLASS (im);
+  klass->focus_out (im);
+
+  g_signal_emit (im, signals[INPUT_PANEL_STATE],
+                 0, CLUTTER_INPUT_PANEL_STATE_OFF);
+}
+
+ClutterInputFocus *
+clutter_input_method_get_focus (ClutterInputMethod *im)
+{
+  ClutterInputMethodPrivate *priv;
+
+  priv = clutter_input_method_get_instance_private (im);
+  return priv->focus;
+}
+
+void
+clutter_input_method_commit (ClutterInputMethod *im,
+                             const gchar        *text)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  priv = clutter_input_method_get_instance_private (im);
+  if (priv->focus)
+    clutter_input_focus_commit (priv->focus, text);
+}
+
+void
+clutter_input_method_delete_surrounding (ClutterInputMethod *im,
+                                         guint               offset,
+                                         guint               len)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  priv = clutter_input_method_get_instance_private (im);
+  if (priv->focus)
+    clutter_input_focus_delete_surrounding (priv->focus, offset, len);
+}
+
+void
+clutter_input_method_request_surrounding (ClutterInputMethod *im)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  priv = clutter_input_method_get_instance_private (im);
+  if (priv->focus)
+    clutter_input_focus_request_surrounding (priv->focus);
+}
+
+/**
+ * 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 *im,
+                                       const gchar        *preedit,
+                                       guint               cursor)
+{
+  ClutterInputMethodPrivate *priv;
+
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  priv = clutter_input_method_get_instance_private (im);
+  if (priv->focus)
+    clutter_input_focus_set_preedit_text (priv->focus, preedit, cursor);
+}
+
+void
+clutter_input_method_notify_key_event (ClutterInputMethod *im,
+                                       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);
+    }
+}
+
+void
+clutter_input_method_toggle_input_panel (ClutterInputMethod *im)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  g_signal_emit (im, signals[INPUT_PANEL_STATE], 0,
+                 CLUTTER_INPUT_PANEL_STATE_TOGGLE);
+}
+
+void
+clutter_input_method_reset (ClutterInputMethod *im)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (im)->reset (im);
+}
+
+void
+clutter_input_method_set_cursor_location (ClutterInputMethod *im,
+                                          const ClutterRect  *rect)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (im)->set_cursor_location (im, rect);
+
+  g_signal_emit (im, signals[CURSOR_LOCATION_CHANGED], 0, rect);
+}
+
+void
+clutter_input_method_set_surrounding (ClutterInputMethod *im,
+                                      const gchar        *text,
+                                      guint               cursor,
+                                      guint               anchor)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  CLUTTER_INPUT_METHOD_GET_CLASS (im)->set_surrounding (im, text,
+                                                        cursor, anchor);
+}
+
+void
+clutter_input_method_set_content_hints (ClutterInputMethod           *im,
+                                        ClutterInputContentHintFlags  hints)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  g_object_set (G_OBJECT (im), "content-hints", hints, NULL);
+}
+
+void
+clutter_input_method_set_content_purpose (ClutterInputMethod         *im,
+                                          ClutterInputContentPurpose  purpose)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  g_object_set (G_OBJECT (im), "content-purpose", purpose, NULL);
+}
+
+void
+clutter_input_method_set_can_show_preedit (ClutterInputMethod *im,
+                                           gboolean            can_show_preedit)
+{
+  g_return_if_fail (CLUTTER_IS_INPUT_METHOD (im));
+
+  g_object_set (G_OBJECT (im), "can-show-preedit", can_show_preedit, NULL);
+}
+
+gboolean
+clutter_input_method_filter_key_event (ClutterInputMethod    *im,
+                                       const ClutterKeyEvent *key)
+{
+  ClutterInputMethodClass *im_class = CLUTTER_INPUT_METHOD_GET_CLASS (im);
+
+  g_return_val_if_fail (CLUTTER_IS_INPUT_METHOD (im), FALSE);
+  g_return_val_if_fail (key != NULL, FALSE);
+
+  if (clutter_event_get_flags ((ClutterEvent *) key) & CLUTTER_EVENT_FLAG_INPUT_METHOD)
+    return FALSE;
+  if (!im_class->filter_key_event)
+    return FALSE;
+
+  return im_class->filter_key_event (im, (const ClutterEvent *) key);
+}
diff --git a/clutter/clutter/clutter-input-method.h b/clutter/clutter/clutter-input-method.h
new file mode 100644
index 0000000..d37522d
--- /dev/null
+++ b/clutter/clutter/clutter-input-method.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017,2018 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 *im,
+                     ClutterInputFocus  *actor);
+  void (* focus_out) (ClutterInputMethod *im);
+
+  void (* reset) (ClutterInputMethod *im);
+
+  void (* set_cursor_location) (ClutterInputMethod          *im,
+                                const ClutterRect           *rect);
+  void (* set_surrounding) (ClutterInputMethod *im,
+                            const gchar        *text,
+                            guint               cursor,
+                            guint               anchor);
+  void (* update_content_hints) (ClutterInputMethod           *im,
+                                 ClutterInputContentHintFlags  hint);
+  void (* update_content_purpose) (ClutterInputMethod         *im,
+                                   ClutterInputContentPurpose  purpose);
+
+  gboolean (* filter_key_event) (ClutterInputMethod *im,
+                                 const ClutterEvent *key);
+};
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_focus_in  (ClutterInputMethod *im,
+                                     ClutterInputFocus  *focus);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_focus_out (ClutterInputMethod *im);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_commit (ClutterInputMethod *im,
+                                  const gchar        *text);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_delete_surrounding (ClutterInputMethod *im,
+                                              guint               offset,
+                                              guint               len);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_request_surrounding (ClutterInputMethod *im);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_set_preedit_text (ClutterInputMethod *im,
+                                            const gchar        *preedit,
+                                            guint               cursor);
+
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_notify_key_event (ClutterInputMethod *im,
+                                            const ClutterEvent *event,
+                                            gboolean            filtered);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_input_method_request_toggle_input_panel (ClutterInputMethod *im);
+
+#endif /* __CLUTTER_INPUT_METHOD_H__ */
diff --git a/clutter/clutter/clutter-types.h b/clutter/clutter/clutter-types.h
index 4d5b018..d7f3dfb 100644
--- a/clutter/clutter/clutter-types.h
+++ b/clutter/clutter/clutter-types.h
@@ -98,6 +98,7 @@ typedef struct _ClutterInputDevice              ClutterInputDevice;
 typedef struct _ClutterVirtualInputDevice       ClutterVirtualInputDevice;
 
 typedef struct _ClutterInputMethod              ClutterInputMethod;
+typedef struct _ClutterInputFocus               ClutterInputFocus;
 
 typedef CoglMatrix                              ClutterMatrix;
 
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]