Implement status line
Does not yet support i3bar json protocol
This commit is contained in:
parent
718502c815
commit
0d0ab7c5ce
|
@ -16,6 +16,7 @@ struct swaybar {
|
||||||
|
|
||||||
struct swaybar_config *config;
|
struct swaybar_config *config;
|
||||||
struct swaybar_output *focused_output;
|
struct swaybar_output *focused_output;
|
||||||
|
struct status_line *status;
|
||||||
|
|
||||||
int ipc_event_socketfd;
|
int ipc_event_socketfd;
|
||||||
int ipc_socketfd;
|
int ipc_socketfd;
|
||||||
|
|
|
@ -1,61 +1,30 @@
|
||||||
#ifndef _SWAYBAR_STATUS_LINE_H
|
#ifndef _SWAYBAR_STATUS_LINE_H
|
||||||
#define _SWAYBAR_STATUS_LINE_H
|
#define _SWAYBAR_STATUS_LINE_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "list.h"
|
|
||||||
#include "bar.h"
|
#include "bar.h"
|
||||||
|
|
||||||
typedef enum {UNDEF, TEXT, I3BAR} command_protocol;
|
enum status_protocol {
|
||||||
|
PROTOCOL_UNDEF,
|
||||||
|
PROTOCOL_TEXT,
|
||||||
|
PROTOCOL_I3BAR,
|
||||||
|
};
|
||||||
|
|
||||||
struct status_line {
|
struct status_line {
|
||||||
list_t *block_line;
|
pid_t pid;
|
||||||
const char *text_line;
|
int read_fd, write_fd;
|
||||||
command_protocol protocol;
|
FILE *read, *write;
|
||||||
bool click_events;
|
|
||||||
|
enum status_protocol protocol;
|
||||||
|
const char *text;
|
||||||
|
|
||||||
|
char *buffer;
|
||||||
|
size_t buffer_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct status_block {
|
struct status_line *status_line_init(char *cmd);
|
||||||
char *full_text, *short_text, *align;
|
void status_line_free(struct status_line *status);
|
||||||
bool urgent;
|
bool handle_status_readable(struct status_line *status);
|
||||||
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;
|
|
||||||
|
|
||||||
// Set during rendering
|
#endif
|
||||||
int x;
|
|
||||||
int width;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
|
|
||||||
#endif /* _SWAYBAR_STATUS_LINE_H */
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "swaybar/render.h"
|
#include "swaybar/render.h"
|
||||||
#include "swaybar/config.h"
|
#include "swaybar/config.h"
|
||||||
#include "swaybar/event_loop.h"
|
#include "swaybar/event_loop.h"
|
||||||
|
#include "swaybar/status_line.h"
|
||||||
#include "swaybar/bar.h"
|
#include "swaybar/bar.h"
|
||||||
#include "swaybar/ipc.h"
|
#include "swaybar/ipc.h"
|
||||||
#include "ipc-client.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_socketfd = ipc_open_socket(socket_path);
|
||||||
bar->ipc_event_socketfd = ipc_open_socket(socket_path);
|
bar->ipc_event_socketfd = ipc_open_socket(socket_path);
|
||||||
ipc_initialize(bar, bar_id);
|
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));
|
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) {
|
static void display_in(int fd, short mask, void *_bar) {
|
||||||
struct swaybar *bar = (struct swaybar *)_bar;
|
struct swaybar *bar = (struct swaybar *)_bar;
|
||||||
if (wl_display_dispatch(bar->display) == -1) {
|
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) {
|
static void ipc_in(int fd, short mask, void *_bar) {
|
||||||
struct swaybar *bar = (struct swaybar *)_bar;
|
struct swaybar *bar = (struct swaybar *)_bar;
|
||||||
if (handle_ipc_event(bar)) {
|
if (handle_ipc_event(bar)) {
|
||||||
struct swaybar_output *output;
|
render_all_frames(bar);
|
||||||
wl_list_for_each(output, &bar->outputs, link) {
|
}
|
||||||
render_frame(bar, output);
|
}
|
||||||
}
|
|
||||||
|
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) {
|
void bar_run(struct swaybar *bar) {
|
||||||
add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar);
|
add_event(wl_display_get_fd(bar->display), POLLIN, display_in, bar);
|
||||||
add_event(bar->ipc_event_socketfd, POLLIN, ipc_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) {
|
while (1) {
|
||||||
event_loop_poll();
|
event_loop_poll();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,7 @@ struct swaybar_config *init_config() {
|
||||||
config->colors.background = 0x000000FF;
|
config->colors.background = 0x000000FF;
|
||||||
config->colors.focused_background = 0x000000FF;
|
config->colors.focused_background = 0x000000FF;
|
||||||
config->colors.statusline = 0xFFFFFFFF;
|
config->colors.statusline = 0xFFFFFFFF;
|
||||||
|
config->colors.focused_statusline = 0xFFFFFFFF;
|
||||||
config->colors.separator = 0x666666FF;
|
config->colors.separator = 0x666666FF;
|
||||||
|
|
||||||
config->colors.focused_workspace.border = 0x4C7899FF;
|
config->colors.focused_workspace.border = 0x4C7899FF;
|
||||||
|
|
|
@ -7,6 +7,7 @@ executable(
|
||||||
'ipc.c',
|
'ipc.c',
|
||||||
'main.c',
|
'main.c',
|
||||||
'render.c',
|
'render.c',
|
||||||
|
'status_line.c',
|
||||||
],
|
],
|
||||||
include_directories: [sway_inc],
|
include_directories: [sway_inc],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
|
|
|
@ -9,12 +9,59 @@
|
||||||
#include "swaybar/bar.h"
|
#include "swaybar/bar.h"
|
||||||
#include "swaybar/config.h"
|
#include "swaybar/config.h"
|
||||||
#include "swaybar/render.h"
|
#include "swaybar/render.h"
|
||||||
|
#include "swaybar/status_line.h"
|
||||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||||
|
|
||||||
static const int ws_horizontal_padding = 5;
|
static const int ws_horizontal_padding = 5;
|
||||||
static const double ws_vertical_padding = 1.5;
|
static const double ws_vertical_padding = 1.5;
|
||||||
static const double border_width = 1;
|
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,
|
static uint32_t render_binding_mode_indicator(cairo_t *cairo,
|
||||||
struct swaybar_config *config, const char *mode, double x,
|
struct swaybar_config *config, const char *mode, double x,
|
||||||
uint32_t height) {
|
uint32_t height) {
|
||||||
|
@ -148,6 +195,11 @@ static uint32_t render_to_cairo(cairo_t *cairo,
|
||||||
cairo, config, config->mode, x, output->height);
|
cairo, config, config->mode, x, output->height);
|
||||||
max_height = h > max_height ? h : max_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;
|
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_surface_t *recorder = cairo_recording_surface_create(
|
||||||
CAIRO_CONTENT_COLOR_ALPHA, NULL);
|
CAIRO_CONTENT_COLOR_ALPHA, NULL);
|
||||||
cairo_t *cairo = cairo_create(recorder);
|
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);
|
uint32_t height = render_to_cairo(cairo, bar, output);
|
||||||
if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) {
|
if (bar->config->height >= 0 && height < (uint32_t)bar->config->height) {
|
||||||
height = bar->config->height;
|
height = bar->config->height;
|
||||||
|
|
78
swaybar/status_line.c
Normal file
78
swaybar/status_line.c
Normal file
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in a new issue