| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | #define _POSIX_C_SOURCE 200809L
 | 
					
						
							| 
									
										
										
										
											2018-09-19 11:37:24 +02:00
										 |  |  | #include <assert.h>
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | #include <limits.h>
 | 
					
						
							| 
									
										
										
										
											2016-01-23 20:55:01 +01:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stdint.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | #include <wlr/util/log.h>
 | 
					
						
							|  |  |  | #include "cairo.h"
 | 
					
						
							|  |  |  | #include "pango.h"
 | 
					
						
							|  |  |  | #include "pool-buffer.h"
 | 
					
						
							|  |  |  | #include "swaybar/bar.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-01 08:18:37 -04:00
										 |  |  | #include "swaybar/config.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-24 21:56:35 +01:00
										 |  |  | #include "swaybar/i3bar.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | #include "swaybar/ipc.h"
 | 
					
						
							| 
									
										
										
										
											2016-09-01 08:18:37 -04:00
										 |  |  | #include "swaybar/render.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | #include "swaybar/status_line.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | #include "wlr-layer-shell-unstable-v1-client-protocol.h"
 | 
					
						
							| 
									
										
										
										
											2016-01-23 20:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | static const int WS_HORIZONTAL_PADDING = 5; | 
					
						
							|  |  |  | static const double WS_VERTICAL_PADDING = 1.5; | 
					
						
							|  |  |  | static const double BORDER_WIDTH = 1; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | static uint32_t render_status_line_error(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, double *x) { | 
					
						
							|  |  |  | 	const char *error = output->bar->status->text; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	if (!error) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = output->height * output->scale; | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	cairo_set_source_u32(cairo, 0xFF0000FF); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int margin = 3 * output->scale; | 
					
						
							|  |  |  | 	int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	char *font = output->bar->config->font; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	int text_width, text_height; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	get_text_size(cairo, font, &text_width, &text_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 			output->scale, false, "%s", error); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 	uint32_t ideal_surface_height = ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	if (output->height < ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		return ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	*x -= text_width + margin; | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	double text_y = height / 2.0 - text_height / 2.0; | 
					
						
							|  |  |  | 	cairo_move_to(cairo, *x, (int)floor(text_y)); | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	pango_printf(cairo, font, output->scale, false, "%s", error); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	*x -= margin; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	return output->height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | static uint32_t render_status_line_text(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, double *x) { | 
					
						
							|  |  |  | 	const char *text = output->bar->status->text; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	if (!text) { | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	struct swaybar_config *config = output->bar->config; | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, output->focused ? | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 			config->colors.focused_statusline : config->colors.statusline); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	int text_width, text_height; | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 	get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 			output->scale, config->pango_markup, "%s", text); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 
					
						
							|  |  |  | 	int margin = 3 * output->scale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 	uint32_t ideal_surface_height = ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	if (output->height < ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		return ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	*x -= text_width + margin; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = output->height * output->scale; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	double text_y = height / 2.0 - text_height / 2.0; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	cairo_move_to(cairo, *x, (int)floor(text_y)); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 	pango_printf(cairo, config->font, output->scale, | 
					
						
							|  |  |  | 			config->pango_markup, "%s", text); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	*x -= margin; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	return output->height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void render_sharp_line(cairo_t *cairo, uint32_t color, | 
					
						
							|  |  |  | 		double x, double y, double width, double height) { | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, color); | 
					
						
							|  |  |  | 	if (width > 1 && height > 1) { | 
					
						
							|  |  |  | 		cairo_rectangle(cairo, x, y, width, height); | 
					
						
							|  |  |  | 		cairo_fill(cairo); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if (width == 1) { | 
					
						
							|  |  |  | 			x += 0.5; | 
					
						
							|  |  |  | 			height += y; | 
					
						
							|  |  |  | 			width = x; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (height == 1) { | 
					
						
							|  |  |  | 			y += 0.5; | 
					
						
							|  |  |  | 			width += x; | 
					
						
							|  |  |  | 			height = y; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		cairo_move_to(cairo, x, y); | 
					
						
							|  |  |  | 		cairo_set_line_width(cairo, 1.0); | 
					
						
							|  |  |  | 		cairo_line_to(cairo, width, height); | 
					
						
							|  |  |  | 		cairo_stroke(cairo); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-19 21:15:01 +02:00
										 |  |  | static enum hotspot_event_handling block_hotspot_callback(struct swaybar_output *output, | 
					
						
							| 
									
										
										
										
											2018-07-15 20:16:37 -04:00
										 |  |  | 			int x, int y, enum x11_button button, void *data) { | 
					
						
							| 
									
										
										
										
											2018-03-31 14:58:30 -04:00
										 |  |  | 	struct i3bar_block *block = data; | 
					
						
							|  |  |  | 	struct status_line *status = output->bar->status; | 
					
						
							| 
									
										
										
										
											2018-07-19 21:15:01 +02:00
										 |  |  | 	return i3bar_block_send_click(status, block, x, y, button); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:58:30 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-12 08:28:28 +01:00
										 |  |  | static void i3bar_block_unref_callback(void *data) { | 
					
						
							|  |  |  | 	i3bar_block_unref(data); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | static uint32_t render_status_block(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-17 13:31:24 +01:00
										 |  |  | 		struct swaybar_output *output, struct i3bar_block *block, double *x, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		bool edge) { | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	if (!block->full_text || !*block->full_text) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-17 13:31:24 +01:00
										 |  |  | 	struct swaybar_config *config = output->bar->config; | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	int text_width, text_height; | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 	get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 			output->scale, block->markup, "%s", block->full_text); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	int margin = 3 * output->scale; | 
					
						
							|  |  |  | 	int ws_vertical_padding = WS_VERTICAL_PADDING * 2; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	int width = text_width; | 
					
						
							|  |  |  | 	if (width < block->min_width) { | 
					
						
							|  |  |  | 		width = block->min_width; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	double block_width = width; | 
					
						
							|  |  |  | 	uint32_t ideal_height = text_height + ws_vertical_padding * 2; | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 	uint32_t ideal_surface_height = ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	if (output->height < ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		return ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*x -= width; | 
					
						
							|  |  |  | 	if (block->border && block->border_left > 0) { | 
					
						
							|  |  |  | 		*x -= (block->border_left + margin); | 
					
						
							|  |  |  | 		block_width += block->border_left + margin; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (block->border && block->border_right > 0) { | 
					
						
							|  |  |  | 		*x -= (block->border_right + margin); | 
					
						
							|  |  |  | 		block_width += block->border_right + margin; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-10 16:08:08 +10:00
										 |  |  | 	int sep_width, sep_height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	if (!edge) { | 
					
						
							|  |  |  | 		if (config->sep_symbol) { | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 			get_text_size(cairo, config->font, &sep_width, &sep_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 					output->scale, false, "%s", config->sep_symbol); | 
					
						
							| 
									
										
										
										
											2018-04-10 22:18:54 -04:00
										 |  |  | 			uint32_t _ideal_height = sep_height + ws_vertical_padding * 2; | 
					
						
							|  |  |  | 			uint32_t _ideal_surface_height = _ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 			if (output->height < _ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-11 08:34:21 +10:00
										 |  |  | 				return _ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			if (sep_width > block->separator_block_width) { | 
					
						
							|  |  |  | 				block->separator_block_width = sep_width + margin * 2; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		*x -= block->separator_block_width; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		*x -= margin; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = output->height * output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-17 14:10:57 +01:00
										 |  |  | 	if (output->bar->status->click_events) { | 
					
						
							| 
									
										
										
										
											2018-09-17 13:31:24 +01:00
										 |  |  | 		struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | 
					
						
							|  |  |  | 		hotspot->x = *x; | 
					
						
							|  |  |  | 		hotspot->y = 0; | 
					
						
							|  |  |  | 		hotspot->width = width; | 
					
						
							|  |  |  | 		hotspot->height = height; | 
					
						
							|  |  |  | 		hotspot->callback = block_hotspot_callback; | 
					
						
							|  |  |  | 		hotspot->destroy = i3bar_block_unref_callback; | 
					
						
							|  |  |  | 		hotspot->data = block; | 
					
						
							|  |  |  | 		block->ref_count++; | 
					
						
							|  |  |  | 		wl_list_insert(&output->hotspots, &hotspot->link); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	double pos = *x; | 
					
						
							|  |  |  | 	if (block->background) { | 
					
						
							|  |  |  | 		cairo_set_source_u32(cairo, block->background); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 		cairo_rectangle(cairo, pos - 0.5 * output->scale, | 
					
						
							| 
									
										
										
										
											2018-09-05 18:48:31 +09:00
										 |  |  | 				output->scale, width, height); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 		cairo_fill(cairo); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (block->border && block->border_top > 0) { | 
					
						
							|  |  |  | 		render_sharp_line(cairo, block->border, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 				pos - 0.5 * output->scale, output->scale, | 
					
						
							|  |  |  | 				block_width, block->border_top); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (block->border && block->border_bottom > 0) { | 
					
						
							|  |  |  | 		render_sharp_line(cairo, block->border, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 				pos - 0.5 * output->scale, | 
					
						
							|  |  |  | 				height - output->scale - block->border_bottom, | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 				block_width, block->border_bottom); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if (block->border != 0 && block->border_left > 0) { | 
					
						
							|  |  |  | 		render_sharp_line(cairo, block->border, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 				pos - 0.5 * output->scale, output->scale, | 
					
						
							|  |  |  | 				block->border_left, height); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 		pos += block->border_left + margin; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	double offset = 0; | 
					
						
							|  |  |  | 	if (strncmp(block->align, "left", 5) == 0) { | 
					
						
							|  |  |  | 		offset = pos; | 
					
						
							|  |  |  | 	} else if (strncmp(block->align, "right", 5) == 0) { | 
					
						
							|  |  |  | 		offset = pos + width - text_width; | 
					
						
							|  |  |  | 	} else if (strncmp(block->align, "center", 6) == 0) { | 
					
						
							|  |  |  | 		offset = pos + (width - text_width) / 2; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cairo_move_to(cairo, offset, height / 2.0 - text_height / 2.0); | 
					
						
							|  |  |  | 	uint32_t color = block->color ?  *block->color : config->colors.statusline; | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, color); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 	pango_printf(cairo, config->font, output->scale, | 
					
						
							|  |  |  | 			block->markup, "%s", block->full_text); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	pos += width; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (block->border && block->border_right > 0) { | 
					
						
							|  |  |  | 		pos += margin; | 
					
						
							|  |  |  | 		render_sharp_line(cairo, block->border, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 				pos - 0.5 * output->scale, output->scale, | 
					
						
							|  |  |  | 				block->border_right, height); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 		pos += block->border_right; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!edge && block->separator) { | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		if (output->focused) { | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 			cairo_set_source_u32(cairo, config->colors.focused_separator); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			cairo_set_source_u32(cairo, config->colors.separator); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if (config->sep_symbol) { | 
					
						
							|  |  |  | 			offset = pos + (block->separator_block_width - sep_width) / 2; | 
					
						
							| 
									
										
										
										
											2018-04-10 16:08:08 +10:00
										 |  |  | 			cairo_move_to(cairo, offset, height / 2.0 - sep_height / 2.0); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 			pango_printf(cairo, config->font, output->scale, false, | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 					"%s", config->sep_symbol); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			cairo_set_line_width(cairo, 1); | 
					
						
							|  |  |  | 			cairo_move_to(cairo, | 
					
						
							|  |  |  | 					pos + block->separator_block_width / 2, margin); | 
					
						
							|  |  |  | 			cairo_line_to(cairo, | 
					
						
							|  |  |  | 					pos + block->separator_block_width / 2, height - margin); | 
					
						
							|  |  |  | 			cairo_stroke(cairo); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	return output->height; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint32_t render_status_line_i3bar(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, double *x) { | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	uint32_t max_height = 0; | 
					
						
							|  |  |  | 	bool edge = true; | 
					
						
							| 
									
										
										
										
											2018-04-02 11:53:56 -04:00
										 |  |  | 	struct i3bar_block *block; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	wl_list_for_each(block, &output->bar->status->blocks, link) { | 
					
						
							|  |  |  | 		uint32_t h = render_status_block(cairo, output, block, x, edge); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 		max_height = h > max_height ? h : max_height; | 
					
						
							|  |  |  | 		edge = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return max_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static uint32_t render_status_line(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, double *x) { | 
					
						
							|  |  |  | 	struct status_line *status = output->bar->status; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	switch (status->protocol) { | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	case PROTOCOL_ERROR: | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		return render_status_line_error(cairo, output, x); | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	case PROTOCOL_TEXT: | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		return render_status_line_text(cairo, output, x); | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	case PROTOCOL_I3BAR: | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		return render_status_line_i3bar(cairo, output, x); | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	case PROTOCOL_UNDEF: | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-31 14:39:18 -04:00
										 |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | static uint32_t render_binding_mode_indicator(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, double x) { | 
					
						
							| 
									
										
										
										
											2018-10-12 20:23:01 +01:00
										 |  |  | 	const char *mode = output->bar->mode; | 
					
						
							|  |  |  | 	if (!mode) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	struct swaybar_config *config = output->bar->config; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	int text_width, text_height; | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 	get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-10-12 20:23:01 +01:00
										 |  |  | 			output->scale, output->bar->mode_pango_markup, | 
					
						
							| 
									
										
										
										
											2018-07-05 18:12:14 -04:00
										 |  |  | 			"%s", mode); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 
					
						
							|  |  |  | 	int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; | 
					
						
							|  |  |  | 	int border_width = BORDER_WIDTH * output->scale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	uint32_t ideal_height = text_height + ws_vertical_padding * 2 | 
					
						
							|  |  |  | 		+ border_width * 2; | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 	uint32_t ideal_surface_height = ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	if (output->height < ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		return ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	uint32_t width = text_width + ws_horizontal_padding * 2 + border_width * 2; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = output->height * output->scale; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	cairo_set_source_u32(cairo, config->colors.binding_mode.background); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_rectangle(cairo, x, 0, width, height); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, config->colors.binding_mode.border); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_rectangle(cairo, x, 0, width, border_width); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, x, 0, border_width, height); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, x + width - border_width, 0, border_width, height); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, x, height - border_width, width, border_width); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	double text_y = height / 2.0 - text_height / 2.0; | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, config->colors.binding_mode.text); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_move_to(cairo, x + width / 2 - text_width / 2, (int)floor(text_y)); | 
					
						
							| 
									
										
										
										
											2018-10-12 20:23:01 +01:00
										 |  |  | 	pango_printf(cairo, config->font, output->scale, | 
					
						
							|  |  |  | 			output->bar->mode_pango_markup, "%s", mode); | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	return output->height; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-19 21:15:01 +02:00
										 |  |  | static enum hotspot_event_handling workspace_hotspot_callback(struct swaybar_output *output, | 
					
						
							| 
									
										
										
										
											2018-07-15 20:16:37 -04:00
										 |  |  | 			int x, int y, enum x11_button button, void *data) { | 
					
						
							| 
									
										
										
										
											2018-07-19 21:15:01 +02:00
										 |  |  | 	if (button != LEFT) { | 
					
						
							|  |  |  | 		return HOTSPOT_PROCESS; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | 	ipc_send_workspace_command(output->bar, (const char *)data); | 
					
						
							| 
									
										
										
										
											2018-07-19 21:15:01 +02:00
										 |  |  | 	return HOTSPOT_IGNORE; | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | static uint32_t render_workspace_button(cairo_t *cairo, | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		struct swaybar_output *output, | 
					
						
							|  |  |  | 		struct swaybar_workspace *ws, double *x) { | 
					
						
							|  |  |  | 	struct swaybar_config *config = output->bar->config; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 	struct box_colors box_colors; | 
					
						
							|  |  |  | 	if (ws->urgent) { | 
					
						
							|  |  |  | 		box_colors = config->colors.urgent_workspace; | 
					
						
							|  |  |  | 	} else if (ws->focused) { | 
					
						
							|  |  |  | 		box_colors = config->colors.focused_workspace; | 
					
						
							|  |  |  | 	} else if (ws->visible) { | 
					
						
							|  |  |  | 		box_colors = config->colors.active_workspace; | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		box_colors = config->colors.inactive_workspace; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = output->height * output->scale; | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 	int text_width, text_height; | 
					
						
							| 
									
										
										
										
											2018-09-08 16:19:31 +10:00
										 |  |  | 	get_text_size(cairo, config->font, &text_width, &text_height, NULL, | 
					
						
							| 
									
										
										
										
											2018-11-17 16:11:28 +00:00
										 |  |  | 			output->scale, config->pango_markup, "%s", ws->label); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	int ws_vertical_padding = WS_VERTICAL_PADDING * output->scale; | 
					
						
							|  |  |  | 	int ws_horizontal_padding = WS_HORIZONTAL_PADDING * output->scale; | 
					
						
							|  |  |  | 	int border_width = BORDER_WIDTH * output->scale; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	uint32_t ideal_height = ws_vertical_padding * 2 + text_height | 
					
						
							|  |  |  | 		+ border_width * 2; | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 	uint32_t ideal_surface_height = ideal_height / output->scale; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	if (output->height < ideal_surface_height) { | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		return ideal_surface_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	uint32_t width = ws_horizontal_padding * 2 + text_width + border_width * 2; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, box_colors.background); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_rectangle(cairo, *x, 0, width, height); | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, box_colors.border); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_rectangle(cairo, *x, 0, width, border_width); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, *x, 0, border_width, height); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, *x + width - border_width, 0, border_width, height); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							|  |  |  | 	cairo_rectangle(cairo, *x, height - border_width, width, border_width); | 
					
						
							|  |  |  | 	cairo_fill(cairo); | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	double text_y = height / 2.0 - text_height / 2.0; | 
					
						
							|  |  |  | 	cairo_set_source_u32(cairo, box_colors.text); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	cairo_move_to(cairo, *x + width / 2 - text_width / 2, (int)floor(text_y)); | 
					
						
							| 
									
										
										
										
											2018-05-09 14:54:22 +10:00
										 |  |  | 	pango_printf(cairo, config->font, output->scale, config->pango_markup, | 
					
						
							| 
									
										
										
										
											2018-11-17 16:11:28 +00:00
										 |  |  | 			"%s", ws->label); | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | 	struct swaybar_hotspot *hotspot = calloc(1, sizeof(struct swaybar_hotspot)); | 
					
						
							|  |  |  | 	hotspot->x = *x; | 
					
						
							|  |  |  | 	hotspot->y = 0; | 
					
						
							|  |  |  | 	hotspot->width = width; | 
					
						
							| 
									
										
										
										
											2018-03-31 14:58:30 -04:00
										 |  |  | 	hotspot->height = height; | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | 	hotspot->callback = workspace_hotspot_callback; | 
					
						
							|  |  |  | 	hotspot->destroy = free; | 
					
						
							| 
									
										
										
										
											2018-04-08 10:04:23 -04:00
										 |  |  | 	hotspot->data = strdup(ws->name); | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | 	wl_list_insert(&output->hotspots, &hotspot->link); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 	*x += width; | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	return output->height; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | static uint32_t render_to_cairo(cairo_t *cairo, struct swaybar_output *output) { | 
					
						
							|  |  |  | 	struct swaybar *bar = output->bar; | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 	struct swaybar_config *config = bar->config; | 
					
						
							| 
									
										
										
										
											2016-10-12 23:44:19 -04:00
										 |  |  | 	cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 	if (output->focused) { | 
					
						
							| 
									
										
										
										
											2016-11-02 18:48:43 +01:00
										 |  |  | 		cairo_set_source_u32(cairo, config->colors.focused_background); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		cairo_set_source_u32(cairo, config->colors.background); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2016-01-23 20:55:01 +01:00
										 |  |  | 	cairo_paint(cairo); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-20 21:12:54 +01:00
										 |  |  | 	int th; | 
					
						
							|  |  |  | 	get_text_size(cairo, config->font, NULL, &th, NULL, output->scale, false, ""); | 
					
						
							|  |  |  | 	uint32_t max_height = (th + WS_VERTICAL_PADDING * 4) / output->scale; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	/*
 | 
					
						
							|  |  |  | 	 * Each render_* function takes the actual height of the bar, and returns | 
					
						
							|  |  |  | 	 * the ideal height. If the actual height is too short, the render function | 
					
						
							|  |  |  | 	 * can do whatever it wants - the buffer won't be committed. If the actual | 
					
						
							|  |  |  | 	 * height is too tall, the render function should adapt its drawing to | 
					
						
							|  |  |  | 	 * utilize the available space. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 	double x = output->width * output->scale; | 
					
						
							|  |  |  | 	if (bar->status) { | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		uint32_t h = render_status_line(cairo, output, &x); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 		max_height = h > max_height ? h : max_height; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	x = 0; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 	if (config->workspace_buttons) { | 
					
						
							|  |  |  | 		struct swaybar_workspace *ws; | 
					
						
							| 
									
										
										
										
											2018-10-25 12:23:48 +01:00
										 |  |  | 		wl_list_for_each(ws, &output->workspaces, link) { | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 			uint32_t h = render_workspace_button(cairo, output, ws, &x); | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 			max_height = h > max_height ? h : max_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-12 20:23:01 +01:00
										 |  |  | 	if (config->binding_mode_indicator) { | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		uint32_t h = render_binding_mode_indicator(cairo, output, x); | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 		max_height = h > max_height ? h : max_height; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-03-29 00:49:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 	return max_height > output->height ? max_height : output->height; | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-28 16:17:15 +01:00
										 |  |  | static void output_frame_handle_done(void *data, struct wl_callback *callback, | 
					
						
							|  |  |  | 		uint32_t time) { | 
					
						
							|  |  |  | 	wl_callback_destroy(callback); | 
					
						
							|  |  |  | 	struct swaybar_output *output = data; | 
					
						
							|  |  |  | 	output->frame_scheduled = false; | 
					
						
							|  |  |  | 	if (output->dirty) { | 
					
						
							|  |  |  | 		render_frame(output); | 
					
						
							|  |  |  | 		output->dirty = false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct wl_callback_listener output_frame_listener = { | 
					
						
							|  |  |  | 	.done = output_frame_handle_done | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void render_frame(struct swaybar_output *output) { | 
					
						
							| 
									
										
										
										
											2018-09-19 11:37:24 +02:00
										 |  |  | 	assert(output->surface != NULL); | 
					
						
							| 
									
										
										
										
											2018-10-12 20:32:48 +01:00
										 |  |  | 	if (!output->layer_surface) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-09-19 11:37:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-12 20:18:04 +01:00
										 |  |  | 	free_hotspots(&output->hotspots); | 
					
						
							| 
									
										
										
										
											2018-03-30 22:42:59 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 	cairo_surface_t *recorder = cairo_recording_surface_create( | 
					
						
							|  |  |  | 			CAIRO_CONTENT_COLOR_ALPHA, NULL); | 
					
						
							|  |  |  | 	cairo_t *cairo = cairo_create(recorder); | 
					
						
							| 
									
										
										
										
											2018-09-20 20:37:08 -07:00
										 |  |  | 	cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | 
					
						
							|  |  |  | 	cairo_font_options_t *fo = cairo_font_options_create(); | 
					
						
							|  |  |  | 	cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); | 
					
						
							|  |  |  | 	cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | 
					
						
							|  |  |  | 	cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(output->subpixel)); | 
					
						
							|  |  |  | 	cairo_set_font_options(cairo, fo); | 
					
						
							|  |  |  | 	cairo_font_options_destroy(fo); | 
					
						
							| 
									
										
										
										
											2018-03-29 15:16:12 -04:00
										 |  |  | 	cairo_save(cairo); | 
					
						
							|  |  |  | 	cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR); | 
					
						
							|  |  |  | 	cairo_paint(cairo); | 
					
						
							|  |  |  | 	cairo_restore(cairo); | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 	uint32_t height = render_to_cairo(cairo, output); | 
					
						
							|  |  |  | 	int config_height = output->bar->config->height; | 
					
						
							|  |  |  | 	if (config_height >= 0 && height < (uint32_t)config_height) { | 
					
						
							|  |  |  | 		height = config_height; | 
					
						
							| 
									
										
										
										
											2018-03-29 12:03:08 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-13 11:56:56 +01:00
										 |  |  | 	if (height != output->height || output->width == 0) { | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		// Reconfigure surface
 | 
					
						
							| 
									
										
										
										
											2018-04-08 13:49:11 -04:00
										 |  |  | 		zwlr_layer_surface_v1_set_size(output->layer_surface, 0, height); | 
					
						
							| 
									
										
										
										
											2018-11-28 11:23:48 -05:00
										 |  |  | 		zwlr_layer_surface_v1_set_margin(output->layer_surface, | 
					
						
							|  |  |  | 				output->bar->config->gaps.top, | 
					
						
							|  |  |  | 				output->bar->config->gaps.right, | 
					
						
							|  |  |  | 				output->bar->config->gaps.bottom, | 
					
						
							|  |  |  | 				output->bar->config->gaps.left); | 
					
						
							| 
									
										
										
										
											2018-10-12 20:32:48 +01:00
										 |  |  | 		if (strcmp(output->bar->config->mode, "dock") == 0) { | 
					
						
							|  |  |  | 			zwlr_layer_surface_v1_set_exclusive_zone(output->layer_surface, height); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		// TODO: this could infinite loop if the compositor assigns us a
 | 
					
						
							|  |  |  | 		// different height than what we asked for
 | 
					
						
							|  |  |  | 		wl_surface_commit(output->surface); | 
					
						
							| 
									
										
										
										
											2018-07-06 11:38:02 -04:00
										 |  |  | 	} else if (height > 0) { | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		// Replay recording into shm and send it off
 | 
					
						
							| 
									
										
										
										
											2018-09-28 14:09:33 +01:00
										 |  |  | 		output->current_buffer = get_next_buffer(output->bar->shm, | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 				output->buffers, | 
					
						
							|  |  |  | 				output->width * output->scale, | 
					
						
							|  |  |  | 				output->height * output->scale); | 
					
						
							| 
									
										
										
										
											2018-07-14 00:01:43 +02:00
										 |  |  | 		if (!output->current_buffer) { | 
					
						
							| 
									
										
										
										
											2018-09-28 16:17:15 +01:00
										 |  |  | 			cairo_surface_destroy(recorder); | 
					
						
							|  |  |  | 			cairo_destroy(cairo); | 
					
						
							| 
									
										
										
										
											2018-07-14 00:01:43 +02:00
										 |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		cairo_t *shm = output->current_buffer->cairo; | 
					
						
							| 
									
										
										
										
											2018-03-29 10:59:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		cairo_save(shm); | 
					
						
							|  |  |  | 		cairo_set_operator(shm, CAIRO_OPERATOR_CLEAR); | 
					
						
							|  |  |  | 		cairo_paint(shm); | 
					
						
							|  |  |  | 		cairo_restore(shm); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		cairo_set_source_surface(shm, recorder, 0.0, 0.0); | 
					
						
							|  |  |  | 		cairo_paint(shm); | 
					
						
							| 
									
										
										
										
											2018-03-29 11:58:54 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 		wl_surface_set_buffer_scale(output->surface, output->scale); | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		wl_surface_attach(output->surface, | 
					
						
							|  |  |  | 				output->current_buffer->buffer, 0, 0); | 
					
						
							| 
									
										
										
										
											2018-04-03 21:06:28 -04:00
										 |  |  | 		wl_surface_damage(output->surface, 0, 0, | 
					
						
							|  |  |  | 				output->width, output->height); | 
					
						
							| 
									
										
										
										
											2018-09-28 16:17:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		struct wl_callback *frame_callback = wl_surface_frame(output->surface); | 
					
						
							|  |  |  | 		wl_callback_add_listener(frame_callback, &output_frame_listener, output); | 
					
						
							|  |  |  | 		output->frame_scheduled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-28 23:04:20 -04:00
										 |  |  | 		wl_surface_commit(output->surface); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cairo_surface_destroy(recorder); | 
					
						
							|  |  |  | 	cairo_destroy(cairo); | 
					
						
							| 
									
										
										
										
											2016-01-24 00:23:09 +01:00
										 |  |  | } |