diff options
author | Tim Janik <timj@gtk.org> | 2001-11-20 23:43:03 +0000 |
---|---|---|
committer | Tim Janik <timj@src.gnome.org> | 2001-11-20 23:43:03 +0000 |
commit | 9800f731e09e28defb46994ae11674d2553f0cc0 (patch) | |
tree | f212fba144769eedf92541cd4dbe9843d24ed97a /gtk/gtkwidget.c | |
parent | 9ea603f15dccb57a8b763fda35b929dbb70914d6 (diff) | |
download | gtk+-9800f731e09e28defb46994ae11674d2553f0cc0.tar.gz |
applied patch from owen to get rid of accel map notifiers. changed things
Tue Nov 20 21:25:08 2001 Tim Janik <timj@gtk.org>
* applied patch from owen to get rid of accel map notifiers.
changed things to fix reentrancy and API as discussed on gtk-devel.
* gtk/gtkaccelgroup.[hc]:
(gtk_accel_group_finalize): unregister this accel group from all
accel map paths.
(accel_closure_invalidate): handle invalidation of closures by
disconnecting their accelerators.
(quick_accel_add): move closure connection and changed notification
into this function to reduce code duplication. don't emit change
notification on closurers without accelerators.
(quick_accel_remove): rewrite, do the exact opposite of quick_accel_add
for a GtkAccelGroupEntry.
(gtk_accel_group_connect): get rid of the accel_path_quark argument.
(gtk_accel_group_connect_by_path): new function to add accelerators
with an accel path.
(gtk_accel_group_disconnect_closure): new function, disconnect a
closure from of an accel group.
(gtk_accel_group_disconnect): loop over all closure for a accel_ley,
accel_mods pair and remove them.
(_gtk_accel_group_reconnect): new function that basically does
gtk_accel_group_disconnect_closure() and
gtk_accel_group_connect_by_path() once an accel path changed.
(gtk_accel_groups_disconnect_closure): remove this, there's
gtk_accel_group_disconnect_closure().
* gtk/gtkaccelmap.[hc]: keep list of accel groups per entry now,
nuke notifiers.
(_gtk_accel_path_is_valid): make this non-static for
gtkwidget.c and gtkaccelgroup.c assertions.
(gtk_accel_map_add_notifer): removed this function.
(gtk_accel_map_remove_notifer): same.
(_gtk_accel_map_add_group):
(_gtk_accel_map_remove_group): (un-)register accel groups, with
accel paths for correct propagation.
(gtk_accel_map_add_entry): return void.
(gtk_accel_map_lookup): return gboolean instead of GQuark.
* gtk/gtkitemfactory.c (gtk_item_factory_add_foreign): always
set accel_path on widgets.
* gtk/gtkwidget.[hc]:
(accel_path_changed): got rid of this, changes are handled by
accel maps internally now.
(_gtk_widget_set_accel_path): get things to work without notifiers.
(gtk_widget_list_accel_closures): list accel closures of a widget.
* gtk/gtkwindow.[hc]: rename ::accels_changed, to ::keys_changed.
Diffstat (limited to 'gtk/gtkwidget.c')
-rw-r--r-- | gtk/gtkwidget.c | 122 |
1 files changed, 49 insertions, 73 deletions
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b65e0d68fe..bb64921cf3 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -2615,6 +2615,8 @@ gtk_widget_add_accelerator (GtkWidget *widget, closure = widget_new_accel_closure (widget, query.signal_id); + g_object_ref (widget); + /* install the accelerator. since we don't map this onto an accel_path, * the accelerator will automatically be locked. */ @@ -2622,10 +2624,11 @@ gtk_widget_add_accelerator (GtkWidget *widget, accel_key, accel_mods, accel_flags | GTK_ACCEL_LOCKED, - closure, - 0); + closure); g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); + + g_object_unref (widget); } /** @@ -2646,24 +2649,31 @@ gtk_widget_remove_accelerator (GtkWidget *widget, guint accel_mods) { GtkAccelGroupEntry *ag_entry; - GSList *slist; - guint n, i; + GList *slist, *clist; + guint n; g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE); ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n); - for (slist = _gtk_widget_get_accel_closures (widget); slist; slist = slist->next) + clist = gtk_widget_list_accel_closures (widget); + for (slist = clist; slist; slist = slist->next) { - /* paranoid sanity checking */ + guint i; + for (i = 0; i < n; i++) if (slist->data == (gpointer) ag_entry[i].closure) { - gboolean is_removed = gtk_accel_groups_disconnect_closure (slist->data); + gboolean is_removed = gtk_accel_group_disconnect (accel_group, slist->data); + g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); + + g_list_free (clist); + return is_removed; } } + g_list_free (clist); g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)", accel_key, accel_mods, accel_group, @@ -2672,73 +2682,48 @@ gtk_widget_remove_accelerator (GtkWidget *widget, return FALSE; } -GSList* -_gtk_widget_get_accel_closures (GtkWidget *widget) +/** + * gtk_widget_list_accel_closures + * @widget: widget to list accelerator closures for + * @returns: a newly allocated #GList of closures + * + * List the closures used by @widget for accelerator group connections + * with gtk_accel_group_connect_by_path() or gtk_accel_group_connect(). + * The closures can be used to monitor accelerator changes on @widget, + * by connecting to the ::accel_changed signal of the #GtkAccelGroup + * of a closure which can be found out with gtk_accel_group_from_accel_closure(). + */ +GList* +gtk_widget_list_accel_closures (GtkWidget *widget) { + GSList *slist; + GList *clist = NULL; + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); - return g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); + for (slist = g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); slist; slist = slist->next) + if (gtk_accel_group_from_accel_closure (slist->data)) + clist = g_list_prepend (clist, slist->data); + return clist; } typedef struct { + GQuark path_quark; GtkWidget *widget; GtkAccelGroup *accel_group; - const gchar *path; GClosure *closure; } AccelPath; static void -accel_path_changed (gpointer data, - GQuark accel_path_quark, - guint accel_key, - guint accel_mods, - GtkAccelGroup *accel_group, - guint old_accel_key, - guint old_accel_mods) -{ - AccelPath *apath = data; - gboolean notify = FALSE; - - if (apath->closure) - { - /* the closure might have been removed already (due to replacements) */ - gtk_accel_groups_disconnect_closure (apath->closure); - g_closure_unref (apath->closure); - apath->closure = NULL; - notify = TRUE; - } - if (accel_key) - { - apath->closure = widget_new_accel_closure (apath->widget, GTK_WIDGET_GET_CLASS (apath->widget)->activate_signal); - g_closure_ref (apath->closure); - /* need to specify path to get an unlocked accelerator */ - gtk_accel_group_connect (apath->accel_group, - accel_key, - accel_mods, - GTK_ACCEL_VISIBLE, - apath->closure, - accel_path_quark); - notify = TRUE; - } - if (notify) - g_signal_emit (apath->widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); -} - -static void destroy_accel_path (gpointer data) { AccelPath *apath = data; - /* stop notification */ - gtk_accel_map_remove_notifer (apath->path, apath, accel_path_changed); + gtk_accel_group_disconnect (apath->accel_group, apath->closure); - /* if the closure is currently connected, get rid of that connection */ - if (apath->closure) - { - gtk_accel_groups_disconnect_closure (apath->closure); - g_closure_unref (apath->closure); - } + /* closures_destroy takes care of unrefing the closure */ g_object_unref (apath->accel_group); + g_free (apath); } @@ -2753,25 +2738,21 @@ _gtk_widget_set_accel_path (GtkWidget *widget, GtkAccelGroup *accel_group) { AccelPath *apath; - GtkAccelKey key; g_return_if_fail (GTK_IS_WIDGET (widget)); g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0); - if (accel_path) - g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); if (accel_path) { - GQuark quark_path = gtk_accel_map_add_entry (accel_path, 0, 0); - - if (!quark_path) - return; /* pathologic anyway */ + g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); + g_return_if_fail (_gtk_accel_path_is_valid (accel_path)); + gtk_accel_map_add_entry (accel_path, 0, 0); apath = g_new (AccelPath, 1); apath->widget = widget; apath->accel_group = g_object_ref (accel_group); - apath->path = g_quark_to_string (quark_path); - apath->closure = NULL; + apath->path_quark = g_quark_from_string (accel_path); + apath->closure = widget_new_accel_closure (apath->widget, GTK_WIDGET_GET_CLASS (apath->widget)->activate_signal); } else apath = NULL; @@ -2780,14 +2761,9 @@ _gtk_widget_set_accel_path (GtkWidget *widget, g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path); if (apath) - { - /* setup accel path hooks to react to changes */ - gtk_accel_map_add_notifer (apath->path, apath, accel_path_changed, apath->accel_group); + gtk_accel_group_connect_by_path (apath->accel_group, g_quark_to_string (apath->path_quark), apath->closure); - /* install accelerators for this path */ - if (gtk_accel_map_lookup_entry (apath->path, &key)) - accel_path_changed (apath, g_quark_try_string (apath->path), key.accel_key, key.accel_mods, NULL, 0, 0); - } + g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0); } const gchar* @@ -2798,7 +2774,7 @@ _gtk_widget_get_accel_path (GtkWidget *widget) g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path); - return apath ? apath->path : NULL; + return apath ? g_quark_to_string (apath->path_quark) : NULL; } gboolean |