From fae87e8d3d4e69f40b6c3e51ea2c8c8477995857 Mon Sep 17 00:00:00 2001 From: Jon Trowbridge Date: Thu, 1 Mar 2001 20:59:42 +0000 Subject: Boost version number to 0.5.99.3. 2001-03-01 Jon Trowbridge * configure.in: Boost version number to 0.5.99.3. * gal/e-text/e-entry.c (e_entry_show_popup): Grab pointer when the popup is visible, and then hide the popup if any button press events occur outside of the popup. This lets up avoid most of the worst "floating popup" cases that would occur if windows are moved, desktops changed, etc. with the mouse. (Doing things like changing desktop w/ keybindings can still cause a "floating popup", but that is also true of Gtk's own combo box.) Change popup positioning to slightly offset it from the entry, rather than just plopping it down directly below. (button_press_cb): Determine if a button press occured outside of the popup when the pointer was grabbed, and unbrowse accordingly. * gal/e-text/e-completion-view.c (e_completion_view_key_press_handler): Improve keystroke handling. Allow Tabs to pass through (after hiding the pop-up) in order to allow focus change requests to work properly. (e_completion_view_construct): Disable horizontal scrollbars. * gal/e-text/e-completion-test.c (main): Reworked to use signals instead of explicit callbacks. * gal/e-text/e-completion.h: * gal/e-text/e-completion.c: Fix the awkward mix of signals and explicitly-specified callbacks by taking out the explicit callbacks. This approach is more gtk-ish, after all. svn path=/trunk/; revision=8458 --- widgets/text/e-completion-test.c | 18 +++++++++-- widgets/text/e-completion-view.c | 33 ++++++++++---------- widgets/text/e-completion.c | 64 ++++++++++----------------------------- widgets/text/e-completion.h | 10 +++---- widgets/text/e-entry.c | 65 +++++++++++++++++++++++++--------------- 5 files changed, 91 insertions(+), 99 deletions(-) (limited to 'widgets') diff --git a/widgets/text/e-completion-test.c b/widgets/text/e-completion-test.c index 0d846ec9ff..3172cecb13 100644 --- a/widgets/text/e-completion-test.c +++ b/widgets/text/e-completion-test.c @@ -134,7 +134,7 @@ begin_dict_search (ECompletion *complete, const gchar *txt, gint pos, gint limit } static void -end_dict_search (ECompletion *complete, gboolean finished, gpointer foo) +end_dict_search (ECompletion *complete, gpointer user_data) { if (dict_tag != 0) { gtk_timeout_remove (dict_tag); @@ -153,11 +153,23 @@ main (int argc, gchar **argv) read_dict (); - complete = e_completion_new (begin_dict_search, end_dict_search, NULL); + complete = e_completion_new (); + gtk_signal_connect (GTK_OBJECT (complete), + "begin_completion", + GTK_SIGNAL_FUNC (begin_dict_search), + NULL); + gtk_signal_connect (GTK_OBJECT (complete), + "end_completion", + GTK_SIGNAL_FUNC (end_dict_search), + NULL); + gtk_signal_connect (GTK_OBJECT (complete), + "cancel_completion", + GTK_SIGNAL_FUNC (end_dict_search), + NULL); win = gtk_window_new (GTK_WINDOW_TOPLEVEL); entry = e_entry_new (); - e_entry_enable_completion_full (E_ENTRY (entry), complete, 100, NULL); + e_entry_enable_completion_full (E_ENTRY (entry), complete, -1, NULL); e_entry_set_editable (E_ENTRY (entry), TRUE); gtk_container_add (GTK_CONTAINER (win), entry); diff --git a/widgets/text/e-completion-view.c b/widgets/text/e-completion-view.c index e2352ec7a9..825e7c5e11 100644 --- a/widgets/text/e-completion-view.c +++ b/widgets/text/e-completion-view.c @@ -305,6 +305,7 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin { ECompletionView *cv = E_COMPLETION_VIEW (user_data); gint dir = 0; + gboolean key_handled = TRUE; /* Start up a completion.*/ if (cv->complete_key && key_event->keyval == cv->complete_key && !cv->editable) { @@ -332,13 +333,18 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin case GDK_KP_Up: dir = -1; break; + + case GDK_Tab: + /* Unbrowse, unhandled. */ + cv->selection = -1; + dir = 0; + key_handled = FALSE; + break; case GDK_Return: case GDK_KP_Enter: case GDK_space: case GDK_KP_Space: - case GDK_Right: /* Lynx-style "forward" */ - case GDK_KP_Right: /* Only handle these key presses if we have an active selection; otherwise, pass them on. */ if (cv->selection >= 0) { @@ -353,17 +359,6 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin dir = 0; break; - case GDK_Left: /* Lynx-style "back" */ - case GDK_KP_Left: - if (cv->selection >= 0) { - /* A hack to "unbrowse" us on these keys if we are browsing. */ - cv->selection = -1; - dir = 0; - break; - } - - return FALSE; - default: return FALSE; } @@ -385,13 +380,14 @@ e_completion_view_key_press_handler (GtkWidget *w, GdkEventKey *key_event, gpoin gtk_signal_emit (GTK_OBJECT (cv), e_completion_view_signals[E_COMPLETION_VIEW_UNBROWSE]); stop_emission: - gtk_signal_emit_stop_by_name (GTK_OBJECT (w), "key_press_event"); + if (key_handled) + gtk_signal_emit_stop_by_name (GTK_OBJECT (w), "key_press_event"); - return TRUE; + return key_handled; } static void -begin_completion_cb (ECompletion *completion, gpointer user_data) +begin_completion_cb (ECompletion *completion, const gchar *txt, gint pos, gint limit, gpointer user_data) { ECompletionView *cv = E_COMPLETION_VIEW (user_data); @@ -405,7 +401,7 @@ static void restart_completion_cb (ECompletion *completion, gpointer user_data) { /* For now, handle restarts like the beginning of a new completion. */ - begin_completion_cb (completion, user_data); + begin_completion_cb (completion, NULL, 0, 0, user_data); } static void @@ -557,6 +553,8 @@ e_completion_view_construct (ECompletionView *cv, ECompletion *completion) cv->table = e_table_scrolled_new (cv->model, NULL, simple_spec, NULL); + e_scroll_frame_set_policy (E_SCROLL_FRAME (cv->table), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); + frame = gtk_frame_new (NULL); gtk_container_add (GTK_CONTAINER (cv), frame); @@ -655,6 +653,7 @@ e_completion_view_set_width (ECompletionView *cv, gint width) e_table_group_compute_location (e_completion_view_table (cv)->group, &dummy, &line_height, &r, &dummy); } + if (line_height >= 1000) { /* Something went wrong, so we make a (possibly very lame) guess */ line_height = 30; diff --git a/widgets/text/e-completion.c b/widgets/text/e-completion.c index 8b875c7af6..bf12d6a365 100644 --- a/widgets/text/e-completion.c +++ b/widgets/text/e-completion.c @@ -50,11 +50,6 @@ struct _Match { }; struct _ECompletionPrivate { - - ECompletionBeginFn begin_search; - ECompletionEndFn end_search; - gpointer user_data; - gboolean searching; gchar *search_text; gint pos; @@ -115,8 +110,9 @@ e_completion_class_init (ECompletionClass *klass) GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (ECompletionClass, begin_completion), - gtk_marshal_NONE__NONE, - GTK_TYPE_NONE, 0); + gtk_marshal_NONE__POINTER_INT_INT, + GTK_TYPE_NONE, 3, + GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT); e_completion_signals[E_COMPLETION_COMPLETION] = gtk_signal_new ("completion", @@ -259,26 +255,17 @@ e_completion_begin_search (ECompletion *complete, const gchar *text, gint pos, g if (complete->priv->searching) e_completion_cancel_search (complete); - /* Without one of these, we can't search! */ - if (complete->priv->begin_search) { - - g_free (complete->priv->search_text); - complete->priv->search_text = g_strdup (text); - - complete->priv->pos = pos; - - complete->priv->searching = TRUE; + g_free (complete->priv->search_text); + complete->priv->search_text = g_strdup (text); - e_completion_clear_matches (complete); + complete->priv->pos = pos; + complete->priv->searching = TRUE; - complete->priv->limit = limit > 0 ? limit : G_MAXINT; + e_completion_clear_matches (complete); - gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_BEGIN_COMPLETION]); - complete->priv->begin_search (complete, text, pos, limit, complete->priv->user_data); - return; - } + complete->priv->limit = limit > 0 ? limit : G_MAXINT; - g_warning ("Unable to search for \"%s\" - no virtual method specified.", text); + gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_BEGIN_COMPLETION], text, pos, limit); } void @@ -291,12 +278,9 @@ e_completion_cancel_search (ECompletion *complete) if (!complete->priv->searching) return; - if (complete->priv->end_search) - complete->priv->end_search (complete, FALSE, complete->priv->user_data); + gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_CANCEL_COMPLETION]); complete->priv->searching = FALSE; - - gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_CANCEL_COMPLETION]); } gboolean @@ -369,25 +353,10 @@ e_completion_find_extra_data (ECompletion *complete, const gchar *text) return NULL; } -void -e_completion_construct (ECompletion *complete, ECompletionBeginFn begin_fn, ECompletionEndFn end_fn, gpointer user_data) -{ - g_return_if_fail (complete != NULL); - g_return_if_fail (E_IS_COMPLETION (complete)); - - complete->priv->begin_search = begin_fn; - complete->priv->end_search = end_fn; - complete->priv->user_data = user_data; -} - ECompletion * -e_completion_new (ECompletionBeginFn begin_fn, ECompletionEndFn end_fn, gpointer user_data) +e_completion_new (void) { - ECompletion *complete = E_COMPLETION (gtk_type_new (e_completion_get_type ())); - - e_completion_construct (complete, begin_fn, end_fn, user_data); - - return complete; + return E_COMPLETION (gtk_type_new (e_completion_get_type ())); } static gint @@ -501,11 +470,8 @@ e_completion_end_search (ECompletion *complete) if (e_completion_sort_by_score (complete)) e_completion_restart (complete); - if (complete->priv->end_search) - complete->priv->end_search (complete, TRUE, complete->priv->user_data); - - complete->priv->searching = FALSE; - gtk_signal_emit (GTK_OBJECT (complete), e_completion_signals[E_COMPLETION_END_COMPLETION]); + + complete->priv->searching = FALSE; } diff --git a/widgets/text/e-completion.h b/widgets/text/e-completion.h index 41be79a927..e101d6aa55 100644 --- a/widgets/text/e-completion.h +++ b/widgets/text/e-completion.h @@ -43,8 +43,6 @@ typedef struct _ECompletion ECompletion; typedef struct _ECompletionClass ECompletionClass; struct _ECompletionPrivate; -typedef void (*ECompletionBeginFn) (ECompletion *, const gchar *text, gint pos, gint limit, gpointer user_data); -typedef void (*ECompletionEndFn) (ECompletion *, gboolean finished, gpointer user_data); typedef void (*ECompletionMatchFn) (const gchar *text, double score, gpointer extra_data, gpointer user_data); struct _ECompletion { @@ -57,8 +55,8 @@ struct _ECompletionClass { GtkObjectClass parent_class; /* Signals */ - void (*begin_completion) (ECompletion *comp); - void (*completion) (ECompletion *comp, const gchar *text, gpointer extra_data); + void (*begin_completion) (ECompletion *comp, const gchar *search_text, gint pos, gint limit); + void (*completion) (ECompletion *comp, const gchar *match_text, gpointer extra_data); void (*restart_completion) (ECompletion *comp); void (*cancel_completion) (ECompletion *comp); void (*end_completion) (ECompletion *comp); @@ -76,8 +74,7 @@ gint e_completion_match_count (ECompletion *comp); void e_completion_foreach_match (ECompletion *comp, ECompletionMatchFn fn, gpointer user_data); gpointer e_completion_find_extra_data (ECompletion *comp, const gchar *text); -void e_completion_construct (ECompletion *comp, ECompletionBeginFn, ECompletionEndFn, gpointer user_data); -ECompletion *e_completion_new (ECompletionBeginFn, ECompletionEndFn, gpointer user_data); +ECompletion *e_completion_new (void); @@ -93,3 +90,4 @@ END_GNOME_DECLS #endif /* E_COMPLETION_H */ + diff --git a/widgets/text/e-entry.c b/widgets/text/e-entry.c index 07fddb6b87..8116895e1c 100644 --- a/widgets/text/e-entry.c +++ b/widgets/text/e-entry.c @@ -116,6 +116,7 @@ struct _EEntryPrivate { gchar *pre_browse_text; gint completion_delay; guint completion_delay_tag; + gboolean ptr_grab; guint draw_borders : 1; }; @@ -200,8 +201,8 @@ e_entry_proxy_changed (EText *text, EEntry *entry) e_entry_cancel_delayed_completion (entry); e_entry_show_popup (entry, FALSE); } else if (entry->priv->popup_is_visible) - e_entry_start_completion (entry); - else if (entry->priv->completion && entry->priv->completion_delay >= 0) + e_entry_start_delayed_completion (entry, 1); + else if (entry->priv->completion) e_entry_start_delayed_completion (entry, entry->priv->completion_delay); gtk_signal_emit (GTK_OBJECT (entry), e_entry_signals [E_ENTRY_CHANGED]); @@ -261,7 +262,7 @@ e_entry_init (GtkObject *object) /* * Proxy functions: we proxy the changed and activate signals - * from the item to outselves + * from the item to ourselves */ entry->priv->changed_proxy_tag = gtk_signal_connect (GTK_OBJECT (entry->priv->item), "changed", @@ -272,7 +273,7 @@ e_entry_init (GtkObject *object) GTK_SIGNAL_FUNC (e_entry_proxy_activate), entry); - entry->priv->completion_delay = -1; + entry->priv->completion_delay = 1; } /** @@ -406,27 +407,45 @@ e_entry_show_popup (EEntry *entry, gboolean visible) if (visible) { GtkAllocation *dim = &(GTK_WIDGET (entry)->allocation); - gint x, y; + gint x, y, fudge; + const GdkEventMask grab_mask = (GdkEventMask)GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK; /* Figure out where to put our popup. */ gdk_window_get_origin (GTK_WIDGET (entry)->window, &x, &y); x += dim->x; y += dim->height + dim->y; + /* Put our popup slightly to the right and up, to try to give a visual cue that this popup + is tied to this entry. Otherwise one-row popups can sort of "blend" with an entry + directly below. */ + fudge = MAX (dim->height/10, 3); /* just in case we are using a really big font, etc. */ + x += 2*fudge; + y -= fudge; + gtk_widget_set_uposition (pop, x, y); e_completion_view_set_width (E_COMPLETION_VIEW (entry->priv->completion_view), dim->width); gtk_widget_show (pop); - gdk_keyboard_grab (GTK_WIDGET (entry)->window, TRUE, GDK_CURRENT_TIME); - gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE, - (GdkEventMask) GDK_BUTTON_PRESS_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_RELEASE_MASK, - NULL, NULL, GDK_CURRENT_TIME); - + + + if (! entry->priv->ptr_grab) { + entry->priv->ptr_grab = gdk_pointer_grab (GTK_WIDGET (entry->priv->completion_view)->window, TRUE, + grab_mask, NULL, NULL, GDK_CURRENT_TIME); + if (entry->priv->ptr_grab) + gtk_grab_add (GTK_WIDGET (entry->priv->completion_view)); + } + } else { gtk_widget_hide (pop); - gdk_keyboard_ungrab (GDK_CURRENT_TIME); - gdk_pointer_ungrab (GDK_CURRENT_TIME); + + if (entry->priv->ptr_grab) { + gdk_pointer_ungrab (GDK_CURRENT_TIME); + gtk_grab_remove (GTK_WIDGET (entry->priv->completion_view)); + } + + entry->priv->ptr_grab = FALSE; + } @@ -452,11 +471,10 @@ e_entry_start_completion (EEntry *entry) if (e_entry_is_empty (entry)) return; - if (entry->priv->completion) - e_completion_begin_search (entry->priv->completion, - e_entry_get_text (entry), - e_entry_get_position (entry), - 0); /* No limit. Probably a bad idea. */ + e_completion_begin_search (entry->priv->completion, + e_entry_get_text (entry), + e_entry_get_position (entry), + 0); /* No limit. Probably a bad idea. */ } static gboolean @@ -475,11 +493,7 @@ e_entry_start_delayed_completion (EEntry *entry, gint delay) return; e_entry_cancel_delayed_completion (entry); - - if (delay == 0) - e_entry_start_completion (entry); - else - entry->priv->completion_delay_tag = gtk_timeout_add (delay, start_delayed_cb, entry); + entry->priv->completion_delay_tag = gtk_timeout_add (MAX (delay, 1), start_delayed_cb, entry); } static void @@ -488,7 +502,6 @@ e_entry_cancel_delayed_completion (EEntry *entry) if (entry->priv->completion == NULL) return; - e_completion_cancel_search (entry->priv->completion); /* just to be sure... */ if (entry->priv->completion_delay_tag) { gtk_timeout_remove (entry->priv->completion_delay_tag); entry->priv->completion_delay_tag = 0; @@ -599,7 +612,8 @@ button_press_cb (GtkWidget *w, GdkEvent *ev, gpointer user_data) } } - e_entry_show_popup (entry, FALSE); + /* Treat this as an unbrowse */ + unbrowse_cb (E_COMPLETION_VIEW (w), entry); } void @@ -976,6 +990,9 @@ e_entry_destroy (GtkObject *object) gtk_widget_destroy (entry->priv->completion_view_popup); g_free (entry->priv->pre_browse_text); + if (entry->priv->ptr_grab) + gdk_pointer_ungrab (GDK_CURRENT_TIME); + g_free (entry->priv); entry->priv = NULL; } -- cgit v1.2.3