Skip to content

Commit

Permalink
Merge pull request dunst-project#330 from miseran/click_action
Browse files Browse the repository at this point in the history
Allow middle click on notification to invoke action
  • Loading branch information
tsipinakis authored Jun 30, 2017
2 parents aec3533 + d9977cb commit 2927140
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 24 deletions.
5 changes: 5 additions & 0 deletions docs/dunst.pod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
28 changes: 10 additions & 18 deletions src/menu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
28 changes: 28 additions & 0 deletions src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -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: */
1 change: 1 addition & 0 deletions src/notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -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: */
15 changes: 10 additions & 5 deletions src/x11/x.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand All @@ -910,8 +910,13 @@ static void x_handle_click(XEvent ev)
if (first)
y += settings.frame_width;
}
if (n)
notification_close(n, 2);

if (n) {
if (ev.xbutton.button == Button1)
notification_close(n, 2);
else
notification_do_action(n);
}
}
}

Expand Down Expand Up @@ -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 =
Expand Down

0 comments on commit 2927140

Please sign in to comment.