mirror of
				https://github.com/kolunmi/dwlb.git
				synced 2025-10-31 04:04:13 +00:00 
			
		
		
		
	allow color commands in status text
This commit is contained in:
		
							parent
							
								
									352c66ed10
								
							
						
					
					
						commit
						f1b1429015
					
				
							
								
								
									
										163
									
								
								dwlb.c
									
									
									
									
									
								
							
							
						
						
									
										163
									
								
								dwlb.c
									
									
									
									
									
								
							| @ -150,6 +150,73 @@ allocate_shm_file(size_t size) | |||||||
| 	return fd; | 	return fd; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | /* Color parsing logic adapted from [sway] */ | ||||||
|  | static int | ||||||
|  | parse_color(const char *str, pixman_color_t *clr) | ||||||
|  | { | ||||||
|  | 	if (*str == '#') | ||||||
|  | 		str++; | ||||||
|  | 	int len = strlen(str); | ||||||
|  | 
 | ||||||
|  | 	// Disallows "0x" prefix that strtoul would ignore
 | ||||||
|  | 	if ((len != 6 && len != 8) || !isxdigit(str[0]) || !isxdigit(str[1])) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	char *ptr; | ||||||
|  | 	uint32_t parsed = strtoul(str, &ptr, 16); | ||||||
|  | 	if (*ptr) | ||||||
|  | 		return -1; | ||||||
|  | 
 | ||||||
|  | 	if (len == 8) { | ||||||
|  | 		clr->alpha = (parsed & 0xff) * 0x101; | ||||||
|  | 		parsed >>= 8; | ||||||
|  | 	} else { | ||||||
|  | 		clr->alpha = 0xffff; | ||||||
|  | 	} | ||||||
|  | 	clr->red =   ((parsed >> 16) & 0xff) * 0x101; | ||||||
|  | 	clr->green = ((parsed >>  8) & 0xff) * 0x101; | ||||||
|  | 	clr->blue =  ((parsed >>  0) & 0xff) * 0x101; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static char * | ||||||
|  | handle_cmd(char *cmd, pixman_color_t *fg, pixman_color_t *bg, | ||||||
|  | 	   pixman_color_t *def_fg, pixman_color_t *def_bg) | ||||||
|  | { | ||||||
|  | 	char *arg, *end; | ||||||
|  | 
 | ||||||
|  | 	if (!(arg = strchr(cmd, '(')) || !(end = strchr(arg + 1, ')'))) | ||||||
|  | 		return cmd; | ||||||
|  | 
 | ||||||
|  | 	*arg++ = '\0'; | ||||||
|  | 	*end = '\0'; | ||||||
|  | 
 | ||||||
|  | 	if (!strcmp(cmd, "bg")) { | ||||||
|  | 		if (bg && def_bg) { | ||||||
|  | 			if (!*arg) { | ||||||
|  | 				*bg = *def_bg; | ||||||
|  | 			} else if (parse_color(arg, bg)) { | ||||||
|  | 				fprintf(stderr, "Bad color string \"%s\"\n", arg); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if (!strcmp(cmd, "fg")) { | ||||||
|  | 		if (fg && def_fg) { | ||||||
|  | 			if (!*arg) { | ||||||
|  | 				*fg = *def_fg; | ||||||
|  | 			} else if (parse_color(arg, fg)) { | ||||||
|  | 				fprintf(stderr, "Bad color string \"%s\"\n", arg); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		fprintf(stderr, "Unrecognized command \"%s\"\n", cmd); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* Restore string for later redraws */ | ||||||
|  | 	*--arg = '('; | ||||||
|  | 	*end = ')'; | ||||||
|  | 	return end; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static uint32_t | static uint32_t | ||||||
| draw_text(char *text, | draw_text(char *text, | ||||||
| 	  uint32_t xpos, | 	  uint32_t xpos, | ||||||
| @ -158,26 +225,51 @@ draw_text(char *text, | |||||||
| 	  pixman_image_t *background, | 	  pixman_image_t *background, | ||||||
| 	  pixman_color_t *fgcolor, | 	  pixman_color_t *fgcolor, | ||||||
| 	  pixman_color_t *bgcolor, | 	  pixman_color_t *bgcolor, | ||||||
| 	  uint32_t max_x, | 	  uint32_t surface_width, | ||||||
| 	  uint32_t height, | 	  uint32_t height, | ||||||
| 	  uint32_t padding) | 	  uint32_t padding, | ||||||
|  | 	  bool commands) | ||||||
| { | { | ||||||
| 	uint32_t codepoint; | 	uint32_t codepoint; | ||||||
| 	uint32_t state = UTF8_ACCEPT; | 	uint32_t state = UTF8_ACCEPT; | ||||||
| 	uint32_t ixpos = xpos; | 	uint32_t ixpos = xpos; | ||||||
| 	uint32_t nxpos; | 	uint32_t nxpos; | ||||||
| 	uint32_t lastcp = 0; | 	uint32_t lastcp = 0; | ||||||
| 	pixman_image_t *fgfill = pixman_image_create_solid_fill(fgcolor); |  | ||||||
| 
 | 
 | ||||||
| 	if (!*text) | 	if (!*text || !surface_width || xpos >= surface_width) | ||||||
| 		return xpos; | 		return xpos; | ||||||
| 	 | 	 | ||||||
| 	if ((nxpos = xpos + padding) > max_x) | 	if ((nxpos = xpos + padding) >= surface_width) | ||||||
| 		return xpos; | 		return xpos; | ||||||
| 	 |  | ||||||
| 	xpos = nxpos; | 	xpos = nxpos; | ||||||
| 	 | 	 | ||||||
|  | 	pixman_color_t cur_fgcolor = *fgcolor; | ||||||
|  | 	pixman_color_t cur_bgcolor; | ||||||
|  | 	if (background && bgcolor) { | ||||||
|  | 		cur_bgcolor = *bgcolor; | ||||||
|  | 		pixman_image_fill_boxes(PIXMAN_OP_OVER, background, | ||||||
|  | 					&cur_bgcolor, 1, &(pixman_box32_t){ | ||||||
|  | 						.x1 = ixpos, | ||||||
|  | 						.x2 = xpos, | ||||||
|  | 						.y1 = 0, | ||||||
|  | 						.y2 = height | ||||||
|  | 					}); | ||||||
|  | 	} | ||||||
|  | 	 | ||||||
|  | 	pixman_image_t *fgfill = pixman_image_create_solid_fill(fgcolor); | ||||||
|  | 
 | ||||||
| 	for (char *p = text; *p; p++) { | 	for (char *p = text; *p; p++) { | ||||||
|  | 		/* Check for inline ^ commands */ | ||||||
|  | 		if (commands && state == UTF8_ACCEPT && *p == '^') { | ||||||
|  | 			p++; | ||||||
|  | 			if (*p != '^') { | ||||||
|  | 				p = handle_cmd(p, &cur_fgcolor, &cur_bgcolor, fgcolor, bgcolor); | ||||||
|  | 				pixman_image_unref(fgfill); | ||||||
|  | 				fgfill = pixman_image_create_solid_fill(&cur_fgcolor); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		/* Returns nonzero if more bytes are needed */ | 		/* Returns nonzero if more bytes are needed */ | ||||||
| 		if (utf8decode(&state, &codepoint, *p)) | 		if (utf8decode(&state, &codepoint, *p)) | ||||||
| 			continue; | 			continue; | ||||||
| @ -192,13 +284,11 @@ draw_text(char *text, | |||||||
| 		long x_kern = 0; | 		long x_kern = 0; | ||||||
| 		if (lastcp) | 		if (lastcp) | ||||||
| 			fcft_kerning(font, lastcp, codepoint, &x_kern, NULL); | 			fcft_kerning(font, lastcp, codepoint, &x_kern, NULL); | ||||||
| 
 | 		if ((nxpos = xpos + x_kern + glyph->advance.x) >= surface_width) { | ||||||
| 		if ((nxpos = xpos + x_kern + glyph->advance.x) > max_x) { |  | ||||||
| 			if (!lastcp) | 			if (!lastcp) | ||||||
| 				return ixpos; | 				return ixpos; | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		 |  | ||||||
| 		xpos += x_kern; | 		xpos += x_kern; | ||||||
| 		lastcp = codepoint; | 		lastcp = codepoint; | ||||||
| 
 | 
 | ||||||
| @ -219,6 +309,15 @@ draw_text(char *text, | |||||||
| 				xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height); | 				xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		if (background && bgcolor) | ||||||
|  | 			pixman_image_fill_boxes(PIXMAN_OP_OVER, background, | ||||||
|  | 						&cur_bgcolor, 1, &(pixman_box32_t){ | ||||||
|  | 							.x1 = xpos, | ||||||
|  | 							.x2 = nxpos, | ||||||
|  | 							.y1 = 0, | ||||||
|  | 							.y2 = height | ||||||
|  | 						}); | ||||||
|  | 		 | ||||||
| 		/* increment pen position */ | 		/* increment pen position */ | ||||||
| 		xpos = nxpos; | 		xpos = nxpos; | ||||||
| 		ypos += glyph->advance.y; | 		ypos += glyph->advance.y; | ||||||
| @ -227,16 +326,17 @@ draw_text(char *text, | |||||||
| 	if (state != UTF8_ACCEPT) | 	if (state != UTF8_ACCEPT) | ||||||
| 		fprintf(stderr, "malformed UTF-8 sequence\n"); | 		fprintf(stderr, "malformed UTF-8 sequence\n"); | ||||||
| 
 | 
 | ||||||
| 	xpos = MIN(xpos + padding, max_x); | 	nxpos = MIN(xpos + padding, surface_width - 1); | ||||||
| 
 | 
 | ||||||
| 	if (background && bgcolor) | 	if (background && bgcolor) | ||||||
| 		pixman_image_fill_boxes(PIXMAN_OP_OVER, background, | 		pixman_image_fill_boxes(PIXMAN_OP_OVER, background, | ||||||
| 					bgcolor, 1, &(pixman_box32_t){ | 					bgcolor, 1, &(pixman_box32_t){ | ||||||
| 						.x1 = ixpos, | 						.x1 = xpos, | ||||||
| 						.x2 = xpos, | 						.x2 = nxpos, | ||||||
| 						.y1 = 0, | 						.y1 = 0, | ||||||
| 						.y2 = height | 						.y2 = height | ||||||
| 					}); | 					}); | ||||||
|  | 	xpos = nxpos; | ||||||
| 	 | 	 | ||||||
| 	pixman_image_unref(fgfill); | 	pixman_image_unref(fgfill); | ||||||
| 
 | 
 | ||||||
| @ -304,21 +404,21 @@ draw_frame(Bar *b) | |||||||
| 		 | 		 | ||||||
| 		if (urgent) | 		if (urgent) | ||||||
| 			xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, | 			xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, | ||||||
| 					      &urgtextcolor, &urgbgcolor, b->width, b->height, b->textpadding); | 					      &urgtextcolor, &urgbgcolor, b->width, b->height, b->textpadding, false); | ||||||
| 		else | 		else | ||||||
| 			xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, | 			xpos_left = draw_text(tags[i], xpos_left, ypos, foreground_left, background_left, | ||||||
| 					      &textcolor, active ? &activecolor : &inactivecolor, b->width, b->height, b->textpadding); | 					      &textcolor, active ? &activecolor : &inactivecolor, b->width, b->height, b->textpadding, false); | ||||||
| 	} | 	} | ||||||
| 	xpos_left = draw_text(b->layout, xpos_left, ypos, foreground_left, background_left, | 	xpos_left = draw_text(b->layout, xpos_left, ypos, foreground_left, background_left, | ||||||
| 			      &textcolor, &inactivecolor, b->width, b->height, b->textpadding); | 			      &textcolor, &inactivecolor, b->width, b->height, b->textpadding, false); | ||||||
| 
 | 
 | ||||||
| 	xpos_right = draw_text(b->status, 0, ypos, foreground_right, background_right, | 	xpos_right = draw_text(b->status, 0, ypos, foreground_right, background_right, | ||||||
| 			       &textcolor, &inactivecolor, b->width, b->height, b->textpadding); | 			       &textcolor, &inactivecolor, b->width, b->height, b->textpadding, true); | ||||||
| 	if (xpos_right > b->width) | 	if (xpos_right > b->width) | ||||||
| 		xpos_right = b->width; | 		xpos_right = b->width; | ||||||
| 	 | 	 | ||||||
| 	draw_text(b->title, 0, ypos, foreground_title, NULL, | 	draw_text(b->title, 0, ypos, foreground_title, NULL, | ||||||
| 		  &textcolor, NULL, b->width, b->height, b->textpadding); | 		  &textcolor, NULL, b->width, b->height, b->textpadding, false); | ||||||
| 
 | 
 | ||||||
| 	/* Draw background and foreground on bar */ | 	/* Draw background and foreground on bar */ | ||||||
| 	pixman_image_composite32(PIXMAN_OP_OVER, foreground_title, NULL, bar, 0, 0, 0, 0, xpos_left, 0, b->width, b->height); | 	pixman_image_composite32(PIXMAN_OP_OVER, foreground_title, NULL, bar, 0, 0, 0, 0, xpos_left, 0, b->width, b->height); | ||||||
| @ -722,35 +822,6 @@ client_send_command(struct sockaddr_un *sock_address, | |||||||
| 	closedir(dir); | 	closedir(dir); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Color parsing logic adapted from [sway] */ |  | ||||||
| static int |  | ||||||
| parse_color(const char *str, pixman_color_t *clr) |  | ||||||
| { |  | ||||||
| 	if (*str == '#') |  | ||||||
| 		str++; |  | ||||||
| 	int len = strlen(str); |  | ||||||
| 
 |  | ||||||
| 	// Disallows "0x" prefix that strtoul would ignore
 |  | ||||||
| 	if ((len != 6 && len != 8) || !isxdigit(str[0]) || !isxdigit(str[1])) |  | ||||||
| 		return -1; |  | ||||||
| 
 |  | ||||||
| 	char *ptr; |  | ||||||
| 	uint32_t parsed = strtoul(str, &ptr, 16); |  | ||||||
| 	if (*ptr) |  | ||||||
| 		return -1; |  | ||||||
| 
 |  | ||||||
| 	if (len == 8) { |  | ||||||
| 		clr->alpha = (parsed & 0xff) * 0x101; |  | ||||||
| 		parsed >>= 8; |  | ||||||
| 	} else { |  | ||||||
| 		clr->alpha = 0xffff; |  | ||||||
| 	} |  | ||||||
| 	clr->red =   ((parsed >> 16) & 0xff) * 0x101; |  | ||||||
| 	clr->green = ((parsed >>  8) & 0xff) * 0x101; |  | ||||||
| 	clr->blue =  ((parsed >>  0) & 0xff) * 0x101; |  | ||||||
| 	return 0; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void | void | ||||||
| sig_handler(int sig) | sig_handler(int sig) | ||||||
| { | { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 kolunmi
						kolunmi