Compare commits
	
		
			4 Commits
		
	
	
		
			92c1bf783f
			...
			a20e4c74d8
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| a20e4c74d8 | |||
| d33c17b888 | |||
| 6033f6a869 | |||
| 88e86724c3 | 
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							| @ -2,6 +2,8 @@ Unreleased | |||||||
| 
 | 
 | ||||||
|  * Added an optional X11 user interface |  * Added an optional X11 user interface | ||||||
| 
 | 
 | ||||||
|  |  * Implemented mouse drags on the elapsed time gauge and the scrollbar | ||||||
|  | 
 | ||||||
|  * Added a "z" binding to center the view on the selected item |  * Added a "z" binding to center the view on the selected item | ||||||
| 
 | 
 | ||||||
|  * Fixed possibility of connection timeouts with PulseAudio integration |  * Fixed possibility of connection timeouts with PulseAudio integration | ||||||
|  | |||||||
							
								
								
									
										88
									
								
								nncmpp.c
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								nncmpp.c
									
									
									
									
									
								
							| @ -1144,7 +1144,7 @@ pulse_volume_status (struct pulse *self, struct str *s) | |||||||
| enum | enum | ||||||
| { | { | ||||||
| 	WIDGET_NONE = 0, WIDGET_BUTTON, WIDGET_GAUGE, WIDGET_TAB, WIDGET_SPECTRUM, | 	WIDGET_NONE = 0, WIDGET_BUTTON, WIDGET_GAUGE, WIDGET_TAB, WIDGET_SPECTRUM, | ||||||
| 	WIDGET_LIST, WIDGET_SCROLLBAR, | 	WIDGET_LIST, WIDGET_SCROLLBAR, WIDGET_MESSAGE, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct widget; | struct widget; | ||||||
| @ -1335,6 +1335,7 @@ static struct app_context | |||||||
| 	int ui_hunit;                       ///< Horizontal unit
 | 	int ui_hunit;                       ///< Horizontal unit
 | ||||||
| 	int ui_vunit;                       ///< Vertical unit
 | 	int ui_vunit;                       ///< Vertical unit
 | ||||||
| 	bool ui_focused;                    ///< Whether the window has focus
 | 	bool ui_focused;                    ///< Whether the window has focus
 | ||||||
|  | 	short ui_dragging;                  ///< ID of any dragged widget
 | ||||||
| 
 | 
 | ||||||
| #ifdef WITH_FFTW | #ifdef WITH_FFTW | ||||||
| 	struct spectrum spectrum;           ///< Spectrum analyser
 | 	struct spectrum spectrum;           ///< Spectrum analyser
 | ||||||
| @ -2187,12 +2188,19 @@ app_layout_mpd_status (void) | |||||||
| static void | static void | ||||||
| app_layout_statusbar (void) | app_layout_statusbar (void) | ||||||
| { | { | ||||||
| 
 | 	struct layout l = {}; | ||||||
| 	if (g.message) | 	if (g.message) | ||||||
| 		app_layout_text (g.message, APP_ATTR (HIGHLIGHT)); | 	{ | ||||||
|  | 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)) | ||||||
|  | 			->id = WIDGET_MESSAGE; | ||||||
|  | 		app_push_fill (&l, g.ui->label (APP_ATTR (HIGHLIGHT), g.message)) | ||||||
|  | 			->id = WIDGET_MESSAGE; | ||||||
|  | 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)) | ||||||
|  | 			->id = WIDGET_MESSAGE; | ||||||
|  | 		app_flush_layout (&l); | ||||||
|  | 	} | ||||||
| 	else if (g.editor.line) | 	else if (g.editor.line) | ||||||
| 	{ | 	{ | ||||||
| 		struct layout l = {}; |  | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | ||||||
| 		app_push (&l, g.ui->editor (APP_ATTR (HIGHLIGHT))); | 		app_push (&l, g.ui->editor (APP_ATTR (HIGHLIGHT))); | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | ||||||
| @ -2536,6 +2544,7 @@ app_process_action (enum action action) | |||||||
| 		app_invalidate (); | 		app_invalidate (); | ||||||
| 		return true; | 		return true; | ||||||
| 	default: | 	default: | ||||||
|  | 		print_error ("can't do that here: %s", g_action_descriptions[action]); | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	case ACTION_MULTISELECT: | 	case ACTION_MULTISELECT: | ||||||
| @ -2666,6 +2675,7 @@ app_editor_process_action (enum action action) | |||||||
| 		g.editor.on_end = NULL; | 		g.editor.on_end = NULL; | ||||||
| 		return true; | 		return true; | ||||||
| 	default: | 	default: | ||||||
|  | 		print_error ("can't do that here: %s", g_action_descriptions[action]); | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	case ACTION_EDITOR_B_CHAR: | 	case ACTION_EDITOR_B_CHAR: | ||||||
| @ -2706,6 +2716,7 @@ app_process_left_mouse_click (struct widget *w, int x, int y, bool double_click) | |||||||
| 		break; | 		break; | ||||||
| 	case WIDGET_GAUGE: | 	case WIDGET_GAUGE: | ||||||
| 	{ | 	{ | ||||||
|  | 		// TODO: We should avoid queuing up too many.
 | ||||||
| 		float position = (float) x / w->width; | 		float position = (float) x / w->width; | ||||||
| 		if (g.song_duration >= 1) | 		if (g.song_duration >= 1) | ||||||
| 		{ | 		{ | ||||||
| @ -2750,7 +2761,12 @@ app_process_left_mouse_click (struct widget *w, int x, int y, bool double_click) | |||||||
| 		tab->item_top = (float) y / w->height | 		tab->item_top = (float) y / w->height | ||||||
| 			* (int) tab->item_count - visible_items / 2; | 			* (int) tab->item_count - visible_items / 2; | ||||||
| 		app_invalidate (); | 		app_invalidate (); | ||||||
|  | 		break; | ||||||
| 	} | 	} | ||||||
|  | 	case WIDGET_MESSAGE: | ||||||
|  | 		cstr_set (&g.message, NULL); | ||||||
|  | 		poller_timer_reset (&g.message_timer); | ||||||
|  | 		app_invalidate (); | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
| } | } | ||||||
| @ -2762,8 +2778,27 @@ app_process_mouse (termo_mouse_event_t type, int x, int y, int button, | |||||||
| 	// XXX: Terminals don't let us know which button has been released,
 | 	// XXX: Terminals don't let us know which button has been released,
 | ||||||
| 	//   so we can't press buttons at that point.  We'd need a special "click"
 | 	//   so we can't press buttons at that point.  We'd need a special "click"
 | ||||||
| 	//   event handler that could be handled better under X11.
 | 	//   event handler that could be handled better under X11.
 | ||||||
| 	if (type != TERMO_MOUSE_PRESS) | 	if (type == TERMO_MOUSE_RELEASE) | ||||||
|  | 	{ | ||||||
|  | 		g.ui_dragging = WIDGET_NONE; | ||||||
| 		return true; | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (type == TERMO_MOUSE_DRAG) | ||||||
|  | 	{ | ||||||
|  | 		if (g.ui_dragging != WIDGET_GAUGE | ||||||
|  | 		 && g.ui_dragging != WIDGET_SCROLLBAR) | ||||||
|  | 			return true; | ||||||
|  | 
 | ||||||
|  | 		struct widget *target = NULL; | ||||||
|  | 		LIST_FOR_EACH (struct widget, w, g.widgets.head) | ||||||
|  | 			if (w->id == g.ui_dragging) | ||||||
|  | 				target = w; | ||||||
|  | 
 | ||||||
|  | 		x -= target->x; | ||||||
|  | 		y -= target->y; | ||||||
|  | 		return app_process_left_mouse_click (target, x, y, double_click); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	if (g.editor.line) | 	if (g.editor.line) | ||||||
| 	{ | 	{ | ||||||
| @ -2784,6 +2819,7 @@ app_process_mouse (termo_mouse_event_t type, int x, int y, int button, | |||||||
| 	switch (button) | 	switch (button) | ||||||
| 	{ | 	{ | ||||||
| 	case 1: | 	case 1: | ||||||
|  | 		g.ui_dragging = target->id; | ||||||
| 		return app_process_left_mouse_click (target, x, y, double_click); | 		return app_process_left_mouse_click (target, x, y, double_click); | ||||||
| 	case 4: | 	case 4: | ||||||
| 		if (target->id == WIDGET_LIST) | 		if (target->id == WIDGET_LIST) | ||||||
| @ -5244,6 +5280,8 @@ tui_init (void) | |||||||
| 	if (!termo_start (g.tk) || !initscr () || nonl () == ERR) | 	if (!termo_start (g.tk) || !initscr () || nonl () == ERR) | ||||||
| 		exit_fatal ("failed to set up the terminal"); | 		exit_fatal ("failed to set up the terminal"); | ||||||
| 
 | 
 | ||||||
|  | 	termo_set_mouse_tracking_mode (g.tk, TERMO_MOUSE_TRACKING_DRAG); | ||||||
|  | 
 | ||||||
| 	g.ui = &tui_ui; | 	g.ui = &tui_ui; | ||||||
| 	g.ui_width = COLS; | 	g.ui_width = COLS; | ||||||
| 	g.ui_height = LINES; | 	g.ui_height = LINES; | ||||||
| @ -5941,6 +5979,13 @@ on_x11_input_event (XEvent *ev) | |||||||
| 		on_x11_keypress (ev); | 		on_x11_keypress (ev); | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
|  | 	if (ev->type == MotionNotify) | ||||||
|  | 	{ | ||||||
|  | 		// We only select for Button1MotionMask, so this works out.
 | ||||||
|  | 		int x = ev->xmotion.x, y = ev->xmotion.y; | ||||||
|  | 		app_process_mouse (TERMO_MOUSE_DRAG, x, y, 1, false); | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	// See tui_on_tty_event().  Just here we know the button on button release.
 | 	// See tui_on_tty_event().  Just here we know the button on button release.
 | ||||||
| 	int x = ev->xbutton.x, y = ev->xbutton.y; | 	int x = ev->xbutton.x, y = ev->xbutton.y; | ||||||
| @ -5986,6 +6031,7 @@ on_x11_event (XEvent *ev) | |||||||
| 	case KeyPress: | 	case KeyPress: | ||||||
| 	case ButtonPress: | 	case ButtonPress: | ||||||
| 	case ButtonRelease: | 	case ButtonRelease: | ||||||
|  | 	case MotionNotify: | ||||||
| 		on_x11_input_event (ev); | 		on_x11_input_event (ev); | ||||||
| 		break; | 		break; | ||||||
| 	case UnmapNotify: | 	case UnmapNotify: | ||||||
| @ -6182,7 +6228,8 @@ x11_init (void) | |||||||
| 	XSetWindowAttributes attrs = | 	XSetWindowAttributes attrs = | ||||||
| 	{ | 	{ | ||||||
| 		.event_mask = StructureNotifyMask | ExposureMask | FocusChangeMask | 		.event_mask = StructureNotifyMask | ExposureMask | FocusChangeMask | ||||||
| 			| KeyPressMask | ButtonPressMask | ButtonReleaseMask, | 			| KeyPressMask | ButtonPressMask | ButtonReleaseMask | ||||||
|  | 			| Button1MotionMask, | ||||||
| 		.bit_gravity = NorthWestGravity, | 		.bit_gravity = NorthWestGravity, | ||||||
| 		.background_pixel = default_bg.pixel, | 		.background_pixel = default_bg.pixel, | ||||||
| 	}; | 	}; | ||||||
| @ -6307,6 +6354,8 @@ signals_setup_handlers (void) | |||||||
| 
 | 
 | ||||||
| // --- Initialisation, event handling ------------------------------------------
 | // --- Initialisation, event handling ------------------------------------------
 | ||||||
| 
 | 
 | ||||||
|  | static bool g_verbose_mode = false; | ||||||
|  | 
 | ||||||
| static void | static void | ||||||
| app_on_signal_pipe_readable (const struct pollfd *fd, void *user_data) | app_on_signal_pipe_readable (const struct pollfd *fd, void *user_data) | ||||||
| { | { | ||||||
| @ -6352,19 +6401,16 @@ app_log_handler (void *user_data, const char *quote, const char *fmt, | |||||||
| 	str_append (&message, quote); | 	str_append (&message, quote); | ||||||
| 	str_append_vprintf (&message, fmt, ap); | 	str_append_vprintf (&message, fmt, ap); | ||||||
| 
 | 
 | ||||||
| 	// If the standard error output isn't redirected, try our best at showing
 | 	// Show it to the user, then maybe log it elsewhere as well.
 | ||||||
| 	// the message to the user
 | 	cstr_set (&g.message, xstrdup (message.str)); | ||||||
| 	if (!isatty (STDERR_FILENO)) | 	poller_timer_set (&g.message_timer, 5000); | ||||||
|  | 	app_invalidate (); | ||||||
|  | 
 | ||||||
|  | 	if (g_verbose_mode && (g.ui != &tui_ui || !isatty (STDERR_FILENO))) | ||||||
| 		fprintf (stderr, "%s\n", message.str); | 		fprintf (stderr, "%s\n", message.str); | ||||||
| 	else if (g_debug_tab.active) | 	if (g_debug_tab.active) | ||||||
| 		debug_tab_push (str_steal (&message), | 		debug_tab_push (str_steal (&message), | ||||||
| 			user_data == NULL ? 0 : g.attrs[(intptr_t) user_data].attrs); | 			user_data == NULL ? 0 : g.attrs[(intptr_t) user_data].attrs); | ||||||
| 	else |  | ||||||
| 	{ |  | ||||||
| 		cstr_set (&g.message, xstrdup (message.str)); |  | ||||||
| 		app_invalidate (); |  | ||||||
| 		poller_timer_set (&g.message_timer, 5000); |  | ||||||
| 	} |  | ||||||
| 	str_free (&message); | 	str_free (&message); | ||||||
| 
 | 
 | ||||||
| 	in_processing = false; | 	in_processing = false; | ||||||
| @ -6434,6 +6480,7 @@ main (int argc, char *argv[]) | |||||||
| 		{ 'x', "x11", NULL, 0, "use X11 even when run from a terminal" }, | 		{ 'x', "x11", NULL, 0, "use X11 even when run from a terminal" }, | ||||||
| #endif  // WITH_X11
 | #endif  // WITH_X11
 | ||||||
| 		{ 'h', "help", NULL, 0, "display this help and exit" }, | 		{ 'h', "help", NULL, 0, "display this help and exit" }, | ||||||
|  | 		{ 'v', "verbose", NULL, 0, "log messages on standard error" }, | ||||||
| 		{ 'V', "version", NULL, 0, "output version information and exit" }, | 		{ 'V', "version", NULL, 0, "output version information and exit" }, | ||||||
| 		{ 0, NULL, NULL, 0, NULL } | 		{ 0, NULL, NULL, 0, NULL } | ||||||
| 	}; | 	}; | ||||||
| @ -6449,15 +6496,18 @@ main (int argc, char *argv[]) | |||||||
| 	case 'd': | 	case 'd': | ||||||
| 		g_debug_mode = true; | 		g_debug_mode = true; | ||||||
| 		break; | 		break; | ||||||
|  | 	case 'x': | ||||||
|  | 		requested_x11 = true; | ||||||
|  | 		break; | ||||||
|  | 	case 'v': | ||||||
|  | 		g_verbose_mode = true; | ||||||
|  | 		break; | ||||||
| 	case 'h': | 	case 'h': | ||||||
| 		opt_handler_usage (&oh, stdout); | 		opt_handler_usage (&oh, stdout); | ||||||
| 		exit (EXIT_SUCCESS); | 		exit (EXIT_SUCCESS); | ||||||
| 	case 'V': | 	case 'V': | ||||||
| 		printf (PROGRAM_NAME " " PROGRAM_VERSION "\n"); | 		printf (PROGRAM_NAME " " PROGRAM_VERSION "\n"); | ||||||
| 		exit (EXIT_SUCCESS); | 		exit (EXIT_SUCCESS); | ||||||
| 	case 'x': |  | ||||||
| 		requested_x11 = true; |  | ||||||
| 		break; |  | ||||||
| 	default: | 	default: | ||||||
| 		print_error ("wrong options"); | 		print_error ("wrong options"); | ||||||
| 		opt_handler_usage (&oh, stderr); | 		opt_handler_usage (&oh, stderr); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user