summaryrefslogtreecommitdiff
path: root/gtk/gtkaccelgroup.c
diff options
context:
space:
mode:
Diffstat (limited to 'gtk/gtkaccelgroup.c')
-rw-r--r--gtk/gtkaccelgroup.c647
1 files changed, 0 insertions, 647 deletions
diff --git a/gtk/gtkaccelgroup.c b/gtk/gtkaccelgroup.c
index 76817a0d12..553ec84ce3 100644
--- a/gtk/gtkaccelgroup.c
+++ b/gtk/gtkaccelgroup.c
@@ -55,658 +55,11 @@
* and mnemonics, of course.
*/
-/* --- prototypes --- */
-static void gtk_accel_group_finalize (GObject *object);
-static void accel_closure_invalidate (gpointer data,
- GClosure *closure);
-
-
/* --- variables --- */
-static guint signal_accel_activate = 0;
-static guint signal_accel_changed = 0;
-static guint quark_acceleratable_groups = 0;
static guint default_accel_mod_mask = 0;
-G_DEFINE_TYPE_WITH_PRIVATE (GtkAccelGroup, gtk_accel_group, G_TYPE_OBJECT)
-
/* --- functions --- */
-static void
-gtk_accel_group_class_init (GtkAccelGroupClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- quark_acceleratable_groups = g_quark_from_static_string ("gtk-acceleratable-accel-groups");
-
- object_class->finalize = gtk_accel_group_finalize;
-
- class->accel_changed = NULL;
-
- /**
- * GtkAccelGroup::accel-activate:
- * @accel_group: the #GtkAccelGroup which received the signal
- * @acceleratable: the object on which the accelerator was activated
- * @keyval: the accelerator keyval
- * @modifier: the modifier combination of the accelerator
- *
- * The accel-activate signal is an implementation detail of
- * #GtkAccelGroup and not meant to be used by applications.
- *
- * Returns: %TRUE if the accelerator was activated
- */
- signal_accel_activate =
- g_signal_new (I_("accel-activate"),
- G_OBJECT_CLASS_TYPE (class),
- G_SIGNAL_DETAILED,
- 0,
- _gtk_boolean_handled_accumulator, NULL,
- _gtk_marshal_BOOLEAN__OBJECT_UINT_FLAGS,
- G_TYPE_BOOLEAN, 3,
- G_TYPE_OBJECT,
- G_TYPE_UINT,
- GDK_TYPE_MODIFIER_TYPE);
- /**
- * GtkAccelGroup::accel-changed:
- * @accel_group: the #GtkAccelGroup which received the signal
- * @keyval: the accelerator keyval
- * @modifier: the modifier combination of the accelerator
- * @accel_closure: the #GClosure of the accelerator
- *
- * The accel-changed signal is emitted when an entry
- * is added to or removed from the accel group.
- *
- * Widgets like #GtkAccelLabel which display an associated
- * accelerator should connect to this signal, and rebuild
- * their visual representation if the @accel_closure is theirs.
- */
- signal_accel_changed =
- g_signal_new (I_("accel-changed"),
- G_OBJECT_CLASS_TYPE (class),
- G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
- G_STRUCT_OFFSET (GtkAccelGroupClass, accel_changed),
- NULL, NULL,
- _gtk_marshal_VOID__UINT_FLAGS_BOXED,
- G_TYPE_NONE, 3,
- G_TYPE_UINT,
- GDK_TYPE_MODIFIER_TYPE,
- G_TYPE_CLOSURE);
-}
-
-static void
-gtk_accel_group_finalize (GObject *object)
-{
- GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (object);
- guint i;
-
- for (i = 0; i < accel_group->priv->n_accels; i++)
- {
- GtkAccelGroupEntry *entry = &accel_group->priv->priv_accels[i];
-
- g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
-
- /* remove quick_accel_add() refcount */
- g_closure_unref (entry->closure);
- }
-
- g_free (accel_group->priv->priv_accels);
-
- G_OBJECT_CLASS (gtk_accel_group_parent_class)->finalize (object);
-}
-
-static void
-gtk_accel_group_init (GtkAccelGroup *accel_group)
-{
- GtkAccelGroupPrivate *priv;
-
- accel_group->priv = gtk_accel_group_get_instance_private (accel_group);
- priv = accel_group->priv;
-
- priv->acceleratables = NULL;
- priv->n_accels = 0;
- priv->priv_accels = NULL;
-}
-
-/**
- * gtk_accel_group_new:
- *
- * Creates a new #GtkAccelGroup.
- *
- * Returns: a new #GtkAccelGroup object
- */
-GtkAccelGroup*
-gtk_accel_group_new (void)
-{
- return g_object_new (GTK_TYPE_ACCEL_GROUP, NULL);
-}
-
-static void
-accel_group_weak_ref_detach (GSList *free_list,
- GObject *stale_object)
-{
- GSList *slist;
-
- for (slist = free_list; slist; slist = slist->next)
- {
- GtkAccelGroup *accel_group;
-
- accel_group = slist->data;
- accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, stale_object);
- g_object_unref (accel_group);
- }
- g_slist_free (free_list);
- g_object_set_qdata (stale_object, quark_acceleratable_groups, NULL);
-}
-
-void
-_gtk_accel_group_attach (GtkAccelGroup *accel_group,
- GObject *object)
-{
- GSList *slist;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) == NULL);
-
- g_object_ref (accel_group);
- accel_group->priv->acceleratables = g_slist_prepend (accel_group->priv->acceleratables, object);
- slist = g_object_get_qdata (object, quark_acceleratable_groups);
- if (slist)
- g_object_weak_unref (object,
- (GWeakNotify) accel_group_weak_ref_detach,
- slist);
- slist = g_slist_prepend (slist, accel_group);
- g_object_set_qdata (object, quark_acceleratable_groups, slist);
- g_object_weak_ref (object,
- (GWeakNotify) accel_group_weak_ref_detach,
- slist);
-}
-
-void
-_gtk_accel_group_detach (GtkAccelGroup *accel_group,
- GObject *object)
-{
- GSList *slist;
-
- g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
- g_return_if_fail (G_IS_OBJECT (object));
- g_return_if_fail (g_slist_find (accel_group->priv->acceleratables, object) != NULL);
-
- accel_group->priv->acceleratables = g_slist_remove (accel_group->priv->acceleratables, object);
- slist = g_object_get_qdata (object, quark_acceleratable_groups);
- g_object_weak_unref (object,
- (GWeakNotify) accel_group_weak_ref_detach,
- slist);
- slist = g_slist_remove (slist, accel_group);
- g_object_set_qdata (object, quark_acceleratable_groups, slist);
- if (slist)
- g_object_weak_ref (object,
- (GWeakNotify) accel_group_weak_ref_detach,
- slist);
- g_object_unref (accel_group);
-}
-
-/**
- * gtk_accel_groups_from_object:
- * @object: a #GObject, usually a #GtkWindow
- *
- * Gets a list of all accel groups which are attached to @object.
- *
- * Returns: (element-type GtkAccelGroup) (transfer none): a list of
- * all accel groups which are attached to @object
- */
-GSList*
-gtk_accel_groups_from_object (GObject *object)
-{
- g_return_val_if_fail (G_IS_OBJECT (object), NULL);
-
- return g_object_get_qdata (object, quark_acceleratable_groups);
-}
-
-/**
- * gtk_accel_group_find:
- * @accel_group: a #GtkAccelGroup
- * @find_func: (scope call): a function to filter the entries
- * of @accel_group with
- * @data: data to pass to @find_func
- *
- * Finds the first entry in an accelerator group for which
- * @find_func returns %TRUE and returns its #GtkAccelKey.
- *
- * Returns: (transfer none): the key of the first entry passing
- * @find_func. The key is owned by GTK+ and must not be freed.
- */
-GtkAccelKey*
-gtk_accel_group_find (GtkAccelGroup *accel_group,
- GtkAccelGroupFindFunc find_func,
- gpointer data)
-{
- GtkAccelKey *key = NULL;
- guint i;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
- g_return_val_if_fail (find_func != NULL, NULL);
-
- g_object_ref (accel_group);
- for (i = 0; i < accel_group->priv->n_accels; i++)
- if (find_func (&accel_group->priv->priv_accels[i].key,
- accel_group->priv->priv_accels[i].closure,
- data))
- {
- key = &accel_group->priv->priv_accels[i].key;
- break;
- }
- g_object_unref (accel_group);
-
- return key;
-}
-
-static void
-accel_closure_invalidate (gpointer data,
- GClosure *closure)
-{
- GtkAccelGroup *accel_group = GTK_ACCEL_GROUP (data);
-
- gtk_accel_group_disconnect (accel_group, closure);
-}
-
-static int
-bsearch_compare_accels (const void *d1,
- const void *d2)
-{
- const GtkAccelGroupEntry *entry1 = d1;
- const GtkAccelGroupEntry *entry2 = d2;
-
- if (entry1->key.accel_key == entry2->key.accel_key)
- return entry1->key.accel_mods < entry2->key.accel_mods ? -1 : entry1->key.accel_mods > entry2->key.accel_mods;
- else
- return entry1->key.accel_key < entry2->key.accel_key ? -1 : 1;
-}
-
-static void
-quick_accel_add (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags,
- GClosure *closure)
-{
- guint pos, i = accel_group->priv->n_accels++;
- GtkAccelGroupEntry key;
-
- /* find position */
- key.key.accel_key = accel_key;
- key.key.accel_mods = accel_mods;
- for (pos = 0; pos < i; pos++)
- if (bsearch_compare_accels (&key, accel_group->priv->priv_accels + pos) < 0)
- break;
-
- /* insert at position, ref closure */
- accel_group->priv->priv_accels = g_renew (GtkAccelGroupEntry, accel_group->priv->priv_accels, accel_group->priv->n_accels);
- memmove (accel_group->priv->priv_accels + pos + 1, accel_group->priv->priv_accels + pos,
- (i - pos) * sizeof (accel_group->priv->priv_accels[0]));
- accel_group->priv->priv_accels[pos].key.accel_key = accel_key;
- accel_group->priv->priv_accels[pos].key.accel_mods = accel_mods;
- accel_group->priv->priv_accels[pos].key.accel_flags = accel_flags;
- accel_group->priv->priv_accels[pos].closure = g_closure_ref (closure);
- g_closure_sink (closure);
-
- /* handle closure invalidation and reverse lookups */
- g_closure_add_invalidate_notifier (closure, accel_group, accel_closure_invalidate);
-
- /* connect and notify changed */
- if (accel_key)
- {
- gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
- GQuark accel_quark = g_quark_from_string (accel_name);
-
- g_free (accel_name);
-
- /* setup handler */
- g_signal_connect_closure_by_id (accel_group, signal_accel_activate, accel_quark, closure, FALSE);
-
- /* and notify */
- g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
- }
-}
-
-static void
-quick_accel_remove (GtkAccelGroup *accel_group,
- guint pos)
-{
- GQuark accel_quark = 0;
- GtkAccelGroupEntry *entry = accel_group->priv->priv_accels + pos;
- guint accel_key = entry->key.accel_key;
- GdkModifierType accel_mods = entry->key.accel_mods;
- GClosure *closure = entry->closure;
-
- /* quark for notification */
- if (accel_key)
- {
- gchar *accel_name = gtk_accelerator_name (accel_key, accel_mods);
-
- accel_quark = g_quark_from_string (accel_name);
- g_free (accel_name);
- }
-
- /* clean up closure invalidate notification and disconnect */
- g_closure_remove_invalidate_notifier (entry->closure, accel_group, accel_closure_invalidate);
- if (accel_quark)
- g_signal_handlers_disconnect_matched (accel_group,
- G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | G_SIGNAL_MATCH_CLOSURE,
- signal_accel_activate, accel_quark,
- closure, NULL, NULL);
-
- /* physically remove */
- accel_group->priv->n_accels -= 1;
- memmove (entry, entry + 1,
- (accel_group->priv->n_accels - pos) * sizeof (accel_group->priv->priv_accels[0]));
-
- /* and notify */
- if (accel_quark)
- g_signal_emit (accel_group, signal_accel_changed, accel_quark, accel_key, accel_mods, closure);
-
- /* remove quick_accel_add() refcount */
- g_closure_unref (closure);
-}
-
-static GtkAccelGroupEntry*
-quick_accel_find (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- guint *count_p)
-{
- GtkAccelGroupEntry *entry;
- GtkAccelGroupEntry key;
-
- *count_p = 0;
-
- if (!accel_group->priv->n_accels)
- return NULL;
-
- key.key.accel_key = accel_key;
- key.key.accel_mods = accel_mods;
- entry = bsearch (&key, accel_group->priv->priv_accels, accel_group->priv->n_accels,
- sizeof (accel_group->priv->priv_accels[0]), bsearch_compare_accels);
-
- if (!entry)
- return NULL;
-
- /* step back to the first member */
- for (; entry > accel_group->priv->priv_accels; entry--)
- if (entry[-1].key.accel_key != accel_key ||
- entry[-1].key.accel_mods != accel_mods)
- break;
- /* count equal members */
- for (; entry + *count_p < accel_group->priv->priv_accels + accel_group->priv->n_accels; (*count_p)++)
- if (entry[*count_p].key.accel_key != accel_key ||
- entry[*count_p].key.accel_mods != accel_mods)
- break;
- return entry;
-}
-
-/**
- * gtk_accel_group_connect:
- * @accel_group: the accelerator group to install an accelerator in
- * @accel_key: key value of the accelerator
- * @accel_mods: modifier combination of the accelerator
- * @accel_flags: a flag mask to configure this accelerator
- * @closure: closure to be executed upon accelerator activation
- *
- * Installs an accelerator in this group. When @accel_group is being
- * activated in response to a call to gtk_accel_groups_activate(),
- * @closure will be invoked if the @accel_key and @accel_mods from
- * gtk_accel_groups_activate() match those of this connection.
- *
- * The signature used for the @closure is that of #GtkAccelGroupActivate.
- *
- * Note that, due to implementation details, a single closure can
- * only be connected to one accelerator group.
- */
-void
-gtk_accel_group_connect (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- GtkAccelFlags accel_flags,
- GClosure *closure)
-{
- g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
- g_return_if_fail (closure != NULL);
- g_return_if_fail (accel_key > 0);
- g_return_if_fail (gtk_accel_group_from_accel_closure (closure) == NULL);
-
- g_object_ref (accel_group);
- if (!closure->is_invalid)
- quick_accel_add (accel_group,
- gdk_keyval_to_lower (accel_key),
- accel_mods, accel_flags, closure);
- g_object_unref (accel_group);
-}
-
-/**
- * gtk_accel_group_disconnect:
- * @accel_group: the accelerator group to remove an accelerator from
- * @closure: (allow-none): the closure to remove from this accelerator
- * group, or %NULL to remove all closures
- *
- * Removes an accelerator previously installed through
- * gtk_accel_group_connect().
- *
- * Returns: %TRUE if the closure was found and got disconnected
- */
-gboolean
-gtk_accel_group_disconnect (GtkAccelGroup *accel_group,
- GClosure *closure)
-{
- guint i;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
-
- for (i = 0; i < accel_group->priv->n_accels; i++)
- if (accel_group->priv->priv_accels[i].closure == closure)
- {
- g_object_ref (accel_group);
- quick_accel_remove (accel_group, i);
- g_object_unref (accel_group);
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * gtk_accel_group_disconnect_key:
- * @accel_group: the accelerator group to install an accelerator in
- * @accel_key: key value of the accelerator
- * @accel_mods: modifier combination of the accelerator
- *
- * Removes an accelerator previously installed through
- * gtk_accel_group_connect().
- *
- * Returns: %TRUE if there was an accelerator which could be
- * removed, %FALSE otherwise
- */
-gboolean
-gtk_accel_group_disconnect_key (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods)
-{
- GtkAccelGroupEntry *entries;
- GSList *slist, *clist = NULL;
- gboolean removed_one = FALSE;
- guint n;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
-
- g_object_ref (accel_group);
-
- accel_key = gdk_keyval_to_lower (accel_key);
- entries = quick_accel_find (accel_group, accel_key, accel_mods, &n);
- while (n--)
- {
- GClosure *closure = g_closure_ref (entries[n].closure);
-
- clist = g_slist_prepend (clist, closure);
- }
-
- for (slist = clist; slist; slist = slist->next)
- {
- GClosure *closure = slist->data;
-
- removed_one |= gtk_accel_group_disconnect (accel_group, closure);
- g_closure_unref (closure);
- }
- g_slist_free (clist);
-
- g_object_unref (accel_group);
-
- return removed_one;
-}
-
-GSList*
-_gtk_accel_group_get_accelerables (GtkAccelGroup *accel_group)
-{
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
-
- return accel_group->priv->acceleratables;
-}
-
-/**
- * gtk_accel_group_query:
- * @accel_group: the accelerator group to query
- * @accel_key: key value of the accelerator
- * @accel_mods: modifier combination of the accelerator
- * @n_entries: (out) (optional): location to return the number
- * of entries found, or %NULL
- *
- * Queries an accelerator group for all entries matching @accel_key
- * and @accel_mods.
- *
- * Returns: (nullable) (transfer none) (array length=n_entries): an array of
- * @n_entries #GtkAccelGroupEntry elements, or %NULL. The array
- * is owned by GTK+ and must not be freed.
- */
-GtkAccelGroupEntry*
-gtk_accel_group_query (GtkAccelGroup *accel_group,
- guint accel_key,
- GdkModifierType accel_mods,
- guint *n_entries)
-{
- GtkAccelGroupEntry *entries;
- guint n;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), NULL);
-
- entries = quick_accel_find (accel_group, gdk_keyval_to_lower (accel_key), accel_mods, &n);
-
- if (n_entries)
- *n_entries = entries ? n : 0;
-
- return entries;
-}
-
-/**
- * gtk_accel_group_from_accel_closure:
- * @closure: a #GClosure
- *
- * Finds the #GtkAccelGroup to which @closure is connected;
- * see gtk_accel_group_connect().
- *
- * Returns: (nullable) (transfer none): the #GtkAccelGroup to which @closure
- * is connected, or %NULL
- */
-GtkAccelGroup*
-gtk_accel_group_from_accel_closure (GClosure *closure)
-{
- guint i;
-
- g_return_val_if_fail (closure != NULL, NULL);
-
- /* A few remarks on what we do here. in general, we need a way to
- * reverse lookup accel_groups from closures that are being used in
- * accel groups. this could be done e.g via a hashtable. it is however
- * cheaper (memory wise) to just use the invalidation notifier on the
- * closure itself (which we need to install anyway), that contains the
- * accel group as data which, besides needing to peek a bit at closure
- * internals, works just as good.
- */
- for (i = 0; i < G_CLOSURE_N_NOTIFIERS (closure); i++)
- if (closure->notifiers[i].notify == accel_closure_invalidate)
- return closure->notifiers[i].data;
-
- return NULL;
-}
-
-/**
- * gtk_accel_group_activate:
- * @accel_group: a #GtkAccelGroup
- * @accel_quark: the quark for the accelerator name
- * @acceleratable: the #GObject, usually a #GtkWindow, on which
- * to activate the accelerator
- * @accel_key: accelerator keyval from a key event
- * @accel_mods: keyboard state mask from a key event
- *
- * Finds the first accelerator in @accel_group that matches
- * @accel_key and @accel_mods, and activates it.
- *
- * Returns: %TRUE if an accelerator was activated and handled
- * this keypress
- */
-gboolean
-gtk_accel_group_activate (GtkAccelGroup *accel_group,
- GQuark accel_quark,
- GObject *acceleratable,
- guint accel_key,
- GdkModifierType accel_mods)
-{
- gboolean was_handled;
-
- g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
- g_return_val_if_fail (G_IS_OBJECT (acceleratable), FALSE);
-
- was_handled = FALSE;
- g_signal_emit (accel_group, signal_accel_activate, accel_quark,
- acceleratable, accel_key, accel_mods, &was_handled);
-
- return was_handled;
-}
-
-/**
- * gtk_accel_groups_activate:
- * @object: the #GObject, usually a #GtkWindow, on which
- * to activate the accelerator
- * @accel_key: accelerator keyval from a key event
- * @accel_mods: keyboard state mask from a key event
- *
- * Finds the first accelerator in any #GtkAccelGroup attached
- * to @object that matches @accel_key and @accel_mods, and
- * activates that accelerator.
- *
- * Returns: %TRUE if an accelerator was activated and handled
- * this keypress
- */
-gboolean
-gtk_accel_groups_activate (GObject *object,
- guint accel_key,
- GdkModifierType accel_mods)
-{
- g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
-
- if (gtk_accelerator_valid (accel_key, accel_mods))
- {
- gchar *accel_name;
- GQuark accel_quark;
- GSList *slist;
-
- accel_name = gtk_accelerator_name (accel_key, (accel_mods & gtk_accelerator_get_default_mod_mask ()));
- accel_quark = g_quark_from_string (accel_name);
- g_free (accel_name);
-
- for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next)
- if (gtk_accel_group_activate (slist->data, accel_quark, object, accel_key, accel_mods))
- return TRUE;
- }
-
- return FALSE;
-}
-
/**
* gtk_accelerator_valid:
* @keyval: a GDK keyval