diff options
Diffstat (limited to 'src/indicator-sus.c')
-rw-r--r-- | src/indicator-sus.c | 243 |
1 files changed, 209 insertions, 34 deletions
diff --git a/src/indicator-sus.c b/src/indicator-sus.c index 53a0db6..18b6c44 100644 --- a/src/indicator-sus.c +++ b/src/indicator-sus.c @@ -1,6 +1,6 @@ #include <gtk/gtk.h> -#include <libdbusmenu-gtk/menu.h> +#include <libdbusmenu-gtk/client.h> #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-bindings.h> @@ -12,9 +12,10 @@ INDICATOR_SET_NAME("users-status-session") #include "dbus-shared-names.h" #include "status-service-client.h" -static GtkMenu * status_menu = NULL; -static GtkMenu * users_menu = NULL; -static GtkMenu * session_menu = NULL; +static DbusmenuGtkClient * status_client = NULL; +static DbusmenuGtkClient * users_client = NULL; +static DbusmenuGtkClient * session_client = NULL; + static GtkMenu * main_menu = NULL; static GtkWidget * status_separator = NULL; @@ -25,10 +26,23 @@ static GtkWidget * loading_item = NULL; static DBusGConnection * connection = NULL; static DBusGProxy * proxy = NULL; +typedef enum { + STATUS_SECTION, + USERS_SECTION, + SESSION_SECTION, + END_OF_SECTIONS +} section_t; + +static void child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint position, gpointer section); +static guint status_menu_pos_offset (void); +static guint users_menu_pos_offset (void); +static guint session_menu_pos_offset (void); + GtkLabel * get_label (void) { GtkLabel * returnval = GTK_LABEL(gtk_label_new("Ted Gould")); + gtk_widget_show(GTK_WIDGET(returnval)); return returnval; } @@ -39,16 +53,44 @@ get_icon (void) } static void -menu_add (GtkContainer * source, GtkWidget * addee, GtkMenu * addto, guint positionoffset) +child_added (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint position, gpointer section) { - GList * location = g_list_find(GTK_MENU_SHELL(source)->children, addee); - guint position = g_list_position(GTK_MENU_SHELL(source)->children, location); + DbusmenuGtkClient * client = NULL; + gchar * errorstr = NULL; + guint (*posfunc) (void) = NULL; + + switch (GPOINTER_TO_UINT(section)) { + case STATUS_SECTION: + client = status_client; + errorstr = "Status"; + posfunc = status_menu_pos_offset; + break; + case USERS_SECTION: + client = users_client; + errorstr = "Users"; + posfunc = users_menu_pos_offset; + break; + case SESSION_SECTION: + client = session_client; + errorstr = "Session"; + posfunc = session_menu_pos_offset; + break; + default: + g_warning("Child Added called with an unknown position function!"); + return; + } + + position += posfunc(); + g_debug("SUS: Adding child: %d", position); + GtkMenuItem * widget = dbusmenu_gtkclient_menuitem_get(client, child); - position += positionoffset; - g_debug("Adding a widget: %d", position); + if (widget == NULL) { + g_warning("Had a menu item added to the %s menu, but yet it didn't have a GtkWidget with it. Can't add that to a menu now can we? You need to figure this @#$# out!", errorstr); + return; + } - gtk_menu_insert(addto, addee, position); - gtk_widget_show(addee); + gtk_menu_insert(main_menu, GTK_WIDGET(widget), position); + gtk_widget_show(GTK_WIDGET(widget)); gtk_widget_hide(loading_item); @@ -56,44 +98,67 @@ menu_add (GtkContainer * source, GtkWidget * addee, GtkMenu * addto, guint posit } static void -status_menu_add (GtkContainer * container, GtkWidget * widget, gpointer userdata) +child_moved (DbusmenuMenuitem * parent, DbusmenuMenuitem * child, guint newpos, guint oldpos, guint (*posfunc) (void)) +{ + + +} + + +/* Status Menu */ +static guint +status_menu_pos_offset (void) +{ + return 0; +} + +static void +status_menu_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, gpointer user_data) { - menu_add(container, widget, GTK_MENU(userdata), 0); - gtk_widget_show(status_separator); + gtk_widget_show(GTK_WIDGET(status_separator)); return; } static void -users_menu_add (GtkContainer * container, GtkWidget * widget, gpointer userdata) +status_menu_removed (DbusmenuMenuitem * root, DbusmenuMenuitem * child, gpointer user_data) { - guint position = 0; - if (SEPARATOR_SHOWN(status_separator)) { - GList * location = g_list_find(GTK_MENU_SHELL(main_menu)->children, status_separator); - position = g_list_position(GTK_MENU_SHELL(main_menu)->children, location) + 1; + if (g_list_length(dbusmenu_menuitem_get_children(root)) == 0) { + gtk_widget_hide(GTK_WIDGET(status_separator)); } - menu_add(container, widget, GTK_MENU(userdata), position); - gtk_widget_show(users_separator); return; } static void -session_menu_add (GtkContainer * container, GtkWidget * widget, gpointer userdata) +status_menu_root_changed(DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, GtkMenu * main) { - guint position = 0; - if (SEPARATOR_SHOWN(users_separator)) { - GList * location = g_list_find(GTK_MENU_SHELL(main_menu)->children, users_separator); - position = g_list_position(GTK_MENU_SHELL(main_menu)->children, location) + 1; + if (newroot == NULL) { + gtk_widget_hide(GTK_WIDGET(status_separator)); + return; + } + + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(child_added), GUINT_TO_POINTER(STATUS_SECTION)); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(status_menu_added), NULL); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(status_menu_removed), NULL); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(child_moved), GUINT_TO_POINTER(STATUS_SECTION)); + + GList * child = NULL; + guint count = 0; + for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child), count++) { + child_added(newroot, DBUSMENU_MENUITEM(child->data), count, GUINT_TO_POINTER(STATUS_SECTION)); + } + + if (count > 0) { + gtk_widget_show(GTK_WIDGET(status_separator)); } - menu_add(container, widget, GTK_MENU(userdata), position); return; } - static gboolean build_status_menu (gpointer userdata) { + g_debug("Building Status Menu"); guint returnval = 0; GError * error = NULL; @@ -113,8 +178,8 @@ build_status_menu (gpointer userdata) return FALSE; } - status_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_STATUS_DBUS_NAME, INDICATOR_STATUS_DBUS_OBJECT)); - g_signal_connect(G_OBJECT(status_menu), DBUSMENU_GTKMENU_SIGNAL_ADD, G_CALLBACK(status_menu_add), main_menu); + status_client = dbusmenu_gtkclient_new(INDICATOR_STATUS_DBUS_NAME, INDICATOR_STATUS_DBUS_OBJECT); + g_signal_connect(G_OBJECT(status_client), DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(status_menu_root_changed), main_menu); status_separator = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), status_separator); @@ -123,9 +188,67 @@ build_status_menu (gpointer userdata) return FALSE; } +/* Users menu */ + +static guint +users_menu_pos_offset (void) +{ + guint position = 0; + if (SEPARATOR_SHOWN(status_separator)) { + GList * location = g_list_find(GTK_MENU_SHELL(main_menu)->children, status_separator); + position = g_list_position(GTK_MENU_SHELL(main_menu)->children, location) + 1; + } + + return position; +} + +static void +users_menu_added (DbusmenuMenuitem * root, DbusmenuMenuitem * child, guint position, gpointer user_data) +{ + gtk_widget_show(GTK_WIDGET(users_separator)); + return; +} + +static void +users_menu_removed (DbusmenuMenuitem * root, DbusmenuMenuitem * child, gpointer user_data) +{ + if (g_list_length(dbusmenu_menuitem_get_children(root)) == 0) { + gtk_widget_hide(GTK_WIDGET(users_separator)); + } + + return; +} + +static void +users_menu_root_changed(DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, GtkMenu * main) +{ + if (newroot == NULL) { + gtk_widget_hide(GTK_WIDGET(users_separator)); + return; + } + + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(child_added), GUINT_TO_POINTER(USERS_SECTION)); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(users_menu_added), NULL); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(users_menu_removed), NULL); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(child_moved), GUINT_TO_POINTER(USERS_SECTION)); + + GList * child = NULL; + guint count = 0; + for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child), count++) { + child_added(newroot, DBUSMENU_MENUITEM(child->data), count, GUINT_TO_POINTER(USERS_SECTION)); + } + + if (count > 0) { + gtk_widget_show(GTK_WIDGET(users_separator)); + } + + return; +} + static gboolean build_users_menu (gpointer userdata) { + g_debug("Building Users Menu"); guint returnval = 0; GError * error = NULL; @@ -145,8 +268,8 @@ build_users_menu (gpointer userdata) return FALSE; } - users_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_USERS_DBUS_NAME, INDICATOR_USERS_DBUS_OBJECT)); - g_signal_connect(G_OBJECT(users_menu), DBUSMENU_GTKMENU_SIGNAL_ADD, G_CALLBACK(users_menu_add), main_menu); + users_client = dbusmenu_gtkclient_new(INDICATOR_USERS_DBUS_NAME, INDICATOR_USERS_DBUS_OBJECT); + g_signal_connect(G_OBJECT(users_client), DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(users_menu_root_changed), main_menu); users_separator = gtk_separator_menu_item_new(); gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), users_separator); @@ -155,9 +278,55 @@ build_users_menu (gpointer userdata) return FALSE; } +/* Session Menu Stuff */ + +static guint +session_menu_pos_offset (void) +{ + guint position = 0; + if (SEPARATOR_SHOWN(users_separator)) { + GList * location = g_list_find(GTK_MENU_SHELL(main_menu)->children, users_separator); + position = g_list_position(GTK_MENU_SHELL(main_menu)->children, location) + 1; + } else if (SEPARATOR_SHOWN(status_separator)) { + GList * location = g_list_find(GTK_MENU_SHELL(main_menu)->children, status_separator); + position = g_list_position(GTK_MENU_SHELL(main_menu)->children, location) + 1; + } + + return position; +} + +static void +session_menu_removed (DbusmenuMenuitem * root, DbusmenuMenuitem * child, gpointer user_data) +{ + return; +} + +static void +session_menu_root_changed(DbusmenuGtkClient * client, DbusmenuMenuitem * newroot, GtkMenu * main) +{ + if (newroot == NULL) { + /* We're assuming this'll crash the least so it doesn't + hide a separator. May be a bad choice. */ + return; + } + + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_ADDED, G_CALLBACK(child_added), GUINT_TO_POINTER(SESSION_SECTION)); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_REMOVED, G_CALLBACK(session_menu_removed), NULL); + g_signal_connect(G_OBJECT(newroot), DBUSMENU_MENUITEM_SIGNAL_CHILD_MOVED, G_CALLBACK(child_moved), GUINT_TO_POINTER(SESSION_SECTION)); + + GList * child = NULL; + guint count = 0; + for (child = dbusmenu_menuitem_get_children(newroot); child != NULL; child = g_list_next(child), count++) { + child_added(newroot, DBUSMENU_MENUITEM(child->data), count, GUINT_TO_POINTER(SESSION_SECTION)); + } + + return; +} + static gboolean build_session_menu (gpointer userdata) { + g_debug("Building Session Menu"); guint returnval = 0; GError * error = NULL; @@ -177,17 +346,22 @@ build_session_menu (gpointer userdata) return FALSE; } - session_menu = GTK_MENU(dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_OBJECT)); - g_signal_connect(G_OBJECT(session_menu), DBUSMENU_GTKMENU_SIGNAL_ADD, G_CALLBACK(session_menu_add), main_menu); + session_client = dbusmenu_gtkclient_new(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_OBJECT); + g_signal_connect(G_OBJECT(session_client), DBUSMENU_GTKCLIENT_SIGNAL_ROOT_CHANGED, G_CALLBACK(session_menu_root_changed), main_menu); return FALSE; } +/* Base menu stuff */ + GtkMenu * get_menu (void) { connection = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); proxy = dbus_g_proxy_new_for_name(connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); + if (proxy == NULL) { + g_warning("Unable to get proxy for DBus itself. Seriously."); + } g_idle_add(build_status_menu, NULL); g_idle_add(build_users_menu, NULL); @@ -196,6 +370,7 @@ get_menu (void) main_menu = GTK_MENU(gtk_menu_new()); loading_item = gtk_menu_item_new_with_label("Loading..."); gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), loading_item); + gtk_widget_show(GTK_WIDGET(loading_item)); return main_menu; } |