diff options
Diffstat (limited to 'src/messages-service.c')
-rw-r--r-- | src/messages-service.c | 253 |
1 files changed, 221 insertions, 32 deletions
diff --git a/src/messages-service.c b/src/messages-service.c index ca9e799..0ebab0b 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -31,6 +31,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/client.h> #include <libdbusmenu-glib/server.h> +#include <libdbusmenu-glib/menuitem-proxy.h> #include "im-menu-item.h" #include "app-menu-item.h" @@ -48,7 +49,10 @@ static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; +#define DESKTOP_FILE_GROUP "Messaging Menu" +#define DESKTOP_FILE_KEY_DESKTOP "DesktopFile" +static void server_shortcuts_changed (AppMenuItem * appitem, gpointer data); static void server_count_changed (AppMenuItem * appitem, guint count, gpointer data); static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data); static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data); @@ -57,9 +61,14 @@ static void indicator_removed (IndicateListener * listener, IndicateListenerServ static void check_eclipses (AppMenuItem * ai); static void remove_eclipses (AppMenuItem * ai); static gboolean build_launcher (gpointer data); +static gboolean build_launcher_keyfile (gpointer data); +static void build_launcher_core (const gchar * desktop); static gboolean build_launchers (gpointer data); static gboolean blacklist_init (gpointer data); static gboolean blacklist_add (gpointer data); +static gchar * desktop_file_from_keyfile (const gchar * definition_file); +static gboolean blacklist_keyfile_add (gpointer udata); +static void blacklist_add_core (gchar * desktop, gchar * definition); static gboolean blacklist_remove (gpointer data); static void blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data); static void app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data); @@ -241,7 +250,11 @@ blacklist_init (gpointer data) while ((filename = g_dir_read_name(dir)) != NULL) { g_debug("Found file: %s", filename); gchar * path = g_build_filename(blacklistdir, filename, NULL); - g_idle_add(blacklist_add, path); + if (g_str_has_suffix(path, "keyfile")) { + g_idle_add(blacklist_keyfile_add, path); + } else { + g_idle_add(blacklist_add, path); + } } g_dir_close(dir); @@ -250,6 +263,53 @@ blacklist_init (gpointer data) return FALSE; } +/* Parses through a keyfile to find the desktop file entry and + pushes them into the blacklist. */ +static gboolean +blacklist_keyfile_add (gpointer udata) +{ + gchar * definition_file = (gchar *)udata; + gchar * desktopfile = desktop_file_from_keyfile(definition_file); + if (desktopfile != NULL) { + blacklist_add_core(desktopfile, definition_file); + g_free(desktopfile); + } + return FALSE; +} + +/* Takes a keyfile and finds the desktop file in it for + us. With some error handling. */ +static gchar * +desktop_file_from_keyfile (const gchar * definition_file) +{ + GKeyFile * keyfile = g_key_file_new(); + GError * error = NULL; + + if (!g_key_file_load_from_file(keyfile, definition_file, G_KEY_FILE_NONE, &error)) { + g_warning("Unable to load keyfile '%s' because: %s", definition_file, error == NULL ? "unknown" : error->message); + g_error_free(error); + g_key_file_free(keyfile); + return NULL; + } + + if (!g_key_file_has_group(keyfile, DESKTOP_FILE_GROUP)) { + g_warning("Unable to use keyfile '%s' as it has no '" DESKTOP_FILE_GROUP "' group.", definition_file); + g_key_file_free(keyfile); + return NULL; + } + + if (!g_key_file_has_key(keyfile, DESKTOP_FILE_GROUP, DESKTOP_FILE_KEY_DESKTOP, &error)) { + g_warning("Unable to use keyfile '%s' as there is no key '" DESKTOP_FILE_KEY_DESKTOP "' in the group '" DESKTOP_FILE_GROUP "' because: %s", definition_file, error == NULL ? "unknown" : error->message); + g_error_free(error); + g_key_file_free(keyfile); + return NULL; + } + + gchar * desktopfile = g_key_file_get_string(keyfile, DESKTOP_FILE_GROUP, DESKTOP_FILE_KEY_DESKTOP, &error); + g_key_file_free(keyfile); + return desktopfile; +} + /* Add a definition file into the black list and eclipse and launchers that have the same file. */ static gboolean @@ -268,38 +328,51 @@ blacklist_add (gpointer udata) gchar * trimdesktop = pango_trim_string(desktop); g_free(desktop); + blacklist_add_core(trimdesktop, definition_file); + g_free(trimdesktop); + + return FALSE; +} + +/* This takes a desktop file and tries to add it to the black + list for applications in the messaging menu. If it can, + then the launcher item gets marked as eclipsed and hidden + from the user. */ +static void +blacklist_add_core (gchar * desktop, gchar * definition) +{ /* Check for conflicts */ - gpointer data = g_hash_table_lookup(blacklist, trimdesktop); + gpointer data = g_hash_table_lookup(blacklist, desktop); if (data != NULL) { gchar * oldfile = (gchar *)data; - if (!g_strcmp0(oldfile, definition_file)) { + if (!g_strcmp0(oldfile, definition)) { g_warning("Already added file '%s'", oldfile); } else { - g_warning("Already have desktop file '%s' in blacklist file '%s' not adding from '%s'", trimdesktop, oldfile, definition_file); + g_warning("Already have desktop file '%s' in blacklist file '%s' not adding from '%s'", desktop, oldfile, definition); } - g_free(trimdesktop); - g_free(definition_file); - return FALSE; + return; } /* Actually blacklist this thing */ - g_hash_table_insert(blacklist, trimdesktop, definition_file); - g_debug("Adding Blacklist item '%s' for desktop '%s'", definition_file, trimdesktop); + g_hash_table_insert(blacklist, desktop, definition); + g_debug("Adding Blacklist item '%s' for desktop '%s'", definition, desktop); /* Go through and eclipse folks */ GList * launcher; for (launcher = launcherList; launcher != NULL; launcher = launcher->next) { launcherList_t * item = (launcherList_t *)launcher->data; - if (!g_strcmp0(trimdesktop, launcher_menu_item_get_desktop(item->menuitem))) { + if (!g_strcmp0(desktop, launcher_menu_item_get_desktop(item->menuitem))) { launcher_menu_item_set_eclipsed(item->menuitem, TRUE); - dbusmenu_menuitem_property_set(item->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(item->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); } } check_hidden(); + /* Shouldn't need a resort here as hiding shouldn't cause things to + move other than this item disappearing. */ - return FALSE; + return; } /* Remove a black list item based on the definition file @@ -340,7 +413,7 @@ blacklist_remove (gpointer data) } if (serveritem == NULL) { launcher_menu_item_set_eclipsed(li->menuitem, FALSE); - dbusmenu_menuitem_property_set(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "true"); + dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); } } } @@ -506,11 +579,21 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha /* Connect the signals up to the menu item */ g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_COUNT_CHANGED, G_CALLBACK(server_count_changed), sl_item); g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_NAME_CHANGED, G_CALLBACK(server_name_changed), menushell); + g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUTS_CHANGED, G_CALLBACK(server_shortcuts_changed), menushell); /* Put our new menu item in, with the separator behind it. resort_menu will take care of whether it should be hidden or not. */ dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem)); + + GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); + while (shortcuts != NULL) { + DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcuts->data); + g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_child_append(menushell, mi); + shortcuts = g_list_next(shortcuts); + } + dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator)); resort_menu(menushell); @@ -519,6 +602,50 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha return; } +/* The shortcuts have changed, let's just remove them and put + the back. */ +static void +server_shortcuts_changed (AppMenuItem * appitem, gpointer data) +{ + g_debug("Application Shortcuts changed"); + DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data); + gboolean appitemfound = FALSE; + GList * children = dbusmenu_menuitem_get_children(shell); + GList * removelist = NULL; + + while (children != NULL) { + if (!appitemfound && children->data != appitem) { + children = g_list_next(children); + continue; + } + appitemfound = TRUE; + + if (!DBUSMENU_IS_MENUITEM_PROXY(children->data)) { + break; + } + + removelist = g_list_prepend(removelist, children->data); + } + + GList * removeitem; + for (removeitem = removelist; removeitem != NULL; removeitem = g_list_next(removeitem)) { + dbusmenu_menuitem_child_delete(shell, DBUSMENU_MENUITEM(removeitem->data)); + } + g_list_free(removeitem); + + GList * shortcuts = app_menu_item_get_items(appitem); + while (shortcuts != NULL) { + DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcuts->data); + g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_child_append(shell, mi); + shortcuts = g_list_next(shortcuts); + } + + resort_menu(shell); + + return; +} + /* The name of a server has changed, we probably need to reorder the menu to keep it in alphabetical order. This happens often after we read the destkop @@ -626,14 +753,14 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc /* If there is a menu item, let's get rid of it. */ if (sltp->menuitem != NULL) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem)); g_object_unref(G_OBJECT(sltp->menuitem)); } /* If there is a separator, let's get rid of it. */ if (sltp->separator != NULL) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sltp->separator), DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->separator), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->separator)); g_object_unref(G_OBJECT(sltp->separator)); } @@ -724,12 +851,21 @@ resort_menu (DbusmenuMenuitem * menushell) dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position); position++; + /* Inserting the shortcuts from the launcher */ + GList * shortcuts = launcher_menu_item_get_items(li->menuitem); + while (shortcuts != NULL) { + g_debug("\t\tMoving shortcut to position %d", position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position); + position++; + shortcuts = g_list_next(shortcuts); + } + /* Putting the launcher separator in */ g_debug("\tMoving launcher separator to position %d", position); dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position); if (!launcher_menu_item_get_eclipsed(li->menuitem)) { /* Only clear the visiblity if we're not eclipsed */ - dbusmenu_menuitem_property_set(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "true"); + dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); last_separator = li->separator; } position++; @@ -746,6 +882,15 @@ resort_menu (DbusmenuMenuitem * menushell) g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position); dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->menuitem), position); position++; + + /* Inserting the shortcuts from the launcher */ + GList * shortcuts = app_menu_item_get_items(si->menuitem); + while (shortcuts != NULL) { + g_debug("\t\tMoving shortcut to position %d", position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position); + position++; + shortcuts = g_list_next(shortcuts); + } } /* Putting all the indicators that are related to this application @@ -765,7 +910,7 @@ resort_menu (DbusmenuMenuitem * menushell) if (si->separator != NULL) { g_debug("\tMoving app %s separator to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position); dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->separator), position); - dbusmenu_menuitem_property_set(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "true"); + dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); position++; last_separator = si->separator; } @@ -780,12 +925,21 @@ resort_menu (DbusmenuMenuitem * menushell) dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->menuitem), position); position++; + /* Inserting the shortcuts from the launcher */ + GList * shortcuts = launcher_menu_item_get_items(li->menuitem); + while (shortcuts != NULL) { + g_debug("\t\tMoving shortcut to position %d", position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position); + position++; + shortcuts = g_list_next(shortcuts); + } + /* Putting the launcher separator in */ g_debug("\tMoving launcher separator to position %d", position); dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(li->separator), position); if (!launcher_menu_item_get_eclipsed(li->menuitem)) { /* Only clear the visiblity if we're not eclipsed */ - dbusmenu_menuitem_property_set(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "true"); + dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); last_separator = li->separator; } position++; @@ -794,7 +948,7 @@ resort_menu (DbusmenuMenuitem * menushell) } if (last_separator != NULL) { - dbusmenu_menuitem_property_set(last_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(last_separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); } else { g_warning("No last separator on resort"); } @@ -953,7 +1107,7 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server, /* Hide the item immediately, and then remove it which might take a little longer. */ - dbusmenu_menuitem_property_set(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), menuitem); removed = TRUE; } @@ -981,7 +1135,11 @@ app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFile case G_FILE_MONITOR_EVENT_CREATED: { gchar * path = g_file_get_path(file); g_debug("\tCreate: %s", path); - g_idle_add(build_launcher, path); + if (g_str_has_suffix(path, "keyfile")) { + g_idle_add(build_launcher_keyfile, path); + } else { + g_idle_add(build_launcher, path); + } break; } default: @@ -1010,7 +1168,7 @@ check_eclipses (AppMenuItem * ai) if (!g_strcmp0(aidesktop, lidesktop)) { launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); - dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); break; } } @@ -1035,7 +1193,7 @@ remove_eclipses (AppMenuItem * ai) if (!g_strcmp0(aidesktop, lidesktop)) { launcher_menu_item_set_eclipsed(ll->menuitem, FALSE); - dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "true"); + dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); break; } } @@ -1087,7 +1245,7 @@ destroy_launcher (gpointer data) g_list_free(li->appdiritems); if (li->menuitem != NULL) { - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(li->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(li->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); dbusmenu_menuitem_child_delete(root_menuitem, DBUSMENU_MENUITEM(li->menuitem)); g_object_unref(G_OBJECT(li->menuitem)); li->menuitem = NULL; @@ -1119,11 +1277,34 @@ build_launcher (gpointer data) g_free(desktop); g_debug("\tcontents: %s", trimdesktop); + build_launcher_core(trimdesktop); + g_free(trimdesktop); + return FALSE; +} + +/* Use a key file to find the desktop file. */ +static gboolean +build_launcher_keyfile (gpointer data) +{ + gchar * path = (gchar *)data; + gchar * desktop = desktop_file_from_keyfile (path); + if (desktop != NULL) { + build_launcher_core(desktop); + g_free(desktop); + } + return FALSE; +} + +/* The core action of dealing with a desktop file that should + be a launcher */ +static void +build_launcher_core (const gchar * desktop) +{ /* Check to see if we already have a launcher */ GList * listitem; for (listitem = launcherList; listitem != NULL; listitem = listitem->next) { launcherList_t * li = (launcherList_t *)listitem->data; - if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), trimdesktop)) { + if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), desktop)) { break; } } @@ -1132,9 +1313,8 @@ build_launcher (gpointer data) /* If not */ /* Build the item */ launcherList_t * ll = g_new0(launcherList_t, 1); - ll->menuitem = launcher_menu_item_new(trimdesktop); - g_free(trimdesktop); - ll->appdiritems = g_list_append(NULL, path); + ll->menuitem = launcher_menu_item_new(desktop); + ll->appdiritems = g_list_append(NULL, g_strdup(desktop)); /* Build a separator */ ll->separator = dbusmenu_menuitem_new(); @@ -1145,6 +1325,11 @@ build_launcher (gpointer data) /* Add it to the menu */ dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->menuitem)); + GList * shortcuts = launcher_menu_item_get_items(ll->menuitem); + while (shortcuts != NULL) { + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcuts->data)); + shortcuts = g_list_next(shortcuts); + } dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->separator)); /* If we're in the black list or we've gotten eclipsed @@ -1152,7 +1337,7 @@ build_launcher (gpointer data) if (blacklist_check(launcher_menu_item_get_desktop(ll->menuitem)) || launcher_menu_item_get_eclipsed(ll->menuitem)) { launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); - dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, "false"); + dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); } resort_menu(root_menuitem); @@ -1160,10 +1345,10 @@ build_launcher (gpointer data) } else { /* If so add ourselves */ launcherList_t * ll = (launcherList_t *)listitem->data; - ll->appdiritems = g_list_append(ll->appdiritems, path); + ll->appdiritems = g_list_append(ll->appdiritems, g_strdup(desktop)); } - return FALSE; + return; } /* This function goes through all the launchers that we're @@ -1197,7 +1382,11 @@ build_launchers (gpointer data) while ((filename = g_dir_read_name(dir)) != NULL) { g_debug("Found file: %s", filename); gchar * path = g_build_filename(directory, filename, NULL); - g_idle_add(build_launcher, path); + if (g_str_has_suffix(path, "keyfile")) { + g_idle_add(build_launcher_keyfile, path); + } else { + g_idle_add(build_launcher, path); + } } g_dir_close(dir); |