summaryrefslogtreecommitdiff
path: root/gtk/gtkmenutrackeritem.c
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2014-01-04 02:25:43 -0500
committerRyan Lortie <desrt@desrt.ca>2014-01-08 14:21:18 -0500
commit2b1aa12f01f382652a3b6b9c7e51959dde194143 (patch)
treee876e84ade9f3c592c2d238e832b836b7c116a0d /gtk/gtkmenutrackeritem.c
parent8efb1404cbdeedfaf894c219fcae9dbdd1986fa2 (diff)
downloadgtk+-2b1aa12f01f382652a3b6b9c7e51959dde194143.tar.gz
GtkMenuTrackerItem: add an internal 'visible' flag
Add an internal API for checking if a GtkMenuTrackerItem is visible, along with a signal for reporting changes in that flag. The item will become invisible in situations according to the new hidden-when='' attribute, which can be set to 'action-disabled' or 'action-missing'. This new flag doesn't actually do anything yet, and none of the consumers of GtkMenuTracker do anything with it (nor should they). A followup patch will address the issue. https://bugzilla.gnome.org/show_bug.cgi?id=688421
Diffstat (limited to 'gtk/gtkmenutrackeritem.c')
-rw-r--r--gtk/gtkmenutrackeritem.c90
1 files changed, 90 insertions, 0 deletions
diff --git a/gtk/gtkmenutrackeritem.c b/gtk/gtkmenutrackeritem.c
index d81c9de8e5..fdda28f9fb 100644
--- a/gtk/gtkmenutrackeritem.c
+++ b/gtk/gtkmenutrackeritem.c
@@ -97,8 +97,14 @@ struct _GtkMenuTrackerItem
guint toggled : 1;
guint submenu_shown : 1;
guint submenu_requested : 1;
+ guint hidden_when : 2;
+ guint is_visible : 1;
};
+#define HIDDEN_NEVER 0
+#define HIDDEN_WHEN_MISSING 1
+#define HIDDEN_WHEN_DISABLED 2
+
enum {
PROP_0,
PROP_IS_SEPARATOR,
@@ -115,6 +121,7 @@ enum {
};
static GParamSpec *gtk_menu_tracker_item_pspecs[N_PROPS];
+static guint gtk_menu_tracker_visibility_changed_signal;
static void gtk_menu_tracker_item_init_observer_iface (GtkActionObserverInterface *iface);
G_DEFINE_TYPE_WITH_CODE (GtkMenuTrackerItem, gtk_menu_tracker_item, G_TYPE_OBJECT,
@@ -239,6 +246,46 @@ gtk_menu_tracker_item_class_init (GtkMenuTrackerItemClass *class)
g_param_spec_boolean ("submenu-shown", "", "", FALSE, G_PARAM_STATIC_STRINGS | G_PARAM_READABLE);
g_object_class_install_properties (class, N_PROPS, gtk_menu_tracker_item_pspecs);
+
+ gtk_menu_tracker_visibility_changed_signal = g_signal_new ("visibility-changed", GTK_TYPE_MENU_TRACKER_ITEM,
+ G_SIGNAL_RUN_FIRST, 0, NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE,
+ 1, G_TYPE_BOOLEAN);
+}
+
+/* This syncs up the visibility for the hidden-when='' case. We call it
+ * from the action observer functions on changes to the action group and
+ * on initialisation (via the action observer functions that are invoked
+ * at that time).
+ */
+static void
+gtk_menu_tracker_item_update_visibility (GtkMenuTrackerItem *self)
+{
+ gboolean visible;
+
+ switch (self->hidden_when)
+ {
+ case HIDDEN_NEVER:
+ visible = TRUE;
+ break;
+
+ case HIDDEN_WHEN_MISSING:
+ visible = self->can_activate;
+ break;
+
+ case HIDDEN_WHEN_DISABLED:
+ visible = self->sensitive;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (visible != self->is_visible)
+ {
+ self->is_visible = visible;
+ g_signal_emit (self, gtk_menu_tracker_visibility_changed_signal, 0, visible);
+ }
}
static void
@@ -294,6 +341,12 @@ gtk_menu_tracker_item_action_added (GtkActionObserver *observer,
if (action_target)
g_variant_unref (action_target);
+
+ /* In case of hidden-when='', we want to Wait until after refreshing
+ * all of the properties to emit the signal that will cause the
+ * tracker to expose us (to prevent too much thrashing).
+ */
+ gtk_menu_tracker_item_update_visibility (self);
}
static void
@@ -313,6 +366,8 @@ gtk_menu_tracker_item_action_enabled_changed (GtkActionObserver *observer,
self->sensitive = enabled;
g_object_notify_by_pspec (G_OBJECT (self), gtk_menu_tracker_item_pspecs[PROP_SENSITIVE]);
+
+ gtk_menu_tracker_item_update_visibility (self);
}
static void
@@ -368,6 +423,11 @@ gtk_menu_tracker_item_action_removed (GtkActionObserver *observer,
self->toggled = FALSE;
self->role = GTK_MENU_TRACKER_ITEM_ROLE_NORMAL;
+ /* Backwards from adding: we want to remove ourselves from the menu
+ * -before- thrashing the properties.
+ */
+ gtk_menu_tracker_item_update_visibility (self);
+
g_object_freeze_notify (G_OBJECT (self));
if (was_sensitive)
@@ -413,6 +473,7 @@ _gtk_menu_tracker_item_new (GtkActionObservable *observable,
{
GtkMenuTrackerItem *self;
const gchar *action_name;
+ const gchar *hidden_when;
g_return_val_if_fail (GTK_IS_ACTION_OBSERVABLE (observable), NULL);
g_return_val_if_fail (G_IS_MENU_MODEL (model), NULL);
@@ -423,6 +484,23 @@ _gtk_menu_tracker_item_new (GtkActionObservable *observable,
self->observable = g_object_ref (observable);
self->is_separator = is_separator;
+ if (!is_separator && g_menu_item_get_attribute (self->item, "hidden-when", "&s", &hidden_when))
+ {
+ if (g_str_equal (hidden_when, "action-disabled"))
+ self->hidden_when = HIDDEN_WHEN_DISABLED;
+ else if (g_str_equal (hidden_when, "action-missing"))
+ self->hidden_when = HIDDEN_WHEN_MISSING;
+
+ /* Ignore other values -- this code may be running in context of a
+ * desktop shell or the like and should not spew criticals due to
+ * application bugs...
+ *
+ * Note: if we just set a hidden-when state, but don't get the
+ * action_name below then our visibility will be FALSE forever.
+ * That's to be expected since the action is missing...
+ */
+ }
+
if (!is_separator && g_menu_item_get_attribute (self->item, "action", "&s", &action_name))
{
GActionGroup *group = G_ACTION_GROUP (observable);
@@ -803,3 +881,15 @@ gtk_menu_tracker_item_request_submenu_shown (GtkMenuTrackerItem *self,
else
gtk_menu_tracker_item_set_submenu_shown (self, shown);
}
+
+gboolean
+_gtk_menu_tracker_item_is_visible (GtkMenuTrackerItem *self)
+{
+ return self->is_visible;
+}
+
+gboolean
+_gtk_menu_tracker_item_may_disappear (GtkMenuTrackerItem *self)
+{
+ return self->hidden_when != HIDDEN_NEVER;
+}