diff options
author | Owen Taylor <otaylor@redhat.com> | 2001-05-30 20:40:28 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2001-05-30 20:40:28 +0000 |
commit | 27bf39f924eb1e9600d574e2f97f0fb0cc2e6495 (patch) | |
tree | 4ca99341dca29756863e53c3a1b0f4c2540c407b /gtk/gtkentry.c | |
parent | 811b03aef1456ce88499896fa0618e219fd533ae (diff) | |
download | gtk+-27bf39f924eb1e9600d574e2f97f0fb0cc2e6495.tar.gz |
Validate value from GDK settings against parameter spec.
Wed May 30 15:56:30 2001 Owen Taylor <otaylor@redhat.com>
* gtk/gtksettings.c (gtk_settings_get_property): Validate
value from GDK settings against parameter spec.
* gdk/x11/gdkevents-x11.c (gdk_setting_get): Add assignments
to temporary values and use g_value_transform(), since
thinking that GValue was going to be easy or efficient
to use was, of course, a mistake.
* gtk/gtksettings.c: Add cursor blink setting.
* gdk/x11/gdkevents-x11.c: Add cursor blink X settings.
* gtk/gtkentry.c: Add cursor blinking.
* gtk/gtktextview.c (gtk_text_view_check_cursor_blink): Use
cursor blink global settings.
* gtk/gtkentry.c (gtk_entry_button_press): Add notification
for :text_position in places where it is missing.
Diffstat (limited to 'gtk/gtkentry.c')
-rw-r--r-- | gtk/gtkentry.c | 279 |
1 files changed, 211 insertions, 68 deletions
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index ccb21525b4..098b6b9ca5 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -40,6 +40,7 @@ #include "gtkmenuitem.h" #include "gtkseparatormenuitem.h" #include "gtkselection.h" +#include "gtksettings.h" #include "gtksignal.h" #include "gtkwindow.h" @@ -219,6 +220,9 @@ static void gtk_entry_preedit_changed_cb (GtkIMContext *context, GtkEntry *entry); /* Internal routines */ +static void gtk_entry_set_positions (GtkEntry *entry, + gint current_pos, + gint selection_bound); static void gtk_entry_draw_text (GtkEntry *entry); static void gtk_entry_draw_cursor (GtkEntry *entry, CursorType type); @@ -257,6 +261,8 @@ static void gtk_entry_do_popup (GtkEntry *entry, GdkEventButton *event); static gboolean gtk_entry_mnemonic_activate (GtkWidget *widget, gboolean group_cycling); +static void gtk_entry_check_cursor_blink (GtkEntry *entry); +static void gtk_entry_pend_cursor_blink (GtkEntry *entry); static GtkWidgetClass *parent_class = NULL; @@ -861,8 +867,8 @@ gtk_entry_finalize (GObject *object) gtk_object_unref (GTK_OBJECT (entry->im_context)); - if (entry->timer) - g_source_remove (entry->timer); + if (entry->blink_timeout) + g_source_remove (entry->blink_timeout); if (entry->recompute_idle) g_source_remove (entry->recompute_idle); @@ -1250,7 +1256,7 @@ gtk_entry_expose (GtkWidget *widget, if ((entry->visible || entry->invisible_char != 0) && GTK_WIDGET_HAS_FOCUS (widget) && - entry->selection_bound == entry->current_pos) + entry->selection_bound == entry->current_pos && entry->cursor_visible) gtk_entry_draw_cursor (GTK_ENTRY (widget), CURSOR_STANDARD); if (entry->dnd_position != -1) @@ -1289,13 +1295,15 @@ gtk_entry_button_press (GtkWidget *widget, if (event->state & GDK_SHIFT_MASK) { + gtk_entry_reset_im_context (entry); + if (!have_selection) /* select from the current position to the clicked position */ sel_start = sel_end = entry->current_pos; if (tmp_pos > sel_start && tmp_pos < sel_end) { /* Truncate current selection */ - entry->current_pos = tmp_pos; + gtk_entry_set_positions (entry, tmp_pos, -1); } else { @@ -1306,7 +1314,7 @@ gtk_entry_button_press (GtkWidget *widget, switch (event->type) { case GDK_BUTTON_PRESS: - entry->current_pos = entry->selection_bound = tmp_pos; + gtk_entry_set_positions (entry, tmp_pos, tmp_pos); break; case GDK_2BUTTON_PRESS: @@ -1333,18 +1341,10 @@ gtk_entry_button_press (GtkWidget *widget, extend_to_left = (end == sel_end); if (extend_to_left) - { - entry->selection_bound = end; - entry->current_pos = start; - } + gtk_entry_set_positions (entry, start, end); else - { - entry->selection_bound = start; - entry->current_pos = end; - } + gtk_entry_set_positions (entry, end, start); } - - gtk_entry_recompute (entry); } else /* no shift key */ switch (event->type) @@ -1361,14 +1361,7 @@ gtk_entry_button_press (GtkWidget *widget, entry->drag_start_y = event->y + entry->scroll_offset; } else - { - gtk_entry_reset_im_context (entry); - - entry->current_pos = tmp_pos; - entry->selection_bound = tmp_pos; - - gtk_entry_recompute (entry); - } + gtk_editable_set_position (editable, tmp_pos); break; @@ -1428,12 +1421,7 @@ gtk_entry_button_release (GtkWidget *widget, { gint tmp_pos = gtk_entry_find_position (entry, entry->drag_start_x); - gtk_entry_reset_im_context (entry); - - entry->current_pos = tmp_pos; - entry->selection_bound = tmp_pos; - - gtk_entry_recompute (entry); + gtk_editable_set_position (GTK_EDITABLE (entry), tmp_pos); entry->in_drag = 0; } @@ -1481,12 +1469,7 @@ gtk_entry_motion_notify (GtkWidget *widget, else { tmp_pos = gtk_entry_find_position (entry, event->x + entry->scroll_offset); - - if (tmp_pos != entry->current_pos) - { - entry->current_pos = tmp_pos; - gtk_entry_recompute (entry); - } + gtk_entry_set_positions (entry, tmp_pos, -1); } return TRUE; @@ -1501,6 +1484,8 @@ gtk_entry_key_press (GtkWidget *widget, if (!entry->editable) return FALSE; + gtk_entry_pend_cursor_blink (entry); + if (gtk_im_context_filter_keypress (entry->im_context, event)) { entry->need_im_reset = TRUE; @@ -1518,17 +1503,16 @@ static gint gtk_entry_focus_in (GtkWidget *widget, GdkEventFocus *event) { - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - + GtkEntry *entry = GTK_ENTRY (widget); + GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS); - gtk_entry_draw_focus (widget); - gtk_entry_queue_draw (GTK_ENTRY (widget)); + gtk_entry_queue_draw (entry); - GTK_ENTRY (widget)->need_im_reset = TRUE; - gtk_im_context_focus_in (GTK_ENTRY (widget)->im_context); + entry->need_im_reset = TRUE; + gtk_im_context_focus_in (entry->im_context); + gtk_entry_check_cursor_blink (entry); + return FALSE; } @@ -1536,17 +1520,16 @@ static gint gtk_entry_focus_out (GtkWidget *widget, GdkEventFocus *event) { - g_return_val_if_fail (widget != NULL, FALSE); - g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - + GtkEntry *entry = GTK_ENTRY (widget); + GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS); - gtk_entry_draw_focus (widget); - gtk_entry_queue_draw (GTK_ENTRY (widget)); + gtk_entry_queue_draw (entry); - GTK_ENTRY (widget)->need_im_reset = TRUE; - gtk_im_context_focus_out (GTK_ENTRY (widget)->im_context); + entry->need_im_reset = TRUE; + gtk_im_context_focus_out (entry->im_context); + gtk_entry_check_cursor_blink (entry); + return FALSE; } @@ -1667,14 +1650,11 @@ gtk_entry_real_set_position (GtkEditable *editable, if (position < 0 || position > entry->text_length) position = entry->text_length; - if (position != entry->current_pos) + if (position != entry->current_pos || + position != entry->selection_bound) { gtk_entry_reset_im_context (entry); - - entry->current_pos = entry->selection_bound = position; - gtk_entry_recompute (entry); - - g_object_notify (G_OBJECT (entry), "text_position"); + gtk_entry_set_positions (entry, position, position); } } @@ -1698,12 +1678,11 @@ gtk_entry_set_selection_bounds (GtkEditable *editable, gtk_entry_reset_im_context (entry); - entry->selection_bound = MIN (start, entry->text_length); - entry->current_pos = MIN (end, entry->text_length); + gtk_entry_set_positions (entry, + MIN (end, entry->text_length), + MIN (start, entry->text_length)); gtk_entry_update_primary_selection (entry); - - gtk_entry_recompute (entry); } static gboolean @@ -1882,6 +1861,8 @@ gtk_entry_move_cursor (GtkEntry *entry, gtk_editable_select_region (GTK_EDITABLE (entry), entry->selection_bound, new_pos); else gtk_editable_set_position (GTK_EDITABLE (entry), new_pos); + + gtk_entry_pend_cursor_blink (entry); } static void @@ -1966,6 +1947,8 @@ gtk_entry_delete_from_cursor (GtkEntry *entry, gtk_entry_delete_whitespace (entry); break; } + + gtk_entry_pend_cursor_blink (entry); } static void @@ -2061,6 +2044,36 @@ gtk_entry_preedit_changed_cb (GtkIMContext *context, /* Internal functions */ +/* All changes to entry->current_pos and entry->selection_bound + * should go through this function. + */ +static void +gtk_entry_set_positions (GtkEntry *entry, + gint current_pos, + gint selection_bound) +{ + gboolean changed = FALSE; + + if (current_pos != -1 && + entry->current_pos != current_pos) + { + entry->current_pos = current_pos; + changed = TRUE; + + g_object_notify (G_OBJECT (entry), "text_position"); + } + + if (selection_bound != -1 && + entry->selection_bound != current_pos) + { + entry->selection_bound = selection_bound; + changed = TRUE; + } + + if (changed) + gtk_entry_recompute (entry); +} + static void gtk_entry_reset_layout (GtkEntry *entry) { @@ -2119,7 +2132,8 @@ static void gtk_entry_recompute (GtkEntry *entry) { gtk_entry_reset_layout (entry); - + gtk_entry_check_cursor_blink (entry); + if (!entry->recompute_idle) { entry->recompute_idle = g_idle_add_full (G_PRIORITY_HIGH_IDLE + 15, /* between resize and redraw */ @@ -2421,12 +2435,7 @@ gtk_entry_queue_draw (GtkEntry *entry) g_return_if_fail (GTK_IS_ENTRY (entry)); if (GTK_WIDGET_REALIZED (entry)) - { - GdkRectangle rect = { 0 }; - - gdk_window_get_size (entry->text_area, &rect.width, &rect.height); - gdk_window_invalidate_rect (entry->text_area, &rect, FALSE); - } + gdk_window_invalidate_rect (entry->text_area, NULL, FALSE); } static void @@ -3483,3 +3492,137 @@ gtk_entry_drag_data_delete (GtkWidget *widget, if (gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end)) gtk_editable_delete_text (editable, sel_start, sel_end); } + +/* We display the cursor when + * + * - the selection is empty, AND + * - the widget has focus + */ + +#define CURSOR_ON_MULTIPLIER 0.66 +#define CURSOR_OFF_MULTIPLIER 0.34 +#define CURSOR_PEND_MULTIPLIER 1.0 + +static gboolean +cursor_blinks (GtkEntry *entry) +{ + GtkSettings *settings = gtk_settings_get_global (); + gboolean blink; + + if (GTK_WIDGET_HAS_FOCUS (entry) && + entry->selection_bound == entry->current_pos) + { + g_object_get (G_OBJECT (settings), "gtk-cursor-blink", &blink, NULL); + return blink; + } + else + return FALSE; +} + +static gint +get_cursor_time (GtkEntry *entry) +{ + GtkSettings *settings = gtk_settings_get_global (); + gint time; + + g_object_get (G_OBJECT (settings), "gtk-cursor-blink-time", &time, NULL); + + return time; +} + +static void +show_cursor (GtkEntry *entry) +{ + if (!entry->cursor_visible) + { + entry->cursor_visible = TRUE; + + if (GTK_WIDGET_HAS_FOCUS (entry) && entry->selection_bound == entry->current_pos) + gtk_widget_queue_draw (GTK_WIDGET (entry)); + } +} + +static void +hide_cursor (GtkEntry *entry) +{ + if (entry->cursor_visible) + { + entry->cursor_visible = FALSE; + + if (GTK_WIDGET_HAS_FOCUS (entry) && entry->selection_bound == entry->current_pos) + gtk_widget_queue_draw (GTK_WIDGET (entry)); + } +} + +/* + * Blink! + */ +static gint +blink_cb (gpointer data) +{ + GtkEntry *entry = GTK_ENTRY (data); + + g_assert (GTK_WIDGET_HAS_FOCUS (entry)); + g_assert (entry->selection_bound == entry->current_pos); + + if (entry->cursor_visible) + { + hide_cursor (entry); + entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_OFF_MULTIPLIER, + blink_cb, + entry); + } + else + { + show_cursor (entry); + entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER, + blink_cb, + entry); + } + + /* Remove ourselves */ + return FALSE; +} + +static void +gtk_entry_check_cursor_blink (GtkEntry *entry) +{ + if (cursor_blinks (entry)) + { + if (!entry->blink_timeout) + { + entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_ON_MULTIPLIER, + blink_cb, + entry); + show_cursor (entry); + } + } + else + { + if (entry->blink_timeout) + { + gtk_timeout_remove (entry->blink_timeout); + entry->blink_timeout = 0; + } + + entry->cursor_visible = TRUE; + } + +} + +static void +gtk_entry_pend_cursor_blink (GtkEntry *entry) +{ + if (cursor_blinks (entry)) + { + if (entry->blink_timeout != 0) + gtk_timeout_remove (entry->blink_timeout); + + entry->blink_timeout = gtk_timeout_add (get_cursor_time (entry) * CURSOR_PEND_MULTIPLIER, + blink_cb, + entry); + show_cursor (entry); + } +} + + |