From ab416588f88aa199193f234220f102788c0493c0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Fri, 18 May 2012 23:41:22 +0200 Subject: Remove the seen db It was only really used to figure out whether one of the default apps was ever running, so that "Set up..." or the app name and actions would be shown in the menu. Since there are no default apps anymore, this is not needed either. --- src/messages-service.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 078cee3..2188ab0 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -39,7 +39,6 @@ with this program. If not, see . #include "dbus-data.h" #include "dirs.h" #include "messages-service-dbus.h" -#include "seen-db.h" #include "status-items.h" static IndicatorService * service = NULL; @@ -1533,9 +1532,6 @@ main (int argc, char ** argv) bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); - /* Create the Seen DB */ - seen_db_init(); - /* Bring up the service DBus interface */ dbus_interface = message_service_dbus_new(); -- cgit v1.2.3 From 14716e2d8d8bf7ccd8ba3ee2e9607a718bf2ff66 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 21 May 2012 16:45:58 +0200 Subject: Use a gsettings list for finding out which apps should appear in the menu Previously, this was handled by looking for .desktop files in various system and user directories. The messaging menu should not display any applications by default anymore, so a simple per-user gsettings list suffices. A neat side effect is that the hairy blacklist handling is not needed anymore, either. Small regression: apps are not configurable at runtime anymore (settings key is not listened to for changes). --- src/messages-service.c | 506 +++---------------------------------------------- 1 file changed, 23 insertions(+), 483 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 2188ab0..12b1ded 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -28,6 +28,7 @@ with this program. If not, see . #include #include #include +#include #include #include @@ -37,7 +38,6 @@ with this program. If not, see . #include "app-menu-item.h" #include "launcher-menu-item.h" #include "dbus-data.h" -#include "dirs.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -49,6 +49,7 @@ static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; static DbusmenuMenuitem * status_separator = NULL; static DbusmenuMenuitem * clear_attention = NULL; +static GSettings *settings; static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; @@ -66,18 +67,8 @@ 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); -static gboolean destroy_launcher (gpointer data); static void check_hidden (void); @@ -219,311 +210,6 @@ launcherList_count (void) return count; } -/* - * Black List - */ - -static GHashTable * blacklist = NULL; -static GFileMonitor * blacklistdirmon = NULL; - -/* Initialize the black list and start to setup - handlers for it. */ -static gboolean -blacklist_init (gpointer data) -{ - blacklist = g_hash_table_new_full(g_str_hash, g_str_equal, - g_free, g_free); - - gchar * blacklistdir = g_build_filename(g_get_user_config_dir(), USER_BLACKLIST_DIR, NULL); - g_debug("Looking at blacklist: %s", blacklistdir); - if (!g_file_test(blacklistdir, G_FILE_TEST_IS_DIR)) { - g_free(blacklistdir); - return FALSE; - } - - GFile * filedir = g_file_new_for_path(blacklistdir); - blacklistdirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL); - if (blacklistdirmon != NULL) { - g_signal_connect(G_OBJECT(blacklistdirmon), "changed", G_CALLBACK(blacklist_dir_changed), NULL); - } - - GError * error = NULL; - GDir * dir = g_dir_open(blacklistdir, 0, &error); - if (dir == NULL) { - g_warning("Unable to open blacklist directory (%s): %s", blacklistdir, error == NULL ? "No Message" : error->message); - g_error_free(error); - g_free(blacklistdir); - return FALSE; - } - - const gchar * filename = NULL; - while ((filename = g_dir_read_name(dir)) != NULL) { - g_debug("Found file: %s", filename); - gchar * path = g_build_filename(blacklistdir, filename, NULL); - 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); - g_free(blacklistdir); - - 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; -} - -/* Check if path is a symlink and return its target if it is */ -static gchar * -get_symlink_target (const gchar *path) -{ - GFile *file; - GFileInfo *fileinfo; - gchar *target = NULL; - - file = g_file_new_for_path (path); - - fileinfo = g_file_query_info (file, "standard::is-symlink", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - g_object_unref (file); - - if (!fileinfo) - return NULL; - - if (g_file_info_get_is_symlink (fileinfo)) - target = g_strdup (g_file_info_get_symlink_target (fileinfo)); - - g_object_unref (fileinfo); - return target; -} - -/* Add a definition file into the black list and eclipse - any launchers that have the same file. */ -static gboolean -blacklist_add (gpointer udata) -{ - gchar * definition_file = (gchar *)udata; - gchar * symlink_target = get_symlink_target (definition_file); - gchar * contents = NULL; - - if (symlink_target) - { - blacklist_add_core (symlink_target, definition_file); - g_free (symlink_target); - } - else if (g_str_has_suffix (definition_file, ".desktop")) - { - blacklist_add_core(definition_file, definition_file); - } - else if (g_file_get_contents (definition_file, &contents, NULL, NULL)) - { - gchar *trimmed = pango_trim_string (contents); - blacklist_add_core (trimmed, definition_file); - g_free (trimmed); - g_free (contents); - } - else - g_warning ("invalid blacklist entry: %s", definition_file); - - 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) -{ - gchar *basename = g_path_get_basename(desktop); - - /* Check for conflicts */ - gpointer data = g_hash_table_lookup(blacklist, basename); - if (data != NULL) { - gchar * oldfile = (gchar *)data; - 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'", desktop, oldfile, definition); - } - - g_free(basename); - return; - } - - /* Actually blacklist this thing */ - g_hash_table_insert(blacklist, g_strdup(basename), g_strdup(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; - gchar * item_basename = g_path_get_basename(launcher_menu_item_get_desktop(item->menuitem)); - if (!g_strcmp0(basename, item_basename)) { - launcher_menu_item_set_eclipsed(item->menuitem, TRUE); - dbusmenu_menuitem_property_set_bool(item->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - g_free(item_basename); - } - - check_hidden(); - /* Shouldn't need a resort here as hiding shouldn't cause things to - move other than this item disappearing. */ - - g_free(basename); - return; -} - -/* Remove a black list item based on the definition file - and uneclipse those launchers blocked by it. */ -static gboolean -blacklist_remove (gpointer data) -{ - gchar * definition_file = (gchar *)data; - g_debug("Removing: %s", definition_file); - - GHashTableIter iter; - gpointer key, value; - gboolean found = FALSE; - - g_hash_table_iter_init(&iter, blacklist); - while (g_hash_table_iter_next(&iter, &key, &value)) { - if (!g_strcmp0((gchar *)value, definition_file)) { - found = TRUE; - break; - } - } - - if (!found) { - g_debug("\tNot found!"); - return FALSE; - } - - GList * launcheritem; - for (launcheritem = launcherList; launcheritem != NULL; launcheritem = launcheritem->next) { - launcherList_t * li = (launcherList_t *)launcheritem->data; - if (!g_strcmp0(launcher_menu_item_get_desktop(li->menuitem), (gchar *)key)) { - GList * serveritem; - for (serveritem = serverList; serveritem != NULL; serveritem = serveritem->next) { - serverList_t * si = (serverList_t *)serveritem->data; - if (!g_strcmp0(app_menu_item_get_desktop(si->menuitem), (gchar *)key)) { - break; - } - } - if (serveritem == NULL) { - launcher_menu_item_set_eclipsed(li->menuitem, FALSE); - dbusmenu_menuitem_property_set_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - } - } - } - - if (!g_hash_table_remove(blacklist, key)) { - g_warning("Unable to remove '%s' with value '%s'", definition_file, (gchar *)key); - } - - check_hidden(); - resort_menu(root_menuitem); - - return FALSE; -} - -/* Check to see if a particular desktop file is - in the blacklist. */ -static gboolean -blacklist_check (const gchar * desktop_file) -{ - gchar *basename = g_path_get_basename(desktop_file); - gboolean found; - - g_debug("Checking blacklist for: %s", basename); - - if (blacklist && g_hash_table_lookup(blacklist, basename)) { - g_debug("\tFound!"); - found = TRUE; - } - else - found = FALSE; - - g_free(basename); - return found; -} - -/* A callback everytime the blacklist directory changes - in some way. It needs to handle that. */ -static void -blacklist_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data) -{ - g_debug("Blacklist directory changed!"); - - switch (event_type) { - case G_FILE_MONITOR_EVENT_DELETED: { - gchar * path = g_file_get_path(file); - g_debug("\tDelete: %s", path); - g_idle_add(blacklist_remove, path); - break; - } - case G_FILE_MONITOR_EVENT_CREATED: { - gchar * path = g_file_get_path(file); - g_debug("\tCreate: %s", path); - g_idle_add(blacklist_add, path); - break; - } - default: - break; - } - - return; -} - /* * More code */ @@ -1186,36 +872,6 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server, return; } -static void -app_dir_changed (GFileMonitor * monitor, GFile * file, GFile * other_file, GFileMonitorEvent event_type, gpointer user_data) -{ - gchar * directory = (gchar *)user_data; - g_debug("Application directory changed: %s", directory); - - switch (event_type) { - case G_FILE_MONITOR_EVENT_DELETED: { - gchar * path = g_file_get_path(file); - g_debug("\tDelete: %s", path); - g_idle_add(destroy_launcher, path); - break; - } - case G_FILE_MONITOR_EVENT_CREATED: { - gchar * path = g_file_get_path(file); - g_debug("\tCreate: %s", path); - if (g_str_has_suffix(path, "keyfile")) { - g_idle_add(build_launcher_keyfile, path); - } else { - g_idle_add(build_launcher, path); - } - break; - } - default: - break; - } - - return; -} - /* Check to see if a new desktop file causes any of the launchers to be eclipsed by a running process */ @@ -1251,8 +907,6 @@ remove_eclipses (AppMenuItem * ai) const gchar * aidesktop = app_menu_item_get_desktop(ai); if (aidesktop == NULL) return; - if (blacklist_check(aidesktop)) return; - GList * llitem; for (llitem = launcherList; llitem != NULL; llitem = llitem->next) { launcherList_t * ll = (launcherList_t *)llitem->data; @@ -1268,108 +922,19 @@ remove_eclipses (AppMenuItem * ai) return; } -/* Remove a launcher from the system. We need to figure - out what it's up to! */ -static gboolean -destroy_launcher (gpointer data) -{ - gchar * appdirentry = (gchar *)data; - - GList * listitem; - GList * direntry; - launcherList_t * li; - gchar * appdir; - - for (listitem = launcherList; listitem != NULL; listitem = listitem->next) { - li = (launcherList_t *)listitem->data; - for (direntry = li->appdiritems; direntry != NULL; direntry = direntry->next) { - appdir = (gchar *)direntry->data; - if (!g_strcmp0(appdir, appdirentry)) { - break; - } - } - - if (direntry != NULL) { - break; - } - } - - if (listitem == NULL) { - g_warning("Removed '%s' by the way of it not seeming to exist anywhere.", appdirentry); - return FALSE; - } - - if (g_list_length(li->appdiritems) > 1) { - /* Just remove this item, and we can move on */ - g_debug("Just removing file entry: %s", appdir); - li->appdiritems = g_list_remove(li->appdiritems, appdir); - g_free(appdir); - return FALSE; - } - - /* Full Destroy */ - g_free(appdir); - g_list_free(li->appdiritems); - - if (li->menuitem != NULL) { - /* If there are shortcuts remove them */ - GList * shortcuts = launcher_menu_item_get_items(li->menuitem); - while (shortcuts != NULL) { - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcuts->data)); - shortcuts = g_list_next(shortcuts); - } - - 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; - } - - launcherList = g_list_remove(launcherList, li); - g_free(li); - - return FALSE; -} - /* This function turns a specific file into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) { - /* Read the file get the data */ - gchar * path = (gchar *)data; - g_debug("\tpath: %s", path); - gchar * desktop = NULL; - - g_file_get_contents(path, &desktop, NULL, NULL); + gchar *desktop_id = data; + GDesktopAppInfo *appinfo; - if (desktop == NULL) { - g_free(path); - return FALSE; - } + appinfo = g_desktop_app_info_new (desktop_id); + build_launcher_core(g_desktop_app_info_get_filename (appinfo)); - gchar * trimdesktop = pango_trim_string(desktop); - g_free(desktop); - g_debug("\tcontents: %s", trimdesktop); - - build_launcher_core(trimdesktop); - g_free(trimdesktop); - g_free(path); - 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); - } - g_free(path); + g_object_unref (appinfo); + g_free (desktop_id); return FALSE; } @@ -1411,10 +976,9 @@ build_launcher_core (const gchar * desktop) } dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(ll->separator)); - /* If we're in the black list or we've gotten eclipsed - by something else, hide the item and the separator. */ - if (blacklist_check(launcher_menu_item_get_desktop(ll->menuitem)) || - launcher_menu_item_get_eclipsed(ll->menuitem)) { + /* If we've gotten eclipsed by something else, hide the item + * and the separator. */ + if (launcher_menu_item_get_eclipsed(ll->menuitem)) { launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); } @@ -1445,39 +1009,19 @@ build_launcher_core (const gchar * desktop) static gboolean build_launchers (gpointer data) { - gchar * directory = (gchar *)data; - - if (!g_file_test(directory, G_FILE_TEST_IS_DIR)) { - return FALSE; - } + gchar **applications = g_settings_get_strv (settings, "applications"); + gchar **app; - GFile * filedir = g_file_new_for_path(directory); - GFileMonitor * dirmon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL); - if (dirmon != NULL) { - g_signal_connect(G_OBJECT(dirmon), "changed", G_CALLBACK(app_dir_changed), directory); - } + g_return_val_if_fail (applications != NULL, FALSE); - GError * error = NULL; - GDir * dir = g_dir_open(directory, 0, &error); - if (dir == NULL) { - g_warning("Unable to open system apps directory: %s", error->message); - g_error_free(error); - return FALSE; - } - - const gchar * filename = NULL; - while ((filename = g_dir_read_name(dir)) != NULL) { - g_debug("Found file: %s", filename); - gchar * path = g_build_filename(directory, filename, NULL); - if (g_str_has_suffix(path, "keyfile")) { - g_idle_add(build_launcher_keyfile, path); - } else { - g_idle_add(build_launcher, path); - } + for (app = applications; *app; app++) + { + g_idle_add(build_launcher, g_strdup (*app)); } - g_dir_close(dir); launcherList = g_list_sort(launcherList, launcherList_sort); + + g_strfreev (applications); return FALSE; } @@ -1566,13 +1110,9 @@ main (int argc, char ** argv) g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem); g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem); - /* Find launchers by looking through the config directories - in the idle loop */ - g_idle_add(blacklist_init, NULL); - g_idle_add(build_launchers, SYSTEM_APPS_DIR); - g_idle_add(build_launchers, SYSTEM_APPS_DIR_OLD); - gchar * userdir = g_build_filename(g_get_user_config_dir(), USER_APPS_DIR, NULL); - g_idle_add(build_launchers, userdir); + settings = g_settings_new ("com.canonical.indicator.messages"); + + g_idle_add(build_launchers, NULL); /* Let's run a mainloop */ mainloop = g_main_loop_new(NULL, FALSE); @@ -1580,7 +1120,7 @@ main (int argc, char ** argv) /* Clean up */ status_items_cleanup(); - g_free(userdir); + g_object_unref (settings); return 0; } -- cgit v1.2.3 From 5faae9360d6836f4b5ab59ef2bbbf7cb624bafc1 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 21 May 2012 19:07:25 +0200 Subject: Move build_launcher_core into build_launcher --- src/messages-service.c | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 12b1ded..547e527 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -67,7 +67,6 @@ 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 void build_launcher_core (const gchar * desktop); static gboolean build_launchers (gpointer data); static void check_hidden (void); @@ -170,7 +169,6 @@ typedef struct _launcherList_t launcherList_t; struct _launcherList_t { LauncherMenuItem * menuitem; DbusmenuMenuitem * separator; - GList * appdiritems; }; static gint @@ -928,21 +926,12 @@ static gboolean build_launcher (gpointer data) { gchar *desktop_id = data; + const gchar *desktop = data; GDesktopAppInfo *appinfo; appinfo = g_desktop_app_info_new (desktop_id); - build_launcher_core(g_desktop_app_info_get_filename (appinfo)); + desktop = g_desktop_app_info_get_filename (appinfo); - g_object_unref (appinfo); - g_free (desktop_id); - 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) { @@ -957,7 +946,6 @@ build_launcher_core (const gchar * desktop) /* Build the item */ launcherList_t * ll = g_new0(launcherList_t, 1); ll->menuitem = launcher_menu_item_new(desktop); - ll->appdiritems = g_list_append(NULL, g_strdup(desktop)); /* Build a separator */ ll->separator = dbusmenu_menuitem_new(); @@ -993,13 +981,11 @@ build_launcher_core (const gchar * desktop) resort_menu(root_menuitem); check_hidden(); - } else { - /* If so add ourselves */ - launcherList_t * ll = (launcherList_t *)listitem->data; - ll->appdiritems = g_list_append(ll->appdiritems, g_strdup(desktop)); } - return; + g_object_unref (appinfo); + g_free (desktop_id); + return FALSE; } /* This function goes through all the launchers that we're -- cgit v1.2.3 From 6d16700bcbf52e66fffba24d8077ea7c09ddc771 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 21 May 2012 20:39:05 +0200 Subject: Allow creating AppMenuItems without initial listener / server --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 547e527..1b01e4b 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -286,7 +286,7 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha } /* Build the Menu item */ - AppMenuItem * menuitem = app_menu_item_new(listener, server); + AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); /* Build a possible server structure */ serverList_t * sl_item = g_new0(serverList_t, 1); -- cgit v1.2.3 From 8960bbafb9805c1e787e70bb2289cb8bc95a5f30 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 23 May 2012 21:30:00 +0200 Subject: Merge launcher- and appmenuitems --- src/messages-service.c | 415 ++++++++++++++----------------------------------- 1 file changed, 117 insertions(+), 298 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 1b01e4b..0934b9c 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -36,7 +36,6 @@ with this program. If not, see . #include "im-menu-item.h" #include "app-menu-item.h" -#include "launcher-menu-item.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -44,7 +43,6 @@ with this program. If not, see . static IndicatorService * service = NULL; static IndicateListener * listener = NULL; static GList * serverList = NULL; -static GList * launcherList = NULL; static DbusmenuMenuitem * root_menuitem = NULL; static DbusmenuMenuitem * status_separator = NULL; @@ -64,11 +62,8 @@ static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer d static void im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data); static void resort_menu (DbusmenuMenuitem * menushell); static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data); -static void check_eclipses (AppMenuItem * ai); -static void remove_eclipses (AppMenuItem * ai); static gboolean build_launcher (gpointer data); static gboolean build_launchers (gpointer data); -static void check_hidden (void); /* @@ -161,56 +156,6 @@ imList_sort (gconstpointer a, gconstpointer b) return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem))); } -/* - * Launcher List - */ - -typedef struct _launcherList_t launcherList_t; -struct _launcherList_t { - LauncherMenuItem * menuitem; - DbusmenuMenuitem * separator; -}; - -static gint -launcherList_sort (gconstpointer a, gconstpointer b) -{ - launcherList_t * pa, * pb; - - pa = (launcherList_t *)a; - pb = (launcherList_t *)b; - - const gchar * pan = launcher_menu_item_get_name(pa->menuitem); - const gchar * pbn = launcher_menu_item_get_name(pb->menuitem); - - return g_strcmp0(pan, pbn); -} - -static void -launcherList_count_helper (gpointer data, gpointer user_data) -{ - guint * count = (guint *)user_data; - launcherList_t * li = (launcherList_t *)data; - - if (!launcher_menu_item_get_eclipsed(li->menuitem)) { - *count = *count + 1; - } - - return; -} - -static guint -launcherList_count (void) -{ - guint count = 0; - - g_list_foreach(launcherList, launcherList_count_helper, &count); - - return count; -} - -/* - * More code - */ /* Goes through all the servers and sees if any of them want attention. If they do, then well we'll give it @@ -259,6 +204,84 @@ server_attention (serverList_t * slt) return; } +static void +desktop_cb (IndicateListener *listener, + IndicateListenerServer *server, + const gchar *value, + gpointer data) +{ + DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); + GList *listitem; + serverList_t * sl_item = NULL; + + /* Check to see if we already have a launcher for this app */ + for (listitem = serverList; listitem != NULL; listitem = listitem->next) { + serverList_t * slt = listitem->data; + if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), value)) { + sl_item = slt; + break; + } + } + + if (!sl_item) { + /* Build the Menu item */ + AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); + + /* Build a possible server structure */ + sl_item = g_new0(serverList_t, 1); + sl_item->server = server; + sl_item->menuitem = menuitem; + sl_item->imList = NULL; + sl_item->attention = FALSE; + sl_item->count = 0; + + /* Build a separator */ + sl_item->separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + + /* 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_SHORTCUT_ADDED, G_CALLBACK(server_shortcut_added), menushell); + g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, G_CALLBACK(server_shortcut_removed), 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)); + + /* Incase we got an indicator first */ + GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal); + if (alreadythere != NULL) { + /* Use the one we already had */ + g_free(sl_item); + sl_item = (serverList_t *)alreadythere->data; + sl_item->menuitem = menuitem; + serverList = g_list_sort(serverList, serverList_sort); + } else { + /* Insert the new one in the list */ + serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort); + } + + dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator)); + } + else { + app_menu_item_set_server (sl_item->menuitem, listener, server); + } + + GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcut->data); + g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_child_append(menushell, mi); + shortcut = g_list_next(shortcut); + } + g_list_free (shortcuts); + + resort_menu(menushell); +} + /* A new server has been created on the indicate bus. We need to check to see if we like it. And build structures for it if so. */ @@ -279,65 +302,9 @@ server_added (IndicateListener * listener, IndicateListenerServer * server, gcha return; } - DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); - if (menushell == NULL) { - g_error("\tData in callback is not a menushell"); - return; - } - - /* Build the Menu item */ - AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); - - /* Build a possible server structure */ - serverList_t * sl_item = g_new0(serverList_t, 1); - sl_item->server = server; - sl_item->menuitem = menuitem; - sl_item->imList = NULL; - sl_item->attention = FALSE; - sl_item->count = 0; - - /* Incase we got an indicator first */ - GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal); - if (alreadythere != NULL) { - /* Use the one we already had */ - g_free(sl_item); - sl_item = (serverList_t *)alreadythere->data; - sl_item->menuitem = menuitem; - serverList = g_list_sort(serverList, serverList_sort); - } else { - /* Insert the new one in the list */ - serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort); - } - - /* Build a separator */ - sl_item->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - - /* 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_SHORTCUT_ADDED, G_CALLBACK(server_shortcut_added), menushell); - g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, G_CALLBACK(server_shortcut_removed), 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); - check_hidden(); - - return; + /* fetch the desktop file before creating the menu item, in case we + * already have a launcher for it */ + indicate_listener_server_get_desktop(listener, server, desktop_cb, data); } /* Server shortcut has been added */ @@ -372,7 +339,6 @@ static void server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data) { serverList = g_list_sort(serverList, serverList_sort); - check_eclipses(appitem); resort_menu(DBUSMENU_MENUITEM(data)); return; } @@ -466,19 +432,18 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc /* Remove from the server list */ serverList = g_list_remove(serverList, sltp); - /* Remove launchers this could be eclipsing */ - remove_eclipses(sltp->menuitem); - /* If there is a menu item, let's get rid of it. */ if (sltp->menuitem != NULL) { /* If there are shortcuts remove them */ GList * shortcuts = app_menu_item_get_items(sltp->menuitem); - while (shortcuts != NULL) { - g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_LABEL)); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcuts->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcuts->data)); - shortcuts = g_list_next(shortcuts); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_LABEL)); + dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); + dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcut->data)); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); g_debug("\tRemoving item"); dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); @@ -506,8 +471,6 @@ server_removed (IndicateListener * listener, IndicateListenerServer * server, gc g_free(sltp); - check_hidden(); - return; } @@ -531,9 +494,12 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { AppMenuItem * appmenu = APP_MENU_ITEM(data_mi); if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) { + GList *shortcuts = app_menu_item_get_items(appmenu); msl->found = TRUE; /* Return a position at the end of our shortcuts */ - msl->position += g_list_length(app_menu_item_get_items(appmenu)); + msl->position += g_list_length(shortcuts); + g_list_free (shortcuts); + } else { msl->position++; } @@ -541,24 +507,6 @@ menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { return; } -static void -check_hidden (void) -{ - g_debug("Checking Hidden..."); - gboolean hide = FALSE; - if (launcherList_count() == 0) { - g_debug("\tZero Launchers"); - /* If we don't have visible launchers we need to look more */ - if (g_list_length(serverList) == 0) { - g_debug("\tZero Applications"); - hide = TRUE; - } - } - - message_service_dbus_set_icon(dbus_interface, hide); - return; -} - /* This function takes care of putting the menu in the right order. It basically it rebuilds the order by looking through all the applications and launchers and puts them in the right place. The @@ -569,7 +517,6 @@ resort_menu (DbusmenuMenuitem * menushell) { guint position = 0; GList * serverentry; - GList * launcherentry = launcherList; g_debug("Reordering Menu:"); @@ -581,41 +528,6 @@ resort_menu (DbusmenuMenuitem * menushell) for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) { serverList_t * si = (serverList_t *)serverentry->data; - /* Looking to see if there are any launchers we need to insert - into the menu structure. We put as many as we need to. */ - if (launcherentry != NULL) { - launcherList_t * li = (launcherList_t *)launcherentry->data; - while (launcherentry != NULL && g_strcmp0(launcher_menu_item_get_name(li->menuitem), app_menu_item_get_name(si->menuitem)) < 0) { - /* Putting the launcher item in */ - g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position); - 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_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - } - position++; - - launcherentry = launcherentry->next; - if (launcherentry != NULL) { - li = (launcherList_t *)launcherentry->data; - } - } - } - /* Putting the app menu item in */ if (si->menuitem != NULL) { g_debug("\tMoving app %s to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position); @@ -624,12 +536,14 @@ resort_menu (DbusmenuMenuitem * menushell) /* Inserting the shortcuts from the launcher */ GList * shortcuts = app_menu_item_get_items(si->menuitem); - while (shortcuts != NULL) { + GList * shortcut = shortcuts; + while (shortcut != NULL) { g_debug("\t\tMoving shortcut to position %d", position); - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcuts->data), position); + dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcut->data), position); position++; - shortcuts = g_list_next(shortcuts); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); } /* Putting all the indicators that are related to this application @@ -668,36 +582,6 @@ resort_menu (DbusmenuMenuitem * menushell) } } - /* Put any leftover launchers in at the end of the list. */ - while (launcherentry != NULL) { - launcherList_t * li = (launcherList_t *)launcherentry->data; - - /* Putting the launcher in */ - g_debug("\tMoving launcher '%s' to position %d", launcher_menu_item_get_name(li->menuitem), position); - 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_bool(li->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - } - position++; - - launcherentry = launcherentry->next; - } - if (clear_attention != NULL) { dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), clear_attention, position); position++; /* Not needed, but reduce bugs on code tacked on here, compiler will remove */ @@ -870,73 +754,22 @@ indicator_removed (IndicateListener * listener, IndicateListenerServer * server, return; } -/* Check to see if a new desktop file causes - any of the launchers to be eclipsed by a running - process */ -static void -check_eclipses (AppMenuItem * ai) -{ - g_debug("Checking eclipsing"); - const gchar * aidesktop = app_menu_item_get_desktop(ai); - if (aidesktop == NULL) return; - g_debug("\tApp desktop: %s", aidesktop); - - GList * llitem; - for (llitem = launcherList; llitem != NULL; llitem = llitem->next) { - launcherList_t * ll = (launcherList_t *)llitem->data; - const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem); - g_debug("\tLauncher desktop: %s", lidesktop); - - if (!g_strcmp0(aidesktop, lidesktop)) { - launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); - dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - break; - } - } - - return; -} - -/* Remove any eclipses that might have been caused - by this app item that is now retiring */ -static void -remove_eclipses (AppMenuItem * ai) -{ - const gchar * aidesktop = app_menu_item_get_desktop(ai); - if (aidesktop == NULL) return; - - GList * llitem; - for (llitem = launcherList; llitem != NULL; llitem = llitem->next) { - launcherList_t * ll = (launcherList_t *)llitem->data; - const gchar * lidesktop = launcher_menu_item_get_desktop(ll->menuitem); - - if (!g_strcmp0(aidesktop, lidesktop)) { - launcher_menu_item_set_eclipsed(ll->menuitem, FALSE); - dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - break; - } - } - - return; -} - /* This function turns a specific file into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) { gchar *desktop_id = data; - const gchar *desktop = data; GDesktopAppInfo *appinfo; + GList *listitem; appinfo = g_desktop_app_info_new (desktop_id); - desktop = g_desktop_app_info_get_filename (appinfo); /* 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), desktop)) { + for (listitem = serverList; listitem != NULL; listitem = listitem->next) { + serverList_t * slt = listitem->data; + if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), + g_desktop_app_info_get_filename (appinfo))) { break; } } @@ -944,43 +777,29 @@ build_launcher (gpointer data) if (listitem == NULL) { /* If not */ /* Build the item */ - launcherList_t * ll = g_new0(launcherList_t, 1); - ll->menuitem = launcher_menu_item_new(desktop); + serverList_t * sl_item = g_new0(serverList_t, 1); + sl_item->menuitem = app_menu_item_new(appinfo); /* Build a separator */ - ll->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(ll->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); + sl_item->separator = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); /* Add it to the list */ - launcherList = g_list_insert_sorted(launcherList, ll, launcherList_sort); + serverList = g_list_insert_sorted (serverList, sl_item, serverList_sort); /* Add it to the menu */ - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(ll->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - 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've gotten eclipsed by something else, hide the item - * and the separator. */ - if (launcher_menu_item_get_eclipsed(ll->menuitem)) { - launcher_menu_item_set_eclipsed(ll->menuitem, TRUE); - dbusmenu_menuitem_property_set_bool(ll->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } - - /* Check to see if any of the current applications should - be eclipsing us. */ - GList * server; - for (server = serverList; server != NULL; server = g_list_next(server)) { - serverList_t * slt = (serverList_t *)server->data; - check_eclipses(slt->menuitem); + dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sl_item->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->menuitem)); + GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); + GList * shortcut = shortcuts; + while (shortcut != NULL) { + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcut->data)); + shortcut = g_list_next(shortcut); } + g_list_free (shortcuts); + dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->separator)); resort_menu(root_menuitem); - check_hidden(); } g_object_unref (appinfo); @@ -1005,7 +824,7 @@ build_launchers (gpointer data) g_idle_add(build_launcher, g_strdup (*app)); } - launcherList = g_list_sort(launcherList, launcherList_sort); + serverList = g_list_sort(serverList, serverList_sort); g_strfreev (applications); return FALSE; -- cgit v1.2.3 From e1c600ba95e4520caf471ebf2eb9f41e2580fa98 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 24 May 2012 22:28:40 +0200 Subject: Port to gmenu, act I Work-in-progress of the gmenu port for the service. The bulk of this patch removes everything related to libindicate from the service. Only the static app launchers and their configured shortcut actions are exported for now. --- src/messages-service.c | 807 ++++--------------------------------------------- 1 file changed, 57 insertions(+), 750 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 0934b9c..432846e 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -25,46 +25,27 @@ with this program. If not, see . #include #include #include -#include #include #include #include #include -#include -#include - -#include "im-menu-item.h" #include "app-menu-item.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" static IndicatorService * service = NULL; -static IndicateListener * listener = NULL; static GList * serverList = NULL; -static DbusmenuMenuitem * root_menuitem = NULL; -static DbusmenuMenuitem * status_separator = NULL; -static DbusmenuMenuitem * clear_attention = NULL; +static GDBusConnection *bus; +static GSimpleActionGroup *actions; +static GMenu *menu; static GSettings *settings; static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; -#define DESKTOP_FILE_GROUP "Messaging Menu" -#define DESKTOP_FILE_KEY_DESKTOP "DesktopFile" - -static void server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data); -static void server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, 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); -static void resort_menu (DbusmenuMenuitem * menushell); -static void indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data); -static gboolean build_launcher (gpointer data); -static gboolean build_launchers (gpointer data); - /* * Server List @@ -72,33 +53,12 @@ static gboolean build_launchers (gpointer data); typedef struct _serverList_t serverList_t; struct _serverList_t { - IndicateListenerServer * server; AppMenuItem * menuitem; - DbusmenuMenuitem * separator; gboolean attention; guint count; GList * imList; }; -static gint -serverList_equal (gconstpointer a, gconstpointer b) -{ - serverList_t * pa, * pb; - - pa = (serverList_t *)a; - pb = (serverList_t *)b; - - const gchar * pan = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server); - const gchar * pbn = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server); - const gchar * pap = indicate_listener_server_get_dbuspath(pa->server); - const gchar * pbp = indicate_listener_server_get_dbuspath(pb->server); - - if (g_strcmp0(pan, pbn) == 0) - return g_strcmp0(pap, pbp); - else - return 1; -} - static gint serverList_sort (gconstpointer a, gconstpointer b) { @@ -113,648 +73,7 @@ serverList_sort (gconstpointer a, gconstpointer b) return g_strcmp0(pan, pbn); } -/* - * Item List - */ - -typedef struct _imList_t imList_t; -struct _imList_t { - IndicateListenerServer * server; - IndicateListenerIndicator * indicator; - DbusmenuMenuitem * menuitem; - gulong timechange_cb; - gulong attentionchange_cb; -}; - -static gboolean -imList_equal (gconstpointer a, gconstpointer b) -{ - imList_t * pa, * pb; - - pa = (imList_t *)a; - pb = (imList_t *)b; - - const gchar * pas = INDICATE_LISTENER_SERVER_DBUS_NAME(pa->server); - const gchar * pbs = INDICATE_LISTENER_SERVER_DBUS_NAME(pb->server); - - guint pai = INDICATE_LISTENER_INDICATOR_ID(pa->indicator); - guint pbi = INDICATE_LISTENER_INDICATOR_ID(pb->indicator); - - g_debug("\tComparing (%s %d) to (%s %d)", pas, pai, pbs, pbi); - - return !((!g_strcmp0(pas, pbs)) && (pai == pbi)); -} - -static gint -imList_sort (gconstpointer a, gconstpointer b) -{ - imList_t * pa, * pb; - - pa = (imList_t *)a; - pb = (imList_t *)b; - - return (gint)(im_menu_item_get_seconds(IM_MENU_ITEM(pb->menuitem)) - im_menu_item_get_seconds(IM_MENU_ITEM(pa->menuitem))); -} - - -/* Goes through all the servers and sees if any of them - want attention. If they do, then well we'll give it - to them. If they don't, let's not bother the user - any, shall we? */ -static void -check_attention (void) -{ - GList * pointer; - for (pointer = serverList; pointer != NULL; pointer = g_list_next(pointer)) { - serverList_t * slt = (serverList_t *)pointer->data; - if (slt->attention) { - message_service_dbus_set_attention(dbus_interface, TRUE); - return; - } - } - message_service_dbus_set_attention(dbus_interface, FALSE); - return; -} - -/* This checks a server listing to see if it should - have attention. It can get attention through it's - count or by having an indicator that is requestion - attention. */ -static void -server_attention (serverList_t * slt) -{ - /* Count, easy yes and out. */ - if (slt->count > 0) { - slt->attention = TRUE; - return; - } - - /* Check to see if any of the indicators want attention */ - GList * pointer; - for (pointer = slt->imList; pointer != NULL; pointer = g_list_next(pointer)) { - imList_t * ilt = (imList_t *)pointer->data; - if (im_menu_item_get_attention(IM_MENU_ITEM(ilt->menuitem))) { - slt->attention = TRUE; - return; - } - } - - /* Nope, no one */ - slt->attention = FALSE; - return; -} - -static void -desktop_cb (IndicateListener *listener, - IndicateListenerServer *server, - const gchar *value, - gpointer data) -{ - DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); - GList *listitem; - serverList_t * sl_item = NULL; - - /* Check to see if we already have a launcher for this app */ - for (listitem = serverList; listitem != NULL; listitem = listitem->next) { - serverList_t * slt = listitem->data; - if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), value)) { - sl_item = slt; - break; - } - } - - if (!sl_item) { - /* Build the Menu item */ - AppMenuItem * menuitem = app_menu_item_new_with_server (listener, server); - - /* Build a possible server structure */ - sl_item = g_new0(serverList_t, 1); - sl_item->server = server; - sl_item->menuitem = menuitem; - sl_item->imList = NULL; - sl_item->attention = FALSE; - sl_item->count = 0; - - /* Build a separator */ - sl_item->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - - /* 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_SHORTCUT_ADDED, G_CALLBACK(server_shortcut_added), menushell); - g_signal_connect(G_OBJECT(menuitem), APP_MENU_ITEM_SIGNAL_SHORTCUT_REMOVED, G_CALLBACK(server_shortcut_removed), 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)); - - /* Incase we got an indicator first */ - GList * alreadythere = g_list_find_custom(serverList, sl_item, serverList_equal); - if (alreadythere != NULL) { - /* Use the one we already had */ - g_free(sl_item); - sl_item = (serverList_t *)alreadythere->data; - sl_item->menuitem = menuitem; - serverList = g_list_sort(serverList, serverList_sort); - } else { - /* Insert the new one in the list */ - serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort); - } - - dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(sl_item->separator)); - } - else { - app_menu_item_set_server (sl_item->menuitem, listener, server); - } - - GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(shortcut->data); - g_debug("\tAdding shortcut: %s", dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL)); - dbusmenu_menuitem_child_append(menushell, mi); - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - - resort_menu(menushell); -} - -/* A new server has been created on the indicate bus. - We need to check to see if we like it. And build - structures for it if so. */ -static void -server_added (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data) -{ - g_debug("Server Added '%s' of type '%s'.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), type); - if (type == NULL) { - return; - } - - if (type[0] == '\0') { - return; - } - - if (strncmp(type, "message", strlen("message"))) { - g_debug("\tServer type '%s' is not a message based type.", type); - return; - } - - /* fetch the desktop file before creating the menu item, in case we - * already have a launcher for it */ - indicate_listener_server_get_desktop(listener, server, desktop_cb, data); -} - -/* Server shortcut has been added */ -static void -server_shortcut_added (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data) -{ - g_debug("Application Shortcut added: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none"); - DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data); - if (mi != NULL) { - dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_ICON_NAME, DBUSMENU_MENUITEM_ICON_NAME_BLANK); - dbusmenu_menuitem_child_append(shell, mi); - } - resort_menu(shell); - return; -} - -/* Server shortcut has been removed */ -static void -server_shortcut_removed (AppMenuItem * appitem, DbusmenuMenuitem * mi, gpointer data) -{ - g_debug("Application Shortcut removed: %s", mi != NULL ? dbusmenu_menuitem_property_get(mi, DBUSMENU_MENUITEM_PROP_LABEL) : "none"); - DbusmenuMenuitem * shell = DBUSMENU_MENUITEM(data); - dbusmenu_menuitem_child_delete(shell, mi); - 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 - file from disk. */ -static void -server_name_changed (AppMenuItem * appitem, gchar * name, gpointer data) -{ - serverList = g_list_sort(serverList, serverList_sort); - resort_menu(DBUSMENU_MENUITEM(data)); - return; -} - -/* If the count on the server changes, we need to know - whether that should be grabbing attention or not. If - it is, we need to reevaluate whether the whole thing - should be grabbing attention or not. */ -static void -server_count_changed (AppMenuItem * appitem, guint count, gpointer data) -{ - serverList_t * slt = (serverList_t *)data; - slt->count = count; - - if (count == 0 && slt->attention) { - /* Regen based on indicators if the count isn't going to cause it. */ - server_attention(slt); - /* If we're dropping let's see if we're the last. */ - if (!slt->attention) { - check_attention(); - } - } - - if (count != 0 && !slt->attention) { - slt->attention = TRUE; - /* Let's tell everyone about us! */ - message_service_dbus_set_attention(dbus_interface, TRUE); - } - - return; -} - -/* Respond to the IM entrie's time changing - which results in it needing to resort the list - and rebuild the menu to match. */ -static void -im_time_changed (ImMenuItem * imitem, glong seconds, gpointer data) -{ - serverList_t * sl = (serverList_t *)data; - sl->imList = g_list_sort(sl->imList, imList_sort); - resort_menu(root_menuitem); - return; -} - -/* The IM entrie's request for attention has changed - so we need to pass that up the stack. */ -static void -im_attention_changed (ImMenuItem * imitem, gboolean requestit, gpointer data) -{ - serverList_t * sl = (serverList_t *)data; - - if (requestit) { - sl->attention = TRUE; - message_service_dbus_set_attention(dbus_interface, TRUE); - } else { - server_attention(sl); - if (!sl->attention) { - check_attention(); - } - } - - return; -} - -/* Run when a server is removed from the indicator bus. It figures - out if we have it somewhere, and if so then we dump it out and - clean up all of it's entries. */ -static void -server_removed (IndicateListener * listener, IndicateListenerServer * server, gchar * type, gpointer data) -{ - /* Look for the server */ - g_debug("Removing server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server)); - serverList_t slt = {0}; - slt.server = server; - GList * lookup = g_list_find_custom(serverList, &slt, serverList_equal); - - /* If we don't have it, exit */ - if (lookup == NULL) { - g_debug("\tUnable to find server: %s", INDICATE_LISTENER_SERVER_DBUS_NAME(server)); - return; - } - - serverList_t * sltp = (serverList_t *)lookup->data; - - /* Removing indicators from this server */ - while (sltp->imList) { - imList_t * imitem = (imList_t *)sltp->imList->data; - indicator_removed(listener, server, imitem->indicator, data); - } - - /* Remove from the server list */ - serverList = g_list_remove(serverList, sltp); - - /* If there is a menu item, let's get rid of it. */ - if (sltp->menuitem != NULL) { - /* If there are shortcuts remove them */ - GList * shortcuts = app_menu_item_get_items(sltp->menuitem); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - g_debug("\tRemoving shortcut: %s", dbusmenu_menuitem_property_get(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_LABEL)); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(shortcut->data), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(shortcut->data)); - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - - g_debug("\tRemoving item"); - dbusmenu_menuitem_property_set_bool(DBUSMENU_MENUITEM(sltp->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), DBUSMENU_MENUITEM(sltp->menuitem)); - g_object_unref(G_OBJECT(sltp->menuitem)); - } else { - g_debug("\tNo menuitem"); - } - - /* If there is a separator, let's get rid of it. */ - if (sltp->separator != NULL) { - g_debug("\tRemoving separator"); - 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)); - } else { - g_debug("\tNo separator"); - } - - if (sltp->attention) { - /* Check to see if this was the server causing the menu item to - be lit up. */ - check_attention(); - } - - g_free(sltp); - - return; -} - -typedef struct _menushell_location menushell_location_t; -struct _menushell_location { - const IndicateListenerServer * server; - gint position; - gboolean found; -}; - -static void -menushell_foreach_cb (DbusmenuMenuitem * data_mi, gpointer data_ms) { - menushell_location_t * msl = (menushell_location_t *)data_ms; - - if (msl->found) return; - - if (!IS_APP_MENU_ITEM(data_mi)) { - msl->position++; - return; - } - - AppMenuItem * appmenu = APP_MENU_ITEM(data_mi); - if (!g_strcmp0(INDICATE_LISTENER_SERVER_DBUS_NAME((IndicateListenerServer*)msl->server), INDICATE_LISTENER_SERVER_DBUS_NAME(app_menu_item_get_server(appmenu)))) { - GList *shortcuts = app_menu_item_get_items(appmenu); - msl->found = TRUE; - /* Return a position at the end of our shortcuts */ - msl->position += g_list_length(shortcuts); - g_list_free (shortcuts); - - } else { - msl->position++; - } - - return; -} - -/* This function takes care of putting the menu in the right order. - It basically it rebuilds the order by looking through all the - applications and launchers and puts them in the right place. The - menu functions will handle the cases where they don't move so this - is a good way to ensure everything is right. */ -static void -resort_menu (DbusmenuMenuitem * menushell) -{ - guint position = 0; - GList * serverentry; - - g_debug("Reordering Menu:"); - - if (DBUSMENU_IS_MENUITEM(status_separator)) { - position = dbusmenu_menuitem_get_position(status_separator, root_menuitem) + 1; - g_debug("\tPriming with location of status separator: %d", position); - } - - for (serverentry = serverList; serverentry != NULL; serverentry = serverentry->next) { - serverList_t * si = (serverList_t *)serverentry->data; - - /* Putting the app menu item in */ - if (si->menuitem != NULL) { - 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); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - g_debug("\t\tMoving shortcut to position %d", position); - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(shortcut->data), position); - position++; - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - } - - /* Putting all the indicators that are related to this application - after it. */ - GList * imentry; - for (imentry = si->imList; imentry != NULL; imentry = imentry->next) { - imList_t * imi = (imList_t *)imentry->data; - - if (imi->menuitem != NULL) { - g_debug("\tMoving indicator on %s id %d to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(imi->server), INDICATE_LISTENER_INDICATOR_ID(imi->indicator), position); - - if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) { - dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - } else { - dbusmenu_menuitem_property_set_bool(imi->menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - } - - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(imi->menuitem), position); - position++; - } - } - - /* Lastly putting the separator in */ - if (si->separator != NULL) { - g_debug("\tMoving app %s separator to position %d", INDICATE_LISTENER_SERVER_DBUS_NAME(si->server), position); - - if (si->menuitem == NULL || !dbusmenu_menuitem_property_get_bool(DBUSMENU_MENUITEM(si->menuitem), DBUSMENU_MENUITEM_PROP_VISIBLE)) { - dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - /* Note, this isn't the last if we can't see it */ - } else { - dbusmenu_menuitem_property_set_bool(si->separator, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE); - } - - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), DBUSMENU_MENUITEM(si->separator), position); - position++; - } - } - - if (clear_attention != NULL) { - dbusmenu_menuitem_child_reorder(DBUSMENU_MENUITEM(menushell), clear_attention, position); - position++; /* Not needed, but reduce bugs on code tacked on here, compiler will remove */ - } - - return; -} - -/* Responding to a new indicator showing up on the bus. We - need to create a menuitem for it and start populating the - internal structures to track it. */ -static void -indicator_added (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data) -{ - DbusmenuMenuitem * menushell = DBUSMENU_MENUITEM(data); - if (menushell == NULL) { - g_error("Data in callback is not a menushell"); - return; - } - - imList_t * listItem = g_new0(imList_t, 1); - listItem->server = server; - listItem->indicator = indicator; - - /* Building the IM Menu Item which is a subclass - of DBus Menuitem */ - ImMenuItem * menuitem = im_menu_item_new(listener, server, indicator); - listItem->menuitem = DBUSMENU_MENUITEM(menuitem); - - /* Looking for a server entry to attach this indicator - to. If we can't find one then we have to build one - and attach the indicator to it. */ - serverList_t sl_item_local = {0}; - serverList_t * sl_item = NULL; - sl_item_local.server = server; - GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal); - - if (serverentry == NULL) { - /* This sucks, we got an indicator before the server. I guess - that's the joy of being asynchronous */ - sl_item = g_new0(serverList_t, 1); - sl_item->server = server; - sl_item->menuitem = NULL; - sl_item->imList = NULL; - sl_item->attention = FALSE; - sl_item->count = 0; - sl_item->separator = NULL; - - serverList = g_list_insert_sorted(serverList, sl_item, serverList_sort); - } else { - sl_item = (serverList_t *)serverentry->data; - } - - /* Added a this entry into the IM list */ - sl_item->imList = g_list_insert_sorted(sl_item->imList, listItem, imList_sort); - listItem->timechange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_TIME_CHANGED, G_CALLBACK(im_time_changed), sl_item); - listItem->attentionchange_cb = g_signal_connect(G_OBJECT(menuitem), IM_MENU_ITEM_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(im_attention_changed), sl_item); - - /* Check the length of the list. If we've got more inidactors - than we allow. Well. Someone's gotta pay. Sorry. I didn't - want to do this, but you did it to yourself. */ - if (g_list_length(sl_item->imList) > MAX_NUMBER_OF_INDICATORS) { - GList * indicatoritem; - gint count; - for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) { - imList_t * im = (imList_t *)indicatoritem->data; - im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS); - } - } - - /* Placing the item into the shell. Look to see if - we can find our server and slip in there. Otherwise - we'll just append. */ - menushell_location_t msl; - msl.found = FALSE; - msl.position = 0; - msl.server = server; - - dbusmenu_menuitem_foreach(DBUSMENU_MENUITEM(menushell), menushell_foreach_cb, &msl); - if (msl.found) { - dbusmenu_menuitem_child_add_position(menushell, DBUSMENU_MENUITEM(menuitem), msl.position); - } else { - g_warning("Unable to find server menu item"); - dbusmenu_menuitem_child_append(menushell, DBUSMENU_MENUITEM(menuitem)); - resort_menu (root_menuitem); - } - - return; -} - -/* Process and indicator getting removed from the system. We - first need to ensure that it's one of ours and figure out - where we put it. When we find all that out we can go through - the process of removing the effect it had on the system. */ -static void -indicator_removed (IndicateListener * listener, IndicateListenerServer * server, IndicateListenerIndicator * indicator, gpointer data) -{ - g_debug("Removing %s %d", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator)); - - gboolean removed = FALSE; - - /* Find the server that was related to this item */ - serverList_t sl_item_local = {0}; - serverList_t * sl_item = NULL; - sl_item_local.server = server; - GList * serverentry = g_list_find_custom(serverList, &sl_item_local, serverList_equal); - if (serverentry == NULL) { - /* We didn't care about that server */ - return; - } - sl_item = (serverList_t *)serverentry->data; - - /* Look in the IM Hash Table */ - imList_t listData = {0}; - listData.server = server; - listData.indicator = indicator; - - GList * listItem = g_list_find_custom(sl_item->imList, &listData, imList_equal); - DbusmenuMenuitem * menuitem = NULL; - imList_t * ilt = NULL; - if (listItem != NULL) { - ilt = (imList_t *)listItem->data; - menuitem = ilt->menuitem; - } - - /* If we found a menu item and an imList_t item then - we can go ahead and remove it. Otherwise we can - skip this and exit. */ - if (!removed && menuitem != NULL) { - sl_item->imList = g_list_remove(sl_item->imList, ilt); - g_signal_handler_disconnect(menuitem, ilt->timechange_cb); - g_signal_handler_disconnect(menuitem, ilt->attentionchange_cb); - g_free(ilt); - - if (im_menu_item_get_attention(IM_MENU_ITEM(menuitem)) && im_menu_item_shown(IM_MENU_ITEM(menuitem))) { - /* If the removed indicator menu item was asking for - attention we need to see if this server should still - be asking for attention. */ - server_attention(sl_item); - /* If the server is no longer asking for attention then - we need to check if the whole system should be. */ - if (!sl_item->attention) { - check_attention(); - } - } - - if (im_menu_item_shown(IM_MENU_ITEM(menuitem)) && g_list_length(sl_item->imList) >= MAX_NUMBER_OF_INDICATORS) { - /* In this case we need to show a different indicator - becasue a shown one has left. But we're going to be - easy and set all the values. */ - GList * indicatoritem; - gint count; - for (indicatoritem = sl_item->imList, count = 0; indicatoritem != NULL; indicatoritem = g_list_next(indicatoritem), count++) { - imList_t * im = (imList_t *)indicatoritem->data; - im_menu_item_show(IM_MENU_ITEM(im->menuitem), count < MAX_NUMBER_OF_INDICATORS); - } - } - - /* Hide the item immediately, and then remove it - which might take a little longer. */ - dbusmenu_menuitem_property_set_bool(menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE); - dbusmenu_menuitem_child_delete(DBUSMENU_MENUITEM(data), menuitem); - removed = TRUE; - } - - if (!removed) { - g_warning("We were asked to remove %s %d but we didn't.", INDICATE_LISTENER_SERVER_DBUS_NAME(server), INDICATE_LISTENER_INDICATOR_ID(indicator)); - } - - return; -} - -/* This function turns a specific file into a menu +/* This function turns a specific desktop id into a menu item and registers it appropriately with everyone */ static gboolean build_launcher (gpointer data) @@ -780,26 +99,12 @@ build_launcher (gpointer data) serverList_t * sl_item = g_new0(serverList_t, 1); sl_item->menuitem = app_menu_item_new(appinfo); - /* Build a separator */ - sl_item->separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(sl_item->separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - - /* Add it to the list */ serverList = g_list_insert_sorted (serverList, sl_item, serverList_sort); - /* Add it to the menu */ - dbusmenu_menuitem_property_set(DBUSMENU_MENUITEM(sl_item->menuitem), DBUSMENU_MENUITEM_PROP_TYPE, APPLICATION_MENUITEM_TYPE); - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->menuitem)); - GList * shortcuts = app_menu_item_get_items(sl_item->menuitem); - GList * shortcut = shortcuts; - while (shortcut != NULL) { - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(shortcut->data)); - shortcut = g_list_next(shortcut); - } - g_list_free (shortcuts); - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(sl_item->separator)); - - resort_menu(root_menuitem); + /* TODO insert it at the right position (alphabetically by application name) */ + g_menu_insert_section (menu, 2, + app_menu_item_get_name (sl_item->menuitem), + app_menu_item_get_menu (sl_item->menuitem)); } g_object_unref (appinfo); @@ -838,36 +143,34 @@ service_shutdown (IndicatorService * service, gpointer user_data) return; } -/* Respond to changing status by updating the icon that - is on the panel */ static void -status_update_callback (void) +clear_action_activate (GSimpleAction *simple, + GVariant *param, + gpointer user_data) { - return; + MessageServiceDbus *msg_service = user_data; + message_service_dbus_set_attention(msg_service, FALSE); } -/* The clear attention item has been clicked on, what to do? */ static void -clear_attention_activate (DbusmenuMenuitem * mi, guint timestamp, MessageServiceDbus * dbus) +clear_action_handler (MessageServiceDbus *msd, + gboolean attention, + gpointer user_data) { - message_service_dbus_set_attention(dbus, FALSE); - return; + GSimpleAction *action = user_data; + g_simple_action_set_enabled (action, attention); } -/* Handle an update of the active state to ensure that we're - only enabled when we could do something. */ -static void -clear_attention_handler (MessageServiceDbus * msd, gboolean attention, DbusmenuMenuitem * clearitem) -{ - dbusmenu_menuitem_property_set_bool(clearitem, DBUSMENU_MENUITEM_PROP_ENABLED, attention); - return; -} - -/* Oh, if you don't know what main() is for - we really shouldn't be talking. */ int main (int argc, char ** argv) { + GError *error = NULL; + GActionEntry entries[] = { + { "status", NULL, "s", "'offline'", NULL }, + { "clear", clear_action_activate } + }; + GMenuModel *status_items; + /* Glib init */ g_type_init(); @@ -884,36 +187,40 @@ main (int argc, char ** argv) /* Bring up the service DBus interface */ dbus_interface = message_service_dbus_new(); - /* Build the base menu */ - root_menuitem = dbusmenu_menuitem_new(); - DbusmenuServer * server = dbusmenu_server_new(INDICATOR_MESSAGES_DBUS_OBJECT); - dbusmenu_server_set_root(server, root_menuitem); + bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); + if (!bus) { + g_warning ("unable to connect to the session bus: %s", error->message); + g_error_free (error); + return 1; + } + + actions = g_simple_action_group_new (); + g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_ACTION_GROUP (actions), &error); + if (error) { + g_warning ("unable to export action group on dbus: %s", error->message); + g_error_free (error); + return 1; + } + + g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, + G_CALLBACK(clear_action_handler), + g_action_map_lookup_action (G_ACTION_MAP (actions), "clear")); + + status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status")); + + menu = g_menu_new (); + g_menu_append_section (menu, _("Status"), status_items); + g_menu_append (menu, _("Clear"), "clear"); - /* Add status items */ - GList * statusitems = status_items_build(&status_update_callback); - while (statusitems != NULL) { - dbusmenu_menuitem_child_append(root_menuitem, DBUSMENU_MENUITEM(statusitems->data)); - statusitems = g_list_next(statusitems); + g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_MENU_MODEL (menu), &error); + if (error) { + g_warning ("unable to export menu on dbus: %s", error->message); + g_error_free (error); + return 1; } - status_separator = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(status_separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append(root_menuitem, status_separator); - - /* Add in the clear attention item */ - clear_attention = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set(clear_attention, DBUSMENU_MENUITEM_PROP_LABEL, _("Clear")); - dbusmenu_menuitem_child_append(root_menuitem, clear_attention); - g_signal_connect(G_OBJECT(dbus_interface), MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(clear_attention_handler), clear_attention); - g_signal_connect(G_OBJECT(clear_attention), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(clear_attention_activate), dbus_interface); - - /* Start up the libindicate listener */ - listener = indicate_listener_ref_default(); - serverList = NULL; - - g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_ADDED, G_CALLBACK(indicator_added), root_menuitem); - g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_INDICATOR_REMOVED, G_CALLBACK(indicator_removed), root_menuitem); - g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_ADDED, G_CALLBACK(server_added), root_menuitem); - g_signal_connect(listener, INDICATE_LISTENER_SIGNAL_SERVER_REMOVED, G_CALLBACK(server_removed), root_menuitem); settings = g_settings_new ("com.canonical.indicator.messages"); -- cgit v1.2.3 From 9763d347aabc9050e4f17133bcf287ed1cbc190d Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 24 May 2012 22:50:22 +0200 Subject: message-service: replace the server list with a hash table of appmenuitems --- src/messages-service.c | 61 ++++++++++---------------------------------------- 1 file changed, 12 insertions(+), 49 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 432846e..fbbfb9d 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -36,7 +36,7 @@ with this program. If not, see . #include "status-items.h" static IndicatorService * service = NULL; -static GList * serverList = NULL; +static GHashTable *applications; static GDBusConnection *bus; static GSimpleActionGroup *actions; @@ -47,32 +47,6 @@ static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; -/* - * Server List - */ - -typedef struct _serverList_t serverList_t; -struct _serverList_t { - AppMenuItem * menuitem; - gboolean attention; - guint count; - GList * imList; -}; - -static gint -serverList_sort (gconstpointer a, gconstpointer b) -{ - serverList_t * pa, * pb; - - pa = (serverList_t *)a; - pb = (serverList_t *)b; - - const gchar * pan = app_menu_item_get_name(pa->menuitem); - const gchar * pbn = app_menu_item_get_name(pb->menuitem); - - return g_strcmp0(pan, pbn); -} - /* This function turns a specific desktop id into a menu item and registers it appropriately with everyone */ static gboolean @@ -80,31 +54,20 @@ build_launcher (gpointer data) { gchar *desktop_id = data; GDesktopAppInfo *appinfo; - GList *listitem; + const gchar *desktop_file; appinfo = g_desktop_app_info_new (desktop_id); + desktop_file = g_desktop_app_info_get_filename (appinfo); - /* Check to see if we already have a launcher */ - for (listitem = serverList; listitem != NULL; listitem = listitem->next) { - serverList_t * slt = listitem->data; - if (!g_strcmp0(app_menu_item_get_desktop(slt->menuitem), - g_desktop_app_info_get_filename (appinfo))) { - break; - } - } - - if (listitem == NULL) { - /* If not */ - /* Build the item */ - serverList_t * sl_item = g_new0(serverList_t, 1); - sl_item->menuitem = app_menu_item_new(appinfo); - - serverList = g_list_insert_sorted (serverList, sl_item, serverList_sort); + if (!g_hash_table_lookup (applications, desktop_file)) { + AppMenuItem *menuitem = app_menu_item_new(appinfo); /* TODO insert it at the right position (alphabetically by application name) */ g_menu_insert_section (menu, 2, - app_menu_item_get_name (sl_item->menuitem), - app_menu_item_get_menu (sl_item->menuitem)); + app_menu_item_get_name (menuitem), + app_menu_item_get_menu (menuitem)); + + g_hash_table_insert (applications, g_strdup (desktop_file), menuitem); } g_object_unref (appinfo); @@ -129,8 +92,6 @@ build_launchers (gpointer data) g_idle_add(build_launcher, g_strdup (*app)); } - serverList = g_list_sort(serverList, serverList_sort); - g_strfreev (applications); return FALSE; } @@ -224,6 +185,8 @@ main (int argc, char ** argv) settings = g_settings_new ("com.canonical.indicator.messages"); + applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + g_idle_add(build_launchers, NULL); /* Let's run a mainloop */ @@ -233,6 +196,6 @@ main (int argc, char ** argv) /* Clean up */ status_items_cleanup(); g_object_unref (settings); - + g_hash_table_unref (applications); return 0; } -- cgit v1.2.3 From 54621a3d3ece6ddf0bdd9868b8d0405c396c59b2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 24 May 2012 22:53:00 +0200 Subject: Check whether supplied desktop files exist --- src/messages-service.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index fbbfb9d..cfc07fc 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -57,6 +57,12 @@ build_launcher (gpointer data) const gchar *desktop_file; appinfo = g_desktop_app_info_new (desktop_id); + if (!appinfo) { + g_warning ("could not find a desktop file with id '%s'\n", desktop_id); + g_free (desktop_id); + return FALSE; + } + desktop_file = g_desktop_app_info_get_filename (appinfo); if (!g_hash_table_lookup (applications, desktop_file)) { -- cgit v1.2.3 From cb34c1a8d430a21330edc0119a6b74642f77c274 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 30 May 2012 19:23:43 +0200 Subject: Allow applications to (un)register themselves from the messaging menu via d-bus --- src/messages-service.c | 79 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 72 insertions(+), 7 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index cfc07fc..7c1a2b5 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -47,20 +47,17 @@ static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; -/* This function turns a specific desktop id into a menu - item and registers it appropriately with everyone */ -static gboolean -build_launcher (gpointer data) +static void +add_application (const gchar *desktop_id, + const gchar *menu_path) { - gchar *desktop_id = data; GDesktopAppInfo *appinfo; const gchar *desktop_file; appinfo = g_desktop_app_info_new (desktop_id); if (!appinfo) { g_warning ("could not find a desktop file with id '%s'\n", desktop_id); - g_free (desktop_id); - return FALSE; + return; } desktop_file = g_desktop_app_info_get_filename (appinfo); @@ -77,6 +74,17 @@ build_launcher (gpointer data) } g_object_unref (appinfo); +} + +/* This function turns a specific desktop id into a menu + item and registers it appropriately with everyone */ +static gboolean +build_launcher (gpointer data) +{ + gchar *desktop_id = data; + + add_application (desktop_id, NULL); + g_free (desktop_id); return FALSE; } @@ -128,6 +136,58 @@ clear_action_handler (MessageServiceDbus *msd, g_simple_action_set_enabled (action, attention); } +static void +register_application (MessageServiceDbus *msd, + const gchar *desktop_id, + const gchar *menu_path, + gpointer user_data) +{ + gchar **applications = g_settings_get_strv (settings, "applications"); + gchar **app; + + for (app = applications; *app; app++) { + if (!g_strcmp0 (desktop_id, *app)) + break; + } + + if (*app == NULL) { + GVariantBuilder builder; + + g_variant_builder_init (&builder, (GVariantType *)"as"); + for (app = applications; *app; app++) + g_variant_builder_add (&builder, "s", *app); + g_variant_builder_add (&builder, "s", desktop_id); + + g_settings_set_value (settings, "applications", + g_variant_builder_end (&builder)); + + add_application (desktop_id, menu_path); + } + + g_strfreev (applications); +} + +static void +unregister_application (MessageServiceDbus *msd, + const gchar *desktop_id, + gpointer user_data) +{ + gchar **applications = g_settings_get_strv (settings, "applications"); + gchar **app; + GVariantBuilder builder; + + g_variant_builder_init (&builder, (GVariantType *)"as"); + for (app = applications; *app; app++) { + if (g_strcmp0 (desktop_id, *app)) + g_variant_builder_add (&builder, "s", *app); + } + + g_settings_set_value (settings, "applications", + g_variant_builder_end (&builder)); + + g_strfreev (applications); +} + int main (int argc, char ** argv) { @@ -175,6 +235,11 @@ main (int argc, char ** argv) G_CALLBACK(clear_action_handler), g_action_map_lookup_action (G_ACTION_MAP (actions), "clear")); + g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION, + G_CALLBACK (register_application), NULL); + g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, + G_CALLBACK (unregister_application), NULL); + status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status")); menu = g_menu_new (); -- cgit v1.2.3 From 0f9764c90a24880a5bda8ff047585ef65958cad4 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 31 May 2012 15:59:02 +0200 Subject: Remove an application from the menu after it unregistered --- src/messages-service.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 7c1a2b5..134c4ee 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -56,7 +56,7 @@ add_application (const gchar *desktop_id, appinfo = g_desktop_app_info_new (desktop_id); if (!appinfo) { - g_warning ("could not find a desktop file with id '%s'\n", desktop_id); + g_warning ("could not add '%s', there's no desktop file with that id", desktop_id); return; } @@ -76,6 +76,55 @@ add_application (const gchar *desktop_id, g_object_unref (appinfo); } +/* g_menu_model_find_section: + * + * @Returns the index of the first menu item that is linked to #section, or -1 + * if there's no such item. + */ +static int +g_menu_find_section (GMenu *menu, + GMenuModel *section) +{ + int n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu)); + int i; + + for (i = 0; i < n_items; i++) { + if (section == g_menu_model_get_item_link (G_MENU_MODEL (menu), i, G_MENU_LINK_SECTION)) + return i; + } + + return -1; +} + +static void +remove_application (const char *desktop_id) +{ + GDesktopAppInfo *appinfo; + const gchar *desktop_file; + AppMenuItem *menuitem; + + appinfo = g_desktop_app_info_new (desktop_id); + if (!appinfo) { + g_warning ("could not remove '%s', there's no desktop file with that id", desktop_id); + return; + } + + desktop_file = g_desktop_app_info_get_filename (appinfo); + + menuitem = g_hash_table_lookup (applications, desktop_file); + if (menuitem) { + int pos = g_menu_find_section (menu, app_menu_item_get_menu (menuitem)); + if (pos >= 0) + g_menu_remove (menu, pos); + } + else { + g_warning ("could not remove '%s', it's not registered", desktop_id); + } + + g_hash_table_remove (applications, desktop_file); + g_object_unref (appinfo); +} + /* This function turns a specific desktop id into a menu item and registers it appropriately with everyone */ static gboolean @@ -185,6 +234,8 @@ unregister_application (MessageServiceDbus *msd, g_settings_set_value (settings, "applications", g_variant_builder_end (&builder)); + remove_application (desktop_id); + g_strfreev (applications); } -- cgit v1.2.3 From 4f2dd60a130dcaeb4378219baca1f3d4e9637824 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 31 May 2012 18:55:06 +0200 Subject: Rename AppMenuItem to AppSection --- src/messages-service.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 134c4ee..dcce1c5 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -30,7 +30,7 @@ with this program. If not, see . #include #include -#include "app-menu-item.h" +#include "app-section.h" #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" @@ -63,14 +63,14 @@ add_application (const gchar *desktop_id, desktop_file = g_desktop_app_info_get_filename (appinfo); if (!g_hash_table_lookup (applications, desktop_file)) { - AppMenuItem *menuitem = app_menu_item_new(appinfo); + AppSection *section = app_section_new(appinfo); /* TODO insert it at the right position (alphabetically by application name) */ g_menu_insert_section (menu, 2, - app_menu_item_get_name (menuitem), - app_menu_item_get_menu (menuitem)); + app_section_get_name (section), + app_section_get_menu (section)); - g_hash_table_insert (applications, g_strdup (desktop_file), menuitem); + g_hash_table_insert (applications, g_strdup (desktop_file), section); } g_object_unref (appinfo); @@ -101,7 +101,7 @@ remove_application (const char *desktop_id) { GDesktopAppInfo *appinfo; const gchar *desktop_file; - AppMenuItem *menuitem; + AppSection *section; appinfo = g_desktop_app_info_new (desktop_id); if (!appinfo) { @@ -111,9 +111,9 @@ remove_application (const char *desktop_id) desktop_file = g_desktop_app_info_get_filename (appinfo); - menuitem = g_hash_table_lookup (applications, desktop_file); - if (menuitem) { - int pos = g_menu_find_section (menu, app_menu_item_get_menu (menuitem)); + section = g_hash_table_lookup (applications, desktop_file); + if (section) { + int pos = g_menu_find_section (menu, app_section_get_menu (section)); if (pos >= 0) g_menu_remove (menu, pos); } -- cgit v1.2.3 From eea45a449eb4de159aab08bad864b27f584af519 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 31 May 2012 19:29:27 +0200 Subject: Put the 'launch' action onto app's menu sections This requires clients to make those menu sections clickable. --- src/messages-service.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index dcce1c5..ddedee9 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -64,13 +64,14 @@ add_application (const gchar *desktop_id, if (!g_hash_table_lookup (applications, desktop_file)) { AppSection *section = app_section_new(appinfo); + GMenuItem *item = app_section_create_menu_item (section); + + g_hash_table_insert (applications, g_strdup (desktop_file), section); /* TODO insert it at the right position (alphabetically by application name) */ - g_menu_insert_section (menu, 2, - app_section_get_name (section), - app_section_get_menu (section)); + g_menu_insert_item (menu, 2, item); - g_hash_table_insert (applications, g_strdup (desktop_file), section); + g_object_unref (item); } g_object_unref (appinfo); -- cgit v1.2.3 From 21f3cac4cb191430abf89b7cebd0093952c827b0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sat, 2 Jun 2012 16:44:47 +0200 Subject: Listen to actions exported by applications --- src/messages-service.c | 57 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 39 insertions(+), 18 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index ddedee9..28a64a0 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -47,34 +47,36 @@ static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; -static void -add_application (const gchar *desktop_id, - const gchar *menu_path) +static AppSection * +add_application (const gchar *desktop_id) { GDesktopAppInfo *appinfo; const gchar *desktop_file; + AppSection *section; appinfo = g_desktop_app_info_new (desktop_id); if (!appinfo) { g_warning ("could not add '%s', there's no desktop file with that id", desktop_id); - return; + return NULL; } desktop_file = g_desktop_app_info_get_filename (appinfo); + section = g_hash_table_lookup (applications, desktop_file); - if (!g_hash_table_lookup (applications, desktop_file)) { - AppSection *section = app_section_new(appinfo); - GMenuItem *item = app_section_create_menu_item (section); + if (!section) { + GMenuItem *item; + section = app_section_new(appinfo); g_hash_table_insert (applications, g_strdup (desktop_file), section); + item = app_section_create_menu_item (section); /* TODO insert it at the right position (alphabetically by application name) */ g_menu_insert_item (menu, 2, item); - g_object_unref (item); } g_object_unref (appinfo); + return section; } /* g_menu_model_find_section: @@ -133,7 +135,7 @@ build_launcher (gpointer data) { gchar *desktop_id = data; - add_application (desktop_id, NULL); + add_application (desktop_id); g_free (desktop_id); return FALSE; @@ -186,22 +188,43 @@ clear_action_handler (MessageServiceDbus *msd, g_simple_action_set_enabled (action, attention); } +static gint +g_strv_find (gchar **str_array, + const gchar *key) +{ + gchar **it; + + g_return_val_if_fail (str_array != NULL, -1); + + for (it = str_array; *it; it++) { + if (!g_strcmp0 (key, *it)) + return it - str_array; + } + + return -1; +} + static void register_application (MessageServiceDbus *msd, + const gchar *sender, const gchar *desktop_id, const gchar *menu_path, gpointer user_data) { - gchar **applications = g_settings_get_strv (settings, "applications"); - gchar **app; + AppSection *section; + gchar **applications; - for (app = applications; *app; app++) { - if (!g_strcmp0 (desktop_id, *app)) - break; - } + section = add_application (desktop_id); + if (!section) + return; - if (*app == NULL) { + app_section_set_object_path (section, bus, sender, menu_path); + + /* remember this application in the settings key */ + applications = g_settings_get_strv (settings, "applications"); + if (g_strv_find (applications, desktop_id) < 0) { GVariantBuilder builder; + gchar **app; g_variant_builder_init (&builder, (GVariantType *)"as"); for (app = applications; *app; app++) @@ -210,8 +233,6 @@ register_application (MessageServiceDbus *msd, g_settings_set_value (settings, "applications", g_variant_builder_end (&builder)); - - add_application (desktop_id, menu_path); } g_strfreev (applications); -- cgit v1.2.3 From 6872c840672049695904d61c1a3baba22c6d9627 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sun, 3 Jun 2012 08:33:31 +0200 Subject: Add GActionMuxer This is a new implementation of an action muxer with the same interface as the one in the gtk tree. Its implementation is considerably simpler, mostly because it doesn't need to implement GActionObservable. In addition to muxing different action groups with the . scheme, it has the notion of global, prefix-less actions. Indicator-messages needs those for the status and clear actions. --- src/messages-service.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 28a64a0..c1069b8 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -34,12 +34,14 @@ with this program. If not, see . #include "dbus-data.h" #include "messages-service-dbus.h" #include "status-items.h" +#include "gactionmuxer.h" static IndicatorService * service = NULL; static GHashTable *applications; static GDBusConnection *bus; static GSimpleActionGroup *actions; +static GActionMuxer *action_muxer; static GMenu *menu; static GSettings *settings; static GMainLoop * mainloop = NULL; @@ -296,8 +298,11 @@ main (int argc, char ** argv) actions = g_simple_action_group_new (); g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + + action_muxer = g_action_muxer_new (); + g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_ACTION_GROUP (actions), &error); + G_ACTION_GROUP (action_muxer), &error); if (error) { g_warning ("unable to export action group on dbus: %s", error->message); g_error_free (error); -- cgit v1.2.3 From 76b172f49929b8feb1375df830042f6d47121f67 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sun, 3 Jun 2012 09:00:10 +0200 Subject: Use ids instead of .desktop file names to identify applications --- src/messages-service.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index c1069b8..ec12cbe 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -49,11 +49,26 @@ static GMainLoop * mainloop = NULL; static MessageServiceDbus * dbus_interface = NULL; +static gchar * +g_app_info_get_simple_id (GAppInfo *appinfo) +{ + const gchar *id; + + id = g_app_info_get_id (appinfo); + if (!id) + return NULL; + + if (g_str_has_suffix (id, ".desktop")) + return g_strndup (id, strlen (id) - 8); + else + return g_strdup (id); +} + static AppSection * add_application (const gchar *desktop_id) { GDesktopAppInfo *appinfo; - const gchar *desktop_file; + gchar *id; AppSection *section; appinfo = g_desktop_app_info_new (desktop_id); @@ -62,14 +77,14 @@ add_application (const gchar *desktop_id) return NULL; } - desktop_file = g_desktop_app_info_get_filename (appinfo); - section = g_hash_table_lookup (applications, desktop_file); + id = g_app_info_get_simple_id (G_APP_INFO (appinfo)); + section = g_hash_table_lookup (applications, id); if (!section) { GMenuItem *item; section = app_section_new(appinfo); - g_hash_table_insert (applications, g_strdup (desktop_file), section); + g_hash_table_insert (applications, g_strdup (id), section); item = app_section_create_menu_item (section); /* TODO insert it at the right position (alphabetically by application name) */ @@ -77,6 +92,7 @@ add_application (const gchar *desktop_id) g_object_unref (item); } + g_free (id); g_object_unref (appinfo); return section; } @@ -105,7 +121,7 @@ static void remove_application (const char *desktop_id) { GDesktopAppInfo *appinfo; - const gchar *desktop_file; + gchar *id; AppSection *section; appinfo = g_desktop_app_info_new (desktop_id); @@ -114,9 +130,9 @@ remove_application (const char *desktop_id) return; } - desktop_file = g_desktop_app_info_get_filename (appinfo); + id = g_app_info_get_simple_id (G_APP_INFO (appinfo)); - section = g_hash_table_lookup (applications, desktop_file); + section = g_hash_table_lookup (applications, id); if (section) { int pos = g_menu_find_section (menu, app_section_get_menu (section)); if (pos >= 0) @@ -126,7 +142,8 @@ remove_application (const char *desktop_id) g_warning ("could not remove '%s', it's not registered", desktop_id); } - g_hash_table_remove (applications, desktop_file); + g_hash_table_remove (applications, id); + g_free (id); g_object_unref (appinfo); } -- cgit v1.2.3 From 98538a540ba7a741a68b4cff6d3e192a43d61077 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Sun, 3 Jun 2012 12:59:43 +0200 Subject: Reexport application actions --- src/messages-service.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index ec12cbe..e302219 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -64,6 +64,22 @@ g_app_info_get_simple_id (GAppInfo *appinfo) return g_strdup (id); } +static void +actions_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + AppSection *section = APP_SECTION (object); + gchar *id; + GActionGroup *actions; + + id = g_app_info_get_simple_id (app_section_get_app_info (section)); + actions = app_section_get_actions (section); + + g_action_muxer_insert (action_muxer, id, actions); + g_free (id); +} + static AppSection * add_application (const gchar *desktop_id) { @@ -86,6 +102,10 @@ add_application (const gchar *desktop_id) section = app_section_new(appinfo); g_hash_table_insert (applications, g_strdup (id), section); + g_action_muxer_insert (action_muxer, id, app_section_get_actions (section)); + g_signal_connect (section, "notify::actions", + G_CALLBACK (actions_changed), NULL); + item = app_section_create_menu_item (section); /* TODO insert it at the right position (alphabetically by application name) */ g_menu_insert_item (menu, 2, item); @@ -137,6 +157,7 @@ remove_application (const char *desktop_id) int pos = g_menu_find_section (menu, app_section_get_menu (section)); if (pos >= 0) g_menu_remove (menu, pos); + g_action_muxer_remove (action_muxer, id); } else { g_warning ("could not remove '%s', it's not registered", desktop_id); -- cgit v1.2.3 From 787dff35a9a9e0c491e960754b8bbdeb46ae800c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 16:40:26 +0200 Subject: Put launcher and shortcut menu items into the same gmenu section --- src/messages-service.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index e302219..805e684 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -97,8 +97,6 @@ add_application (const gchar *desktop_id) section = g_hash_table_lookup (applications, id); if (!section) { - GMenuItem *item; - section = app_section_new(appinfo); g_hash_table_insert (applications, g_strdup (id), section); @@ -106,10 +104,8 @@ add_application (const gchar *desktop_id) g_signal_connect (section, "notify::actions", G_CALLBACK (actions_changed), NULL); - item = app_section_create_menu_item (section); /* TODO insert it at the right position (alphabetically by application name) */ - g_menu_insert_item (menu, 2, item); - g_object_unref (item); + g_menu_insert_section (menu, 2, NULL, app_section_get_menu (section)); } g_free (id); -- cgit v1.2.3 From 27dbefcc92d9c91bb090f94ba64910867baa605b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 16:52:05 +0200 Subject: Set action namespace on application sections --- src/messages-service.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 805e684..fcceb58 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -97,6 +97,8 @@ add_application (const gchar *desktop_id) section = g_hash_table_lookup (applications, id); if (!section) { + GMenuItem *menuitem; + section = app_section_new(appinfo); g_hash_table_insert (applications, g_strdup (id), section); @@ -105,7 +107,10 @@ add_application (const gchar *desktop_id) G_CALLBACK (actions_changed), NULL); /* TODO insert it at the right position (alphabetically by application name) */ - g_menu_insert_section (menu, 2, NULL, app_section_get_menu (section)); + menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); + g_menu_item_set_attribute (menuitem, "action-namespace", "s", id); + g_menu_insert_item (menu, 2, menuitem); + g_object_unref (menuitem); } g_free (id); -- cgit v1.2.3 From b942b3f993ce9bc89ff04ad7a79878902fd1922f Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 16:52:48 +0200 Subject: Set user_data that action handlers expect --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index fcceb58..203156e 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -336,7 +336,7 @@ main (int argc, char ** argv) } actions = g_simple_action_group_new (); - g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), dbus_interface); action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); -- cgit v1.2.3 From 3da349e33e434c13a27f956374e97c75ef0480a0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 22:40:59 +0200 Subject: Remove status providers Applications will be able to set and retrieve status through libmessaging-menu and telepathy. --- src/messages-service.c | 54 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 203156e..9f4cddc 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -33,7 +33,6 @@ with this program. If not, see . #include "app-section.h" #include "dbus-data.h" #include "messages-service-dbus.h" -#include "status-items.h" #include "gactionmuxer.h" static IndicatorService * service = NULL; @@ -220,6 +219,22 @@ clear_action_activate (GSimpleAction *simple, message_service_dbus_set_attention(msg_service, FALSE); } +static void +radio_item_activate (GSimpleAction *action, + GVariant *parameter, + gpointer user_data) +{ + g_action_change_state (G_ACTION (action), parameter); +} + +static void +change_status (GSimpleAction *action, + GVariant *value, + gpointer user_data) +{ + g_message ("changing status to %s", g_variant_get_string (value, NULL)); +} + static void clear_action_handler (MessageServiceDbus *msd, gboolean attention, @@ -302,12 +317,42 @@ unregister_application (MessageServiceDbus *msd, g_strfreev (applications); } +static void +g_menu_append_with_icon (GMenu *menu, + const gchar *label, + const gchar *icon_name, + const gchar *detailed_action) +{ + GMenuItem *item; + + item = g_menu_item_new (label, detailed_action); + g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", icon_name); + + g_menu_append_item (menu, item); + g_object_unref (item); +} + +GMenuModel * +create_status_section () +{ + GMenu *menu; + + menu = g_menu_new (); + g_menu_append_with_icon (menu, _("Available"), "user-available", "status::available"); + g_menu_append_with_icon (menu, _("Away"), "user-away", "status::away"); + g_menu_append_with_icon (menu, _("Busy"), "user-busy", "status::busy"); + g_menu_append_with_icon (menu, _("Invisible"), "user-invisible", "status::invisible"); + g_menu_append_with_icon (menu, _("Offline"), "user-offline", "status::offline"); + + return G_MENU_MODEL (menu); +} + int main (int argc, char ** argv) { GError *error = NULL; GActionEntry entries[] = { - { "status", NULL, "s", "'offline'", NULL }, + { "status", radio_item_activate, "s", "'offline'", change_status }, { "clear", clear_action_activate } }; GMenuModel *status_items; @@ -357,9 +402,8 @@ main (int argc, char ** argv) g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, G_CALLBACK (unregister_application), NULL); - status_items = status_items_build (g_action_map_lookup_action (G_ACTION_MAP (actions), "status")); - menu = g_menu_new (); + status_items = create_status_section (); g_menu_append_section (menu, _("Status"), status_items); g_menu_append (menu, _("Clear"), "clear"); @@ -382,7 +426,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ - status_items_cleanup(); + g_object_unref (status_items); g_object_unref (settings); g_hash_table_unref (applications); return 0; -- cgit v1.2.3 From e500cbf335ba59066db88088ff18a86a4b45113c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 22:45:55 +0200 Subject: messages-service.c: removee unused includes --- src/messages-service.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 9f4cddc..15ddc22 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -20,11 +20,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include -#include -#include #include -#include +#include #include #include #include -- cgit v1.2.3 From cf241b32dd111b6b57ddd95bb06f3ad558c00a88 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 23:05:01 +0200 Subject: messages-service.c: get session bus asynchronously --- src/messages-service.c | 59 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 23 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 15ddc22..7be2274 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -35,7 +35,6 @@ with this program. If not, see . static IndicatorService * service = NULL; static GHashTable *applications; -static GDBusConnection *bus; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *menu; @@ -266,11 +265,14 @@ register_application (MessageServiceDbus *msd, { AppSection *section; gchar **applications; + GDBusConnection *bus; section = add_application (desktop_id); if (!section) return; + bus = message_service_dbus_get_connection (msd); + app_section_set_object_path (section, bus, sender, menu_path); /* remember this application in the settings key */ @@ -344,10 +346,41 @@ create_status_section () return G_MENU_MODEL (menu); } +static void +got_bus (GObject *object, + GAsyncResult * res, + gpointer user_data) +{ + GDBusConnection *bus; + GError *error = NULL; + + bus = g_bus_get_finish (res, &error); + if (!bus) { + g_warning ("unable to connect to the session bus: %s", error->message); + g_error_free (error); + return; + } + + g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_ACTION_GROUP (action_muxer), &error); + if (error) { + g_warning ("unable to export action group on dbus: %s", error->message); + g_error_free (error); + return; + } + + g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, + G_MENU_MODEL (menu), &error); + if (error) { + g_warning ("unable to export menu on dbus: %s", error->message); + g_error_free (error); + return; + } +} + int main (int argc, char ** argv) { - GError *error = NULL; GActionEntry entries[] = { { "status", radio_item_activate, "s", "'offline'", change_status }, { "clear", clear_action_activate } @@ -370,25 +403,13 @@ main (int argc, char ** argv) /* Bring up the service DBus interface */ dbus_interface = message_service_dbus_new(); - bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error); - if (!bus) { - g_warning ("unable to connect to the session bus: %s", error->message); - g_error_free (error); - return 1; - } + g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); actions = g_simple_action_group_new (); g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), dbus_interface); action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); - g_dbus_connection_export_action_group (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_ACTION_GROUP (action_muxer), &error); - if (error) { - g_warning ("unable to export action group on dbus: %s", error->message); - g_error_free (error); - return 1; - } g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, G_CALLBACK(clear_action_handler), @@ -404,14 +425,6 @@ main (int argc, char ** argv) g_menu_append_section (menu, _("Status"), status_items); g_menu_append (menu, _("Clear"), "clear"); - g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_MENU_MODEL (menu), &error); - if (error) { - g_warning ("unable to export menu on dbus: %s", error->message); - g_error_free (error); - return 1; - } - settings = g_settings_new ("com.canonical.indicator.messages"); applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); -- cgit v1.2.3 From f4c01bf86c886d8b534e14f05f813222d825f37c Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 23:20:46 +0200 Subject: messages-service.c: get rid of some global variables --- src/messages-service.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 7be2274..f7f76c2 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -32,16 +32,12 @@ with this program. If not, see . #include "messages-service-dbus.h" #include "gactionmuxer.h" -static IndicatorService * service = NULL; static GHashTable *applications; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *menu; static GSettings *settings; -static GMainLoop * mainloop = NULL; - -static MessageServiceDbus * dbus_interface = NULL; static gchar * @@ -201,9 +197,10 @@ build_launchers (gpointer data) static void service_shutdown (IndicatorService * service, gpointer user_data) { + GMainLoop *mainloop = user_data; + g_warning("Shutting down service!"); g_main_loop_quit(mainloop); - return; } static void @@ -381,6 +378,9 @@ got_bus (GObject *object, int main (int argc, char ** argv) { + GMainLoop * mainloop = NULL; + IndicatorService * service = NULL; + MessageServiceDbus * dbus_interface = NULL; GActionEntry entries[] = { { "status", radio_item_activate, "s", "'offline'", change_status }, { "clear", clear_action_activate } @@ -390,9 +390,11 @@ main (int argc, char ** argv) /* Glib init */ g_type_init(); + mainloop = g_main_loop_new (NULL, FALSE); + /* Create the Indicator Service interface */ service = indicator_service_new_version(INDICATOR_MESSAGES_DBUS_NAME, 1); - g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL); + g_signal_connect(service, INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), mainloop); /* Setting up i18n and gettext. Apparently, we need all of these. */ @@ -431,8 +433,6 @@ main (int argc, char ** argv) g_idle_add(build_launchers, NULL); - /* Let's run a mainloop */ - mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); /* Clean up */ -- cgit v1.2.3 From 82c080337fc3f420043dab2784f598472c7cfda0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 25 Jun 2012 23:22:27 +0200 Subject: messages-service.c: fix memory leak --- src/messages-service.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index f7f76c2..33ad237 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -373,6 +373,8 @@ got_bus (GObject *object, g_error_free (error); return; } + + g_object_unref (bus); } int -- cgit v1.2.3 From 106146172620ce24dc34575a3ad5237251a80407 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 26 Jun 2012 00:18:18 +0200 Subject: messages-service.c: move gsettings strv handling into gsettingsstrv.[ch] --- src/messages-service.c | 51 +++----------------------------------------------- 1 file changed, 3 insertions(+), 48 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 33ad237..f07ea68 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -31,6 +31,7 @@ with this program. If not, see . #include "dbus-data.h" #include "messages-service-dbus.h" #include "gactionmuxer.h" +#include "gsettingsstrv.h" static GHashTable *applications; @@ -237,22 +238,6 @@ clear_action_handler (MessageServiceDbus *msd, g_simple_action_set_enabled (action, attention); } -static gint -g_strv_find (gchar **str_array, - const gchar *key) -{ - gchar **it; - - g_return_val_if_fail (str_array != NULL, -1); - - for (it = str_array; *it; it++) { - if (!g_strcmp0 (key, *it)) - return it - str_array; - } - - return -1; -} - static void register_application (MessageServiceDbus *msd, const gchar *sender, @@ -261,7 +246,6 @@ register_application (MessageServiceDbus *msd, gpointer user_data) { AppSection *section; - gchar **applications; GDBusConnection *bus; section = add_application (desktop_id); @@ -272,22 +256,7 @@ register_application (MessageServiceDbus *msd, app_section_set_object_path (section, bus, sender, menu_path); - /* remember this application in the settings key */ - applications = g_settings_get_strv (settings, "applications"); - if (g_strv_find (applications, desktop_id) < 0) { - GVariantBuilder builder; - gchar **app; - - g_variant_builder_init (&builder, (GVariantType *)"as"); - for (app = applications; *app; app++) - g_variant_builder_add (&builder, "s", *app); - g_variant_builder_add (&builder, "s", desktop_id); - - g_settings_set_value (settings, "applications", - g_variant_builder_end (&builder)); - } - - g_strfreev (applications); + g_settings_strv_append_unique (settings, "applications", desktop_id); } static void @@ -295,22 +264,8 @@ unregister_application (MessageServiceDbus *msd, const gchar *desktop_id, gpointer user_data) { - gchar **applications = g_settings_get_strv (settings, "applications"); - gchar **app; - GVariantBuilder builder; - - g_variant_builder_init (&builder, (GVariantType *)"as"); - for (app = applications; *app; app++) { - if (g_strcmp0 (desktop_id, *app)) - g_variant_builder_add (&builder, "s", *app); - } - - g_settings_set_value (settings, "applications", - g_variant_builder_end (&builder)); - remove_application (desktop_id); - - g_strfreev (applications); + g_settings_strv_remove (settings, "applications", desktop_id); } static void -- cgit v1.2.3 From be44bb8644730b598fdc1990ab81c1f067dc2353 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 26 Jun 2012 00:46:00 +0200 Subject: messages-service: move gmenu utility functions into gmenuutils.[ch] As a neat side-effect, this fixes a memory leak in app-section.c. --- src/messages-service.c | 46 ++++++---------------------------------------- 1 file changed, 6 insertions(+), 40 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index f07ea68..8a08423 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -32,6 +32,7 @@ with this program. If not, see . #include "messages-service-dbus.h" #include "gactionmuxer.h" #include "gsettingsstrv.h" +#include "gmenuutils.h" static GHashTable *applications; @@ -110,26 +111,6 @@ add_application (const gchar *desktop_id) return section; } -/* g_menu_model_find_section: - * - * @Returns the index of the first menu item that is linked to #section, or -1 - * if there's no such item. - */ -static int -g_menu_find_section (GMenu *menu, - GMenuModel *section) -{ - int n_items = g_menu_model_get_n_items (G_MENU_MODEL (menu)); - int i; - - for (i = 0; i < n_items; i++) { - if (section == g_menu_model_get_item_link (G_MENU_MODEL (menu), i, G_MENU_LINK_SECTION)) - return i; - } - - return -1; -} - static void remove_application (const char *desktop_id) { @@ -268,32 +249,17 @@ unregister_application (MessageServiceDbus *msd, g_settings_strv_remove (settings, "applications", desktop_id); } -static void -g_menu_append_with_icon (GMenu *menu, - const gchar *label, - const gchar *icon_name, - const gchar *detailed_action) -{ - GMenuItem *item; - - item = g_menu_item_new (label, detailed_action); - g_menu_item_set_attribute (item, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", icon_name); - - g_menu_append_item (menu, item); - g_object_unref (item); -} - GMenuModel * create_status_section () { GMenu *menu; menu = g_menu_new (); - g_menu_append_with_icon (menu, _("Available"), "user-available", "status::available"); - g_menu_append_with_icon (menu, _("Away"), "user-away", "status::away"); - g_menu_append_with_icon (menu, _("Busy"), "user-busy", "status::busy"); - g_menu_append_with_icon (menu, _("Invisible"), "user-invisible", "status::invisible"); - g_menu_append_with_icon (menu, _("Offline"), "user-offline", "status::offline"); + g_menu_append_with_icon_name (menu, _("Available"), "user-available", "status::available"); + g_menu_append_with_icon_name (menu, _("Away"), "user-away", "status::away"); + g_menu_append_with_icon_name (menu, _("Busy"), "user-busy", "status::busy"); + g_menu_append_with_icon_name (menu, _("Invisible"), "user-invisible", "status::invisible"); + g_menu_append_with_icon_name (menu, _("Offline"), "user-offline", "status::offline"); return G_MENU_MODEL (menu); } -- cgit v1.2.3 From 93db8c38f2252cb4d506d90721446c0ad524ca3b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 17:25:34 +0200 Subject: Add draws-attention flag to source actions AppSections watch those flags for associated sources and mux them into a draws-attention property for the whole section. --- src/messages-service.c | 43 ++++++++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 8a08423..209abe5 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -73,6 +73,31 @@ actions_changed (GObject *object, g_free (id); } + +static gboolean +app_section_draws_attention (gpointer key, + gpointer value, + gpointer user_data) +{ + AppSection *section = value; + return app_section_get_draws_attention (section); +} + +static void +draws_attention_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + GSimpleAction *clear; + gboolean attention; + + clear = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "clear")); + g_return_if_fail (clear != NULL); + + attention = g_hash_table_find (applications, app_section_draws_attention, NULL) != NULL; + g_simple_action_set_enabled (clear, attention); +} + static AppSection * add_application (const gchar *desktop_id) { @@ -98,6 +123,8 @@ add_application (const gchar *desktop_id) g_action_muxer_insert (action_muxer, id, app_section_get_actions (section)); g_signal_connect (section, "notify::actions", G_CALLBACK (actions_changed), NULL); + g_signal_connect (section, "notify::draws-attention", + G_CALLBACK (draws_attention_changed), NULL); /* TODO insert it at the right position (alphabetically by application name) */ menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); @@ -132,6 +159,9 @@ remove_application (const char *desktop_id) if (pos >= 0) g_menu_remove (menu, pos); g_action_muxer_remove (action_muxer, id); + + g_signal_handlers_disconnect_by_func (section, actions_changed, NULL); + g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL); } else { g_warning ("could not remove '%s', it's not registered", desktop_id); @@ -210,15 +240,6 @@ change_status (GSimpleAction *action, g_message ("changing status to %s", g_variant_get_string (value, NULL)); } -static void -clear_action_handler (MessageServiceDbus *msd, - gboolean attention, - gpointer user_data) -{ - GSimpleAction *action = user_data; - g_simple_action_set_enabled (action, attention); -} - static void register_application (MessageServiceDbus *msd, const gchar *sender, @@ -336,10 +357,6 @@ main (int argc, char ** argv) action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_ATTENTION_CHANGED, - G_CALLBACK(clear_action_handler), - g_action_map_lookup_action (G_ACTION_MAP (actions), "clear")); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION, G_CALLBACK (register_application), NULL); g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, -- cgit v1.2.3 From 58bb62e4b6f88e2f6688afe2e94ac0d954eacadf Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 17:56:32 +0200 Subject: Make "Clear" work again --- src/messages-service.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 209abe5..2fa36b2 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -215,13 +215,21 @@ service_shutdown (IndicatorService * service, gpointer user_data) g_main_loop_quit(mainloop); } +static void +app_section_remove_attention (gpointer key, + gpointer value, + gpointer user_data) +{ + AppSection *section = value; + app_section_clear_draws_attention (section); +} + static void clear_action_activate (GSimpleAction *simple, GVariant *param, gpointer user_data) { - MessageServiceDbus *msg_service = user_data; - message_service_dbus_set_attention(msg_service, FALSE); + g_hash_table_foreach (applications, app_section_remove_attention, NULL); } static void @@ -352,7 +360,7 @@ main (int argc, char ** argv) g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); actions = g_simple_action_group_new (); - g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), dbus_interface); + g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); -- cgit v1.2.3 From eec8624cd87d14d083fc2c81dec85e79e93e494b Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 18:08:42 +0200 Subject: Disable "Clear" initially --- src/messages-service.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 2fa36b2..f7bcc2a 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -278,6 +278,30 @@ unregister_application (MessageServiceDbus *msd, g_settings_strv_remove (settings, "applications", desktop_id); } +GSimpleActionGroup * +create_action_group () +{ + GSimpleActionGroup *actions; + GSimpleAction *clear; + GSimpleAction *status; + + actions = g_simple_action_group_new (); + + status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"), + g_variant_new ("s", "offline")); + g_signal_connect (status, "activate", G_CALLBACK (radio_item_activate), NULL); + g_signal_connect (status, "change-state", G_CALLBACK (change_status), NULL); + + clear = g_simple_action_new ("clear", NULL); + g_simple_action_set_enabled (clear, FALSE); + g_signal_connect (clear, "activate", G_CALLBACK (clear_action_activate), NULL); + + g_simple_action_group_insert (actions, G_ACTION (status)); + g_simple_action_group_insert (actions, G_ACTION (clear)); + + return actions; +} + GMenuModel * create_status_section () { @@ -333,10 +357,6 @@ main (int argc, char ** argv) GMainLoop * mainloop = NULL; IndicatorService * service = NULL; MessageServiceDbus * dbus_interface = NULL; - GActionEntry entries[] = { - { "status", radio_item_activate, "s", "'offline'", change_status }, - { "clear", clear_action_activate } - }; GMenuModel *status_items; /* Glib init */ @@ -359,8 +379,7 @@ main (int argc, char ** argv) g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); - actions = g_simple_action_group_new (); - g_simple_action_group_add_entries (actions, entries, G_N_ELEMENTS (entries), NULL); + actions = create_action_group (); action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); -- cgit v1.2.3 From 9ebfba3cde97027e4db9e220886760b802b8a213 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 18:21:55 +0200 Subject: Set status action when requested --- src/messages-service.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index f7bcc2a..e892aef 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -245,6 +245,18 @@ change_status (GSimpleAction *action, GVariant *value, gpointer user_data) { + const gchar *status; + + g_variant_get (value, "&s", &status); + + g_return_if_fail (g_str_equal (status, "available") || + g_str_equal (status, "away")|| + g_str_equal (status, "busy") || + g_str_equal (status, "invisible") || + g_str_equal (status, "offline")); + + g_simple_action_set_state (action, value); + g_message ("changing status to %s", g_variant_get_string (value, NULL)); } -- cgit v1.2.3 From 579f3cbd04bed13dae44dc87e83cae3092a90d49 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 20:50:22 +0200 Subject: Add toplevel menu The toplevel menu represents the indicator itself. It has one item with a submenu, which is the indicator's popup menu. The action that is set on the toplevel will never be activated, but its state is used to indicate "draws-attention". --- src/messages-service.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index e892aef..4bd7e0c 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -38,6 +38,7 @@ static GHashTable *applications; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; +static GMenu *toplevel_menu; static GMenu *menu; static GSettings *settings; @@ -88,13 +89,17 @@ draws_attention_changed (GObject *object, GParamSpec *pspec, gpointer user_data) { + GSimpleAction *messages; GSimpleAction *clear; gboolean attention; + messages = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "messages")); clear = G_SIMPLE_ACTION (g_simple_action_group_lookup (actions, "clear")); - g_return_if_fail (clear != NULL); + g_return_if_fail (messages != NULL && clear != NULL); attention = g_hash_table_find (applications, app_section_draws_attention, NULL) != NULL; + + g_simple_action_set_state (messages, g_variant_new_boolean (attention)); g_simple_action_set_enabled (clear, attention); } @@ -294,11 +299,16 @@ GSimpleActionGroup * create_action_group () { GSimpleActionGroup *actions; + GSimpleAction *messages; GSimpleAction *clear; GSimpleAction *status; actions = g_simple_action_group_new (); + /* state of the messages action mirrors "draws-attention" */ + messages = g_simple_action_new_stateful ("messages", G_VARIANT_TYPE ("b"), + g_variant_new_boolean (FALSE)); + status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"), g_variant_new ("s", "offline")); g_signal_connect (status, "activate", G_CALLBACK (radio_item_activate), NULL); @@ -308,6 +318,7 @@ create_action_group () g_simple_action_set_enabled (clear, FALSE); g_signal_connect (clear, "activate", G_CALLBACK (clear_action_activate), NULL); + g_simple_action_group_insert (actions, G_ACTION (messages)); g_simple_action_group_insert (actions, G_ACTION (status)); g_simple_action_group_insert (actions, G_ACTION (clear)); @@ -353,7 +364,7 @@ got_bus (GObject *object, } g_dbus_connection_export_menu_model (bus, INDICATOR_MESSAGES_DBUS_OBJECT, - G_MENU_MODEL (menu), &error); + G_MENU_MODEL (toplevel_menu), &error); if (error) { g_warning ("unable to export menu on dbus: %s", error->message); g_error_free (error); @@ -370,6 +381,7 @@ main (int argc, char ** argv) IndicatorService * service = NULL; MessageServiceDbus * dbus_interface = NULL; GMenuModel *status_items; + GMenuItem *header; /* Glib init */ g_type_init(); @@ -406,6 +418,13 @@ main (int argc, char ** argv) g_menu_append_section (menu, _("Status"), status_items); g_menu_append (menu, _("Clear"), "clear"); + toplevel_menu = g_menu_new (); + header = g_menu_item_new (NULL, "messages"); + g_menu_item_set_submenu (header, G_MENU_MODEL (menu)); + g_menu_item_set_attribute (header, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", "indicator-messages"); + g_menu_append_item (toplevel_menu, header); + g_object_unref (header); + settings = g_settings_new ("com.canonical.indicator.messages"); applications = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); -- cgit v1.2.3 From 193886f467b636a91d546656017de3fd0fa62677 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 21:42:23 +0200 Subject: Use gdbus-codegen also for the server side messages service --- src/messages-service.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 4bd7e0c..ec36335 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -29,13 +29,14 @@ with this program. If not, see . #include "app-section.h" #include "dbus-data.h" -#include "messages-service-dbus.h" #include "gactionmuxer.h" #include "gsettingsstrv.h" #include "gmenuutils.h" +#include "indicator-messages-service.h" static GHashTable *applications; +IndicatorMessagesService *messages_service; static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *toplevel_menu; @@ -266,33 +267,39 @@ change_status (GSimpleAction *action, } static void -register_application (MessageServiceDbus *msd, - const gchar *sender, +register_application (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, const gchar *desktop_id, const gchar *menu_path, gpointer user_data) { AppSection *section; GDBusConnection *bus; + const gchar *sender; section = add_application (desktop_id); if (!section) return; - bus = message_service_dbus_get_connection (msd); + bus = g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (service)); + sender = g_dbus_method_invocation_get_sender (invocation); app_section_set_object_path (section, bus, sender, menu_path); - g_settings_strv_append_unique (settings, "applications", desktop_id); + + indicator_messages_service_complete_register_application (service, invocation); } static void -unregister_application (MessageServiceDbus *msd, +unregister_application (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, const gchar *desktop_id, gpointer user_data) { remove_application (desktop_id); g_settings_strv_remove (settings, "applications", desktop_id); + + indicator_messages_service_complete_unregister_application (service, invocation); } GSimpleActionGroup * @@ -371,6 +378,15 @@ got_bus (GObject *object, return; } + g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (messages_service), + bus, INDICATOR_MESSAGES_DBUS_SERVICE_OBJECT, + &error); + if (error) { + g_warning ("unable to export messages service on dbus: %s", error->message); + g_error_free (error); + return; + } + g_object_unref (bus); } @@ -379,7 +395,6 @@ main (int argc, char ** argv) { GMainLoop * mainloop = NULL; IndicatorService * service = NULL; - MessageServiceDbus * dbus_interface = NULL; GMenuModel *status_items; GMenuItem *header; @@ -399,7 +414,7 @@ main (int argc, char ** argv) textdomain (GETTEXT_PACKAGE); /* Bring up the service DBus interface */ - dbus_interface = message_service_dbus_new(); + messages_service = indicator_messages_service_skeleton_new (); g_bus_get (G_BUS_TYPE_SESSION, NULL, got_bus, NULL); @@ -408,9 +423,9 @@ main (int argc, char ** argv) action_muxer = g_action_muxer_new (); g_action_muxer_insert (action_muxer, NULL, G_ACTION_GROUP (actions)); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_REGISTER_APPLICATION, + g_signal_connect (messages_service, "handle-register-application", G_CALLBACK (register_application), NULL); - g_signal_connect (dbus_interface, MESSAGE_SERVICE_DBUS_SIGNAL_UNREGISTER_APPLICATION, + g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); menu = g_menu_new (); @@ -434,6 +449,7 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ + g_object_unref (messages_service); g_object_unref (status_items); g_object_unref (settings); g_hash_table_unref (applications); -- cgit v1.2.3 From cc6cbf767baba6ab2b5f2ec32f0d9ff2a7f94cfa Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 22:44:30 +0200 Subject: Sync chat status from and to clients --- src/messages-service.c | 50 +++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 7 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index ec36335..a12847f 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -246,10 +246,26 @@ radio_item_activate (GSimpleAction *action, g_action_change_state (G_ACTION (action), parameter); } +static gboolean +g_action_state_equal (GAction *action, + GVariant *value) +{ + GVariant *state; + gboolean eq; + + state = g_action_get_state (action); + g_return_val_if_fail (state != NULL, FALSE); + + eq = g_variant_equal (state, value); + + g_variant_unref (state); + return eq; +} + static void -change_status (GSimpleAction *action, - GVariant *value, - gpointer user_data) +change_status_action (GSimpleAction *action, + GVariant *value, + gpointer user_data) { const gchar *status; @@ -261,9 +277,11 @@ change_status (GSimpleAction *action, g_str_equal (status, "invisible") || g_str_equal (status, "offline")); - g_simple_action_set_state (action, value); - - g_message ("changing status to %s", g_variant_get_string (value, NULL)); + if (!g_action_state_equal (G_ACTION (action), value)) { + g_message ("%s", status); + g_simple_action_set_state (action, value); + indicator_messages_service_emit_status_changed (messages_service, status); + } } static void @@ -302,6 +320,22 @@ unregister_application (IndicatorMessagesService *service, indicator_messages_service_complete_unregister_application (service, invocation); } +static void +set_status (IndicatorMessagesService *service, + GDBusMethodInvocation *invocation, + const gchar *status_str, + gpointer user_data) +{ + GAction *status; + + status = g_simple_action_group_lookup (actions, "status"); + g_return_if_fail (status != NULL); + + g_action_change_state (status, g_variant_new_string (status_str)); + + indicator_messages_service_complete_set_status (service, invocation); +} + GSimpleActionGroup * create_action_group () { @@ -319,7 +353,7 @@ create_action_group () status = g_simple_action_new_stateful ("status", G_VARIANT_TYPE ("s"), g_variant_new ("s", "offline")); g_signal_connect (status, "activate", G_CALLBACK (radio_item_activate), NULL); - g_signal_connect (status, "change-state", G_CALLBACK (change_status), NULL); + g_signal_connect (status, "change-state", G_CALLBACK (change_status_action), NULL); clear = g_simple_action_new ("clear", NULL); g_simple_action_set_enabled (clear, FALSE); @@ -427,6 +461,8 @@ main (int argc, char ** argv) G_CALLBACK (register_application), NULL); g_signal_connect (messages_service, "handle-unregister-application", G_CALLBACK (unregister_application), NULL); + g_signal_connect (messages_service, "handle-set-status", + G_CALLBACK (set_status), NULL); menu = g_menu_new (); status_items = create_status_section (); -- cgit v1.2.3 From 6c93ee8e97bca993273c9dcfbebd3e52d0ac6c83 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 22:47:11 +0200 Subject: Remove header from status section --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index a12847f..53d6509 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -466,7 +466,7 @@ main (int argc, char ** argv) menu = g_menu_new (); status_items = create_status_section (); - g_menu_append_section (menu, _("Status"), status_items); + g_menu_append_section (menu, NULL, status_items); g_menu_append (menu, _("Clear"), "clear"); toplevel_menu = g_menu_new (); -- cgit v1.2.3 From 37acacae18286dbfeceacc74db8e5ff02ae8f8b2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Wed, 27 Jun 2012 23:55:52 +0200 Subject: Only show chat section when necessary The chat section is only shown when an application that is registered to use it is running. Applications are registered if their desktop file contains: X-MessagingMenu-UsesChatStatus: true --- src/messages-service.c | 39 +++++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 53d6509..6e88087 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -41,6 +41,7 @@ static GSimpleActionGroup *actions; static GActionMuxer *action_muxer; static GMenu *toplevel_menu; static GMenu *menu; +static GMenuModel *chat_section; static GSettings *settings; @@ -104,6 +105,36 @@ draws_attention_changed (GObject *object, g_simple_action_set_enabled (clear, attention); } +static gboolean +app_section_uses_chat (gpointer key, + gpointer value, + gpointer user_data) +{ + AppSection *section = value; + return app_section_get_uses_chat_status (section); +} + +static void +uses_chat_status_changed (GObject *object, + GParamSpec *pspec, + gpointer user_data) +{ + gboolean show_chat; + GMenuModel *first_section; + + show_chat = g_hash_table_find (applications, app_section_uses_chat, NULL) != NULL; + + first_section = g_menu_model_get_item_link (G_MENU_MODEL (menu), 0, G_MENU_LINK_SECTION); + if (first_section == chat_section) { + if (!show_chat) + g_menu_remove (menu, 0); + } + else { + if (show_chat) + g_menu_insert_section (menu, 0, NULL, chat_section); + } +} + static AppSection * add_application (const gchar *desktop_id) { @@ -131,6 +162,8 @@ add_application (const gchar *desktop_id) G_CALLBACK (actions_changed), NULL); g_signal_connect (section, "notify::draws-attention", G_CALLBACK (draws_attention_changed), NULL); + g_signal_connect (section, "notify::uses-chat-status", + G_CALLBACK (uses_chat_status_changed), NULL); /* TODO insert it at the right position (alphabetically by application name) */ menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); @@ -429,7 +462,6 @@ main (int argc, char ** argv) { GMainLoop * mainloop = NULL; IndicatorService * service = NULL; - GMenuModel *status_items; GMenuItem *header; /* Glib init */ @@ -465,8 +497,7 @@ main (int argc, char ** argv) G_CALLBACK (set_status), NULL); menu = g_menu_new (); - status_items = create_status_section (); - g_menu_append_section (menu, NULL, status_items); + chat_section = create_status_section (); g_menu_append (menu, _("Clear"), "clear"); toplevel_menu = g_menu_new (); @@ -486,7 +517,7 @@ main (int argc, char ** argv) /* Clean up */ g_object_unref (messages_service); - g_object_unref (status_items); + g_object_unref (chat_section); g_object_unref (settings); g_hash_table_unref (applications); return 0; -- cgit v1.2.3 From 2c2d155860b16329d6f2c697b64cbe6f2ad639e2 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 16 Aug 2012 20:35:07 +0200 Subject: Set accessible description (statically to "Messages" for now) --- src/messages-service.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 6e88087..4b32006 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -504,6 +504,7 @@ main (int argc, char ** argv) header = g_menu_item_new (NULL, "messages"); g_menu_item_set_submenu (header, G_MENU_MODEL (menu)); g_menu_item_set_attribute (header, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", "indicator-messages"); + g_menu_item_set_attribute (header, INDICATOR_MENU_ATTRIBUTE_ACCESSIBLE_DESCRIPTION, "s", _("Messages")); g_menu_append_item (toplevel_menu, header); g_object_unref (header); -- cgit v1.2.3 From d62fb5bcbc663b4f511f25963c06ec3d51eccdb8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 19 Aug 2012 19:37:37 -0500 Subject: when removing an application in messages-service, disconnect the notify::uses-chat-status handler --- src/messages-service.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index 4b32006..a7355d0 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -201,6 +201,7 @@ remove_application (const char *desktop_id) g_signal_handlers_disconnect_by_func (section, actions_changed, NULL); g_signal_handlers_disconnect_by_func (section, draws_attention_changed, NULL); + g_signal_handlers_disconnect_by_func (section, uses_chat_status_changed, NULL); } else { g_warning ("could not remove '%s', it's not registered", desktop_id); -- cgit v1.2.3 From d34fb7000e9b508b05c653b47bb60f35989c34f9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 19 Aug 2012 23:34:49 -0500 Subject: in messages-service.c, make the functions create_action_group() and create_status_section() static --- src/messages-service.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index a7355d0..ccd2eba 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -370,8 +370,8 @@ set_status (IndicatorMessagesService *service, indicator_messages_service_complete_set_status (service, invocation); } -GSimpleActionGroup * -create_action_group () +static GSimpleActionGroup * +create_action_group (void) { GSimpleActionGroup *actions; GSimpleAction *messages; @@ -400,8 +400,8 @@ create_action_group () return actions; } -GMenuModel * -create_status_section () +static GMenuModel * +create_status_section (void) { GMenu *menu; -- cgit v1.2.3 From 4e68daeee7fe848ce95157c18f1499335b0888fc Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Mon, 20 Aug 2012 23:44:39 +0200 Subject: Insert new app items right before the "Clear" item This still isn't as specified by design (should be alphabetically), but at least "Clear" is below the app items now. --- src/messages-service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index ccd2eba..aade829 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -168,7 +168,7 @@ add_application (const gchar *desktop_id) /* TODO insert it at the right position (alphabetically by application name) */ menuitem = g_menu_item_new_section (NULL, app_section_get_menu (section)); g_menu_item_set_attribute (menuitem, "action-namespace", "s", id); - g_menu_insert_item (menu, 2, menuitem); + g_menu_insert_item (menu, g_menu_model_get_n_items (G_MENU_MODEL (menu)) -1, menuitem); g_object_unref (menuitem); } -- cgit v1.2.3 From 7d036b65aac90b646eb7845cfc8e229464f372f0 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Tue, 21 Aug 2012 11:40:47 +0200 Subject: Show icons in application and source menu items Everthing goes through GIcon now, using g_icon_{to,new_for}_string to set a string attribute on the menu item. The attribute is prefixed x-canonical- for now. --- src/messages-service.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/messages-service.c') diff --git a/src/messages-service.c b/src/messages-service.c index aade829..7654e1f 100644 --- a/src/messages-service.c +++ b/src/messages-service.c @@ -464,6 +464,8 @@ main (int argc, char ** argv) GMainLoop * mainloop = NULL; IndicatorService * service = NULL; GMenuItem *header; + GIcon *icon; + gchar *iconstr; /* Glib init */ g_type_init(); @@ -501,11 +503,14 @@ main (int argc, char ** argv) chat_section = create_status_section (); g_menu_append (menu, _("Clear"), "clear"); + icon = g_themed_icon_new ("indicator-messages"); + iconstr = g_icon_to_string (icon); + toplevel_menu = g_menu_new (); header = g_menu_item_new (NULL, "messages"); g_menu_item_set_submenu (header, G_MENU_MODEL (menu)); - g_menu_item_set_attribute (header, INDICATOR_MENU_ATTRIBUTE_ICON_NAME, "s", "indicator-messages"); - g_menu_item_set_attribute (header, INDICATOR_MENU_ATTRIBUTE_ACCESSIBLE_DESCRIPTION, "s", _("Messages")); + g_menu_item_set_attribute (header, "x-canonical-icon", "s", iconstr); + g_menu_item_set_attribute (header, "x-canonical-accessible-description", "s", _("Messages")); g_menu_append_item (toplevel_menu, header); g_object_unref (header); @@ -518,6 +523,8 @@ main (int argc, char ** argv) g_main_loop_run(mainloop); /* Clean up */ + g_free (iconstr); + g_object_unref (icon); g_object_unref (messages_service); g_object_unref (chat_section); g_object_unref (settings); -- cgit v1.2.3