Accelerator-only actions
- From: Matthias Clasen <maclas gmx de>
- To: gtk-devel-list gnome org
- Subject: Accelerator-only actions
- Date: 05 Sep 2003 11:16:59 +0200
This is the last major API change which I want to get into the action
menu code to make it ready for 2.4: Switch back to installing
accelerators on the actions, instead of the proxies. This is relatively
straightforward except for a little problem with editing of
accelerators. I'd be most interested in feedback on the way I solved
this in gtkmenu.c. Since the patch is unfortunately a little blown up by
formatting changes (I recently discovered egtk-format-protos...), here
is a quick summary:
- the accel_group reference moves from the ui manager to the action
groups. An action group creates its own accel group by default, but you
can set a different one.
- actions install their accelerator when their accel path is set,
meaning that action can activated via accelerator even if they don't
have any proxies.
- making accelerators do nothing on insensitive actions is done in the
same way as for menuitems: the accel_closure simply returns
Matthias
Index: gtk/gtkaction.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaction.c,v
retrieving revision 1.5
diff -u -p -r1.5 gtkaction.c
--- gtk/gtkaction.c 4 Sep 2003 21:34:15 -0000 1.5
+++ gtk/gtkaction.c 5 Sep 2003 09:06:20 -0000
@@ -59,7 +59,9 @@ struct _GtkActionPrivate
guint is_important : 1;
/* accelerator */
- GQuark accel_quark;
+ GClosure *accel_closure;
+ GtkAccelGroup *accel_group;
+ GQuark accel_quark;
/* list of proxy widgets */
GSList *proxies;
@@ -118,22 +120,28 @@ gtk_action_get_type (void)
return type;
}
-static void gtk_action_finalize (GObject *object);
-static void gtk_action_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void gtk_action_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-static GtkWidget *create_menu_item (GtkAction *action);
-static GtkWidget *create_tool_item (GtkAction *action);
-static void connect_proxy (GtkAction *action,
- GtkWidget *proxy);
-static void disconnect_proxy (GtkAction *action,
- GtkWidget *proxy);
+static void gtk_action_finalize (GObject *object);
+static void gtk_action_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gtk_action_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+static void closure_accel_activate (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+static GtkWidget *create_menu_item (GtkAction *action);
+static GtkWidget *create_tool_item (GtkAction *action);
+static void connect_proxy (GtkAction *action,
+ GtkWidget *proxy);
+static void disconnect_proxy (GtkAction *action,
+ GtkWidget *proxy);
+
static GObjectClass *parent_class = NULL;
static guint action_signals[LAST_SIGNAL] = { 0 };
@@ -260,6 +268,13 @@ gtk_action_init (GtkAction *action)
action->private_data->label_set = FALSE;
action->private_data->short_label_set = FALSE;
+ action->private_data->accel_closure = g_closure_new_object (sizeof (GClosure),
+ G_OBJECT (action));
+ g_closure_set_marshal (action->private_data->accel_closure, closure_accel_activate);
+ g_closure_ref (action->private_data->accel_closure);
+ g_closure_sink (action->private_data->accel_closure);
+
+ action->private_data->accel_group = NULL;
action->private_data->accel_quark = 0;
action->private_data->proxies = NULL;
@@ -272,6 +287,12 @@ gtk_action_finalize (GObject *object)
action = GTK_ACTION (object);
+ if (action->private_data->accel_closure)
+ g_closure_unref (action->private_data->accel_closure);
+
+ if (action->private_data->accel_group)
+ g_object_unref (action->private_data->accel_group);
+
g_free (action->private_data->name);
g_free (action->private_data->label);
g_free (action->private_data->short_label);
@@ -564,7 +585,7 @@ connect_proxy (GtkAction *action,
"xalign", 0.0,
"visible", TRUE,
"parent", proxy,
- "accel_widget", proxy,
+ "accel_closure", action->private_data->accel_closure,
NULL);
}
gtk_label_set_label (GTK_LABEL (label), action->private_data->label);
@@ -928,6 +949,22 @@ gtk_action_unblock_activate_from (GtkAct
action);
}
+static void
+closure_accel_activate (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ if (GTK_ACTION (closure->data)->private_data->sensitive)
+ g_signal_emit (closure->data, action_signals[ACTIVATE], 0);
+
+ /* we handled the accelerator */
+ g_value_set_boolean (return_value, TRUE);
+}
+
+
/**
* gtk_action_set_accel_path:
* @action: the action object
@@ -940,8 +977,43 @@ gtk_action_unblock_activate_from (GtkAct
* Since: 2.4
*/
void
-gtk_action_set_accel_path (GtkAction *action,
- const gchar *accel_path)
+gtk_action_set_accel_path (GtkAction *action,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group)
{
+ g_return_if_fail (GTK_IS_ACTION (action));
+ g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
+
+ g_object_ref (accel_group);
+ if (action->private_data->accel_group)
+ g_object_unref (action->private_data->accel_group);
+ action->private_data->accel_group = accel_group;
+
action->private_data->accel_quark = g_quark_from_string (accel_path);
+
+ gtk_accel_group_connect_by_path (accel_group,
+ g_quark_to_string (action->private_data->accel_quark),
+ action->private_data->accel_closure);
+}
+
+const gchar *
+gtk_action_get_accel_path (GtkAction *action,
+ gboolean *locked)
+{
+ g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
+
+ if (action->private_data->accel_quark)
+ {
+ if (locked)
+ *locked = action->private_data->accel_group->lock_count > 0;
+
+ return g_quark_to_string (action->private_data->accel_quark);
+ }
+ else
+ {
+ if (locked)
+ *locked = TRUE;
+
+ return NULL;
+ }
}
Index: gtk/gtkaction.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkaction.h,v
retrieving revision 1.1
diff -u -p -r1.1 gtkaction.h
--- gtk/gtkaction.h 24 Aug 2003 19:58:28 -0000 1.1
+++ gtk/gtkaction.h 5 Sep 2003 09:06:20 -0000
@@ -78,30 +78,32 @@ struct _GtkActionClass
void (*_gtk_reserved4) (void);
};
-GType gtk_action_get_type (void);
-
-const gchar* gtk_action_get_name (GtkAction *action);
-void gtk_action_activate (GtkAction *action);
-
-GtkWidget *gtk_action_create_icon (GtkAction *action,
- GtkIconSize icon_size);
-GtkWidget *gtk_action_create_menu_item (GtkAction *action);
-GtkWidget *gtk_action_create_tool_item (GtkAction *action);
-void gtk_action_connect_proxy (GtkAction *action,
- GtkWidget *proxy);
-void gtk_action_disconnect_proxy (GtkAction *action,
- GtkWidget *proxy);
-GSList *gtk_action_get_proxies (GtkAction *action);
+GType gtk_action_get_type (void);
+const gchar *gtk_action_get_name (GtkAction *action);
+void gtk_action_activate (GtkAction *action);
+GtkWidget *gtk_action_create_icon (GtkAction *action,
+ GtkIconSize icon_size);
+GtkWidget *gtk_action_create_menu_item (GtkAction *action);
+GtkWidget *gtk_action_create_tool_item (GtkAction *action);
+void gtk_action_connect_proxy (GtkAction *action,
+ GtkWidget *proxy);
+void gtk_action_disconnect_proxy (GtkAction *action,
+ GtkWidget *proxy);
+GSList *gtk_action_get_proxies (GtkAction *action);
/* protected ... for use by child actions */
-void gtk_action_block_activate_from (GtkAction *action,
- GtkWidget *proxy);
-void gtk_action_unblock_activate_from (GtkAction *action,
- GtkWidget *proxy);
+void gtk_action_block_activate_from (GtkAction *action,
+ GtkWidget *proxy);
+void gtk_action_unblock_activate_from (GtkAction *action,
+ GtkWidget *proxy);
/* protected ... for use by action groups */
-void gtk_action_set_accel_path (GtkAction *action,
- const gchar *accel_path);
+void gtk_action_set_accel_path (GtkAction *action,
+ const gchar *accel_path,
+ GtkAccelGroup *accel_group);
+const gchar *gtk_action_get_accel_path (GtkAction *action,
+ gboolean *locked);
+
#endif /* __GTK_ACTION_H__ */
Index: gtk/gtkactiongroup.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkactiongroup.c,v
retrieving revision 1.11
diff -u -p -r1.11 gtkactiongroup.c
--- gtk/gtkactiongroup.c 4 Sep 2003 00:49:36 -0000 1.11
+++ gtk/gtkactiongroup.c 5 Sep 2003 09:06:20 -0000
@@ -41,6 +41,7 @@
struct _GtkActionGroupPrivate
{
gchar *name;
+ GtkAccelGroup *accel_group;
GHashTable *actions;
GtkTranslateFunc translate_func;
@@ -102,9 +103,11 @@ gtk_action_group_init (GtkActionGroup *s
{
self->private_data = GTK_ACTION_GROUP_GET_PRIVATE (self);
self->private_data->name = NULL;
+ self->private_data->accel_group = gtk_accel_group_new ();
self->private_data->actions = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) g_object_unref);
+
self->private_data->translate_func = NULL;
self->private_data->translate_data = NULL;
self->private_data->translate_notify = NULL;
@@ -123,12 +126,19 @@ gtk_action_group_init (GtkActionGroup *s
* Since: 2.4
*/
GtkActionGroup *
-gtk_action_group_new (const gchar *name)
+gtk_action_group_new (const gchar *name,
+ GtkAccelGroup *accel_group)
{
GtkActionGroup *self;
self = g_object_new (GTK_TYPE_ACTION_GROUP, NULL);
self->private_data->name = g_strdup (name);
+ if (accel_group)
+ {
+ g_object_ref (accel_group);
+ g_object_unref (self->private_data->accel_group);
+ self->private_data->accel_group = accel_group;
+ }
return self;
}
@@ -144,6 +154,8 @@ gtk_action_group_finalize (GObject *obje
self->private_data->name = NULL;
g_hash_table_destroy (self->private_data->actions);
+ g_object_unref (self->private_data->accel_group);
+ self->private_data->accel_group = NULL;
self->private_data->actions = NULL;
if (self->private_data->translate_notify)
@@ -179,6 +191,24 @@ gtk_action_group_get_name (GtkActionGrou
}
/**
+ * gtk_action_group_get_accel_group:
+ * @action_group: a #GtkActionGroup object
+ *
+ * Returns the #GtkAccelGroup associated with @action_group.
+ *
+ * Return value: the #GtkAccelGroup.
+ *
+ * Since: 2.4
+ **/
+GtkAccelGroup *
+gtk_action_group_get_accel_group (GtkActionGroup *action_group)
+{
+ g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL);
+
+ return action_group->private_data->accel_group;
+}
+
+/**
* gtk_action_group_get_action:
* @action_group: the action group
* @action_name: the name of the action
@@ -384,7 +414,7 @@ gtk_action_group_add_actions_full (GtkAc
gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
}
- gtk_action_set_accel_path (action, accel_path);
+ gtk_action_set_accel_path (action, accel_path, action_group->private_data->accel_group);
g_free (accel_path);
gtk_action_group_add_action (action_group, action);
@@ -503,7 +533,7 @@ gtk_action_group_add_radio_actions_full
gtk_accel_map_add_entry (accel_path, accel_key, accel_mods);
}
- gtk_action_set_accel_path (action, accel_path);
+ gtk_action_set_accel_path (action, accel_path, action_group->private_data->accel_group);
g_free (accel_path);
gtk_action_group_add_action (action_group, action);
Index: gtk/gtkactiongroup.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkactiongroup.h,v
retrieving revision 1.4
diff -u -p -r1.4 gtkactiongroup.h
--- gtk/gtkactiongroup.h 27 Aug 2003 22:22:27 -0000 1.4
+++ gtk/gtkactiongroup.h 5 Sep 2003 09:06:20 -0000
@@ -93,46 +93,45 @@ struct _GtkRadioActionEntry
gint value;
};
-GType gtk_action_group_get_type (void);
-
-GtkActionGroup *gtk_action_group_new (const gchar *name);
-
-const gchar *gtk_action_group_get_name (GtkActionGroup *action_group);
-GtkAction *gtk_action_group_get_action (GtkActionGroup *action_group,
- const gchar *action_name);
-GList *gtk_action_group_list_actions (GtkActionGroup *action_group);
-void gtk_action_group_add_action (GtkActionGroup *action_group,
- GtkAction *action);
-void gtk_action_group_remove_action (GtkActionGroup *action_group,
- GtkAction *action);
-
-void gtk_action_group_add_actions (GtkActionGroup *action_group,
- GtkActionEntry *entries,
- guint n_entries,
- gpointer user_data);
-void gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
- GtkRadioActionEntry *entries,
- guint n_entries,
- GCallback on_change,
- gpointer user_data);
-void gtk_action_group_add_actions_full (GtkActionGroup *action_group,
- GtkActionEntry *entries,
- guint n_entries,
- gpointer user_data,
- GDestroyNotify destroy);
+GType gtk_action_group_get_type (void);
+GtkActionGroup *gtk_action_group_new (const gchar *name,
+ GtkAccelGroup *accel_group);
+const gchar *gtk_action_group_get_name (GtkActionGroup *action_group);
+GtkAccelGroup *gtk_action_group_get_accel_group (GtkActionGroup *action_group);
+GtkAction *gtk_action_group_get_action (GtkActionGroup *action_group,
+ const gchar *action_name);
+GList *gtk_action_group_list_actions (GtkActionGroup *action_group);
+void gtk_action_group_add_action (GtkActionGroup *action_group,
+ GtkAction *action);
+void gtk_action_group_remove_action (GtkActionGroup *action_group,
+ GtkAction *action);
+void gtk_action_group_add_actions (GtkActionGroup *action_group,
+ GtkActionEntry *entries,
+ guint n_entries,
+ gpointer user_data);
+void gtk_action_group_add_radio_actions (GtkActionGroup *action_group,
+ GtkRadioActionEntry *entries,
+ guint n_entries,
+ GCallback on_change,
+ gpointer user_data);
+void gtk_action_group_add_actions_full (GtkActionGroup *action_group,
+ GtkActionEntry *entries,
+ guint n_entries,
+ gpointer user_data,
+ GDestroyNotify destroy);
void gtk_action_group_add_radio_actions_full (GtkActionGroup *action_group,
- GtkRadioActionEntry *entries,
- guint n_entries,
- GCallback on_change,
- gpointer user_data,
+ GtkRadioActionEntry *entries,
+ guint n_entries,
+ GCallback on_change,
+ gpointer user_data,
GDestroyNotify destroy);
-
-void gtk_action_group_set_translate_func (GtkActionGroup *action_group,
- GtkTranslateFunc func,
- gpointer data,
- GtkDestroyNotify notify);
-
+void gtk_action_group_set_translate_func (GtkActionGroup *action_group,
+ GtkTranslateFunc func,
+ gpointer data,
+ GtkDestroyNotify notify);
void gtk_action_group_set_translation_domain (GtkActionGroup *action_group,
const gchar *domain);
+
+
#endif /* __GTK_ACTION_GROUP_H__ */
Index: gtk/gtkmarshal.list
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmarshal.list,v
retrieving revision 1.43
diff -u -p -r1.43 gtkmarshal.list
--- gtk/gtkmarshal.list 17 Nov 2001 23:28:50 -0000 1.43
+++ gtk/gtkmarshal.list 5 Sep 2003 09:06:20 -0000
@@ -4,6 +4,7 @@ BOOL:POINTER,POINTER,INT,INT
BOOL:POINTER,INT,INT
BOOL:POINTER,INT,INT,UINT
BOOL:POINTER,STRING,STRING,POINTER
+BOOL:OBJECT
ENUM:ENUM
INT:POINTER
INT:POINTER,CHAR,CHAR
Index: gtk/gtkmarshalers.list
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmarshalers.list,v
retrieving revision 1.53
diff -u -p -r1.53 gtkmarshalers.list
--- gtk/gtkmarshalers.list 11 Jul 2003 12:51:24 -0000 1.53
+++ gtk/gtkmarshalers.list 5 Sep 2003 09:06:20 -0000
@@ -28,6 +28,7 @@ BOOLEAN:ENUM,INT
BOOLEAN:OBJECT,UINT,FLAGS
BOOLEAN:OBJECT,INT,INT,UINT
BOOLEAN:OBJECT,STRING,STRING,BOXED
+BOOLEAN:OBJECT
BOOLEAN:OBJECT,BOXED
BOOLEAN:OBJECT,BOXED,BOXED
BOOLEAN:OBJECT,STRING,STRING
Index: gtk/gtkmenu.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmenu.c,v
retrieving revision 1.139
diff -u -p -r1.139 gtkmenu.c
--- gtk/gtkmenu.c 3 Sep 2003 21:26:13 -0000 1.139
+++ gtk/gtkmenu.c 5 Sep 2003 09:06:21 -0000
@@ -29,6 +29,7 @@
#include <string.h> /* memset */
#include "gdk/gdkkeysyms.h"
#include "gtkaccelmap.h"
+#include "gtkaction.h"
#include "gtkbindings.h"
#include "gtklabel.h"
#include "gtkmain.h"
@@ -2125,6 +2126,13 @@ gtk_menu_key_press (GtkWidget *widget,
const gchar *path;
path = _gtk_widget_get_accel_path (menu_item, &locked);
+ if (!path)
+ {
+ GtkAction *action = g_object_get_data (G_OBJECT (menu_item),
+ "gtk-action");
+ if (action)
+ path = gtk_action_get_accel_path (action, &locked);
+ }
if (!path || locked)
{
/* can't change accelerators on menu_items without paths
Index: gtk/gtkuimanager.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkuimanager.c,v
retrieving revision 1.16
diff -u -p -r1.16 gtkuimanager.c
--- gtk/gtkuimanager.c 4 Sep 2003 20:39:14 -0000 1.16
+++ gtk/gtkuimanager.c 5 Sep 2003 09:06:22 -0000
@@ -80,8 +80,6 @@ struct _Node {
struct _GtkUIManagerPrivate
{
- GtkAccelGroup *accel_group;
-
GNode *root_node;
GList *action_groups;
@@ -261,8 +259,6 @@ gtk_ui_manager_init (GtkUIManager *self)
self->private_data = GTK_UI_MANAGER_GET_PRIVATE (self);
- self->private_data->accel_group = gtk_accel_group_new ();
-
self->private_data->root_node = NULL;
self->private_data->action_groups = NULL;
@@ -470,24 +466,6 @@ gtk_ui_manager_get_action_groups (GtkUIM
}
/**
- * gtk_ui_manager_get_accel_group:
- * @self: a #GtkUIManager object
- *
- * Returns the #GtkAccelGroup associated with @self.
- *
- * Return value: the #GtkAccelGroup.
- *
- * Since: 2.4
- **/
-GtkAccelGroup *
-gtk_ui_manager_get_accel_group (GtkUIManager *self)
-{
- g_return_val_if_fail (GTK_IS_UI_MANAGER (self), NULL);
-
- return self->private_data->accel_group;
-}
-
-/**
* gtk_ui_manager_get_widget:
* @self: a #GtkUIManager
* @path: a path
@@ -1636,8 +1614,6 @@ update_node (GtkUIManager *self,
if (info->proxy == NULL)
{
info->proxy = gtk_menu_new ();
- gtk_menu_set_accel_group (GTK_MENU (info->proxy),
- self->private_data->accel_group);
}
break;
case NODE_TYPE_MENU:
@@ -1672,7 +1648,6 @@ update_node (GtkUIManager *self,
GtkWidget *tearoff = gtk_tearoff_menu_item_new ();
gtk_menu_shell_append (GTK_MENU_SHELL (menu), tearoff);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (info->proxy), menu);
- gtk_menu_set_accel_group (GTK_MENU (menu), self->private_data->accel_group);
gtk_menu_shell_insert (GTK_MENU_SHELL (menushell), info->proxy, pos);
}
}
Index: gtk/gtkuimanager.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkuimanager.h,v
retrieving revision 1.10
diff -u -p -r1.10 gtkuimanager.h
--- gtk/gtkuimanager.h 4 Sep 2003 20:39:14 -0000 1.10
+++ gtk/gtkuimanager.h 5 Sep 2003 09:06:22 -0000
@@ -95,7 +95,6 @@ void gtk_ui_manager_insert_act
void gtk_ui_manager_remove_action_group (GtkUIManager *self,
GtkActionGroup *action_group);
GList *gtk_ui_manager_get_action_groups (GtkUIManager *self);
-GtkAccelGroup *gtk_ui_manager_get_accel_group (GtkUIManager *self);
GtkWidget *gtk_ui_manager_get_widget (GtkUIManager *self,
const gchar *path);
GtkAction *gtk_ui_manager_get_action (GtkUIManager *self,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]