static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
static GQuark quark_inner_border = 0;
static GQuark quark_password_hint = 0;
+static GQuark quark_cursor_hadjustment = 0;
typedef struct _GtkEntryPrivate GtkEntryPrivate;
gfloat xalign;
gint insert_pos;
guint blink_time; /* time in msec the cursor has blinked since last user event */
- guint real_changed : 1;
- guint change_count : 8;
+ guint interior_focus : 1;
+ guint real_changed : 1;
+ guint change_count : 8;
gint focus_width;
- gboolean interior_focus;
GtkShadowType shadow_type;
-
- GtkAdjustment *cursor_hadjustment;
};
typedef struct _GtkEntryPasswordHint GtkEntryPasswordHint;
quark_inner_border = g_quark_from_static_string ("gtk-entry-inner-border");
quark_password_hint = g_quark_from_static_string ("gtk-entry-password-hint");
+ quark_cursor_hadjustment = g_quark_from_static_string ("gtk-hadjustment");
g_object_class_install_property (gobject_class,
PROP_CURSOR_POSITION,
/**
* GtkSettings:gtk-entry-password-hint-timeout:
*
- * How long to show the last inputted character in hidden
+ * How long to show the last input character in hidden
* entries. This value is in milliseconds. 0 disables showing the
* last char. 600 is a good value for enabling it.
*
*/
gtk_settings_install_property (g_param_spec_uint ("gtk-entry-password-hint-timeout",
P_("Password Hint Timeout"),
- P_("How long to show the last inputted character in hidden entries"),
+ P_("How long to show the last input character in hidden entries"),
0, G_MAXUINT, 0,
GTK_PARAM_READWRITE));
GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
&event->area, widget, "entry_bg",
0, 0, area_width, area_height);
-
- if ((entry->visible || entry->invisible_char != 0) &&
- GTK_WIDGET_HAS_FOCUS (widget) &&
- entry->selection_bound == entry->current_pos && entry->cursor_visible)
- gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
if (entry->dnd_position != -1)
gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_DND);
gtk_entry_draw_text (GTK_ENTRY (widget));
+
+ if ((entry->visible || entry->invisible_char != 0) &&
+ GTK_WIDGET_HAS_FOCUS (widget) &&
+ entry->selection_bound == entry->current_pos && entry->cursor_visible)
+ gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD);
}
return FALSE;
{
GtkEntry *entry = GTK_ENTRY (widget);
GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
+ gint focus_width;
+ gboolean interior_focus;
gtk_widget_style_get (widget,
- "focus-line-width", &priv->focus_width,
- "interior-focus", &priv->interior_focus,
+ "focus-line-width", &focus_width,
+ "interior-focus", &interior_focus,
NULL);
+
+ priv->focus_width = focus_width;
+ priv->interior_focus = interior_focus;
gtk_entry_recompute (entry);
gtk_entry_toggle_overwrite (GtkEntry *entry)
{
entry->overwrite_mode = !entry->overwrite_mode;
+ gtk_entry_pend_cursor_blink (entry);
+ gtk_widget_queue_draw (GTK_WIDGET (entry));
}
static void
entry->text_length -
password_hint->password_hint_position);
- /* Now remove this last inputted character, don't need
+ /* Now remove this last input character, don't need
* it anymore
*/
memset (password_hint->password_hint, 0, PASSWORD_HINT_MAX);
GtkWidget *widget = GTK_WIDGET (entry);
GdkRectangle cursor_location;
gboolean split_cursor;
-
+ PangoRectangle cursor_rect;
GtkBorder inner_border;
gint xoffset;
- gint strong_x, weak_x;
gint text_area_height;
- PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
- PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
- gint x1 = 0;
- gint x2 = 0;
+ gint cursor_index;
+ gboolean block;
+ gboolean block_at_line_end;
_gtk_entry_effective_inner_border (entry, &inner_border);
xoffset = inner_border.left - entry->scroll_offset;
gdk_drawable_get_size (entry->text_area, NULL, &text_area_height);
-
- gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
- g_object_get (gtk_widget_get_settings (widget),
- "gtk-split-cursor", &split_cursor,
- NULL);
+ cursor_index = g_utf8_offset_to_pointer (entry->text, entry->current_pos + entry->preedit_cursor) - entry->text;
+ if (!entry->overwrite_mode)
+ block = FALSE;
+ else
+ block = _gtk_text_util_get_block_cursor_location (gtk_entry_ensure_layout (entry, TRUE),
+ cursor_index, &cursor_rect, &block_at_line_end);
+
+ if (!block)
+ {
+ gint strong_x, weak_x;
+ PangoDirection dir1 = PANGO_DIRECTION_NEUTRAL;
+ PangoDirection dir2 = PANGO_DIRECTION_NEUTRAL;
+ gint x1 = 0;
+ gint x2 = 0;
+
+ gtk_entry_get_cursor_locations (entry, type, &strong_x, &weak_x);
+
+ g_object_get (gtk_widget_get_settings (widget),
+ "gtk-split-cursor", &split_cursor,
+ NULL);
- dir1 = entry->resolved_dir;
+ dir1 = entry->resolved_dir;
- if (split_cursor)
- {
- x1 = strong_x;
+ if (split_cursor)
+ {
+ x1 = strong_x;
- if (weak_x != strong_x)
- {
- dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
- x2 = weak_x;
- }
- }
- else
- {
- if (keymap_direction == entry->resolved_dir)
- x1 = strong_x;
- else
- x1 = weak_x;
- }
+ if (weak_x != strong_x)
+ {
+ dir2 = (entry->resolved_dir == PANGO_DIRECTION_LTR) ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR;
+ x2 = weak_x;
+ }
+ }
+ else
+ {
+ if (keymap_direction == entry->resolved_dir)
+ x1 = strong_x;
+ else
+ x1 = weak_x;
+ }
- cursor_location.x = xoffset + x1;
- cursor_location.y = inner_border.top;
- cursor_location.width = 0;
- cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
+ cursor_location.x = xoffset + x1;
+ cursor_location.y = inner_border.top;
+ cursor_location.width = 0;
+ cursor_location.height = text_area_height - inner_border.top - inner_border.bottom;
- draw_insertion_cursor (entry,
- &cursor_location, TRUE, dir1,
- dir2 != PANGO_DIRECTION_NEUTRAL);
+ draw_insertion_cursor (entry,
+ &cursor_location, TRUE, dir1,
+ dir2 != PANGO_DIRECTION_NEUTRAL);
- if (dir2 != PANGO_DIRECTION_NEUTRAL)
- {
- cursor_location.x = xoffset + x2;
- draw_insertion_cursor (entry,
- &cursor_location, FALSE, dir2,
- TRUE);
- }
+ if (dir2 != PANGO_DIRECTION_NEUTRAL)
+ {
+ cursor_location.x = xoffset + x2;
+ draw_insertion_cursor (entry,
+ &cursor_location, FALSE, dir2,
+ TRUE);
+ }
+ }
+ else /* overwrite_mode */
+ {
+ PangoLayout *layout = gtk_entry_ensure_layout (entry, TRUE);
+ GdkColor cursor_color;
+ GdkRectangle rect;
+ cairo_t *cr;
+ gint x, y;
+
+ get_layout_position (entry, &x, &y);
+
+ rect.x = PANGO_PIXELS (cursor_rect.x) + x;
+ rect.y = PANGO_PIXELS (cursor_rect.y) + y;
+ rect.width = PANGO_PIXELS (cursor_rect.width);
+ rect.height = PANGO_PIXELS (cursor_rect.height);
+
+ cr = gdk_cairo_create (entry->text_area);
+
+ _gtk_widget_get_cursor_color (widget, &cursor_color);
+ gdk_cairo_set_source_color (cr, &cursor_color);
+ gdk_cairo_rectangle (cr, &rect);
+ cairo_fill (cr);
+
+ if (!block_at_line_end)
+ {
+ gdk_cairo_rectangle (cr, &rect);
+ cairo_clip (cr);
+ cairo_move_to (cr, x, y);
+ gdk_cairo_set_source_color (cr, &widget->style->base[widget->state]);
+ pango_cairo_show_layout (cr, layout);
+ }
+
+ cairo_destroy (cr);
+ }
}
}
static void
gtk_entry_move_adjustments (GtkEntry *entry)
{
- GtkEntryPrivate *priv = GTK_ENTRY_GET_PRIVATE (entry);
PangoContext *context;
PangoFontMetrics *metrics;
gint x, layout_x, border_x, border_y;
gint char_width;
+ GtkAdjustment *adjustment;
- if (!priv->cursor_hadjustment)
+ adjustment = g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
+ if (!adjustment)
return;
/* Cursor position, layout offset, border width, and widget allocation */
char_width = pango_font_metrics_get_approximate_char_width (metrics) / PANGO_SCALE;
/* Scroll it */
- gtk_adjustment_clamp_page (priv->cursor_hadjustment,
+ gtk_adjustment_clamp_page (adjustment,
x - (char_width + 1), /* one char + one pixel before */
x + (char_width + 2)); /* one char + cursor + one pixel after */
}
{
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view)));
gtk_tree_selection_unselect_all (gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->action_view)));
+
+ if (completion->priv->inline_selection &&
+ completion->priv->completion_prefix)
+ {
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ }
}
else if (completion->priv->current_selected < matches)
{
return FALSE;
if (completion->priv->completion_prefix == NULL)
- {
- completion->priv->completion_prefix = g_strdup (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)));
- }
-
+ completion->priv->completion_prefix = g_strdup (gtk_entry_get_text (GTK_ENTRY (completion->priv->entry)));
+
g_signal_emit_by_name (completion, "cursor_on_match", model,
&iter, &entry_set);
}
path = gtk_tree_path_new_from_indices (completion->priv->current_selected - matches, -1);
gtk_tree_view_set_cursor (GTK_TREE_VIEW (completion->priv->action_view),
path, NULL, FALSE);
+
+ if (completion->priv->inline_selection &&
+ completion->priv->completion_prefix)
+ {
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ }
}
gtk_tree_path_free (path);
event->keyval == GDK_Right ||
event->keyval == GDK_KP_Right)
{
+ gboolean retval = TRUE;
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
- if (completion->priv->inline_selection)
+ if (completion->priv->current_selected < 0)
+ {
+ retval = FALSE;
+ goto keypress_completion_out;
+ }
+ else if (completion->priv->inline_selection)
{
/* Escape rejects the tentative completion */
if (event->keyval == GDK_Escape)
{
- gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), completion->priv->completion_prefix);
+ if (completion->priv->completion_prefix)
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry),
+ completion->priv->completion_prefix);
+ else
+ gtk_entry_set_text (GTK_ENTRY (completion->priv->entry), "");
}
/* Move the cursor to the end for Right/Esc, to the
gtk_editable_set_position (GTK_EDITABLE (widget), -1);
else
gtk_editable_set_position (GTK_EDITABLE (widget), 0);
+ }
+keypress_completion_out:
+ if (completion->priv->inline_selection)
+ {
g_free (completion->priv->completion_prefix);
completion->priv->completion_prefix = NULL;
}
- return TRUE;
+ return retval;
}
else if (event->keyval == GDK_Tab ||
event->keyval == GDK_KP_Tab ||
{
GtkDirectionType dir = event->keyval == GDK_ISO_Left_Tab ?
GTK_DIR_TAB_BACKWARD : GTK_DIR_TAB_FORWARD;
-
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
- if (completion->priv->completion_prefix)
- {
- g_free (completion->priv->completion_prefix);
- completion->priv->completion_prefix = NULL;
- }
+ g_free (completion->priv->completion_prefix);
+ completion->priv->completion_prefix = NULL;
gtk_widget_child_focus (gtk_widget_get_toplevel (widget), dir);
event->keyval == GDK_KP_Enter ||
event->keyval == GDK_Return)
{
+ gboolean retval = TRUE;
+
_gtk_entry_reset_im_context (GTK_ENTRY (widget));
_gtk_entry_completion_popdown (completion);
gboolean entry_set;
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (completion->priv->tree_view));
- if (!gtk_tree_selection_get_selected (sel, &model, &iter))
- return FALSE;
-
- g_signal_handler_block (widget, completion->priv->changed_id);
- g_signal_emit_by_name (completion, "match_selected",
- model, &iter, &entry_set);
- g_signal_handler_unblock (widget, completion->priv->changed_id);
-
- if (!entry_set)
+ if (gtk_tree_selection_get_selected (sel, &model, &iter))
{
- gchar *str = NULL;
+ g_signal_handler_block (widget, completion->priv->changed_id);
+ g_signal_emit_by_name (completion, "match_selected",
+ model, &iter, &entry_set);
+ g_signal_handler_unblock (widget, completion->priv->changed_id);
- gtk_tree_model_get (model, &iter,
- completion->priv->text_column, &str,
- -1);
+ if (!entry_set)
+ {
+ gchar *str = NULL;
- gtk_entry_set_text (GTK_ENTRY (widget), str);
+ gtk_tree_model_get (model, &iter,
+ completion->priv->text_column, &str,
+ -1);
- /* move the cursor to the end */
- gtk_editable_set_position (GTK_EDITABLE (widget), -1);
+ gtk_entry_set_text (GTK_ENTRY (widget), str);
- g_free (str);
- }
+ /* move the cursor to the end */
+ gtk_editable_set_position (GTK_EDITABLE (widget), -1);
- return TRUE;
+ g_free (str);
+ }
+ }
+ else
+ retval = FALSE;
}
else if (completion->priv->current_selected - matches >= 0)
{
g_signal_emit_by_name (completion, "action_activated",
gtk_tree_path_get_indices (path)[0]);
gtk_tree_path_free (path);
-
- return TRUE;
}
+
+ g_free (completion->priv->completion_prefix);
+ completion->priv->completion_prefix = NULL;
+
+ return retval;
}
return FALSE;
gtk_entry_set_cursor_hadjustment (GtkEntry *entry,
GtkAdjustment *adjustment)
{
- GtkEntryPrivate *priv;
-
g_return_if_fail (GTK_IS_ENTRY (entry));
if (adjustment)
g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
- priv = GTK_ENTRY_GET_PRIVATE (entry);
- if (priv->cursor_hadjustment)
- g_object_unref (priv->cursor_hadjustment);
if (adjustment)
g_object_ref (adjustment);
- priv->cursor_hadjustment = adjustment;
+
+ g_object_set_qdata_full (G_OBJECT (entry),
+ quark_cursor_hadjustment,
+ adjustment,
+ g_object_unref);
}
/**
GtkAdjustment*
gtk_entry_get_cursor_hadjustment (GtkEntry *entry)
{
- GtkEntryPrivate *priv;
-
g_return_val_if_fail (GTK_IS_ENTRY (entry), NULL);
- priv = GTK_ENTRY_GET_PRIVATE (entry);
-
- return priv->cursor_hadjustment;
+ return g_object_get_qdata (G_OBJECT (entry), quark_cursor_hadjustment);
}
#define __GTK_ENTRY_C__