Compare commits
3 Commits
matthiasc/
...
preedit-hi
Author | SHA1 | Date | |
---|---|---|---|
|
ed851504f0 | ||
|
f9c2b70812 | ||
|
e09d2a676c |
@@ -1005,3 +1005,50 @@ gtk_im_context_set_property (GObject *obj,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PangoAttribute *
|
||||||
|
attr_preedit_properties_copy (const PangoAttribute *attr)
|
||||||
|
{
|
||||||
|
const PangoAttrInt *int_attr = (PangoAttrInt *)attr;
|
||||||
|
|
||||||
|
return gtk_im_context_preedit_attr_new (int_attr->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
attr_preedit_properties_destroy (PangoAttribute *attr)
|
||||||
|
{
|
||||||
|
PangoAttrInt *iattr = (PangoAttrInt *)attr;
|
||||||
|
|
||||||
|
g_slice_free (PangoAttrInt, iattr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
attr_preedit_properties_equal (const PangoAttribute *attr1,
|
||||||
|
const PangoAttribute *attr2)
|
||||||
|
{
|
||||||
|
const PangoAttrInt *int_attr1 = (const PangoAttrInt *)attr1;
|
||||||
|
const PangoAttrInt *int_attr2 = (const PangoAttrInt *)attr2;
|
||||||
|
|
||||||
|
return (int_attr1->value == int_attr2->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
PangoAttribute *
|
||||||
|
gtk_im_context_preedit_attr_new (GtkIMContextPreeditProperties value)
|
||||||
|
{
|
||||||
|
PangoAttrInt *result = g_slice_new (PangoAttrInt);
|
||||||
|
static PangoAttrClass klass = {
|
||||||
|
0,
|
||||||
|
attr_preedit_properties_copy,
|
||||||
|
attr_preedit_properties_destroy,
|
||||||
|
attr_preedit_properties_equal
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!klass.type)
|
||||||
|
klass.type = pango_attr_type_register ("GtkIMContextPreeditProperties");
|
||||||
|
|
||||||
|
pango_attribute_init (&result->attr, &klass);
|
||||||
|
result->value = value;
|
||||||
|
|
||||||
|
return (PangoAttribute *)result;
|
||||||
|
}
|
||||||
|
@@ -168,6 +168,16 @@ gboolean gtk_im_context_delete_surrounding (GtkIMContext *context,
|
|||||||
int offset,
|
int offset,
|
||||||
int n_chars);
|
int n_chars);
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GTK_IM_CONTEXT_PREEDIT_CURSOR,
|
||||||
|
} GtkIMContextPreeditProperties;
|
||||||
|
|
||||||
|
GDK_AVAILABLE_IN_4_8
|
||||||
|
PangoAttribute * gtk_im_context_preedit_attr_new (GtkIMContextPreeditProperties value);
|
||||||
|
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GTK_IM_CONTEXT_H__ */
|
#endif /* __GTK_IM_CONTEXT_H__ */
|
||||||
|
@@ -656,11 +656,10 @@ gtk_im_context_wayland_get_preedit_string (GtkIMContext *context,
|
|||||||
if (context_wayland->current_preedit.cursor_begin
|
if (context_wayland->current_preedit.cursor_begin
|
||||||
!= context_wayland->current_preedit.cursor_end)
|
!= context_wayland->current_preedit.cursor_end)
|
||||||
{
|
{
|
||||||
/* FIXME: Oh noes, how to highlight while taking into account user preferences? */
|
attr = gtk_im_context_preedit_attr_new (GTK_IM_CONTEXT_PREEDIT_CURSOR);
|
||||||
PangoAttribute *cursor = pango_attr_weight_new (PANGO_WEIGHT_BOLD);
|
attr->start_index = context_wayland->current_preedit.cursor_begin;
|
||||||
cursor->start_index = context_wayland->current_preedit.cursor_begin;
|
attr->end_index = context_wayland->current_preedit.cursor_end;
|
||||||
cursor->end_index = context_wayland->current_preedit.cursor_end;
|
pango_attr_list_insert (*attrs, attr);
|
||||||
pango_attr_list_insert (*attrs, cursor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
112
gtk/gtktext.c
112
gtk/gtktext.c
@@ -217,6 +217,8 @@ struct _GtkTextPrivate
|
|||||||
|
|
||||||
guint16 preedit_length; /* length of preedit string, in bytes */
|
guint16 preedit_length; /* length of preedit string, in bytes */
|
||||||
guint16 preedit_cursor; /* offset of cursor within preedit string, in chars */
|
guint16 preedit_cursor; /* offset of cursor within preedit string, in chars */
|
||||||
|
guint16 preedit_highlight_start;
|
||||||
|
guint16 preedit_highlight_end;
|
||||||
|
|
||||||
gint64 handle_place_time;
|
gint64 handle_place_time;
|
||||||
|
|
||||||
@@ -4234,6 +4236,32 @@ gtk_text_commit_cb (GtkIMContext *context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_preedit_highlight (PangoAttrList *attrs,
|
||||||
|
guint16 *start,
|
||||||
|
guint16 *end)
|
||||||
|
{
|
||||||
|
GSList *l, *list = pango_attr_list_get_attributes (attrs);
|
||||||
|
|
||||||
|
*start = *end = 0;
|
||||||
|
|
||||||
|
for (l = list; l; l = l->next)
|
||||||
|
{
|
||||||
|
PangoAttribute *attr = l->data;
|
||||||
|
|
||||||
|
if (pango_attr_type_get_name (attr->klass->type) == g_intern_static_string ("GtkIMContextPreeditProperties"))
|
||||||
|
{
|
||||||
|
*start = attr->start_index;
|
||||||
|
*end = attr->end_index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_slist_free_full (list, (GDestroyNotify) pango_attribute_destroy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_selection_node (GtkText *self);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_text_preedit_changed_cb (GtkIMContext *context,
|
gtk_text_preedit_changed_cb (GtkIMContext *context,
|
||||||
GtkText *self)
|
GtkText *self)
|
||||||
@@ -4243,18 +4271,26 @@ gtk_text_preedit_changed_cb (GtkIMContext *context,
|
|||||||
if (priv->editable)
|
if (priv->editable)
|
||||||
{
|
{
|
||||||
char *preedit_string;
|
char *preedit_string;
|
||||||
|
PangoAttrList *preedit_attrs;
|
||||||
int cursor_pos;
|
int cursor_pos;
|
||||||
|
|
||||||
gtk_text_obscure_mouse_cursor (self);
|
gtk_text_obscure_mouse_cursor (self);
|
||||||
|
|
||||||
gtk_im_context_get_preedit_string (priv->im_context,
|
gtk_im_context_get_preedit_string (priv->im_context,
|
||||||
&preedit_string, NULL,
|
&preedit_string,
|
||||||
|
&preedit_attrs,
|
||||||
&cursor_pos);
|
&cursor_pos);
|
||||||
g_signal_emit (self, signals[PREEDIT_CHANGED], 0, preedit_string);
|
g_signal_emit (self, signals[PREEDIT_CHANGED], 0, preedit_string);
|
||||||
priv->preedit_length = strlen (preedit_string);
|
priv->preedit_length = strlen (preedit_string);
|
||||||
cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
|
cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (preedit_string, -1));
|
||||||
priv->preedit_cursor = cursor_pos;
|
priv->preedit_cursor = cursor_pos;
|
||||||
|
if (priv->preedit_length > 0)
|
||||||
|
get_preedit_highlight (preedit_attrs, &priv->preedit_highlight_start, &priv->preedit_highlight_end);
|
||||||
|
|
||||||
|
update_selection_node (self);
|
||||||
|
|
||||||
g_free (preedit_string);
|
g_free (preedit_string);
|
||||||
|
pango_attr_list_unref (preedit_attrs);
|
||||||
|
|
||||||
gtk_text_recompute (self);
|
gtk_text_recompute (self);
|
||||||
update_placeholder_visibility (self);
|
update_placeholder_visibility (self);
|
||||||
@@ -4329,6 +4365,35 @@ gtk_text_enter_text (GtkText *self,
|
|||||||
priv->need_im_reset = old_need_im_reset;
|
priv->need_im_reset = old_need_im_reset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_selection_node (GtkText *self)
|
||||||
|
{
|
||||||
|
GtkTextPrivate *priv = gtk_text_get_instance_private (self);
|
||||||
|
|
||||||
|
if ((priv->current_pos != priv->selection_bound) ||
|
||||||
|
(priv->preedit_length > 0 && priv->preedit_highlight_start != priv->preedit_highlight_end))
|
||||||
|
{
|
||||||
|
if (!priv->selection_node)
|
||||||
|
{
|
||||||
|
GtkCssNode *widget_node = gtk_widget_get_css_node (GTK_WIDGET (self));
|
||||||
|
|
||||||
|
priv->selection_node = gtk_css_node_new ();
|
||||||
|
gtk_css_node_set_name (priv->selection_node, g_quark_from_static_string ("selection"));
|
||||||
|
gtk_css_node_set_parent (priv->selection_node, widget_node);
|
||||||
|
gtk_css_node_set_state (priv->selection_node, gtk_css_node_get_state (widget_node));
|
||||||
|
g_object_unref (priv->selection_node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (priv->selection_node)
|
||||||
|
{
|
||||||
|
gtk_css_node_set_parent (priv->selection_node, NULL);
|
||||||
|
priv->selection_node = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* All changes to priv->current_pos and priv->selection_bound
|
/* All changes to priv->current_pos and priv->selection_bound
|
||||||
* should go through this function.
|
* should go through this function.
|
||||||
*/
|
*/
|
||||||
@@ -4362,27 +4427,7 @@ gtk_text_set_positions (GtkText *self,
|
|||||||
|
|
||||||
g_object_thaw_notify (G_OBJECT (self));
|
g_object_thaw_notify (G_OBJECT (self));
|
||||||
|
|
||||||
if (priv->current_pos != priv->selection_bound)
|
update_selection_node (self);
|
||||||
{
|
|
||||||
if (!priv->selection_node)
|
|
||||||
{
|
|
||||||
GtkCssNode *widget_node = gtk_widget_get_css_node (GTK_WIDGET (self));
|
|
||||||
|
|
||||||
priv->selection_node = gtk_css_node_new ();
|
|
||||||
gtk_css_node_set_name (priv->selection_node, g_quark_from_static_string ("selection"));
|
|
||||||
gtk_css_node_set_parent (priv->selection_node, widget_node);
|
|
||||||
gtk_css_node_set_state (priv->selection_node, gtk_css_node_get_state (widget_node));
|
|
||||||
g_object_unref (priv->selection_node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (priv->selection_node)
|
|
||||||
{
|
|
||||||
gtk_css_node_set_parent (priv->selection_node, NULL);
|
|
||||||
priv->selection_node = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
{
|
{
|
||||||
@@ -4595,6 +4640,8 @@ gtk_text_draw_text (GtkText *self,
|
|||||||
GtkStyleContext *context;
|
GtkStyleContext *context;
|
||||||
PangoLayout *layout;
|
PangoLayout *layout;
|
||||||
int x, y;
|
int x, y;
|
||||||
|
int start_index, end_index;
|
||||||
|
const char *text;
|
||||||
|
|
||||||
/* Nothing to display at all */
|
/* Nothing to display at all */
|
||||||
if (gtk_text_get_display_mode (self) == DISPLAY_BLANK)
|
if (gtk_text_get_display_mode (self) == DISPLAY_BLANK)
|
||||||
@@ -4602,6 +4649,7 @@ gtk_text_draw_text (GtkText *self,
|
|||||||
|
|
||||||
context = gtk_widget_get_style_context (widget);
|
context = gtk_widget_get_style_context (widget);
|
||||||
layout = gtk_text_ensure_layout (self, TRUE);
|
layout = gtk_text_ensure_layout (self, TRUE);
|
||||||
|
text = pango_layout_get_text (layout);
|
||||||
|
|
||||||
gtk_text_get_layout_offsets (self, &x, &y);
|
gtk_text_get_layout_offsets (self, &x, &y);
|
||||||
|
|
||||||
@@ -4609,9 +4657,23 @@ gtk_text_draw_text (GtkText *self,
|
|||||||
|
|
||||||
if (priv->selection_bound != priv->current_pos)
|
if (priv->selection_bound != priv->current_pos)
|
||||||
{
|
{
|
||||||
const char *text = pango_layout_get_text (layout);
|
start_index = g_utf8_offset_to_pointer (text, priv->selection_bound) - text;
|
||||||
int start_index = g_utf8_offset_to_pointer (text, priv->selection_bound) - text;
|
end_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
|
||||||
int end_index = g_utf8_offset_to_pointer (text, priv->current_pos) - text;
|
}
|
||||||
|
else if (priv->preedit_length > 0)
|
||||||
|
{
|
||||||
|
start_index = end_index = g_utf8_offset_to_pointer (text, priv->selection_bound) - text;
|
||||||
|
start_index += priv->preedit_highlight_start;
|
||||||
|
end_index += priv->preedit_highlight_end;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
start_index = 0;
|
||||||
|
end_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start_index != end_index)
|
||||||
|
{
|
||||||
cairo_region_t *clip;
|
cairo_region_t *clip;
|
||||||
cairo_rectangle_int_t clip_extents;
|
cairo_rectangle_int_t clip_extents;
|
||||||
int range[2];
|
int range[2];
|
||||||
|
Reference in New Issue
Block a user