aboutsummaryrefslogtreecommitdiff
path: root/dwlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'dwlb.c')
-rw-r--r--dwlb.c1016
1 files changed, 670 insertions, 346 deletions
diff --git a/dwlb.c b/dwlb.c
index 6743184..fa4591c 100644
--- a/dwlb.c
+++ b/dwlb.c
@@ -4,6 +4,7 @@
#include <errno.h>
#include <fcft/fcft.h>
#include <fcntl.h>
+#include <linux/input-event-codes.h>
#include <pixman-1/pixman.h>
#include <signal.h>
#include <stdbool.h>
@@ -11,45 +12,56 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
+#include <sys/select.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <unistd.h>
#include <utlist.h>
#include <wayland-client.h>
+#include <wayland-cursor.h>
#include "utf8.h"
#include "xdg-shell-protocol.h"
#include "xdg-output-unstable-v1-protocol.h"
#include "wlr-layer-shell-unstable-v1-protocol.h"
-#define DIE(fmt, ...) \
+#define DIE(fmt, ...) \
do { \
+ cleanup(); \
fprintf(stderr, fmt "\n", ##__VA_ARGS__); \
exit(1); \
} while (0)
-
#define EDIE(fmt, ...) \
DIE(fmt ": %s", ##__VA_ARGS__, strerror(errno));
-#define CLEANUP_DIE(why) \
- do { \
- cleanup(); \
- DIE(why); \
- } while(0)
-
-#define CLEANUP_EDIE(why) \
- do { \
- cleanup(); \
- EDIE(why); \
- } while(0)
-
#define MIN(a, b) \
((a) < (b) ? (a) : (b))
#define MAX(a, b) \
((a) > (b) ? (a) : (b))
-#define LENGTH(X) \
- (sizeof X / sizeof X[0])
+#define LENGTH(x) \
+ (sizeof x / sizeof x[0])
+
+#define ARRAY_INIT_CAP 8
+#define ARRAY_EXPAND(arr, len, cap, inc) \
+ do { \
+ uint32_t new_len, new_cap; \
+ new_len = (len) + (inc); \
+ if (new_len > (cap)) { \
+ new_cap = new_len * 2; \
+ if (new_cap < ARRAY_INIT_CAP) \
+ new_cap = ARRAY_INIT_CAP; \
+ if (!((arr) = realloc((arr), sizeof(*(arr)) * new_cap))) \
+ EDIE("realloc"); \
+ (cap) = new_cap; \
+ } \
+ (len) = new_len; \
+ } while (0)
+#define ARRAY_APPEND(arr, len, cap, ptr) \
+ do { \
+ ARRAY_EXPAND((arr), (len), (cap), 1); \
+ (ptr) = &(arr)[(len) - 1]; \
+ } while (0)
#define PROGRAM "dwlb"
#define VERSION "0.1"
@@ -85,6 +97,22 @@
" -v get version information\n" \
" -h view this help text\n"
+typedef struct {
+ pixman_color_t color;
+ bool bg;
+ char *start;
+} StatusColor;
+
+typedef struct {
+ uint32_t button;
+ uint32_t x1;
+ uint32_t x2;
+ bool incomplete;
+ char command[128];
+ char *start;
+ char *end;
+} StatusButton;
+
typedef struct Bar Bar;
struct Bar {
struct zxdg_output_v1 *xdg_output;
@@ -109,14 +137,35 @@ struct Bar {
char layout[32];
char title[512];
char status[512];
+
+ StatusColor *status_colors;
+ uint32_t status_colors_l, status_colors_c;
+ StatusButton *status_buttons;
+ uint32_t status_buttons_l, status_buttons_c;
bool hidden;
bool bottom;
+
bool redraw;
Bar *prev, *next;
};
+typedef struct Seat Seat;
+struct Seat {
+ struct wl_seat *wl_seat;
+ struct wl_pointer *wl_pointer;
+
+ uint32_t registry_name;
+
+ Bar *pointer_bar;
+ uint32_t pointer_x;
+ uint32_t pointer_y;
+ uint32_t pointer_button;
+
+ Seat *prev, *next;
+};
+
static int sock_fd;
static char socketdir[256];
static char *socketpath = NULL;
@@ -129,10 +178,13 @@ static struct wl_compositor *compositor;
static struct wl_shm *shm;
static struct zwlr_layer_shell_v1 *layer_shell;
static struct zxdg_output_manager_v1 *output_manager;
+static struct wl_cursor_image *cursor_image;
+static struct wl_surface *cursor_surface;
-static struct fcft_font *font;
+static Bar *bar_list = NULL;
+static Seat *seat_list = NULL;
-static Bar *bars = NULL;
+static struct fcft_font *font;
static uint32_t height;
static uint32_t textpadding;
@@ -171,123 +223,81 @@ allocate_shm_file(size_t size)
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
- parse_color(arg, bg);
- }
- } else if (!strcmp(cmd, "fg")) {
- if (fg && def_fg) {
- if (!*arg)
- *fg = *def_fg;
- else
- parse_color(arg, fg);
- }
- }
-
- /* Restore string for later redraws */
- *--arg = '(';
- *end = ')';
- return end;
-}
-
static uint32_t
draw_text(char *text,
uint32_t xpos,
uint32_t ypos,
pixman_image_t *foreground,
pixman_image_t *background,
- pixman_color_t *fgcolor,
- pixman_color_t *bgcolor,
- uint32_t maxxpos,
- uint32_t bufheight,
+ pixman_color_t *fg_color,
+ pixman_color_t *bg_color,
+ uint32_t max_xpos,
+ uint32_t buf_height,
uint32_t padding,
- bool commands)
+ StatusColor *colors,
+ uint32_t colors_l,
+ StatusButton *buttons,
+ uint32_t buttons_l)
{
- if (!*text || !maxxpos)
+ if (!*text || !max_xpos)
return xpos;
uint32_t ixpos = xpos;
uint32_t nxpos;
- if ((nxpos = xpos + padding) + padding >= maxxpos)
+ if ((nxpos = xpos + padding) + padding >= max_xpos)
return xpos;
xpos = nxpos;
- bool drawfg = foreground && fgcolor;
- bool drawbg = background && bgcolor;
+ bool draw_fg = foreground && fg_color;
+ bool draw_bg = background && bg_color;
+
+ pixman_image_t *fg_fill;
+ pixman_color_t *cur_bg_color;
+ if (draw_fg)
+ fg_fill = pixman_image_create_solid_fill(fg_color);
+ if (draw_bg)
+ cur_bg_color = bg_color;
+
+ if (buttons)
+ for (uint32_t i = 0; i < buttons_l; i++)
+ buttons[i].incomplete = true;
- pixman_image_t *fgfill;
- pixman_color_t cur_fgcolor;
- pixman_color_t cur_bgcolor;
- if (drawfg) {
- fgfill = pixman_image_create_solid_fill(fgcolor);
- cur_fgcolor = *fgcolor;
- }
- if (drawbg)
- cur_bgcolor = *bgcolor;
-
uint32_t codepoint;
uint32_t state = UTF8_ACCEPT;
- uint32_t lastcp = 0;
-
+ uint32_t last_cp = 0;
+ uint32_t color_ind = 0;
+
for (char *p = text; *p; p++) {
- /* If commands are enabled, check for inline ^ commands */
- if (commands && state == UTF8_ACCEPT && *p == '^') {
- p++;
- if (*p != '^') {
- p = handle_cmd(p, &cur_fgcolor, &cur_bgcolor, fgcolor, bgcolor);
- if (drawfg) {
- pixman_image_unref(fgfill);
- fgfill = pixman_image_create_solid_fill(&cur_fgcolor);
+ /* Check for color changes */
+ if (state == UTF8_ACCEPT) {
+ if (colors && (draw_fg || draw_bg)) {
+ while (color_ind < colors_l && p == colors[color_ind].start) {
+ if (colors[color_ind].bg) {
+ if (draw_bg)
+ cur_bg_color = &colors[color_ind].color;
+ } else {
+ if (draw_fg) {
+ pixman_image_unref(fg_fill);
+ fg_fill = pixman_image_create_solid_fill(&colors[color_ind].color);
+ }
+ }
+ color_ind++;
+ }
+ }
+
+ if (buttons) {
+ for (uint32_t i = 0; i < buttons_l; i++) {
+ if (p == buttons[i].start) {
+ buttons[i].x1 = xpos;
+ } else if (p == buttons[i].end) {
+ buttons[i].x2 = xpos;
+ buttons[i].incomplete = false;
+ }
}
- continue;
}
}
-
+
/* Returns nonzero if more bytes are needed */
if (utf8decode(&state, &codepoint, *p))
continue;
@@ -300,109 +310,111 @@ draw_text(char *text,
/* Adjust x position based on kerning with previous glyph */
long x_kern = 0;
- if (lastcp)
- fcft_kerning(font, lastcp, codepoint, &x_kern, NULL);
- if ((nxpos = xpos + x_kern + glyph->advance.x) + padding > maxxpos)
+ if (last_cp)
+ fcft_kerning(font, last_cp, codepoint, &x_kern, NULL);
+ if ((nxpos = xpos + x_kern + glyph->advance.x) + padding > max_xpos)
break;
- lastcp = codepoint;
+ last_cp = codepoint;
xpos += x_kern;
- if (drawfg) {
+ if (draw_fg) {
/* Detect and handle pre-rendered glyphs (e.g. emoji) */
if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) {
/* Only the alpha channel of the mask is used, so we can
* use fgfill here to blend prerendered glyphs with the
* same opacity */
pixman_image_composite32(
- PIXMAN_OP_OVER, glyph->pix, fgfill, foreground, 0, 0, 0, 0,
+ PIXMAN_OP_OVER, glyph->pix, fg_fill, foreground, 0, 0, 0, 0,
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height);
} else {
/* Applying the foreground color here would mess up
* component alphas for subpixel-rendered text, so we
* apply it when blending. */
pixman_image_composite32(
- PIXMAN_OP_OVER, fgfill, glyph->pix, foreground, 0, 0, 0, 0,
+ PIXMAN_OP_OVER, fg_fill, glyph->pix, foreground, 0, 0, 0, 0,
xpos + glyph->x, ypos - glyph->y, glyph->width, glyph->height);
}
}
- if (drawbg)
+ if (draw_bg)
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
- &cur_bgcolor, 1, &(pixman_box32_t){
+ cur_bg_color, 1, &(pixman_box32_t){
.x1 = xpos, .x2 = nxpos,
- .y1 = 0, .y2 = bufheight
+ .y1 = 0, .y2 = buf_height
});
/* increment pen position */
xpos = nxpos;
ypos += glyph->advance.y;
}
- if (drawfg)
- pixman_image_unref(fgfill);
-
- if (!lastcp)
+
+ if (draw_fg)
+ pixman_image_unref(fg_fill);
+ if (!last_cp)
return ixpos;
- if (state != UTF8_ACCEPT)
- fprintf(stderr, "malformed UTF-8 sequence\n");
+ if (buttons)
+ for (uint32_t i = 0; i < buttons_l; i++)
+ if (buttons[i].incomplete)
+ buttons[i].x2 = xpos;
nxpos = xpos + padding;
- if (drawbg) {
+ if (draw_bg) {
/* Fill padding background */
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
- &cur_bgcolor, 1, &(pixman_box32_t){
+ bg_color, 1, &(pixman_box32_t){
.x1 = ixpos, .x2 = ixpos + padding,
- .y1 = 0, .y2 = bufheight
+ .y1 = 0, .y2 = buf_height
});
pixman_image_fill_boxes(PIXMAN_OP_OVER, background,
- bgcolor, 1, &(pixman_box32_t){
+ bg_color, 1, &(pixman_box32_t){
.x1 = xpos, .x2 = nxpos,
- .y1 = 0, .y2 = bufheight
+ .y1 = 0, .y2 = buf_height
});
}
return nxpos;
}
-#define TEXT_WIDTH(text, maxwidth, padding, commands) \
- draw_text(text, 0, 0, NULL, NULL, NULL, NULL, maxwidth, 0, padding, commands)
+#define TEXT_WIDTH(text, maxwidth, padding) \
+ draw_text(text, 0, 0, NULL, NULL, NULL, NULL, maxwidth, 0, padding, NULL, 0, NULL, 0)
static int
-draw_frame(Bar *b)
+draw_frame(Bar *bar)
{
/* Allocate buffer to be attached to the surface */
- int fd = allocate_shm_file(b->bufsize);
+ int fd = allocate_shm_file(bar->bufsize);
if (fd == -1)
return -1;
- uint32_t *data = mmap(NULL, b->bufsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ uint32_t *data = mmap(NULL, bar->bufsize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (data == MAP_FAILED) {
close(fd);
return -1;
}
- struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, b->bufsize);
- struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, b->width, b->height, b->stride, WL_SHM_FORMAT_ARGB8888);
+ struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, bar->bufsize);
+ struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, bar->width, bar->height, bar->stride, WL_SHM_FORMAT_ARGB8888);
wl_buffer_add_listener(buffer, &wl_buffer_listener, NULL);
wl_shm_pool_destroy(pool);
close(fd);
/* Pixman image corresponding to main buffer */
- pixman_image_t *bar = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, data, b->width * 4);
+ pixman_image_t *final = pixman_image_create_bits(PIXMAN_a8r8g8b8, bar->width, bar->height, data, bar->width * 4);
/* Text background and foreground layers */
- pixman_image_t *foreground = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
- pixman_image_t *background = pixman_image_create_bits(PIXMAN_a8r8g8b8, b->width, b->height, NULL, b->width * 4);
+ pixman_image_t *foreground = pixman_image_create_bits(PIXMAN_a8r8g8b8, bar->width, bar->height, NULL, bar->width * 4);
+ pixman_image_t *background = pixman_image_create_bits(PIXMAN_a8r8g8b8, bar->width, bar->height, NULL, bar->width * 4);
/* Draw on images */
uint32_t xpos_left = 0;
- uint32_t ypos = (b->height + font->ascent - font->descent) / 2;
+ uint32_t ypos = (bar->height + font->ascent - font->descent) / 2;
uint32_t boxs = font->height / 9;
uint32_t boxw = font->height / 6 + 2;
for (uint32_t i = 0; i < LENGTH(tags); i++) {
- bool active = b->mtags & 1 << i;
- bool occupied = b->ctags & 1 << i;
- bool urgent = b->urg & 1 << i;
+ bool active = bar->mtags & 1 << i;
+ bool occupied = bar->ctags & 1 << i;
+ bool urgent = bar->urg & 1 << i;
if (hide_vacant && !active && !occupied && !urgent)
continue;
@@ -417,43 +429,47 @@ draw_frame(Bar *b)
.y1 = boxs, .y2 = boxs + boxw
});
- xpos_left = draw_text(tags[i], xpos_left, ypos, foreground, background, fg_color,
- bg_color, b->width, b->height, b->textpadding, false);
+ xpos_left = draw_text(tags[i], xpos_left, ypos, foreground, background, fg_color, bg_color,
+ bar->width, bar->height, bar->textpadding, NULL, 0, NULL, 0);
}
- xpos_left = draw_text(b->layout, xpos_left, ypos, foreground, background, &inactive_fg_color,
- &inactive_bg_color, b->width, b->height, b->textpadding, false);
+ xpos_left = draw_text(bar->layout, xpos_left, ypos, foreground, background,
+ &inactive_fg_color, &inactive_bg_color, bar->width,
+ bar->height, bar->textpadding, NULL, 0, NULL, 0);
- uint32_t status_width = TEXT_WIDTH(b->status, b->width - xpos_left, b->textpadding, true);
- draw_text(b->status, b->width - status_width, ypos, foreground,
+ uint32_t status_width = TEXT_WIDTH(bar->status, bar->width - xpos_left, bar->textpadding);
+ draw_text(bar->status, bar->width - status_width, ypos, foreground,
background, &inactive_fg_color, &inactive_bg_color,
- b->width, b->height, b->textpadding, status_commands);
+ bar->width, bar->height, bar->textpadding,
+ bar->status_colors, bar->status_colors_l,
+ bar->status_buttons, bar->status_buttons_l);
- xpos_left = draw_text(b->title, xpos_left, ypos, foreground, background,
- b->selmon ? &active_fg_color : &inactive_fg_color,
- b->selmon ? &active_bg_color : &inactive_bg_color,
- b->width - status_width, b->height, b->textpadding, false);
+ xpos_left = draw_text(bar->title, xpos_left, ypos, foreground, background,
+ bar->selmon ? &active_fg_color : &inactive_fg_color,
+ bar->selmon ? &active_bg_color : &inactive_bg_color,
+ bar->width - status_width, bar->height, bar->textpadding,
+ NULL, 0, NULL, 0);
pixman_image_fill_boxes(PIXMAN_OP_SRC, background,
- b->selmon ? &active_bg_color : &inactive_bg_color, 1,
+ bar->selmon ? &active_bg_color : &inactive_bg_color, 1,
&(pixman_box32_t){
- .x1 = xpos_left, .x2 = b->width - status_width,
- .y1 = 0, .y2 = b->height
+ .x1 = xpos_left, .x2 = bar->width - status_width,
+ .y1 = 0, .y2 = bar->height
});
/* Draw background and foreground on bar */
- pixman_image_composite32(PIXMAN_OP_OVER, background, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
- pixman_image_composite32(PIXMAN_OP_OVER, foreground, NULL, bar, 0, 0, 0, 0, 0, 0, b->width, b->height);
+ pixman_image_composite32(PIXMAN_OP_OVER, background, NULL, final, 0, 0, 0, 0, 0, 0, bar->width, bar->height);
+ pixman_image_composite32(PIXMAN_OP_OVER, foreground, NULL, final, 0, 0, 0, 0, 0, 0, bar->width, bar->height);
pixman_image_unref(foreground);
pixman_image_unref(background);
- pixman_image_unref(bar);
+ pixman_image_unref(final);
- munmap(data, b->bufsize);
+ munmap(data, bar->bufsize);
- wl_surface_attach(b->wl_surface, buffer, 0, 0);
- wl_surface_damage_buffer(b->wl_surface, 0, 0, b->width, b->height);
- wl_surface_commit(b->wl_surface);
+ wl_surface_attach(bar->wl_surface, buffer, 0, 0);
+ wl_surface_damage_buffer(bar->wl_surface, 0, 0, bar->width, bar->height);
+ wl_surface_commit(bar->wl_surface);
return 0;
}
@@ -465,18 +481,18 @@ layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface,
{
zwlr_layer_surface_v1_ack_configure(surface, serial);
- Bar *b = (Bar *)data;
+ Bar *bar = (Bar *)data;
- if (b->configured && w == b->width && h == b->height)
+ if (bar->configured && w == bar->width && h == bar->height)
return;
- b->width = w;
- b->height = h;
- b->stride = b->width * 4;
- b->bufsize = b->stride * b->height;
- b->configured = true;
+ bar->width = w;
+ bar->height = h;
+ bar->stride = bar->width * 4;
+ bar->bufsize = bar->stride * bar->height;
+ bar->configured = true;
- draw_frame(b);
+ draw_frame(bar);
}
static void
@@ -500,13 +516,13 @@ cleanup(void)
static void
output_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name)
{
- Bar *b = (Bar *)data;
+ Bar *bar = (Bar *)data;
/* Is this necessary? */
- if (b->xdg_output_name)
- free(b->xdg_output_name);
- if (!(b->xdg_output_name = strdup(name)))
- CLEANUP_EDIE("strdup");
+ if (bar->xdg_output_name)
+ free(bar->xdg_output_name);
+ if (!(bar->xdg_output_name = strdup(name)))
+ EDIE("strdup");
}
static void
@@ -541,56 +557,215 @@ static const struct zxdg_output_v1_listener output_listener = {
};
static void
-show_bar(Bar *b)
+shell_command(char *command)
+{
+ if (fork() == 0) {
+ setsid();
+ execl("/bin/sh", "sh", "-c", command, NULL);
+ perror(" failed");
+ exit(EXIT_SUCCESS);
+ }
+}
+
+static void
+pointer_enter(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface,
+ wl_fixed_t surface_x, wl_fixed_t surface_y)
+{
+ Seat *seat = (Seat *)data;
+
+ Bar *bar;
+ DL_FOREACH(bar_list, bar)
+ if (bar->wl_surface == surface)
+ break;
+ seat->pointer_bar = bar;
+
+ if (!cursor_image) {
+ struct wl_cursor_theme *cursor_theme = wl_cursor_theme_load(NULL, 24, shm);
+ cursor_image = wl_cursor_theme_get_cursor(cursor_theme, "left_ptr")->images[0];
+ cursor_surface = wl_compositor_create_surface(compositor);
+ wl_surface_attach(cursor_surface, wl_cursor_image_get_buffer(cursor_image), 0, 0);
+ wl_surface_commit(cursor_surface);
+ }
+ wl_pointer_set_cursor(pointer, serial, cursor_surface,
+ cursor_image->hotspot_x,
+ cursor_image->hotspot_y);
+}
+
+static void
+pointer_leave(void *data, struct wl_pointer *pointer,
+ uint32_t serial, struct wl_surface *surface)
+{
+ Seat *seat = (Seat *)data;
+
+ seat->pointer_bar = NULL;
+}
+
+static void
+pointer_button(void *data, struct wl_pointer *pointer, uint32_t serial,
+ uint32_t time, uint32_t button, uint32_t state)
+{
+ Seat *seat = (Seat *)data;
+
+ seat->pointer_button = state == WL_POINTER_BUTTON_STATE_PRESSED ? button : 0;
+}
+
+static void
+pointer_motion(void *data, struct wl_pointer *pointer, uint32_t time,
+ wl_fixed_t surface_x, wl_fixed_t surface_y)
+{
+ Seat *seat = (Seat *)data;
+
+ seat->pointer_x = wl_fixed_to_int(surface_x);
+ seat->pointer_y = wl_fixed_to_int(surface_y);
+}
+
+static void
+pointer_frame(void *data, struct wl_pointer *pointer)
+{
+ Seat *seat = (Seat *)data;
+
+ if (!seat->pointer_button || !seat->pointer_bar)
+ return;
+
+ for (uint32_t i = 0; i < seat->pointer_bar->status_buttons_l; i++) {\
+ if (seat->pointer_button == seat->pointer_bar->status_buttons[i].button
+ && seat->pointer_x >= seat->pointer_bar->status_buttons[i].x1
+ && seat->pointer_x < seat->pointer_bar->status_buttons[i].x2) {
+ shell_command(seat->pointer_bar->status_buttons[i].command);
+ break;
+ }
+ }
+
+ seat->pointer_button = 0;
+}
+
+static void
+pointer_axis(void *data, struct wl_pointer *pointer,
+ uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+}
+
+static void
+pointer_axis_discrete(void *data, struct wl_pointer *pointer,
+ uint32_t axis, int32_t discrete)
+{
+}
+
+static void
+pointer_axis_source(void *data, struct wl_pointer *pointer,
+ uint32_t axis_source)
+{
+}
+
+static void
+pointer_axis_stop(void *data, struct wl_pointer *pointer,
+ uint32_t time, uint32_t axis)
+{
+}
+
+static void
+pointer_axis_value120(void *data, struct wl_pointer *pointer,
+ uint32_t axis, int32_t discrete)
+{
+}
+
+static const struct wl_pointer_listener pointer_listener = {
+ .axis = pointer_axis,
+ .axis_discrete = pointer_axis_discrete,
+ .axis_source = pointer_axis_source,
+ .axis_stop = pointer_axis_stop,
+ .axis_value120 = pointer_axis_value120,
+ .button = pointer_button,
+ .enter = pointer_enter,
+ .frame = pointer_frame,
+ .leave = pointer_leave,
+ .motion = pointer_motion,
+};
+
+static void
+seat_capabilities(void *data, struct wl_seat *wl_seat,
+ uint32_t capabilities)
+{
+ Seat *seat = (Seat *)data;
+
+ uint32_t has_pointer = capabilities & WL_SEAT_CAPABILITY_POINTER;
+ if (has_pointer && !seat->wl_pointer) {
+ seat->wl_pointer = wl_seat_get_pointer(seat->wl_seat);
+ wl_pointer_add_listener(seat->wl_pointer, &pointer_listener, seat);
+ } else if (!has_pointer && seat->wl_pointer) {
+ wl_pointer_destroy(seat->wl_pointer);
+ seat->wl_pointer = NULL;
+ }
+}
+
+static void
+seat_name(void *data, struct wl_seat *wl_seat, const char *name)
+{
+}
+
+static const struct wl_seat_listener seat_listener = {
+ .capabilities = seat_capabilities,
+ .name = seat_name,
+};
+
+static void
+show_bar(Bar *bar)
{
- b->wl_surface = wl_compositor_create_surface(compositor);
- if (!b->wl_surface)
- CLEANUP_DIE("Could not create wl_surface");
+ bar->wl_surface = wl_compositor_create_surface(compositor);
+ if (!bar->wl_surface)
+ DIE("Could not create wl_surface");
- b->layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, b->wl_surface, b->wl_output,
+ bar->layer_surface = zwlr_layer_shell_v1_get_layer_surface(layer_shell, bar->wl_surface, bar->wl_output,
ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, PROGRAM);
- if (!b->layer_surface)
- CLEANUP_DIE("Could not create layer_surface");
- zwlr_layer_surface_v1_add_listener(b->layer_surface, &layer_surface_listener, b);
+ if (!bar->layer_surface)
+ DIE("Could not create layer_surface");
+ zwlr_layer_surface_v1_add_listener(bar->layer_surface, &layer_surface_listener, bar);
- zwlr_layer_surface_v1_set_size(b->layer_surface, 0, b->height);
- zwlr_layer_surface_v1_set_anchor(b->layer_surface,
- (b->bottom ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)
+ zwlr_layer_surface_v1_set_size(bar->layer_surface, 0, bar->height);
+ zwlr_layer_surface_v1_set_anchor(bar->layer_surface,
+ (bar->bottom ? ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM : ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP)
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
- zwlr_layer_surface_v1_set_exclusive_zone(b->layer_surface, b->height);
- wl_surface_commit(b->wl_surface);
+ zwlr_layer_surface_v1_set_exclusive_zone(bar->layer_surface, bar->height);
+ wl_surface_commit(bar->wl_surface);
- b->hidden = false;
+ bar->hidden = false;
}
static void
-hide_bar(Bar *b)
+hide_bar(Bar *bar)
{
- zwlr_layer_surface_v1_destroy(b->layer_surface);
- wl_surface_destroy(b->wl_surface);
+ zwlr_layer_surface_v1_destroy(bar->layer_surface);
+ wl_surface_destroy(bar->wl_surface);
- b->configured = false;
- b->hidden = true;
+ bar->configured = false;
+ bar->hidden = true;
}
static void
-setup_bar(Bar *b)
+setup_bar(Bar *bar)
{
- b->height = height;
- b->textpadding = textpadding;
- b->bottom = bottom;
- b->hidden = hidden;
+ bar->height = height;
+ bar->textpadding = textpadding;
+ bar->bottom = bottom;
+ bar->hidden = hidden;
- snprintf(b->layout, sizeof b->layout, "[]=");
+ snprintf(bar->layout, sizeof bar->layout, "[]=");
- b->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, b->wl_output);
- if (!b->xdg_output)
- CLEANUP_DIE("Could not create xdg_output");
- zxdg_output_v1_add_listener(b->xdg_output, &output_listener, b);
+ bar->xdg_output = zxdg_output_manager_v1_get_xdg_output(output_manager, bar->wl_output);
+ if (!bar->xdg_output)
+ DIE("Could not create xdg_output");
+ zxdg_output_v1_add_listener(bar->xdg_output, &output_listener, bar);
- if (!b->hidden)
- show_bar(b);
+ if (!bar->hidden)
+ show_bar(bar);
+}
+
+static void
+setup_seat(Seat *seat)
+{
+ wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
}
static void
@@ -601,49 +776,81 @@ handle_global(void *data, struct wl_registry *registry,
compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4);
} else if (!strcmp(interface, wl_shm_interface.name)) {
shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
- } else if (!strcmp(interface, wl_output_interface.name)) {
- Bar *b = malloc(sizeof(Bar));
- if (!b)
- CLEANUP_EDIE("malloc");
- memset(b, 0, sizeof(Bar));
- b->registry_name = name;
- b->wl_output = wl_registry_bind(registry, name, &wl_output_interface, 1);
- DL_APPEND(bars, b);
- if (ready)
- setup_bar(b);
} else if (!strcmp(interface, zwlr_layer_shell_v1_interface.name)) {
layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
} else if (!strcmp(interface, zxdg_output_manager_v1_interface.name)) {
output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, 2);
+ } else if (!strcmp(interface, wl_output_interface.name)) {
+ Bar *bar = malloc(sizeof(Bar));
+ if (!bar)
+ EDIE("malloc");
+ memset(bar, 0, sizeof(Bar));
+ bar->registry_name = name;
+ bar->wl_output = wl_registry_bind(registry, name, &wl_output_interface, 1);
+ DL_APPEND(bar_list, bar);
+ if (ready)
+ setup_bar(bar);
+ } else if (!strcmp(interface, wl_seat_interface.name)) {
+ Seat *seat = malloc(sizeof(Seat));
+ if (!seat)
+ EDIE("malloc");
+ memset(seat, 0, sizeof(Seat));
+ seat->registry_name = name;
+ seat->wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, 7);
+ DL_APPEND(seat_list, seat);
+ setup_seat(seat);
}
}
static void
-teardown_bar(Bar *b)
+teardown_bar(Bar *bar)
{
- zxdg_output_v1_destroy(b->xdg_output);
- if (!b->hidden) {
- zwlr_layer_surface_v1_destroy(b->layer_surface);
- wl_surface_destroy(b->wl_surface);
+ zxdg_output_v1_destroy(bar->xdg_output);
+ if (!bar->hidden) {
+ zwlr_layer_surface_v1_destroy(bar->layer_surface);
+ wl_surface_destroy(bar->wl_surface);
}
- if (b->xdg_output_name)
- free(b->xdg_output_name);
- free(b);
+ if (bar->xdg_output_name)
+ free(bar->xdg_output_name);
+ if (bar->status_colors)
+ free(bar->status_colors);
+ if (bar->status_buttons)
+ free(bar->status_buttons);
+ free(bar);
+}
+
+static void
+teardown_seat(Seat *seat)
+{
+ wl_seat_destroy(seat->wl_seat);
+ free(seat);
}
static void
handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
{
- Bar *b;
- DL_FOREACH(bars, b)
- if (b->registry_name == name)
+ do {
+ Bar *bar;
+ DL_FOREACH(bar_list, bar)
+ if (bar->registry_name == name)
+ break;
+ if (!bar)
break;
-
- if (!b)
+ DL_DELETE(bar_list, bar);
+ teardown_bar(bar);
return;
-
- DL_DELETE(bars, b);
- teardown_bar(b);
+ } while(0);
+
+ do {
+ Seat *seat;
+ DL_FOREACH(seat_list, seat)
+ if (seat->registry_name == name)
+ break;
+ if (!seat)
+ break;
+ DL_DELETE(seat_list, seat);
+ teardown_seat(seat);
+ } while(0);
}
static const struct wl_registry_listener registry_listener = {
@@ -677,7 +884,7 @@ read_stdin(void)
if (rv == -1) {
if (errno == EWOULDBLOCK)
break;
- CLEANUP_EDIE("read");
+ EDIE("read");
}
if (rv == 0) {
run_display = 0;
@@ -686,7 +893,7 @@ read_stdin(void)
if ((len += rv) > stdinbuf_cap / 2)
if (!(stdinbuf = realloc(stdinbuf, (stdinbuf_cap *= 2))))
- CLEANUP_EDIE("realloc");
+ EDIE("realloc");
}
char *linebeg, *lineend;
@@ -700,12 +907,12 @@ read_stdin(void)
ADVANCE_IF_LAST_CONT();
- Bar *b;
- DL_FOREACH(bars, b)
- if (b->xdg_output_name)
- if (!strcmp(wordbeg, b->xdg_output_name))
+ Bar *bar;
+ DL_FOREACH(bar_list, bar)
+ if (bar->xdg_output_name)
+ if (!strcmp(wordbeg, bar->xdg_output_name))
break;
- if (!b)
+ if (!bar)
continue;
ADVANCE_IF_LAST_CONT();
@@ -713,66 +920,184 @@ read_stdin(void)
uint32_t val;
if (!strcmp(wordbeg, "tags")) {
ADVANCE_IF_LAST_CONT();
- if ((val = atoi(wordbeg)) != b->ctags) {
- b->ctags = val;
- b->redraw = true;
+ if ((val = atoi(wordbeg)) != bar->ctags) {
+ bar->ctags = val;
+ bar->redraw = true;
}
ADVANCE_IF_LAST_CONT();
- if ((val = atoi(wordbeg)) != b->mtags) {
- b->mtags = val;
- b->redraw = true;
+ if ((val = atoi(wordbeg)) != bar->mtags) {
+ bar->mtags = val;
+ bar->redraw = true;
}
ADVANCE_IF_LAST_CONT();
/* skip sel */
ADVANCE();
- if ((val = atoi(wordbeg)) != b->urg) {
- b->urg = val;
- b->redraw = true;
+ if ((val = atoi(wordbeg)) != bar->urg) {
+ bar->urg = val;
+ bar->redraw = true;
}
} else if (!strcmp(wordbeg, "layout")) {
- if (strcmp(b->layout, wordend) != 0) {
- snprintf(b->layout, sizeof b->layout, "%s", wordend);
- b->redraw = true;
+ if (strcmp(bar->layout, wordend) != 0) {
+ snprintf(bar->layout, sizeof bar->layout, "%s", wordend);
+ bar->redraw = true;
}
} else if (!strcmp(wordbeg, "title")) {
- if (strcmp(b->title, wordend) != 0) {
- snprintf(b->title, sizeof b->title, "%s", wordend);
- b->redraw = true;
+ if (strcmp(bar->title, wordend) != 0) {
+ snprintf(bar->title, sizeof bar->title, "%s", wordend);
+ bar->redraw = true;
}
} else if (!strcmp(wordbeg, "selmon")) {
ADVANCE();
- if ((val = atoi(wordbeg)) != b->selmon) {
- b->selmon = val;
- b->redraw = true;
+ if ((val = atoi(wordbeg)) != bar->selmon) {
+ bar->selmon = val;
+ bar->redraw = true;
}
}
}
}
static void
-bar_set_top(Bar *b)
+set_top(Bar *bar)
{
- if (!b->hidden) {
- zwlr_layer_surface_v1_set_anchor(b->layer_surface,
+ if (!bar->hidden) {
+ zwlr_layer_surface_v1_set_anchor(bar->layer_surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
- b->redraw = true;
+ bar->redraw = true;
}
- b->bottom = false;
+ bar->bottom = false;
}
static void
-bar_set_bottom(Bar *b)
+set_bottom(Bar *bar)
{
- if (!b->hidden) {
- zwlr_layer_surface_v1_set_anchor(b->layer_surface,
+ if (!bar->hidden) {
+ zwlr_layer_surface_v1_set_anchor(bar->layer_surface,
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM
| ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
| ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT);
- b->redraw = true;
+ bar->redraw = true;
}
- b->bottom = true;
+ bar->bottom = true;
+}
+
+/* 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 void
+set_status(Bar *bar, char *text)
+{
+ bar->status_colors_l = 0;
+ bar->status_buttons_l = 0;
+
+ size_t str_pos = 0;
+ uint32_t codepoint;
+ uint32_t state = UTF8_ACCEPT;
+
+ StatusButton *left_button = NULL;
+ StatusButton *middle_button = NULL;
+ StatusButton *right_button = NULL;
+
+ for (char *p = text; *p && str_pos < sizeof(bar->status) - 1; p++) {
+ if (state == UTF8_ACCEPT && *p == '^') {
+ p++;
+ if (*p != '^') {
+ char *arg, *end;
+ if (!(arg = strchr(p, '(')) || !(end = strchr(arg + 1, ')')))
+ continue;
+ *arg++ = '\0';
+ *end = '\0';
+
+ if (!strcmp(p, "bg")) {
+ StatusColor *status_color;
+ ARRAY_APPEND(bar->status_colors, bar->status_colors_l, bar->status_colors_c, status_color);
+ if (!*arg)
+ status_color->color = inactive_bg_color;
+ else
+ parse_color(arg, &status_color->color);
+ status_color->bg = true;
+ status_color->start = bar->status + str_pos;
+ } else if (!strcmp(p, "fg")) {
+ StatusColor *status_color;
+ ARRAY_APPEND(bar->status_colors, bar->status_colors_l, bar->status_colors_c, status_color);
+ if (!*arg)
+ status_color->color = inactive_fg_color;
+ else
+ parse_color(arg, &status_color->color);
+ status_color->bg = false;
+ status_color->start = bar->status + str_pos;
+ } else if (!strcmp(p, "lm")) {
+ if (left_button) {
+ left_button->end = bar->status + str_pos;
+ left_button = NULL;
+ } else if (*arg) {
+ ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, left_button);
+ left_button->button = BTN_LEFT;
+ snprintf(left_button->command, sizeof left_button->command, "%s", arg);
+ left_button->start = bar->status + str_pos;
+ }
+ } else if (!strcmp(p, "mm")) {
+ if (middle_button) {
+ middle_button->end = bar->status + str_pos;
+ middle_button = NULL;
+ } else if (*arg) {
+ ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, middle_button);
+ middle_button->button = BTN_MIDDLE;
+ snprintf(middle_button->command, sizeof middle_button->command, "%s", arg);
+ middle_button->start = bar->status + str_pos;
+ }
+ } else if (!strcmp(p, "rm")) {
+ if (right_button) {
+ right_button->end = bar->status + str_pos;
+ right_button = NULL;
+ } else if (*arg) {
+ ARRAY_APPEND(bar->status_buttons, bar->status_buttons_l, bar->status_buttons_c, right_button);
+ right_button->button = BTN_RIGHT;
+ snprintf(right_button->command, sizeof right_button->command, "%s", arg);
+ right_button->start = bar->status + str_pos;
+ }
+ }
+
+ *--arg = '(';
+ *end = ')';
+
+ p = end;
+ continue;
+ }
+ }
+
+ bar->status[str_pos++] = *p;
+ utf8decode(&state, &codepoint, *p);
+ }
+
+ bar->status[str_pos] = '\0';
}
static void
@@ -780,10 +1105,10 @@ read_socket(void)
{
int cli_fd;
if ((cli_fd = accept(sock_fd, NULL, 0)) == -1)
- CLEANUP_EDIE("accept");
+ EDIE("accept");
ssize_t len = recv(cli_fd, sockbuf, sizeof sockbuf - 1, 0);
if (len == -1)
- CLEANUP_EDIE("recv");
+ EDIE("recv");
close(cli_fd);
if (len == 0)
return;
@@ -795,25 +1120,25 @@ read_socket(void)
ADVANCE_IF_LAST_BREAK();
- Bar *b;
+ Bar *bar;
bool all = false;
if (!strcmp(wordbeg, "all")) {
all = true;
} else if (!strcmp(wordbeg, "selected")) {
- DL_FOREACH(bars, b)
- if (b->selmon)
+ DL_FOREACH(bar_list, bar)
+ if (bar->selmon)
break;
} else if (!strcmp(wordbeg, "first")) {
- b = bars;
+ bar = bar_list;
} else {
- DL_FOREACH(bars, b)
- if (b->xdg_output_name)
- if (!strcmp(wordbeg, b->xdg_output_name))
+ DL_FOREACH(bar_list, bar)
+ if (bar->xdg_output_name)
+ if (!strcmp(wordbeg, bar->xdg_output_name))
break;
}
- if (!all && !b)
+ if (!all && !bar)
break;
ADVANCE();
@@ -822,81 +1147,77 @@ read_socket(void)
if (!wordend)
break;
if (all) {
- DL_FOREACH(bars, b) {
- if (strcmp(b->status, wordend) != 0) {
- snprintf(b->status, sizeof b->status, "%s", wordend);
- b->redraw = true;
- }
+ DL_FOREACH(bar_list, bar) {
+ set_status(bar, wordend);
+ bar->redraw = true;
}
} else {
- if (strcmp(b->status, wordend) != 0) {
- snprintf(b->status, sizeof b->status, "%s", wordend);
- b->redraw = true;
- }
+ set_status(bar, wordend);
+ bar->redraw = true;
}
} else if (!strcmp(wordbeg, "show")) {
if (all) {
- DL_FOREACH(bars, b)
- if (b->hidden)
- show_bar(b);
+ DL_FOREACH(bar_list, bar)
+ if (bar->hidden)
+ show_bar(bar);
} else {
- if (b->hidden)
- show_bar(b);
+ if (bar->hidden)
+ show_bar(bar);
}
} else if (!strcmp(wordbeg, "hide")) {
if (all) {
- DL_FOREACH(bars, b)
- if (!b->hidden)
- hide_bar(b);
+ DL_FOREACH(bar_list, bar)
+ if (!bar->hidden)
+ hide_bar(bar);
} else {
- if (!b->hidden)
- hide_bar(b);
+ if (!bar->hidden)
+ hide_bar(bar);
}
} else if (!strcmp(wordbeg, "toggle-visibility")) {
if (all) {
- DL_FOREACH(bars, b)
- if (b->hidden)
- show_bar(b);
+ DL_FOREACH(bar_list, bar)
+ if (bar->hidden)
+ show_bar(bar);
else
- hide_bar(b);
+ hide_bar(bar);
} else {
- if (b->hidden)
- show_bar(b);
+ if (bar->hidden)
+ show_bar(bar);
else
- hide_bar(b);
+ hide_bar(bar);
}
} else if (!strcmp(wordbeg, "set-top")) {
if (all) {
- DL_FOREACH(bars, b)
- if (b->bottom)
- bar_set_top(b);
+ DL_FOREACH(bar_list, bar)
+ if (bar->bottom)
+ set_top(bar);
} else {
- if (b->bottom)
- bar_set_top(b);
+ if (bar->bottom)
+ set_top(bar);
}
} else if (!strcmp(wordbeg, "set-bottom")) {
if (all) {
- DL_FOREACH(bars, b)
- if (!b->bottom)
- bar_set_bottom(b);
+ DL_FOREACH(bar_list, bar)
+ if (!bar->bottom)
+ set_bottom(bar);
} else {
- if (!b->bottom)
- bar_set_bottom(b);
+ if (!bar->bottom)
+ set_bottom(bar);
}
} else if (!strcmp(wordbeg, "toggle-location")) {
if (all) {
- DL_FOREACH(bars, b)
- if (b->bottom)
- bar_set_top(b);
+ DL_FOREACH(bar_list, bar)
+ if (bar->bottom)
+ set_top(bar);
else
- bar_set_bottom(b);
+ set_bottom(bar);
} else {
- if (b->bottom)
- bar_set_top(b);
+ if (bar->bottom)
+ set_top(bar);
else
- bar_set_bottom(b);
+ set_bottom(bar);
}
}
} while (0);
@@ -910,32 +1231,31 @@ event_loop(void)
while (run_display) {
fd_set rfds;
FD_ZERO(&rfds);
+ FD_SET(wl_fd, &rfds);
FD_SET(STDIN_FILENO, &rfds);
FD_SET(sock_fd, &rfds);
- FD_SET(wl_fd, &rfds);
- /* Does this need to be inside the loop? */
wl_display_flush(display);
if (select(MAX(sock_fd, wl_fd) + 1, &rfds, NULL, NULL, NULL) == -1)
continue;
+ if (FD_ISSET(wl_fd, &rfds))
+ if (wl_display_dispatch(display) == -1)
+ break;
+
if (FD_ISSET(STDIN_FILENO, &rfds))
read_stdin();
if (FD_ISSET(sock_fd, &rfds))
read_socket();
-
- if (FD_ISSET(wl_fd, &rfds))
- if (wl_display_dispatch(display) == -1)
- break;
- Bar *b;
- DL_FOREACH(bars, b) {
- if (b->redraw) {
- if (!b->hidden)
- draw_frame(b);
- b->redraw = false;
+ Bar *bar;
+ DL_FOREACH(bar_list, bar) {
+ if (bar->redraw) {
+ if (!bar->hidden)
+ draw_frame(bar);
+ bar->redraw = false;
}
}
}
@@ -991,7 +1311,8 @@ main(int argc, char **argv)
{
char *xdgruntimedir;
struct sockaddr_un sock_address;
- Bar *b, *t;
+ Bar *bar, *bar2;
+ Seat *seat, *seat2;
/* Establish socket directory */
if (!(xdgruntimedir = getenv("XDG_RUNTIME_DIR")))
@@ -1131,8 +1452,8 @@ main(int argc, char **argv)
height = font->height + vertical_padding * 2;
/* Setup bars */
- DL_FOREACH(bars, b)
- setup_bar(b);
+ DL_FOREACH(bar_list, bar)
+ setup_bar(bar);
wl_display_roundtrip(display);
/* Configure stdin */
@@ -1157,16 +1478,17 @@ main(int argc, char **argv)
socketpath = (char *)&sock_address.sun_path;
unlink(socketpath);
if (bind(sock_fd, (struct sockaddr *) &sock_address, sizeof sock_address) == -1)
- CLEANUP_EDIE("bind");
+ EDIE("bind");
if (listen(sock_fd, SOMAXCONN) == -1)
- CLEANUP_EDIE("listen");
+ EDIE("listen");
fcntl(sock_fd, F_SETFD, FD_CLOEXEC | fcntl(sock_fd, F_GETFD));
/* Set up signals */
signal(SIGINT, sig_handler);
signal(SIGHUP, sig_handler);
signal(SIGTERM, sig_handler);
-
+ signal(SIGCHLD, SIG_IGN);
+
/* Run */
ready = true;
event_loop();
@@ -1178,8 +1500,10 @@ main(int argc, char **argv)
zwlr_layer_shell_v1_destroy(layer_shell);
zxdg_output_manager_v1_destroy(output_manager);
- DL_FOREACH_SAFE(bars, b, t)
- teardown_bar(b);
+ DL_FOREACH_SAFE(bar_list, bar, bar2)
+ teardown_bar(bar);
+ DL_FOREACH_SAFE(seat_list, seat, seat2)
+ teardown_seat(seat);
fcft_destroy(font);
fcft_fini();