Merge pull request #330 from miseran/click_action

Allow middle click on notification to invoke action
This commit is contained in:
Nikos Tsipinakis 2017-06-30 08:00:41 +03:00 committed by GitHub
commit 2927140d8b
6 changed files with 55 additions and 24 deletions

View File

@ -614,6 +614,11 @@ The "context" keybinding is used to interact with these actions, by showing a
menu of possible actions. This feature requires "dmenu" or a dmenu drop-in
replacement present.
Alternatively, you can invoke an action with a middle click on the notification.
If there is exactly one associated action, or one is marked as default, that one
is invoked. If there are multiple, the context menu is shown. The same applies
to URLs when there are no actions.
=head1 MISCELLANEOUS
Dunst can be paused by sending a notification with a summary of

View File

@ -94,11 +94,16 @@ char *extract_urls(const char *to_match)
* Open url in browser.
*
*/
void open_browser(const char *url)
{
void open_browser(const char *in) {
// remove prefix and test url
char *url = extract_urls(in);
if (!url)
return;
int browser_pid1 = fork();
if (browser_pid1) {
g_free(url);
int status;
waitpid(browser_pid1, &status, 0);
} else {
@ -164,23 +169,10 @@ void dispatch_menu_result(const char *input)
{
char *in = g_strdup(input);
g_strstrip(in);
switch (in[0]) {
case '#':
if (in[0] == '#') {
invoke_action(in + 1);
break;
case '[': // named url. skip name and continue
in = strchr(in, ']');
if (in == NULL)
break;
default:
{ // test and open url
char *maybe_url = extract_urls(in);
if (maybe_url) {
open_browser(maybe_url);
g_free(maybe_url);
break;
}
}
} else {
open_browser(in);
}
g_free(in);
}

View File

@ -3,7 +3,7 @@
#define DUNST_MENU_H
char *extract_urls(const char *to_match);
void open_browser(const char *url);
void open_browser(const char *in);
void invoke_action(const char *action);
void regex_teardown(void);

View File

@ -588,4 +588,32 @@ int notification_get_ttl(notification *n) {
int notification_get_age(notification *n) {
return time(NULL) - n->timestamp;
}
/*
* If the notification has exactly one action, or one is marked as default,
* invoke it. If there are multiple and no default, open the context menu. If
* there are no actions, proceed similarly with urls.
*/
void notification_do_action(notification *n) {
if (n->actions) {
if (n->actions->count == 2) {
action_invoked(n, n->actions->actions[0]);
return;
}
for (int i = 0; i < n->actions->count; i += 2) {
if (strcmp(n->actions->actions[i], "default") == 0) {
action_invoked(n, n->actions->actions[i]);
return;
}
}
context_menu();
} else if (n->urls) {
if (strstr(n->urls, "\n") == NULL)
open_browser(n->urls);
else
context_menu();
}
}
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -73,6 +73,7 @@ char *notification_replace_format(const char *needle, const char *replacement, c
void notification_update_text_to_render(notification *n);
int notification_get_ttl(notification *n);
int notification_get_age(notification *n);
void notification_do_action(notification *n);
#endif
/* vim: set tabstop=8 shiftwidth=8 expandtab textwidth=0: */

View File

@ -820,7 +820,7 @@ gboolean x_mainloop_fd_dispatch(GSource * source, GSourceFunc callback,
case SelectionNotify:
if (ev.xselection.property == xctx.utf8)
break;
case ButtonPress:
case ButtonRelease:
if (ev.xbutton.window == xctx.win) {
x_handle_click(ev);
}
@ -896,7 +896,7 @@ static void x_handle_click(XEvent ev)
return;
}
if (ev.xbutton.button == Button1) {
if (ev.xbutton.button == Button1 || ev.xbutton.button == Button2) {
int y = settings.separator_height;
notification *n = NULL;
int first = true;
@ -910,8 +910,13 @@ static void x_handle_click(XEvent ev)
if (first)
y += settings.frame_width;
}
if (n)
if (n) {
if (ev.xbutton.button == Button1)
notification_close(n, 2);
else
notification_do_action(n);
}
}
}
@ -1055,7 +1060,7 @@ static void x_win_setup(void)
wa.background_pixmap = ParentRelative;
wa.event_mask =
ExposureMask | KeyPressMask | VisibilityChangeMask |
ButtonPressMask | FocusChangeMask| StructureNotifyMask;
ButtonReleaseMask | FocusChangeMask| StructureNotifyMask;
screen_info *scr = get_active_screen();
xctx.win =