aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--swaybar/main.c301
1 files changed, 235 insertions, 66 deletions
diff --git a/swaybar/main.c b/swaybar/main.c
index 434d7363..c9fc7de7 100644
--- a/swaybar/main.c
+++ b/swaybar/main.c
@@ -54,6 +54,13 @@ struct status_block {
char *name, *instance;
bool separator;
int separator_block_width;
+ // Airblader features
+ uint32_t background;
+ uint32_t border;
+ int border_top;
+ int border_bottom;
+ int border_left;
+ int border_right;
};
list_t *status_line = NULL;
@@ -397,7 +404,185 @@ void bar_ipc_init(int outputi, const char *bar_id) {
ipc_update_workspaces();
}
+/**
+ * Renders a sharp line of any width and height.
+ *
+ * The line is drawn from (x,y) to (x+width,y+height) where width/height is 0
+ * if the line has a width/height of one pixel, respectively.
+ */
+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);
+ }
+}
+
+void render_block(struct status_block *block, double *x, bool edge) {
+ int width, height;
+ get_text_size(window, &width, &height, "%s", block->full_text);
+
+ int textwidth = width;
+ double block_width = width;
+
+ if (width < block->min_width) {
+ width = block->min_width;
+ }
+
+ *x -= width;
+
+ if (block->border != 0 && block->border_left > 0) {
+ *x -= (block->border_left + margin);
+ block_width += block->border_left + margin;
+ }
+
+ if (block->border != 0 && block->border_right > 0) {
+ *x -= (block->border_right + margin);
+ block_width += block->border_right + margin;
+ }
+
+ // Add separator
+ if (!edge) {
+ *x -= block->separator_block_width;
+ } else {
+ *x -= margin;
+ }
+
+ double pos = *x;
+
+ // render background
+ if (block->background != 0x0) {
+ cairo_set_source_u32(window->cairo, block->background);
+ cairo_rectangle(window->cairo, pos - 0.5, 1, block_width, window->height - 2);
+ cairo_fill(window->cairo);
+ }
+
+ // render top border
+ if (block->border != 0 && block->border_top > 0) {
+ render_sharp_line(window->cairo, block->border,
+ pos - 0.5,
+ 1,
+ block_width,
+ block->border_top);
+ }
+
+ // render bottom border
+ if (block->border != 0 && block->border_bottom > 0) {
+ render_sharp_line(window->cairo, block->border,
+ pos - 0.5,
+ window->height - 1 - block->border_bottom,
+ block_width,
+ block->border_bottom);
+ }
+
+ // render left border
+ if (block->border != 0 && block->border_left > 0) {
+ render_sharp_line(window->cairo, block->border,
+ pos - 0.5,
+ 1,
+ block->border_left,
+ window->height - 2);
+
+ pos += block->border_left + margin;
+ }
+
+ // render text
+ double offset = 0;
+
+ if (strncmp(block->align, "left", 5) == 0) {
+ offset = pos;
+ } else if (strncmp(block->align, "right", 5) == 0) {
+ offset = pos + width - textwidth;
+ } else if (strncmp(block->align, "center", 6) == 0) {
+ offset = pos + (width - textwidth) / 2;
+ }
+
+ cairo_move_to(window->cairo, offset, margin);
+ cairo_set_source_u32(window->cairo, block->color);
+ pango_printf(window, "%s", block->full_text);
+
+ pos += width;
+
+ // render right border
+ if (block->border != 0 && block->border_right > 0) {
+ pos += margin;
+
+ render_sharp_line(window->cairo, block->border,
+ pos - 0.5,
+ 1,
+ block->border_right,
+ window->height - 2);
+
+ pos += block->border_right;
+ }
+
+ // render separator
+ // TODO: Handle custom separator
+ if (!edge && block->separator) {
+ cairo_set_source_u32(window->cairo, colors.separator);
+ cairo_set_line_width(window->cairo, 1);
+ cairo_move_to(window->cairo, pos + block->separator_block_width/2, margin);
+ cairo_line_to(window->cairo, pos + block->separator_block_width/2, window->height - margin);
+ cairo_stroke(window->cairo);
+ }
+
+}
+
+void render_workspace_button(struct workspace *ws, double *x) {
+ int width, height;
+ get_text_size(window, &width, &height, "%s", ws->name);
+ struct box_colors box_colors;
+ if (ws->urgent) {
+ box_colors = colors.urgent_workspace;
+ } else if (ws->focused) {
+ box_colors = colors.focused_workspace;
+ } else if (ws->visible) {
+ box_colors = colors.active_workspace;
+ } else {
+ box_colors = colors.inactive_workspace;
+ }
+
+ // background
+ cairo_set_source_u32(window->cairo, box_colors.background);
+ cairo_rectangle(window->cairo, *x, 1.5, width + ws_hor_padding * 2 - 1,
+ height + ws_ver_padding * 2);
+ cairo_fill(window->cairo);
+
+ // border
+ cairo_set_source_u32(window->cairo, box_colors.border);
+ cairo_rectangle(window->cairo, *x, 1.5, width + ws_hor_padding * 2 - 1,
+ height + ws_ver_padding * 2);
+ cairo_stroke(window->cairo);
+
+ // text
+ cairo_set_source_u32(window->cairo, box_colors.text);
+ cairo_move_to(window->cairo, (int)*x + ws_hor_padding, margin);
+ pango_printf(window, "%s", ws->name);
+
+ *x += width + ws_hor_padding * 2 + ws_spacing;
+}
+
void render() {
+ int i;
+
// Clear
cairo_save(window->cairo);
cairo_set_operator(window->cairo, CAIRO_OPERATOR_CLEAR);
@@ -417,49 +602,13 @@ void render() {
cairo_move_to(window->cairo, window->width - margin - width, margin);
pango_printf(window, "%s", line);
} else if (protocol == I3BAR && status_line) {
- int i, blockpos;
- int moved = 0;
- bool corner = true;
+ double pos = window->width - 0.5;
+ bool edge = true;
for (i = status_line->length - 1; i >= 0; --i) {
struct status_block *block = status_line->items[i];
if (block->full_text && block->full_text[0]) {
- get_text_size(window, &width, &height, "%s", block->full_text);
-
- int textwidth = width;
-
- if (width < block->min_width) {
- width = block->min_width;
- }
-
- moved += width + block->separator_block_width;
- blockpos = window->width - margin - moved;
-
- int offset = 0;
-
- if (strncmp(block->align, "left", 5) == 0) {
- offset = blockpos;
- }
- else if (strncmp(block->align, "right", 5) == 0) {
- offset = blockpos + width - textwidth;
- }
- else if (strncmp(block->align, "center", 6) == 0) {
- offset = blockpos + (width - textwidth) / 2;
- }
-
- cairo_move_to(window->cairo, offset, margin);
- cairo_set_source_u32(window->cairo, block->color);
- pango_printf(window, "%s", block->full_text);
- if (corner) {
- corner = false;
- } else if (block->separator) {
- cairo_set_source_u32(window->cairo, colors.separator);
- cairo_set_line_width(window->cairo, 1);
- cairo_move_to(window->cairo, blockpos + width
- + block->separator_block_width/2, margin);
- cairo_line_to(window->cairo, blockpos + width
- + block->separator_block_width/2, window->height - margin);
- cairo_stroke(window->cairo);
- }
+ render_block(block, &pos, edge);
+ edge = false;
}
}
}
@@ -467,34 +616,9 @@ void render() {
// Workspaces
cairo_set_line_width(window->cairo, 1.0);
double x = 0.5;
- int i;
for (i = 0; i < workspaces->length; ++i) {
struct workspace *ws = workspaces->items[i];
- get_text_size(window, &width, &height, "%s", ws->name);
- struct box_colors box_colors;
- if (ws->urgent) {
- box_colors = colors.urgent_workspace;
- } else if (ws->focused) {
- box_colors = colors.focused_workspace;
- } else if (ws->visible) {
- box_colors = colors.active_workspace;
- } else {
- box_colors = colors.inactive_workspace;
- }
-
- cairo_set_source_u32(window->cairo, box_colors.background);
- cairo_rectangle(window->cairo, x, 1.5, width + ws_hor_padding * 2 - 1, height + ws_ver_padding * 2);
- cairo_fill(window->cairo);
-
- cairo_set_source_u32(window->cairo, box_colors.border);
- cairo_rectangle(window->cairo, x, 1.5, width + ws_hor_padding * 2 - 1, height + ws_ver_padding * 2);
- cairo_stroke(window->cairo);
-
- cairo_set_source_u32(window->cairo, box_colors.text);
- cairo_move_to(window->cairo, (int)x + ws_hor_padding, margin);
- pango_printf(window, "%s", ws->name);
-
- x += width + ws_hor_padding * 2 + ws_spacing;
+ render_workspace_button(ws, &x);
}
}
@@ -543,6 +667,8 @@ void parse_json(const char *text) {
for (i = 0; i < json_object_array_length(results); ++i) {
json_object *full_text, *short_text, *color, *min_width, *align, *urgent;
json_object *name, *instance, *separator, *separator_block_width;
+ json_object *background, *border, *border_top, *border_bottom;
+ json_object *border_left, *border_right;
json_object *json = json_object_array_get_idx(results, i);
if (!json) {
@@ -559,6 +685,12 @@ void parse_json(const char *text) {
json_object_object_get_ex(json, "instance", &instance);
json_object_object_get_ex(json, "separator", &separator);
json_object_object_get_ex(json, "separator_block_width", &separator_block_width);
+ json_object_object_get_ex(json, "background", &background);
+ json_object_object_get_ex(json, "border", &border);
+ json_object_object_get_ex(json, "border_top", &border_top);
+ json_object_object_get_ex(json, "border_bottom", &border_bottom);
+ json_object_object_get_ex(json, "border_left", &border_left);
+ json_object_object_get_ex(json, "border_right", &border_right);
struct status_block *new = malloc(sizeof(struct status_block));
memset(new, 0, sizeof(struct status_block));
@@ -623,6 +755,43 @@ void parse_json(const char *text) {
new->separator_block_width = 9; // i3bar spec
}
+ // Airblader features
+ if (background) {
+ new->background = parse_color(json_object_get_string(background));
+ } else {
+ new->background = 0x0; // transparent
+ }
+
+ if (border) {
+ new->border = parse_color(json_object_get_string(border));
+ } else {
+ new->border = 0x0; // transparent
+ }
+
+ if (border_top) {
+ new->border_top = json_object_get_int(border_top);
+ } else {
+ new->border_top = 1;
+ }
+
+ if (border_bottom) {
+ new->border_bottom = json_object_get_int(border_bottom);
+ } else {
+ new->border_bottom = 1;
+ }
+
+ if (border_left) {
+ new->border_left = json_object_get_int(border_left);
+ } else {
+ new->border_left = 1;
+ }
+
+ if (border_right) {
+ new->border_right = json_object_get_int(border_right);
+ } else {
+ new->border_right = 1;
+ }
+
list_add(status_line, new);
}