aboutsummaryrefslogtreecommitdiffstats
path: root/swaybar/main.c
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2015-12-27 11:10:41 -0500
committerLibravatar Drew DeVault <sir@cmpwn.com>2015-12-27 11:10:41 -0500
commit97a4f7ceac99bdac80acbaab2ef22b86efe9453c (patch)
treec96e35749eae72a6ea4cfe336a546bde7fa576c2 /swaybar/main.c
parentUpdate README (diff)
parentswaybar: if-else style fixes (diff)
downloadsway-97a4f7ceac99bdac80acbaab2ef22b86efe9453c.tar.gz
sway-97a4f7ceac99bdac80acbaab2ef22b86efe9453c.tar.zst
sway-97a4f7ceac99bdac80acbaab2ef22b86efe9453c.zip
Merge pull request #409 from mikkeloscar/bar-airblade-features
swaybar: Add support for Airblade i3bar extensions
Diffstat (limited to 'swaybar/main.c')
-rw-r--r--swaybar/main.c316
1 files changed, 240 insertions, 76 deletions
diff --git a/swaybar/main.c b/swaybar/main.c
index 747e03de..49aa08cd 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -54,6 +54,13 @@ struct status_block {
54 char *name, *instance; 54 char *name, *instance;
55 bool separator; 55 bool separator;
56 int separator_block_width; 56 int separator_block_width;
57 // Airblader features
58 uint32_t background;
59 uint32_t border;
60 int border_top;
61 int border_bottom;
62 int border_left;
63 int border_right;
57}; 64};
58 65
59list_t *status_line = NULL; 66list_t *status_line = NULL;
@@ -398,7 +405,185 @@ void bar_ipc_init(int outputi, const char *bar_id) {
398 ipc_update_workspaces(); 405 ipc_update_workspaces();
399} 406}
400 407
408/**
409 * Renders a sharp line of any width and height.
410 *
411 * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0
412 * if the line has a width/height of one pixel, respectively.
413 */
414void render_sharp_line(cairo_t *cairo, uint32_t color, double x, double y, double width, double height) {
415 cairo_set_source_u32(cairo, color);
416
417 if (width > 1 && height > 1) {
418 cairo_rectangle(cairo, x, y, width, height);
419 cairo_fill(cairo);
420 } else {
421 if (width == 1) {
422 x += 0.5;
423 height += y;
424 width = x;
425 }
426
427 if (height == 1) {
428 y += 0.5;
429 width += x;
430 height = y;
431 }
432
433 cairo_move_to(cairo, x, y);
434 cairo_set_line_width(cairo, 1.0);
435 cairo_line_to(cairo, width, height);
436 cairo_stroke(cairo);
437 }
438}
439
440void render_block(struct status_block *block, double *x, bool edge) {
441 int width, height;
442 get_text_size(window, &width, &height, "%s", block->full_text);
443
444 int textwidth = width;
445 double block_width = width;
446
447 if (width < block->min_width) {
448 width = block->min_width;
449 }
450
451 *x -= width;
452
453 if (block->border != 0 && block->border_left > 0) {
454 *x -= (block->border_left + margin);
455 block_width += block->border_left + margin;
456 }
457
458 if (block->border != 0 && block->border_right > 0) {
459 *x -= (block->border_right + margin);
460 block_width += block->border_right + margin;
461 }
462
463 // Add separator
464 if (!edge) {
465 *x -= block->separator_block_width;
466 } else {
467 *x -= margin;
468 }
469
470 double pos = *x;
471
472 // render background
473 if (block->background != 0x0) {
474 cairo_set_source_u32(window->cairo, block->background);
475 cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, window->height - 2);
476 cairo_fill(window->cairo);
477 }
478
479 // render top border
480 if (block->border != 0 && block->border_top > 0) {
481 render_sharp_line(window->cairo, block->border,
482 pos - 0.5,
483 1,
484 block_width,
485 block->border_top);
486 }
487
488 // render bottom border
489 if (block->border != 0 && block->border_bottom > 0) {
490 render_sharp_line(window->cairo, block->border,
491 pos - 0.5,
492 window->height - 1 - block->border_bottom,
493 block_width,
494 block->border_bottom);
495 }
496
497 // render left border
498 if (block->border != 0 && block->border_left > 0) {
499 render_sharp_line(window->cairo, block->border,
500 pos - 0.5,
501 1,
502 block->border_left,
503 window->height - 2);
504
505 pos += block->border_left + margin;
506 }
507
508 // render text
509 double offset = 0;
510
511 if (strncmp(block->align, "left", 5) == 0) {
512 offset = pos;
513 } else if (strncmp(block->align, "right", 5) == 0) {
514 offset = pos + width - textwidth;
515 } else if (strncmp(block->align, "center", 6) == 0) {
516 offset = pos + (width - textwidth) / 2;
517 }
518
519 cairo_move_to(window->cairo, offset, margin);
520 cairo_set_source_u32(window->cairo, block->color);
521 pango_printf(window, "%s", block->full_text);
522
523 pos += width;
524
525 // render right border
526 if (block->border != 0 && block->border_right > 0) {
527 pos += margin;
528
529 render_sharp_line(window->cairo, block->border,
530 pos - 0.5,
531 1,
532 block->border_right,
533 window->height - 2);
534
535 pos += block->border_right;
536 }
537
538 // render separator
539 // TODO: Handle custom separator
540 if (!edge && block->separator) {
541 cairo_set_source_u32(window->cairo, colors.separator);
542 cairo_set_line_width(window->cairo, 1);
543 cairo_move_to(window->cairo, pos + block->separator_block_width/2, margin);
544 cairo_line_to(window->cairo, pos + block->separator_block_width/2, window->height - margin);
545 cairo_stroke(window->cairo);
546 }
547
548}
549
550void render_workspace_button(struct workspace *ws, double *x) {
551 int width, height;
552 get_text_size(window, &width, &height, "%s", ws->name);
553 struct box_colors box_colors;
554 if (ws->urgent) {
555 box_colors = colors.urgent_workspace;
556 } else if (ws->focused) {
557 box_colors = colors.focused_workspace;
558 } else if (ws->visible) {
559 box_colors = colors.active_workspace;
560 } else {
561 box_colors = colors.inactive_workspace;
562 }
563
564 // background
565 cairo_set_source_u32(window->cairo, box_colors.background);
566 cairo_rectangle(window->cairo, *x, 1.5, width + ws_hor_padding * 2 - 1,
567 height + ws_ver_padding * 2);
568 cairo_fill(window->cairo);
569
570 // border
571 cairo_set_source_u32(window->cairo, box_colors.border);
572 cairo_rectangle(window->cairo, *x, 1.5, width + ws_hor_padding * 2 - 1,
573 height + ws_ver_padding * 2);
574 cairo_stroke(window->cairo);
575
576 // text
577 cairo_set_source_u32(window->cairo, box_colors.text);
578 cairo_move_to(window->cairo, (int)*x + ws_hor_padding, margin);
579 pango_printf(window, "%s", ws->name);
580
581 *x += width + ws_hor_padding * 2 + ws_spacing;
582}
583
401void render() { 584void render() {
585 int i;
586
402 // Clear 587 // Clear
403 cairo_save(window->cairo); 588 cairo_save(window->cairo);
404 cairo_set_operator(window->cairo, CAIRO_OPERATOR_CLEAR); 589 cairo_set_operator(window->cairo, CAIRO_OPERATOR_CLEAR);
@@ -418,49 +603,13 @@ void render() {
418 cairo_move_to(window->cairo, window->width - margin - width, margin); 603 cairo_move_to(window->cairo, window->width - margin - width, margin);
419 pango_printf(window, "%s", line); 604 pango_printf(window, "%s", line);
420 } else if (protocol == I3BAR && status_line) { 605 } else if (protocol == I3BAR && status_line) {
421 int i, blockpos; 606 double pos = window->width - 0.5;
422 int moved = 0; 607 bool edge = true;
423 bool corner = true;
424 for (i = status_line->length - 1; i >= 0; --i) { 608 for (i = status_line->length - 1; i >= 0; --i) {
425 struct status_block *block = status_line->items[i]; 609 struct status_block *block = status_line->items[i];
426 if (block->full_text && block->full_text[0]) { 610 if (block->full_text && block->full_text[0]) {
427 get_text_size(window, &width, &height, "%s", block->full_text); 611 render_block(block, &pos, edge);
428 612 edge = false;
429 int textwidth = width;
430
431 if (width < block->min_width) {
432 width = block->min_width;
433 }
434
435 moved += width + block->separator_block_width;
436 blockpos = window->width - margin - moved;
437
438 int offset = 0;
439
440 if (strncmp(block->align, "left", 5) == 0) {
441 offset = blockpos;
442 }
443 else if (strncmp(block->align, "right", 5) == 0) {
444 offset = blockpos + width - textwidth;
445 }
446 else if (strncmp(block->align, "center", 6) == 0) {
447 offset = blockpos + (width - textwidth) / 2;
448 }
449
450 cairo_move_to(window->cairo, offset, margin);
451 cairo_set_source_u32(window->cairo, block->color);
452 pango_printf(window, "%s", block->full_text);
453 if (corner) {
454 corner = false;
455 } else if (block->separator) {
456 cairo_set_source_u32(window->cairo, colors.separator);
457 cairo_set_line_width(window->cairo, 1);
458 cairo_move_to(window->cairo, blockpos + width
459 + block->separator_block_width/2, margin);
460 cairo_line_to(window->cairo, blockpos + width
461 + block->separator_block_width/2, window->height - margin);
462 cairo_stroke(window->cairo);
463 }
464 } 613 }
465 } 614 }
466 } 615 }
@@ -468,34 +617,9 @@ void render() {
468 // Workspaces 617 // Workspaces
469 cairo_set_line_width(window->cairo, 1.0); 618 cairo_set_line_width(window->cairo, 1.0);
470 double x = 0.5; 619 double x = 0.5;
471 int i;
472 for (i = 0; i < workspaces->length; ++i) { 620 for (i = 0; i < workspaces->length; ++i) {
473 struct workspace *ws = workspaces->items[i]; 621 struct workspace *ws = workspaces->items[i];
474 get_text_size(window, &width, &height, "%s", ws->name); 622 render_workspace_button(ws, &x);
475 struct box_colors box_colors;
476 if (ws->urgent) {
477 box_colors = colors.urgent_workspace;
478 } else if (ws->focused) {
479 box_colors = colors.focused_workspace;
480 } else if (ws->visible) {
481 box_colors = colors.active_workspace;
482 } else {
483 box_colors = colors.inactive_workspace;
484 }
485
486 cairo_set_source_u32(window->cairo, box_colors.background);
487 cairo_rectangle(window->cairo, x, 1.5, width + ws_hor_padding * 2 - 1, height + ws_ver_padding * 2);
488 cairo_fill(window->cairo);
489
490 cairo_set_source_u32(window->cairo, box_colors.border);
491 cairo_rectangle(window->cairo, x, 1.5, width + ws_hor_padding * 2 - 1, height + ws_ver_padding * 2);
492 cairo_stroke(window->cairo);
493
494 cairo_set_source_u32(window->cairo, box_colors.text);
495 cairo_move_to(window->cairo, (int)x + ws_hor_padding, margin);
496 pango_printf(window, "%s", ws->name);
497
498 x += width + ws_hor_padding * 2 + ws_spacing;
499 } 623 }
500} 624}
501 625
@@ -544,6 +668,8 @@ void parse_json(const char *text) {
544 for (i = 0; i < json_object_array_length(results); ++i) { 668 for (i = 0; i < json_object_array_length(results); ++i) {
545 json_object *full_text, *short_text, *color, *min_width, *align, *urgent; 669 json_object *full_text, *short_text, *color, *min_width, *align, *urgent;
546 json_object *name, *instance, *separator, *separator_block_width; 670 json_object *name, *instance, *separator, *separator_block_width;
671 json_object *background, *border, *border_top, *border_bottom;
672 json_object *border_left, *border_right;
547 673
548 json_object *json = json_object_array_get_idx(results, i); 674 json_object *json = json_object_array_get_idx(results, i);
549 if (!json) { 675 if (!json) {
@@ -560,6 +686,12 @@ void parse_json(const char *text) {
560 json_object_object_get_ex(json, "instance", &instance); 686 json_object_object_get_ex(json, "instance", &instance);
561 json_object_object_get_ex(json, "separator", &separator); 687 json_object_object_get_ex(json, "separator", &separator);
562 json_object_object_get_ex(json, "separator_block_width", &separator_block_width); 688 json_object_object_get_ex(json, "separator_block_width", &separator_block_width);
689 json_object_object_get_ex(json, "background", &background);
690 json_object_object_get_ex(json, "border", &border);
691 json_object_object_get_ex(json, "border_top", &border_top);
692 json_object_object_get_ex(json, "border_bottom", &border_bottom);
693 json_object_object_get_ex(json, "border_left", &border_left);
694 json_object_object_get_ex(json, "border_right", &border_right);
563 695
564 struct status_block *new = malloc(sizeof(struct status_block)); 696 struct status_block *new = malloc(sizeof(struct status_block));
565 memset(new, 0, sizeof(struct status_block)); 697 memset(new, 0, sizeof(struct status_block));
@@ -574,8 +706,7 @@ void parse_json(const char *text) {
574 706
575 if (color) { 707 if (color) {
576 new->color = parse_color(json_object_get_string(color)); 708 new->color = parse_color(json_object_get_string(color));
577 } 709 } else {
578 else {
579 new->color = colors.statusline; 710 new->color = colors.statusline;
580 } 711 }
581 712
@@ -583,8 +714,7 @@ void parse_json(const char *text) {
583 json_type type = json_object_get_type(min_width); 714 json_type type = json_object_get_type(min_width);
584 if (type == json_type_int) { 715 if (type == json_type_int) {
585 new->min_width = json_object_get_int(min_width); 716 new->min_width = json_object_get_int(min_width);
586 } 717 } else if (type == json_type_string) {
587 else if (type == json_type_string) {
588 int width, height; 718 int width, height;
589 get_text_size(window, &width, &height, "%s", json_object_get_string(min_width)); 719 get_text_size(window, &width, &height, "%s", json_object_get_string(min_width));
590 new->min_width = width; 720 new->min_width = width;
@@ -593,8 +723,7 @@ void parse_json(const char *text) {
593 723
594 if (align) { 724 if (align) {
595 new->align = strdup(json_object_get_string(align)); 725 new->align = strdup(json_object_get_string(align));
596 } 726 } else {
597 else {
598 new->align = strdup("left"); 727 new->align = strdup("left");
599 } 728 }
600 729
@@ -612,18 +741,53 @@ void parse_json(const char *text) {
612 741
613 if (separator) { 742 if (separator) {
614 new->separator = json_object_get_int(separator); 743 new->separator = json_object_get_int(separator);
615 } 744 } else {
616 else {
617 new->separator = true; // i3bar spec 745 new->separator = true; // i3bar spec
618 } 746 }
619 747
620 if (separator_block_width) { 748 if (separator_block_width) {
621 new->separator_block_width = json_object_get_int(separator_block_width); 749 new->separator_block_width = json_object_get_int(separator_block_width);
622 } 750 } else {
623 else {
624 new->separator_block_width = 9; // i3bar spec 751 new->separator_block_width = 9; // i3bar spec
625 } 752 }
626 753
754 // Airblader features
755 if (background) {
756 new->background = parse_color(json_object_get_string(background));
757 } else {
758 new->background = 0x0; // transparent
759 }
760
761 if (border) {
762 new->border = parse_color(json_object_get_string(border));
763 } else {
764 new->border = 0x0; // transparent
765 }
766
767 if (border_top) {
768 new->border_top = json_object_get_int(border_top);
769 } else {
770 new->border_top = 1;
771 }
772
773 if (border_bottom) {
774 new->border_bottom = json_object_get_int(border_bottom);
775 } else {
776 new->border_bottom = 1;
777 }
778
779 if (border_left) {
780 new->border_left = json_object_get_int(border_left);
781 } else {
782 new->border_left = 1;
783 }
784
785 if (border_right) {
786 new->border_right = json_object_get_int(border_right);
787 } else {
788 new->border_right = 1;
789 }
790
627 list_add(status_line, new); 791 list_add(status_line, new);
628 } 792 }
629 793