aboutsummaryrefslogtreecommitdiff
path: root/libdbusmenu-gtk/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdbusmenu-gtk/client.c')
-rw-r--r--libdbusmenu-gtk/client.c120
1 files changed, 71 insertions, 49 deletions
diff --git a/libdbusmenu-gtk/client.c b/libdbusmenu-gtk/client.c
index 6970d59..7ab2fe9 100644
--- a/libdbusmenu-gtk/client.c
+++ b/libdbusmenu-gtk/client.c
@@ -37,13 +37,12 @@ License version 3 and version 2.1 along with this program. If not, see
#include "genericmenuitem.h"
/* Private */
-typedef struct _DbusmenuGtkClientPrivate DbusmenuGtkClientPrivate;
struct _DbusmenuGtkClientPrivate {
GtkAccelGroup * agroup;
};
-#define DBUSMENU_GTKCLIENT_GET_PRIVATE(o) \
-(G_TYPE_INSTANCE_GET_PRIVATE ((o), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClientPrivate))
+#define DBUSMENU_GTKCLIENT_GET_PRIVATE(o) (DBUSMENU_GTKCLIENT(o)->priv)
+#define USE_FALLBACK_PROP "use-fallback"
/* Prototypes */
static void dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass);
@@ -56,12 +55,12 @@ static void delete_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, Dbusm
static void move_child (DbusmenuMenuitem * mi, DbusmenuMenuitem * child, guint new, guint old, DbusmenuGtkClient * gtkclient);
static void item_activate (DbusmenuClient * client, DbusmenuMenuitem * mi, guint timestamp, gpointer userdata);
-static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
-static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+static gboolean new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
+static gboolean new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
-static void process_visible (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value);
-static void process_sensitive (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value);
-static void image_property_handle (DbusmenuMenuitem * item, const gchar * property, const GValue * invalue, gpointer userdata);
+static void process_visible (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * value);
+static void process_sensitive (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * value);
+static void image_property_handle (DbusmenuMenuitem * item, const gchar * property, GVariant * invalue, gpointer userdata);
/* GObject Stuff */
G_DEFINE_TYPE (DbusmenuGtkClient, dbusmenu_gtkclient, DBUSMENU_TYPE_CLIENT);
@@ -85,6 +84,8 @@ dbusmenu_gtkclient_class_init (DbusmenuGtkClientClass *klass)
static void
dbusmenu_gtkclient_init (DbusmenuGtkClient *self)
{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), DBUSMENU_GTKCLIENT_TYPE, DbusmenuGtkClientPrivate);
+
DbusmenuGtkClientPrivate * priv = DBUSMENU_GTKCLIENT_GET_PRIVATE(self);
priv->agroup = NULL;
@@ -249,6 +250,7 @@ dbusmenu_gtkclient_set_accel_group (DbusmenuGtkClient * client, GtkAccelGroup *
}
priv->agroup = agroup;
+ g_object_ref(priv->agroup);
return;
}
@@ -283,10 +285,8 @@ static gboolean
menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
{
if (gtk_menu_item_get_submenu(gmi) == NULL) {
- GValue value = {0};
- g_value_init(&value, G_TYPE_INT);
- g_value_set_int(&value, 0);
- dbusmenu_menuitem_handle_event(mi, "clicked", &value, gtk_get_current_event_time());
+ GVariant * variant = g_variant_new("i", 0);
+ dbusmenu_menuitem_handle_event(mi, "clicked", variant, gtk_get_current_event_time());
} else {
/* TODO: We need to stop the display of the submenu
until this callback returns. */
@@ -297,7 +297,7 @@ menu_pressed_cb (GtkMenuItem * gmi, DbusmenuMenuitem * mi)
/* Process the visible property */
static void
-process_visible (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value)
+process_visible (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * value)
{
gboolean val = TRUE;
if (value != NULL) {
@@ -314,7 +314,7 @@ process_visible (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value)
/* Process the sensitive property */
static void
-process_sensitive (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value)
+process_sensitive (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * value)
{
gboolean val = TRUE;
if (value != NULL) {
@@ -326,26 +326,21 @@ process_sensitive (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * valu
/* Process the sensitive property */
static void
-process_toggle_type (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value)
+process_toggle_type (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant)
{
if (!IS_GENERICMENUITEM(gmi)) return;
- if (value == NULL) return;
+ if (variant == NULL) return;
GenericmenuitemCheckType type = GENERICMENUITEM_CHECK_TYPE_NONE;
- GValue strvalue = {0};
- g_value_init(&strvalue, G_TYPE_STRING);
-
- if (value != NULL && g_value_transform(value, &strvalue)) {
- const gchar * strval = g_value_get_string(&strvalue);
+ if (variant != NULL) {
+ const gchar * strval = g_variant_get_string(variant, NULL);
if (!g_strcmp0(strval, DBUSMENU_MENUITEM_TOGGLE_CHECK)) {
type = GENERICMENUITEM_CHECK_TYPE_CHECKBOX;
} else if (!g_strcmp0(strval, DBUSMENU_MENUITEM_TOGGLE_RADIO)) {
type = GENERICMENUITEM_CHECK_TYPE_RADIO;
}
-
- g_value_unset(&strvalue);
}
genericmenuitem_set_check_type(GENERICMENUITEM(gmi), type);
@@ -355,17 +350,14 @@ process_toggle_type (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * va
/* Process the sensitive property */
static void
-process_toggle_state (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * value)
+process_toggle_state (DbusmenuMenuitem * mi, GtkMenuItem * gmi, GVariant * variant)
{
if (!IS_GENERICMENUITEM(gmi)) return;
GenericmenuitemState state = GENERICMENUITEM_STATE_UNCHECKED;
- GValue intvalue = {0};
- g_value_init(&intvalue, G_TYPE_INT);
-
- if (value != NULL && g_value_transform(value, &intvalue)) {
- int val = g_value_get_int(&intvalue);
+ if (variant != NULL) {
+ int val = g_variant_get_int32(variant);
if (val == DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED) {
state = GENERICMENUITEM_STATE_CHECKED;
@@ -381,18 +373,18 @@ process_toggle_state (DbusmenuMenuitem * mi, GtkMenuItem * gmi, const GValue * v
/* Whenever we have a property change on a DbusmenuMenuitem
we need to be responsive to that. */
static void
-menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkMenuItem * gmi)
+menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * variant, GtkMenuItem * gmi)
{
if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_LABEL)) {
- gtk_menu_item_set_label(gmi, g_value_get_string(value));
+ gtk_menu_item_set_label(gmi, variant == NULL ? NULL : g_variant_get_string(variant, NULL));
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_VISIBLE)) {
- process_visible(mi, gmi, value);
+ process_visible(mi, gmi, variant);
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_ENABLED)) {
- process_sensitive(mi, gmi, value);
+ process_sensitive(mi, gmi, variant);
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE)) {
- process_toggle_type(mi, gmi, value);
+ process_toggle_type(mi, gmi, variant);
} else if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE)) {
- process_toggle_state(mi, gmi, value);
+ process_toggle_state(mi, gmi, variant);
}
return;
@@ -401,7 +393,7 @@ menu_prop_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, GtkMen
/* Special handler for the shortcut changing as we need to have the
client for that one to get the accel group. */
static void
-menu_shortcut_change_cb (DbusmenuMenuitem * mi, gchar * prop, GValue * value, DbusmenuGtkClient * client)
+menu_shortcut_change_cb (DbusmenuMenuitem * mi, gchar * prop, GVariant * value, DbusmenuGtkClient * client)
{
if (!g_strcmp0(prop, DBUSMENU_MENUITEM_PROP_SHORTCUT)) {
refresh_shortcut(client, mi);
@@ -454,11 +446,17 @@ activate_helper (GtkMenuShell * shell)
activate_helper(GTK_MENU_SHELL(parent));
}
+ /* This code is being commented out for GTK 3 because it
+ doesn't expose the right variables. We need to figure
+ this out as menus won't get grabs properly.
+ TODO FIXME HELP ARGHHHHHHHH */
+#if (HAVE_GTK3 == 0)
if (!GTK_MENU_SHELL (parent)->active) {
gtk_grab_add (parent);
GTK_MENU_SHELL (parent)->have_grab = TRUE;
GTK_MENU_SHELL (parent)->active = TRUE;
}
+#endif
gtk_menu_shell_select_item(GTK_MENU_SHELL(parent), attach);
}
@@ -537,10 +535,10 @@ dbusmenu_gtkclient_newitem_base (DbusmenuGtkClient * client, DbusmenuMenuitem *
g_object_weak_ref(G_OBJECT(item), destoryed_dbusmenuitem_cb, gmi);
/* Check our set of props to see if any are set already */
- process_visible(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_VISIBLE));
- process_sensitive(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_ENABLED));
- process_toggle_type(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE));
- process_toggle_state(item, gmi, dbusmenu_menuitem_property_get_value(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE));
+ process_visible(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_VISIBLE));
+ process_sensitive(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_ENABLED));
+ process_toggle_type(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE));
+ process_toggle_state(item, gmi, dbusmenu_menuitem_property_get_variant(item, DBUSMENU_MENUITEM_PROP_TOGGLE_STATE));
refresh_shortcut(client, item);
/* Oh, we're a child, let's deal with that */
@@ -687,7 +685,7 @@ dbusmenu_gtkclient_menuitem_get_submenu (DbusmenuGtkClient * client, DbusmenuMen
/* The base type handler that builds a plain ol'
GtkMenuItem to represent, well, the GtkMenuItem */
static gboolean
-new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
@@ -705,11 +703,11 @@ new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu
image_property_handle(newitem,
DBUSMENU_MENUITEM_PROP_ICON_NAME,
- dbusmenu_menuitem_property_get_value(newitem, DBUSMENU_MENUITEM_PROP_ICON_NAME),
+ dbusmenu_menuitem_property_get_variant(newitem, DBUSMENU_MENUITEM_PROP_ICON_NAME),
client);
image_property_handle(newitem,
DBUSMENU_MENUITEM_PROP_ICON_DATA,
- dbusmenu_menuitem_property_get_value(newitem, DBUSMENU_MENUITEM_PROP_ICON_DATA),
+ dbusmenu_menuitem_property_get_variant(newitem, DBUSMENU_MENUITEM_PROP_ICON_DATA),
client);
g_signal_connect(G_OBJECT(newitem),
DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED,
@@ -722,7 +720,7 @@ new_item_normal (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusmenu
/* Type handler for the seperators where it builds
a GtkSeparator to act as the GtkMenuItem */
static gboolean
-new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
{
g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
@@ -740,10 +738,33 @@ new_item_seperator (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm
return TRUE;
}
+/* A little helper so we don't generate a bunch of warnings
+ about being able to set use-fallback */
+static void
+set_use_fallback (GtkWidget * widget)
+{
+ static gboolean checked = FALSE;
+ static gboolean available = FALSE;
+
+ if (!checked) {
+ available = (g_object_class_find_property(G_OBJECT_CLASS(GTK_IMAGE_GET_CLASS(widget)), USE_FALLBACK_PROP) != NULL);
+ if (!available) {
+ g_warning("The '" USE_FALLBACK_PROP "' is not available on GtkImage so icons may not show correctly.");
+ }
+ checked = TRUE;
+ }
+
+ if (available) {
+ g_object_set(G_OBJECT(widget), USE_FALLBACK_PROP, TRUE, NULL);
+ }
+
+ return;
+}
+
/* This handler looks at property changes for items that are
image menu items. */
static void
-image_property_handle (DbusmenuMenuitem * item, const gchar * property, const GValue * invalue, gpointer userdata)
+image_property_handle (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer userdata)
{
/* We're only looking at these two properties here */
if (g_strcmp0(property, DBUSMENU_MENUITEM_PROP_ICON_NAME) != 0 &&
@@ -752,11 +773,10 @@ image_property_handle (DbusmenuMenuitem * item, const gchar * property, const GV
}
const gchar * value = NULL;
-
- if (invalue != NULL && G_VALUE_TYPE(invalue) == G_TYPE_STRING) {
- value = g_value_get_string(invalue);
+ if (variant != NULL) {
+ value = g_variant_get_string(variant, NULL);
}
-
+
if (value == NULL || value[0] == '\0') {
/* This means that we're unsetting a value. */
/* Try to use the other one */
@@ -793,6 +813,7 @@ image_property_handle (DbusmenuMenuitem * item, const gchar * property, const GV
gtkimage = NULL;
} else if (g_strcmp0(iconname, DBUSMENU_MENUITEM_ICON_NAME_BLANK) == 0) {
gtkimage = gtk_image_new();
+ set_use_fallback(gtkimage);
} else {
/* Look to see if we want to have an icon with the 'ltr' or
'rtl' depending on what we're doing. */
@@ -811,6 +832,7 @@ image_property_handle (DbusmenuMenuitem * item, const gchar * property, const GV
can just convert it to this name. */
if (gtkimage == NULL) {
gtkimage = gtk_image_new_from_icon_name(finaliconname, GTK_ICON_SIZE_MENU);
+ set_use_fallback(gtkimage);
} else {
gtk_image_set_from_icon_name(GTK_IMAGE(gtkimage), finaliconname, GTK_ICON_SIZE_MENU);
}