From 62e92c7625bc472f7b2132e2d325ca35879c2261 Mon Sep 17 00:00:00 2001 From: Sascha Kruse Date: Mon, 18 Feb 2013 10:03:54 +0000 Subject: [PATCH] add actions to context menu --- dunst.c | 106 +++++++++++++++++++++++++++++++++++++++++++-------- dunst.h | 1 + dunst_dbus.c | 26 ++++++++++++- dunst_dbus.h | 1 + 4 files changed, 118 insertions(+), 16 deletions(-) diff --git a/dunst.c b/dunst.c index fd0817d..fc60eca 100644 --- a/dunst.c +++ b/dunst.c @@ -258,12 +258,82 @@ char *extract_urls( const char * to_match) return urls; } + +void open_browser(const char *url) +{ + int browser_pid1 = fork(); + + if (browser_pid1) { + int status; + waitpid(browser_pid1, &status, 0); + } else { + int browser_pid2 = fork(); + if (browser_pid2) { + exit(0); + } else { + browser = string_append(browser, url, " "); + char **cmd = g_strsplit(browser, " ", 0); + execvp(cmd[0], cmd); + } + } +} + +void invoke_action(const char *action) +{ + notification *invoked = NULL; + char *action_identifier = NULL; + + char *name_begin = strstr(action, "("); + if (!name_begin) { + printf("invalid action: %s\n", action); + return; + } + name_begin++; + + + for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) { + notification *n = iter->data; + if (g_str_has_prefix(action, n->appname)) { + if (! n->actions) + continue; + + for (int i = 0; i < n->actions->count; i += 2) { + char *a_identifier = n->actions->actions[i]; + char *name = n->actions->actions[i+1]; + if (g_str_has_prefix(name_begin, name)) { + invoked = n; + action_identifier = a_identifier; + break; + } + } + } + } + + if (invoked && action_identifier) { + actionInvoked(invoked, action_identifier); + } +} + +void dispatch_menu_result(const char *input) +{ + char *maybe_url = extract_urls(input); + if (maybe_url) { + open_browser(maybe_url); + free(maybe_url); + return; + } + + invoke_action(input); +} + void context_menu(void) { char *dmenu_input = NULL; for (GList *iter = g_queue_peek_head_link(displayed); iter; iter = iter->next) { notification *n = iter->data; dmenu_input = string_append(dmenu_input, n->urls, "\n"); + if (n->actions) + dmenu_input = string_append(dmenu_input, n->actions->dmenu_str, "\n"); } @@ -317,23 +387,11 @@ void context_menu(void) { close(parent_io[0]); - int browser_pid1 = fork(); - if (browser_pid1) { - int status; - waitpid(browser_pid1, &status, 0); - } else { - int browser_pid2 = fork(); - if (browser_pid2) { - exit(0); - } else { - browser = string_append(browser, buf, " "); - char **cmd = g_strsplit(browser, " ", 0); - execvp(cmd[0], cmd); - } - } + dispatch_menu_result(buf); } + void run_script(notification *n) { if (!n->script || strlen(n->script) < 1) @@ -415,12 +473,13 @@ static void print_notification(notification * n) printf("\t}\n"); } - if (n->actions->count > 0) { + if (n->actions) { printf("\tactions:\n"); printf("\t{\n"); for (int i = 0; i < n->actions->count; i += 2) { printf("\t\t [%s,%s]\n", n->actions->actions[i], n->actions->actions[i+1]); } + printf("actions_dmenu: %s\n", n->actions->dmenu_str); printf("\t]\n"); } printf("\tscript: %s\n", n->script); @@ -1193,6 +1252,23 @@ int init_notification(notification * n, int id) n->urls = extract_urls(tmp); + + if (n->actions) { + n->actions->dmenu_str = NULL; + for (int i = 0; i < n->actions->count; i += 2) { + char *human_readable = n->actions->actions[i+1]; + printf("debug: %s\n", n->appname); + printf("debug: %s\n", human_readable); + char *tmp = g_strdup_printf("%s %s", n->appname, human_readable); + printf("debug: %s\n", tmp); + + n->actions->dmenu_str = string_append(n->actions->dmenu_str, + g_strdup_printf("%s(%s)", + n->appname, + human_readable), "\n"); + } + } + free(tmp); diff --git a/dunst.h b/dunst.h index b86390f..411f752 100644 --- a/dunst.h +++ b/dunst.h @@ -38,6 +38,7 @@ typedef struct _screen_info { typedef struct _actions { char **actions; + char *dmenu_str; gsize count; } Actions; diff --git a/dunst_dbus.c b/dunst_dbus.c index 2e104fe..7c4e614 100644 --- a/dunst_dbus.c +++ b/dunst_dbus.c @@ -202,7 +202,12 @@ static void onNotify(GDBusConnection *connection, n->progress = (progress < 0 || progress > 100) ? 0 : progress + 1; n->urgency = urgency; n->dbus_client = strdup(sender); - n->actions = actions; + if (actions->count > 0) { + n->actions = actions; + } else { + n->actions = NULL; + free(actions); + } for (int i = 0; i < ColLast; i++) { n->color_strings[i] = NULL; @@ -265,6 +270,25 @@ void notificationClosed(notification * n, int reason) } +void actionInvoked(notification *n, const char *identifier) +{ + GVariant *body = g_variant_new ("(us)", n->id, identifier); + GError *err = NULL; + + g_dbus_connection_emit_signal( + dbus_conn, + n->dbus_client, + "/org/freedesktop/Notifications", + "org.freedesktop.Notifications", + "ActionInvoked", + body, + &err); + + if (err) { + printf("ActionInvoked ERROR\n"); + } +} + static const GDBusInterfaceVTable interface_vtable = { handle_method_call diff --git a/dunst_dbus.h b/dunst_dbus.h index c4db447..f6e56bb 100644 --- a/dunst_dbus.h +++ b/dunst_dbus.h @@ -9,6 +9,7 @@ int initdbus(void); void dbus_tear_down(int id); /* void dbus_poll(int timeout); */ void notificationClosed(notification * n, int reason); +void actionInvoked(notification *n, const char *identifier); #endif