mirror of
https://github.com/brl/mutter.git
synced 2024-11-28 19:10:43 -05:00
clutter: Make ClutterText implement ClutterInputFocus
This only applies when the actor is editable. Implementing this interface will allow it to interact with the input method.
This commit is contained in:
parent
ca654ac544
commit
d7cb3da324
@ -63,6 +63,7 @@
|
|||||||
#include "clutter-units.h"
|
#include "clutter-units.h"
|
||||||
#include "clutter-paint-volume-private.h"
|
#include "clutter-paint-volume-private.h"
|
||||||
#include "clutter-scriptable.h"
|
#include "clutter-scriptable.h"
|
||||||
|
#include "clutter-input-focus.h"
|
||||||
|
|
||||||
/* cursor width in pixels */
|
/* cursor width in pixels */
|
||||||
#define DEFAULT_CURSOR_SIZE 2
|
#define DEFAULT_CURSOR_SIZE 2
|
||||||
@ -269,6 +270,7 @@ static const ClutterColor default_selected_text_color = { 0, 0, 0, 255 };
|
|||||||
static ClutterAnimatableIface *parent_animatable_iface = NULL;
|
static ClutterAnimatableIface *parent_animatable_iface = NULL;
|
||||||
static ClutterScriptableIface *parent_scriptable_iface = NULL;
|
static ClutterScriptableIface *parent_scriptable_iface = NULL;
|
||||||
|
|
||||||
|
static void clutter_input_focus_iface_init (ClutterInputFocusInterface *iface);
|
||||||
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
static void clutter_scriptable_iface_init (ClutterScriptableIface *iface);
|
||||||
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
|
static void clutter_animatable_iface_init (ClutterAnimatableIface *iface);
|
||||||
|
|
||||||
@ -276,11 +278,91 @@ G_DEFINE_TYPE_WITH_CODE (ClutterText,
|
|||||||
clutter_text,
|
clutter_text,
|
||||||
CLUTTER_TYPE_ACTOR,
|
CLUTTER_TYPE_ACTOR,
|
||||||
G_ADD_PRIVATE (ClutterText)
|
G_ADD_PRIVATE (ClutterText)
|
||||||
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_INPUT_FOCUS,
|
||||||
|
clutter_input_focus_iface_init)
|
||||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE,
|
||||||
clutter_scriptable_iface_init)
|
clutter_scriptable_iface_init)
|
||||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE,
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE,
|
||||||
clutter_animatable_iface_init));
|
clutter_animatable_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_input_focus_request_surrounding (ClutterInputFocus *focus)
|
||||||
|
{
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (focus);
|
||||||
|
ClutterTextBuffer *buffer;
|
||||||
|
const gchar *text;
|
||||||
|
gint anchor_pos, cursor_pos;
|
||||||
|
|
||||||
|
buffer = clutter_text_get_buffer (clutter_text);
|
||||||
|
text = clutter_text_buffer_get_text (buffer);
|
||||||
|
|
||||||
|
cursor_pos = clutter_text_get_cursor_position (clutter_text);
|
||||||
|
if (cursor_pos < 0)
|
||||||
|
cursor_pos = clutter_text_buffer_get_length (buffer);
|
||||||
|
|
||||||
|
anchor_pos = clutter_text_get_selection_bound (clutter_text);
|
||||||
|
if (anchor_pos < 0)
|
||||||
|
anchor_pos = cursor_pos;
|
||||||
|
|
||||||
|
clutter_input_focus_set_surrounding (focus, text,
|
||||||
|
g_utf8_offset_to_pointer (text, cursor_pos) - text,
|
||||||
|
g_utf8_offset_to_pointer (text, anchor_pos) - text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_input_focus_delete_surrounding (ClutterInputFocus *focus,
|
||||||
|
guint offset,
|
||||||
|
guint len)
|
||||||
|
{
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (focus);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
clutter_text_delete_text (clutter_text, offset, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_input_focus_commit_text (ClutterInputFocus *focus,
|
||||||
|
const gchar *text)
|
||||||
|
{
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (focus);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
clutter_text_delete_selection (clutter_text);
|
||||||
|
clutter_text_insert_text (clutter_text, text,
|
||||||
|
clutter_text_get_cursor_position (clutter_text));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_text_input_focus_set_preedit_text (ClutterInputFocus *focus,
|
||||||
|
const gchar *preedit_text,
|
||||||
|
guint cursor_pos)
|
||||||
|
{
|
||||||
|
ClutterText *clutter_text = CLUTTER_TEXT (focus);
|
||||||
|
|
||||||
|
if (clutter_text_get_editable (clutter_text))
|
||||||
|
{
|
||||||
|
PangoAttrList *list;
|
||||||
|
|
||||||
|
list = pango_attr_list_new ();
|
||||||
|
pango_attr_list_insert (list, pango_attr_underline_new (PANGO_UNDERLINE_SINGLE));
|
||||||
|
clutter_text_set_preedit_string (clutter_text,
|
||||||
|
preedit_text, list,
|
||||||
|
cursor_pos);
|
||||||
|
pango_attr_list_unref (list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_input_focus_iface_init (ClutterInputFocusInterface *iface)
|
||||||
|
{
|
||||||
|
iface->request_surrounding = clutter_text_input_focus_request_surrounding;
|
||||||
|
iface->delete_surrounding = clutter_text_input_focus_delete_surrounding;
|
||||||
|
iface->commit_text = clutter_text_input_focus_commit_text;
|
||||||
|
iface->set_preedit_text = clutter_text_input_focus_set_preedit_text;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
clutter_text_dirty_paint_volume (ClutterText *text)
|
clutter_text_dirty_paint_volume (ClutterText *text)
|
||||||
{
|
{
|
||||||
@ -1009,6 +1091,22 @@ clutter_text_position_to_coords (ClutterText *self,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
update_cursor_location (ClutterText *self)
|
||||||
|
{
|
||||||
|
ClutterTextPrivate *priv = self->priv;
|
||||||
|
ClutterRect rect;
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
if (!priv->editable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rect = priv->cursor_rect;
|
||||||
|
clutter_actor_get_transformed_position (CLUTTER_ACTOR (self), &x, &y);
|
||||||
|
clutter_rect_offset (&rect, x, y);
|
||||||
|
clutter_input_focus_set_cursor_location (CLUTTER_INPUT_FOCUS (self), &rect);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
clutter_text_ensure_cursor_position (ClutterText *self)
|
clutter_text_ensure_cursor_position (ClutterText *self)
|
||||||
{
|
{
|
||||||
@ -1057,6 +1155,8 @@ clutter_text_ensure_cursor_position (ClutterText *self)
|
|||||||
g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &cursor_pos);
|
g_signal_emit (self, text_signals[CURSOR_EVENT], 0, &cursor_pos);
|
||||||
|
|
||||||
g_signal_emit (self, text_signals[CURSOR_CHANGED], 0);
|
g_signal_emit (self, text_signals[CURSOR_CHANGED], 0);
|
||||||
|
|
||||||
|
update_cursor_location (self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2085,9 +2185,11 @@ clutter_text_key_press (ClutterActor *actor,
|
|||||||
g_assert (pool != NULL);
|
g_assert (pool != NULL);
|
||||||
|
|
||||||
/* we allow passing synthetic events that only contain
|
/* we allow passing synthetic events that only contain
|
||||||
* the Unicode value and not the key symbol
|
* the Unicode value and not the key symbol, unless they
|
||||||
|
* contain the input method flag.
|
||||||
*/
|
*/
|
||||||
if (event->keyval == 0 && (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC))
|
if (event->keyval == 0 && (event->flags & CLUTTER_EVENT_FLAG_SYNTHETIC) &&
|
||||||
|
!(event->flags & CLUTTER_EVENT_FLAG_INPUT_METHOD))
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
else
|
else
|
||||||
res = clutter_binding_pool_activate (pool, event->keyval,
|
res = clutter_binding_pool_activate (pool, event->keyval,
|
||||||
@ -2105,6 +2207,9 @@ clutter_text_key_press (ClutterActor *actor,
|
|||||||
{
|
{
|
||||||
gunichar key_unichar;
|
gunichar key_unichar;
|
||||||
|
|
||||||
|
if (clutter_input_focus_filter_key_event (CLUTTER_INPUT_FOCUS (actor), event))
|
||||||
|
return CLUTTER_EVENT_STOP;
|
||||||
|
|
||||||
/* Skip keys when control is pressed */
|
/* Skip keys when control is pressed */
|
||||||
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) event);
|
key_unichar = clutter_event_get_key_unicode ((ClutterEvent *) event);
|
||||||
|
|
||||||
@ -2141,6 +2246,16 @@ clutter_text_key_press (ClutterActor *actor,
|
|||||||
return CLUTTER_EVENT_PROPAGATE;
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
clutter_text_key_release (ClutterActor *actor,
|
||||||
|
ClutterKeyEvent *event)
|
||||||
|
{
|
||||||
|
if (clutter_input_focus_filter_key_event (CLUTTER_INPUT_FOCUS (actor), event))
|
||||||
|
return CLUTTER_EVENT_STOP;
|
||||||
|
|
||||||
|
return CLUTTER_EVENT_PROPAGATE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_text_compute_layout_offsets (ClutterText *self,
|
clutter_text_compute_layout_offsets (ClutterText *self,
|
||||||
PangoLayout *layout,
|
PangoLayout *layout,
|
||||||
@ -2664,6 +2779,9 @@ clutter_text_key_focus_in (ClutterActor *actor)
|
|||||||
{
|
{
|
||||||
ClutterTextPrivate *priv = CLUTTER_TEXT (actor)->priv;
|
ClutterTextPrivate *priv = CLUTTER_TEXT (actor)->priv;
|
||||||
|
|
||||||
|
if (priv->editable)
|
||||||
|
clutter_input_focus_focus_in (CLUTTER_INPUT_FOCUS (actor));
|
||||||
|
|
||||||
priv->has_focus = TRUE;
|
priv->has_focus = TRUE;
|
||||||
|
|
||||||
clutter_text_queue_redraw (actor);
|
clutter_text_queue_redraw (actor);
|
||||||
@ -2676,6 +2794,9 @@ clutter_text_key_focus_out (ClutterActor *actor)
|
|||||||
|
|
||||||
priv->has_focus = FALSE;
|
priv->has_focus = FALSE;
|
||||||
|
|
||||||
|
if (priv->editable)
|
||||||
|
clutter_input_focus_focus_out (CLUTTER_INPUT_FOCUS (actor));
|
||||||
|
|
||||||
clutter_text_queue_redraw (actor);
|
clutter_text_queue_redraw (actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3369,6 +3490,7 @@ clutter_text_class_init (ClutterTextClass *klass)
|
|||||||
actor_class->get_preferred_height = clutter_text_get_preferred_height;
|
actor_class->get_preferred_height = clutter_text_get_preferred_height;
|
||||||
actor_class->allocate = clutter_text_allocate;
|
actor_class->allocate = clutter_text_allocate;
|
||||||
actor_class->key_press_event = clutter_text_key_press;
|
actor_class->key_press_event = clutter_text_key_press;
|
||||||
|
actor_class->key_release_event = clutter_text_key_release;
|
||||||
actor_class->button_press_event = clutter_text_button_press;
|
actor_class->button_press_event = clutter_text_button_press;
|
||||||
actor_class->button_release_event = clutter_text_button_release;
|
actor_class->button_release_event = clutter_text_button_release;
|
||||||
actor_class->motion_event = clutter_text_motion;
|
actor_class->motion_event = clutter_text_motion;
|
||||||
@ -4469,6 +4591,11 @@ clutter_text_set_editable (ClutterText *self,
|
|||||||
{
|
{
|
||||||
priv->editable = editable;
|
priv->editable = editable;
|
||||||
|
|
||||||
|
if (!priv->editable)
|
||||||
|
clutter_input_focus_focus_out (CLUTTER_INPUT_FOCUS (self));
|
||||||
|
else if (priv->has_focus)
|
||||||
|
clutter_input_focus_focus_in (CLUTTER_INPUT_FOCUS (self));
|
||||||
|
|
||||||
clutter_text_queue_redraw (CLUTTER_ACTOR (self));
|
clutter_text_queue_redraw (CLUTTER_ACTOR (self));
|
||||||
|
|
||||||
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_EDITABLE]);
|
g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_EDITABLE]);
|
||||||
|
Loading…
Reference in New Issue
Block a user