aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDrew DeVault <sir@cmpwn.com>2018-03-29 15:16:12 -0400
committerDrew DeVault <sir@cmpwn.com>2018-03-29 22:11:08 -0400
commit0d0ab7c5ce148bce841fa0682d04bc7b6c21b902 (patch)
treebc3dcefa0e306ac00d81a0cabbd6a0404d7baff6
parent718502c815d0af81b4ab71fb6b86976b5403adf9 (diff)
Implement status line
Does not yet support i3bar json protocol
-rw-r--r--include/swaybar/bar.h1
-rw-r--r--include/swaybar/status_line.h65
-rw-r--r--swaybar/bar.c26
-rw-r--r--swaybar/config.c1
-rw-r--r--swaybar/meson.build1
-rw-r--r--swaybar/render.c56
-rw-r--r--swaybar/status_line.c78
7 files changed, 176 insertions, 52 deletions
diff --git a/include/swaybar/bar.h b/include/swaybar/bar.h
index c89aa61c..1bf2ea2d 100644
--- a/include/swaybar/bar.h
+++ b/include/swaybar/bar.h
@@ -16,6 +16,7 @@ struct swaybar {
struct swaybar_config *config;
struct swaybar_output *focused_output;
+ struct status_line *status;
int ipc_event_socketfd;
int ipc_socketfd;
diff --git a/include/swaybar/status_line.h b/include/swaybar/status_line.h
index 0664ddee..6c595df0 100644
--- a/include/swaybar/status_line.h
+++ b/include/swaybar/status_line.h
@@ -1,61 +1,30 @@
#ifndef _SWAYBAR_STATUS_LINE_H
#define _SWAYBAR_STATUS_LINE_H
-
#include <stdint.h>
+#include <stdio.h>
#include <stdbool.h>
-
-#include "list.h"
#include "bar.h"
-typedef enum {UNDEF, TEXT, I3BAR} command_protocol;
+enum status_protocol {
+ PROTOCOL_UNDEF,
+ PROTOCOL_TEXT,
+ PROTOCOL_I3BAR,
+};
struct status_line {
- list_t *block_line;
- const char *text_line;
- command_protocol protocol;
- bool click_events;
-};
+ pid_t pid;
+ int read_fd, write_fd;
+ FILE *read, *write;
-struct status_block {
- char *full_text, *short_text, *align;
- bool urgent;
- uint32_t color;
- int min_width;
- char *name, *instance;
- bool separator;
- int separator_block_width;
- bool markup;
- // Airblader features
- uint32_t background;
- uint32_t border;
- int border_top;
- int border_bottom;
- int border_left;
- int border_right;
+ enum status_protocol protocol;
+ const char *text;
- // Set during rendering
- int x;
- int width;
+ char *buffer;
+ size_t buffer_size;
};
-/**
- * Initialize status line struct.
- */
-struct status_line *init_status_line();
-
-/**
- * handle status line activity.
- */
-bool handle_status_line(struct bar *bar);
-
-/**
- * Handle mouse clicks.
- */
-bool status_line_mouse_event(struct bar *bar, int x, int y, uint32_t button);
-
-/**
- * Free status line struct.
- */
-void free_status_line(struct status_line *line);
+struct status_line *status_line_init(char *cmd);
+void status_line_free(struct status_line *status);
+bool handle_status_readable(struct status_line *status);
-#endif /* _SWAYBAR_STATUS_LINE_H */
+#endif
diff --git a/swaybar/bar.c b/swaybar/bar.c
index 90fd5ad4..72c4be8f 100644
--- a/swaybar/bar.c
+++ b/swaybar/bar.c
@@ -13,6 +13,7 @@
#include "swaybar/render.h"
#include "swaybar/config.h"
#include "swaybar/event_loop.h"
+#include "swaybar/status_line.h"
#include "swaybar/bar.h"
#include "swaybar/ipc.h"
#include "ipc-client.h"
@@ -98,6 +99,9 @@ void bar_setup(struct swaybar *bar,
bar->ipc_socketfd = ipc_open_socket(socket_path);
bar->ipc_event_socketfd = ipc_open_socket(socket_path);
ipc_initialize(bar, bar_id);
+ if (bar->config->status_command) {
+ bar->status = status_line_init(bar->config->status_command);
+ }
assert(bar->display = wl_display_connect(NULL));
@@ -134,6 +138,13 @@ void bar_setup(struct swaybar *bar,
}
}
+static void render_all_frames(struct swaybar *bar) {
+ struct swaybar_output *output;
+ wl_list_for_each(output, &bar->outputs, link) {
+ render_frame(bar, output);
+ }
+}
+
static void display_in(int fd, short mask, void *_bar) {
struct swaybar *bar = (struct swaybar *)_bar;
if (wl_display_dispatch(bar->display) == -1) {
@@ -144,16 +155,23 @@ static void display_in(int fd, short mask, void *_bar) {
static void ipc_in(int fd, short mask, void *_bar) {
struct swaybar *bar = (struct swaybar *)_bar;
if (handle_ipc_event(bar)) {
- struct swaybar_output *output;
- wl_list_for_each(output, &bar->outputs, link) {
- render_frame(bar, output);
- }
+ render_all_frames(bar);
+ }
+}
+
+static void status_in(int fd, short mask, void *_bar) {
+ struct swaybar *bar = (struct swaybar *)_bar;
+ if (handle_status_readable(bar->status)) {
+ render_all_frames(bar);
}
}
void bar_run(struct swaybar *bar) {
add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar);
add_event(bar->ipc_event_socketfd, POLLIN, ipc_in, bar);
+ if (bar->status) {
+ add_event(bar->status->read_fd, POLLIN, status_in, bar);
+ }
while (1) {
event_loop_poll();
}
diff --git a/swaybar/config.c b/swaybar/config.c
index 802d0779..9169ad27 100644
--- a/swaybar/config.c
+++ b/swaybar/config.c
@@ -43,6 +43,7 @@ struct swaybar_config *init_config() {
config->colors.background = 0x000000FF;
config->colors.focused_background = 0x000000FF;
config->colors.statusline = 0xFFFFFFFF;
+ config->colors.focused_statusline = 0xFFFFFFFF;
config->colors.separator = 0x666666FF;
config->colors.focused_workspace.border = 0x4C7899FF;
diff --git a/swaybar/meson.build b/swaybar/meson.build
index 6dc7c564..d15e8b5c 100644
--- a/swaybar/meson.build
+++ b/swaybar/meson.build
@@ -7,6 +7,7 @@ executable(
'ipc.c',
'main.c',
'render.c',
+ 'status_line.c',
],
include_directories: [sway_inc],
dependencies: [
diff --git a/swaybar/render.c b/swaybar/render.c
index f797873c..ec1239a1 100644
--- a/swaybar/render.c
+++ b/swaybar/render.c
@@ -9,12 +9,59 @@
#include "swaybar/bar.h"
#include "swaybar/config.h"
#include "swaybar/render.h"
+#include "swaybar/status_line.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
static const int ws_horizontal_padding = 5;
static const double ws_vertical_padding = 1.5;
static const double border_width = 1;
+static uint32_t render_status_line_text(cairo_t *cairo,
+ struct swaybar_config *config, struct status_line *status,
+ bool focused, uint32_t width, uint32_t height) {
+ if (!status->text) {
+ return 0;
+ }
+ //wlr_log(L_DEBUG, "focused %d", focused);
+ cairo_set_source_u32(cairo, focused ?
+ config->colors.focused_statusline : config->colors.statusline);
+ static const int margin = 3;
+ int text_width, text_height;
+ get_text_size(cairo, config->font, &text_width, &text_height,
+ 1, config->pango_markup, "%s", status->text);
+ uint32_t ideal_height = text_height + ws_vertical_padding * 2;
+ if (height < ideal_height) {
+ height = ideal_height;
+ }
+ double text_y = height / 2.0 - text_height / 2.0;
+ cairo_move_to(cairo, width - text_width - margin, (int)floor(text_y));
+ pango_printf(cairo, config->font, 1, config->pango_markup,
+ "%s", status->text);
+ return ideal_height;
+}
+
+static uint32_t render_status_line_i3bar(cairo_t *cairo,
+ struct swaybar_config *config, struct status_line *status,
+ bool focused, uint32_t width, uint32_t height) {
+ // TODO
+ return 0;
+}
+
+static uint32_t render_status_line(cairo_t *cairo,
+ struct swaybar_config *config, struct status_line *status,
+ bool focused, uint32_t width, uint32_t height) {
+ switch (status->protocol) {
+ case PROTOCOL_TEXT:
+ return render_status_line_text(cairo,
+ config, status, focused, width, height);
+ case PROTOCOL_I3BAR:
+ return render_status_line_i3bar(cairo,
+ config, status, focused, width, height);
+ default:
+ return 0;
+ }
+}
+
static uint32_t render_binding_mode_indicator(cairo_t *cairo,
struct swaybar_config *config, const char *mode, double x,
uint32_t height) {
@@ -148,6 +195,11 @@ static uint32_t render_to_cairo(cairo_t *cairo,
cairo, config, config->mode, x, output->height);
max_height = h > max_height ? h : max_height;
}
+ if (bar->status) {
+ uint32_t h = render_status_line(cairo, config, bar->status,
+ output->focused, output->width, output->height);
+ max_height = h > max_height ? h : max_height;
+ }
return max_height > output->height ? max_height : output->height;
}
@@ -157,6 +209,10 @@ void render_frame(struct swaybar *bar,
cairo_surface_t *recorder = cairo_recording_surface_create(
CAIRO_CONTENT_COLOR_ALPHA, NULL);
cairo_t *cairo = cairo_create(recorder);
+ cairo_save(cairo);
+ cairo_set_operator(cairo, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(cairo);
+ cairo_restore(cairo);
uint32_t height = render_to_cairo(cairo, bar, output);
if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) {
height = bar->config->height;
diff --git a/swaybar/status_line.c b/swaybar/status_line.c
new file mode 100644
index 00000000..ff668c9c
--- /dev/null
+++ b/swaybar/status_line.c
@@ -0,0 +1,78 @@
+#define _POSIX_C_SOURCE
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <wlr/util/log.h>
+#include "swaybar/config.h"
+#include "swaybar/status_line.h"
+#include "readline.h"
+
+bool handle_status_readable(struct status_line *status) {
+ char *line = read_line_buffer(status->read,
+ status->buffer, status->buffer_size);
+ switch (status->protocol) {
+ case PROTOCOL_I3BAR:
+ // TODO
+ break;
+ case PROTOCOL_TEXT:
+ status->text = line;
+ return true;
+ case PROTOCOL_UNDEF:
+ if (!line) {
+ return false;
+ }
+ if (line[0] == '{') {
+ // TODO: JSON
+ } else {
+ status->text = line;
+ status->protocol = PROTOCOL_TEXT;
+ }
+ return false;
+ }
+ return false;
+}
+
+struct status_line *status_line_init(char *cmd) {
+ struct status_line *status = calloc(1, sizeof(struct status_line));
+ status->buffer_size = 4096;
+ status->buffer = malloc(status->buffer_size);
+
+ int pipe_read_fd[2];
+ int pipe_write_fd[2];
+ if (pipe(pipe_read_fd) != 0 || pipe(pipe_write_fd) != 0) {
+ wlr_log(L_ERROR, "Unable to create pipes for status_command fork");
+ exit(1);
+ }
+
+ status->pid = fork();
+ if (status->pid == 0) {
+ dup2(pipe_read_fd[1], STDOUT_FILENO);
+ close(pipe_read_fd[0]);
+ close(pipe_read_fd[1]);
+
+ dup2(pipe_write_fd[0], STDIN_FILENO);
+ close(pipe_write_fd[0]);
+ close(pipe_write_fd[1]);
+
+ char *const _cmd[] = { "sh", "-c", cmd, NULL, };
+ execvp(_cmd[0], _cmd);
+ exit(1);
+ }
+
+ close(pipe_read_fd[1]);
+ status->read_fd = pipe_read_fd[0];
+ fcntl(status->read_fd, F_SETFL, O_NONBLOCK);
+ close(pipe_write_fd[0]);
+ status->write_fd = pipe_write_fd[1];
+ fcntl(status->write_fd, F_SETFL, O_NONBLOCK);
+
+ status->read = fdopen(status->read_fd, "r");
+ status->write = fdopen(status->write_fd, "w");
+ return status;
+}
+
+void status_line_free(struct status_line *line) {
+ free(line);
+}