Bug 83935 – GtkEntry's default invisible char should be U+25CF

2008-09-19  Carlos Garnacho  <carlos@imendio.com>

        Bug 83935 – GtkEntry's default invisible char should be U+25CF

        * gtk/gtkentry.c (find_invisible_char) (gtk_entry_init): Find a
        more suitable invisible char than '*' based on the used font.
        (gtk_entry_class_init) (gtk_entry_set_property)
        (gtk_entry_get_property): Add a "invisible-char-set" property.
        (gtk_entry_unset_invisible_char): New function, needed now that the
        default invisible char isn't fixed.
        * gtk/gtkentry.h:
        * gtk/gtk.symbols:
        * docs/reference/gtk/gtk-sections.txt: Add the new function.

svn path=/trunk/; revision=21446
This commit is contained in:
Carlos Garnacho 2008-09-19 13:45:07 +00:00 committed by Carlos Garnacho
parent 34b3bb8c5f
commit ee06ce951b
5 changed files with 144 additions and 10 deletions

View File

@ -1,3 +1,17 @@
2008-09-19 Carlos Garnacho <carlos@imendio.com>
Bug 83935 GtkEntry's default invisible char should be U+25CF
* gtk/gtkentry.c (find_invisible_char) (gtk_entry_init): Find a
more suitable invisible char than '*' based on the used font.
(gtk_entry_class_init) (gtk_entry_set_property)
(gtk_entry_get_property): Add a "invisible-char-set" property.
(gtk_entry_unset_invisible_char): New function, needed now that the
default invisible char isn't fixed.
* gtk/gtkentry.h:
* gtk/gtk.symbols:
* docs/reference/gtk/gtk-sections.txt: Add the new function.
2008-09-19 Christian Persch <chpe@gnome.org> 2008-09-19 Christian Persch <chpe@gnome.org>
Bug 552837 mem leak in gtkimmulticontext Bug 552837 mem leak in gtkimmulticontext

View File

@ -1228,6 +1228,7 @@ gtk_entry_get_text_length
gtk_entry_select_region gtk_entry_select_region
gtk_entry_set_visibility gtk_entry_set_visibility
gtk_entry_set_invisible_char gtk_entry_set_invisible_char
gtk_entry_unset_invisible_char
gtk_entry_set_editable gtk_entry_set_editable
gtk_entry_set_max_length gtk_entry_set_max_length
gtk_entry_get_activates_default gtk_entry_get_activates_default

View File

@ -1299,6 +1299,7 @@ gtk_entry_set_width_chars
gtk_entry_text_index_to_layout_index gtk_entry_text_index_to_layout_index
gtk_entry_set_cursor_hadjustment gtk_entry_set_cursor_hadjustment
gtk_entry_get_cursor_hadjustment gtk_entry_get_cursor_hadjustment
gtk_entry_unset_invisible_char
#endif #endif
#endif #endif

View File

@ -87,6 +87,7 @@ struct _GtkEntryPrivate
guint blink_time; /* time in msec the cursor has blinked since last user event */ guint blink_time; /* time in msec the cursor has blinked since last user event */
guint interior_focus : 1; guint interior_focus : 1;
guint real_changed : 1; guint real_changed : 1;
guint invisible_char_set : 1;
guint change_count : 8; guint change_count : 8;
gint focus_width; gint focus_width;
@ -135,7 +136,8 @@ enum {
PROP_TRUNCATE_MULTILINE, PROP_TRUNCATE_MULTILINE,
PROP_SHADOW_TYPE, PROP_SHADOW_TYPE,
PROP_OVERWRITE_MODE, PROP_OVERWRITE_MODE,
PROP_TEXT_LENGTH PROP_TEXT_LENGTH,
PROP_INVISIBLE_CHAR_SET
}; };
static guint signals[LAST_SIGNAL] = { 0 }; static guint signals[LAST_SIGNAL] = { 0 };
@ -664,6 +666,20 @@ gtk_entry_class_init (GtkEntryClass *class)
G_MAXUINT16, G_MAXUINT16,
0, 0,
GTK_PARAM_READABLE)); GTK_PARAM_READABLE));
/**
* GtkEntry:invisible-char-set:
*
* Whether the invisible char has been set for the #GtkEntry.
*
* Since: 2.16
*/
g_object_class_install_property (gobject_class,
PROP_INVISIBLE_CHAR_SET,
g_param_spec_boolean ("invisible-char-set",
P_("Invisible char set"),
P_("Whether the invisible char has been set"),
FALSE,
GTK_PARAM_READWRITE));
signals[POPULATE_POPUP] = signals[POPULATE_POPUP] =
g_signal_new (I_("populate-popup"), g_signal_new (I_("populate-popup"),
@ -1063,6 +1079,13 @@ gtk_entry_set_property (GObject *object,
gtk_entry_set_overwrite_mode (entry, g_value_get_boolean (value)); gtk_entry_set_overwrite_mode (entry, g_value_get_boolean (value));
break; break;
case PROP_INVISIBLE_CHAR_SET:
if (g_value_get_boolean (value))
priv->invisible_char_set = TRUE;
else
gtk_entry_unset_invisible_char (entry);
break;
case PROP_SCROLL_OFFSET: case PROP_SCROLL_OFFSET:
case PROP_CURSOR_POSITION: case PROP_CURSOR_POSITION:
default: default:
@ -1133,13 +1156,57 @@ gtk_entry_get_property (GObject *object,
case PROP_TEXT_LENGTH: case PROP_TEXT_LENGTH:
g_value_set_uint (value, entry->text_length); g_value_set_uint (value, entry->text_length);
break; break;
case PROP_INVISIBLE_CHAR_SET:
g_value_set_boolean (value, priv->invisible_char_set);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
static gunichar
find_invisible_char (GtkWidget *widget)
{
PangoLayout *layout;
PangoAttrList *attr_list;
gint i;
gunichar invisible_chars [] = {
0x25cf, /* BLACK CIRCLE */
0x2022, /* BULLET */
0x2731, /* HEAVY ASTERISK */
0x273a /* SIXTEEN POINTED ASTERISK */
};
layout = gtk_widget_create_pango_layout (widget, NULL);
attr_list = pango_attr_list_new ();
pango_attr_list_insert (attr_list, pango_attr_fallback_new (FALSE));
pango_layout_set_attributes (layout, attr_list);
pango_attr_list_unref (attr_list);
for (i = 0; i < G_N_ELEMENTS (invisible_chars); i++)
{
gchar text[7] = { 0, };
gint len, count;
len = g_unichar_to_utf8 (invisible_chars[i], text);
pango_layout_set_text (layout, text, len);
count = pango_layout_get_unknown_glyphs_count (layout);
if (count == 0)
{
g_object_unref (layout);
return invisible_chars[i];
}
}
g_object_unref (layout);
return '*';
}
static void static void
gtk_entry_init (GtkEntry *entry) gtk_entry_init (GtkEntry *entry)
{ {
@ -1153,7 +1220,7 @@ gtk_entry_init (GtkEntry *entry)
entry->editable = TRUE; entry->editable = TRUE;
entry->visible = TRUE; entry->visible = TRUE;
entry->invisible_char = '*'; entry->invisible_char = find_invisible_char (GTK_WIDGET (entry));
entry->dnd_position = -1; entry->dnd_position = -1;
entry->width_chars = -1; entry->width_chars = -1;
entry->is_cell_renderer = FALSE; entry->is_cell_renderer = FALSE;
@ -2441,7 +2508,10 @@ gtk_entry_style_set (GtkWidget *widget,
priv->focus_width = focus_width; priv->focus_width = focus_width;
priv->interior_focus = interior_focus; priv->interior_focus = interior_focus;
if (!priv->invisible_char_set)
entry->invisible_char = find_invisible_char (GTK_WIDGET (entry));
gtk_entry_recompute (entry); gtk_entry_recompute (entry);
if (previous_style && GTK_WIDGET_REALIZED (widget)) if (previous_style && GTK_WIDGET_REALIZED (widget))
@ -4548,8 +4618,9 @@ gtk_entry_set_position (GtkEntry *entry,
* as the invisible char, and will also appear that way when * as the invisible char, and will also appear that way when
* the text in the entry widget is copied elsewhere. * the text in the entry widget is copied elsewhere.
* *
* The default invisible char is the asterisk '*', but it can * By default, GTK+ picks the best invisible character available
* be changed with gtk_entry_set_invisible_char(). * in the current font, but it can be changed with
* gtk_entry_set_invisible_char().
*/ */
void void
gtk_entry_set_visibility (GtkEntry *entry, gtk_entry_set_visibility (GtkEntry *entry,
@ -4615,17 +4686,27 @@ gtk_entry_get_visibility (GtkEntry *entry)
* Sets the character to use in place of the actual text when * Sets the character to use in place of the actual text when
* gtk_entry_set_visibility() has been called to set text visibility * gtk_entry_set_visibility() has been called to set text visibility
* to %FALSE. i.e. this is the character used in "password mode" to * to %FALSE. i.e. this is the character used in "password mode" to
* show the user how many characters have been typed. The default * show the user how many characters have been typed. By default, GTK+
* invisible char is an asterisk ('*'). If you set the invisible char * picks the best invisible char available in the current font. If you
* to 0, then the user will get no feedback at all; there will be * set the invisible char to 0, then the user will get no feedback
* no text on the screen as they type. * at all; there will be no text on the screen as they type.
**/ **/
void void
gtk_entry_set_invisible_char (GtkEntry *entry, gtk_entry_set_invisible_char (GtkEntry *entry,
gunichar ch) gunichar ch)
{ {
GtkEntryPrivate *priv;
g_return_if_fail (GTK_IS_ENTRY (entry)); g_return_if_fail (GTK_IS_ENTRY (entry));
priv = GTK_ENTRY_GET_PRIVATE (entry);
if (!priv->invisible_char_set)
{
priv->invisible_char_set = TRUE;
g_object_notify (G_OBJECT (entry), "invisible-char-set");
}
if (ch == entry->invisible_char) if (ch == entry->invisible_char)
return; return;
@ -4652,6 +4733,42 @@ gtk_entry_get_invisible_char (GtkEntry *entry)
return entry->invisible_char; return entry->invisible_char;
} }
/**
* gtk_entry_unset_invisible_char:
* @entry: a #GtkEntry
*
* Unsets the invisible char previously set with
* gtk_entry_set_invisible_char(). So that the
* default invisible char is used again.
*
* Since: 2.16
**/
void
gtk_entry_unset_invisible_char (GtkEntry *entry)
{
GtkEntryPrivate *priv;
gunichar ch;
g_return_if_fail (GTK_IS_ENTRY (entry));
priv = GTK_ENTRY_GET_PRIVATE (entry);
if (!priv->invisible_char_set)
return;
priv->invisible_char_set = FALSE;
ch = find_invisible_char (GTK_WIDGET (entry));
if (entry->invisible_char != ch)
{
entry->invisible_char = ch;
g_object_notify (G_OBJECT (entry), "invisible-char");
}
g_object_notify (G_OBJECT (entry), "invisible-char-set");
gtk_entry_recompute (entry);
}
/** /**
* gtk_entry_set_editable: * gtk_entry_set_editable:
* @entry: a #GtkEntry * @entry: a #GtkEntry

View File

@ -160,6 +160,7 @@ gboolean gtk_entry_get_visibility (GtkEntry *entry);
void gtk_entry_set_invisible_char (GtkEntry *entry, void gtk_entry_set_invisible_char (GtkEntry *entry,
gunichar ch); gunichar ch);
gunichar gtk_entry_get_invisible_char (GtkEntry *entry); gunichar gtk_entry_get_invisible_char (GtkEntry *entry);
void gtk_entry_unset_invisible_char (GtkEntry *entry);
void gtk_entry_set_has_frame (GtkEntry *entry, void gtk_entry_set_has_frame (GtkEntry *entry,
gboolean setting); gboolean setting);
gboolean gtk_entry_get_has_frame (GtkEntry *entry); gboolean gtk_entry_get_has_frame (GtkEntry *entry);