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: */ | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/x11/x.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								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) | ||||
|                         notification_close(n, 2); | ||||
| 
 | ||||
|                 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
	 Nikos Tsipinakis
						Nikos Tsipinakis