Merge pull request #330 from miseran/click_action
Allow middle click on notification to invoke action
This commit is contained in:
commit
2927140d8b
@ -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
|
||||
|
28
src/menu.c
28
src/menu.c
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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: */
|
||||
|
@ -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: */
|
||||
|
13
src/x11/x.c
13
src/x11/x.c
@ -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 =
|
||||
|
Loading…
x
Reference in New Issue
Block a user