Apply "clang-format" preferences globally

This commit is contained in:
Delgan 2024-04-07 10:05:10 +02:00
parent d841aeeecd
commit b85ba99980
64 changed files with 1868 additions and 2678 deletions

View file

@ -3,6 +3,7 @@ BasedOnStyle: GNU
IndentWidth: 4 IndentWidth: 4
--- ---
Language: Cpp Language: Cpp
Standard: Auto
PointerAlignment: Right PointerAlignment: Right
ColumnLimit: 120 ColumnLimit: 120
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
@ -15,3 +16,9 @@ BraceWrapping:
SpaceBeforeParens: ControlStatements SpaceBeforeParens: ControlStatements
Cpp11BracedListStyle: true Cpp11BracedListStyle: true
WhitespaceSensitiveMacros:
- REGISTER_CORE_PARTICLE
- REGISTER_CORE_DECORATION
- REGISTER_CORE_PLUGIN
- REGISTER_CORE_MODULE

View file

@ -7,10 +7,8 @@
struct backend { struct backend {
bool (*setup)(struct bar *bar); bool (*setup)(struct bar *bar);
void (*cleanup)(struct bar *bar); void (*cleanup)(struct bar *bar);
void (*loop)(struct bar *bar, void (*loop)(struct bar *bar, void (*expose)(const struct bar *bar),
void (*expose)(const struct bar *bar), void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y));
void (*on_mouse)(struct bar *bar, enum mouse_event event,
enum mouse_button btn, int x, int y));
void (*commit)(const struct bar *bar); void (*commit)(const struct bar *bar);
void (*refresh)(const struct bar *bar); void (*refresh)(const struct bar *bar);
void (*set_cursor)(struct bar *bar, const char *cursor); void (*set_cursor)(struct bar *bar, const char *cursor);

View file

@ -1,15 +1,15 @@
#include "bar.h" #include "bar.h"
#include "private.h" #include "private.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <threads.h>
#include <assert.h> #include <assert.h>
#include <unistd.h>
#include <pthread.h> #include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <unistd.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
@ -18,11 +18,11 @@
#include "../log.h" #include "../log.h"
#if defined(ENABLE_X11) #if defined(ENABLE_X11)
#include "xcb.h" #include "xcb.h"
#endif #endif
#if defined(ENABLE_WAYLAND) #if defined(ENABLE_WAYLAND)
#include "wayland.h" #include "wayland.h"
#endif #endif
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
@ -75,9 +75,8 @@ expose(const struct bar *_bar)
const struct private *bar = _bar->private; const struct private *bar = _bar->private;
pixman_image_t *pix = bar->pix; pixman_image_t *pix = bar->pix;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(PIXMAN_OP_SRC, pix, &bar->background, 1,
PIXMAN_OP_SRC, pix, &bar->background, 1, &(pixman_rectangle16_t){0, 0, bar->width, bar->height_with_border});
&(pixman_rectangle16_t){0, 0, bar->width, bar->height_with_border});
pixman_image_fill_rectangles( pixman_image_fill_rectangles(
PIXMAN_OP_OVER, pix, &bar->border.color, 4, PIXMAN_OP_OVER, pix, &bar->border.color, 4,
@ -86,20 +85,15 @@ expose(const struct bar *_bar)
{0, 0, bar->border.left_width, bar->height_with_border}, {0, 0, bar->border.left_width, bar->height_with_border},
/* Right */ /* Right */
{bar->width - bar->border.right_width, {bar->width - bar->border.right_width, 0, bar->border.right_width, bar->height_with_border},
0, bar->border.right_width, bar->height_with_border},
/* Top */ /* Top */
{bar->border.left_width, {bar->border.left_width, 0, bar->width - bar->border.left_width - bar->border.right_width,
0,
bar->width - bar->border.left_width - bar->border.right_width,
bar->border.top_width}, bar->border.top_width},
/* Bottom */ /* Bottom */
{bar->border.left_width, {bar->border.left_width, bar->height_with_border - bar->border.bottom_width,
bar->height_with_border - bar->border.bottom_width, bar->width - bar->border.left_width - bar->border.right_width, bar->border.bottom_width},
bar->width - bar->border.left_width - bar->border.right_width,
bar->border.bottom_width},
}); });
for (size_t i = 0; i < bar->left.count; i++) { for (size_t i = 0; i < bar->left.count; i++) {
@ -136,12 +130,8 @@ expose(const struct bar *_bar)
int x = bar->border.left_width + bar->left_margin - bar->left_spacing; int x = bar->border.left_width + bar->left_margin - bar->left_spacing;
pixman_region32_t clip; pixman_region32_t clip;
pixman_region32_init_rect( pixman_region32_init_rect(
&clip, &clip, bar->border.left_width + bar->left_margin, bar->border.top_width,
bar->border.left_width + bar->left_margin, (bar->width - bar->left_margin - bar->right_margin - bar->border.left_width - bar->border.right_width),
bar->border.top_width,
(bar->width -
bar->left_margin - bar->right_margin -
bar->border.left_width - bar->border.right_width),
bar->height); bar->height);
pixman_image_set_clip_region32(pix, &clip); pixman_image_set_clip_region32(pix, &clip);
pixman_region32_fini(&clip); pixman_region32_fini(&clip);
@ -161,11 +151,7 @@ expose(const struct bar *_bar)
x += bar->left_spacing + e->width + bar->right_spacing; x += bar->left_spacing + e->width + bar->right_spacing;
} }
x = bar->width - ( x = bar->width - (right_width + bar->left_spacing + bar->right_margin + bar->border.right_width);
right_width +
bar->left_spacing +
bar->right_margin +
bar->border.right_width);
for (size_t i = 0; i < bar->right.count; i++) { for (size_t i = 0; i < bar->right.count; i++) {
const struct exposable *e = bar->right.exps[i]; const struct exposable *e = bar->right.exps[i];
@ -177,7 +163,6 @@ expose(const struct bar *_bar)
bar->backend.iface->commit(_bar); bar->backend.iface->commit(_bar);
} }
static void static void
refresh(const struct bar *bar) refresh(const struct bar *bar)
{ {
@ -200,15 +185,12 @@ output_name(const struct bar *bar)
} }
static void static void
on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn, int x, int y)
int x, int y)
{ {
struct private *bar = _bar->private; struct private *bar = _bar->private;
if ((y < bar->border.top_width || if ((y < bar->border.top_width || y >= (bar->height_with_border - bar->border.bottom_width))
y >= (bar->height_with_border - bar->border.bottom_width)) || || (x < bar->border.left_width || x >= (bar->width - bar->border.right_width))) {
(x < bar->border.left_width || x >= (bar->width - bar->border.right_width)))
{
set_cursor(_bar, "left_ptr"); set_cursor(_bar, "left_ptr");
return; return;
} }
@ -250,10 +232,7 @@ on_mouse(struct bar *_bar, enum mouse_event event, enum mouse_button btn,
mx += e->width + bar->right_spacing; mx += e->width + bar->right_spacing;
} }
mx = bar->width - (right_width + mx = bar->width - (right_width + bar->left_spacing + bar->right_margin + bar->border.right_width);
bar->left_spacing +
bar->right_margin +
bar->border.right_width);
for (size_t i = 0; i < bar->right.count; i++) { for (size_t i = 0; i < bar->right.count; i++) {
struct exposable *e = bar->right.exps[i]; struct exposable *e = bar->right.exps[i];
@ -294,8 +273,7 @@ run(struct bar *_bar)
{ {
struct private *bar = _bar->private; struct private *bar = _bar->private;
bar->height_with_border = bar->height_with_border = bar->height + bar->border.top_width + bar->border.bottom_width;
bar->height + bar->border.top_width + bar->border.bottom_width;
if (!bar->backend.iface->setup(_bar)) { if (!bar->backend.iface->setup(_bar)) {
bar->backend.iface->cleanup(_bar); bar->backend.iface->cleanup(_bar);
@ -347,8 +325,7 @@ run(struct bar *_bar)
thrd_join(thrd_left[i], &mod_ret); thrd_join(thrd_left[i], &mod_ret);
if (mod_ret != 0) { if (mod_ret != 0) {
const struct module *m = bar->left.mods[i]; const struct module *m = bar->left.mods[i];
LOG_ERR("module: LEFT #%zu (%s): non-zero exit value: %d", LOG_ERR("module: LEFT #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret);
i, m->description(m), mod_ret);
} }
ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; ret = ret == 0 && mod_ret != 0 ? mod_ret : ret;
} }
@ -356,8 +333,7 @@ run(struct bar *_bar)
thrd_join(thrd_center[i], &mod_ret); thrd_join(thrd_center[i], &mod_ret);
if (mod_ret != 0) { if (mod_ret != 0) {
const struct module *m = bar->center.mods[i]; const struct module *m = bar->center.mods[i];
LOG_ERR("module: CENTER #%zu (%s): non-zero exit value: %d", LOG_ERR("module: CENTER #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret);
i, m->description(m), mod_ret);
} }
ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; ret = ret == 0 && mod_ret != 0 ? mod_ret : ret;
} }
@ -365,8 +341,7 @@ run(struct bar *_bar)
thrd_join(thrd_right[i], &mod_ret); thrd_join(thrd_right[i], &mod_ret);
if (mod_ret != 0) { if (mod_ret != 0) {
const struct module *m = bar->right.mods[i]; const struct module *m = bar->right.mods[i];
LOG_ERR("module: RIGHT #%zu (%s): non-zero exit value: %d", LOG_ERR("module: RIGHT #%zu (%s): non-zero exit value: %d", i, m->description(m), mod_ret);
i, m->description(m), mod_ret);
} }
ret = ret == 0 && mod_ret != 0 ? mod_ret : ret; ret = ret == 0 && mod_ret != 0 ? mod_ret : ret;
} }

View file

@ -3,7 +3,8 @@
#include "../bar/bar.h" #include "../bar/bar.h"
#include "backend.h" #include "backend.h"
struct private { struct private
{
/* From bar_config */ /* From bar_config */
char *monitor; char *monitor;
enum bar_layer layer; enum bar_layer layer;

View file

@ -1,25 +1,25 @@
#include "wayland.h" #include "wayland.h"
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <poll.h>
#include <pthread.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h> #include <fcntl.h>
#include <linux/input-event-codes.h> #include <linux/input-event-codes.h>
#include <sys/mman.h>
#include <pixman.h> #include <pixman.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <wayland-cursor.h> #include <wayland-cursor.h>
#include <tllist.h> #include <tllist.h>
#include <xdg-output-unstable-v1.h>
#include <wlr-layer-shell-unstable-v1.h> #include <wlr-layer-shell-unstable-v1.h>
#include <xdg-output-unstable-v1.h>
#define LOG_MODULE "bar:wayland" #define LOG_MODULE "bar:wayland"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
@ -29,7 +29,7 @@
#include "private.h" #include "private.h"
#if !defined(MFD_NOEXEC_SEAL) #if !defined(MFD_NOEXEC_SEAL)
#define MFD_NOEXEC_SEAL 0 #define MFD_NOEXEC_SEAL 0
#endif #endif
struct buffer { struct buffer {
@ -116,16 +116,15 @@ struct wayland_backend {
/* We're already waiting for a frame done callback */ /* We're already waiting for a frame done callback */
bool render_scheduled; bool render_scheduled;
tll(struct buffer) buffers; /* List of SHM buffers */ tll(struct buffer) buffers; /* List of SHM buffers */
struct buffer *next_buffer; /* Bar is rendering to this one */ struct buffer *next_buffer; /* Bar is rendering to this one */
struct buffer *pending_buffer; /* Finished, but not yet rendered */ struct buffer *pending_buffer; /* Finished, but not yet rendered */
struct wl_callback *frame_callback; struct wl_callback *frame_callback;
double aggregated_scroll; double aggregated_scroll;
bool have_discrete; bool have_discrete;
void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, void (*bar_on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y);
enum mouse_button btn, int x, int y);
}; };
static void static void
@ -157,7 +156,7 @@ bar_backend_wayland_new(void)
static void static void
shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
{ {
//printf("SHM format: 0x%08x\n", format); // printf("SHM format: 0x%08x\n", format);
} }
static const struct wl_shm_listener shm_listener = { static const struct wl_shm_listener shm_listener = {
@ -167,10 +166,7 @@ static const struct wl_shm_listener shm_listener = {
static void static void
update_cursor_surface(struct wayland_backend *backend, struct seat *seat) update_cursor_surface(struct wayland_backend *backend, struct seat *seat)
{ {
if (seat->pointer.serial == 0 || if (seat->pointer.serial == 0 || seat->pointer.cursor == NULL || seat->pointer.surface == NULL) {
seat->pointer.cursor == NULL ||
seat->pointer.surface == NULL)
{
return; return;
} }
@ -179,17 +175,12 @@ update_cursor_surface(struct wayland_backend *backend, struct seat *seat)
const int scale = seat->pointer.scale; const int scale = seat->pointer.scale;
wl_surface_set_buffer_scale(seat->pointer.surface, scale); wl_surface_set_buffer_scale(seat->pointer.surface, scale);
wl_surface_attach( wl_surface_attach(seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0);
seat->pointer.surface, wl_cursor_image_get_buffer(image), 0, 0);
wl_pointer_set_cursor( wl_pointer_set_cursor(seat->wl_pointer, seat->pointer.serial, seat->pointer.surface, image->hotspot_x / scale,
seat->wl_pointer, seat->pointer.serial, image->hotspot_y / scale);
seat->pointer.surface,
image->hotspot_x / scale, image->hotspot_y / scale);
wl_surface_damage_buffer(seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_damage_buffer(
seat->pointer.surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(seat->pointer.surface); wl_surface_commit(seat->pointer.surface);
wl_display_flush(backend->display); wl_display_flush(backend->display);
@ -219,11 +210,9 @@ reload_cursor_theme(struct seat *seat, int new_scale)
} }
} }
LOG_INFO("%s: cursor theme: %s, size: %u, scale: %d", LOG_INFO("%s: cursor theme: %s, size: %u, scale: %d", seat->name, cursor_theme, cursor_size, new_scale);
seat->name, cursor_theme, cursor_size, new_scale);
struct wl_cursor_theme *theme = wl_cursor_theme_load( struct wl_cursor_theme *theme = wl_cursor_theme_load(cursor_theme, cursor_size * new_scale, seat->backend->shm);
cursor_theme, cursor_size * new_scale, seat->backend->shm);
if (theme == NULL) { if (theme == NULL) {
LOG_ERR("%s: failed to load cursor theme", seat->name); LOG_ERR("%s: failed to load cursor theme", seat->name);
@ -235,8 +224,7 @@ reload_cursor_theme(struct seat *seat, int new_scale)
} }
static void static void
wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface,
uint32_t serial, struct wl_surface *surface,
wl_fixed_t surface_x, wl_fixed_t surface_y) wl_fixed_t surface_x, wl_fixed_t surface_y)
{ {
struct seat *seat = data; struct seat *seat = data;
@ -252,8 +240,7 @@ wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
} }
static void static void
wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface)
uint32_t serial, struct wl_surface *surface)
{ {
struct seat *seat = data; struct seat *seat = data;
struct wayland_backend *backend = seat->backend; struct wayland_backend *backend = seat->backend;
@ -265,8 +252,7 @@ wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
} }
static void static void
wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{ {
struct seat *seat = data; struct seat *seat = data;
struct wayland_backend *backend = seat->backend; struct wayland_backend *backend = seat->backend;
@ -275,14 +261,12 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer,
seat->pointer.y = wl_fixed_to_int(surface_y) * backend->scale; seat->pointer.y = wl_fixed_to_int(surface_y) * backend->scale;
backend->active_seat = seat; backend->active_seat = seat;
backend->bar_on_mouse( backend->bar_on_mouse(backend->bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE, seat->pointer.x, seat->pointer.y);
backend->bar, ON_MOUSE_MOTION, MOUSE_BTN_NONE,
seat->pointer.x, seat->pointer.y);
} }
static void static void
wl_pointer_button(void *data, struct wl_pointer *wl_pointer, wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button,
uint32_t serial, uint32_t time, uint32_t button, uint32_t state) uint32_t state)
{ {
struct seat *seat = data; struct seat *seat = data;
struct wayland_backend *backend = seat->backend; struct wayland_backend *backend = seat->backend;
@ -293,23 +277,31 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer,
enum mouse_button btn; enum mouse_button btn;
switch (button) { switch (button) {
case BTN_LEFT: btn = MOUSE_BTN_LEFT; break; case BTN_LEFT:
case BTN_MIDDLE: btn = MOUSE_BTN_MIDDLE; break; btn = MOUSE_BTN_LEFT;
case BTN_RIGHT: btn = MOUSE_BTN_RIGHT; break; break;
case BTN_SIDE: btn = MOUSE_BTN_PREVIOUS; break; case BTN_MIDDLE:
case BTN_EXTRA: btn = MOUSE_BTN_NEXT; break; btn = MOUSE_BTN_MIDDLE;
break;
case BTN_RIGHT:
btn = MOUSE_BTN_RIGHT;
break;
case BTN_SIDE:
btn = MOUSE_BTN_PREVIOUS;
break;
case BTN_EXTRA:
btn = MOUSE_BTN_NEXT;
break;
default: default:
return; return;
} }
backend->bar_on_mouse( backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y);
backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y);
} }
} }
static void static void
wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
uint32_t time, uint32_t axis, wl_fixed_t value)
{ {
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
return; return;
@ -325,24 +317,18 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer,
const double amount = wl_fixed_to_double(value); const double amount = wl_fixed_to_double(value);
if ((backend->aggregated_scroll > 0 && amount < 0) || if ((backend->aggregated_scroll > 0 && amount < 0) || (backend->aggregated_scroll < 0 && amount > 0)) {
(backend->aggregated_scroll < 0 && amount > 0))
{
backend->aggregated_scroll = amount; backend->aggregated_scroll = amount;
} else } else
backend->aggregated_scroll += amount; backend->aggregated_scroll += amount;
enum mouse_button btn = backend->aggregated_scroll > 0 enum mouse_button btn = backend->aggregated_scroll > 0 ? MOUSE_BTN_WHEEL_DOWN : MOUSE_BTN_WHEEL_UP;
? MOUSE_BTN_WHEEL_DOWN
: MOUSE_BTN_WHEEL_UP;
const double step = bar->trackpad_sensitivity; const double step = bar->trackpad_sensitivity;
const double adjust = backend->aggregated_scroll > 0 ? -step : step; const double adjust = backend->aggregated_scroll > 0 ? -step : step;
while (fabs(backend->aggregated_scroll) >= step) { while (fabs(backend->aggregated_scroll) >= step) {
backend->bar_on_mouse( backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y);
backend->bar, ON_MOUSE_CLICK, btn,
seat->pointer.x, seat->pointer.y);
backend->aggregated_scroll += adjust; backend->aggregated_scroll += adjust;
} }
} }
@ -356,14 +342,12 @@ wl_pointer_frame(void *data, struct wl_pointer *wl_pointer)
} }
static void static void
wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, uint32_t axis_source)
uint32_t axis_source)
{ {
} }
static void static void
wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis)
uint32_t time, uint32_t axis)
{ {
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
return; return;
@ -374,8 +358,7 @@ wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer,
} }
static void static void
wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, uint32_t axis, int32_t discrete)
uint32_t axis, int32_t discrete)
{ {
if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL)
return; return;
@ -384,16 +367,12 @@ wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer,
struct wayland_backend *backend = seat->backend; struct wayland_backend *backend = seat->backend;
backend->have_discrete = true; backend->have_discrete = true;
enum mouse_button btn = discrete > 0 enum mouse_button btn = discrete > 0 ? MOUSE_BTN_WHEEL_DOWN : MOUSE_BTN_WHEEL_UP;
? MOUSE_BTN_WHEEL_DOWN
: MOUSE_BTN_WHEEL_UP;
int count = abs(discrete); int count = abs(discrete);
for (int32_t i = 0; i < count; i++) { for (int32_t i = 0; i < count; i++) {
backend->bar_on_mouse( backend->bar_on_mouse(backend->bar, ON_MOUSE_CLICK, btn, seat->pointer.x, seat->pointer.y);
backend->bar, ON_MOUSE_CLICK, btn,
seat->pointer.x, seat->pointer.y);
} }
} }
@ -410,16 +389,14 @@ static const struct wl_pointer_listener pointer_listener = {
}; };
static void static void
seat_handle_capabilities(void *data, struct wl_seat *wl_seat, seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps)
enum wl_seat_capability caps)
{ {
struct seat *seat = data; struct seat *seat = data;
if (caps & WL_SEAT_CAPABILITY_POINTER) { if (caps & WL_SEAT_CAPABILITY_POINTER) {
if (seat->wl_pointer == NULL) { if (seat->wl_pointer == NULL) {
assert(seat->pointer.surface == NULL); assert(seat->pointer.surface == NULL);
seat->pointer.surface = wl_compositor_create_surface( seat->pointer.surface = wl_compositor_create_surface(seat->backend->compositor);
seat->backend->compositor);
if (seat->pointer.surface == NULL) { if (seat->pointer.surface == NULL) {
LOG_ERR("%s: failed to create pointer surface", seat->name); LOG_ERR("%s: failed to create pointer surface", seat->name);
@ -459,10 +436,8 @@ static const struct wl_seat_listener seat_listener = {
}; };
static void static void
output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width,
int32_t physical_width, int32_t physical_height, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform)
int32_t subpixel, const char *make, const char *model,
int32_t transform)
{ {
struct monitor *mon = data; struct monitor *mon = data;
mon->width_mm = physical_width; mon->width_mm = physical_width;
@ -470,8 +445,7 @@ output_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y,
} }
static void static void
output_mode(void *data, struct wl_output *wl_output, uint32_t flags, output_mode(void *data, struct wl_output *wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
int32_t width, int32_t height, int32_t refresh)
{ {
} }
@ -516,8 +490,7 @@ output_name(void *data, struct wl_output *wl_output, const char *name)
#if defined(WL_OUTPUT_DESCRIPTION_SINCE_VERSION) #if defined(WL_OUTPUT_DESCRIPTION_SINCE_VERSION)
static void static void
output_description(void *data, struct wl_output *wl_output, output_description(void *data, struct wl_output *wl_output, const char *description)
const char *description)
{ {
} }
#endif #endif
@ -536,9 +509,7 @@ static const struct wl_output_listener output_listener = {
}; };
static void static void
xdg_output_handle_logical_position(void *data, xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y)
struct zxdg_output_v1 *xdg_output,
int32_t x, int32_t y)
{ {
struct monitor *mon = data; struct monitor *mon = data;
mon->x = x; mon->x = x;
@ -546,8 +517,7 @@ xdg_output_handle_logical_position(void *data,
} }
static void static void
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height)
int32_t width, int32_t height)
{ {
struct monitor *mon = data; struct monitor *mon = data;
mon->width_px = width; mon->width_px = width;
@ -562,9 +532,8 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
{ {
const struct monitor *mon = data; const struct monitor *mon = data;
LOG_INFO("monitor: %s: %dx%d+%d+%d (%dx%dmm)", LOG_INFO("monitor: %s: %dx%d+%d+%d (%dx%dmm)", mon->name, mon->width_px, mon->height_px, mon->x, mon->y,
mon->name, mon->width_px, mon->height_px, mon->width_mm, mon->height_mm);
mon->x, mon->y, mon->width_mm, mon->height_mm);
struct wayland_backend *backend = mon->backend; struct wayland_backend *backend = mon->backend;
struct private *bar = backend->bar->private; struct private *bar = backend->bar->private;
@ -576,15 +545,11 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
return; return;
} }
const bool output_is_our_configured_monitor = ( const bool output_is_our_configured_monitor
bar->monitor != NULL && = (bar->monitor != NULL && mon->name != NULL && strcmp(bar->monitor, mon->name) == 0);
mon->name != NULL &&
strcmp(bar->monitor, mon->name) == 0);
const bool output_is_last_mapped = ( const bool output_is_last_mapped = (backend->last_mapped_monitor != NULL && mon->name != NULL
backend->last_mapped_monitor != NULL && && strcmp(backend->last_mapped_monitor, mon->name) == 0);
mon->name != NULL &&
strcmp(backend->last_mapped_monitor, mon->name) == 0);
if (output_is_our_configured_monitor) if (output_is_our_configured_monitor)
LOG_DBG("%s: using this monitor (user configured)", mon->name); LOG_DBG("%s: using this monitor (user configured)", mon->name);
@ -606,8 +571,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
} }
static void static void
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name)
const char *name)
{ {
struct monitor *mon = data; struct monitor *mon = data;
free(mon->name); free(mon->name);
@ -615,8 +579,7 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
} }
static void static void
xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description)
const char *description)
{ {
} }
@ -634,14 +597,12 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted)
if (version >= wanted) if (version >= wanted)
return true; return true;
LOG_ERR("%s: need interface version %u, but compositor only implements %u", LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version);
iface, wanted, version);
return false; return false;
} }
static void static void
handle_global(void *data, struct wl_registry *registry, handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
uint32_t name, const char *interface, uint32_t version)
{ {
LOG_DBG("global: 0x%08x, interface=%s, version=%u", name, interface, version); LOG_DBG("global: 0x%08x, interface=%s, version=%u", name, interface, version);
struct wayland_backend *backend = data; struct wayland_backend *backend = data;
@ -651,8 +612,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
backend->compositor = wl_registry_bind( backend->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, required);
registry, name, &wl_compositor_interface, required);
} }
else if (strcmp(interface, wl_shm_interface.name) == 0) { else if (strcmp(interface, wl_shm_interface.name) == 0) {
@ -660,8 +620,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
backend->shm = wl_registry_bind( backend->shm = wl_registry_bind(registry, name, &wl_shm_interface, required);
registry, name, &wl_shm_interface, required);
wl_shm_add_listener(backend->shm, &shm_listener, backend); wl_shm_add_listener(backend->shm, &shm_listener, backend);
} }
@ -670,13 +629,9 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
struct wl_output *output = wl_registry_bind( struct wl_output *output = wl_registry_bind(registry, name, &wl_output_interface, required);
registry, name, &wl_output_interface, required);
tll_push_back(backend->monitors, ((struct monitor){ tll_push_back(backend->monitors, ((struct monitor){.backend = backend, .wl_name = name, .output = output}));
.backend = backend,
.wl_name = name,
.output = output}));
struct monitor *mon = &tll_back(backend->monitors); struct monitor *mon = &tll_back(backend->monitors);
wl_output_add_listener(output, &output_listener, mon); wl_output_add_listener(output, &output_listener, mon);
@ -689,8 +644,7 @@ handle_global(void *data, struct wl_registry *registry,
assert(backend->xdg_output_manager != NULL); assert(backend->xdg_output_manager != NULL);
if (backend->xdg_output_manager != NULL) { if (backend->xdg_output_manager != NULL) {
mon->xdg = zxdg_output_manager_v1_get_xdg_output( mon->xdg = zxdg_output_manager_v1_get_xdg_output(backend->xdg_output_manager, mon->output);
backend->xdg_output_manager, mon->output);
zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon); zxdg_output_v1_add_listener(mon->xdg, &xdg_output_listener, mon);
} }
@ -701,8 +655,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
backend->layer_shell = wl_registry_bind( backend->layer_shell = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, required);
registry, name, &zwlr_layer_shell_v1_interface, required);
} }
else if (strcmp(interface, wl_seat_interface.name) == 0) { else if (strcmp(interface, wl_seat_interface.name) == 0) {
@ -710,12 +663,10 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
struct wl_seat *seat = wl_registry_bind( struct wl_seat *seat = wl_registry_bind(registry, name, &wl_seat_interface, required);
registry, name, &wl_seat_interface, required);
assert(seat != NULL); assert(seat != NULL);
tll_push_back( tll_push_back(backend->seats, ((struct seat){.backend = backend, .seat = seat, .id = name}));
backend->seats, ((struct seat){.backend = backend, .seat = seat, .id = name}));
wl_seat_add_listener(seat, &seat_listener, &tll_back(backend->seats)); wl_seat_add_listener(seat, &seat_listener, &tll_back(backend->seats));
} }
@ -725,8 +676,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
backend->xdg_output_manager = wl_registry_bind( backend->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required);
registry, name, &zxdg_output_manager_v1_interface, required);
} }
} }
@ -735,7 +685,8 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
{ {
struct wayland_backend *backend = data; struct wayland_backend *backend = data;
tll_foreach(backend->seats, it) { tll_foreach(backend->seats, it)
{
if (it->item.id == name) { if (it->item.id == name) {
if (backend->active_seat == &it->item) if (backend->active_seat == &it->item)
backend->active_seat = NULL; backend->active_seat = NULL;
@ -745,7 +696,8 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
} }
} }
tll_foreach(backend->monitors, it) { tll_foreach(backend->monitors, it)
{
struct monitor *mon = &it->item; struct monitor *mon = &it->item;
if (mon->wl_name == name) { if (mon->wl_name == name) {
LOG_INFO("%s disconnected/disabled", mon->name); LOG_INFO("%s disconnected/disabled", mon->name);
@ -770,8 +722,7 @@ static const struct wl_registry_listener registry_listener = {
}; };
static void static void
layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h)
uint32_t serial, uint32_t w, uint32_t h)
{ {
struct wayland_backend *backend = data; struct wayland_backend *backend = data;
backend->width = w * backend->scale; backend->width = w * backend->scale;
@ -814,7 +765,6 @@ create_surface(struct wayland_backend *backend)
wl_surface_add_listener(backend->surface, &surface_listener, backend); wl_surface_add_listener(backend->surface, &surface_listener, backend);
enum zwlr_layer_shell_v1_layer layer; enum zwlr_layer_shell_v1_layer layer;
switch (bar->layer) { switch (bar->layer) {
@ -836,28 +786,22 @@ create_surface(struct wayland_backend *backend)
} }
backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface( backend->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
backend->layer_shell, backend->surface, backend->layer_shell, backend->surface, backend->monitor != NULL ? backend->monitor->output : NULL, layer,
backend->monitor != NULL ? backend->monitor->output : NULL, "panel");
layer, "panel");
if (backend->layer_surface == NULL) { if (backend->layer_surface == NULL) {
LOG_ERR("failed to create layer shell surface"); LOG_ERR("failed to create layer shell surface");
return false; return false;
} }
zwlr_layer_surface_v1_add_listener( zwlr_layer_surface_v1_add_listener(backend->layer_surface, &layer_surface_listener, backend);
backend->layer_surface, &layer_surface_listener, backend);
/* Aligned to top, maximum width */ /* Aligned to top, maximum width */
enum zwlr_layer_surface_v1_anchor top_or_bottom = bar->location == BAR_TOP enum zwlr_layer_surface_v1_anchor top_or_bottom
? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP = bar->location == BAR_TOP ? ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP : ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
: ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM;
zwlr_layer_surface_v1_set_anchor( zwlr_layer_surface_v1_set_anchor(backend->layer_surface, ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT
backend->layer_surface, | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT | top_or_bottom);
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
top_or_bottom);
return true; return true;
} }
@ -890,7 +834,7 @@ destroy_surface(struct wayland_backend *backend)
static void static void
buffer_release(void *data, struct wl_buffer *wl_buffer) buffer_release(void *data, struct wl_buffer *wl_buffer)
{ {
//printf("buffer release\n"); // printf("buffer release\n");
struct buffer *buffer = data; struct buffer *buffer = data;
assert(buffer->busy); assert(buffer->busy);
buffer->busy = false; buffer->busy = false;
@ -903,7 +847,8 @@ static const struct wl_buffer_listener buffer_listener = {
static struct buffer * static struct buffer *
get_buffer(struct wayland_backend *backend) get_buffer(struct wayland_backend *backend)
{ {
tll_foreach(backend->buffers, it) { tll_foreach(backend->buffers, it)
{
if (!it->item.busy && it->item.width == backend->width && it->item.height == backend->height) { if (!it->item.busy && it->item.width == backend->width && it->item.height == backend->height) {
it->item.busy = true; it->item.busy = true;
return &it->item; return &it->item;
@ -936,13 +881,10 @@ get_buffer(struct wayland_backend *backend)
* *with* it, and if that fails, try again *without* it. * *with* it, and if that fails, try again *without* it.
*/ */
errno = 0; errno = 0;
pool_fd = memfd_create( pool_fd = memfd_create("yambar-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL);
"yambar-wayland-shm-buffer-pool",
MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL);
if (pool_fd < 0 && errno == EINVAL) { if (pool_fd < 0 && errno == EINVAL) {
pool_fd = memfd_create( pool_fd = memfd_create("yambar-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
"yambar-wayland-shm-buffer-pool", MFD_CLOEXEC | MFD_ALLOW_SEALING);
} }
#elif defined(__FreeBSD__) #elif defined(__FreeBSD__)
// memfd_create on FreeBSD 13 is SHM_ANON without sealing support // memfd_create on FreeBSD 13 is SHM_ANON without sealing support
@ -958,8 +900,7 @@ get_buffer(struct wayland_backend *backend)
} }
/* Total size */ /* Total size */
const uint32_t stride = stride_for_format_and_width( const uint32_t stride = stride_for_format_and_width(PIXMAN_a8r8g8b8, backend->width);
PIXMAN_a8r8g8b8, backend->width);
size = stride * backend->height; size = stride * backend->height;
if (ftruncate(pool_fd, size) == -1) { if (ftruncate(pool_fd, size) == -1) {
@ -976,9 +917,7 @@ get_buffer(struct wayland_backend *backend)
#if defined(MEMFD_CREATE) #if defined(MEMFD_CREATE)
/* Seal file - we no longer allow any kind of resizing */ /* Seal file - we no longer allow any kind of resizing */
/* TODO: wayland mmaps(PROT_WRITE), for some unknown reason, hence we cannot use F_SEAL_FUTURE_WRITE */ /* TODO: wayland mmaps(PROT_WRITE), for some unknown reason, hence we cannot use F_SEAL_FUTURE_WRITE */
if (fcntl(pool_fd, F_ADD_SEALS, if (fcntl(pool_fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0) {
F_SEAL_GROW | F_SEAL_SHRINK | /*F_SEAL_FUTURE_WRITE |*/ F_SEAL_SEAL) < 0)
{
LOG_ERRNO("failed to seal SHM backing memory file"); LOG_ERRNO("failed to seal SHM backing memory file");
/* This is not a fatal error */ /* This is not a fatal error */
} }
@ -990,37 +929,35 @@ get_buffer(struct wayland_backend *backend)
goto err; goto err;
} }
buf = wl_shm_pool_create_buffer( buf = wl_shm_pool_create_buffer(pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888);
pool, 0, backend->width, backend->height, stride, WL_SHM_FORMAT_ARGB8888);
if (buf == NULL) { if (buf == NULL) {
LOG_ERR("failed to create SHM buffer"); LOG_ERR("failed to create SHM buffer");
goto err; goto err;
} }
/* We use the entire pool for our single buffer */ /* We use the entire pool for our single buffer */
wl_shm_pool_destroy(pool); pool = NULL; wl_shm_pool_destroy(pool);
close(pool_fd); pool_fd = -1; pool = NULL;
close(pool_fd);
pool_fd = -1;
pix = pixman_image_create_bits_no_clear( pix = pixman_image_create_bits_no_clear(PIXMAN_a8r8g8b8, backend->width, backend->height, (uint32_t *)mmapped,
PIXMAN_a8r8g8b8, backend->width, backend->height, (uint32_t *)mmapped, stride); stride);
if (pix == NULL) { if (pix == NULL) {
LOG_ERR("failed to create pixman image"); LOG_ERR("failed to create pixman image");
goto err; goto err;
} }
/* Push to list of available buffers, but marked as 'busy' */ /* Push to list of available buffers, but marked as 'busy' */
tll_push_back( tll_push_back(backend->buffers, ((struct buffer){
backend->buffers, .busy = true,
((struct buffer){ .width = backend->width,
.busy = true, .height = backend->height,
.width = backend->width, .size = size,
.height = backend->height, .mmapped = mmapped,
.size = size, .wl_buf = buf,
.mmapped = mmapped, .pix = pix,
.wl_buf = buf, }));
.pix = pix,
})
);
struct buffer *ret = &tll_back(backend->buffers); struct buffer *ret = &tll_back(backend->buffers);
wl_buffer_add_listener(ret->wl_buf, &buffer_listener, ret); wl_buffer_add_listener(ret->wl_buf, &buffer_listener, ret);
@ -1050,7 +987,8 @@ guess_scale(const struct wayland_backend *backend)
bool all_have_same_scale = true; bool all_have_same_scale = true;
int last_scale = -1; int last_scale = -1;
tll_foreach(backend->monitors, it) { tll_foreach(backend->monitors, it)
{
if (last_scale == -1) if (last_scale == -1)
last_scale = it->item.scale; last_scale = it->item.scale;
else if (last_scale != it->item.scale) { else if (last_scale != it->item.scale) {
@ -1086,29 +1024,21 @@ update_size(struct wayland_backend *backend)
bar->height = height - bar->border.top_width - bar->border.bottom_width; bar->height = height - bar->border.top_width - bar->border.bottom_width;
bar->height_with_border = height; bar->height_with_border = height;
zwlr_layer_surface_v1_set_size( zwlr_layer_surface_v1_set_size(backend->layer_surface, 0, bar->height_with_border / scale);
backend->layer_surface, 0, bar->height_with_border / scale);
zwlr_layer_surface_v1_set_exclusive_zone( zwlr_layer_surface_v1_set_exclusive_zone(
backend->layer_surface, backend->layer_surface,
(bar->height_with_border + (bar->location == BAR_TOP (bar->height_with_border + (bar->location == BAR_TOP ? bar->border.bottom_margin : bar->border.top_margin))
? bar->border.bottom_margin / scale);
: bar->border.top_margin))
/ scale);
zwlr_layer_surface_v1_set_margin( zwlr_layer_surface_v1_set_margin(backend->layer_surface, bar->border.top_margin / scale,
backend->layer_surface, bar->border.right_margin / scale, bar->border.bottom_margin / scale,
bar->border.top_margin / scale, bar->border.left_margin / scale);
bar->border.right_margin / scale,
bar->border.bottom_margin / scale,
bar->border.left_margin / scale
);
/* Trigger a 'configure' event, after which we'll have the width */ /* Trigger a 'configure' event, after which we'll have the width */
wl_surface_commit(backend->surface); wl_surface_commit(backend->surface);
wl_display_roundtrip(backend->display); wl_display_roundtrip(backend->display);
if (backend->width == -1 || if (backend->width == -1 || backend->height != bar->height_with_border) {
backend->height != bar->height_with_border) {
LOG_ERR("failed to get panel width"); LOG_ERR("failed to get panel width");
return false; return false;
} }
@ -1178,8 +1108,7 @@ setup(struct bar *_bar)
return false; return false;
} }
assert(backend->monitor == NULL || assert(backend->monitor == NULL || backend->width / backend->monitor->scale <= backend->monitor->width_px);
backend->width / backend->monitor->scale <= backend->monitor->width_px);
if (pipe2(backend->pipe_fds, O_CLOEXEC | O_NONBLOCK) == -1) { if (pipe2(backend->pipe_fds, O_CLOEXEC | O_NONBLOCK) == -1) {
LOG_ERRNO("failed to create pipe"); LOG_ERRNO("failed to create pipe");
@ -1201,7 +1130,8 @@ cleanup(struct bar *_bar)
if (backend->pipe_fds[1] >= 0) if (backend->pipe_fds[1] >= 0)
close(backend->pipe_fds[1]); close(backend->pipe_fds[1]);
tll_foreach(backend->monitors, it) { tll_foreach(backend->monitors, it)
{
struct monitor *mon = &it->item; struct monitor *mon = &it->item;
free(mon->name); free(mon->name);
@ -1216,13 +1146,13 @@ cleanup(struct bar *_bar)
if (backend->xdg_output_manager != NULL) if (backend->xdg_output_manager != NULL)
zxdg_output_manager_v1_destroy(backend->xdg_output_manager); zxdg_output_manager_v1_destroy(backend->xdg_output_manager);
tll_foreach(backend->seats, it) tll_foreach(backend->seats, it) seat_destroy(&it->item);
seat_destroy(&it->item);
tll_free(backend->seats); tll_free(backend->seats);
destroy_surface(backend); destroy_surface(backend);
tll_foreach(backend->buffers, it) { tll_foreach(backend->buffers, it)
{
if (it->item.wl_buf != NULL) if (it->item.wl_buf != NULL)
wl_buffer_destroy(it->item.wl_buf); wl_buffer_destroy(it->item.wl_buf);
if (it->item.pix != NULL) if (it->item.pix != NULL)
@ -1247,14 +1177,11 @@ cleanup(struct bar *_bar)
/* Destroyed when freeing buffer list */ /* Destroyed when freeing buffer list */
bar->pix = NULL; bar->pix = NULL;
} }
static void static void
loop(struct bar *_bar, loop(struct bar *_bar, void (*expose)(const struct bar *bar),
void (*expose)(const struct bar *bar), void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y))
void (*on_mouse)(struct bar *bar, enum mouse_event event,
enum mouse_button btn, int x, int y))
{ {
struct private *bar = _bar->private; struct private *bar = _bar->private;
struct wayland_backend *backend = bar->backend.data; struct wayland_backend *backend = bar->backend.data;
@ -1341,25 +1268,23 @@ out:
if (!send_abort_to_modules) if (!send_abort_to_modules)
return; return;
if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) {
!= sizeof(uint64_t))
{
LOG_ERRNO("failed to signal abort to modules"); LOG_ERRNO("failed to signal abort to modules");
} }
//wl_display_cancel_read(backend->display); // wl_display_cancel_read(backend->display);
} }
static void static void
surface_enter(void *data, struct wl_surface *wl_surface, surface_enter(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct wayland_backend *backend = data; struct wayland_backend *backend = data;
free(backend->last_mapped_monitor); free(backend->last_mapped_monitor);
backend->last_mapped_monitor = NULL; backend->last_mapped_monitor = NULL;
tll_foreach(backend->monitors, it) { tll_foreach(backend->monitors, it)
{
struct monitor *mon = &it->item; struct monitor *mon = &it->item;
if (mon->output != wl_output) if (mon->output != wl_output)
@ -1379,8 +1304,7 @@ surface_enter(void *data, struct wl_surface *wl_surface,
} }
static void static void
surface_leave(void *data, struct wl_surface *wl_surface, surface_leave(void *data, struct wl_surface *wl_surface, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct wayland_backend *backend = data; struct wayland_backend *backend = data;
const struct monitor *mon = backend->monitor; const struct monitor *mon = backend->monitor;
@ -1399,8 +1323,7 @@ static const struct wl_surface_listener surface_listener = {
.leave = &surface_leave, .leave = &surface_leave,
}; };
static void frame_callback( static void frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data);
void *data, struct wl_callback *wl_callback, uint32_t callback_data);
static const struct wl_callback_listener frame_listener = { static const struct wl_callback_listener frame_listener = {
.done = &frame_callback, .done = &frame_callback,
@ -1409,7 +1332,7 @@ static const struct wl_callback_listener frame_listener = {
static void static void
frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data) frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_data)
{ {
//printf("frame callback\n"); // printf("frame callback\n");
struct private *bar = data; struct private *bar = data;
struct wayland_backend *backend = bar->backend.data; struct wayland_backend *backend = bar->backend.data;
@ -1436,7 +1359,7 @@ frame_callback(void *data, struct wl_callback *wl_callback, uint32_t callback_da
backend->pending_buffer = NULL; backend->pending_buffer = NULL;
backend->render_scheduled = true; backend->render_scheduled = true;
} else } else
;//printf("nothing more to do\n"); ; // printf("nothing more to do\n");
} }
static void static void
@ -1445,7 +1368,7 @@ commit(const struct bar *_bar)
struct private *bar = _bar->private; struct private *bar = _bar->private;
struct wayland_backend *backend = bar->backend.data; struct wayland_backend *backend = bar->backend.data;
//printf("commit: %dxl%d\n", backend->width, backend->height); // printf("commit: %dxl%d\n", backend->width, backend->height);
if (backend->next_buffer == NULL) if (backend->next_buffer == NULL)
return; return;
@ -1454,7 +1377,7 @@ commit(const struct bar *_bar)
assert(backend->next_buffer->busy); assert(backend->next_buffer->busy);
if (backend->render_scheduled) { if (backend->render_scheduled) {
//printf("already scheduled\n"); // printf("already scheduled\n");
if (backend->pending_buffer != NULL) if (backend->pending_buffer != NULL)
backend->pending_buffer->busy = false; backend->pending_buffer->busy = false;
@ -1463,7 +1386,7 @@ commit(const struct bar *_bar)
backend->next_buffer = NULL; backend->next_buffer = NULL;
} else { } else {
//printf("scheduling new frame callback\n"); // printf("scheduling new frame callback\n");
struct buffer *buffer = backend->next_buffer; struct buffer *buffer = backend->next_buffer;
assert(buffer->busy); assert(buffer->busy);
@ -1491,9 +1414,7 @@ refresh(const struct bar *_bar)
const struct private *bar = _bar->private; const struct private *bar = _bar->private;
const struct wayland_backend *backend = bar->backend.data; const struct wayland_backend *backend = bar->backend.data;
if (write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)) if (write(backend->pipe_fds[1], &(uint8_t){1}, sizeof(uint8_t)) != sizeof(uint8_t)) {
!= sizeof(uint8_t))
{
LOG_ERRNO("failed to signal 'refresh' to main thread"); LOG_ERRNO("failed to signal 'refresh' to main thread");
} }
} }
@ -1513,8 +1434,7 @@ set_cursor(struct bar *_bar, const char *cursor)
seat->pointer.xcursor = cursor; seat->pointer.xcursor = cursor;
seat->pointer.cursor = wl_cursor_theme_get_cursor( seat->pointer.cursor = wl_cursor_theme_get_cursor(seat->pointer.theme, cursor);
seat->pointer.theme, cursor);
if (seat->pointer.cursor == NULL) { if (seat->pointer.cursor == NULL) {
LOG_ERR("%s: failed to load cursor '%s'", seat->name, cursor); LOG_ERR("%s: failed to load cursor '%s'", seat->name, cursor);

208
bar/xcb.c
View file

@ -1,16 +1,16 @@
#include "xcb.h" #include "xcb.h"
#include <string.h>
#include <assert.h> #include <assert.h>
#include <string.h>
#include <unistd.h>
#include <poll.h> #include <poll.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h>
#include <pixman.h> #include <pixman.h>
#include <xcb/xcb.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/render.h> #include <xcb/render.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_cursor.h> #include <xcb/xcb_cursor.h>
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
@ -39,7 +39,6 @@ struct xcb_backend {
void *client_pixmap; void *client_pixmap;
size_t client_pixmap_size; size_t client_pixmap_size;
pixman_image_t *pix; pixman_image_t *pix;
}; };
void * void *
@ -55,11 +54,8 @@ setup(struct bar *_bar)
struct private *bar = _bar->private; struct private *bar = _bar->private;
struct xcb_backend *backend = bar->backend.data; struct xcb_backend *backend = bar->backend.data;
if (bar->border.left_margin != 0 || if (bar->border.left_margin != 0 || bar->border.right_margin != 0 || bar->border.top_margin != 0
bar->border.right_margin != 0 || || bar->border.bottom_margin) {
bar->border.top_margin != 0 ||
bar->border.bottom_margin)
{
LOG_WARN("non-zero border margins ignored in X11 backend"); LOG_WARN("non-zero border margins ignored in X11 backend");
} }
@ -76,10 +72,8 @@ setup(struct bar *_bar)
xcb_screen_t *screen = xcb_aux_get_screen(backend->conn, default_screen); xcb_screen_t *screen = xcb_aux_get_screen(backend->conn, default_screen);
xcb_randr_get_monitors_reply_t *monitors = xcb_randr_get_monitors_reply( xcb_randr_get_monitors_reply_t *monitors
backend->conn, = xcb_randr_get_monitors_reply(backend->conn, xcb_randr_get_monitors(backend->conn, screen->root, 0), &e);
xcb_randr_get_monitors(backend->conn, screen->root, 0),
&e);
if (e != NULL) { if (e != NULL) {
LOG_ERR("failed to get monitor list: %s", xcb_error(e)); LOG_ERR("failed to get monitor list: %s", xcb_error(e));
@ -90,17 +84,13 @@ setup(struct bar *_bar)
/* Find monitor coordinates and width/height */ /* Find monitor coordinates and width/height */
bool found_monitor = false; bool found_monitor = false;
for (xcb_randr_monitor_info_iterator_t it = for (xcb_randr_monitor_info_iterator_t it = xcb_randr_get_monitors_monitors_iterator(monitors); it.rem > 0;
xcb_randr_get_monitors_monitors_iterator(monitors); xcb_randr_monitor_info_next(&it)) {
it.rem > 0;
xcb_randr_monitor_info_next(&it))
{
const xcb_randr_monitor_info_t *mon = it.data; const xcb_randr_monitor_info_t *mon = it.data;
char *name = get_atom_name(backend->conn, mon->name); char *name = get_atom_name(backend->conn, mon->name);
LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, LOG_INFO("monitor: %s: %ux%u+%u+%u (%ux%umm)", name, mon->width, mon->height, mon->x, mon->y,
mon->width, mon->height, mon->x, mon->y, mon->width_in_millimeters, mon->height_in_millimeters);
mon->width_in_millimeters, mon->height_in_millimeters);
/* User wants a specific monitor, and this is not the one */ /* User wants a specific monitor, and this is not the one */
if (bar->monitor != NULL && strcmp(bar->monitor, name) != 0) { if (bar->monitor != NULL && strcmp(bar->monitor, name) != 0) {
@ -111,14 +101,11 @@ setup(struct bar *_bar)
backend->x = mon->x; backend->x = mon->x;
backend->y = mon->y; backend->y = mon->y;
bar->width = mon->width; bar->width = mon->width;
backend->y += bar->location == BAR_TOP ? 0 backend->y += bar->location == BAR_TOP ? 0 : screen->height_in_pixels - bar->height_with_border;
: screen->height_in_pixels - bar->height_with_border;
found_monitor = true; found_monitor = true;
if ((bar->monitor != NULL && strcmp(bar->monitor, name) == 0) || if ((bar->monitor != NULL && strcmp(bar->monitor, name) == 0) || (bar->monitor == NULL && mon->primary)) {
(bar->monitor == NULL && mon->primary))
{
/* Exact match */ /* Exact match */
free(name); free(name);
break; break;
@ -155,61 +142,34 @@ setup(struct bar *_bar)
LOG_DBG("using a %hhu-bit visual", depth); LOG_DBG("using a %hhu-bit visual", depth);
backend->colormap = xcb_generate_id(backend->conn); backend->colormap = xcb_generate_id(backend->conn);
xcb_create_colormap( xcb_create_colormap(backend->conn, 0, backend->colormap, screen->root, vis->visual_id);
backend->conn, 0, backend->colormap, screen->root, vis->visual_id);
backend->win = xcb_generate_id(backend->conn); backend->win = xcb_generate_id(backend->conn);
xcb_create_window( xcb_create_window(
backend->conn, backend->conn, depth, backend->win, screen->root, backend->x, backend->y, bar->width, bar->height_with_border,
depth, backend->win, screen->root, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id,
backend->x, backend->y, bar->width, bar->height_with_border, (XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_EVENT_MASK | XCB_CW_COLORMAP),
0, (const uint32_t[]){screen->black_pixel, screen->white_pixel,
XCB_WINDOW_CLASS_INPUT_OUTPUT, vis->visual_id, (XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS
(XCB_CW_BACK_PIXEL | | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_STRUCTURE_NOTIFY),
XCB_CW_BORDER_PIXEL | backend->colormap});
XCB_CW_EVENT_MASK |
XCB_CW_COLORMAP),
(const uint32_t []){
screen->black_pixel,
screen->white_pixel,
(XCB_EVENT_MASK_EXPOSURE |
XCB_EVENT_MASK_BUTTON_RELEASE |
XCB_EVENT_MASK_BUTTON_PRESS |
XCB_EVENT_MASK_POINTER_MOTION |
XCB_EVENT_MASK_STRUCTURE_NOTIFY),
backend->colormap}
);
const char *title = "yambar"; const char *title = "yambar";
xcb_change_property( xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
backend->conn, strlen(title), title);
XCB_PROP_MODE_REPLACE, backend->win,
XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8,
strlen(title), title);
xcb_change_property( xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1,
backend->conn, (const uint32_t[]){getpid()});
XCB_PROP_MODE_REPLACE, backend->win, xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, 1,
_NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){getpid()}); (const uint32_t[]){_NET_WM_WINDOW_TYPE_DOCK});
xcb_change_property( xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STATE, XCB_ATOM_ATOM, 32, 2,
backend->conn, (const uint32_t[]){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY});
XCB_PROP_MODE_REPLACE, backend->win, xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1,
_NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, (const uint32_t[]){0xffffffff});
1, (const uint32_t []){_NET_WM_WINDOW_TYPE_DOCK});
xcb_change_property(
backend->conn,
XCB_PROP_MODE_REPLACE, backend->win,
_NET_WM_STATE, XCB_ATOM_ATOM, 32,
2, (const uint32_t []){_NET_WM_STATE_ABOVE, _NET_WM_STATE_STICKY});
xcb_change_property(
backend->conn,
XCB_PROP_MODE_REPLACE, backend->win,
_NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, (const uint32_t []){0xffffffff});
/* Always on top */ /* Always on top */
xcb_configure_window( xcb_configure_window(backend->conn, backend->win, XCB_CONFIG_WINDOW_STACK_MODE,
backend->conn, backend->win, XCB_CONFIG_WINDOW_STACK_MODE, (const uint32_t[]){XCB_STACK_MODE_ABOVE});
(const uint32_t []){XCB_STACK_MODE_ABOVE});
uint32_t top_strut, bottom_strut; uint32_t top_strut, bottom_strut;
uint32_t top_pair[2], bottom_pair[2]; uint32_t top_pair[2], bottom_pair[2];
@ -232,42 +192,38 @@ setup(struct bar *_bar)
uint32_t strut[] = { uint32_t strut[] = {
/* left/right/top/bottom */ /* left/right/top/bottom */
0, 0, 0,
0,
top_strut, top_strut,
bottom_strut, bottom_strut,
/* start/end pairs for left/right/top/bottom */ /* start/end pairs for left/right/top/bottom */
0, 0, 0,
0, 0, 0,
top_pair[0], top_pair[1], 0,
bottom_pair[0], bottom_pair[1], 0,
top_pair[0],
top_pair[1],
bottom_pair[0],
bottom_pair[1],
}; };
xcb_change_property( xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STRUT, XCB_ATOM_CARDINAL, 32, 4,
backend->conn, strut);
XCB_PROP_MODE_REPLACE, backend->win,
_NET_WM_STRUT, XCB_ATOM_CARDINAL, 32,
4, strut);
xcb_change_property( xcb_change_property(backend->conn, XCB_PROP_MODE_REPLACE, backend->win, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL,
backend->conn, 32, 12, strut);
XCB_PROP_MODE_REPLACE, backend->win,
_NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32,
12, strut);
backend->gc = xcb_generate_id(backend->conn); backend->gc = xcb_generate_id(backend->conn);
xcb_create_gc(backend->conn, backend->gc, backend->win, xcb_create_gc(backend->conn, backend->gc, backend->win, XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES,
XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES, (const uint32_t[]){screen->white_pixel, 0});
(const uint32_t []){screen->white_pixel, 0});
const uint32_t stride = stride_for_format_and_width( const uint32_t stride = stride_for_format_and_width(PIXMAN_a8r8g8b8, bar->width);
PIXMAN_a8r8g8b8, bar->width);
backend->client_pixmap_size = stride * bar->height_with_border; backend->client_pixmap_size = stride * bar->height_with_border;
backend->client_pixmap = malloc(backend->client_pixmap_size); backend->client_pixmap = malloc(backend->client_pixmap_size);
backend->pix = pixman_image_create_bits_no_clear( backend->pix = pixman_image_create_bits_no_clear(PIXMAN_a8r8g8b8, bar->width, bar->height_with_border,
PIXMAN_a8r8g8b8, bar->width, bar->height_with_border, (uint32_t *)backend->client_pixmap, stride);
(uint32_t *)backend->client_pixmap, stride);
bar->pix = backend->pix; bar->pix = backend->pix;
xcb_map_window(backend->conn, backend->win); xcb_map_window(backend->conn, backend->win);
@ -310,10 +266,8 @@ cleanup(struct bar *_bar)
} }
static void static void
loop(struct bar *_bar, loop(struct bar *_bar, void (*expose)(const struct bar *bar),
void (*expose)(const struct bar *bar), void (*on_mouse)(struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y))
void (*on_mouse)(struct bar *bar, enum mouse_event event,
enum mouse_button btn, int x, int y))
{ {
struct private *bar = _bar->private; struct private *bar = _bar->private;
struct xcb_backend *backend = bar->backend.data; struct xcb_backend *backend = bar->backend.data;
@ -323,10 +277,7 @@ loop(struct bar *_bar,
const int fd = xcb_get_file_descriptor(backend->conn); const int fd = xcb_get_file_descriptor(backend->conn);
while (true) { while (true) {
struct pollfd fds[] = { struct pollfd fds[] = {{.fd = _bar->abort_fd, .events = POLLIN}, {.fd = fd, .events = POLLIN}};
{.fd = _bar->abort_fd, .events = POLLIN},
{.fd = fd, .events = POLLIN}
};
poll(fds, sizeof(fds) / sizeof(fds[0]), -1); poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
@ -335,18 +286,14 @@ loop(struct bar *_bar,
if (fds[1].revents & POLLHUP) { if (fds[1].revents & POLLHUP) {
LOG_WARN("disconnected from XCB"); LOG_WARN("disconnected from XCB");
if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) if (write(_bar->abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) {
!= sizeof(uint64_t))
{
LOG_ERRNO("failed to signal abort to modules"); LOG_ERRNO("failed to signal abort to modules");
} }
break; break;
} }
for (xcb_generic_event_t *e = xcb_wait_for_event(backend->conn); for (xcb_generic_event_t *e = xcb_wait_for_event(backend->conn); e != NULL;
e != NULL; e = xcb_poll_for_event(backend->conn)) {
e = xcb_poll_for_event(backend->conn))
{
switch (XCB_EVENT_RESPONSE_TYPE(e)) { switch (XCB_EVENT_RESPONSE_TYPE(e)) {
case 0: case 0:
LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)e)); LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)e));
@ -369,9 +316,12 @@ loop(struct bar *_bar,
const xcb_button_release_event_t *evt = (void *)e; const xcb_button_release_event_t *evt = (void *)e;
switch (evt->detail) { switch (evt->detail) {
case 1: case 2: case 3: case 4: case 5: case 1:
on_mouse(_bar, ON_MOUSE_CLICK, case 2:
evt->detail, evt->event_x, evt->event_y); case 3:
case 4:
case 5:
on_mouse(_bar, ON_MOUSE_CLICK, evt->detail, evt->event_x, evt->event_y);
break; break;
} }
break; break;
@ -405,10 +355,9 @@ commit(const struct bar *_bar)
const struct private *bar = _bar->private; const struct private *bar = _bar->private;
const struct xcb_backend *backend = bar->backend.data; const struct xcb_backend *backend = bar->backend.data;
xcb_put_image( xcb_put_image(backend->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, backend->win, backend->gc, bar->width,
backend->conn, XCB_IMAGE_FORMAT_Z_PIXMAP, backend->win, backend->gc, bar->height_with_border, 0, 0, 0, backend->depth, backend->client_pixmap_size,
bar->width, bar->height_with_border, 0, 0, 0, backend->client_pixmap);
backend->depth, backend->client_pixmap_size, backend->client_pixmap);
xcb_flush(backend->conn); xcb_flush(backend->conn);
} }
@ -424,19 +373,15 @@ refresh(const struct bar *_bar)
* the size of the event structure */ * the size of the event structure */
xcb_expose_event_t *evt = calloc(32, 1); xcb_expose_event_t *evt = calloc(32, 1);
*evt = (xcb_expose_event_t){ *evt = (xcb_expose_event_t){.response_type = XCB_EXPOSE,
.response_type = XCB_EXPOSE, .window = backend->win,
.window = backend->win, .x = 0,
.x = 0, .y = 0,
.y = 0, .width = bar->width,
.width = bar->width, .height = bar->height,
.height = bar->height, .count = 1};
.count = 1
};
xcb_send_event( xcb_send_event(backend->conn, false, backend->win, XCB_EVENT_MASK_EXPOSURE, (char *)evt);
backend->conn, false, backend->win, XCB_EVENT_MASK_EXPOSURE,
(char *)evt);
xcb_flush(backend->conn); xcb_flush(backend->conn);
free(evt); free(evt);
@ -458,8 +403,7 @@ set_cursor(struct bar *_bar, const char *cursor)
xcb_free_cursor(backend->conn, backend->cursor); xcb_free_cursor(backend->conn, backend->cursor);
backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor); backend->cursor = xcb_cursor_load_cursor(backend->cursor_ctx, cursor);
xcb_change_window_attributes( xcb_change_window_attributes(backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor);
backend->conn, backend->win, XCB_CW_CURSOR, &backend->cursor);
} }
static const char * static const char *

View file

@ -1,15 +1,15 @@
#include "char32.h" #include "char32.h"
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <wchar.h> #include <wchar.h>
#if defined __has_include #if defined __has_include
#if __has_include (<stdc-predef.h>) #if __has_include(<stdc-predef.h>)
#include <stdc-predef.h> #include <stdc-predef.h>
#endif #endif
#endif #endif
#define LOG_MODULE "char32" #define LOG_MODULE "char32"
@ -24,14 +24,13 @@
* - both use the same encoding (though we require that encoding to be UTF-32) * - both use the same encoding (though we require that encoding to be UTF-32)
*/ */
_Static_assert( _Static_assert(sizeof(wchar_t) == sizeof(char32_t), "wchar_t vs. char32_t size mismatch");
sizeof(wchar_t) == sizeof(char32_t), "wchar_t vs. char32_t size mismatch");
#if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__ #if !defined(__STDC_UTF_32__) || !__STDC_UTF_32__
#error "char32_t does not use UTF-32" #error "char32_t does not use UTF-32"
#endif #endif
#if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__) #if (!defined(__STDC_ISO_10646__) || !__STDC_ISO_10646__) && !defined(__FreeBSD__)
#error "wchar_t does not use UTF-32" #error "wchar_t does not use UTF-32"
#endif #endif
size_t size_t

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <uchar.h>
#include <stddef.h> #include <stddef.h>
#include <uchar.h>
size_t c32len(const char32_t *s); size_t c32len(const char32_t *s);
char32_t *ambstoc32(const char *src); char32_t *ambstoc32(const char *src);

View file

@ -1,7 +1,7 @@
#include "config.h" #include "config.h"
#include <string.h>
#include <assert.h> #include <assert.h>
#include <string.h>
#include <tllist.h> #include <tllist.h>
@ -16,11 +16,9 @@ conf_err_prefix(const keychain_t *chain, const struct yml_node *node)
static char msg[4096]; static char msg[4096];
int idx = 0; int idx = 0;
idx += snprintf(&msg[idx], sizeof(msg) - idx, "%zu:%zu: ", idx += snprintf(&msg[idx], sizeof(msg) - idx, "%zu:%zu: ", yml_source_line(node), yml_source_column(node));
yml_source_line(node), yml_source_column(node));
tll_foreach(*chain, key) tll_foreach(*chain, key) idx += snprintf(&msg[idx], sizeof(msg) - idx, "%s.", key->item);
idx += snprintf(&msg[idx], sizeof(msg) - idx, "%s.", key->item);
/* Remove trailing "." */ /* Remove trailing "." */
msg[idx - 1] = '\0'; msg[idx - 1] = '\0';
@ -45,8 +43,7 @@ conf_verify_int(keychain_t *chain, const struct yml_node *node)
if (yml_value_is_int(node)) if (yml_value_is_int(node))
return true; return true;
LOG_ERR("%s: value is not an integer: '%s'", LOG_ERR("%s: value is not an integer: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node));
conf_err_prefix(chain, node), yml_value_as_string(node));
return false; return false;
} }
@ -56,8 +53,7 @@ conf_verify_unsigned(keychain_t *chain, const struct yml_node *node)
if (yml_value_is_int(node) && yml_value_as_int(node) >= 0) if (yml_value_is_int(node) && yml_value_as_int(node) >= 0)
return true; return true;
LOG_ERR("%s: value is not a positive integer: '%s'", LOG_ERR("%s: value is not a positive integer: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node));
conf_err_prefix(chain, node), yml_value_as_string(node));
return false; return false;
} }
@ -67,8 +63,7 @@ conf_verify_bool(keychain_t *chain, const struct yml_node *node)
if (yml_value_is_bool(node)) if (yml_value_is_bool(node))
return true; return true;
LOG_ERR("%s: value is not a boolean: '%s'", LOG_ERR("%s: value is not a boolean: '%s'", conf_err_prefix(chain, node), yml_value_as_string(node));
conf_err_prefix(chain, node), yml_value_as_string(node));
return false; return false;
} }
@ -81,10 +76,7 @@ conf_verify_list(keychain_t *chain, const struct yml_node *node,
return false; return false;
} }
for (struct yml_list_iter iter = yml_list_iter(node); for (struct yml_list_iter iter = yml_list_iter(node); iter.node != NULL; yml_list_next(&iter)) {
iter.node != NULL;
yml_list_next(&iter))
{
if (!verify(chain, iter.node)) if (!verify(chain, iter.node))
return false; return false;
} }
@ -93,8 +85,7 @@ conf_verify_list(keychain_t *chain, const struct yml_node *node,
} }
bool bool
conf_verify_enum(keychain_t *chain, const struct yml_node *node, conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *values[], size_t count)
const char *values[], size_t count)
{ {
const char *s = yml_value_as_string(node); const char *s = yml_value_as_string(node);
if (s == NULL) { if (s == NULL) {
@ -115,8 +106,7 @@ conf_verify_enum(keychain_t *chain, const struct yml_node *node,
} }
bool bool
conf_verify_dict(keychain_t *chain, const struct yml_node *node, conf_verify_dict(keychain_t *chain, const struct yml_node *node, const struct attr_info info[])
const struct attr_info info[])
{ {
if (!yml_is_dict(node)) { if (!yml_is_dict(node)) {
LOG_ERR("%s: must be a dictionary", conf_err_prefix(chain, node)); LOG_ERR("%s: must be a dictionary", conf_err_prefix(chain, node));
@ -131,10 +121,7 @@ conf_verify_dict(keychain_t *chain, const struct yml_node *node,
bool exists[count]; bool exists[count];
memset(exists, 0, sizeof(exists)); memset(exists, 0, sizeof(exists));
for (struct yml_dict_iter it = yml_dict_iter(node); for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) {
it.key != NULL;
yml_dict_next(&it))
{
const char *key = yml_value_as_string(it.key); const char *key = yml_value_as_string(it.key);
if (key == NULL) { if (key == NULL) {
LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key)); LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key));
@ -190,8 +177,7 @@ verify_on_click_path(keychain_t *chain, const struct yml_node *node)
const bool is_tilde = path[0] == '~' && path[1] == '/'; const bool is_tilde = path[0] == '~' && path[1] == '/';
if (!is_absolute && !is_tilde) { if (!is_absolute && !is_tilde) {
LOG_ERR("%s: path must be either absolute, or begin with '~/", LOG_ERR("%s: path must be either absolute, or begin with '~/", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
@ -208,14 +194,10 @@ conf_verify_on_click(keychain_t *chain, const struct yml_node *node)
return verify_on_click_path(chain, node); return verify_on_click_path(chain, node);
static const struct attr_info info[] = { static const struct attr_info info[] = {
{"left", false, &verify_on_click_path}, {"left", false, &verify_on_click_path}, {"middle", false, &verify_on_click_path},
{"middle", false, &verify_on_click_path}, {"right", false, &verify_on_click_path}, {"wheel-up", false, &verify_on_click_path},
{"right", false, &verify_on_click_path}, {"wheel-down", false, &verify_on_click_path}, {"previous", false, &verify_on_click_path},
{"wheel-up", false, &verify_on_click_path}, {"next", false, &verify_on_click_path}, {NULL, false, NULL},
{"wheel-down", false, &verify_on_click_path},
{"previous", false, &verify_on_click_path},
{"next", false, &verify_on_click_path},
{NULL, false, NULL},
}; };
return conf_verify_dict(chain, node, info); return conf_verify_dict(chain, node, info);
@ -234,21 +216,18 @@ conf_verify_color(keychain_t *chain, const struct yml_node *node)
int v = sscanf(s, "%02x%02x%02x%02x", &r, &g, &b, &a); int v = sscanf(s, "%02x%02x%02x%02x", &r, &g, &b, &a);
if (strlen(s) != 8 || v != 4) { if (strlen(s) != 8 || v != 4) {
LOG_ERR("%s: value must be a color ('rrggbbaa', e.g ff00ffff)", LOG_ERR("%s: value must be a color ('rrggbbaa', e.g ff00ffff)", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
return true; return true;
} }
bool bool
conf_verify_font(keychain_t *chain, const struct yml_node *node) conf_verify_font(keychain_t *chain, const struct yml_node *node)
{ {
if (!yml_is_scalar(node)) { if (!yml_is_scalar(node)) {
LOG_ERR("%s: font must be a fontconfig-formatted string", LOG_ERR("%s: font must be a fontconfig-formatted string", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
@ -258,8 +237,7 @@ conf_verify_font(keychain_t *chain, const struct yml_node *node)
bool bool
conf_verify_font_shaping(keychain_t *chain, const struct yml_node *node) conf_verify_font_shaping(keychain_t *chain, const struct yml_node *node)
{ {
return conf_verify_enum( return conf_verify_enum(chain, node, (const char *[]){"full", /*"graphemes",*/ "none"}, 2);
chain, node, (const char *[]){"full", /*"graphemes",*/ "none"}, 2);
} }
bool bool
@ -269,7 +247,8 @@ conf_verify_decoration(keychain_t *chain, const struct yml_node *node)
if (yml_dict_length(node) != 1) { if (yml_dict_length(node) != 1) {
LOG_ERR("%s: decoration must be a dictionary with a single key; " LOG_ERR("%s: decoration must be a dictionary with a single key; "
"the name of the particle", conf_err_prefix(chain, node)); "the name of the particle",
conf_err_prefix(chain, node));
return false; return false;
} }
@ -285,8 +264,7 @@ conf_verify_decoration(keychain_t *chain, const struct yml_node *node)
const struct deco_iface *iface = plugin_load_deco(deco_name); const struct deco_iface *iface = plugin_load_deco(deco_name);
if (iface == NULL) { if (iface == NULL) {
LOG_ERR("%s: invalid decoration name: %s", LOG_ERR("%s: invalid decoration name: %s", conf_err_prefix(chain, deco), deco_name);
conf_err_prefix(chain, deco), deco_name);
return false; return false;
} }
@ -303,10 +281,7 @@ conf_verify_particle_list_items(keychain_t *chain, const struct yml_node *node)
{ {
assert(yml_is_list(node)); assert(yml_is_list(node));
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) {
it.node != NULL;
yml_list_next(&it))
{
if (!conf_verify_particle(chain, it.node)) if (!conf_verify_particle(chain, it.node))
return false; return false;
} }
@ -321,7 +296,8 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node)
if (yml_dict_length(node) != 1) { if (yml_dict_length(node) != 1) {
LOG_ERR("%s: particle must be a dictionary with a single key; " LOG_ERR("%s: particle must be a dictionary with a single key; "
"the name of the particle", conf_err_prefix(chain, node)); "the name of the particle",
conf_err_prefix(chain, node));
return false; return false;
} }
@ -331,15 +307,13 @@ conf_verify_particle_dictionary(keychain_t *chain, const struct yml_node *node)
const char *particle_name = yml_value_as_string(particle); const char *particle_name = yml_value_as_string(particle);
if (particle_name == NULL) { if (particle_name == NULL) {
LOG_ERR("%s: particle name must be a string", LOG_ERR("%s: particle name must be a string", conf_err_prefix(chain, particle));
conf_err_prefix(chain, particle));
return false; return false;
} }
const struct particle_iface *iface = plugin_load_particle(particle_name); const struct particle_iface *iface = plugin_load_particle(particle_name);
if (iface == NULL) { if (iface == NULL) {
LOG_ERR("%s: invalid particle name: %s", LOG_ERR("%s: invalid particle name: %s", conf_err_prefix(chain, particle), particle_name);
conf_err_prefix(chain, particle), particle_name);
return false; return false;
} }
@ -361,19 +335,18 @@ conf_verify_particle(keychain_t *chain, const struct yml_node *node)
else if (yml_is_list(node)) else if (yml_is_list(node))
return conf_verify_particle_list_items(chain, node); return conf_verify_particle_list_items(chain, node);
else { else {
LOG_ERR("%s: particle must be either a dictionary or a list", LOG_ERR("%s: particle must be either a dictionary or a list", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
} }
static bool static bool
verify_module(keychain_t *chain, const struct yml_node *node) verify_module(keychain_t *chain, const struct yml_node *node)
{ {
if (!yml_is_dict(node) || yml_dict_length(node) != 1) { if (!yml_is_dict(node) || yml_dict_length(node) != 1) {
LOG_ERR("%s: module must be a dictionary with a single key; " LOG_ERR("%s: module must be a dictionary with a single key; "
"the name of the module", conf_err_prefix(chain, node)); "the name of the module",
conf_err_prefix(chain, node));
return false; return false;
} }
@ -389,8 +362,7 @@ verify_module(keychain_t *chain, const struct yml_node *node)
const struct module_iface *iface = plugin_load_module(mod_name); const struct module_iface *iface = plugin_load_module(mod_name);
if (iface == NULL) { if (iface == NULL) {
LOG_ERR( LOG_ERR("%s: invalid module name: %s", conf_err_prefix(chain, node), mod_name);
"%s: invalid module name: %s", conf_err_prefix(chain, node), mod_name);
return false; return false;
} }
@ -412,10 +384,7 @@ verify_module_list(keychain_t *chain, const struct yml_node *node)
return false; return false;
} }
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) {
it.node != NULL;
yml_list_next(&it))
{
if (!verify_module(chain, it.node)) if (!verify_module(chain, it.node))
return false; return false;
} }
@ -427,18 +396,12 @@ static bool
verify_bar_border(keychain_t *chain, const struct yml_node *node) verify_bar_border(keychain_t *chain, const struct yml_node *node)
{ {
static const struct attr_info attrs[] = { static const struct attr_info attrs[] = {
{"width", false, &conf_verify_unsigned}, {"width", false, &conf_verify_unsigned}, {"left-width", false, &conf_verify_unsigned},
{"left-width", false, &conf_verify_unsigned}, {"right-width", false, &conf_verify_unsigned}, {"top-width", false, &conf_verify_unsigned},
{"right-width", false, &conf_verify_unsigned}, {"bottom-width", false, &conf_verify_unsigned}, {"color", false, &conf_verify_color},
{"top-width", false, &conf_verify_unsigned}, {"margin", false, &conf_verify_unsigned}, {"left-margin", false, &conf_verify_unsigned},
{"bottom-width", false, &conf_verify_unsigned}, {"right-margin", false, &conf_verify_unsigned}, {"top-margin", false, &conf_verify_unsigned},
{"color", false, &conf_verify_color}, {"bottom-margin", false, &conf_verify_unsigned}, {NULL, false, NULL},
{"margin", false, &conf_verify_unsigned},
{"left-margin", false, &conf_verify_unsigned},
{"right-margin", false, &conf_verify_unsigned},
{"top-margin", false, &conf_verify_unsigned},
{"bottom-margin", false, &conf_verify_unsigned},
{NULL, false, NULL},
}; };
return conf_verify_dict(chain, node, attrs); return conf_verify_dict(chain, node, attrs);
@ -453,9 +416,7 @@ verify_bar_location(keychain_t *chain, const struct yml_node *node)
static bool static bool
verify_bar_layer(keychain_t *chain, const struct yml_node *node) verify_bar_layer(keychain_t *chain, const struct yml_node *node)
{ {
return conf_verify_enum( return conf_verify_enum(chain, node, (const char *[]){"overlay", "top", "bottom", "background"}, 4);
chain, node,
(const char *[]){"overlay", "top", "bottom", "background"}, 4);
} }
bool bool

View file

@ -26,17 +26,14 @@ chain_pop(keychain_t *chain)
tll_pop_back(*chain); tll_pop_back(*chain);
} }
const char *conf_err_prefix( const char *conf_err_prefix(const keychain_t *chain, const struct yml_node *node);
const keychain_t *chain, const struct yml_node *node);
bool conf_verify_string(keychain_t *chain, const struct yml_node *node); bool conf_verify_string(keychain_t *chain, const struct yml_node *node);
bool conf_verify_int(keychain_t *chain, const struct yml_node *node); bool conf_verify_int(keychain_t *chain, const struct yml_node *node);
bool conf_verify_unsigned(keychain_t *chain, const struct yml_node *node); bool conf_verify_unsigned(keychain_t *chain, const struct yml_node *node);
bool conf_verify_bool(keychain_t *chain, const struct yml_node *node); bool conf_verify_bool(keychain_t *chain, const struct yml_node *node);
bool conf_verify_enum(keychain_t *chain, const struct yml_node *node, bool conf_verify_enum(keychain_t *chain, const struct yml_node *node, const char *values[], size_t count);
const char *values[], size_t count);
bool conf_verify_list(keychain_t *chain, const struct yml_node *node, bool conf_verify_list(keychain_t *chain, const struct yml_node *node,
bool (*verify)(keychain_t *chain, const struct yml_node *node)); bool (*verify)(keychain_t *chain, const struct yml_node *node));
bool conf_verify_dict(keychain_t *chain, const struct yml_node *node, bool conf_verify_dict(keychain_t *chain, const struct yml_node *node,

113
config.c
View file

@ -1,10 +1,10 @@
#include "config.h" #include "config.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -21,9 +21,7 @@
static uint8_t static uint8_t
hex_nibble(char hex) hex_nibble(char hex)
{ {
assert((hex >= '0' && hex <= '9') || assert((hex >= '0' && hex <= '9') || (hex >= 'a' && hex <= 'f') || (hex >= 'A' && hex <= 'F'));
(hex >= 'a' && hex <= 'f') ||
(hex >= 'A' && hex <= 'F'));
if (hex >= '0' && hex <= '9') if (hex >= '0' && hex <= '9')
return hex - '0'; return hex - '0';
@ -57,9 +55,9 @@ conf_to_color(const struct yml_node *node)
alpha |= alpha << 8; alpha |= alpha << 8;
return (pixman_color_t){ return (pixman_color_t){
.red = (uint32_t)(red << 8 | red) * alpha / 0xffff, .red = (uint32_t)(red << 8 | red) * alpha / 0xffff,
.green = (uint32_t)(green << 8 | green) * alpha / 0xffff, .green = (uint32_t)(green << 8 | green) * alpha / 0xffff,
.blue = (uint32_t)(blue << 8 | blue) * alpha / 0xffff, .blue = (uint32_t)(blue << 8 | blue) * alpha / 0xffff,
.alpha = alpha, .alpha = alpha,
}; };
} }
@ -74,10 +72,7 @@ conf_to_font(const struct yml_node *node)
const char **fonts = NULL; const char **fonts = NULL;
char *copy = strdup(font_spec); char *copy = strdup(font_spec);
for (const char *font = strtok(copy, ","); for (const char *font = strtok(copy, ","); font != NULL; font = strtok(NULL, ",")) {
font != NULL;
font = strtok(NULL, ","))
{
/* Trim spaces, strictly speaking not necessary, but looks nice :) */ /* Trim spaces, strictly speaking not necessary, but looks nice :) */
while (isspace(font[0])) while (isspace(font[0]))
font++; font++;
@ -112,9 +107,7 @@ conf_to_font_shaping(const struct yml_node *node)
else if (strcmp(v, "graphemes") == 0) { else if (strcmp(v, "graphemes") == 0) {
static bool have_warned = false; static bool have_warned = false;
if (!have_warned && if (!have_warned && !(fcft_capabilities() & FCFT_CAPABILITY_GRAPHEME_SHAPING)) {
!(fcft_capabilities() & FCFT_CAPABILITY_GRAPHEME_SHAPING))
{
have_warned = true; have_warned = true;
LOG_WARN("cannot enable grapheme shaping; no support in fcft"); LOG_WARN("cannot enable grapheme shaping; no support in fcft");
} }
@ -124,9 +117,7 @@ conf_to_font_shaping(const struct yml_node *node)
else if (strcmp(v, "full") == 0) { else if (strcmp(v, "full") == 0) {
static bool have_warned = false; static bool have_warned = false;
if (!have_warned && if (!have_warned && !(fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING)) {
!(fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING))
{
have_warned = true; have_warned = true;
LOG_WARN("cannot enable full text shaping; no support in fcft"); LOG_WARN("cannot enable full text shaping; no support in fcft");
} }
@ -154,25 +145,20 @@ conf_to_deco(const struct yml_node *node)
} }
static struct particle * static struct particle *
particle_simple_list_from_config(const struct yml_node *node, particle_simple_list_from_config(const struct yml_node *node, struct conf_inherit inherited)
struct conf_inherit inherited)
{ {
size_t count = yml_list_length(node); size_t count = yml_list_length(node);
struct particle *parts[count]; struct particle *parts[count];
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL;
yml_list_next(&it), idx++)
{
parts[idx] = conf_to_particle(it.node, inherited); parts[idx] = conf_to_particle(it.node, inherited);
} }
/* Lazy-loaded function pointer to particle_list_new() */ /* Lazy-loaded function pointer to particle_list_new() */
static struct particle *(*particle_list_new)( static struct particle *(*particle_list_new)(struct particle *common, struct particle *particles[], size_t count,
struct particle *common, int left_spacing, int right_spacing)
struct particle *particles[], size_t count, = NULL;
int left_spacing, int right_spacing) = NULL;
if (particle_list_new == NULL) { if (particle_list_new == NULL) {
const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE); const struct plugin *plug = plugin_load("list", PLUGIN_PARTICLE);
@ -181,9 +167,8 @@ particle_simple_list_from_config(const struct yml_node *node,
assert(particle_list_new != NULL); assert(particle_list_new != NULL);
} }
struct particle *common = particle_common_new( struct particle *common = particle_common_new(0, 0, NULL, fcft_clone(inherited.font), inherited.font_shaping,
0, 0, NULL, fcft_clone(inherited.font), inherited.font_shaping, inherited.foreground, NULL);
inherited.foreground, NULL);
return particle_list_new(common, parts, count, 0, 2); return particle_list_new(common, parts, count, 0, 2);
} }
@ -206,10 +191,8 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *foreground_node = yml_get_value(pair.value, "foreground"); const struct yml_node *foreground_node = yml_get_value(pair.value, "foreground");
const struct yml_node *deco_node = yml_get_value(pair.value, "deco"); const struct yml_node *deco_node = yml_get_value(pair.value, "deco");
int left = margin != NULL ? yml_value_as_int(margin) : int left = margin != NULL ? yml_value_as_int(margin) : left_margin != NULL ? yml_value_as_int(left_margin) : 0;
left_margin != NULL ? yml_value_as_int(left_margin) : 0; int right = margin != NULL ? yml_value_as_int(margin) : right_margin != NULL ? yml_value_as_int(right_margin) : 0;
int right = margin != NULL ? yml_value_as_int(margin) :
right_margin != NULL ? yml_value_as_int(right_margin) : 0;
char *on_click_templates[MOUSE_BTN_COUNT] = {NULL}; char *on_click_templates[MOUSE_BTN_COUNT] = {NULL};
if (on_click != NULL) { if (on_click != NULL) {
@ -234,10 +217,7 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
} }
else if (yml_is_dict(on_click)) { else if (yml_is_dict(on_click)) {
for (struct yml_dict_iter it = yml_dict_iter(on_click); for (struct yml_dict_iter it = yml_dict_iter(on_click); it.key != NULL; yml_dict_next(&it)) {
it.key != NULL;
yml_dict_next(&it))
{
const char *key = yml_value_as_string(it.key); const char *key = yml_value_as_string(it.key);
const char *yml_template = yml_value_as_string(it.value); const char *yml_template = yml_value_as_string(it.value);
@ -286,16 +266,14 @@ conf_to_particle(const struct yml_node *node, struct conf_inherit inherited)
* clone the font, since each particle takes ownership of its own * clone the font, since each particle takes ownership of its own
* font. * font.
*/ */
struct fcft_font *font = font_node != NULL struct fcft_font *font = font_node != NULL ? conf_to_font(font_node) : fcft_clone(inherited.font);
? conf_to_font(font_node) : fcft_clone(inherited.font); enum font_shaping font_shaping
enum font_shaping font_shaping = font_shaping_node != NULL = font_shaping_node != NULL ? conf_to_font_shaping(font_shaping_node) : inherited.font_shaping;
? conf_to_font_shaping(font_shaping_node) : inherited.font_shaping; pixman_color_t foreground = foreground_node != NULL ? conf_to_color(foreground_node) : inherited.foreground;
pixman_color_t foreground = foreground_node != NULL
? conf_to_color(foreground_node) : inherited.foreground;
/* Instantiate base/common particle */ /* Instantiate base/common particle */
struct particle *common = particle_common_new( struct particle *common
left, right, on_click_templates, font, font_shaping, foreground, deco); = particle_common_new(left, right, on_click_templates, font, font_shaping, foreground, deco);
const struct particle_iface *iface = plugin_load_particle(type); const struct particle_iface *iface = plugin_load_particle(type);
@ -323,8 +301,7 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
conf.height = yml_value_as_int(height); conf.height = yml_value_as_int(height);
const struct yml_node *location = yml_get_value(bar, "location"); const struct yml_node *location = yml_get_value(bar, "location");
conf.location = strcmp(yml_value_as_string(location), "top") == 0 conf.location = strcmp(yml_value_as_string(location), "top") == 0 ? BAR_TOP : BAR_BOTTOM;
? BAR_TOP : BAR_BOTTOM;
const struct yml_node *background = yml_get_value(bar, "background"); const struct yml_node *background = yml_get_value(bar, "background");
conf.background = conf_to_color(background); conf.background = conf_to_color(background);
@ -352,7 +329,6 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
assert(false); assert(false);
} }
const struct yml_node *spacing = yml_get_value(bar, "spacing"); const struct yml_node *spacing = yml_get_value(bar, "spacing");
if (spacing != NULL) if (spacing != NULL)
conf.left_spacing = conf.right_spacing = yml_value_as_int(spacing); conf.left_spacing = conf.right_spacing = yml_value_as_int(spacing);
@ -377,11 +353,8 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
if (right_margin != NULL) if (right_margin != NULL)
conf.right_margin = yml_value_as_int(right_margin); conf.right_margin = yml_value_as_int(right_margin);
const struct yml_node *trackpad_sensitivity = const struct yml_node *trackpad_sensitivity = yml_get_value(bar, "trackpad-sensitivity");
yml_get_value(bar, "trackpad-sensitivity"); conf.trackpad_sensitivity = trackpad_sensitivity != NULL ? yml_value_as_int(trackpad_sensitivity) : 30;
conf.trackpad_sensitivity = trackpad_sensitivity != NULL
? yml_value_as_int(trackpad_sensitivity)
: 30;
const struct yml_node *border = yml_get_value(bar, "border"); const struct yml_node *border = yml_get_value(bar, "border");
if (border != NULL) { if (border != NULL) {
@ -398,10 +371,8 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
const struct yml_node *bottom_margin = yml_get_value(border, "bottom-margin"); const struct yml_node *bottom_margin = yml_get_value(border, "bottom-margin");
if (width != NULL) if (width != NULL)
conf.border.left_width = conf.border.left_width = conf.border.right_width = conf.border.top_width = conf.border.bottom_width
conf.border.right_width = = yml_value_as_int(width);
conf.border.top_width =
conf.border.bottom_width = yml_value_as_int(width);
if (left_width != NULL) if (left_width != NULL)
conf.border.left_width = yml_value_as_int(left_width); conf.border.left_width = yml_value_as_int(left_width);
@ -416,10 +387,8 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
conf.border.color = conf_to_color(color); conf.border.color = conf_to_color(color);
if (margin != NULL) if (margin != NULL)
conf.border.left_margin = conf.border.left_margin = conf.border.right_margin = conf.border.top_margin = conf.border.bottom_margin
conf.border.right_margin = = yml_value_as_int(margin);
conf.border.top_margin =
conf.border.bottom_margin = yml_value_as_int(margin);
if (left_margin != NULL) if (left_margin != NULL)
conf.border.left_margin = yml_value_as_int(left_margin); conf.border.left_margin = yml_value_as_int(left_margin);
@ -474,10 +443,7 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
struct module **mods = calloc(count, sizeof(*mods)); struct module **mods = calloc(count, sizeof(*mods));
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL;
yml_list_next(&it), idx++)
{
struct yml_dict_iter m = yml_dict_iter(it.node); struct yml_dict_iter m = yml_dict_iter(it.node);
const char *mod_name = yml_value_as_string(m.key); const char *mod_name = yml_value_as_string(m.key);
@ -489,16 +455,13 @@ conf_to_bar(const struct yml_node *bar, enum bar_backend backend)
*/ */
const struct yml_node *mod_font = yml_get_value(m.value, "font"); const struct yml_node *mod_font = yml_get_value(m.value, "font");
const struct yml_node *mod_font_shaping = yml_get_value(m.value, "font-shaping"); const struct yml_node *mod_font_shaping = yml_get_value(m.value, "font-shaping");
const struct yml_node *mod_foreground = yml_get_value( const struct yml_node *mod_foreground = yml_get_value(m.value, "foreground");
m.value, "foreground");
struct conf_inherit mod_inherit = { struct conf_inherit mod_inherit = {
.font = mod_font != NULL .font = mod_font != NULL ? conf_to_font(mod_font) : inherited.font,
? conf_to_font(mod_font) : inherited.font, .font_shaping
.font_shaping = mod_font_shaping != NULL = mod_font_shaping != NULL ? conf_to_font_shaping(mod_font_shaping) : inherited.font_shaping,
? conf_to_font_shaping(mod_font_shaping) : inherited.font_shaping, .foreground = mod_foreground != NULL ? conf_to_color(mod_foreground) : inherited.foreground,
.foreground = mod_foreground != NULL
? conf_to_color(mod_foreground) : inherited.foreground,
}; };
const struct module_iface *iface = plugin_load_module(mod_name); const struct module_iface *iface = plugin_load_module(mod_name);

View file

@ -1,9 +1,9 @@
#pragma once #pragma once
#include <fcft/fcft.h>
#include "yml.h"
#include "bar/bar.h" #include "bar/bar.h"
#include "font-shaping.h" #include "font-shaping.h"
#include "yml.h"
#include <fcft/fcft.h>
struct bar; struct bar;
struct particle; struct particle;
@ -25,6 +25,5 @@ struct conf_inherit {
pixman_color_t foreground; pixman_color_t foreground;
}; };
struct particle *conf_to_particle( struct particle *conf_to_particle(const struct yml_node *node, struct conf_inherit inherited);
const struct yml_node *node, struct conf_inherit inherited);
struct deco *conf_to_deco(const struct yml_node *node); struct deco *conf_to_deco(const struct yml_node *node);

View file

@ -4,10 +4,11 @@
struct deco { struct deco {
void *private; void *private;
void (*expose)(const struct deco *deco, pixman_image_t *pix, void (*expose)(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height);
int x, int y, int width, int height);
void (*destroy)(struct deco *deco); void (*destroy)(struct deco *deco);
}; };
#define DECORATION_COMMON_ATTRS \ #define DECORATION_COMMON_ATTRS \
{NULL, false, NULL} { \
NULL, false, NULL \
}

View file

@ -1,12 +1,13 @@
#include <stdlib.h> #include <stdlib.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../decoration.h" #include "../decoration.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
//struct rgba color; {
// struct rgba color;
pixman_color_t color; pixman_color_t color;
}; };
@ -22,9 +23,7 @@ static void
expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height)
{ {
const struct private *d = deco->private; const struct private *d = deco->private;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1, &(pixman_rectangle16_t){x, y, width, height});
PIXMAN_OP_OVER, pix, &d->color, 1,
&(pixman_rectangle16_t){x, y, width, height});
} }
static struct deco * static struct deco *

View file

@ -1,7 +1,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../decoration.h" #include "../decoration.h"
#include "../plugin.h" #include "../plugin.h"
@ -12,7 +12,8 @@
#define min(x, y) ((x) < (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
struct private { struct private
{
pixman_color_t color; pixman_color_t color;
int size; int size;
}; };
@ -29,21 +30,20 @@ static void
expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height)
{ {
const struct private *d = deco->private; const struct private *d = deco->private;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 4,
PIXMAN_OP_OVER, pix, &d->color, 4, (pixman_rectangle16_t[]){
(pixman_rectangle16_t []){ /* Top */
/* Top */ {x, y, width, min(d->size, height)},
{x, y, width, min(d->size, height)},
/* Bottom */ /* Bottom */
{x, max(y + height - d->size, y), width, min(d->size, height)}, {x, max(y + height - d->size, y), width, min(d->size, height)},
/* Left */ /* Left */
{x, y, min(d->size, width), height}, {x, y, min(d->size, width), height},
/* Right */ /* Right */
{max(x + width - d->size, x), y, min(d->size, width), height}, {max(x + width - d->size, x), y, min(d->size, width), height},
}); });
} }
static struct deco * static struct deco *
@ -66,9 +66,7 @@ from_conf(const struct yml_node *node)
{ {
const struct yml_node *color = yml_get_value(node, "color"); const struct yml_node *color = yml_get_value(node, "color");
const struct yml_node *size = yml_get_value(node, "size"); const struct yml_node *size = yml_get_value(node, "size");
return border_new( return border_new(conf_to_color(color), size != NULL ? yml_value_as_int(size) : 1);
conf_to_color(color),
size != NULL ? yml_value_as_int(size) : 1);
} }
static bool static bool

View file

@ -1,11 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../decoration.h" #include "../decoration.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
int size; int size;
pixman_color_t color; pixman_color_t color;
}; };
@ -22,9 +23,7 @@ static void
expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height)
{ {
const struct private *d = deco->private; const struct private *d = deco->private;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1, &(pixman_rectangle16_t){x, y, width, d->size});
PIXMAN_OP_OVER, pix, &d->color, 1,
&(pixman_rectangle16_t){x, y, width, d->size});
} }
static struct deco * static struct deco *

View file

@ -1,13 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#define LOG_MODULE "stack" #define LOG_MODULE "stack"
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../decoration.h" #include "../decoration.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
struct deco **decos; struct deco **decos;
size_t count; size_t count;
}; };
@ -57,10 +58,7 @@ from_conf(const struct yml_node *node)
struct deco *decos[count]; struct deco *decos[count];
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL;
yml_list_next(&it), idx++)
{
decos[idx] = conf_to_deco(it.node); decos[idx] = conf_to_deco(it.node);
} }
@ -75,10 +73,7 @@ verify_conf(keychain_t *chain, const struct yml_node *node)
return false; return false;
} }
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) {
it.node != NULL;
yml_list_next(&it))
{
if (!conf_verify_decoration(chain, it.node)) if (!conf_verify_decoration(chain, it.node))
return false; return false;
} }

View file

@ -1,11 +1,12 @@
#include <stdlib.h> #include <stdlib.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../decoration.h" #include "../decoration.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
int size; int size;
pixman_color_t color; pixman_color_t color;
}; };
@ -22,9 +23,8 @@ static void
expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height) expose(const struct deco *deco, pixman_image_t *pix, int x, int y, int width, int height)
{ {
const struct private *d = deco->private; const struct private *d = deco->private;
pixman_image_fill_rectangles( pixman_image_fill_rectangles(PIXMAN_OP_OVER, pix, &d->color, 1,
PIXMAN_OP_OVER, pix, &d->color, 1, &(pixman_rectangle16_t){x, y + height - d->size, width, d->size});
&(pixman_rectangle16_t){x, y + height - d->size, width, d->size});
} }
static struct deco * static struct deco *

42
log.c
View file

@ -1,5 +1,6 @@
#include "log.h" #include "log.h"
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h> #include <stdbool.h>
@ -9,7 +10,6 @@
#include <string.h> #include <string.h>
#include <syslog.h> #include <syslog.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#define ALEN(v) (sizeof(v) / sizeof((v)[0])) #define ALEN(v) (sizeof(v) / sizeof((v)[0]))
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
@ -32,23 +32,22 @@ static const struct {
}; };
void void
log_init(enum log_colorize _colorize, bool _do_syslog, log_init(enum log_colorize _colorize, bool _do_syslog, enum log_facility syslog_facility, enum log_class _log_level)
enum log_facility syslog_facility, enum log_class _log_level)
{ {
static const int facility_map[] = { static const int facility_map[] = {
[LOG_FACILITY_USER] = LOG_USER, [LOG_FACILITY_USER] = LOG_USER,
[LOG_FACILITY_DAEMON] = LOG_DAEMON, [LOG_FACILITY_DAEMON] = LOG_DAEMON,
}; };
colorize = _colorize == LOG_COLORIZE_NEVER colorize = _colorize == LOG_COLORIZE_NEVER ? false
? false : _colorize == LOG_COLORIZE_ALWAYS : _colorize == LOG_COLORIZE_ALWAYS ? true
? true : isatty(STDERR_FILENO); : isatty(STDERR_FILENO);
do_syslog = _do_syslog; do_syslog = _do_syslog;
log_level = _log_level; log_level = _log_level;
int slvl = log_level_map[_log_level].syslog_equivalent; int slvl = log_level_map[_log_level].syslog_equivalent;
if (do_syslog && slvl != -1) { if (do_syslog && slvl != -1) {
openlog(NULL, /*LOG_PID*/0, facility_map[syslog_facility]); openlog(NULL, /*LOG_PID*/ 0, facility_map[syslog_facility]);
setlogmask(LOG_UPTO(slvl)); setlogmask(LOG_UPTO(slvl));
} }
} }
@ -61,8 +60,8 @@ log_deinit(void)
} }
static void static void
_log(enum log_class log_class, const char *module, const char *file, int lineno, _log(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, int sys_errno,
const char *fmt, int sys_errno, va_list va) va_list va)
{ {
assert(log_class > LOG_CLASS_NONE); assert(log_class > LOG_CLASS_NONE);
assert(log_class < ALEN(log_level_map)); assert(log_class < ALEN(log_level_map));
@ -92,9 +91,8 @@ _log(enum log_class log_class, const char *module, const char *file, int lineno,
} }
static void static void
_sys_log(enum log_class log_class, const char *module, _sys_log(enum log_class log_class, const char *module, const char UNUSED *file, int UNUSED lineno, const char *fmt,
const char UNUSED *file, int UNUSED lineno, int sys_errno, va_list va)
const char *fmt, int sys_errno, va_list va)
{ {
assert(log_class > LOG_CLASS_NONE); assert(log_class > LOG_CLASS_NONE);
assert(log_class < ALEN(log_level_map)); assert(log_class < ALEN(log_level_map));
@ -119,8 +117,7 @@ _sys_log(enum log_class log_class, const char *module,
} }
void void
log_msg_va(enum log_class log_class, const char *module, log_msg_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va)
const char *file, int lineno, const char *fmt, va_list va)
{ {
va_list va2; va_list va2;
va_copy(va2, va); va_copy(va2, va);
@ -130,8 +127,7 @@ log_msg_va(enum log_class log_class, const char *module,
} }
void void
log_msg(enum log_class log_class, const char *module, log_msg(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...)
const char *file, int lineno, const char *fmt, ...)
{ {
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
@ -140,17 +136,13 @@ log_msg(enum log_class log_class, const char *module,
} }
void void
log_errno_va(enum log_class log_class, const char *module, log_errno_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va)
const char *file, int lineno,
const char *fmt, va_list va)
{ {
log_errno_provided_va(log_class, module, file, lineno, errno, fmt, va); log_errno_provided_va(log_class, module, file, lineno, errno, fmt, va);
} }
void void
log_errno(enum log_class log_class, const char *module, log_errno(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...)
const char *file, int lineno,
const char *fmt, ...)
{ {
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
@ -159,8 +151,7 @@ log_errno(enum log_class log_class, const char *module,
} }
void void
log_errno_provided_va(enum log_class log_class, const char *module, log_errno_provided_va(enum log_class log_class, const char *module, const char *file, int lineno, int errno_copy,
const char *file, int lineno, int errno_copy,
const char *fmt, va_list va) const char *fmt, va_list va)
{ {
va_list va2; va_list va2;
@ -171,8 +162,7 @@ log_errno_provided_va(enum log_class log_class, const char *module,
} }
void void
log_errno_provided(enum log_class log_class, const char *module, log_errno_provided(enum log_class log_class, const char *module, const char *file, int lineno, int errno_copy,
const char *file, int lineno, int errno_copy,
const char *fmt, ...) const char *fmt, ...)
{ {
va_list va; va_list va;

71
log.h
View file

@ -1,68 +1,43 @@
#pragma once #pragma once
#include <stdbool.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO }; enum log_colorize { LOG_COLORIZE_NEVER, LOG_COLORIZE_ALWAYS, LOG_COLORIZE_AUTO };
enum log_facility { LOG_FACILITY_USER, LOG_FACILITY_DAEMON }; enum log_facility { LOG_FACILITY_USER, LOG_FACILITY_DAEMON };
enum log_class { enum log_class { LOG_CLASS_NONE, LOG_CLASS_ERROR, LOG_CLASS_WARNING, LOG_CLASS_INFO, LOG_CLASS_DEBUG };
LOG_CLASS_NONE,
LOG_CLASS_ERROR,
LOG_CLASS_WARNING,
LOG_CLASS_INFO,
LOG_CLASS_DEBUG
};
void log_init(enum log_colorize colorize, bool do_syslog, void log_init(enum log_colorize colorize, bool do_syslog, enum log_facility syslog_facility, enum log_class log_level);
enum log_facility syslog_facility, enum log_class log_level);
void log_deinit(void); void log_deinit(void);
void log_msg( void log_msg(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...)
enum log_class log_class, const char *module, __attribute__((format(printf, 5, 6)));
const char *file, int lineno,
const char *fmt, ...) __attribute__((format (printf, 5, 6)));
void log_errno( void log_errno(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, ...)
enum log_class log_class, const char *module, __attribute__((format(printf, 5, 6)));
const char *file, int lineno,
const char *fmt, ...) __attribute__((format (printf, 5, 6)));
void log_errno_provided( void log_errno_provided(enum log_class log_class, const char *module, const char *file, int lineno, int _errno,
enum log_class log_class, const char *module, const char *fmt, ...) __attribute__((format(printf, 6, 7)));
const char *file, int lineno, int _errno,
const char *fmt, ...) __attribute__((format (printf, 6, 7)));
void log_msg_va(
enum log_class log_class, const char *module,
const char *file, int lineno, const char *fmt, va_list va) __attribute__((format (printf, 5, 0)));
void log_errno_va(
enum log_class log_class, const char *module,
const char *file, int lineno,
const char *fmt, va_list va) __attribute__((format (printf, 5, 0)));
void log_errno_provided_va(
enum log_class log_class, const char *module,
const char *file, int lineno, int _errno,
const char *fmt, va_list va) __attribute__((format (printf, 6, 0)));
void log_msg_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt, va_list va)
__attribute__((format(printf, 5, 0)));
void log_errno_va(enum log_class log_class, const char *module, const char *file, int lineno, const char *fmt,
va_list va) __attribute__((format(printf, 5, 0)));
void log_errno_provided_va(enum log_class log_class, const char *module, const char *file, int lineno, int _errno,
const char *fmt, va_list va) __attribute__((format(printf, 6, 0)));
int log_level_from_string(const char *str); int log_level_from_string(const char *str);
const char *log_level_string_hint(void); const char *log_level_string_hint(void);
#define LOG_ERR(...) \ #define LOG_ERR(...) log_msg(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
log_msg(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) #define LOG_ERRNO(...) log_errno(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_ERRNO(...) \ #define LOG_ERRNO_P(_errno, ...) \
log_errno(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__) log_errno_provided(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, _errno, __VA_ARGS__)
#define LOG_ERRNO_P(_errno, ...) \ #define LOG_WARN(...) log_msg(LOG_CLASS_WARNING, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
log_errno_provided(LOG_CLASS_ERROR, LOG_MODULE, __FILE__, __LINE__, \ #define LOG_INFO(...) log_msg(LOG_CLASS_INFO, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
_errno, __VA_ARGS__)
#define LOG_WARN(...) \
log_msg(LOG_CLASS_WARNING, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INFO(...) \
log_msg(LOG_CLASS_INFO, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
#define LOG_DBG(...) \ #define LOG_DBG(...) log_msg(LOG_CLASS_DEBUG, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
log_msg(LOG_CLASS_DEBUG, LOG_MODULE, __FILE__, __LINE__, __VA_ARGS__)
#else #else
#define LOG_DBG(...) #define LOG_DBG(...)
#endif #endif

53
main.c
View file

@ -1,4 +1,6 @@
#include <assert.h> #include <assert.h>
#include <errno.h>
#include <getopt.h>
#include <locale.h> #include <locale.h>
#include <poll.h> #include <poll.h>
#include <signal.h> #include <signal.h>
@ -9,14 +11,12 @@
#include <string.h> #include <string.h>
#include <threads.h> #include <threads.h>
#include <unistd.h> #include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/eventfd.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <pwd.h> #include <pwd.h>
#include <sys/eventfd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "bar/bar.h" #include "bar/bar.h"
#include "config.h" #include "config.h"
@ -147,9 +147,8 @@ print_pid(const char *pid_file, bool *unlink_at_exit)
int pid_fd = strtoul(pid_file, &end, 10); int pid_fd = strtoul(pid_file, &end, 10);
if (errno != 0 || *end != '\0') { if (errno != 0 || *end != '\0') {
if ((pid_fd = open(pid_file, if ((pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))
O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, < 0) {
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) < 0) {
LOG_ERRNO("%s: failed to open", pid_file); LOG_ERRNO("%s: failed to open", pid_file);
return false; return false;
} else } else
@ -178,16 +177,16 @@ int
main(int argc, char *const *argv) main(int argc, char *const *argv)
{ {
static const struct option longopts[] = { static const struct option longopts[] = {
{"backend", required_argument, 0, 'b'}, {"backend", required_argument, 0, 'b'},
{"config", required_argument, 0, 'c'}, {"config", required_argument, 0, 'c'},
{"validate", no_argument, 0, 'C'}, {"validate", no_argument, 0, 'C'},
{"print-pid", required_argument, 0, 'p'}, {"print-pid", required_argument, 0, 'p'},
{"log-level", required_argument, 0, 'd'}, {"log-level", required_argument, 0, 'd'},
{"log-colorize", optional_argument, 0, 'l'}, {"log-colorize", optional_argument, 0, 'l'},
{"log-no-syslog", no_argument, 0, 's'}, {"log-no-syslog", no_argument, 0, 's'},
{"version", no_argument, 0, 'v'}, {"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'}, {"help", no_argument, 0, 'h'},
{NULL, no_argument, 0, 0}, {NULL, no_argument, 0, 0},
}; };
bool unlink_pid_file = false; bool unlink_pid_file = false;
@ -224,8 +223,7 @@ main(int argc, char *const *argv)
fprintf(stderr, "%s: invalid configuration file: %s\n", optarg, strerror(errno)); fprintf(stderr, "%s: invalid configuration file: %s\n", optarg, strerror(errno));
return EXIT_FAILURE; return EXIT_FAILURE;
} else if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) { } else if (!S_ISREG(st.st_mode) && !S_ISFIFO(st.st_mode)) {
fprintf(stderr, "%s: invalid configuration file: neither a regular file nor a pipe or FIFO\n", fprintf(stderr, "%s: invalid configuration file: neither a regular file nor a pipe or FIFO\n", optarg);
optarg);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -244,11 +242,7 @@ main(int argc, char *const *argv)
case 'd': { case 'd': {
int lvl = log_level_from_string(optarg); int lvl = log_level_from_string(optarg);
if (lvl < 0) { if (lvl < 0) {
fprintf( fprintf(stderr, "-d,--log-level: %s: argument must be one of %s\n", optarg, log_level_string_hint());
stderr,
"-d,--log-level: %s: argument must be one of %s\n",
optarg,
log_level_string_hint());
return EXIT_FAILURE; return EXIT_FAILURE;
} }
log_level = lvl; log_level = lvl;
@ -292,12 +286,9 @@ main(int argc, char *const *argv)
log_init(log_colorize, log_syslog, LOG_FACILITY_DAEMON, log_level); log_init(log_colorize, log_syslog, LOG_FACILITY_DAEMON, log_level);
_Static_assert((int)LOG_CLASS_ERROR == (int)FCFT_LOG_CLASS_ERROR, _Static_assert((int)LOG_CLASS_ERROR == (int)FCFT_LOG_CLASS_ERROR, "fcft log level enum offset");
"fcft log level enum offset"); _Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, "fcft colorize enum mismatch");
_Static_assert((int)LOG_COLORIZE_ALWAYS == (int)FCFT_LOG_COLORIZE_ALWAYS, fcft_init((enum fcft_log_colorize)log_colorize, log_syslog, (enum fcft_log_class)log_level);
"fcft colorize enum mismatch");
fcft_init((enum fcft_log_colorize)log_colorize, log_syslog,
(enum fcft_log_class)log_level);
atexit(&fcft_fini); atexit(&fcft_fini);
const struct sigaction sa = {.sa_handler = &signal_handler}; const struct sigaction sa = {.sa_handler = &signal_handler};

View file

@ -1,6 +1,6 @@
#include "module.h" #include "module.h"
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <unistd.h> #include <unistd.h>
struct module * struct module *

View file

@ -35,9 +35,9 @@ void module_default_destroy(struct module *mod);
struct exposable *module_begin_expose(struct module *mod); struct exposable *module_begin_expose(struct module *mod);
/* List of attributes *all* modules implement */ /* List of attributes *all* modules implement */
#define MODULE_COMMON_ATTRS \ #define MODULE_COMMON_ATTRS \
{"content", true, &conf_verify_particle}, \ {"content", true, &conf_verify_particle}, {"anchors", false, NULL}, {"font", false, &conf_verify_font}, \
{"anchors", false, NULL}, \ {"foreground", false, &conf_verify_color}, \
{"font", false, &conf_verify_font}, \ { \
{"foreground", false, &conf_verify_color}, \ NULL, false, NULL \
{NULL, false, NULL} }

View file

@ -1,8 +1,8 @@
#include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <sys/time.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/time.h>
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
@ -10,10 +10,10 @@
#define LOG_MODULE "alsa" #define LOG_MODULE "alsa"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h" #include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
enum channel_type { CHANNEL_PLAYBACK, CHANNEL_CAPTURE }; enum channel_type { CHANNEL_PLAYBACK, CHANNEL_CAPTURE };
@ -29,7 +29,8 @@ struct channel {
bool muted; bool muted;
}; };
struct private { struct private
{
char *card; char *card;
char *mixer; char *mixer;
char *volume_name; char *volume_name;
@ -70,7 +71,8 @@ static void
destroy(struct module *mod) destroy(struct module *mod)
{ {
struct private *m = mod->private; struct private *m = mod->private;
tll_foreach(m->channels, it) { tll_foreach(m->channels, it)
{
channel_free(&it->item); channel_free(&it->item);
tll_remove(m->channels, it); tll_remove(m->channels, it);
} }
@ -129,9 +131,7 @@ content(struct module *mod)
if (use_db) { if (use_db) {
bool use_linear = db_max - db_min <= 24 * 100; bool use_linear = db_max - db_min <= 24 * 100;
if (use_linear) { if (use_linear) {
percent = db_min - db_max > 0 percent = db_min - db_max > 0 ? round(100. * (db_cur - db_min) / (db_max - db_min)) : 0;
? round(100. * (db_cur - db_min) / (db_max - db_min))
: 0;
} else { } else {
double normalized = pow(10, (double)(db_cur - db_max) / 6000.); double normalized = pow(10, (double)(db_cur - db_max) / 6000.);
if (db_min != SND_CTL_TLV_DB_GAIN_MUTE) { if (db_min != SND_CTL_TLV_DB_GAIN_MUTE) {
@ -141,9 +141,7 @@ content(struct module *mod)
percent = round(100. * normalized); percent = round(100. * normalized);
} }
} else { } else {
percent = vol_max - vol_min > 0 percent = vol_max - vol_min > 0 ? round(100. * (vol_cur - vol_min) / (vol_max - vol_min)) : 0;
? round(100. * (vol_cur - vol_min) / (vol_max - vol_min))
: 0;
} }
struct tag_set tags = { struct tag_set tags = {
@ -173,107 +171,94 @@ update_state(struct module *mod, snd_mixer_elem_t *elem)
/* If volume level can be changed (i.e. this isn't just a switch; /* If volume level can be changed (i.e. this isn't just a switch;
* e.g. a digital channel), get current channel levels */ * e.g. a digital channel), get current channel levels */
tll_foreach(m->channels, it) { tll_foreach(m->channels, it)
{
struct channel *chan = &it->item; struct channel *chan = &it->item;
const bool has_volume = chan->type == CHANNEL_PLAYBACK const bool has_volume = chan->type == CHANNEL_PLAYBACK ? m->has_playback_volume : m->has_capture_volume;
? m->has_playback_volume : m->has_capture_volume; const bool has_db = chan->type == CHANNEL_PLAYBACK ? m->has_playback_db : m->has_capture_db;
const bool has_db = chan->type == CHANNEL_PLAYBACK
? m->has_playback_db : m->has_capture_db;
if (!has_volume && !has_db) if (!has_volume && !has_db)
continue; continue;
if (has_db) { if (has_db) {
chan->use_db = true; chan->use_db = true;
const long min = chan->type == CHANNEL_PLAYBACK const long min = chan->type == CHANNEL_PLAYBACK ? m->playback_db_min : m->capture_db_min;
? m->playback_db_min : m->capture_db_min; const long max = chan->type == CHANNEL_PLAYBACK ? m->playback_db_max : m->capture_db_max;
const long max = chan->type == CHANNEL_PLAYBACK
? m->playback_db_max : m->capture_db_max;
assert(min <= max); assert(min <= max);
int r = chan->type == CHANNEL_PLAYBACK int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_dB(elem, chan->id, &chan->db_cur)
? snd_mixer_selem_get_playback_dB(elem, chan->id, &chan->db_cur) : snd_mixer_selem_get_capture_dB(elem, chan->id, &chan->db_cur);
: snd_mixer_selem_get_capture_dB(elem, chan->id, &chan->db_cur);
if (r < 0) { if (r < 0) {
LOG_ERR("%s,%s: %s: failed to get current dB", LOG_ERR("%s,%s: %s: failed to get current dB", m->card, m->mixer, chan->name);
m->card, m->mixer, chan->name);
} }
if (chan->db_cur < min) { if (chan->db_cur < min) {
LOG_WARN( LOG_WARN("%s,%s: %s: current dB is less than the indicated minimum: "
"%s,%s: %s: current dB is less than the indicated minimum: " "%ld < %ld",
"%ld < %ld", m->card, m->mixer, chan->name, chan->db_cur, min); m->card, m->mixer, chan->name, chan->db_cur, min);
chan->db_cur = min; chan->db_cur = min;
} }
if (chan->db_cur > max) { if (chan->db_cur > max) {
LOG_WARN( LOG_WARN("%s,%s: %s: current dB is greater than the indicated maximum: "
"%s,%s: %s: current dB is greater than the indicated maximum: " "%ld > %ld",
"%ld > %ld", m->card, m->mixer, chan->name, chan->db_cur, max); m->card, m->mixer, chan->name, chan->db_cur, max);
chan->db_cur = max; chan->db_cur = max;
} }
assert(chan->db_cur >= min); assert(chan->db_cur >= min);
assert(chan->db_cur <= max ); assert(chan->db_cur <= max);
LOG_DBG("%s,%s: %s: dB: %ld", LOG_DBG("%s,%s: %s: dB: %ld", m->card, m->mixer, chan->name, chan->db_cur);
m->card, m->mixer, chan->name, chan->db_cur);
} else } else
chan->use_db = false; chan->use_db = false;
const long min = chan->type == CHANNEL_PLAYBACK const long min = chan->type == CHANNEL_PLAYBACK ? m->playback_vol_min : m->capture_vol_min;
? m->playback_vol_min : m->capture_vol_min; const long max = chan->type == CHANNEL_PLAYBACK ? m->playback_vol_max : m->capture_vol_max;
const long max = chan->type == CHANNEL_PLAYBACK
? m->playback_vol_max : m->capture_vol_max;
assert(min <= max); assert(min <= max);
int r = chan->type == CHANNEL_PLAYBACK int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_volume(elem, chan->id, &chan->vol_cur)
? snd_mixer_selem_get_playback_volume(elem, chan->id, &chan->vol_cur) : snd_mixer_selem_get_capture_volume(elem, chan->id, &chan->vol_cur);
: snd_mixer_selem_get_capture_volume(elem, chan->id, &chan->vol_cur);
if (r < 0) { if (r < 0) {
LOG_ERR("%s,%s: %s: failed to get current volume", LOG_ERR("%s,%s: %s: failed to get current volume", m->card, m->mixer, chan->name);
m->card, m->mixer, chan->name);
} }
if (chan->vol_cur < min) { if (chan->vol_cur < min) {
LOG_WARN( LOG_WARN("%s,%s: %s: current volume is less than the indicated minimum: "
"%s,%s: %s: current volume is less than the indicated minimum: " "%ld < %ld",
"%ld < %ld", m->card, m->mixer, chan->name, chan->vol_cur, min); m->card, m->mixer, chan->name, chan->vol_cur, min);
chan->vol_cur = min; chan->vol_cur = min;
} }
if (chan->vol_cur > max) { if (chan->vol_cur > max) {
LOG_WARN( LOG_WARN("%s,%s: %s: current volume is greater than the indicated maximum: "
"%s,%s: %s: current volume is greater than the indicated maximum: " "%ld > %ld",
"%ld > %ld", m->card, m->mixer, chan->name, chan->vol_cur, max); m->card, m->mixer, chan->name, chan->vol_cur, max);
chan->vol_cur = max; chan->vol_cur = max;
} }
assert(chan->vol_cur >= min); assert(chan->vol_cur >= min);
assert(chan->vol_cur <= max ); assert(chan->vol_cur <= max);
LOG_DBG("%s,%s: %s: volume: %ld", LOG_DBG("%s,%s: %s: volume: %ld", m->card, m->mixer, chan->name, chan->vol_cur);
m->card, m->mixer, chan->name, chan->vol_cur);
} }
/* Get channels muted state */ /* Get channels muted state */
tll_foreach(m->channels, it) { tll_foreach(m->channels, it)
{
struct channel *chan = &it->item; struct channel *chan = &it->item;
int unmuted; int unmuted;
int r = chan->type == CHANNEL_PLAYBACK int r = chan->type == CHANNEL_PLAYBACK ? snd_mixer_selem_get_playback_switch(elem, chan->id, &unmuted)
? snd_mixer_selem_get_playback_switch(elem, chan->id, &unmuted) : snd_mixer_selem_get_capture_switch(elem, chan->id, &unmuted);
: snd_mixer_selem_get_capture_switch(elem, chan->id, &unmuted);
if (r < 0) { if (r < 0) {
LOG_WARN("%s,%s: %s: failed to get muted state", LOG_WARN("%s,%s: %s: failed to get muted state", m->card, m->mixer, chan->name);
m->card, m->mixer, chan->name);
unmuted = 1; unmuted = 1;
} }
@ -309,10 +294,8 @@ run_while_online(struct module *mod)
return ret; return ret;
} }
if (snd_mixer_attach(handle, m->card) != 0 || if (snd_mixer_attach(handle, m->card) != 0 || snd_mixer_selem_register(handle, NULL, NULL) != 0
snd_mixer_selem_register(handle, NULL, NULL) != 0 || || snd_mixer_load(handle) != 0) {
snd_mixer_load(handle) != 0)
{
LOG_ERR("failed to attach to card"); LOG_ERR("failed to attach to card");
ret = RUN_FAILED_CONNECT; ret = RUN_FAILED_CONNECT;
goto err; goto err;
@ -323,7 +306,7 @@ run_while_online(struct module *mod)
snd_mixer_selem_id_set_index(sid, 0); snd_mixer_selem_id_set_index(sid, 0);
snd_mixer_selem_id_set_name(sid, m->mixer); snd_mixer_selem_id_set_name(sid, m->mixer);
snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
if (elem == NULL) { if (elem == NULL) {
LOG_ERR("failed to find mixer"); LOG_ERR("failed to find mixer");
goto err; goto err;
@ -332,30 +315,24 @@ run_while_online(struct module *mod)
/* Get playback volume range */ /* Get playback volume range */
m->has_playback_volume = snd_mixer_selem_has_playback_volume(elem) > 0; m->has_playback_volume = snd_mixer_selem_has_playback_volume(elem) > 0;
if (m->has_playback_volume) { if (m->has_playback_volume) {
if (snd_mixer_selem_get_playback_volume_range( if (snd_mixer_selem_get_playback_volume_range(elem, &m->playback_vol_min, &m->playback_vol_max) < 0) {
elem, &m->playback_vol_min, &m->playback_vol_max) < 0) LOG_ERR("%s,%s: failed to get playback volume range", m->card, m->mixer);
{
LOG_ERR("%s,%s: failed to get playback volume range",
m->card, m->mixer);
assert(m->playback_vol_min == 0); assert(m->playback_vol_min == 0);
assert(m->playback_vol_max == 0); assert(m->playback_vol_max == 0);
} }
if (m->playback_vol_min > m->playback_vol_max) { if (m->playback_vol_min > m->playback_vol_max) {
LOG_WARN( LOG_WARN("%s,%s: indicated minimum playback volume is greater than the "
"%s,%s: indicated minimum playback volume is greater than the " "maximum: %ld > %ld",
"maximum: %ld > %ld", m->card, m->mixer, m->playback_vol_min, m->playback_vol_max);
m->card, m->mixer, m->playback_vol_min, m->playback_vol_max);
m->playback_vol_min = m->playback_vol_max; m->playback_vol_min = m->playback_vol_max;
} }
} }
if (snd_mixer_selem_get_playback_dB_range( if (snd_mixer_selem_get_playback_dB_range(elem, &m->playback_db_min, &m->playback_db_max) < 0) {
elem, &m->playback_db_min, &m->playback_db_max) < 0) LOG_WARN("%s,%s: failed to get playback dB range, "
{ "will use raw volume values instead",
LOG_WARN( m->card, m->mixer);
"%s,%s: failed to get playback dB range, "
"will use raw volume values instead", m->card, m->mixer);
m->has_playback_db = false; m->has_playback_db = false;
} else } else
m->has_playback_db = true; m->has_playback_db = true;
@ -363,30 +340,24 @@ run_while_online(struct module *mod)
/* Get capture volume range */ /* Get capture volume range */
m->has_capture_volume = snd_mixer_selem_has_capture_volume(elem) > 0; m->has_capture_volume = snd_mixer_selem_has_capture_volume(elem) > 0;
if (m->has_capture_volume) { if (m->has_capture_volume) {
if (snd_mixer_selem_get_capture_volume_range( if (snd_mixer_selem_get_capture_volume_range(elem, &m->capture_vol_min, &m->capture_vol_max) < 0) {
elem, &m->capture_vol_min, &m->capture_vol_max) < 0) LOG_ERR("%s,%s: failed to get capture volume range", m->card, m->mixer);
{
LOG_ERR("%s,%s: failed to get capture volume range",
m->card, m->mixer);
assert(m->capture_vol_min == 0); assert(m->capture_vol_min == 0);
assert(m->capture_vol_max == 0); assert(m->capture_vol_max == 0);
} }
if (m->capture_vol_min > m->capture_vol_max) { if (m->capture_vol_min > m->capture_vol_max) {
LOG_WARN( LOG_WARN("%s,%s: indicated minimum capture volume is greater than the "
"%s,%s: indicated minimum capture volume is greater than the " "maximum: %ld > %ld",
"maximum: %ld > %ld", m->card, m->mixer, m->capture_vol_min, m->capture_vol_max);
m->card, m->mixer, m->capture_vol_min, m->capture_vol_max);
m->capture_vol_min = m->capture_vol_max; m->capture_vol_min = m->capture_vol_max;
} }
} }
if (snd_mixer_selem_get_capture_dB_range( if (snd_mixer_selem_get_capture_dB_range(elem, &m->capture_db_min, &m->capture_db_max) < 0) {
elem, &m->capture_db_min, &m->capture_db_max) < 0) LOG_WARN("%s,%s: failed to get capture dB range, "
{ "will use raw volume values instead",
LOG_WARN( m->card, m->mixer);
"%s,%s: failed to get capture dB range, "
"will use raw volume values instead", m->card, m->mixer);
m->has_capture_db = false; m->has_capture_db = false;
} else } else
m->has_capture_db = true; m->has_capture_db = true;
@ -400,7 +371,7 @@ run_while_online(struct module *mod)
struct channel chan = { struct channel chan = {
.id = i, .id = i,
.type = is_playback ? CHANNEL_PLAYBACK : CHANNEL_CAPTURE, .type = is_playback ? CHANNEL_PLAYBACK : CHANNEL_CAPTURE,
.name = strdup(snd_mixer_selem_channel_name( i)), .name = strdup(snd_mixer_selem_channel_name(i)),
}; };
tll_push_back(m->channels, chan); tll_push_back(m->channels, chan);
} }
@ -413,13 +384,13 @@ run_while_online(struct module *mod)
char channels_str[1024]; char channels_str[1024];
int channels_idx = 0; int channels_idx = 0;
tll_foreach(m->channels, it) { tll_foreach(m->channels, it)
{
const struct channel *chan = &it->item; const struct channel *chan = &it->item;
channels_idx += snprintf( channels_idx += snprintf(&channels_str[channels_idx], sizeof(channels_str) - channels_idx,
&channels_str[channels_idx], sizeof(channels_str) - channels_idx, channels_idx == 0 ? "%s (%s)" : ", %s (%s)", chan->name,
channels_idx == 0 ? "%s (%s)" : ", %s (%s)", chan->type == CHANNEL_PLAYBACK ? "🔊" : "🎤");
chan->name, chan->type == CHANNEL_PLAYBACK ? "🔊" : "🎤");
assert(channels_idx <= sizeof(channels_str)); assert(channels_idx <= sizeof(channels_str));
} }
@ -429,7 +400,8 @@ run_while_online(struct module *mod)
bool volume_channel_is_valid = m->volume_name == NULL; bool volume_channel_is_valid = m->volume_name == NULL;
bool muted_channel_is_valid = m->muted_name == NULL; bool muted_channel_is_valid = m->muted_name == NULL;
tll_foreach(m->channels, it) { tll_foreach(m->channels, it)
{
const struct channel *chan = &it->item; const struct channel *chan = &it->item;
if (m->volume_name != NULL && strcmp(chan->name, m->volume_name) == 0) { if (m->volume_name != NULL && strcmp(chan->name, m->volume_name) == 0) {
m->volume_chan = chan; m->volume_chan = chan;
@ -462,26 +434,14 @@ run_while_online(struct module *mod)
update_state(mod, elem); update_state(mod, elem);
LOG_INFO( LOG_INFO(
"%s,%s: %s range=%ld-%ld, current=%ld%s (sources: volume=%s, muted=%s)", "%s,%s: %s range=%ld-%ld, current=%ld%s (sources: volume=%s, muted=%s)", m->card, m->mixer,
m->card, m->mixer,
m->volume_chan->use_db ? "dB" : "volume", m->volume_chan->use_db ? "dB" : "volume",
(m->volume_chan->type == CHANNEL_PLAYBACK (m->volume_chan->type == CHANNEL_PLAYBACK ? (m->volume_chan->use_db ? m->playback_db_min : m->playback_vol_min)
? (m->volume_chan->use_db : (m->volume_chan->use_db ? m->capture_db_min : m->capture_vol_min)),
? m->playback_db_min (m->volume_chan->type == CHANNEL_PLAYBACK ? (m->volume_chan->use_db ? m->playback_db_max : m->playback_vol_max)
: m->playback_vol_min) : (m->volume_chan->use_db ? m->capture_db_max : m->capture_vol_max)),
: (m->volume_chan->use_db
? m->capture_db_min
: m->capture_vol_min)),
(m->volume_chan->type == CHANNEL_PLAYBACK
? (m->volume_chan->use_db
? m->playback_db_max
: m->playback_vol_max)
: (m->volume_chan->use_db
? m->capture_db_max
: m->capture_vol_max)),
m->volume_chan->use_db ? m->volume_chan->db_cur : m->volume_chan->vol_cur, m->volume_chan->use_db ? m->volume_chan->db_cur : m->volume_chan->vol_cur,
m->muted_chan->muted ? " (muted)" : "", m->muted_chan->muted ? " (muted)" : "", m->volume_chan->name, m->muted_chan->name);
m->volume_chan->name, m->muted_chan->name);
mod->bar->refresh(mod->bar); mod->bar->refresh(mod->bar);
@ -595,8 +555,7 @@ run(struct module *mod)
bool have_create_event = false; bool have_create_event = false;
while (!have_create_event) { while (!have_create_event) {
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = ifd, .events = POLLIN}};
{.fd = ifd, .events = POLLIN}};
int r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1); int r = poll(fds, sizeof(fds) / sizeof(fds[0]), -1);
if (r < 0) { if (r < 0) {
@ -638,7 +597,7 @@ run(struct module *mod)
break; break;
/* Consume inotify data */ /* Consume inotify data */
for (const char *ptr = buf; ptr < buf + len; ) { for (const char *ptr = buf; ptr < buf + len;) {
const struct inotify_event *e = (const struct inotify_event *)ptr; const struct inotify_event *e = (const struct inotify_event *)ptr;
if (e->mask & IN_CREATE) { if (e->mask & IN_CREATE) {
@ -656,23 +615,20 @@ out:
if (wd >= 0) if (wd >= 0)
inotify_rm_watch(ifd, wd); inotify_rm_watch(ifd, wd);
if (ifd >= 0) if (ifd >= 0)
close (ifd); close(ifd);
return ret; return ret;
} }
static struct module * static struct module *
alsa_new(const char *card, const char *mixer, alsa_new(const char *card, const char *mixer, const char *volume_channel_name, const char *muted_channel_name,
const char *volume_channel_name, const char *muted_channel_name,
struct particle *label) struct particle *label)
{ {
struct private *priv = calloc(1, sizeof(*priv)); struct private *priv = calloc(1, sizeof(*priv));
priv->label = label; priv->label = label;
priv->card = strdup(card); priv->card = strdup(card);
priv->mixer = strdup(mixer); priv->mixer = strdup(mixer);
priv->volume_name = priv->volume_name = volume_channel_name != NULL ? strdup(volume_channel_name) : NULL;
volume_channel_name != NULL ? strdup(volume_channel_name) : NULL; priv->muted_name = muted_channel_name != NULL ? strdup(muted_channel_name) : NULL;
priv->muted_name =
muted_channel_name != NULL ? strdup(muted_channel_name) : NULL;
struct module *mod = module_common_new(); struct module *mod = module_common_new();
mod->private = priv; mod->private = priv;
@ -692,12 +648,9 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *muted = yml_get_value(node, "muted"); const struct yml_node *muted = yml_get_value(node, "muted");
const struct yml_node *content = yml_get_value(node, "content"); const struct yml_node *content = yml_get_value(node, "content");
return alsa_new( return alsa_new(yml_value_as_string(card), yml_value_as_string(mixer),
yml_value_as_string(card), volume != NULL ? yml_value_as_string(volume) : NULL,
yml_value_as_string(mixer), muted != NULL ? yml_value_as_string(muted) : NULL, conf_to_particle(content, inherited));
volume != NULL ? yml_value_as_string(volume) : NULL,
muted != NULL ? yml_value_as_string(muted) : NULL,
conf_to_particle(content, inherited));
} }
static bool static bool

View file

@ -1,25 +1,26 @@
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <poll.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <libudev.h> #include <libudev.h>
#define LOG_MODULE "backlight" #define LOG_MODULE "backlight"
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
struct particle *label; struct particle *label;
char *device; char *device;
@ -145,8 +146,7 @@ initialize(struct private *m)
m->current_brightness = readint_from_fd(current_fd); m->current_brightness = readint_from_fd(current_fd);
LOG_INFO("%s: brightness: %ld (max: %ld)", m->device, m->current_brightness, LOG_INFO("%s: brightness: %ld (max: %ld)", m->device, m->current_brightness, m->max_brightness);
m->max_brightness);
return current_fd; return current_fd;
} }
@ -244,8 +244,7 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *name = yml_get_value(node, "name"); const struct yml_node *name = yml_get_value(node, "name");
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
return backlight_new( return backlight_new(yml_value_as_string(name), conf_to_particle(c, inherited));
yml_value_as_string(name), conf_to_particle(c, inherited));
} }
static bool static bool

View file

@ -1,26 +1,26 @@
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <poll.h> #include <poll.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <libudev.h> #include <libudev.h>
#include <tllist.h> #include <tllist.h>
#define LOG_MODULE "battery" #define LOG_MODULE "battery"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
@ -37,7 +37,8 @@ struct current_state {
struct timespec time; struct timespec time;
}; };
struct private { struct private
{
struct particle *label; struct particle *label;
long poll_interval; long poll_interval;
@ -65,7 +66,7 @@ static int64_t
difftimespec_ns(const struct timespec after, const struct timespec before) difftimespec_ns(const struct timespec after, const struct timespec before)
{ {
return ((int64_t)after.tv_sec - (int64_t)before.tv_sec) * (int64_t)one_sec_in_ns return ((int64_t)after.tv_sec - (int64_t)before.tv_sec) * (int64_t)one_sec_in_ns
+ ((int64_t)after.tv_nsec - (int64_t)before.tv_nsec); + ((int64_t)after.tv_nsec - (int64_t)before.tv_nsec);
} }
// Linear Exponential Moving Average (unevenly spaced time series) // Linear Exponential Moving Average (unevenly spaced time series)
@ -88,7 +89,7 @@ ema_linear(struct current_state *state, struct current_state curr, long tau)
w2 = (1 - w) / tmp; w2 = (1 - w) / tmp;
} else { } else {
// Use taylor expansion for numerical stability // Use taylor expansion for numerical stability
w2 = 1 - tmp/2 + tmp*tmp/6 - tmp*tmp*tmp/24; w2 = 1 - tmp / 2 + tmp * tmp / 6 - tmp * tmp * tmp / 24;
} }
double ema = state->ema * w + curr.current * (1 - w2) + state->current * (w2 - w); double ema = state->ema * w + curr.current * (1 - w2) + state->current * (w2 - w);
@ -101,8 +102,7 @@ ema_linear(struct current_state *state, struct current_state curr, long tau)
} }
static void static void
timespec_sub(const struct timespec *a, const struct timespec *b, timespec_sub(const struct timespec *a, const struct timespec *b, struct timespec *res)
struct timespec *res)
{ {
res->tv_sec = a->tv_sec - b->tv_sec; res->tv_sec = a->tv_sec - b->tv_sec;
@ -145,11 +145,8 @@ content(struct module *mod)
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
assert(m->state == STATE_FULL || assert(m->state == STATE_FULL || m->state == STATE_NOTCHARGING || m->state == STATE_CHARGING
m->state == STATE_NOTCHARGING || || m->state == STATE_DISCHARGING || m->state == STATE_UNKNOWN);
m->state == STATE_CHARGING ||
m->state == STATE_DISCHARGING ||
m->state == STATE_UNKNOWN);
unsigned long hours; unsigned long hours;
unsigned long minutes; unsigned long minutes;
@ -162,9 +159,8 @@ content(struct module *mod)
minutes = m->time_to_full / 60; minutes = m->time_to_full / 60;
hours = minutes / 60; hours = minutes / 60;
minutes = minutes % 60; minutes = minutes % 60;
} else if (m->energy_full >= 0 && m->charge && m->power >= 0) { } else if (m->energy_full >= 0 && m->charge && m->power >= 0) {
unsigned long energy = m->state == STATE_CHARGING unsigned long energy = m->state == STATE_CHARGING ? m->energy_full - m->energy : m->energy;
? m->energy_full - m->energy : m->energy;
double hours_as_float; double hours_as_float;
if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING) if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING)
@ -177,8 +173,7 @@ content(struct module *mod)
hours = hours_as_float; hours = hours_as_float;
minutes = (hours_as_float - (double)hours) * 60; minutes = (hours_as_float - (double)hours) * 60;
} else if (m->charge_full >= 0 && m->charge >= 0 && m->ema_current.current >= 0) { } else if (m->charge_full >= 0 && m->charge >= 0 && m->ema_current.current >= 0) {
unsigned long charge = m->state == STATE_CHARGING unsigned long charge = m->state == STATE_CHARGING ? m->charge_full - m->charge : m->charge;
? m->charge_full - m->charge : m->charge;
double hours_as_float; double hours_as_float;
if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING) if (m->state == STATE_FULL || m->state == STATE_NOTCHARGING)
@ -281,8 +276,7 @@ initialize(struct private *m)
{ {
int fd = openat(base_dir_fd, "manufacturer", O_RDONLY); int fd = openat(base_dir_fd, "manufacturer", O_RDONLY);
if (fd == -1) { if (fd == -1) {
LOG_WARN("/sys/class/power_supply/%s/manufacturer: %s", LOG_WARN("/sys/class/power_supply/%s/manufacturer: %s", m->battery, strerror(errno));
m->battery, strerror(errno));
m->manufacturer = NULL; m->manufacturer = NULL;
} else { } else {
m->manufacturer = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf)); m->manufacturer = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf));
@ -293,8 +287,7 @@ initialize(struct private *m)
{ {
int fd = openat(base_dir_fd, "model_name", O_RDONLY); int fd = openat(base_dir_fd, "model_name", O_RDONLY);
if (fd == -1) { if (fd == -1) {
LOG_WARN("/sys/class/power_supply/%s/model_name: %s", LOG_WARN("/sys/class/power_supply/%s/model_name: %s", m->battery, strerror(errno));
m->battery, strerror(errno));
m->model = NULL; m->model = NULL;
} else { } else {
m->model = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf)); m->model = strdup(readline_from_fd(fd, sizeof(line_buf), line_buf));
@ -302,9 +295,8 @@ initialize(struct private *m)
} }
} }
if (faccessat(base_dir_fd, "energy_full_design", O_RDONLY, 0) == 0 && if (faccessat(base_dir_fd, "energy_full_design", O_RDONLY, 0) == 0
faccessat(base_dir_fd, "energy_full", O_RDONLY, 0) == 0) && faccessat(base_dir_fd, "energy_full", O_RDONLY, 0) == 0) {
{
{ {
int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY); int fd = openat(base_dir_fd, "energy_full_design", O_RDONLY);
if (fd == -1) { if (fd == -1) {
@ -330,9 +322,8 @@ initialize(struct private *m)
m->energy_full = m->energy_full_design = -1; m->energy_full = m->energy_full_design = -1;
} }
if (faccessat(base_dir_fd, "charge_full_design", O_RDONLY, 0) == 0 && if (faccessat(base_dir_fd, "charge_full_design", O_RDONLY, 0) == 0
faccessat(base_dir_fd, "charge_full", O_RDONLY, 0) == 0) && faccessat(base_dir_fd, "charge_full", O_RDONLY, 0) == 0) {
{
{ {
int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY); int fd = openat(base_dir_fd, "charge_full_design", O_RDONLY);
if (fd == -1) { if (fd == -1) {
@ -462,8 +453,8 @@ update_status(struct module *mod)
} }
LOG_DBG("capacity: %ld, energy: %ld, power: %ld, charge=%ld, current=%ld, " LOG_DBG("capacity: %ld, energy: %ld, power: %ld, charge=%ld, current=%ld, "
"time-to-empty: %ld, time-to-full: %ld", capacity, "time-to-empty: %ld, time-to-full: %ld",
energy, power, charge, current, time_to_empty, time_to_full); capacity, energy, power, charge, current, time_to_empty, time_to_full);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
if (m->state != state) { if (m->state != state) {
@ -494,13 +485,10 @@ run(struct module *mod)
if (!initialize(m)) if (!initialize(m))
return -1; return -1;
LOG_INFO("%s: %s %s (at %.1f%% of original capacity)", LOG_INFO("%s: %s %s (at %.1f%% of original capacity)", m->battery, m->manufacturer, m->model,
m->battery, m->manufacturer, m->model, (m->energy_full > 0 ? 100.0 * m->energy_full / m->energy_full_design
(m->energy_full > 0 : m->charge_full > 0 ? 100.0 * m->charge_full / m->charge_full_design
? 100.0 * m->energy_full / m->energy_full_design : 0.0));
: m->charge_full > 0
? 100.0 * m->charge_full / m->charge_full_design
: 0.0));
int ret = 1; int ret = 1;
@ -555,12 +543,11 @@ run(struct module *mod)
struct udev_device *dev = udev_monitor_receive_device(mon); struct udev_device *dev = udev_monitor_receive_device(mon);
if (dev != NULL) { if (dev != NULL) {
const char *sysname = udev_device_get_sysname(dev); const char *sysname = udev_device_get_sysname(dev);
udev_for_us = udev_for_us = sysname != NULL && strcmp(sysname, m->battery) == 0;
sysname != NULL && strcmp(sysname, m->battery) == 0;
if (!udev_for_us) { if (!udev_for_us) {
LOG_DBG("udev notification not for us (%s != %s)", LOG_DBG("udev notification not for us (%s != %s)", m->battery,
m->battery, sysname != sysname ? sysname : "NULL"); sysname != sysname ? sysname : "NULL");
} else } else
LOG_DBG("triggering update due to udev notification"); LOG_DBG("triggering update due to udev notification");
@ -586,11 +573,9 @@ run(struct module *mod)
struct timespec timeout_consumed; struct timespec timeout_consumed;
timespec_sub(&time_after_poll, &time_before_poll, &timeout_consumed); timespec_sub(&time_after_poll, &time_before_poll, &timeout_consumed);
const int timeout_consumed_ms = const int timeout_consumed_ms = timeout_consumed.tv_sec * 1000 + timeout_consumed.tv_nsec / 1000000;
timeout_consumed.tv_sec * 1000 + timeout_consumed.tv_nsec / 1000000;
LOG_DBG("timeout-left before: %dms, consumed: %dms, updated: %dms", LOG_DBG("timeout-left before: %dms, consumed: %dms, updated: %dms", timeout_left_ms, timeout_consumed_ms,
timeout_left_ms, timeout_consumed_ms,
max(timeout_left_ms - timeout_consumed_ms, 0)); max(timeout_left_ms - timeout_consumed_ms, 0));
timeout_left_ms -= timeout_consumed_ms; timeout_left_ms -= timeout_consumed_ms;
@ -608,7 +593,8 @@ out:
} }
static struct module * static struct module *
battery_new(const char *battery, struct particle *label, long poll_interval_msecs, int battery_scale, long smoothing_secs) battery_new(const char *battery, struct particle *label, long poll_interval_msecs, int battery_scale,
long smoothing_secs)
{ {
struct private *m = calloc(1, sizeof(*m)); struct private *m = calloc(1, sizeof(*m));
m->label = label; m->label = label;
@ -617,7 +603,7 @@ battery_new(const char *battery, struct particle *label, long poll_interval_msec
m->smoothing_scale = smoothing_secs * one_sec_in_ns; m->smoothing_scale = smoothing_secs * one_sec_in_ns;
m->battery = strdup(battery); m->battery = strdup(battery);
m->state = STATE_UNKNOWN; m->state = STATE_UNKNOWN;
m->ema_current = (struct current_state){ -1, 0, (struct timespec){0, 0} }; m->ema_current = (struct current_state){-1, 0, (struct timespec){0, 0}};
struct module *mod = module_common_new(); struct module *mod = module_common_new();
mod->private = m; mod->private = m;
@ -637,18 +623,10 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *battery_scale = yml_get_value(node, "battery-scale"); const struct yml_node *battery_scale = yml_get_value(node, "battery-scale");
const struct yml_node *smoothing_secs = yml_get_value(node, "smoothing-secs"); const struct yml_node *smoothing_secs = yml_get_value(node, "smoothing-secs");
return battery_new( return battery_new(yml_value_as_string(name), conf_to_particle(c, inherited),
yml_value_as_string(name), (poll_interval != NULL ? yml_value_as_int(poll_interval) : default_poll_interval),
conf_to_particle(c, inherited), (battery_scale != NULL ? yml_value_as_int(battery_scale) : 1),
(poll_interval != NULL (smoothing_secs != NULL ? yml_value_as_int(smoothing_secs) : 100));
? yml_value_as_int(poll_interval)
: default_poll_interval),
(battery_scale != NULL
? yml_value_as_int(battery_scale)
: 1),
(smoothing_secs != NULL
? yml_value_as_int(smoothing_secs)
: 100));
} }
static bool static bool
@ -660,8 +638,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
const long value = yml_value_as_int(node); const long value = yml_value_as_int(node);
if (value != 0 && value < min_poll_interval) { if (value != 0 && value < min_poll_interval) {
LOG_ERR("%s: interval value cannot be less than %ldms", LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -1,21 +1,22 @@
#include <assert.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <assert.h>
#include <errno.h>
#include <poll.h> #include <poll.h>
#include <sys/time.h> #include <sys/time.h>
#define LOG_MODULE "clock" #define LOG_MODULE "clock"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
struct particle *label; struct particle *label;
enum { enum {
UPDATE_GRANULARITY_SECONDS, UPDATE_GRANULARITY_SECONDS,
@ -57,8 +58,7 @@ content(struct module *mod)
strftime(time_str, sizeof(time_str), m->time_format, tm); strftime(time_str, sizeof(time_str), m->time_format, tm);
struct tag_set tags = { struct tag_set tags = {
.tags = (struct tag *[]){tag_new_string(mod, "time", time_str), .tags = (struct tag *[]){tag_new_string(mod, "time", time_str), tag_new_string(mod, "date", date_str)},
tag_new_string(mod, "date", date_str)},
.count = 2, .count = 2,
}; };
@ -90,15 +90,12 @@ run(struct module *mod)
switch (m->update_granularity) { switch (m->update_granularity) {
case UPDATE_GRANULARITY_SECONDS: { case UPDATE_GRANULARITY_SECONDS: {
const struct timeval next_second = { const struct timeval next_second = {.tv_sec = now.tv_sec + 1, .tv_usec = 0};
.tv_sec = now.tv_sec + 1,
.tv_usec = 0};
struct timeval _timeout; struct timeval _timeout;
timersub(&next_second, &now, &_timeout); timersub(&next_second, &now, &_timeout);
assert(_timeout.tv_sec == 0 || assert(_timeout.tv_sec == 0 || (_timeout.tv_sec == 1 && _timeout.tv_usec == 0));
(_timeout.tv_sec == 1 && _timeout.tv_usec == 0));
timeout_ms = _timeout.tv_usec / 1000; timeout_ms = _timeout.tv_usec / 1000;
break; break;
} }
@ -118,8 +115,7 @@ run(struct module *mod)
/* Add 1ms to account for rounding errors */ /* Add 1ms to account for rounding errors */
timeout_ms++; timeout_ms++;
LOG_DBG("now: %lds %ldµs -> timeout: %dms", LOG_DBG("now: %lds %ldµs -> timeout: %dms", now.tv_sec, now.tv_usec, timeout_ms);
now.tv_sec, now.tv_usec, timeout_ms);
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}}; struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}};
if (poll(fds, 1, timeout_ms) < 0) { if (poll(fds, 1, timeout_ms) < 0) {
@ -142,8 +138,7 @@ run(struct module *mod)
} }
static struct module * static struct module *
clock_new(struct particle *label, const char *date_format, clock_new(struct particle *label, const char *date_format, const char *time_format, bool utc)
const char *time_format, bool utc)
{ {
struct private *m = calloc(1, sizeof(*m)); struct private *m = calloc(1, sizeof(*m));
m->label = label; m->label = label;
@ -152,20 +147,12 @@ clock_new(struct particle *label, const char *date_format,
m->utc = utc; m->utc = utc;
static const char *const seconds_formatters[] = { static const char *const seconds_formatters[] = {
"%c", "%c", "%s", "%S", "%T", "%r", "%X",
"%s",
"%S",
"%T",
"%r",
"%X",
}; };
m->update_granularity = UPDATE_GRANULARITY_MINUTES; m->update_granularity = UPDATE_GRANULARITY_MINUTES;
for (size_t i = 0; for (size_t i = 0; i < sizeof(seconds_formatters) / sizeof(seconds_formatters[0]); i++) {
i < sizeof(seconds_formatters) / sizeof(seconds_formatters[0]);
i++)
{
if (strstr(time_format, seconds_formatters[i]) != NULL) { if (strstr(time_format, seconds_formatters[i]) != NULL) {
m->update_granularity = UPDATE_GRANULARITY_SECONDS; m->update_granularity = UPDATE_GRANULARITY_SECONDS;
break; break;
@ -173,8 +160,7 @@ clock_new(struct particle *label, const char *date_format,
} }
LOG_DBG("using %s update granularity", LOG_DBG("using %s update granularity",
(m->update_granularity == UPDATE_GRANULARITY_MINUTES (m->update_granularity == UPDATE_GRANULARITY_MINUTES ? "minutes" : "seconds"));
? "minutes" : "seconds"));
struct module *mod = module_common_new(); struct module *mod = module_common_new();
mod->private = m; mod->private = m;
@ -193,11 +179,9 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *time_format = yml_get_value(node, "time-format"); const struct yml_node *time_format = yml_get_value(node, "time-format");
const struct yml_node *utc = yml_get_value(node, "utc"); const struct yml_node *utc = yml_get_value(node, "utc");
return clock_new( return clock_new(conf_to_particle(c, inherited), date_format != NULL ? yml_value_as_string(date_format) : "%x",
conf_to_particle(c, inherited), time_format != NULL ? yml_value_as_string(time_format) : "%H:%M",
date_format != NULL ? yml_value_as_string(date_format) : "%x", utc != NULL ? yml_value_as_bool(utc) : false);
time_format != NULL ? yml_value_as_string(time_format) : "%H:%M",
utc != NULL ? yml_value_as_bool(utc) : false);
} }
static bool static bool

View file

@ -31,7 +31,8 @@ struct cpu_stats {
uint32_t *cur_cores_nidle; uint32_t *cur_cores_nidle;
}; };
struct private { struct private
{
struct particle *template; struct particle *template;
uint16_t interval; uint16_t interval;
size_t core_count; size_t core_count;
@ -69,28 +70,22 @@ get_cpu_nb_cores()
} }
static bool static bool
parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice, parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice, uint32_t *system, uint32_t *idle,
uint32_t *system, uint32_t *idle, uint32_t *iowait, uint32_t *iowait, uint32_t *irq, uint32_t *softirq, uint32_t *steal, uint32_t *guest,
uint32_t *irq, uint32_t *softirq, uint32_t *steal, uint32_t *guestnice)
uint32_t *guest, uint32_t *guestnice)
{ {
int32_t core_id; int32_t core_id;
if (line[sizeof("cpu") - 1] == ' ') { if (line[sizeof("cpu") - 1] == ' ') {
int read = sscanf( int read = sscanf(line,
line, "cpu %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32
"cpu %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32,
" %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32, user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice);
user, nice, system, idle, iowait, irq, softirq, steal, guest,
guestnice);
return read == 10; return read == 10;
} else { } else {
int read = sscanf( int read = sscanf(line,
line, "cpu%" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32
"cpu%" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32,
" %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 &core_id, user, nice, system, idle, iowait, irq, softirq, steal, guest, guestnice);
" %" SCNu32,
&core_id, user, nice, system, idle, iowait, irq, softirq, steal,
guest, guestnice);
return read == 11; return read == 11;
} }
} }
@ -98,18 +93,12 @@ parse_proc_stat_line(const char *line, uint32_t *user, uint32_t *nice,
static uint8_t static uint8_t
get_cpu_usage_percent(const struct cpu_stats *cpu_stats, int8_t core_idx) get_cpu_usage_percent(const struct cpu_stats *cpu_stats, int8_t core_idx)
{ {
uint32_t prev_total = uint32_t prev_total = cpu_stats->prev_cores_idle[core_idx + 1] + cpu_stats->prev_cores_nidle[core_idx + 1];
cpu_stats->prev_cores_idle[core_idx + 1] +
cpu_stats->prev_cores_nidle[core_idx + 1];
uint32_t cur_total = uint32_t cur_total = cpu_stats->cur_cores_idle[core_idx + 1] + cpu_stats->cur_cores_nidle[core_idx + 1];
cpu_stats->cur_cores_idle[core_idx + 1] +
cpu_stats->cur_cores_nidle[core_idx + 1];
double totald = cur_total - prev_total; double totald = cur_total - prev_total;
double nidled = double nidled = cpu_stats->cur_cores_nidle[core_idx + 1] - cpu_stats->prev_cores_nidle[core_idx + 1];
cpu_stats->cur_cores_nidle[core_idx + 1] -
cpu_stats->prev_cores_nidle[core_idx + 1];
double percent = (nidled * 100) / (totald + 1); double percent = (nidled * 100) / (totald + 1);
return round(percent); return round(percent);
@ -143,10 +132,8 @@ refresh_cpu_stats(struct cpu_stats *cpu_stats, size_t core_count)
while ((read = getline(&line, &len, fp)) != -1 && core <= core_count) { while ((read = getline(&line, &len, fp)) != -1 && core <= core_count) {
if (strncmp(line, "cpu", sizeof("cpu") - 1) == 0) { if (strncmp(line, "cpu", sizeof("cpu") - 1) == 0) {
if (!parse_proc_stat_line( if (!parse_proc_stat_line(line, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &steal, &guest,
line, &user, &nice, &system, &idle, &iowait, &irq, &softirq, &guestnice)) {
&steal, &guest, &guestnice))
{
LOG_ERR("unable to parse /proc/stat line"); LOG_ERR("unable to parse /proc/stat line");
goto exit; goto exit;
} }
@ -251,15 +238,11 @@ cpu_new(uint16_t interval, struct particle *template)
p->interval = interval; p->interval = interval;
p->core_count = nb_cores; p->core_count = nb_cores;
p->cpu_stats.prev_cores_nidle = calloc( p->cpu_stats.prev_cores_nidle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_nidle));
nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_nidle)); p->cpu_stats.prev_cores_idle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_idle));
p->cpu_stats.prev_cores_idle = calloc(
nb_cores + 1, sizeof(*p->cpu_stats.prev_cores_idle));
p->cpu_stats.cur_cores_nidle = calloc( p->cpu_stats.cur_cores_nidle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_nidle));
nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_nidle)); p->cpu_stats.cur_cores_idle = calloc(nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_idle));
p->cpu_stats.cur_cores_idle = calloc(
nb_cores + 1, sizeof(*p->cpu_stats.cur_cores_idle));
struct module *mod = module_common_new(); struct module *mod = module_common_new();
mod->private = p; mod->private = p;
@ -276,9 +259,7 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *interval = yml_get_value(node, "poll-interval"); const struct yml_node *interval = yml_get_value(node, "poll-interval");
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
return cpu_new( return cpu_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval), conf_to_particle(c, inherited));
interval == NULL ? min_poll_interval : yml_value_as_int(interval),
conf_to_particle(c, inherited));
} }
static bool static bool
@ -288,8 +269,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
return false; return false;
if (yml_value_as_int(node) < min_poll_interval) { if (yml_value_as_int(node) < min_poll_interval) {
LOG_ERR("%s: interval value cannot be less than %ldms", LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -1,9 +1,9 @@
#include <dirent.h>
#include <errno.h> #include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include <poll.h> #include <poll.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <dirent.h>
#include <tllist.h> #include <tllist.h>
@ -34,7 +34,8 @@ struct device_stats {
bool exists; bool exists;
}; };
struct private { struct private
{
struct particle *label; struct particle *label;
uint16_t interval; uint16_t interval;
tll(struct device_stats *) devices; tll(struct device_stats *) devices;
@ -63,7 +64,7 @@ is_disk(char const *name)
return found; return found;
} }
static struct device_stats* static struct device_stats *
new_device_stats(char const *name) new_device_stats(char const *name)
{ {
struct device_stats *dev = malloc(sizeof(*dev)); struct device_stats *dev = malloc(sizeof(*dev));
@ -84,9 +85,7 @@ destroy(struct module *mod)
{ {
struct private *m = mod->private; struct private *m = mod->private;
m->label->destroy(m->label); m->label->destroy(m->label);
tll_foreach(m->devices, it) { tll_foreach(m->devices, it) { free_device_stats(it->item); }
free_device_stats(it->item);
}
tll_free(m->devices); tll_free(m->devices);
free(m); free(m);
module_default_destroy(mod); module_default_destroy(mod);
@ -126,9 +125,7 @@ refresh_device_stats(struct private *m)
* The 'exists' variable is what keep tracks of whether or not /proc/diskstats * The 'exists' variable is what keep tracks of whether or not /proc/diskstats
* is still reporting the device (i.e., it is still connected). * is still reporting the device (i.e., it is still connected).
*/ */
tll_foreach(m->devices, it) { tll_foreach(m->devices, it) { it->item->exists = false; }
it->item->exists = false;
}
while ((read = getline(&line, &len, fp)) != -1) { while ((read = getline(&line, &len, fp)) != -1) {
/* /*
@ -156,25 +153,23 @@ refresh_device_stats(struct private *m)
uint32_t completed_flushes = 0; uint32_t completed_flushes = 0;
uint32_t flushing_time = 0; uint32_t flushing_time = 0;
if (!sscanf(line, if (!sscanf(line,
" %" SCNu8 " %" SCNu8 " %ms %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu8 " %" SCNu8 " %ms %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32
" %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu64 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32
" %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32 " %" SCNu32,
" %" SCNu32, &major_number, &minor_number, &device_name, &completed_reads, &merged_reads, &sectors_read,
&major_number, &minor_number, &device_name, &completed_reads, &reading_time, &completed_writes, &merged_writes, &sectors_written, &writting_time,
&merged_reads, &sectors_read, &reading_time, &completed_writes, &ios_in_progress, &io_time, &io_weighted_time, &completed_discards, &merged_discards,
&merged_writes, &sectors_written, &writting_time, &ios_in_progress, &sectors_discarded, &discarding_time, &completed_flushes, &flushing_time)) {
&io_time, &io_weighted_time, &completed_discards, &merged_discards,
&sectors_discarded, &discarding_time, &completed_flushes, &flushing_time))
{
LOG_ERR("unable to parse /proc/diskstats line"); LOG_ERR("unable to parse /proc/diskstats line");
free(device_name); free(device_name);
goto exit; goto exit;
} }
bool found = false; bool found = false;
tll_foreach(m->devices, it) { tll_foreach(m->devices, it)
{
struct device_stats *dev = it->item; struct device_stats *dev = it->item;
if (strcmp(dev->name, device_name) == 0){ if (strcmp(dev->name, device_name) == 0) {
dev->prev_sectors_read = dev->cur_sectors_read; dev->prev_sectors_read = dev->cur_sectors_read;
dev->prev_sectors_written = dev->cur_sectors_written; dev->prev_sectors_written = dev->cur_sectors_written;
dev->ios_in_progress = ios_in_progress; dev->ios_in_progress = ios_in_progress;
@ -200,8 +195,9 @@ refresh_device_stats(struct private *m)
free(device_name); free(device_name);
} }
tll_foreach(m->devices, it) { tll_foreach(m->devices, it)
if (!it->item->exists){ {
if (!it->item->exists) {
free_device_stats(it->item); free_device_stats(it->item);
tll_remove(m->devices, it); tll_remove(m->devices, it);
} }
@ -221,12 +217,13 @@ content(struct module *mod)
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
struct exposable *tag_parts[p->devices.length + 1]; struct exposable *tag_parts[p->devices.length + 1];
int i = 0; int i = 0;
tll_foreach(p->devices, it) { tll_foreach(p->devices, it)
{
struct device_stats *dev = it->item; struct device_stats *dev = it->item;
uint64_t bytes_read = (dev->cur_sectors_read - dev->prev_sectors_read) * 512; uint64_t bytes_read = (dev->cur_sectors_read - dev->prev_sectors_read) * 512;
uint64_t bytes_written = (dev->cur_sectors_written - dev->prev_sectors_written) * 512; uint64_t bytes_written = (dev->cur_sectors_written - dev->prev_sectors_written) * 512;
if (dev->is_disk){ if (dev->is_disk) {
total_bytes_read += bytes_read; total_bytes_read += bytes_read;
total_bytes_written += bytes_written; total_bytes_written += bytes_written;
total_ios_in_progress += dev->ios_in_progress; total_ios_in_progress += dev->ios_in_progress;
@ -314,9 +311,8 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *interval = yml_get_value(node, "poll-interval"); const struct yml_node *interval = yml_get_value(node, "poll-interval");
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
return disk_io_new( return disk_io_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval),
interval == NULL ? min_poll_interval : yml_value_as_int(interval), conf_to_particle(c, inherited));
conf_to_particle(c, inherited));
} }
static bool static bool
@ -326,9 +322,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
return false; return false;
if (yml_value_as_int(node) < min_poll_interval) { if (yml_value_as_int(node) < min_poll_interval) {
LOG_ERR( LOG_ERR("%s: poll-interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
"%s: poll-interval value cannot be less than %ldms",
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -249,13 +249,16 @@ process_line(char *line, struct module *module)
assert(false); /* unreachable */ assert(false); /* unreachable */
break; break;
case LINE_MODE_FULLSCREEN: case LINE_MODE_FULLSCREEN:
private->fullscreen = (strcmp(string, "0") != 0); private
->fullscreen = (strcmp(string, "0") != 0);
break; break;
case LINE_MODE_FLOATING: case LINE_MODE_FLOATING:
private->floating = (strcmp(string, "0") != 0); private
->floating = (strcmp(string, "0") != 0);
break; break;
case LINE_MODE_SELMON: case LINE_MODE_SELMON:
private->selmon = (strcmp(string, "0") != 0); private
->selmon = (strcmp(string, "0") != 0);
break; break;
case LINE_MODE_LAYOUT: case LINE_MODE_LAYOUT:
free(private->layout); free(private->layout);
@ -438,8 +441,7 @@ run(struct module *module)
} }
static struct module * static struct module *
dwl_new(struct particle *label, int number_of_tags, dwl_new(struct particle *label, int number_of_tags, struct yml_node const *name_of_tags, char const *dwl_info_filename)
struct yml_node const *name_of_tags, char const *dwl_info_filename)
{ {
struct private *private = calloc(1, sizeof(struct private)); struct private *private = calloc(1, sizeof(struct private));
private->label = label; private->label = label;
@ -480,8 +482,8 @@ from_conf(struct yml_node const *node, struct conf_inherit inherited)
struct yml_node const *name_of_tags = yml_get_value(node, "name-of-tags"); struct yml_node const *name_of_tags = yml_get_value(node, "name-of-tags");
struct yml_node const *dwl_info_filename = yml_get_value(node, "dwl-info-filename"); struct yml_node const *dwl_info_filename = yml_get_value(node, "dwl-info-filename");
return dwl_new(conf_to_particle(content, inherited), yml_value_as_int(number_of_tags), return dwl_new(conf_to_particle(content, inherited), yml_value_as_int(number_of_tags), name_of_tags,
name_of_tags, yml_value_as_string(dwl_info_filename)); yml_value_as_string(dwl_info_filename));
} }
static bool static bool

View file

@ -1,7 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h> #include <poll.h>
@ -11,8 +11,8 @@
#define LOG_MODULE "foreign-toplevel" #define LOG_MODULE "foreign-toplevel"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h" #include "../log.h"
#include "../plugin.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h"
#include "wlr-foreign-toplevel-management-unstable-v1.h" #include "wlr-foreign-toplevel-management-unstable-v1.h"
#include "xdg-output-unstable-v1.h" #include "xdg-output-unstable-v1.h"
@ -46,7 +46,8 @@ struct toplevel {
tll(const struct output *) outputs; tll(const struct output *) outputs;
}; };
struct private { struct private
{
struct particle *template; struct particle *template;
uint32_t manager_wl_name; uint32_t manager_wl_name;
struct zwlr_foreign_toplevel_manager_v1 *manager; struct zwlr_foreign_toplevel_manager_v1 *manager;
@ -110,7 +111,8 @@ content(struct module *mod)
const char *current_output = mod->bar->output_name(mod->bar); const char *current_output = mod->bar->output_name(mod->bar);
tll_foreach(m->toplevels, it) { tll_foreach(m->toplevels, it)
{
const struct toplevel *top = &it->item; const struct toplevel *top = &it->item;
bool show = false; bool show = false;
@ -118,11 +120,10 @@ content(struct module *mod)
if (m->all_monitors) if (m->all_monitors)
show = true; show = true;
else if (current_output != NULL) { else if (current_output != NULL) {
tll_foreach(top->outputs, it2) { tll_foreach(top->outputs, it2)
{
const struct output *output = it2->item; const struct output *output = it2->item;
if (output->name != NULL && if (output->name != NULL && strcmp(output->name, current_output) == 0) {
strcmp(output->name, current_output) == 0)
{
show = true; show = true;
break; break;
} }
@ -158,22 +159,18 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted)
if (version >= wanted) if (version >= wanted)
return true; return true;
LOG_ERR("%s: need interface version %u, but compositor only implements %u", LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version);
iface, wanted, version);
return false; return false;
} }
static void static void
xdg_output_handle_logical_position(void *data, xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y)
struct zxdg_output_v1 *xdg_output,
int32_t x, int32_t y)
{ {
} }
static void static void
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height)
int32_t width, int32_t height)
{ {
} }
@ -183,8 +180,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
} }
static void static void
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name)
const char *name)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->mod; struct module *mod = output->mod;
@ -198,8 +194,7 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
} }
static void static void
xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description)
const char *description)
{ {
} }
@ -238,8 +233,7 @@ app_id(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, const char *a
} }
static void static void
output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct toplevel *top = data; struct toplevel *top = data;
struct module *mod = top->mod; struct module *mod = top->mod;
@ -248,7 +242,8 @@ output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
const struct output *output = NULL; const struct output *output = NULL;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
if (it->item.wl_output == wl_output) { if (it->item.wl_output == wl_output) {
output = &it->item; output = &it->item;
break; break;
@ -260,7 +255,8 @@ output_enter(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
goto out; goto out;
} }
tll_foreach(top->outputs, it) { tll_foreach(top->outputs, it)
{
if (it->item == output) { if (it->item == output) {
LOG_ERR("output-enter event on output we're already on"); LOG_ERR("output-enter event on output we're already on");
goto out; goto out;
@ -275,8 +271,7 @@ out:
} }
static void static void
output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct toplevel *top = data; struct toplevel *top = data;
struct module *mod = top->mod; struct module *mod = top->mod;
@ -285,7 +280,8 @@ output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
const struct output *output = NULL; const struct output *output = NULL;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
if (it->item.wl_output == wl_output) { if (it->item.wl_output == wl_output) {
output = &it->item; output = &it->item;
break; break;
@ -298,10 +294,10 @@ output_leave(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
} }
bool output_removed = false; bool output_removed = false;
tll_foreach(top->outputs, it) { tll_foreach(top->outputs, it)
{
if (it->item == output) { if (it->item == output) {
LOG_DBG("unmapped: %s:%s from %s", LOG_DBG("unmapped: %s:%s from %s", top->app_id, top->title, output->name);
top->app_id, top->title, output->name);
tll_remove(top->outputs, it); tll_remove(top->outputs, it);
output_removed = true; output_removed = true;
break; break;
@ -318,8 +314,7 @@ out:
} }
static void static void
state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct wl_array *states)
struct wl_array *states)
{ {
struct toplevel *top = data; struct toplevel *top = data;
@ -329,12 +324,21 @@ state(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle,
bool fullscreen = false; bool fullscreen = false;
enum zwlr_foreign_toplevel_handle_v1_state *state; enum zwlr_foreign_toplevel_handle_v1_state *state;
wl_array_for_each(state, states) { wl_array_for_each(state, states)
{
switch (*state) { switch (*state) {
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED: maximized = true; break; case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MAXIMIZED:
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED: minimized = true; break; maximized = true;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED: activated = true; break; break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN: fullscreen = true; break; case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_MINIMIZED:
minimized = true;
break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_ACTIVATED:
activated = true;
break;
case ZWLR_FOREIGN_TOPLEVEL_HANDLE_V1_STATE_FULLSCREEN:
fullscreen = true;
break;
} }
} }
@ -364,7 +368,8 @@ closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle)
struct private *m = mod->private; struct private *m = mod->private;
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_foreach(m->toplevels, it) { tll_foreach(m->toplevels, it)
{
if (it->item.handle == handle) { if (it->item.handle == handle) {
toplevel_free(top); toplevel_free(top);
tll_remove(m->toplevels, it); tll_remove(m->toplevels, it);
@ -378,9 +383,7 @@ closed(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle)
} }
static void static void
parent(void *data, parent(void *data, struct zwlr_foreign_toplevel_handle_v1 *handle, struct zwlr_foreign_toplevel_handle_v1 *parent)
struct zwlr_foreign_toplevel_handle_v1 *handle,
struct zwlr_foreign_toplevel_handle_v1 *parent)
{ {
} }
@ -396,9 +399,7 @@ static const struct zwlr_foreign_toplevel_handle_v1_listener toplevel_listener =
}; };
static void static void
toplevel(void *data, toplevel(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager, struct zwlr_foreign_toplevel_handle_v1 *handle)
struct zwlr_foreign_toplevel_manager_v1 *manager,
struct zwlr_foreign_toplevel_handle_v1 *handle)
{ {
struct module *mod = data; struct module *mod = data;
struct private *m = mod->private; struct private *m = mod->private;
@ -412,15 +413,13 @@ toplevel(void *data,
{ {
tll_push_back(m->toplevels, toplevel); tll_push_back(m->toplevels, toplevel);
zwlr_foreign_toplevel_handle_v1_add_listener( zwlr_foreign_toplevel_handle_v1_add_listener(handle, &toplevel_listener, &tll_back(m->toplevels));
handle, &toplevel_listener, &tll_back(m->toplevels));
} }
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
} }
static void static void
finished(void *data, finished(void *data, struct zwlr_foreign_toplevel_manager_v1 *manager)
struct zwlr_foreign_toplevel_manager_v1 *manager)
{ {
struct module *mod = data; struct module *mod = data;
struct private *m = mod->private; struct private *m = mod->private;
@ -445,15 +444,12 @@ output_xdg_output(struct output *output)
if (output->xdg_output != NULL) if (output->xdg_output != NULL)
return; return;
output->xdg_output = zxdg_output_manager_v1_get_xdg_output( output->xdg_output = zxdg_output_manager_v1_get_xdg_output(m->xdg_output_manager, output->wl_output);
m->xdg_output_manager, output->wl_output); zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
zxdg_output_v1_add_listener(
output->xdg_output, &xdg_output_listener, output);
} }
static void static void
handle_global(void *data, struct wl_registry *registry, handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
uint32_t name, const char *interface, uint32_t version)
{ {
struct module *mod = data; struct module *mod = data;
struct private *m = mod->private; struct private *m = mod->private;
@ -473,8 +469,7 @@ handle_global(void *data, struct wl_registry *registry,
struct output output = { struct output output = {
.mod = mod, .mod = mod,
.wl_name = name, .wl_name = name,
.wl_output = wl_registry_bind( .wl_output = wl_registry_bind(registry, name, &wl_output_interface, required),
registry, name, &wl_output_interface, required),
}; };
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -488,12 +483,10 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
m->xdg_output_manager = wl_registry_bind( m->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required);
registry, name, &zxdg_output_manager_v1_interface, required);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_foreach(m->outputs, it) tll_foreach(m->outputs, it) output_xdg_output(&it->item);
output_xdg_output(&it->item);
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
} }
} }
@ -506,16 +499,19 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
const struct output *output = &it->item; const struct output *output = &it->item;
if (output->wl_name == name) { if (output->wl_name == name) {
/* Loop all toplevels */ /* Loop all toplevels */
tll_foreach(m->toplevels, it2) { tll_foreach(m->toplevels, it2)
{
/* And remove this output from their list of tracked /* And remove this output from their list of tracked
* outputs */ * outputs */
tll_foreach(it2->item.outputs, it3) { tll_foreach(it2->item.outputs, it3)
{
if (it3->item == output) { if (it3->item == output) {
tll_remove(it2->item.outputs, it3); tll_remove(it2->item.outputs, it3);
break; break;
@ -551,9 +547,8 @@ run(struct module *mod)
goto out; goto out;
} }
if ((registry = wl_display_get_registry(display)) == NULL || if ((registry = wl_display_get_registry(display)) == NULL
wl_registry_add_listener(registry, &registry_listener, mod) != 0) || wl_registry_add_listener(registry, &registry_listener, mod) != 0) {
{
LOG_ERR("failed to get Wayland registry"); LOG_ERR("failed to get Wayland registry");
goto out; goto out;
} }
@ -561,18 +556,14 @@ run(struct module *mod)
wl_display_roundtrip(display); wl_display_roundtrip(display);
if (m->manager_wl_name == 0) { if (m->manager_wl_name == 0) {
LOG_ERR( LOG_ERR("compositor does not implement the foreign-toplevel-manager interface");
"compositor does not implement the foreign-toplevel-manager interface");
goto out; goto out;
} }
m->manager = wl_registry_bind( m->manager = wl_registry_bind(registry, m->manager_wl_name, &zwlr_foreign_toplevel_manager_v1_interface,
registry, m->manager_wl_name, required_manager_interface_version);
&zwlr_foreign_toplevel_manager_v1_interface,
required_manager_interface_version);
zwlr_foreign_toplevel_manager_v1_add_listener( zwlr_foreign_toplevel_manager_v1_add_listener(m->manager, &manager_listener, mod);
m->manager, &manager_listener, mod);
while (true) { while (true) {
wl_display_flush(display); wl_display_flush(display);
@ -606,12 +597,14 @@ run(struct module *mod)
} }
out: out:
tll_foreach(m->toplevels, it) { tll_foreach(m->toplevels, it)
{
toplevel_free(&it->item); toplevel_free(&it->item);
tll_remove(m->toplevels, it); tll_remove(m->toplevels, it);
} }
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
output_free(&it->item); output_free(&it->item);
tll_remove(m->outputs, it); tll_remove(m->outputs, it);
} }
@ -649,9 +642,7 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
const struct yml_node *all_monitors = yml_get_value(node, "all-monitors"); const struct yml_node *all_monitors = yml_get_value(node, "all-monitors");
return ftop_new( return ftop_new(conf_to_particle(c, inherited), all_monitors != NULL ? yml_value_as_bool(all_monitors) : false);
conf_to_particle(c, inherited),
all_monitors != NULL ? yml_value_as_bool(all_monitors) : false);
} }
static bool static bool

View file

@ -1,15 +1,15 @@
#include "i3-common.h" #include "i3-common.h"
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <assert.h>
#include <poll.h> #include <poll.h>
#if defined(ENABLE_X11) #if defined(ENABLE_X11)
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#endif #endif
#include <json-c/json_tokener.h> #include <json-c/json_tokener.h>
@ -19,7 +19,7 @@
#include "../log.h" #include "../log.h"
#if defined(ENABLE_X11) #if defined(ENABLE_X11)
#include "../xcb.h" #include "../xcb.h"
#endif #endif
#include "i3-ipc.h" #include "i3-ipc.h"
@ -41,14 +41,11 @@ get_socket_address_x11(struct sockaddr_un *addr)
xcb_atom_t atom = get_atom(conn, "I3_SOCKET_PATH"); xcb_atom_t atom = get_atom(conn, "I3_SOCKET_PATH");
assert(atom != XCB_ATOM_NONE); assert(atom != XCB_ATOM_NONE);
xcb_get_property_cookie_t cookie xcb_get_property_cookie_t cookie = xcb_get_property_unchecked(conn, false, screen->root, atom,
= xcb_get_property_unchecked( XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr->sun_path));
conn, false, screen->root, atom,
XCB_GET_PROPERTY_TYPE_ANY, 0, sizeof(addr->sun_path));
xcb_generic_error_t *err = NULL; xcb_generic_error_t *err = NULL;
xcb_get_property_reply_t *reply = xcb_get_property_reply_t *reply = xcb_get_property_reply(conn, cookie, &err);
xcb_get_property_reply(conn, cookie, &err);
bool ret = false; bool ret = false;
if (err != NULL) { if (err != NULL) {
@ -102,11 +99,7 @@ bool
i3_send_pkg(int sock, int cmd, char *data) i3_send_pkg(int sock, int cmd, char *data)
{ {
const size_t size = data != NULL ? strlen(data) : 0; const size_t size = data != NULL ? strlen(data) : 0;
const i3_ipc_header_t hdr = { const i3_ipc_header_t hdr = {.magic = I3_IPC_MAGIC, .size = size, .type = cmd};
.magic = I3_IPC_MAGIC,
.size = size,
.type = cmd
};
if (write(sock, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr)) if (write(sock, &hdr, sizeof(hdr)) != (ssize_t)sizeof(hdr))
return false; return false;
@ -120,8 +113,7 @@ i3_send_pkg(int sock, int cmd, char *data)
} }
bool bool
i3_receive_loop(int abort_fd, int sock, i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *cbs, void *data)
const struct i3_ipc_callbacks *cbs, void *data)
{ {
/* Initial reply typically requires a couple of KB. But we often /* Initial reply typically requires a couple of KB. But we often
* need more later. For example, switching workspaces can result * need more later. For example, switching workspaces can result
@ -133,10 +125,7 @@ i3_receive_loop(int abort_fd, int sock,
bool err = false; bool err = false;
while (!err) { while (!err) {
struct pollfd fds[] = { struct pollfd fds[] = {{.fd = abort_fd, .events = POLLIN}, {.fd = sock, .events = POLLIN}};
{.fd = abort_fd, .events = POLLIN},
{.fd = sock, .events = POLLIN}
};
int res = poll(fds, 2, -1); int res = poll(fds, 2, -1);
if (res <= 0) { if (res <= 0) {
@ -159,13 +148,11 @@ i3_receive_loop(int abort_fd, int sock,
/* Grow receive buffer, if necessary */ /* Grow receive buffer, if necessary */
if (buf_idx == reply_buf_size) { if (buf_idx == reply_buf_size) {
LOG_DBG("growing reply buffer: %zu -> %zu", LOG_DBG("growing reply buffer: %zu -> %zu", reply_buf_size, reply_buf_size * 2);
reply_buf_size, reply_buf_size * 2);
char *new_buf = realloc(buf, reply_buf_size * 2); char *new_buf = realloc(buf, reply_buf_size * 2);
if (new_buf == NULL) { if (new_buf == NULL) {
LOG_ERR("failed to grow reply buffer from %zu to %zu bytes", LOG_ERR("failed to grow reply buffer from %zu to %zu bytes", reply_buf_size, reply_buf_size * 2);
reply_buf_size, reply_buf_size * 2);
err = true; err = true;
break; break;
} }
@ -188,10 +175,8 @@ i3_receive_loop(int abort_fd, int sock,
while (!err && buf_idx >= sizeof(i3_ipc_header_t)) { while (!err && buf_idx >= sizeof(i3_ipc_header_t)) {
const i3_ipc_header_t *hdr = (const i3_ipc_header_t *)buf; const i3_ipc_header_t *hdr = (const i3_ipc_header_t *)buf;
if (strncmp(hdr->magic, I3_IPC_MAGIC, sizeof(hdr->magic)) != 0) { if (strncmp(hdr->magic, I3_IPC_MAGIC, sizeof(hdr->magic)) != 0) {
LOG_ERR( LOG_ERR("i3 IPC header magic mismatch: expected \"%.*s\", got \"%.*s\"", (int)sizeof(hdr->magic),
"i3 IPC header magic mismatch: expected \"%.*s\", got \"%.*s\"", I3_IPC_MAGIC, (int)sizeof(hdr->magic), hdr->magic);
(int)sizeof(hdr->magic), I3_IPC_MAGIC,
(int)sizeof(hdr->magic), hdr->magic);
err = true; err = true;
break; break;
@ -210,10 +195,10 @@ i3_receive_loop(int abort_fd, int sock,
char json_str[hdr->size + 1]; char json_str[hdr->size + 1];
memcpy(json_str, &buf[sizeof(*hdr)], hdr->size); memcpy(json_str, &buf[sizeof(*hdr)], hdr->size);
json_str[hdr->size] = '\0'; json_str[hdr->size] = '\0';
//printf("raw: %s\n", json_str); // printf("raw: %s\n", json_str);
LOG_DBG("raw: %s\n", json_str); LOG_DBG("raw: %s\n", json_str);
//json_tokener *tokener = json_tokener_new(); // json_tokener *tokener = json_tokener_new();
struct json_object *json = json_tokener_parse(json_str); struct json_object *json = json_tokener_parse(json_str);
if (json == NULL) { if (json == NULL) {
LOG_ERR("failed to parse json"); LOG_ERR("failed to parse json");
@ -262,13 +247,13 @@ i3_receive_loop(int abort_fd, int sock,
break; break;
#endif #endif
/* Sway extensions */ /* Sway extensions */
case 100: /* IPC_GET_INPUTS */ case 100: /* IPC_GET_INPUTS */
pkt_handler = cbs->reply_inputs; pkt_handler = cbs->reply_inputs;
break; break;
/* /*
* Events * Events
*/ */
case I3_IPC_EVENT_WORKSPACE: case I3_IPC_EVENT_WORKSPACE:
pkt_handler = cbs->event_workspace; pkt_handler = cbs->event_workspace;
@ -295,7 +280,7 @@ i3_receive_loop(int abort_fd, int sock,
pkt_handler = cbs->event_tick; pkt_handler = cbs->event_tick;
break; break;
/* Sway extensions */ /* Sway extensions */
#define SWAY_IPC_EVENT_INPUT ((1u << 31) | 21) #define SWAY_IPC_EVENT_INPUT ((1u << 31) | 21)
case SWAY_IPC_EVENT_INPUT: case SWAY_IPC_EVENT_INPUT:
pkt_handler = cbs->event_input; pkt_handler = cbs->event_input;

View file

@ -2,8 +2,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/types.h>
#include <sys/un.h> #include <sys/un.h>
#include <json-c/json_util.h> #include <json-c/json_util.h>
@ -43,6 +43,4 @@ struct i3_ipc_callbacks {
i3_ipc_callback_t event_input; i3_ipc_callback_t event_input;
}; };
bool i3_receive_loop( bool i3_receive_loop(int abort_fd, int sock, const struct i3_ipc_callbacks *callbacks, void *data);
int abort_fd, int sock,
const struct i3_ipc_callbacks *callbacks, void *data);

View file

@ -1,27 +1,27 @@
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <assert.h>
#include <threads.h> #include <threads.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/types.h>
#include <tllist.h> #include <tllist.h>
#define LOG_MODULE "i3" #define LOG_MODULE "i3"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h" #include "../plugin.h"
#include "i3-ipc.h"
#include "i3-common.h" #include "i3-common.h"
#include "i3-ipc.h"
enum sort_mode {SORT_NONE, SORT_NATIVE, SORT_ASCENDING, SORT_DESCENDING}; enum sort_mode { SORT_NONE, SORT_NATIVE, SORT_ASCENDING, SORT_DESCENDING };
struct ws_content { struct ws_content {
char *name; char *name;
@ -48,7 +48,8 @@ struct workspace {
} window; } window;
}; };
struct private { struct private
{
int left_spacing; int left_spacing;
int right_spacing; int right_spacing;
@ -105,10 +106,8 @@ workspace_from_json(const struct json_object *json, struct workspace *ws)
{ {
/* Always present */ /* Always present */
struct json_object *id, *name, *output; struct json_object *id, *name, *output;
if (!json_object_object_get_ex(json, "id", &id) || if (!json_object_object_get_ex(json, "id", &id) || !json_object_object_get_ex(json, "name", &name)
!json_object_object_get_ex(json, "name", &name) || || !json_object_object_get_ex(json, "output", &output)) {
!json_object_object_get_ex(json, "output", &output))
{
LOG_ERR("workspace reply/event without 'name' and/or 'output' " LOG_ERR("workspace reply/event without 'name' and/or 'output' "
"properties"); "properties");
return false; return false;
@ -126,14 +125,12 @@ workspace_from_json(const struct json_object *json, struct workspace *ws)
const char *name_as_string = json_object_get_string(name); const char *name_as_string = json_object_get_string(name);
const size_t node_count = focus != NULL const size_t node_count = focus != NULL ? json_object_array_length(focus) : 0;
? json_object_array_length(focus)
: 0;
const bool is_empty = node_count == 0; const bool is_empty = node_count == 0;
int name_as_int = workspace_name_as_int(name_as_string); int name_as_int = workspace_name_as_int(name_as_string);
*ws = (struct workspace) { *ws = (struct workspace){
.id = json_object_get_int(id), .id = json_object_get_int(id),
.name = strdup(name_as_string), .name = strdup(name_as_string),
.name_as_int = name_as_int, .name_as_int = name_as_int,
@ -152,9 +149,12 @@ workspace_from_json(const struct json_object *json, struct workspace *ws)
static void static void
workspace_free_persistent(struct workspace *ws) workspace_free_persistent(struct workspace *ws)
{ {
free(ws->output); ws->output = NULL; free(ws->output);
free(ws->window.title); ws->window.title = NULL; ws->output = NULL;
free(ws->window.application); ws->window.application = NULL; free(ws->window.title);
ws->window.title = NULL;
free(ws->window.application);
ws->window.application = NULL;
ws->id = -1; ws->id = -1;
} }
@ -162,13 +162,15 @@ static void
workspace_free(struct workspace *ws) workspace_free(struct workspace *ws)
{ {
workspace_free_persistent(ws); workspace_free_persistent(ws);
free(ws->name); ws->name = NULL; free(ws->name);
ws->name = NULL;
} }
static void static void
workspaces_free(struct private *m, bool free_persistent) workspaces_free(struct private *m, bool free_persistent)
{ {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (free_persistent || !it->item.persistent) { if (free_persistent || !it->item.persistent) {
workspace_free(&it->item); workspace_free(&it->item);
tll_remove(m->workspaces, it); tll_remove(m->workspaces, it);
@ -176,7 +178,6 @@ workspaces_free(struct private *m, bool free_persistent)
} }
} }
static void static void
workspace_add(struct private *m, struct workspace ws) workspace_add(struct private *m, struct workspace ws)
{ {
@ -187,7 +188,8 @@ workspace_add(struct private *m, struct workspace ws)
case SORT_NATIVE: case SORT_NATIVE:
if (ws.name_as_int >= 0) { if (ws.name_as_int >= 0) {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.name_as_int < 0) if (it->item.name_as_int < 0)
continue; continue;
if (it->item.name_as_int > ws.name_as_int) { if (it->item.name_as_int > ws.name_as_int) {
@ -202,7 +204,8 @@ workspace_add(struct private *m, struct workspace ws)
case SORT_ASCENDING: case SORT_ASCENDING:
if (ws.name_as_int >= 0) { if (ws.name_as_int >= 0) {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.name_as_int < 0) if (it->item.name_as_int < 0)
continue; continue;
if (it->item.name_as_int > ws.name_as_int) { if (it->item.name_as_int > ws.name_as_int) {
@ -211,10 +214,9 @@ workspace_add(struct private *m, struct workspace ws)
} }
} }
} else { } else {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
if (strcoll(it->item.name, ws.name) > 0 || {
it->item.name_as_int >= 0) if (strcoll(it->item.name, ws.name) > 0 || it->item.name_as_int >= 0) {
{
tll_insert_before(m->workspaces, it, ws); tll_insert_before(m->workspaces, it, ws);
return; return;
} }
@ -225,14 +227,16 @@ workspace_add(struct private *m, struct workspace ws)
case SORT_DESCENDING: case SORT_DESCENDING:
if (ws.name_as_int >= 0) { if (ws.name_as_int >= 0) {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.name_as_int < ws.name_as_int) { if (it->item.name_as_int < ws.name_as_int) {
tll_insert_before(m->workspaces, it, ws); tll_insert_before(m->workspaces, it, ws);
return; return;
} }
} }
} else { } else {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.name_as_int >= 0) if (it->item.name_as_int >= 0)
continue; continue;
if (strcoll(it->item.name, ws.name) < 0) { if (strcoll(it->item.name, ws.name) < 0) {
@ -249,7 +253,8 @@ workspace_add(struct private *m, struct workspace ws)
static void static void
workspace_del(struct private *m, int id) workspace_del(struct private *m, int id)
{ {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
struct workspace *ws = &it->item; struct workspace *ws = &it->item;
if (ws->id != id) if (ws->id != id)
@ -264,7 +269,8 @@ workspace_del(struct private *m, int id)
static struct workspace * static struct workspace *
workspace_lookup(struct private *m, int id) workspace_lookup(struct private *m, int id)
{ {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
struct workspace *ws = &it->item; struct workspace *ws = &it->item;
if (ws->id == id) if (ws->id == id)
return ws; return ws;
@ -275,7 +281,8 @@ workspace_lookup(struct private *m, int id)
static struct workspace * static struct workspace *
workspace_lookup_by_name(struct private *m, const char *name) workspace_lookup_by_name(struct private *m, const char *name)
{ {
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
struct workspace *ws = &it->item; struct workspace *ws = &it->item;
if (strcmp(ws->name, name) == 0) if (strcmp(ws->name, name) == 0)
return ws; return ws;
@ -339,13 +346,9 @@ workspace_update_or_add(struct private *m, const struct json_object *ws_json)
if (json_object_object_get_ex(ws_json, "name", &_name)) { if (json_object_object_get_ex(ws_json, "name", &_name)) {
const char *name = json_object_get_string(_name); const char *name = json_object_get_string(_name);
if (name != NULL) { if (name != NULL) {
struct workspace *maybe_persistent = struct workspace *maybe_persistent = workspace_lookup_by_name(m, name);
workspace_lookup_by_name(m, name);
if (maybe_persistent != NULL && if (maybe_persistent != NULL && maybe_persistent->persistent && maybe_persistent->id < 0) {
maybe_persistent->persistent &&
maybe_persistent->id < 0)
{
already_exists = maybe_persistent; already_exists = maybe_persistent;
} }
} }
@ -421,10 +424,9 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
bool is_reload = strcmp(change_str, "reload") == 0; bool is_reload = strcmp(change_str, "reload") == 0;
struct json_object *current, *_current_id; struct json_object *current, *_current_id;
if ((!json_object_object_get_ex(json, "current", &current) || if ((!json_object_object_get_ex(json, "current", &current)
!json_object_object_get_ex(current, "id", &_current_id)) && || !json_object_object_get_ex(current, "id", &_current_id))
!is_reload) && !is_reload) {
{
LOG_ERR("workspace event without 'current' and/or 'id' properties"); LOG_ERR("workspace event without 'current' and/or 'id' properties");
return false; return false;
} }
@ -452,10 +454,8 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
else if (is_focused) { else if (is_focused) {
struct json_object *old, *_old_id, *urgent; struct json_object *old, *_old_id, *urgent;
if (!json_object_object_get_ex(json, "old", &old) || if (!json_object_object_get_ex(json, "old", &old) || !json_object_object_get_ex(old, "id", &_old_id)
!json_object_object_get_ex(old, "id", &_old_id) || || !json_object_object_get_ex(current, "urgent", &urgent)) {
!json_object_object_get_ex(current, "urgent", &urgent))
{
LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property"); LOG_ERR("workspace 'focused' event without 'old', 'name' and/or 'urgent' property");
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
return false; return false;
@ -467,7 +467,8 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
LOG_DBG("w: %s", w->name); LOG_DBG("w: %s", w->name);
/* Mark all workspaces on current's output invisible */ /* Mark all workspaces on current's output invisible */
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
struct workspace *ws = &it->item; struct workspace *ws = &it->item;
if (ws->output != NULL && strcmp(ws->output, w->output) == 0) if (ws->output != NULL && strcmp(ws->output, w->output) == 0)
ws->visible = false; ws->visible = false;
@ -501,7 +502,8 @@ handle_workspace_event(int sock, int type, const struct json_object *json, void
/* Re-add the workspace to ensure correct sorting */ /* Re-add the workspace to ensure correct sorting */
struct workspace ws = *w; struct workspace ws = *w;
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.id == current_id) { if (it->item.id == current_id) {
tll_remove(m->workspaces, it); tll_remove(m->workspaces, it);
break; break;
@ -588,7 +590,8 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
struct workspace *ws = NULL; struct workspace *ws = NULL;
size_t focused = 0; size_t focused = 0;
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
if (it->item.focused) { if (it->item.focused) {
ws = &it->item; ws = &it->item;
focused++; focused++;
@ -599,10 +602,8 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
assert(ws != NULL); assert(ws != NULL);
struct json_object *container, *id, *name; struct json_object *container, *id, *name;
if (!json_object_object_get_ex(json, "container", &container) || if (!json_object_object_get_ex(json, "container", &container) || !json_object_object_get_ex(container, "id", &id)
!json_object_object_get_ex(container, "id", &id) || || !json_object_object_get_ex(container, "name", &name)) {
!json_object_object_get_ex(container, "name", &name))
{
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
LOG_ERR("window event without 'container' with 'id' and 'name'"); LOG_ERR("window event without 'container' with 'id' and 'name'");
return false; return false;
@ -645,18 +646,14 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
struct json_object *app_id; struct json_object *app_id;
struct json_object *pid; struct json_object *pid;
if (json_object_object_get_ex(container, "app_id", &app_id) && if (json_object_object_get_ex(container, "app_id", &app_id) && json_object_get_string(app_id) != NULL) {
json_object_get_string(app_id) != NULL)
{
free(ws->window.application); free(ws->window.application);
ws->window.application = strdup(json_object_get_string(app_id)); ws->window.application = strdup(json_object_get_string(app_id));
LOG_DBG("application: \"%s\", via 'app_id'", ws->window.application); LOG_DBG("application: \"%s\", via 'app_id'", ws->window.application);
} }
/* If PID has changed, update application name from /proc/<pid>/comm */ /* If PID has changed, update application name from /proc/<pid>/comm */
else if (json_object_object_get_ex(container, "pid", &pid) && else if (json_object_object_get_ex(container, "pid", &pid) && ws->window.pid != json_object_get_int(pid)) {
ws->window.pid != json_object_get_int(pid))
{
ws->window.pid = json_object_get_int(pid); ws->window.pid = json_object_get_int(pid);
char path[64]; char path[64];
@ -665,7 +662,8 @@ handle_window_event(int sock, int type, const struct json_object *json, void *_m
int fd = open(path, O_RDONLY); int fd = open(path, O_RDONLY);
if (fd == -1) { if (fd == -1) {
/* Application may simply have terminated */ /* Application may simply have terminated */
free(ws->window.application); ws->window.application = NULL; free(ws->window.application);
ws->window.application = NULL;
ws->window.pid = -1; ws->window.pid = -1;
m->dirty = true; m->dirty = true;
@ -837,7 +835,8 @@ content(struct module *mod)
struct exposable *particles[tll_length(m->workspaces) + 1]; struct exposable *particles[tll_length(m->workspaces) + 1];
struct exposable *current = NULL; struct exposable *current = NULL;
tll_foreach(m->workspaces, it) { tll_foreach(m->workspaces, it)
{
struct workspace *ws = &it->item; struct workspace *ws = &it->item;
const struct ws_content *template = NULL; const struct ws_content *template = NULL;
@ -853,21 +852,12 @@ content(struct module *mod)
template = ws_content_for_name(m, ""); template = ws_content_for_name(m, "");
} }
const char *state = const char *state = ws->urgent ? "urgent" : ws->visible ? ws->focused ? "focused" : "unfocused" : "invisible";
ws->urgent ? "urgent" :
ws->visible ? ws->focused ? "focused" : "unfocused" :
"invisible";
LOG_DBG("name=%s (name-as-int=%d): visible=%s, focused=%s, urgent=%s, empty=%s, state=%s, " LOG_DBG("name=%s (name-as-int=%d): visible=%s, focused=%s, urgent=%s, empty=%s, state=%s, "
"application=%s, title=%s, mode=%s", "application=%s, title=%s, mode=%s",
ws->name, ws->name_as_int, ws->name, ws->name_as_int, ws->visible ? "yes" : "no", ws->focused ? "yes" : "no",
ws->visible ? "yes" : "no", ws->urgent ? "yes" : "no", ws->empty ? "yes" : "no", state, ws->window.application, ws->window.title,
ws->focused ? "yes" : "no",
ws->urgent ? "yes" : "no",
ws->empty ? "yes" : "no",
state,
ws->window.application,
ws->window.title,
m->mode); m->mode);
const char *name = ws->name; const char *name = ws->name;
@ -902,12 +892,9 @@ content(struct module *mod)
} }
if (template == NULL) { if (template == NULL) {
LOG_WARN( LOG_WARN("no ws template for %s, and no default template available", ws->name);
"no ws template for %s, and no default template available",
ws->name);
} else { } else {
particles[particle_count++] = template->content->instantiate( particles[particle_count++] = template->content->instantiate(template->content, &tags);
template->content, &tags);
} }
tag_set_destroy(&tags); tag_set_destroy(&tags);
@ -917,8 +904,7 @@ content(struct module *mod)
particles[particle_count++] = current; particles[particle_count++] = current;
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
return dynlist_exposable_new( return dynlist_exposable_new(particles, particle_count, m->left_spacing, m->right_spacing);
particles, particle_count, m->left_spacing, m->right_spacing);
} }
/* Maps workspace name to a content particle. */ /* Maps workspace name to a content particle. */
@ -928,10 +914,8 @@ struct i3_workspaces {
}; };
static struct module * static struct module *
i3_new(struct i3_workspaces workspaces[], size_t workspace_count, i3_new(struct i3_workspaces workspaces[], size_t workspace_count, int left_spacing, int right_spacing,
int left_spacing, int right_spacing, enum sort_mode sort_mode, enum sort_mode sort_mode, size_t persistent_count, const char *persistent_workspaces[static persistent_count],
size_t persistent_count,
const char *persistent_workspaces[static persistent_count],
bool strip_workspace_numbers) bool strip_workspace_numbers)
{ {
struct private *m = calloc(1, sizeof(*m)); struct private *m = calloc(1, sizeof(*m));
@ -952,8 +936,7 @@ i3_new(struct i3_workspaces workspaces[], size_t workspace_count,
m->sort_mode = sort_mode; m->sort_mode = sort_mode;
m->persistent_count = persistent_count; m->persistent_count = persistent_count;
m->persistent_workspaces = calloc( m->persistent_workspaces = calloc(persistent_count, sizeof(m->persistent_workspaces[0]));
persistent_count, sizeof(m->persistent_workspaces[0]));
for (size_t i = 0; i < persistent_count; i++) for (size_t i = 0; i < persistent_count; i++)
m->persistent_workspaces[i] = strdup(persistent_workspaces[i]); m->persistent_workspaces[i] = strdup(persistent_workspaces[i]);
@ -976,31 +959,26 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *right_spacing = yml_get_value(node, "right-spacing");
const struct yml_node *sort = yml_get_value(node, "sort"); const struct yml_node *sort = yml_get_value(node, "sort");
const struct yml_node *persistent = yml_get_value(node, "persistent"); const struct yml_node *persistent = yml_get_value(node, "persistent");
const struct yml_node *strip_workspace_number = yml_get_value( const struct yml_node *strip_workspace_number = yml_get_value(node, "strip-workspace-numbers");
node, "strip-workspace-numbers");
int left = spacing != NULL ? yml_value_as_int(spacing) : int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; int right = spacing != NULL ? yml_value_as_int(spacing)
int right = spacing != NULL ? yml_value_as_int(spacing) : : right_spacing != NULL ? yml_value_as_int(right_spacing)
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; : 0;
const char *sort_value = sort != NULL ? yml_value_as_string(sort) : NULL; const char *sort_value = sort != NULL ? yml_value_as_string(sort) : NULL;
enum sort_mode sort_mode = enum sort_mode sort_mode = sort_value == NULL ? SORT_NONE
sort_value == NULL ? SORT_NONE : : strcmp(sort_value, "none") == 0 ? SORT_NONE
strcmp(sort_value, "none") == 0 ? SORT_NONE : : strcmp(sort_value, "native") == 0 ? SORT_NATIVE
strcmp(sort_value, "native") == 0 ? SORT_NATIVE : : strcmp(sort_value, "ascending") == 0 ? SORT_ASCENDING
strcmp(sort_value, "ascending") == 0 ? SORT_ASCENDING : SORT_DESCENDING; : SORT_DESCENDING;
const size_t persistent_count = const size_t persistent_count = persistent != NULL ? yml_list_length(persistent) : 0;
persistent != NULL ? yml_list_length(persistent) : 0;
const char *persistent_workspaces[persistent_count]; const char *persistent_workspaces[persistent_count];
if (persistent != NULL) { if (persistent != NULL) {
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(persistent); for (struct yml_list_iter it = yml_list_iter(persistent); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL;
yml_list_next(&it), idx++)
{
persistent_workspaces[idx] = yml_value_as_string(it.node); persistent_workspaces[idx] = yml_value_as_string(it.node);
} }
} }
@ -1008,38 +986,27 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
struct i3_workspaces workspaces[yml_dict_length(c)]; struct i3_workspaces workspaces[yml_dict_length(c)];
size_t idx = 0; size_t idx = 0;
for (struct yml_dict_iter it = yml_dict_iter(c); for (struct yml_dict_iter it = yml_dict_iter(c); it.key != NULL; yml_dict_next(&it), idx++) {
it.key != NULL;
yml_dict_next(&it), idx++)
{
workspaces[idx].name = yml_value_as_string(it.key); workspaces[idx].name = yml_value_as_string(it.key);
workspaces[idx].content = conf_to_particle(it.value, inherited); workspaces[idx].content = conf_to_particle(it.value, inherited);
} }
return i3_new(workspaces, yml_dict_length(c), left, right, sort_mode, return i3_new(workspaces, yml_dict_length(c), left, right, sort_mode, persistent_count, persistent_workspaces,
persistent_count, persistent_workspaces, (strip_workspace_number != NULL ? yml_value_as_bool(strip_workspace_number) : false));
(strip_workspace_number != NULL
? yml_value_as_bool(strip_workspace_number) : false));
} }
static bool static bool
verify_content(keychain_t *chain, const struct yml_node *node) verify_content(keychain_t *chain, const struct yml_node *node)
{ {
if (!yml_is_dict(node)) { if (!yml_is_dict(node)) {
LOG_ERR( LOG_ERR("%s: must be a dictionary of workspace-name: particle mappings", conf_err_prefix(chain, node));
"%s: must be a dictionary of workspace-name: particle mappings",
conf_err_prefix(chain, node));
return false; return false;
} }
for (struct yml_dict_iter it = yml_dict_iter(node); for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) {
it.key != NULL;
yml_dict_next(&it))
{
const char *key = yml_value_as_string(it.key); const char *key = yml_value_as_string(it.key);
if (key == NULL) { if (key == NULL) {
LOG_ERR("%s: key must be a string (a i3 workspace name)", LOG_ERR("%s: key must be a string (a i3 workspace name)", conf_err_prefix(chain, it.key));
conf_err_prefix(chain, it.key));
return false; return false;
} }
@ -1055,8 +1022,7 @@ verify_content(keychain_t *chain, const struct yml_node *node)
static bool static bool
verify_sort(keychain_t *chain, const struct yml_node *node) verify_sort(keychain_t *chain, const struct yml_node *node)
{ {
return conf_verify_enum( return conf_verify_enum(chain, node, (const char *[]){"none", "native", "ascending", "descending"}, 4);
chain, node, (const char *[]){"none", "native", "ascending", "descending"}, 4);
} }
static bool static bool
@ -1089,5 +1055,5 @@ const struct module_iface module_i3_iface = {
}; };
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) #if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
extern const struct module_iface iface __attribute__((weak, alias("module_i3_iface"))) ; extern const struct module_iface iface __attribute__((weak, alias("module_i3_iface")));
#endif #endif

View file

@ -1,16 +1,14 @@
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <poll.h> #include <poll.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../module.h" #include "../module.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private { struct particle *label; };
struct particle *label;
};
static void static void
destroy(struct module *mod) destroy(struct module *mod)

View file

@ -162,9 +162,7 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *interval = yml_get_value(node, "poll-interval"); const struct yml_node *interval = yml_get_value(node, "poll-interval");
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
return mem_new( return mem_new(interval == NULL ? min_poll_interval : yml_value_as_int(interval), conf_to_particle(c, inherited));
interval == NULL ? min_poll_interval : yml_value_as_int(interval),
conf_to_particle(c, inherited));
} }
static bool static bool
@ -174,8 +172,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
return false; return false;
if (yml_value_as_int(node) < min_poll_interval) { if (yml_value_as_int(node) < min_poll_interval) {
LOG_ERR("%s: interval value cannot be less than %ldms", LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -1,33 +1,34 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <time.h>
#include <threads.h>
#include <unistd.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <threads.h>
#include <time.h>
#include <unistd.h>
#include <poll.h>
#include <libgen.h> #include <libgen.h>
#include <poll.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/eventfd.h> #include <sys/eventfd.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <mpd/client.h> #include <mpd/client.h>
#define LOG_MODULE "mpd" #define LOG_MODULE "mpd"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
char *host; char *host;
uint16_t port; uint16_t port;
struct particle *label; struct particle *label;
@ -38,7 +39,7 @@ struct private {
bool repeat; bool repeat;
bool random; bool random;
bool consume; bool consume;
int volume; int volume;
char *album; char *album;
char *artist; char *artist;
char *title; char *title;
@ -60,11 +61,9 @@ destroy(struct module *mod)
struct private *m = mod->private; struct private *m = mod->private;
if (m->refresh_thread_id != 0) { if (m->refresh_thread_id != 0) {
assert(m->refresh_abort_fd != -1); assert(m->refresh_abort_fd != -1);
if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) {
!= sizeof(uint64_t))
{
LOG_ERRNO("failed to signal abort to refresher thread"); LOG_ERRNO("failed to signal abort to refresher thread");
} else{ } else {
int res; int res;
thrd_join(m->refresh_thread_id, &res); thrd_join(m->refresh_thread_id, &res);
} }
@ -132,12 +131,11 @@ content(struct module *mod)
if (m->state == MPD_STATE_PLAY) { if (m->state == MPD_STATE_PLAY) {
elapsed += timespec_diff_milli_seconds(&now, &m->elapsed.when); elapsed += timespec_diff_milli_seconds(&now, &m->elapsed.when);
if (elapsed > m->duration) { if (elapsed > m->duration) {
LOG_DBG( LOG_DBG("dynamic update of elapsed overflowed: "
"dynamic update of elapsed overflowed: " "elapsed=%" PRIu64 ", duration=%" PRIu64,
"elapsed=%"PRIu64", duration=%"PRIu64, elapsed, m->duration); elapsed, m->duration);
elapsed = m->duration; elapsed = m->duration;
} }
} }
unsigned elapsed_secs = elapsed / 1000; unsigned elapsed_secs = elapsed / 1000;
@ -154,16 +152,23 @@ content(struct module *mod)
state_str = "offline"; state_str = "offline";
else { else {
switch (m->state) { switch (m->state) {
case MPD_STATE_UNKNOWN: state_str = "unknown"; break; case MPD_STATE_UNKNOWN:
case MPD_STATE_STOP: state_str = "stopped"; break; state_str = "unknown";
case MPD_STATE_PAUSE: state_str = "paused"; break; break;
case MPD_STATE_PLAY: state_str = "playing"; break; case MPD_STATE_STOP:
state_str = "stopped";
break;
case MPD_STATE_PAUSE:
state_str = "paused";
break;
case MPD_STATE_PLAY:
state_str = "playing";
break;
} }
} }
/* Tell particle to real-time track? */ /* Tell particle to real-time track? */
enum tag_realtime_unit realtime = m->state == MPD_STATE_PLAY enum tag_realtime_unit realtime = m->state == MPD_STATE_PLAY ? TAG_REALTIME_MSECS : TAG_REALTIME_NONE;
? TAG_REALTIME_MSECS : TAG_REALTIME_NONE;
struct tag_set tags = { struct tag_set tags = {
.tags = (struct tag *[]){ .tags = (struct tag *[]){
@ -237,8 +242,7 @@ wait_for_socket_create(const struct module *mod)
LOG_DBG("%s: already exists, and is connectable", m->host); LOG_DBG("%s: already exists, and is connectable", m->host);
have_mpd_socket = true; have_mpd_socket = true;
} else { } else {
LOG_DBG("%s: already exists, but isn't connectable: %s", LOG_DBG("%s: already exists, but isn't connectable: %s", m->host, strerror(errno));
m->host, strerror(errno));
} }
close(s); close(s);
@ -249,10 +253,7 @@ wait_for_socket_create(const struct module *mod)
bool ret = false; bool ret = false;
while (!have_mpd_socket) { while (!have_mpd_socket) {
struct pollfd fds[] = { struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = fd, .events = POLLIN}};
{.fd = mod->abort_fd, .events = POLLIN},
{.fd = fd, .events = POLLIN}
};
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) { if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) {
if (errno == EINTR) if (errno == EINTR)
@ -272,7 +273,7 @@ wait_for_socket_create(const struct module *mod)
char buf[1024]; char buf[1024];
ssize_t len = read(fd, buf, sizeof(buf)); ssize_t len = read(fd, buf, sizeof(buf));
for (const char *ptr = buf; ptr < buf + len; ) { for (const char *ptr = buf; ptr < buf + len;) {
const struct inotify_event *e = (const struct inotify_event *)ptr; const struct inotify_event *e = (const struct inotify_event *)ptr;
LOG_DBG("inotify: CREATED: %s/%.*s", directory, e->len, e->name); LOG_DBG("inotify: CREATED: %s/%.*s", directory, e->len, e->name);
@ -282,7 +283,7 @@ wait_for_socket_create(const struct module *mod)
break; break;
} }
ptr += sizeof(*e) + e->len; ptr += sizeof(*e) + e->len;
} }
} }
@ -305,8 +306,7 @@ connect_to_mpd(const struct module *mod)
enum mpd_error merr = mpd_connection_get_error(conn); enum mpd_error merr = mpd_connection_get_error(conn);
if (merr != MPD_ERROR_SUCCESS) { if (merr != MPD_ERROR_SUCCESS) {
LOG_WARN("failed to connect to MPD: %s", LOG_WARN("failed to connect to MPD: %s", mpd_connection_get_error_message(conn));
mpd_connection_get_error_message(conn));
mpd_connection_free(conn); mpd_connection_free(conn);
return NULL; return NULL;
} }
@ -324,8 +324,7 @@ update_status(struct module *mod)
struct mpd_status *status = mpd_run_status(m->conn); struct mpd_status *status = mpd_run_status(m->conn);
if (status == NULL) { if (status == NULL) {
LOG_ERR("failed to get status: %s", LOG_ERR("failed to get status: %s", mpd_connection_get_error_message(m->conn));
mpd_connection_get_error_message(m->conn));
return false; return false;
} }
@ -347,17 +346,20 @@ update_status(struct module *mod)
struct mpd_song *song = mpd_run_current_song(m->conn); struct mpd_song *song = mpd_run_current_song(m->conn);
if (song == NULL && mpd_connection_get_error(m->conn) != MPD_ERROR_SUCCESS) { if (song == NULL && mpd_connection_get_error(m->conn) != MPD_ERROR_SUCCESS) {
LOG_ERR("failed to get current song: %s", LOG_ERR("failed to get current song: %s", mpd_connection_get_error_message(m->conn));
mpd_connection_get_error_message(m->conn));
return false; return false;
} }
if (song == NULL) { if (song == NULL) {
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
free(m->album); m->album = NULL; free(m->album);
free(m->artist); m->artist = NULL; m->album = NULL;
free(m->title); m->title = NULL; free(m->artist);
free(m->file); m->file = NULL; m->artist = NULL;
free(m->title);
m->title = NULL;
free(m->file);
m->file = NULL;
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
} else { } else {
const char *album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0); const char *album = mpd_song_get_tag(song, MPD_TAG_ALBUM, 0);
@ -401,10 +403,14 @@ run(struct module *mod)
/* Reset state */ /* Reset state */
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
free(m->album); m->album = NULL; free(m->album);
free(m->artist); m->artist = NULL; m->album = NULL;
free(m->title); m->title = NULL; free(m->artist);
free(m->file); m->file = NULL; m->artist = NULL;
free(m->title);
m->title = NULL;
free(m->file);
m->file = NULL;
m->state = MPD_STATE_UNKNOWN; m->state = MPD_STATE_UNKNOWN;
m->elapsed.value = m->duration = 0; m->elapsed.value = m->duration = 0;
m->elapsed.when.tv_sec = m->elapsed.when.tv_nsec = 0; m->elapsed.when.tv_sec = m->elapsed.when.tv_nsec = 0;
@ -467,8 +473,7 @@ run(struct module *mod)
}; };
if (!mpd_send_idle(m->conn)) { if (!mpd_send_idle(m->conn)) {
LOG_ERR("failed to send IDLE command: %s", LOG_ERR("failed to send IDLE command: %s", mpd_connection_get_error_message(m->conn));
mpd_connection_get_error_message(m->conn));
break; break;
} }
@ -492,8 +497,7 @@ run(struct module *mod)
} }
if (fds[1].revents & POLLIN) { if (fds[1].revents & POLLIN) {
enum mpd_idle idle __attribute__ ((unused)) = enum mpd_idle idle __attribute__((unused)) = mpd_recv_idle(m->conn, true);
mpd_recv_idle(m->conn, true);
LOG_DBG("IDLE mask: %d", idle); LOG_DBG("IDLE mask: %d", idle);
@ -565,9 +569,7 @@ refresh_in(struct module *mod, long milli_seconds)
/* Signal abort to thread */ /* Signal abort to thread */
assert(m->refresh_abort_fd != -1); assert(m->refresh_abort_fd != -1);
if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) if (write(m->refresh_abort_fd, &(uint64_t){1}, sizeof(uint64_t)) != sizeof(uint64_t)) {
!= sizeof(uint64_t))
{
LOG_ERRNO("failed to signal abort to refresher thread"); LOG_ERRNO("failed to signal abort to refresher thread");
return false; return false;
} }
@ -607,7 +609,7 @@ refresh_in(struct module *mod, long milli_seconds)
} }
/* Detach - we don't want to have to thrd_join() it */ /* Detach - we don't want to have to thrd_join() it */
//thrd_detach(tid); // thrd_detach(tid);
return r == 0; return r == 0;
} }
@ -638,10 +640,8 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *port = yml_get_value(node, "port"); const struct yml_node *port = yml_get_value(node, "port");
const struct yml_node *c = yml_get_value(node, "content"); const struct yml_node *c = yml_get_value(node, "content");
return mpd_new( return mpd_new(yml_value_as_string(host), port != NULL ? yml_value_as_int(port) : 0,
yml_value_as_string(host), conf_to_particle(c, inherited));
port != NULL ? yml_value_as_int(port) : 0,
conf_to_particle(c, inherited));
} }
static bool static bool

View file

@ -1,34 +1,34 @@
#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <assert.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include <threads.h>
#include <poll.h> #include <poll.h>
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <threads.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <linux/genetlink.h>
#include <linux/if.h> #include <linux/if.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/genetlink.h>
#include <linux/rtnetlink.h>
#include <linux/nl80211.h> #include <linux/nl80211.h>
#include <linux/rtnetlink.h>
#include <tllist.h> #include <tllist.h>
#define LOG_MODULE "network" #define LOG_MODULE "network"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../module.h" #include "../module.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h" #include "../plugin.h"
@ -58,7 +58,7 @@ struct iface {
int index; int index;
uint8_t mac[6]; uint8_t mac[6];
bool carrier; bool carrier;
uint8_t state; /* IFLA_OPERSTATE */ uint8_t state; /* IFLA_OPERSTATE */
/* IPv4 and IPv6 addresses */ /* IPv4 and IPv6 addresses */
tll(struct af_addr) addrs; tll(struct af_addr) addrs;
@ -76,7 +76,8 @@ struct iface {
uint64_t dl_bits; uint64_t dl_bits;
}; };
struct private { struct private
{
struct particle *label; struct particle *label;
int poll_interval; int poll_interval;
@ -118,8 +119,7 @@ destroy(struct module *mod)
if (m->urandom_fd >= 0) if (m->urandom_fd >= 0)
close(m->urandom_fd); close(m->urandom_fd);
tll_foreach(m->ifaces, it) tll_foreach(m->ifaces, it) free_iface(it->item);
free_iface(it->item);
free(m); free(m);
module_default_destroy(mod); module_default_destroy(mod);
@ -141,35 +141,53 @@ content(struct module *mod)
struct exposable *exposables[max(tll_length(m->ifaces), 1)]; struct exposable *exposables[max(tll_length(m->ifaces), 1)];
size_t idx = 0; size_t idx = 0;
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
struct iface *iface = &it->item; struct iface *iface = &it->item;
const char *state = NULL; const char *state = NULL;
switch (iface->state) { switch (iface->state) {
case IF_OPER_UNKNOWN: state = "unknown"; break; case IF_OPER_UNKNOWN:
case IF_OPER_NOTPRESENT: state = "not present"; break; state = "unknown";
case IF_OPER_DOWN: state = "down"; break; break;
case IF_OPER_LOWERLAYERDOWN: state = "lower layers down"; break; case IF_OPER_NOTPRESENT:
case IF_OPER_TESTING: state = "testing"; break; state = "not present";
case IF_OPER_DORMANT: state = "dormant"; break; break;
case IF_OPER_UP: state = "up"; break; case IF_OPER_DOWN:
default: state = "unknown"; break; state = "down";
break;
case IF_OPER_LOWERLAYERDOWN:
state = "lower layers down";
break;
case IF_OPER_TESTING:
state = "testing";
break;
case IF_OPER_DORMANT:
state = "dormant";
break;
case IF_OPER_UP:
state = "up";
break;
default:
state = "unknown";
break;
} }
char mac_str[6 * 2 + 5 + 1]; char mac_str[6 * 2 + 5 + 1];
char ipv4_str[INET_ADDRSTRLEN] = {0}; char ipv4_str[INET_ADDRSTRLEN] = {0};
char ipv6_str[INET6_ADDRSTRLEN] = {0}; char ipv6_str[INET6_ADDRSTRLEN] = {0};
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x", iface->mac[0], iface->mac[1], iface->mac[2],
iface->mac[0], iface->mac[1], iface->mac[2], iface->mac[3], iface->mac[4], iface->mac[5]); iface->mac[3], iface->mac[4], iface->mac[5]);
/* TODO: this exposes the *last* added address of each kind. Can /* TODO: this exposes the *last* added address of each kind. Can
* we expose all in some way? */ * we expose all in some way? */
tll_foreach(iface->addrs, it) { tll_foreach(iface->addrs, it)
{
if (it->item.family == AF_INET) if (it->item.family == AF_INET)
inet_ntop(AF_INET, &it->item.addr.ipv4, ipv4_str, sizeof(ipv4_str)); inet_ntop(AF_INET, &it->item.addr.ipv4, ipv4_str, sizeof(ipv4_str));
else if (it->item.family == AF_INET6) else if (it->item.family == AF_INET6)
if(!IN6_IS_ADDR_LINKLOCAL(&it->item.addr.ipv6)) if (!IN6_IS_ADDR_LINKLOCAL(&it->item.addr.ipv6))
inet_ntop(AF_INET6, &it->item.addr.ipv6, ipv6_str, sizeof(ipv6_str)); inet_ntop(AF_INET6, &it->item.addr.ipv6, ipv6_str, sizeof(ipv6_str));
} }
@ -208,8 +226,7 @@ content(struct module *mod)
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
return dynlist_exposable_new( return dynlist_exposable_new(exposables, idx, m->left_spacing, m->right_spacing);
exposables, idx, m->left_spacing, m->right_spacing);
} }
/* Returns a value suitable for nl_pid/nlmsg_pid */ /* Returns a value suitable for nl_pid/nlmsg_pid */
@ -254,8 +271,7 @@ netlink_connect_genl(void)
} }
const struct sockaddr_nl addr = { const struct sockaddr_nl addr = {
.nl_family = AF_NETLINK, .nl_family = AF_NETLINK, .nl_pid = nl_pid_value(),
.nl_pid = nl_pid_value(),
/* no multicast notifications by default, will be added later */ /* no multicast notifications by default, will be added later */
}; };
@ -271,10 +287,8 @@ netlink_connect_genl(void)
static bool static bool
send_nlmsg(int sock, const void *nlmsg, size_t len) send_nlmsg(int sock, const void *nlmsg, size_t len)
{ {
int r = sendto( int r = sendto(sock, nlmsg, len, 0, (struct sockaddr *)&(struct sockaddr_nl){.nl_family = AF_NETLINK},
sock, nlmsg, len, 0, sizeof(struct sockaddr_nl));
(struct sockaddr *)&(struct sockaddr_nl){.nl_family = AF_NETLINK},
sizeof(struct sockaddr_nl));
return r == len; return r == len;
} }
@ -300,8 +314,7 @@ send_rt_request(struct private *m, int request)
}; };
if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) { if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) {
LOG_ERRNO("failed to send netlink RT request (%d)", LOG_ERRNO("failed to send netlink RT request (%d)", request);
request);
return false; return false;
} }
@ -312,8 +325,7 @@ static bool
send_rt_getstats_request(struct private *m, struct iface *iface) send_rt_getstats_request(struct private *m, struct iface *iface)
{ {
if (iface->get_stats_seq_nr > 0) { if (iface->get_stats_seq_nr > 0) {
LOG_DBG( LOG_DBG("%s: RT get-stats request already in progress", iface->name);
"%s: RT get-stats request already in progress", iface->name);
return true; return true;
} }
@ -345,8 +357,7 @@ send_rt_getstats_request(struct private *m, struct iface *iface)
}; };
if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) { if (!send_nlmsg(m->rt_sock, &req, req.hdr.nlmsg_len)) {
LOG_ERRNO("%s: failed to send netlink RT getstats request (%d)", LOG_ERRNO("%s: failed to send netlink RT getstats request (%d)", iface->name, RTM_GETSTATS);
iface->name, RTM_GETSTATS);
return false; return false;
} }
iface->get_stats_seq_nr = seq; iface->get_stats_seq_nr = seq;
@ -391,10 +402,8 @@ send_ctrl_get_family_request(struct private *m)
}, },
}; };
_Static_assert( _Static_assert(sizeof(req.msg.family_name_attr) == NLA_HDRLEN + NLA_ALIGN(sizeof(req.msg.family_name_attr.data)),
sizeof(req.msg.family_name_attr) == "");
NLA_HDRLEN + NLA_ALIGN(sizeof(req.msg.family_name_attr.data)),
"");
if (!send_nlmsg(m->genl_sock, &req, req.hdr.nlmsg_len)) { if (!send_nlmsg(m->genl_sock, &req, req.hdr.nlmsg_len)) {
LOG_ERRNO("failed to send netlink ctrl-get-family request"); LOG_ERRNO("failed to send netlink ctrl-get-family request");
@ -538,15 +547,15 @@ send_nl80211_get_scan(struct private *m)
} }
static void static void
handle_link(struct module *mod, uint16_t type, handle_link(struct module *mod, uint16_t type, const struct ifinfomsg *msg, size_t len)
const struct ifinfomsg *msg, size_t len)
{ {
assert(type == RTM_NEWLINK || type == RTM_DELLINK); assert(type == RTM_NEWLINK || type == RTM_DELLINK);
struct private *m = mod->private; struct private *m = mod->private;
if (type == RTM_DELLINK) { if (type == RTM_DELLINK) {
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
if (msg->ifi_index != it->item.index) if (msg->ifi_index != it->item.index)
continue; continue;
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -560,7 +569,8 @@ handle_link(struct module *mod, uint16_t type,
} }
struct iface *iface = NULL; struct iface *iface = NULL;
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
if (msg->ifi_index != it->item.index) if (msg->ifi_index != it->item.index)
continue; continue;
iface = &it->item; iface = &it->item;
@ -568,21 +578,17 @@ handle_link(struct module *mod, uint16_t type,
} }
if (iface == NULL) { if (iface == NULL) {
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_push_back(m->ifaces, tll_push_back(m->ifaces, ((struct iface){
((struct iface){ .index = msg->ifi_index,
.index = msg->ifi_index, .state = IF_OPER_DOWN,
.state = IF_OPER_DOWN, .addrs = tll_init(),
.addrs = tll_init(), }));
})); mtx_unlock(&mod->lock);
mtx_unlock(&mod->lock); iface = &tll_back(m->ifaces);
iface = &tll_back(m->ifaces);
} }
for (const struct rtattr *attr = IFLA_RTA(msg); for (const struct rtattr *attr = IFLA_RTA(msg); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
RTA_OK(attr, len);
attr = RTA_NEXT(attr, len))
{
switch (attr->rta_type) { switch (attr->rta_type) {
case IFLA_IFNAME: case IFLA_IFNAME:
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -623,9 +629,8 @@ handle_link(struct module *mod, uint16_t type,
if (memcmp(iface->mac, mac, sizeof(iface->mac)) == 0) if (memcmp(iface->mac, mac, sizeof(iface->mac)) == 0)
break; break;
LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x", LOG_DBG("%s: IFLA_ADDRESS: %02x:%02x:%02x:%02x:%02x:%02x", iface->name, mac[0], mac[1], mac[2], mac[3],
iface->name, mac[4], mac[5]);
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
memcpy(iface->mac, mac, sizeof(iface->mac)); memcpy(iface->mac, mac, sizeof(iface->mac));
@ -645,8 +650,7 @@ handle_link(struct module *mod, uint16_t type,
} }
static void static void
handle_address(struct module *mod, uint16_t type, handle_address(struct module *mod, uint16_t type, const struct ifaddrmsg *msg, size_t len)
const struct ifaddrmsg *msg, size_t len)
{ {
assert(type == RTM_NEWADDR || type == RTM_DELADDR); assert(type == RTM_NEWADDR || type == RTM_DELADDR);
@ -656,7 +660,8 @@ handle_address(struct module *mod, uint16_t type,
struct iface *iface = NULL; struct iface *iface = NULL;
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
if (msg->ifa_index != it->item.index) if (msg->ifa_index != it->item.index)
continue; continue;
iface = &it->item; iface = &it->item;
@ -668,10 +673,7 @@ handle_address(struct module *mod, uint16_t type,
return; return;
} }
for (const struct rtattr *attr = IFA_RTA(msg); for (const struct rtattr *attr = IFA_RTA(msg); RTA_OK(attr, len); attr = RTA_NEXT(attr, len)) {
RTA_OK(attr, len);
attr = RTA_NEXT(attr, len))
{
switch (attr->rta_type) { switch (attr->rta_type) {
case IFA_ADDRESS: { case IFA_ADDRESS: {
const void *raw_addr = RTA_DATA(attr); const void *raw_addr = RTA_DATA(attr);
@ -681,14 +683,14 @@ handle_address(struct module *mod, uint16_t type,
char s[INET6_ADDRSTRLEN]; char s[INET6_ADDRSTRLEN];
inet_ntop(msg->ifa_family, raw_addr, s, sizeof(s)); inet_ntop(msg->ifa_family, raw_addr, s, sizeof(s));
#endif #endif
LOG_DBG("%s: IFA_ADDRESS (%s): %s", iface->name, LOG_DBG("%s: IFA_ADDRESS (%s): %s", iface->name, type == RTM_NEWADDR ? "add" : "del", s);
type == RTM_NEWADDR ? "add" : "del", s);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
if (type == RTM_DELADDR) { if (type == RTM_DELADDR) {
/* Find address in our list and remove it */ /* Find address in our list and remove it */
tll_foreach(iface->addrs, it) { tll_foreach(iface->addrs, it)
{
if (it->item.family != msg->ifa_family) if (it->item.family != msg->ifa_family)
continue; continue;
@ -719,19 +721,18 @@ handle_address(struct module *mod, uint16_t type,
static bool static bool
foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len, foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr *genl, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *ctx), size_t len, void *ctx),
void *ctx) void *ctx)
{ {
const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN; const uint8_t *raw = (const uint8_t *)genl + GENL_HDRLEN;
const uint8_t *end = (const uint8_t *)genl + len; const uint8_t *end = (const uint8_t *)genl + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw < end; raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw)
{
uint16_t type = attr->nla_type & NLA_TYPE_MASK; uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0;; bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
;
const void *payload = raw + NLA_HDRLEN; const void *payload = raw + NLA_HDRLEN;
if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx)) if (!cb(mod, iface, type, nested, payload, attr->nla_len - NLA_HDRLEN, ctx))
@ -743,18 +744,15 @@ foreach_nlattr(struct module *mod, struct iface *iface, const struct genlmsghdr
static bool static bool
foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len, foreach_nlattr_nested(struct module *mod, struct iface *iface, const void *parent_payload, size_t len,
bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool (*cb)(struct module *mod, struct iface *iface, uint16_t type, bool nested,
bool nested, const void *payload, size_t len, const void *payload, size_t len, void *ctx),
void *ctx),
void *ctx) void *ctx)
{ {
const uint8_t *raw = parent_payload; const uint8_t *raw = parent_payload;
const uint8_t *end = parent_payload + len; const uint8_t *end = parent_payload + len;
for (const struct nlattr *attr = (const struct nlattr *)raw; for (const struct nlattr *attr = (const struct nlattr *)raw; raw < end;
raw < end; raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw) {
raw += NLA_ALIGN(attr->nla_len), attr = (const struct nlattr *)raw)
{
uint16_t type = attr->nla_type & NLA_TYPE_MASK; uint16_t type = attr->nla_type & NLA_TYPE_MASK;
bool nested = (attr->nla_type & NLA_F_NESTED) != 0; bool nested = (attr->nla_type & NLA_F_NESTED) != 0;
const void *payload = raw + NLA_HDRLEN; const void *payload = raw + NLA_HDRLEN;
@ -772,8 +770,8 @@ struct mcast_group {
}; };
static bool static bool
parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool nested, parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len,
const void *payload, size_t len, void *_ctx) void *_ctx)
{ {
struct mcast_group *ctx = _ctx; struct mcast_group *ctx = _ctx;
@ -790,7 +788,8 @@ parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool n
default: default:
LOG_WARN("unrecognized GENL MCAST GRP attribute: " LOG_WARN("unrecognized GENL MCAST GRP attribute: "
"type=%hu, nested=%d, len=%zu", type, nested, len); "type=%hu, nested=%d, len=%zu",
type, nested, len);
break; break;
} }
@ -798,8 +797,8 @@ parse_mcast_group(struct module *mod, struct iface *iface, uint16_t type, bool n
} }
static bool static bool
parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool nested, parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len,
const void *payload, size_t len, void *_ctx) void *_ctx)
{ {
struct private *m = mod->private; struct private *m = mod->private;
@ -814,9 +813,7 @@ parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool
* CONNECT/DISCONNECT events. * CONNECT/DISCONNECT events.
*/ */
int r = setsockopt( int r = setsockopt(m->genl_sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP, &group.id, sizeof(int));
m->genl_sock, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
&group.id, sizeof(int));
if (r < 0) if (r < 0)
LOG_ERRNO("failed to joint the nl80211 MLME mcast group"); LOG_ERRNO("failed to joint the nl80211 MLME mcast group");
@ -826,8 +823,8 @@ parse_mcast_groups(struct module *mod, struct iface *iface, uint16_t type, bool
} }
static bool static bool
handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len,
const void *payload, size_t len, void *_ctx) void *_ctx)
{ {
struct private *m = mod->private; struct private *m = mod->private;
@ -839,7 +836,7 @@ handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool ne
} }
case CTRL_ATTR_FAMILY_NAME: case CTRL_ATTR_FAMILY_NAME:
//LOG_INFO("NAME: %.*s (%zu bytes)", (int)len, (const char *)payload, len); // LOG_INFO("NAME: %.*s (%zu bytes)", (int)len, (const char *)payload, len);
break; break;
case CTRL_ATTR_MCAST_GROUPS: case CTRL_ATTR_MCAST_GROUPS:
@ -848,17 +845,17 @@ handle_genl_ctrl(struct module *mod, struct iface *iface, uint16_t type, bool ne
default: default:
LOG_DBG("unrecognized GENL CTRL attribute: " LOG_DBG("unrecognized GENL CTRL attribute: "
"type=%hu, nested=%d, len=%zu", type, nested, len); "type=%hu, nested=%d, len=%zu",
type, nested, len);
break; break;
} }
return true; return true;
} }
static bool static bool
find_nl80211_iface(struct module *mod, struct iface *_iface, uint16_t type, bool nested, find_nl80211_iface(struct module *mod, struct iface *_iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *ctx) size_t len, void *ctx)
{ {
struct private *m = mod->private; struct private *m = mod->private;
struct iface **iface = ctx; struct iface **iface = ctx;
@ -868,7 +865,8 @@ find_nl80211_iface(struct module *mod, struct iface *_iface, uint16_t type, bool
if (*iface != NULL) if (*iface != NULL)
if (*(uint32_t *)payload == (*iface)->index) if (*(uint32_t *)payload == (*iface)->index)
return false; return false;
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
if (*(uint32_t *)payload != it->item.index) if (*(uint32_t *)payload != it->item.index)
continue; continue;
*iface = &it->item; *iface = &it->item;
@ -882,8 +880,8 @@ find_nl80211_iface(struct module *mod, struct iface *_iface, uint16_t type, bool
} }
static bool static bool
handle_nl80211_new_interface(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_new_interface(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *_ctx) size_t len, void *_ctx)
{ {
switch (type) { switch (type) {
case NL80211_ATTR_IFINDEX: case NL80211_ATTR_IFINDEX:
@ -907,7 +905,8 @@ handle_nl80211_new_interface(struct module *mod, struct iface *iface, uint16_t t
default: default:
LOG_DBG("%s: unrecognized nl80211 attribute: " LOG_DBG("%s: unrecognized nl80211 attribute: "
"type=%hu, nested=%d, len=%zu", iface->name, type, nested, len); "type=%hu, nested=%d, len=%zu",
iface->name, type, nested, len);
break; break;
} }
@ -919,8 +918,8 @@ struct rate_info_ctx {
}; };
static bool static bool
handle_nl80211_rate_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_rate_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *_ctx) size_t len, void *_ctx)
{ {
struct rate_info_ctx *ctx = _ctx; struct rate_info_ctx *ctx = _ctx;
@ -942,7 +941,8 @@ handle_nl80211_rate_info(struct module *mod, struct iface *iface, uint16_t type,
default: default:
LOG_DBG("%s: unrecognized nl80211 rate info attribute: " LOG_DBG("%s: unrecognized nl80211 rate info attribute: "
"type=%hu, nested=%d, len=%zu", iface->name, type, nested, len); "type=%hu, nested=%d, len=%zu",
iface->name, type, nested, len);
break; break;
} }
@ -954,8 +954,8 @@ struct station_info_ctx {
}; };
static bool static bool
handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *_ctx) size_t len, void *_ctx)
{ {
struct station_info_ctx *ctx = _ctx; struct station_info_ctx *ctx = _ctx;
@ -974,8 +974,7 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty
case NL80211_STA_INFO_TX_BITRATE: { case NL80211_STA_INFO_TX_BITRATE: {
struct rate_info_ctx rctx = {0}; struct rate_info_ctx rctx = {0};
foreach_nlattr_nested( foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_rate_info, &rctx);
mod, iface, payload, len, &handle_nl80211_rate_info, &rctx);
LOG_DBG("TX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.); LOG_DBG("TX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -987,8 +986,7 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty
case NL80211_STA_INFO_RX_BITRATE: { case NL80211_STA_INFO_RX_BITRATE: {
struct rate_info_ctx rctx = {0}; struct rate_info_ctx rctx = {0};
foreach_nlattr_nested( foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_rate_info, &rctx);
mod, iface, payload, len, &handle_nl80211_rate_info, &rctx);
LOG_DBG("RX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.); LOG_DBG("RX bitrate: %.1f Mbit/s", rctx.bitrate / 1000. / 1000.);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -1000,7 +998,8 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty
default: default:
LOG_DBG("%s: unrecognized nl80211 station info attribute: " LOG_DBG("%s: unrecognized nl80211 station info attribute: "
"type=%hu, nested=%d, len=%zu", iface->name, type, nested, len); "type=%hu, nested=%d, len=%zu",
iface->name, type, nested, len);
break; break;
} }
@ -1008,8 +1007,8 @@ handle_nl80211_station_info(struct module *mod, struct iface *iface, uint16_t ty
} }
static bool static bool
handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *_ctx) size_t len, void *_ctx)
{ {
switch (type) { switch (type) {
case NL80211_ATTR_IFINDEX: case NL80211_ATTR_IFINDEX:
@ -1017,8 +1016,7 @@ handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t typ
case NL80211_ATTR_STA_INFO: { case NL80211_ATTR_STA_INFO: {
struct station_info_ctx ctx = {0}; struct station_info_ctx ctx = {0};
foreach_nlattr_nested( foreach_nlattr_nested(mod, iface, payload, len, &handle_nl80211_station_info, &ctx);
mod, iface, payload, len, &handle_nl80211_station_info, &ctx);
if (ctx.update_bar) if (ctx.update_bar)
mod->bar->refresh(mod->bar); mod->bar->refresh(mod->bar);
@ -1027,7 +1025,8 @@ handle_nl80211_new_station(struct module *mod, struct iface *iface, uint16_t typ
default: default:
LOG_DBG("%s: unrecognized nl80211 attribute: " LOG_DBG("%s: unrecognized nl80211 attribute: "
"type=%hu, nested=%d, len=%zu", iface->name, type, nested, len); "type=%hu, nested=%d, len=%zu",
iface->name, type, nested, len);
break; break;
} }
@ -1041,7 +1040,7 @@ handle_ies(struct module *mod, struct iface *iface, const void *_ies, size_t len
while (len >= 2 && len - 2 >= ies[1]) { while (len >= 2 && len - 2 >= ies[1]) {
switch (ies[0]) { switch (ies[0]) {
case 0: { /* SSID */ case 0: { /* SSID */
const char *ssid = (const char *)&ies[2]; const char *ssid = (const char *)&ies[2];
const size_t ssid_len = ies[1]; const size_t ssid_len = ies[1];
@ -1072,8 +1071,8 @@ struct scan_results_context {
}; };
static bool static bool
handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload, size_t len,
const void *payload, size_t len, void *_ctx) void *_ctx)
{ {
struct scan_results_context *ctx = _ctx; struct scan_results_context *ctx = _ctx;
@ -1113,8 +1112,8 @@ handle_nl80211_bss(struct module *mod, struct iface *iface, uint16_t type, bool
} }
static bool static bool
handle_nl80211_scan_results(struct module *mod, struct iface *iface, uint16_t type, bool nested, handle_nl80211_scan_results(struct module *mod, struct iface *iface, uint16_t type, bool nested, const void *payload,
const void *payload, size_t len, void *_ctx) size_t len, void *_ctx)
{ {
struct scan_results_context ctx = {0}; struct scan_results_context ctx = {0};
@ -1172,7 +1171,8 @@ handle_stats(struct module *mod, uint32_t seq, struct rt_stats_msg *msg)
struct iface *iface = NULL; struct iface *iface = NULL;
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
if (seq != it->item.get_stats_seq_nr) if (seq != it->item.get_stats_seq_nr)
continue; continue;
iface = &it->item; iface = &it->item;
@ -1241,16 +1241,14 @@ parse_rt_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
break; break;
} }
case NLMSG_ERROR:{ case NLMSG_ERROR: {
const struct nlmsgerr *err = NLMSG_DATA(hdr); const struct nlmsgerr *err = NLMSG_DATA(hdr);
LOG_ERRNO_P(-err->error, "netlink RT reply"); LOG_ERRNO_P(-err->error, "netlink RT reply");
return false; return false;
} }
default: default:
LOG_WARN( LOG_WARN("unrecognized netlink message type: 0x%x", hdr->nlmsg_type);
"unrecognized netlink message type: 0x%x",
hdr->nlmsg_type);
return false; return false;
} }
} }
@ -1288,8 +1286,7 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
/* Current request is now considered complete */ /* Current request is now considered complete */
m->nl80211.get_scan_seq_nr = 0; m->nl80211.get_scan_seq_nr = 0;
tll_foreach(m->ifaces, it) tll_foreach(m->ifaces, it) send_nl80211_get_station(m, &it->item);
send_nl80211_get_station(m, &it->item);
} }
} }
@ -1300,11 +1297,10 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
switch (genl->cmd) { switch (genl->cmd) {
case NL80211_CMD_NEW_INTERFACE: case NL80211_CMD_NEW_INTERFACE:
if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface))
continue; continue;
LOG_DBG("%s: got interface information", iface->name); LOG_DBG("%s: got interface information", iface->name);
foreach_nlattr( foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_new_interface, NULL);
mod, iface, genl, msg_size, &handle_nl80211_new_interface, NULL);
break; break;
case NL80211_CMD_CONNECT: case NL80211_CMD_CONNECT:
@ -1324,7 +1320,7 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
case NL80211_CMD_DISCONNECT: case NL80211_CMD_DISCONNECT:
if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface))
continue; continue;
LOG_DBG("%s: disconnected, resetting SSID etc", iface->name); LOG_DBG("%s: disconnected, resetting SSID etc", iface->name);
@ -1338,20 +1334,18 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
case NL80211_CMD_NEW_STATION: case NL80211_CMD_NEW_STATION:
if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface))
continue; continue;
LOG_DBG("%s: got station information", iface->name); LOG_DBG("%s: got station information", iface->name);
foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_new_station, NULL); foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_new_station, NULL);
LOG_DBG("%s: signal: %d dBm, RX=%u Mbit/s, TX=%u Mbit/s", LOG_DBG("%s: signal: %d dBm, RX=%u Mbit/s, TX=%u Mbit/s", iface->name, iface->signal_strength_dbm,
iface->name, iface->signal_strength_dbm, iface->rx_bitrate / 1000 / 1000, iface->tx_bitrate / 1000 / 1000);
iface->rx_bitrate / 1000 / 1000,
iface->tx_bitrate / 1000 / 1000);
break; break;
case NL80211_CMD_NEW_SCAN_RESULTS: case NL80211_CMD_NEW_SCAN_RESULTS:
if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface)) if (foreach_nlattr(mod, NULL, genl, msg_size, &find_nl80211_iface, &iface))
continue; continue;
LOG_DBG("%s: got scan results", iface->name); LOG_DBG("%s: got scan results", iface->name);
foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_scan_results, NULL); foreach_nlattr(mod, iface, genl, msg_size, &handle_nl80211_scan_results, NULL);
@ -1372,15 +1366,12 @@ parse_genl_reply(struct module *mod, const struct nlmsghdr *hdr, size_t len)
else if (nl_errno == ENOENT) else if (nl_errno == ENOENT)
; /* iface down? */ ; /* iface down? */
else { else {
LOG_ERRNO_P(nl_errno, "nl80211 reply (seq-nr: %u)", LOG_ERRNO_P(nl_errno, "nl80211 reply (seq-nr: %u)", hdr->nlmsg_seq);
hdr->nlmsg_seq);
} }
} }
else { else {
LOG_WARN( LOG_WARN("unrecognized netlink message type: 0x%x", hdr->nlmsg_type);
"unrecognized netlink message type: 0x%x",
hdr->nlmsg_type);
return false; return false;
} }
} }
@ -1422,9 +1413,7 @@ run(struct module *mod)
if (m->rt_sock < 0 || m->genl_sock < 0) if (m->rt_sock < 0 || m->genl_sock < 0)
goto out; goto out;
if (!send_rt_request(m, RTM_GETLINK) || if (!send_rt_request(m, RTM_GETLINK) || !send_ctrl_get_family_request(m)) {
!send_ctrl_get_family_request(m))
{
goto out; goto out;
} }
@ -1442,9 +1431,7 @@ run(struct module *mod)
if (fds[0].revents & (POLLIN | POLLHUP)) if (fds[0].revents & (POLLIN | POLLHUP))
break; break;
if ((fds[1].revents & POLLHUP) || if ((fds[1].revents & POLLHUP) || (fds[2].revents & POLLHUP)) {
(fds[2].revents & POLLHUP))
{
LOG_ERR("disconnected from netlink socket"); LOG_ERR("disconnected from netlink socket");
break; break;
} }
@ -1493,7 +1480,8 @@ run(struct module *mod)
break; break;
} }
tll_foreach(m->ifaces, it) { tll_foreach(m->ifaces, it)
{
send_nl80211_get_station(m, &it->item); send_nl80211_get_station(m, &it->item);
send_rt_getstats_request(m, &it->item); send_rt_getstats_request(m, &it->item);
}; };
@ -1502,7 +1490,7 @@ run(struct module *mod)
ret = 0; ret = 0;
out: out:
if (m->rt_sock >= 0) if (m->rt_sock >= 0)
close(m->rt_sock); close(m->rt_sock);
if (m->genl_sock >= 0) if (m->genl_sock >= 0)
@ -1552,14 +1540,12 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *left_spacing = yml_get_value(node, "left-spacing");
const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *right_spacing = yml_get_value(node, "right-spacing");
int left = spacing != NULL ? yml_value_as_int(spacing) : int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; int right = spacing != NULL ? yml_value_as_int(spacing)
int right = spacing != NULL ? yml_value_as_int(spacing) : : right_spacing != NULL ? yml_value_as_int(right_spacing)
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; : 0;
return network_new( return network_new(conf_to_particle(content, inherited), poll != NULL ? yml_value_as_int(poll) : 0, left, right);
conf_to_particle(content, inherited),
poll != NULL ? yml_value_as_int(poll) : 0, left, right);
} }
static bool static bool
@ -1570,8 +1556,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
int interval = yml_value_as_int(node); int interval = yml_value_as_int(node);
if (interval > 0 && interval < min_poll_interval) { if (interval > 0 && interval < min_poll_interval) {
LOG_ERR("%s: interval value cannot be less than %ldms", LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -867,9 +867,7 @@ content(struct module *module)
/* sink */ /* sink */
output_informations output_informations
= (private->data->target_sink == NULL = (private->data->target_sink == NULL ? &output_informations_null : &private->sink_informations);
? &output_informations_null
: &private->sink_informations);
struct tag_set sink_tag_set = (struct tag_set){ struct tag_set sink_tag_set = (struct tag_set){
.tags = (struct tag *[]){ .tags = (struct tag *[]){
@ -888,9 +886,7 @@ content(struct module *module)
/* source */ /* source */
output_informations output_informations
= (private->data->target_source == NULL = (private->data->target_source == NULL ? &output_informations_null : &private->source_informations);
? &output_informations_null
: &private->source_informations);
struct tag_set source_tag_set = (struct tag_set){ struct tag_set source_tag_set = (struct tag_set){
.tags = (struct tag *[]){ .tags = (struct tag *[]){

View file

@ -4,8 +4,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <sys/timerfd.h> #include <sys/timerfd.h>
#include <unistd.h>
#include <pulse/pulseaudio.h> #include <pulse/pulseaudio.h>
@ -17,7 +17,8 @@
#include "../log.h" #include "../log.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
char *sink_name; char *sink_name;
char *source_name; char *source_name;
struct particle *label; struct particle *label;
@ -69,9 +70,9 @@ content(struct module *mod)
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
pa_volume_t sink_volume_max = pa_cvolume_max(&priv->sink_volume); pa_volume_t sink_volume_max = pa_cvolume_max(&priv->sink_volume);
pa_volume_t source_volume_max = pa_cvolume_max(&priv->source_volume); pa_volume_t source_volume_max = pa_cvolume_max(&priv->source_volume);
int sink_percent = round(100.0 * sink_volume_max / PA_VOLUME_NORM); int sink_percent = round(100.0 * sink_volume_max / PA_VOLUME_NORM);
int source_percent = round(100.0 * source_volume_max / PA_VOLUME_NORM); int source_percent = round(100.0 * source_volume_max / PA_VOLUME_NORM);
struct tag_set tags = { struct tag_set tags = {
@ -106,11 +107,7 @@ context_error(pa_context *c)
} }
static void static void
abort_event_cb(pa_mainloop_api *api, abort_event_cb(pa_mainloop_api *api, pa_io_event *event, int fd, pa_io_event_flags_t flags, void *userdata)
pa_io_event *event,
int fd,
pa_io_event_flags_t flags,
void *userdata)
{ {
struct module *mod = userdata; struct module *mod = userdata;
struct private *priv = mod->private; struct private *priv = mod->private;
@ -119,11 +116,7 @@ abort_event_cb(pa_mainloop_api *api,
} }
static void static void
refresh_timer_cb(pa_mainloop_api *api, refresh_timer_cb(pa_mainloop_api *api, pa_io_event *event, int fd, pa_io_event_flags_t flags, void *userdata)
pa_io_event *event,
int fd,
pa_io_event_flags_t flags,
void *userdata)
{ {
struct module *mod = userdata; struct module *mod = userdata;
struct private *priv = mod->private; struct private *priv = mod->private;
@ -155,8 +148,8 @@ schedule_refresh(struct module *mod)
// Start the refresh timer. // Start the refresh timer.
struct itimerspec t = { struct itimerspec t = {
.it_interval = { .tv_sec = 0, .tv_nsec = 0 }, .it_interval = {.tv_sec = 0, .tv_nsec = 0},
.it_value = { .tv_sec = 0, .tv_nsec = 50000000 }, .it_value = {.tv_sec = 0, .tv_nsec = 50000000},
}; };
timerfd_settime(priv->refresh_timer_fd, 0, &t, NULL); timerfd_settime(priv->refresh_timer_fd, 0, &t, NULL);
@ -200,12 +193,10 @@ set_sink_info(struct module *mod, const pa_sink_info *sink_info)
free(priv->sink_port); free(priv->sink_port);
priv->sink_online = true; priv->sink_online = true;
priv->sink_index = sink_info->index; priv->sink_index = sink_info->index;
priv->sink_volume = sink_info->volume; priv->sink_volume = sink_info->volume;
priv->sink_muted = sink_info->mute; priv->sink_muted = sink_info->mute;
priv->sink_port = sink_info->active_port != NULL priv->sink_port = sink_info->active_port != NULL ? strdup(sink_info->active_port->description) : NULL;
? strdup(sink_info->active_port->description)
: NULL;
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
@ -234,12 +225,10 @@ set_source_info(struct module *mod, const pa_source_info *source_info)
free(priv->source_port); free(priv->source_port);
priv->source_online = true; priv->source_online = true;
priv->source_index = source_info->index; priv->source_index = source_info->index;
priv->source_volume = source_info->volume; priv->source_volume = source_info->volume;
priv->source_muted = source_info->mute; priv->source_muted = source_info->mute;
priv->source_port = source_info->active_port != NULL priv->source_port = source_info->active_port != NULL ? strdup(source_info->active_port->description) : NULL;
? strdup(source_info->active_port->description)
: NULL;
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
@ -293,32 +282,28 @@ server_info_cb(pa_context *c, const pa_server_info *i, void *userdata)
static void static void
get_sink_info_by_name(pa_context *c, const char *name, void *userdata) get_sink_info_by_name(pa_context *c, const char *name, void *userdata)
{ {
pa_operation *o = pa_operation *o = pa_context_get_sink_info_by_name(c, name, sink_info_cb, userdata);
pa_context_get_sink_info_by_name(c, name, sink_info_cb, userdata);
pa_operation_unref(o); pa_operation_unref(o);
} }
static void static void
get_source_info_by_name(pa_context *c, const char *name, void *userdata) get_source_info_by_name(pa_context *c, const char *name, void *userdata)
{ {
pa_operation *o = pa_operation *o = pa_context_get_source_info_by_name(c, name, source_info_cb, userdata);
pa_context_get_source_info_by_name(c, name, source_info_cb, userdata);
pa_operation_unref(o); pa_operation_unref(o);
} }
static void static void
get_sink_info_by_index(pa_context *c, uint32_t index, void *userdata) get_sink_info_by_index(pa_context *c, uint32_t index, void *userdata)
{ {
pa_operation *o = pa_operation *o = pa_context_get_sink_info_by_index(c, index, sink_info_cb, userdata);
pa_context_get_sink_info_by_index(c, index, sink_info_cb, userdata);
pa_operation_unref(o); pa_operation_unref(o);
} }
static void static void
get_source_info_by_index(pa_context *c, uint32_t index, void *userdata) get_source_info_by_index(pa_context *c, uint32_t index, void *userdata)
{ {
pa_operation *o = pa_operation *o = pa_context_get_source_info_by_index(c, index, source_info_cb, userdata);
pa_context_get_source_info_by_index(c, index, source_info_cb, userdata);
pa_operation_unref(o); pa_operation_unref(o);
} }
@ -332,15 +317,12 @@ get_server_info(pa_context *c, void *userdata)
static void static void
subscribe(pa_context *c, void *userdata) subscribe(pa_context *c, void *userdata)
{ {
pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SERVER pa_subscription_mask_t mask = PA_SUBSCRIPTION_MASK_SERVER | PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE;
| PA_SUBSCRIPTION_MASK_SINK
| PA_SUBSCRIPTION_MASK_SOURCE;
pa_operation *o = pa_context_subscribe(c, mask, NULL, userdata); pa_operation *o = pa_context_subscribe(c, mask, NULL, userdata);
pa_operation_unref(o); pa_operation_unref(o);
} }
static pa_context * static pa_context *connect_to_server(struct module *mod);
connect_to_server(struct module *mod);
static void static void
context_state_change_cb(pa_context *c, void *userdata) context_state_change_cb(pa_context *c, void *userdata)
@ -380,16 +362,13 @@ context_state_change_cb(pa_context *c, void *userdata)
} }
static void static void
subscription_event_cb(pa_context *c, subscription_event_cb(pa_context *c, pa_subscription_event_type_t event_type, uint32_t index, void *userdata)
pa_subscription_event_type_t event_type,
uint32_t index,
void *userdata)
{ {
struct module *mod = userdata; struct module *mod = userdata;
struct private *priv = mod->private; struct private *priv = mod->private;
int facility = event_type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK; int facility = event_type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
int type = event_type & PA_SUBSCRIPTION_EVENT_TYPE_MASK; int type = event_type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
switch (facility) { switch (facility) {
case PA_SUBSCRIPTION_EVENT_SERVER: case PA_SUBSCRIPTION_EVENT_SERVER:
@ -435,8 +414,7 @@ connect_to_server(struct module *mod)
pa_context_set_subscribe_callback(c, subscription_event_cb, mod); pa_context_set_subscribe_callback(c, subscription_event_cb, mod);
// Connect to server. // Connect to server.
pa_context_flags_t flags = PA_CONTEXT_NOFAIL pa_context_flags_t flags = PA_CONTEXT_NOFAIL | PA_CONTEXT_NOAUTOSPAWN;
| PA_CONTEXT_NOAUTOSPAWN;
if (pa_context_connect(c, NULL, flags, NULL) < 0) { if (pa_context_connect(c, NULL, flags, NULL) < 0) {
LOG_ERR("failed to connect to PulseAudio server: %s", context_error(c)); LOG_ERR("failed to connect to PulseAudio server: %s", context_error(c));
pa_context_unref(c); pa_context_unref(c);
@ -477,10 +455,8 @@ run(struct module *mod)
// Poll refresh timer and abort event. // Poll refresh timer and abort event.
pa_mainloop_api *api = pa_mainloop_get_api(priv->mainloop); pa_mainloop_api *api = pa_mainloop_get_api(priv->mainloop);
api->io_new(api, priv->refresh_timer_fd, PA_IO_EVENT_INPUT, api->io_new(api, priv->refresh_timer_fd, PA_IO_EVENT_INPUT, refresh_timer_cb, mod);
refresh_timer_cb, mod); api->io_new(api, mod->abort_fd, PA_IO_EVENT_INPUT | PA_IO_EVENT_HANGUP, abort_event_cb, mod);
api->io_new(api, mod->abort_fd, PA_IO_EVENT_INPUT | PA_IO_EVENT_HANGUP,
abort_event_cb, mod);
// Run main loop. // Run main loop.
if (pa_mainloop_run(priv->mainloop, &ret) < 0) { if (pa_mainloop_run(priv->mainloop, &ret) < 0) {
@ -497,9 +473,7 @@ run(struct module *mod)
} }
static struct module * static struct module *
pulse_new(const char *sink_name, pulse_new(const char *sink_name, const char *source_name, struct particle *label)
const char *source_name,
struct particle *label)
{ {
struct private *priv = calloc(1, sizeof *priv); struct private *priv = calloc(1, sizeof *priv);
priv->label = label; priv->label = label;
@ -522,10 +496,9 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *source = yml_get_value(node, "source"); const struct yml_node *source = yml_get_value(node, "source");
const struct yml_node *content = yml_get_value(node, "content"); const struct yml_node *content = yml_get_value(node, "content");
return pulse_new( return pulse_new(sink != NULL ? yml_value_as_string(sink) : "@DEFAULT_SINK@",
sink != NULL ? yml_value_as_string(sink) : "@DEFAULT_SINK@", source != NULL ? yml_value_as_string(source) : "@DEFAULT_SOURCE@",
source != NULL ? yml_value_as_string(source) : "@DEFAULT_SOURCE@", conf_to_particle(content, inherited));
conf_to_particle(content, inherited));
} }
static bool static bool

View file

@ -1,15 +1,15 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <string.h>
#include <unistd.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h>
#include <libudev.h> #include <libudev.h>
@ -17,10 +17,10 @@
#define LOG_MODULE "removables" #define LOG_MODULE "removables"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h" #include "../plugin.h"
@ -54,7 +54,8 @@ struct block_device {
tll(struct partition) partitions; tll(struct partition) partitions;
}; };
struct private { struct private
{
struct particle *label; struct particle *label;
int left_spacing; int left_spacing;
int right_spacing; int right_spacing;
@ -75,8 +76,7 @@ free_partition(struct partition *p)
static void static void
free_device(struct block_device *b) free_device(struct block_device *b)
{ {
tll_foreach(b->partitions, it) tll_foreach(b->partitions, it) free_partition(&it->item);
free_partition(&it->item);
tll_free(b->partitions); tll_free(b->partitions);
free(b->sys_path); free(b->sys_path);
@ -91,8 +91,7 @@ destroy(struct module *mod)
struct private *m = mod->private; struct private *m = mod->private;
m->label->destroy(m->label); m->label->destroy(m->label);
tll_foreach(m->devices, it) tll_foreach(m->devices, it) free_device(&it->item);
free_device(&it->item);
tll_free(m->devices); tll_free(m->devices);
tll_free_and_free(m->ignore, free); tll_free_and_free(m->ignore, free);
@ -113,24 +112,23 @@ content(struct module *mod)
tll(const struct partition *) partitions = tll_init(); tll(const struct partition *) partitions = tll_init();
tll_foreach(m->devices, dev) { tll_foreach(m->devices, dev)
tll_foreach(dev->item.partitions, part) { {
tll_push_back(partitions, &part->item); tll_foreach(dev->item.partitions, part) { tll_push_back(partitions, &part->item); }
}
} }
struct exposable *exposables[max(tll_length(partitions), 1)]; struct exposable *exposables[max(tll_length(partitions), 1)];
size_t idx = 0; size_t idx = 0;
tll_foreach(partitions, it) { tll_foreach(partitions, it)
{
const struct partition *p = it->item; const struct partition *p = it->item;
char dummy_label[16]; char dummy_label[16];
const char *label = p->label; const char *label = p->label;
if (label == NULL) { if (label == NULL) {
snprintf(dummy_label, sizeof(dummy_label), snprintf(dummy_label, sizeof(dummy_label), "%.1f GB", (double)p->size / 1024 / 1024 / 1024 * 512);
"%.1f GB", (double)p->size / 1024 / 1024 / 1024 * 512);
label = dummy_label; label = dummy_label;
} }
@ -157,8 +155,7 @@ content(struct module *mod)
} }
tll_free(partitions); tll_free(partitions);
return dynlist_exposable_new( return dynlist_exposable_new(exposables, idx, m->left_spacing, m->right_spacing);
exposables, idx, m->left_spacing, m->right_spacing);
} }
static void static void
@ -178,9 +175,7 @@ find_mount_points(const char *dev_path, mount_point_list_t *mount_points)
while (fgets(line, sizeof(line), f) != NULL) { while (fgets(line, sizeof(line), f) != NULL) {
char *dev = NULL, *path = NULL; char *dev = NULL, *path = NULL;
if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-] - %*s %ms %*s", if (sscanf(line, "%*u %*u %*u:%*u %*s %ms %*[^-] - %*s %ms %*s", &path, &dev) != 2) {
&path, &dev) != 2)
{
LOG_ERR("failed to parse /proc/self/mountinfo: %s", line); LOG_ERR("failed to parse /proc/self/mountinfo: %s", line);
free(dev); free(dev);
free(path); free(path);
@ -207,9 +202,11 @@ update_mount_points(struct partition *partition)
/* Remove mount points that no longer exists (i.e. old mount /* Remove mount points that no longer exists (i.e. old mount
* points that aren't in the new list) */ * points that aren't in the new list) */
tll_foreach(partition->mount_points, old) { tll_foreach(partition->mount_points, old)
{
bool gone = true; bool gone = true;
tll_foreach(new_mounts, new) { tll_foreach(new_mounts, new)
{
if (strcmp(new->item, old->item) == 0) { if (strcmp(new->item, old->item) == 0) {
/* Remove from new list, as it's already in the /* Remove from new list, as it's already in the
* partitions list */ * partitions list */
@ -228,7 +225,8 @@ update_mount_points(struct partition *partition)
/* Add new mount points (i.e. mount points in the new list, that /* Add new mount points (i.e. mount points in the new list, that
* aren't in the old list) */ * aren't in the old list) */
tll_foreach(new_mounts, new) { tll_foreach(new_mounts, new)
{
LOG_DBG("%s: mounted on %s", partition->dev_path, new->item); LOG_DBG("%s: mounted on %s", partition->dev_path, new->item);
tll_push_back(partition->mount_points, new->item); tll_push_back(partition->mount_points, new->item);
@ -242,14 +240,13 @@ update_mount_points(struct partition *partition)
} }
static struct partition * static struct partition *
add_partition(struct module *mod, struct block_device *block, add_partition(struct module *mod, struct block_device *block, struct udev_device *dev)
struct udev_device *dev)
{ {
struct private *m = mod->private; struct private *m = mod->private;
const char *_size = udev_device_get_sysattr_value(dev, "size"); const char *_size = udev_device_get_sysattr_value(dev, "size");
uint64_t size = 0; uint64_t size = 0;
if (_size != NULL) if (_size != NULL)
sscanf(_size, "%"SCNu64, &size); sscanf(_size, "%" SCNu64, &size);
#if 0 #if 0
struct udev_list_entry *e = NULL; struct udev_list_entry *e = NULL;
@ -260,7 +257,8 @@ add_partition(struct module *mod, struct block_device *block,
const char *devname = udev_device_get_property_value(dev, "DEVNAME"); const char *devname = udev_device_get_property_value(dev, "DEVNAME");
if (devname != NULL) { if (devname != NULL) {
tll_foreach(m->ignore, it) { tll_foreach(m->ignore, it)
{
if (strcmp(it->item, devname) == 0) { if (strcmp(it->item, devname) == 0) {
LOG_DBG("ignoring %s because it is on the ignore list", devname); LOG_DBG("ignoring %s because it is on the ignore list", devname);
return NULL; return NULL;
@ -272,21 +270,17 @@ add_partition(struct module *mod, struct block_device *block,
if (label == NULL) if (label == NULL)
label = udev_device_get_property_value(dev, "ID_LABEL"); label = udev_device_get_property_value(dev, "ID_LABEL");
LOG_INFO("partition: add: %s: label=%s, size=%"PRIu64, LOG_INFO("partition: add: %s: label=%s, size=%" PRIu64, udev_device_get_devnode(dev), label, size);
udev_device_get_devnode(dev), label, size);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_push_back( tll_push_back(block->partitions, ((struct partition){.block = block,
block->partitions, .sys_path = strdup(udev_device_get_devpath(dev)),
((struct partition){ .dev_path = strdup(udev_device_get_devnode(dev)),
.block = block, .label = label != NULL ? strdup(label) : NULL,
.sys_path = strdup(udev_device_get_devpath(dev)), .size = size,
.dev_path = strdup(udev_device_get_devnode(dev)), .audio_cd = false,
.label = label != NULL ? strdup(label) : NULL, .mount_points = tll_init()}));
.size = size,
.audio_cd = false,
.mount_points = tll_init()}));
struct partition *p = &tll_back(block->partitions); struct partition *p = &tll_back(block->partitions);
update_mount_points(p); update_mount_points(p);
@ -296,14 +290,13 @@ add_partition(struct module *mod, struct block_device *block,
} }
static struct partition * static struct partition *
add_audio_cd(struct module *mod, struct block_device *block, add_audio_cd(struct module *mod, struct block_device *block, struct udev_device *dev)
struct udev_device *dev)
{ {
struct private *m = mod->private; struct private *m = mod->private;
const char *_size = udev_device_get_sysattr_value(dev, "size"); const char *_size = udev_device_get_sysattr_value(dev, "size");
uint64_t size = 0; uint64_t size = 0;
if (_size != NULL) if (_size != NULL)
sscanf(_size, "%"SCNu64, &size); sscanf(_size, "%" SCNu64, &size);
#if 0 #if 0
struct udev_list_entry *e = NULL; struct udev_list_entry *e = NULL;
@ -314,7 +307,8 @@ add_audio_cd(struct module *mod, struct block_device *block,
const char *devname = udev_device_get_property_value(dev, "DEVNAME"); const char *devname = udev_device_get_property_value(dev, "DEVNAME");
if (devname != NULL) { if (devname != NULL) {
tll_foreach(m->ignore, it) { tll_foreach(m->ignore, it)
{
if (strcmp(it->item, devname) == 0) { if (strcmp(it->item, devname) == 0) {
LOG_DBG("ignoring %s because it is on the ignore list", devname); LOG_DBG("ignoring %s because it is on the ignore list", devname);
return NULL; return NULL;
@ -322,28 +316,24 @@ add_audio_cd(struct module *mod, struct block_device *block,
} }
} }
const char *_track_count = udev_device_get_property_value( const char *_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
unsigned long track_count = strtoul(_track_count, NULL, 10); unsigned long track_count = strtoul(_track_count, NULL, 10);
char label[64]; char label[64];
snprintf(label, sizeof(label), "Audio CD - %lu tracks", track_count); snprintf(label, sizeof(label), "Audio CD - %lu tracks", track_count);
LOG_INFO("audio CD: add: %s: tracks=%lu, label=%s, size=%"PRIu64, LOG_INFO("audio CD: add: %s: tracks=%lu, label=%s, size=%" PRIu64, udev_device_get_devnode(dev), track_count, label,
udev_device_get_devnode(dev), track_count, label, size); size);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_push_back( tll_push_back(block->partitions, ((struct partition){.block = block,
block->partitions, .sys_path = strdup(udev_device_get_devpath(dev)),
((struct partition){ .dev_path = strdup(udev_device_get_devnode(dev)),
.block = block, .label = label != NULL ? strdup(label) : NULL,
.sys_path = strdup(udev_device_get_devpath(dev)), .size = size,
.dev_path = strdup(udev_device_get_devnode(dev)), .audio_cd = true,
.label = label != NULL ? strdup(label) : NULL, .mount_points = tll_init()}));
.size = size,
.audio_cd = true,
.mount_points = tll_init()}));
struct partition *p = &tll_back(block->partitions); struct partition *p = &tll_back(block->partitions);
update_mount_points(p); update_mount_points(p);
@ -353,17 +343,15 @@ add_audio_cd(struct module *mod, struct block_device *block,
} }
static bool static bool
del_partition(struct module *mod, struct block_device *block, del_partition(struct module *mod, struct block_device *block, struct udev_device *dev)
struct udev_device *dev)
{ {
const char *sys_path = udev_device_get_devpath(dev); const char *sys_path = udev_device_get_devpath(dev);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_foreach(block->partitions, it) { tll_foreach(block->partitions, it)
{
if (strcmp(it->item.sys_path, sys_path) == 0) { if (strcmp(it->item.sys_path, sys_path) == 0) {
LOG_INFO("%s: del: %s", LOG_INFO("%s: del: %s", it->item.audio_cd ? "audio CD" : "partition", it->item.dev_path);
it->item.audio_cd ? "audio CD" : "partition",
it->item.dev_path);
free_partition(&it->item); free_partition(&it->item);
tll_remove(block->partitions, it); tll_remove(block->partitions, it);
@ -392,7 +380,8 @@ add_device(struct module *mod, struct udev_device *dev)
const char *devname = udev_device_get_property_value(dev, "DEVNAME"); const char *devname = udev_device_get_property_value(dev, "DEVNAME");
if (devname != NULL) { if (devname != NULL) {
tll_foreach(m->ignore, it) { tll_foreach(m->ignore, it)
{
if (strcmp(it->item, devname) == 0) { if (strcmp(it->item, devname) == 0) {
LOG_DBG("ignoring %s because it is on the ignore list", devname); LOG_DBG("ignoring %s because it is on the ignore list", devname);
return NULL; return NULL;
@ -403,11 +392,12 @@ add_device(struct module *mod, struct udev_device *dev)
const char *_size = udev_device_get_sysattr_value(dev, "size"); const char *_size = udev_device_get_sysattr_value(dev, "size");
uint64_t size = 0; uint64_t size = 0;
if (_size != NULL) if (_size != NULL)
sscanf(_size, "%"SCNu64, &size); sscanf(_size, "%" SCNu64, &size);
#if 1 #if 1
struct udev_list_entry *e = NULL; struct udev_list_entry *e = NULL;
udev_list_entry_foreach(e, udev_device_get_properties_list_entry(dev)) { udev_list_entry_foreach(e, udev_device_get_properties_list_entry(dev))
{
LOG_DBG("%s -> %s", udev_list_entry_get_name(e), udev_list_entry_get_value(e)); LOG_DBG("%s -> %s", udev_list_entry_get_name(e), udev_list_entry_get_value(e));
} }
#endif #endif
@ -424,27 +414,22 @@ add_device(struct module *mod, struct udev_device *dev)
const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE");
bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0; bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0;
const char *_audio_track_count = udev_device_get_property_value( const char *_audio_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); unsigned long audio_track_count = _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0;
unsigned long audio_track_count =
_audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0;
LOG_DBG("device: add: %s: vendor=%s, model=%s, optical=%d, size=%"PRIu64, LOG_DBG("device: add: %s: vendor=%s, model=%s, optical=%d, size=%" PRIu64, udev_device_get_devnode(dev), vendor,
udev_device_get_devnode(dev), vendor, model, optical, size); model, optical, size);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_push_back( tll_push_back(m->devices, ((struct block_device){.sys_path = strdup(udev_device_get_devpath(dev)),
m->devices, .dev_path = strdup(udev_device_get_devnode(dev)),
((struct block_device){ .size = size,
.sys_path = strdup(udev_device_get_devpath(dev)), .vendor = vendor != NULL ? strdup(vendor) : NULL,
.dev_path = strdup(udev_device_get_devnode(dev)), .model = model != NULL ? strdup(model) : NULL,
.size = size, .optical = optical,
.vendor = vendor != NULL ? strdup(vendor) : NULL, .media = media,
.model = model != NULL ? strdup(model) : NULL, .partitions = tll_init()}));
.optical = optical,
.media = media,
.partitions = tll_init()}));
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
@ -466,7 +451,8 @@ del_device(struct module *mod, struct udev_device *dev)
const char *sys_path = udev_device_get_devpath(dev); const char *sys_path = udev_device_get_devpath(dev);
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
tll_foreach(m->devices, it) { tll_foreach(m->devices, it)
{
if (strcmp(it->item.sys_path, sys_path) == 0) { if (strcmp(it->item.sys_path, sys_path) == 0) {
LOG_DBG("device: del: %s", it->item.dev_path); LOG_DBG("device: del: %s", it->item.dev_path);
@ -490,7 +476,8 @@ change_device(struct module *mod, struct udev_device *dev)
struct block_device *block = NULL; struct block_device *block = NULL;
tll_foreach(m->devices, it) { tll_foreach(m->devices, it)
{
if (strcmp(it->item.sys_path, sys_path) == 0) { if (strcmp(it->item.sys_path, sys_path) == 0) {
block = &it->item; block = &it->item;
break; break;
@ -511,10 +498,8 @@ change_device(struct module *mod, struct udev_device *dev)
const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE"); const char *_fs_usage = udev_device_get_property_value(dev, "ID_FS_USAGE");
bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0; bool have_fs = _fs_usage != NULL && strcmp(_fs_usage, "filesystem") == 0;
const char *_audio_track_count = udev_device_get_property_value( const char *_audio_track_count = udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO");
dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO"); unsigned long audio_track_count = _audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0;
unsigned long audio_track_count =
_audio_track_count != NULL ? strtoul(_audio_track_count, NULL, 10) : 0;
bool media_change = media != block->media; bool media_change = media != block->media;
@ -522,8 +507,7 @@ change_device(struct module *mod, struct udev_device *dev)
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
if (media_change) { if (media_change) {
LOG_INFO("device: change: %s: media %s", LOG_INFO("device: change: %s: media %s", block->dev_path, media ? "inserted" : "removed");
block->dev_path, media ? "inserted" : "removed");
if (media) { if (media) {
if (have_fs) if (have_fs)
@ -569,7 +553,8 @@ handle_udev_event(struct module *mod, struct udev_device *dev)
struct udev_device *parent = udev_device_get_parent(dev); struct udev_device *parent = udev_device_get_parent(dev);
const char *parent_sys_path = udev_device_get_devpath(parent); const char *parent_sys_path = udev_device_get_devpath(parent);
tll_foreach(m->devices, it) { tll_foreach(m->devices, it)
{
if (strcmp(it->item.sys_path, parent_sys_path) != 0) if (strcmp(it->item.sys_path, parent_sys_path) != 0)
continue; continue;
@ -578,8 +563,7 @@ handle_udev_event(struct module *mod, struct udev_device *dev)
else if (del) else if (del)
return del_partition(mod, &it->item, dev); return del_partition(mod, &it->item, dev);
else { else {
LOG_ERR("unimplemented: 'change' event on partition: %s", LOG_ERR("unimplemented: 'change' event on partition: %s", udev_device_get_devpath(dev));
udev_device_get_devpath(dev));
return false; return false;
} }
break; break;
@ -606,15 +590,15 @@ run(struct module *mod)
udev_enumerate_add_match_subsystem(dev_enum, "block"); udev_enumerate_add_match_subsystem(dev_enum, "block");
/* TODO: verify how an optical presents itself */ /* TODO: verify how an optical presents itself */
//udev_enumerate_add_match_sysattr(dev_enum, "removable", "1"); // udev_enumerate_add_match_sysattr(dev_enum, "removable", "1");
udev_enumerate_add_match_property(dev_enum, "DEVTYPE", "disk"); udev_enumerate_add_match_property(dev_enum, "DEVTYPE", "disk");
udev_enumerate_scan_devices(dev_enum); udev_enumerate_scan_devices(dev_enum);
/* Loop list, and for each device, enumerate its partitions */ /* Loop list, and for each device, enumerate its partitions */
struct udev_list_entry *entry = NULL; struct udev_list_entry *entry = NULL;
udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(dev_enum)) { udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(dev_enum))
struct udev_device *dev = udev_device_new_from_syspath( {
udev, udev_list_entry_get_name(entry)); struct udev_device *dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(entry));
struct block_device *block = add_device(mod, dev); struct block_device *block = add_device(mod, dev);
if (block == NULL) { if (block == NULL) {
@ -631,9 +615,9 @@ run(struct module *mod)
udev_enumerate_scan_devices(part_enum); udev_enumerate_scan_devices(part_enum);
struct udev_list_entry *sub_entry = NULL; struct udev_list_entry *sub_entry = NULL;
udev_list_entry_foreach(sub_entry, udev_enumerate_get_list_entry(part_enum)) { udev_list_entry_foreach(sub_entry, udev_enumerate_get_list_entry(part_enum))
struct udev_device *partition = udev_device_new_from_syspath( {
udev, udev_list_entry_get_name(sub_entry)); struct udev_device *partition = udev_device_new_from_syspath(udev, udev_list_entry_get_name(sub_entry));
add_partition(mod, block, partition); add_partition(mod, block, partition);
udev_device_unref(partition); udev_device_unref(partition);
} }
@ -673,8 +657,10 @@ run(struct module *mod)
bool update = false; bool update = false;
if (fds[2].revents & POLLPRI) { if (fds[2].revents & POLLPRI) {
tll_foreach(m->devices, dev) { tll_foreach(m->devices, dev)
tll_foreach(dev->item.partitions, part) { {
tll_foreach(dev->item.partitions, part)
{
if (update_mount_points(&part->item)) if (update_mount_points(&part->item))
update = true; update = true;
} }
@ -703,8 +689,8 @@ run(struct module *mod)
} }
static struct module * static struct module *
removables_new(struct particle *label, int left_spacing, int right_spacing, removables_new(struct particle *label, int left_spacing, int right_spacing, size_t ignore_count,
size_t ignore_count, const char *ignore[static ignore_count]) const char *ignore[static ignore_count])
{ {
struct private *priv = calloc(1, sizeof(*priv)); struct private *priv = calloc(1, sizeof(*priv));
priv->label = label; priv->label = label;
@ -732,26 +718,22 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *right_spacing = yml_get_value(node, "right-spacing");
const struct yml_node *ignore_list = yml_get_value(node, "ignore"); const struct yml_node *ignore_list = yml_get_value(node, "ignore");
int left = spacing != NULL ? yml_value_as_int(spacing) : int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; int right = spacing != NULL ? yml_value_as_int(spacing)
int right = spacing != NULL ? yml_value_as_int(spacing) : : right_spacing != NULL ? yml_value_as_int(right_spacing)
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; : 0;
size_t ignore_count = ignore_list != NULL ? yml_list_length(ignore_list) : 0; size_t ignore_count = ignore_list != NULL ? yml_list_length(ignore_list) : 0;
const char *ignore[max(ignore_count, 1)]; const char *ignore[max(ignore_count, 1)];
if (ignore_list != NULL) { if (ignore_list != NULL) {
size_t i = 0; size_t i = 0;
for (struct yml_list_iter iter = yml_list_iter(ignore_list); for (struct yml_list_iter iter = yml_list_iter(ignore_list); iter.node != NULL; yml_list_next(&iter), i++) {
iter.node != NULL;
yml_list_next(&iter), i++)
{
ignore[i] = yml_value_as_string(iter.node); ignore[i] = yml_value_as_string(iter.node);
} }
} }
return removables_new( return removables_new(conf_to_particle(content, inherited), left, right, ignore_count, ignore);
conf_to_particle(content, inherited), left, right, ignore_count, ignore);
} }
static bool static bool

View file

@ -1,17 +1,17 @@
#include <assert.h>
#include <errno.h>
#include <poll.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <assert.h>
#include <poll.h>
#include <wayland-client.h>
#include <tllist.h> #include <tllist.h>
#include <wayland-client.h>
#define LOG_MODULE "river" #define LOG_MODULE "river"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h" #include "../log.h"
#include "../plugin.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h"
#include "river-status-unstable-v1.h" #include "river-status-unstable-v1.h"
#include "xdg-output-unstable-v1.h" #include "xdg-output-unstable-v1.h"
@ -49,7 +49,8 @@ struct seat {
struct output *output; struct output *output;
}; };
struct private { struct private
{
struct module *mod; struct module *mod;
struct zxdg_output_manager_v1 *xdg_output_manager; struct zxdg_output_manager_v1 *xdg_output_manager;
struct zriver_status_manager_v1 *status_manager; struct zriver_status_manager_v1 *status_manager;
@ -92,13 +93,12 @@ content(struct module *mod)
uint32_t output_focused = 0; uint32_t output_focused = 0;
uint32_t seat_focused = 0; uint32_t seat_focused = 0;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
const struct output *output = &it->item; const struct output *output = &it->item;
if (!m->all_monitors && if (!m->all_monitors && output_bar_is_on != NULL && output->name != NULL
output_bar_is_on != NULL && output->name != NULL && && strcmp(output->name, output_bar_is_on) != 0) {
strcmp(output->name, output_bar_is_on) != 0)
{
continue; continue;
} }
@ -106,7 +106,8 @@ content(struct module *mod)
urgent |= output->urgent; urgent |= output->urgent;
occupied |= output->occupied; occupied |= output->occupied;
tll_foreach(m->seats, it2) { tll_foreach(m->seats, it2)
{
const struct seat *seat = &it2->item; const struct seat *seat = &it2->item;
if (seat->output == output) { if (seat->output == output) {
seat_focused |= output->focused; seat_focused |= output->focused;
@ -127,10 +128,7 @@ content(struct module *mod)
bool is_urgent = urgent & (1u << i); bool is_urgent = urgent & (1u << i);
bool is_occupied = occupied & (1u << i); bool is_occupied = occupied & (1u << i);
const char *state = const char *state = is_urgent ? "urgent" : is_visible ? is_focused ? "focused" : "unfocused" : "invisible";
is_urgent ? "urgent" :
is_visible ? is_focused ? "focused" : "unfocused" :
"invisible";
#if 0 #if 0
LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s", LOG_DBG("tag: #%u, visible=%d, focused=%d, occupied=%d, state=%s",
@ -155,12 +153,10 @@ content(struct module *mod)
if (m->title != NULL) { if (m->title != NULL) {
size_t i = 32; size_t i = 32;
tll_foreach(m->seats, it) { tll_foreach(m->seats, it)
{
const struct seat *seat = &it->item; const struct seat *seat = &it->item;
const char *layout = const char *layout = seat->output != NULL && seat->output->layout != NULL ? seat->output->layout : "";
seat->output != NULL && seat->output->layout != NULL
? seat->output->layout
: "";
struct tag_set tags = { struct tag_set tags = {
.tags = (struct tag *[]){ .tags = (struct tag *[]){
@ -187,15 +183,15 @@ verify_iface_version(const char *iface, uint32_t version, uint32_t wanted)
if (version >= wanted) if (version >= wanted)
return true; return true;
LOG_ERR("%s: need interface version %u, but compositor only implements %u", LOG_ERR("%s: need interface version %u, but compositor only implements %u", iface, wanted, version);
iface, wanted, version);
return false; return false;
} }
static void static void
output_destroy(struct output *output) output_destroy(struct output *output)
{ {
tll_foreach(output->m->seats, it) { tll_foreach(output->m->seats, it)
{
struct seat *seat = &it->item; struct seat *seat = &it->item;
if (seat->output == output) if (seat->output == output)
seat->output = NULL; seat->output = NULL;
@ -223,8 +219,7 @@ seat_destroy(struct seat *seat)
} }
static void static void
focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, uint32_t tags)
uint32_t tags)
{ {
struct output *output = data; struct output *output = data;
@ -241,8 +236,7 @@ focused_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1
} }
static void static void
view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, struct wl_array *tags)
struct wl_array *tags)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->m->mod; struct module *mod = output->m->mod;
@ -254,9 +248,7 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1,
/* Each entry in the list is a view, and the value is the tags /* Each entry in the list is a view, and the value is the tags
* associated with that view */ * associated with that view */
uint32_t *set; uint32_t *set;
wl_array_for_each(set, tags) { wl_array_for_each(set, tags) { output->occupied |= *set; }
output->occupied |= *set;
}
LOG_DBG("output: %s: occupied tags: 0x%0x", output->name, output->occupied); LOG_DBG("output: %s: occupied tags: 0x%0x", output->name, output->occupied);
} }
@ -265,8 +257,7 @@ view_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1,
} }
static void static void
urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, uint32_t tags)
uint32_t tags)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->m->mod; struct module *mod = output->m->mod;
@ -281,9 +272,7 @@ urgent_tags(void *data, struct zriver_output_status_v1 *zriver_output_status_v1,
#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_SINCE_VERSION) #if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_SINCE_VERSION)
static void static void
layout_name(void *data, layout_name(void *data, struct zriver_output_status_v1 *zriver_output_status_v1, const char *name)
struct zriver_output_status_v1 *zriver_output_status_v1,
const char *name)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->m->mod; struct module *mod = output->m->mod;
@ -300,8 +289,7 @@ layout_name(void *data,
#if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_CLEAR_SINCE_VERSION) #if defined(ZRIVER_OUTPUT_STATUS_V1_LAYOUT_NAME_CLEAR_SINCE_VERSION)
static void static void
layout_name_clear(void *data, layout_name_clear(void *data, struct zriver_output_status_v1 *zriver_output_status_v1)
struct zriver_output_status_v1 *zriver_output_status_v1)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->m->mod; struct module *mod = output->m->mod;
@ -329,15 +317,12 @@ static const struct zriver_output_status_v1_listener river_status_output_listene
}; };
static void static void
xdg_output_handle_logical_position(void *data, xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output, int32_t x, int32_t y)
struct zxdg_output_v1 *xdg_output,
int32_t x, int32_t y)
{ {
} }
static void static void
xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output, int32_t width, int32_t height)
int32_t width, int32_t height)
{ {
} }
@ -347,8 +332,7 @@ xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
} }
static void static void
xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output, const char *name)
const char *name)
{ {
struct output *output = data; struct output *output = data;
struct module *mod = output->m->mod; struct module *mod = output->m->mod;
@ -363,8 +347,7 @@ xdg_output_handle_name(void *data, struct zxdg_output_v1 *xdg_output,
} }
static void static void
xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, xdg_output_handle_description(void *data, struct zxdg_output_v1 *xdg_output, const char *description)
const char *description)
{ {
} }
@ -391,36 +374,32 @@ update_output(struct output *output)
output->status = NULL; output->status = NULL;
} }
output->status = zriver_status_manager_v1_get_river_output_status( output->status = zriver_status_manager_v1_get_river_output_status(output->m->status_manager, output->wl_output);
output->m->status_manager, output->wl_output);
if (output->status != NULL) { if (output->status != NULL) {
zriver_output_status_v1_add_listener( zriver_output_status_v1_add_listener(output->status, &river_status_output_listener, output);
output->status, &river_status_output_listener, output);
} }
} }
if (output->m->xdg_output_manager != NULL && output->xdg_output == NULL) { if (output->m->xdg_output_manager != NULL && output->xdg_output == NULL) {
output->xdg_output = zxdg_output_manager_v1_get_xdg_output( output->xdg_output = zxdg_output_manager_v1_get_xdg_output(output->m->xdg_output_manager, output->wl_output);
output->m->xdg_output_manager, output->wl_output);
if (output->xdg_output != NULL) { if (output->xdg_output != NULL) {
zxdg_output_v1_add_listener( zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output);
output->xdg_output, &xdg_output_listener, output);
} }
} }
} }
static void static void
focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct seat *seat = data; struct seat *seat = data;
struct private *m = seat->m; struct private *m = seat->m;
struct module *mod = m->mod; struct module *mod = m->mod;
struct output *output = NULL; struct output *output = NULL;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
if (it->item.wl_output == wl_output) { if (it->item.wl_output == wl_output) {
output = &it->item; output = &it->item;
break; break;
@ -441,8 +420,7 @@ focused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
} }
static void static void
unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, struct wl_output *wl_output)
struct wl_output *wl_output)
{ {
struct seat *seat = data; struct seat *seat = data;
struct private *m = seat->m; struct private *m = seat->m;
@ -451,7 +429,8 @@ unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
{ {
struct output *output = NULL; struct output *output = NULL;
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
if (it->item.wl_output == wl_output) { if (it->item.wl_output == wl_output) {
output = &it->item; output = &it->item;
break; break;
@ -469,8 +448,7 @@ unfocused_output(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1
} }
static void static void
focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *title)
const char *title)
{ {
struct seat *seat = data; struct seat *seat = data;
struct module *mod = seat->m->mod; struct module *mod = seat->m->mod;
@ -485,11 +463,9 @@ focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
const char *output_bar_is_on = mod->bar->output_name(mod->bar); const char *output_bar_is_on = mod->bar->output_name(mod->bar);
if (seat->m->all_monitors || if (seat->m->all_monitors
(output_bar_is_on != NULL && || (output_bar_is_on != NULL && seat->output != NULL && seat->output->name != NULL
seat->output != NULL && seat->output->name != NULL && && strcmp(output_bar_is_on, seat->output->name) == 0)) {
strcmp(output_bar_is_on, seat->output->name) == 0))
{
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
{ {
free(seat->title); free(seat->title);
@ -502,8 +478,7 @@ focused_view(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1,
#if defined(ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION) #if defined(ZRIVER_SEAT_STATUS_V1_MODE_SINCE_VERSION)
static void static void
mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, mode(void *data, struct zriver_seat_status_v1 *zriver_seat_status_v1, const char *name)
const char *name)
{ {
struct seat *seat = data; struct seat *seat = data;
struct module *mod = seat->m->mod; struct module *mod = seat->m->mod;
@ -531,8 +506,7 @@ static const struct zriver_seat_status_v1_listener river_seat_status_listener =
}; };
static void static void
seat_handle_capabilities(void *data, struct wl_seat *wl_seat, seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps)
enum wl_seat_capability caps)
{ {
} }
@ -569,19 +543,16 @@ update_seat(struct seat *seat)
seat->status = NULL; seat->status = NULL;
} }
seat->status = zriver_status_manager_v1_get_river_seat_status( seat->status = zriver_status_manager_v1_get_river_seat_status(seat->m->status_manager, seat->wl_seat);
seat->m->status_manager, seat->wl_seat);
if (seat->status == NULL) if (seat->status == NULL)
return; return;
zriver_seat_status_v1_add_listener( zriver_seat_status_v1_add_listener(seat->status, &river_seat_status_listener, seat);
seat->status, &river_seat_status_listener, seat);
} }
static void static void
handle_global(void *data, struct wl_registry *registry, handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
uint32_t name, const char *interface, uint32_t version)
{ {
struct private *m = data; struct private *m = data;
@ -590,8 +561,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
struct wl_output *wl_output = wl_registry_bind( struct wl_output *wl_output = wl_registry_bind(registry, name, &wl_output_interface, required);
registry, name, &wl_output_interface, required);
if (wl_output == NULL) if (wl_output == NULL)
return; return;
@ -605,8 +575,7 @@ handle_global(void *data, struct wl_registry *registry,
mtx_lock(&m->mod->lock); mtx_lock(&m->mod->lock);
tll_push_back(m->outputs, output); tll_push_back(m->outputs, output);
update_output(&tll_back(m->outputs)); update_output(&tll_back(m->outputs));
tll_foreach(m->seats, it) tll_foreach(m->seats, it) update_seat(&it->item);
update_seat(&it->item);
mtx_unlock(&m->mod->lock); mtx_unlock(&m->mod->lock);
} }
@ -615,12 +584,10 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
m->xdg_output_manager = wl_registry_bind( m->xdg_output_manager = wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, required);
registry, name, &zxdg_output_manager_v1_interface, required);
mtx_lock(&m->mod->lock); mtx_lock(&m->mod->lock);
tll_foreach(m->outputs, it) tll_foreach(m->outputs, it) update_output(&it->item);
update_output(&it->item);
mtx_unlock(&m->mod->lock); mtx_unlock(&m->mod->lock);
} }
@ -629,8 +596,7 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
struct wl_seat *wl_seat = wl_registry_bind( struct wl_seat *wl_seat = wl_registry_bind(registry, name, &wl_seat_interface, required);
registry, name, &wl_seat_interface, required);
if (wl_seat == NULL) if (wl_seat == NULL)
return; return;
@ -649,14 +615,11 @@ handle_global(void *data, struct wl_registry *registry,
if (!verify_iface_version(interface, version, required)) if (!verify_iface_version(interface, version, required))
return; return;
m->status_manager = wl_registry_bind( m->status_manager = wl_registry_bind(registry, name, &zriver_status_manager_v1_interface, min(version, 4));
registry, name, &zriver_status_manager_v1_interface, min(version, 4));
mtx_lock(&m->mod->lock); mtx_lock(&m->mod->lock);
tll_foreach(m->outputs, it) tll_foreach(m->outputs, it) update_output(&it->item);
update_output(&it->item); tll_foreach(m->seats, it) update_seat(&it->item);
tll_foreach(m->seats, it)
update_seat(&it->item);
mtx_unlock(&m->mod->lock); mtx_unlock(&m->mod->lock);
} }
} }
@ -667,7 +630,8 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
struct private *m = data; struct private *m = data;
mtx_lock(&m->mod->lock); mtx_lock(&m->mod->lock);
tll_foreach(m->outputs, it) { tll_foreach(m->outputs, it)
{
if (it->item.wl_name == name) { if (it->item.wl_name == name) {
output_destroy(&it->item); output_destroy(&it->item);
tll_remove(m->outputs, it); tll_remove(m->outputs, it);
@ -676,7 +640,8 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
} }
} }
tll_foreach(m->seats, it) { tll_foreach(m->seats, it)
{
if (it->item.wl_name == name) { if (it->item.wl_name == name) {
seat_destroy(&it->item); seat_destroy(&it->item);
tll_remove(m->seats, it); tll_remove(m->seats, it);
@ -707,9 +672,8 @@ run(struct module *mod)
goto out; goto out;
} }
if ((registry = wl_display_get_registry(display)) == NULL || if ((registry = wl_display_get_registry(display)) == NULL
wl_registry_add_listener(registry, &registry_listener, m) != 0) || wl_registry_add_listener(registry, &registry_listener, m) != 0) {
{
LOG_ERR("failed to get Wayland registry"); LOG_ERR("failed to get Wayland registry");
goto out; goto out;
} }
@ -754,11 +718,9 @@ run(struct module *mod)
ret = 0; ret = 0;
out: out:
tll_foreach(m->seats, it) tll_foreach(m->seats, it) seat_destroy(&it->item);
seat_destroy(&it->item);
tll_free(m->seats); tll_free(m->seats);
tll_foreach(m->outputs, it) tll_foreach(m->outputs, it) output_destroy(&it->item);
output_destroy(&it->item);
tll_free(m->outputs); tll_free(m->outputs);
if (m->xdg_output_manager != NULL) if (m->xdg_output_manager != NULL)
@ -797,10 +759,8 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *title = yml_get_value(node, "title"); const struct yml_node *title = yml_get_value(node, "title");
const struct yml_node *all_monitors = yml_get_value(node, "all-monitors"); const struct yml_node *all_monitors = yml_get_value(node, "all-monitors");
return river_new( return river_new(conf_to_particle(c, inherited), title != NULL ? conf_to_particle(title, inherited) : NULL,
conf_to_particle(c, inherited), all_monitors != NULL ? yml_value_as_bool(all_monitors) : false);
title != NULL ? conf_to_particle(title, inherited) : NULL,
all_monitors != NULL ? yml_value_as_bool(all_monitors) : false);
} }
static bool static bool

View file

@ -1,14 +1,14 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <assert.h> #include <assert.h>
#include <unistd.h> #include <errno.h>
#include <libgen.h> #include <libgen.h>
#include <signal.h> #include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
@ -16,15 +16,16 @@
#define LOG_MODULE "script" #define LOG_MODULE "script"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../module.h" #include "../module.h"
#include "../plugin.h" #include "../plugin.h"
static const long min_poll_interval = 250; static const long min_poll_interval = 250;
struct private { struct private
{
char *path; char *path;
size_t argc; size_t argc;
char **argv; char **argv;
@ -110,9 +111,8 @@ process_line(struct module *mod, const char *line, size_t len)
size_t value_len = line + len - _value; size_t value_len = line + len - _value;
LOG_DBG("%.*s: name=\"%.*s\", type=\"%.*s\", value=\"%.*s\"", LOG_DBG("%.*s: name=\"%.*s\", type=\"%.*s\", value=\"%.*s\"", (int)len, line, (int)name_len, _name, (int)type_len,
(int)len, line, type, (int)value_len, _value);
(int)name_len, _name, (int)type_len, type, (int)value_len, _value);
name = malloc(name_len + 1); name = malloc(name_len + 1);
memcpy(name, _name, name_len); memcpy(name, _name, name_len);
@ -165,16 +165,12 @@ process_line(struct module *mod, const char *line, size_t len)
tag = tag_new_float(mod, name, v); tag = tag_new_float(mod, name, v);
} }
else if ((type_len > 6 && memcmp(type, "range:", 6) == 0) || else if ((type_len > 6 && memcmp(type, "range:", 6) == 0) || (type_len > 9 && memcmp(type, "realtime:", 9) == 0)) {
(type_len > 9 && memcmp(type, "realtime:", 9) == 0))
{
const char *_start = type + 6; const char *_start = type + 6;
const char *split = memchr(_start, '-', type_len - 6); const char *split = memchr(_start, '-', type_len - 6);
if (split == NULL || split == _start || (split + 1) - type >= type_len) { if (split == NULL || split == _start || (split + 1) - type >= type_len) {
LOG_ERR( LOG_ERR("tag range delimiter ('-') not found in type: %.*s", (int)type_len, type);
"tag range delimiter ('-') not found in type: %.*s",
(int)type_len, type);
goto bad_tag; goto bad_tag;
} }
@ -186,9 +182,7 @@ process_line(struct module *mod, const char *line, size_t len)
long start = 0; long start = 0;
for (size_t i = 0; i < start_len; i++) { for (size_t i = 0; i < start_len; i++) {
if (!(_start[i] >= '0' && _start[i] <= '9')) { if (!(_start[i] >= '0' && _start[i] <= '9')) {
LOG_ERR( LOG_ERR("tag range start is not an integer: %.*s", (int)start_len, _start);
"tag range start is not an integer: %.*s",
(int)start_len, _start);
goto bad_tag; goto bad_tag;
} }
@ -199,9 +193,7 @@ process_line(struct module *mod, const char *line, size_t len)
long end = 0; long end = 0;
for (size_t i = 0; i < end_len; i++) { for (size_t i = 0; i < end_len; i++) {
if (!(_end[i] >= '0' && _end[i] <= '9')) { if (!(_end[i] >= '0' && _end[i] <= '9')) {
LOG_ERR( LOG_ERR("tag range end is not an integer: %.*s", (int)end_len, _end);
"tag range end is not an integer: %.*s",
(int)end_len, _end);
goto bad_tag; goto bad_tag;
} }
@ -223,8 +215,7 @@ process_line(struct module *mod, const char *line, size_t len)
} }
if (v < start || v > end) { if (v < start || v > end) {
LOG_ERR("tag value is outside range: %ld <= %ld <= %ld", LOG_ERR("tag value is outside range: %ld <= %ld <= %ld", start, v, end);
start, v, end);
goto bad_tag; goto bad_tag;
} }
@ -326,9 +317,7 @@ data_received(struct module *mod, const char *data, size_t len)
process_transaction(mod, transaction_size); process_transaction(mod, transaction_size);
assert(m->recv_buf.idx >= transaction_size + 1); assert(m->recv_buf.idx >= transaction_size + 1);
memmove(m->recv_buf.data, memmove(m->recv_buf.data, &m->recv_buf.data[transaction_size + 1], m->recv_buf.idx - (transaction_size + 1));
&m->recv_buf.data[transaction_size + 1],
m->recv_buf.idx - (transaction_size + 1));
m->recv_buf.idx -= transaction_size + 1; m->recv_buf.idx -= transaction_size + 1;
} }
@ -432,11 +421,8 @@ execute_script(struct module *mod)
sigemptyset(&mask); sigemptyset(&mask);
const struct sigaction sa = {.sa_handler = SIG_DFL}; const struct sigaction sa = {.sa_handler = SIG_DFL};
if (sigaction(SIGINT, &sa, NULL) < 0 || if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0 || sigaction(SIGCHLD, &sa, NULL) < 0
sigaction(SIGTERM, &sa, NULL) < 0 || || sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
sigaction(SIGCHLD, &sa, NULL) < 0 ||
sigprocmask(SIG_SETMASK, &mask, NULL) < 0)
{
goto fail; goto fail;
} }
@ -452,9 +438,7 @@ execute_script(struct module *mod)
if (dev_null < 0) if (dev_null < 0)
goto fail; goto fail;
if (dup2(dev_null, STDIN_FILENO) < 0 || if (dup2(dev_null, STDIN_FILENO) < 0 || dup2(comm_pipe[1], STDOUT_FILENO) < 0) {
dup2(comm_pipe[1], STDOUT_FILENO) < 0)
{
goto fail; goto fail;
} }
@ -533,9 +517,7 @@ execute_script(struct module *mod)
usleep(10000); usleep(10000);
pid_t waited_pid; pid_t waited_pid;
while ((waited_pid = waitpid( while ((waited_pid = waitpid(pid, NULL, timeout > 0 ? WNOHANG : 0)) == 0) {
pid, NULL, timeout > 0 ? WNOHANG : 0)) == 0)
{
struct timeval now; struct timeval now;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
@ -547,7 +529,7 @@ execute_script(struct module *mod)
/* Don't spinning */ /* Don't spinning */
thrd_yield(); thrd_yield();
usleep(100000); /* 100ms */ usleep(100000); /* 100ms */
} }
if (waited_pid == pid) { if (waited_pid == pid) {
@ -580,7 +562,7 @@ run(struct module *mod)
break; break;
struct timeval now; struct timeval now;
if (gettimeofday(&now, NULL) < 0) { if (gettimeofday(&now, NULL) < 0) {
LOG_ERRNO("failed to get current time"); LOG_ERRNO("failed to get current time");
break; break;
} }
@ -631,8 +613,7 @@ run(struct module *mod)
} }
static struct module * static struct module *
script_new(char *path, size_t argc, const char *const argv[static argc], script_new(char *path, size_t argc, const char *const argv[static argc], int poll_interval, struct particle *_content)
int poll_interval, struct particle *_content)
{ {
struct private *m = calloc(1, sizeof(*m)); struct private *m = calloc(1, sizeof(*m));
m->path = path; m->path = path;
@ -665,10 +646,7 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
if (args != NULL) { if (args != NULL) {
size_t i = 0; size_t i = 0;
for (struct yml_list_iter iter = yml_list_iter(args); for (struct yml_list_iter iter = yml_list_iter(args); iter.node != NULL; yml_list_next(&iter), i++) {
iter.node != NULL;
yml_list_next(&iter), i++)
{
argv[i] = yml_value_as_string(iter.node); argv[i] = yml_value_as_string(iter.node);
} }
} }
@ -691,10 +669,8 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
} else } else
path = strdup(yml_path); path = strdup(yml_path);
return script_new( return script_new(path, argc, argv, poll_interval != NULL ? yml_value_as_int(poll_interval) : 0,
path, argc, argv, conf_to_particle(c, inherited));
poll_interval != NULL ? yml_value_as_int(poll_interval) : 0,
conf_to_particle(c, inherited));
} }
static bool static bool
@ -709,8 +685,7 @@ conf_verify_path(keychain_t *chain, const struct yml_node *node)
const bool is_absolute = path[0] == '/'; const bool is_absolute = path[0] == '/';
if (!is_tilde && !is_absolute) { if (!is_tilde && !is_absolute) {
LOG_ERR("%s: path must either be absolute, or begin with '~/'", LOG_ERR("%s: path must either be absolute, or begin with '~/'", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
@ -730,8 +705,7 @@ conf_verify_poll_interval(keychain_t *chain, const struct yml_node *node)
return false; return false;
if (yml_value_as_int(node) < min_poll_interval) { if (yml_value_as_int(node) < min_poll_interval) {
LOG_ERR("%s: interval value cannot be less than %ldms", LOG_ERR("%s: interval value cannot be less than %ldms", conf_err_prefix(chain, node), min_poll_interval);
conf_err_prefix(chain, node), min_poll_interval);
return false; return false;
} }

View file

@ -3,15 +3,15 @@
#define LOG_MODULE "sway-xkb" #define LOG_MODULE "sway-xkb"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h" #include "../config.h"
#include "../log.h"
#include "../particles/dynlist.h" #include "../particles/dynlist.h"
#include "../plugin.h" #include "../plugin.h"
#include "i3-ipc.h"
#include "i3-common.h" #include "i3-common.h"
#include "i3-ipc.h"
#define max(x, y) ((x) > (y) ? (x) : (y)) #define max(x, y) ((x) > (y) ? (x) : (y))
@ -21,7 +21,8 @@ struct input {
char *layout; char *layout;
}; };
struct private { struct private
{
struct particle *template; struct particle *template;
int left_spacing; int left_spacing;
int right_spacing; int right_spacing;
@ -89,8 +90,7 @@ content(struct module *mod)
} }
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
return dynlist_exposable_new( return dynlist_exposable_new(particles, m->num_existing_inputs, m->left_spacing, m->right_spacing);
particles, m->num_existing_inputs, m->left_spacing, m->right_spacing);
} }
static bool static bool
@ -121,8 +121,7 @@ handle_input_reply(int sock, int type, const struct json_object *json, void *_mo
struct input *input = NULL; struct input *input = NULL;
for (size_t i = 0; i < m->num_inputs; i++) { for (size_t i = 0; i < m->num_inputs; i++) {
struct input *maybe_input = &m->inputs[i]; struct input *maybe_input = &m->inputs[i];
if (strcmp(maybe_input->identifier, id) == 0 && !maybe_input->exists) if (strcmp(maybe_input->identifier, id) == 0 && !maybe_input->exists) {
{
input = maybe_input; input = maybe_input;
LOG_DBG("adding: %s", id); LOG_DBG("adding: %s", id);
@ -142,8 +141,7 @@ handle_input_reply(int sock, int type, const struct json_object *json, void *_mo
/* Get current/active layout */ /* Get current/active layout */
struct json_object *layout; struct json_object *layout;
if (!json_object_object_get_ex( if (!json_object_object_get_ex(obj, "xkb_active_layout_name", &layout))
obj, "xkb_active_layout_name", &layout))
return false; return false;
const char *new_layout_str = json_object_get_string(layout); const char *new_layout_str = json_object_get_string(layout);
@ -240,8 +238,7 @@ handle_input_event(int sock, int type, const struct json_object *json, void *_mo
/* Get current/active layout */ /* Get current/active layout */
struct json_object *layout; struct json_object *layout;
if (!json_object_object_get_ex( if (!json_object_object_get_ex(obj, "xkb_active_layout_name", &layout))
obj, "xkb_active_layout_name", &layout))
return false; return false;
const char *new_layout_str = json_object_get_string(layout); const char *new_layout_str = json_object_get_string(layout);
@ -309,8 +306,8 @@ run(struct module *mod)
} }
static struct module * static struct module *
sway_xkb_new(struct particle *template, const char *identifiers[], sway_xkb_new(struct particle *template, const char *identifiers[], size_t num_identifiers, int left_spacing,
size_t num_identifiers, int left_spacing, int right_spacing) int right_spacing)
{ {
struct private *m = calloc(1, sizeof(*m)); struct private *m = calloc(1, sizeof(*m));
m->template = template; m->template = template;
@ -343,40 +340,32 @@ from_conf(const struct yml_node *node, struct conf_inherit inherited)
const struct yml_node *left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *left_spacing = yml_get_value(node, "left-spacing");
const struct yml_node *right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *right_spacing = yml_get_value(node, "right-spacing");
int left = spacing != NULL ? yml_value_as_int(spacing) : int left = spacing != NULL ? yml_value_as_int(spacing) : left_spacing != NULL ? yml_value_as_int(left_spacing) : 0;
left_spacing != NULL ? yml_value_as_int(left_spacing) : 0; int right = spacing != NULL ? yml_value_as_int(spacing)
int right = spacing != NULL ? yml_value_as_int(spacing) : : right_spacing != NULL ? yml_value_as_int(right_spacing)
right_spacing != NULL ? yml_value_as_int(right_spacing) : 0; : 0;
const struct yml_node *ids = yml_get_value(node, "identifiers"); const struct yml_node *ids = yml_get_value(node, "identifiers");
const size_t num_ids = yml_list_length(ids); const size_t num_ids = yml_list_length(ids);
const char *identifiers[num_ids]; const char *identifiers[num_ids];
size_t i = 0; size_t i = 0;
for (struct yml_list_iter it = yml_list_iter(ids); for (struct yml_list_iter it = yml_list_iter(ids); it.node != NULL; yml_list_next(&it), i++) {
it.node != NULL;
yml_list_next(&it), i++)
{
identifiers[i] = yml_value_as_string(it.node); identifiers[i] = yml_value_as_string(it.node);
} }
return sway_xkb_new( return sway_xkb_new(conf_to_particle(c, inherited), identifiers, num_ids, left, right);
conf_to_particle(c, inherited), identifiers, num_ids, left, right);
} }
static bool static bool
verify_identifiers(keychain_t *chain, const struct yml_node *node) verify_identifiers(keychain_t *chain, const struct yml_node *node)
{ {
if (!yml_is_list(node)) { if (!yml_is_list(node)) {
LOG_ERR("%s: identifiers must be a list of strings", LOG_ERR("%s: identifiers must be a list of strings", conf_err_prefix(chain, node));
conf_err_prefix(chain, node));
return false; return false;
} }
for (struct yml_list_iter it = yml_list_iter(node); for (struct yml_list_iter it = yml_list_iter(node); it.node != NULL; yml_list_next(&it)) {
it.node != NULL;
yml_list_next(&it))
{
if (!conf_verify_string(chain, it.node)) if (!conf_verify_string(chain, it.node))
return false; return false;
} }
@ -404,5 +393,5 @@ const struct module_iface module_sway_xkb_iface = {
}; };
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) #if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
extern const struct module_iface iface __attribute__((weak, alias("module_sway_xkb_iface"))) ; extern const struct module_iface iface __attribute__((weak, alias("module_sway_xkb_iface")));
#endif #endif

View file

@ -1,7 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h> #include <poll.h>
@ -10,10 +10,10 @@
#define LOG_MODULE "xkb" #define LOG_MODULE "xkb"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
#include "../xcb.h" #include "../xcb.h"
@ -32,7 +32,8 @@ struct indicators {
char **names; char **names;
}; };
struct private { struct private
{
struct particle *label; struct particle *label;
struct indicators indicators; struct indicators indicators;
struct layouts layouts; struct layouts layouts;
@ -117,10 +118,8 @@ xkb_enable(xcb_connection_t *conn)
{ {
xcb_generic_error_t *err; xcb_generic_error_t *err;
xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension( xcb_xkb_use_extension_cookie_t cookie = xcb_xkb_use_extension(conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION);
conn, XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION); xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply(conn, cookie, &err);
xcb_xkb_use_extension_reply_t *reply = xcb_xkb_use_extension_reply(
conn, cookie, &err);
if (err != NULL) { if (err != NULL) {
LOG_ERR("failed to query for XKB extension: %s", xcb_error(err)); LOG_ERR("failed to query for XKB extension: %s", xcb_error(err));
@ -142,8 +141,7 @@ xkb_enable(xcb_connection_t *conn)
static int static int
get_xkb_event_base(xcb_connection_t *conn) get_xkb_event_base(xcb_connection_t *conn)
{ {
const struct xcb_query_extension_reply_t *reply = xcb_get_extension_data( const struct xcb_query_extension_reply_t *reply = xcb_get_extension_data(conn, &xcb_xkb_id);
conn, &xcb_xkb_id);
if (reply == NULL) { if (reply == NULL) {
LOG_ERR("failed to get XKB extension data"); LOG_ERR("failed to get XKB extension data");
@ -159,19 +157,14 @@ get_xkb_event_base(xcb_connection_t *conn)
} }
static bool static bool
get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts, struct indicators *indicators)
struct indicators *indicators)
{ {
xcb_generic_error_t *err; xcb_generic_error_t *err;
xcb_xkb_get_names_cookie_t cookie = xcb_xkb_get_names( xcb_xkb_get_names_cookie_t cookie = xcb_xkb_get_names(conn, XCB_XKB_ID_USE_CORE_KBD,
conn, XCB_XKB_NAME_DETAIL_GROUP_NAMES | XCB_XKB_NAME_DETAIL_SYMBOLS
XCB_XKB_ID_USE_CORE_KBD, | XCB_XKB_NAME_DETAIL_INDICATOR_NAMES);
XCB_XKB_NAME_DETAIL_GROUP_NAMES |
XCB_XKB_NAME_DETAIL_SYMBOLS |
XCB_XKB_NAME_DETAIL_INDICATOR_NAMES);
xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply( xcb_xkb_get_names_reply_t *reply = xcb_xkb_get_names_reply(conn, cookie, &err);
conn, cookie, &err);
if (err != NULL) { if (err != NULL) {
LOG_ERR("failed to get layouts and indicators: %s", xcb_error(err)); LOG_ERR("failed to get layouts and indicators: %s", xcb_error(err));
@ -181,22 +174,18 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
xcb_xkb_get_names_value_list_t vlist; xcb_xkb_get_names_value_list_t vlist;
void *buf = xcb_xkb_get_names_value_list(reply); void *buf = xcb_xkb_get_names_value_list(reply);
xcb_xkb_get_names_value_list_unpack( xcb_xkb_get_names_value_list_unpack(buf, reply->nTypes, reply->indicators, reply->virtualMods, reply->groupNames,
buf, reply->nTypes, reply->indicators, reply->virtualMods, reply->nKeys, reply->nKeyAliases, reply->nRadioGroups, reply->which, &vlist);
reply->groupNames, reply->nKeys, reply->nKeyAliases,
reply->nRadioGroups, reply->which, &vlist);
/* Number of groups (aka layouts) */ /* Number of groups (aka layouts) */
layouts->count = xcb_xkb_get_names_value_list_groups_length(reply, &vlist); layouts->count = xcb_xkb_get_names_value_list_groups_length(reply, &vlist);
layouts->layouts = calloc(layouts->count, sizeof(layouts->layouts[0])); layouts->layouts = calloc(layouts->count, sizeof(layouts->layouts[0]));
/* Number of indicators */ /* Number of indicators */
indicators->count = xcb_xkb_get_names_value_list_indicator_names_length( indicators->count = xcb_xkb_get_names_value_list_indicator_names_length(reply, &vlist);
reply, &vlist);
indicators->names = calloc(indicators->count, sizeof(indicators->names[0])); indicators->names = calloc(indicators->count, sizeof(indicators->names[0]));
xcb_get_atom_name_cookie_t symbols_name_cookie = xcb_get_atom_name( xcb_get_atom_name_cookie_t symbols_name_cookie = xcb_get_atom_name(conn, vlist.symbolsName);
conn, vlist.symbolsName);
xcb_get_atom_name_cookie_t group_name_cookies[layouts->count]; xcb_get_atom_name_cookie_t group_name_cookies[layouts->count];
for (size_t i = 0; i < layouts->count; i++) for (size_t i = 0; i < layouts->count; i++)
@ -209,17 +198,14 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
char *symbols = NULL; char *symbols = NULL;
/* Get layout short names (e.g. "us") */ /* Get layout short names (e.g. "us") */
xcb_get_atom_name_reply_t *atom_name = xcb_get_atom_name_reply( xcb_get_atom_name_reply_t *atom_name = xcb_get_atom_name_reply(conn, symbols_name_cookie, &err);
conn, symbols_name_cookie, &err);
if (err != NULL) { if (err != NULL) {
LOG_ERR("failed to get 'symbols' atom name: %s", xcb_error(err)); LOG_ERR("failed to get 'symbols' atom name: %s", xcb_error(err));
free(err); free(err);
goto err; goto err;
} }
symbols = strndup( symbols = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name));
xcb_get_atom_name_name(atom_name),
xcb_get_atom_name_name_length(atom_name));
LOG_DBG("symbols: %s", symbols); LOG_DBG("symbols: %s", symbols);
free(atom_name); free(atom_name);
@ -232,9 +218,7 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
goto err; goto err;
} }
layouts->layouts[i].name = strndup( layouts->layouts[i].name = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name));
xcb_get_atom_name_name(atom_name),
xcb_get_atom_name_name_length(atom_name));
LOG_DBG("layout #%zd: long name: %s", i, layouts->layouts[i].name); LOG_DBG("layout #%zd: long name: %s", i, layouts->layouts[i].name);
free(atom_name); free(atom_name);
@ -249,9 +233,7 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
goto err; goto err;
} }
indicators->names[i] = strndup( indicators->names[i] = strndup(xcb_get_atom_name_name(atom_name), xcb_get_atom_name_name_length(atom_name));
xcb_get_atom_name_name(atom_name),
xcb_get_atom_name_name_length(atom_name));
LOG_DBG("indicator #%zd: %s", i, indicators->names[i]); LOG_DBG("indicator #%zd: %s", i, indicators->names[i]);
free(atom_name); free(atom_name);
@ -259,8 +241,7 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
/* e.g. pc+us+inet(evdev)+group(..) */ /* e.g. pc+us+inet(evdev)+group(..) */
size_t layout_idx = 0; size_t layout_idx = 0;
for (char *tok_ctx = NULL, *tok = strtok_r(symbols, "+", &tok_ctx); for (char *tok_ctx = NULL, *tok = strtok_r(symbols, "+", &tok_ctx); tok != NULL;
tok != NULL;
tok = strtok_r(NULL, "+", &tok_ctx)) { tok = strtok_r(NULL, "+", &tok_ctx)) {
char *fname = strtok(tok, "()"); char *fname = strtok(tok, "()");
@ -279,8 +260,7 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
continue; continue;
if (layout_idx >= layouts->count) { if (layout_idx >= layouts->count) {
LOG_ERR("layout vs group name count mismatch: %zd > %zd", LOG_ERR("layout vs group name count mismatch: %zd > %zd", layout_idx + 1, layouts->count);
layout_idx + 1, layouts->count);
goto err; goto err;
} }
@ -290,8 +270,7 @@ get_layouts_and_indicators(xcb_connection_t *conn, struct layouts *layouts,
} }
if (layout_idx != layouts->count) { if (layout_idx != layouts->count) {
LOG_ERR("layout vs group name count mismatch: %zd != %zd", LOG_ERR("layout vs group name count mismatch: %zd != %zd", layout_idx, layouts->count);
layout_idx, layouts->count);
goto err; goto err;
} }
@ -312,10 +291,8 @@ get_current_layout(xcb_connection_t *conn)
{ {
xcb_generic_error_t *err; xcb_generic_error_t *err;
xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state( xcb_xkb_get_state_cookie_t cookie = xcb_xkb_get_state(conn, XCB_XKB_ID_USE_CORE_KBD);
conn, XCB_XKB_ID_USE_CORE_KBD); xcb_xkb_get_state_reply_t *reply = xcb_xkb_get_state_reply(conn, cookie, &err);
xcb_xkb_get_state_reply_t *reply = xcb_xkb_get_state_reply(
conn, cookie, &err);
if (err != NULL) { if (err != NULL) {
LOG_ERR("failed to get XKB state: %s", xcb_error(err)); LOG_ERR("failed to get XKB state: %s", xcb_error(err));
@ -332,10 +309,8 @@ static uint32_t
get_indicator_state(xcb_connection_t *conn) get_indicator_state(xcb_connection_t *conn)
{ {
xcb_generic_error_t *err; xcb_generic_error_t *err;
xcb_xkb_get_indicator_state_cookie_t cookie = xcb_xkb_get_indicator_state( xcb_xkb_get_indicator_state_cookie_t cookie = xcb_xkb_get_indicator_state(conn, XCB_XKB_ID_USE_CORE_KBD);
conn, XCB_XKB_ID_USE_CORE_KBD); xcb_xkb_get_indicator_state_reply_t *reply = xcb_xkb_get_indicator_state_reply(conn, cookie, &err);
xcb_xkb_get_indicator_state_reply_t *reply = xcb_xkb_get_indicator_state_reply(
conn, cookie, &err);
if (err != NULL) { if (err != NULL) {
LOG_ERR("failed to get indicator state: %s", xcb_error(err)); LOG_ERR("failed to get indicator state: %s", xcb_error(err));
@ -353,23 +328,14 @@ get_indicator_state(xcb_connection_t *conn)
static bool static bool
register_for_events(xcb_connection_t *conn) register_for_events(xcb_connection_t *conn)
{ {
xcb_void_cookie_t cookie = xcb_xkb_select_events_checked( xcb_void_cookie_t cookie
conn, = xcb_xkb_select_events_checked(conn, XCB_XKB_ID_USE_CORE_KBD,
XCB_XKB_ID_USE_CORE_KBD, (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY
( | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY),
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | 0,
XCB_XKB_EVENT_TYPE_STATE_NOTIFY | (XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY | XCB_XKB_EVENT_TYPE_STATE_NOTIFY
XCB_XKB_EVENT_TYPE_MAP_NOTIFY | | XCB_XKB_EVENT_TYPE_MAP_NOTIFY | XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY),
XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY 0, 0, NULL);
),
0,
(
XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY |
XCB_XKB_EVENT_TYPE_STATE_NOTIFY |
XCB_XKB_EVENT_TYPE_MAP_NOTIFY |
XCB_XKB_EVENT_TYPE_INDICATOR_STATE_NOTIFY
),
0, 0, NULL);
xcb_generic_error_t *err = xcb_request_check(conn, cookie); xcb_generic_error_t *err = xcb_request_check(conn, cookie);
if (err != NULL) { if (err != NULL) {
@ -393,10 +359,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
assert(xcb_fd >= 0); assert(xcb_fd >= 0);
while (!has_error) { while (!has_error) {
struct pollfd pfds[] = { struct pollfd pfds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = xcb_fd, .events = POLLIN | POLLHUP}};
{.fd = mod->abort_fd, .events = POLLIN },
{.fd = xcb_fd, .events = POLLIN | POLLHUP }
};
/* Use poll() since xcb_wait_for_events() doesn't return on signals */ /* Use poll() since xcb_wait_for_events() doesn't return on signals */
if (poll(pfds, sizeof(pfds) / sizeof(pfds[0]), -1) < 0) { if (poll(pfds, sizeof(pfds) / sizeof(pfds[0]), -1) < 0) {
@ -425,9 +388,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
* not for long though... * not for long though...
*/ */
for (xcb_generic_event_t *_evt = xcb_wait_for_event(conn); for (xcb_generic_event_t *_evt = xcb_wait_for_event(conn); _evt != NULL; _evt = xcb_poll_for_event(conn)) {
_evt != NULL;
_evt = xcb_poll_for_event(conn)) {
if (_evt->response_type != xkb_event_base) { if (_evt->response_type != xkb_event_base) {
LOG_WARN("non-XKB event ignored: %d", _evt->response_type); LOG_WARN("non-XKB event ignored: %d", _evt->response_type);
@ -435,7 +396,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
continue; continue;
} }
switch(_evt->pad0) { switch (_evt->pad0) {
default: default:
LOG_WARN("unimplemented XKB event: %d", _evt->pad0); LOG_WARN("unimplemented XKB event: %d", _evt->pad0);
break; break;
@ -463,7 +424,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
mtx_unlock(&mod->lock); mtx_unlock(&mod->lock);
bar->refresh(bar); bar->refresh(bar);
} else { } else {
/* Can happen while transitioning to a new map */ /* Can happen while transitioning to a new map */
free_layouts(layouts); free_layouts(layouts);
free_indicators(indicators); free_indicators(indicators);
} }
@ -472,8 +433,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
} }
case XCB_XKB_STATE_NOTIFY: { case XCB_XKB_STATE_NOTIFY: {
const xcb_xkb_state_notify_event_t *evt = const xcb_xkb_state_notify_event_t *evt = (const xcb_xkb_state_notify_event_t *)_evt;
(const xcb_xkb_state_notify_event_t *)_evt;
if (evt->changed & XCB_XKB_STATE_PART_GROUP_STATE) { if (evt->changed & XCB_XKB_STATE_PART_GROUP_STATE) {
mtx_lock(&mod->lock); mtx_lock(&mod->lock);
@ -490,8 +450,8 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
break; break;
case XCB_XKB_INDICATOR_STATE_NOTIFY: { case XCB_XKB_INDICATOR_STATE_NOTIFY: {
const xcb_xkb_indicator_state_notify_event_t *evt = const xcb_xkb_indicator_state_notify_event_t *evt
(const xcb_xkb_indicator_state_notify_event_t *)_evt; = (const xcb_xkb_indicator_state_notify_event_t *)_evt;
#if 0 #if 0
size_t idx = __builtin_ctz(evt->stateChanged); size_t idx = __builtin_ctz(evt->stateChanged);
@ -508,8 +468,7 @@ event_loop(struct module *mod, xcb_connection_t *conn, int xkb_event_base)
continue; continue;
bool enabled = (evt->state >> i) & 1; bool enabled = (evt->state >> i) & 1;
LOG_DBG("%s: %s", m->indicators.names[i], LOG_DBG("%s: %s", m->indicators.names[i], enabled ? "enabled" : "disabled");
enabled ? "enabled" : "disabled");
const char *name = m->indicators.names[i]; const char *name = m->indicators.names[i];
bool is_caps = strcasecmp(name, "caps lock") == 0; bool is_caps = strcasecmp(name, "caps lock") == 0;
@ -609,18 +568,12 @@ talk_to_xkb(struct module *mod, xcb_connection_t *conn)
size_t idx = 0; size_t idx = 0;
for (size_t i = 0; i < layouts.count; i++) { for (size_t i = 0; i < layouts.count; i++) {
idx += snprintf(&buf[idx], sizeof(buf) - idx, "%s%s (%s)%s", idx += snprintf(&buf[idx], sizeof(buf) - idx, "%s%s (%s)%s", i == m->current ? "*" : "",
i == m->current ? "*" : "", layouts.layouts[i].name, layouts.layouts[i].symbol, i + 1 < layouts.count ? ", " : "");
layouts.layouts[i].name,
layouts.layouts[i].symbol,
i + 1 < layouts.count ? ", " : "");
} }
LOG_INFO("layouts: %s, caps-lock:%s, num-lock:%s, scroll-lock:%s", LOG_INFO("layouts: %s, caps-lock:%s, num-lock:%s, scroll-lock:%s", buf, caps_lock ? "on" : "off",
buf, num_lock ? "on" : "off", scroll_lock ? "on" : "off");
caps_lock ? "on" : "off",
num_lock ? "on" : "off",
scroll_lock ? "on" : "off");
} }
mtx_lock(&mod->lock); mtx_lock(&mod->lock);

View file

@ -1,29 +1,30 @@
#include <assert.h>
#include <errno.h>
#include <libgen.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <threads.h> #include <threads.h>
#include <libgen.h> #include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <poll.h> #include <poll.h>
#include <sys/stat.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_aux.h> #include <xcb/xcb_aux.h>
#include <xcb/xcb_event.h> #include <xcb/xcb_event.h>
#define LOG_MODULE "xwindow" #define LOG_MODULE "xwindow"
#include "../log.h"
#include "../bar/bar.h" #include "../bar/bar.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../plugin.h" #include "../plugin.h"
#include "../xcb.h" #include "../xcb.h"
struct private { struct private
{
/* Accessed from bar thread only */ /* Accessed from bar thread only */
struct particle *label; struct particle *label;
@ -48,23 +49,19 @@ static void
update_active_window(struct private *m) update_active_window(struct private *m)
{ {
if (m->active_win != 0) { if (m->active_win != 0) {
xcb_void_cookie_t c = xcb_change_window_attributes_checked( xcb_void_cookie_t c = xcb_change_window_attributes_checked(m->conn, m->active_win, XCB_CW_EVENT_MASK,
m->conn, m->active_win, XCB_CW_EVENT_MASK, (const uint32_t[]){XCB_EVENT_MASK_NO_EVENT});
(const uint32_t []){XCB_EVENT_MASK_NO_EVENT});
xcb_generic_error_t *e = xcb_request_check(m->conn, c); xcb_generic_error_t *e = xcb_request_check(m->conn, c);
if (e != NULL) { if (e != NULL) {
LOG_DBG( LOG_DBG("failed to de-register events on previous active window: %s", xcb_error(e));
"failed to de-register events on previous active window: %s",
xcb_error(e));
free(e); free(e);
} }
m->active_win = 0; m->active_win = 0;
} }
xcb_get_property_cookie_t c = xcb_get_property( xcb_get_property_cookie_t c = xcb_get_property(m->conn, 0, m->root_win, _NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 32);
m->conn, 0, m->root_win, _NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 0, 32);
xcb_generic_error_t *e; xcb_generic_error_t *e;
xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e); xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e);
@ -86,9 +83,8 @@ update_active_window(struct private *m)
free(r); free(r);
if (m->active_win != 0) { if (m->active_win != 0) {
xcb_change_window_attributes( xcb_change_window_attributes(m->conn, m->active_win, XCB_CW_EVENT_MASK,
m->conn, m->active_win, XCB_CW_EVENT_MASK, (const uint32_t[]){XCB_EVENT_MASK_PROPERTY_CHANGE});
(const uint32_t []){XCB_EVENT_MASK_PROPERTY_CHANGE});
} }
} }
@ -105,8 +101,7 @@ update_application(struct module *mod)
if (m->active_win == 0) if (m->active_win == 0)
return; return;
xcb_get_property_cookie_t c = xcb_get_property( xcb_get_property_cookie_t c = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_PID, XCB_ATOM_CARDINAL, 0, 32);
m->conn, 0, m->active_win, _NET_WM_PID, XCB_ATOM_CARDINAL, 0, 32);
xcb_generic_error_t *e; xcb_generic_error_t *e;
xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e); xcb_get_property_reply_t *r = xcb_get_property_reply(m->conn, c, &e);
@ -164,12 +159,11 @@ update_title(struct module *mod)
if (m->active_win == 0) if (m->active_win == 0)
return; return;
xcb_get_property_cookie_t c1 = xcb_get_property( xcb_get_property_cookie_t c1
m->conn, 0, m->active_win, _NET_WM_VISIBLE_NAME, UTF8_STRING, 0, 1000); = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_VISIBLE_NAME, UTF8_STRING, 0, 1000);
xcb_get_property_cookie_t c2 = xcb_get_property( xcb_get_property_cookie_t c2 = xcb_get_property(m->conn, 0, m->active_win, _NET_WM_NAME, UTF8_STRING, 0, 1000);
m->conn, 0, m->active_win, _NET_WM_NAME, UTF8_STRING, 0, 1000); xcb_get_property_cookie_t c3
xcb_get_property_cookie_t c3 = xcb_get_property( = xcb_get_property(m->conn, 0, m->active_win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1000);
m->conn, 0, m->active_win, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 0, 1000);
xcb_generic_error_t *e1, *e2, *e3; xcb_generic_error_t *e1, *e2, *e3;
xcb_get_property_reply_t *r1 = xcb_get_property_reply(m->conn, c1, &e1); xcb_get_property_reply_t *r1 = xcb_get_property_reply(m->conn, c1, &e1);
@ -207,7 +201,7 @@ update_title(struct module *mod)
free(r1); free(r1);
free(r2); free(r2);
free(r3); free(r3);
} }
static int static int
run(struct module *mod) run(struct module *mod)
@ -227,19 +221,16 @@ run(struct module *mod)
/* Need a window(?) to be able to process events */ /* Need a window(?) to be able to process events */
m->monitor_win = xcb_generate_id(m->conn); m->monitor_win = xcb_generate_id(m->conn);
xcb_create_window(m->conn, screen->root_depth, m->monitor_win, screen->root, xcb_create_window(m->conn, screen->root_depth, m->monitor_win, screen->root, -1, -1, 1, 1, 0,
-1, -1, 1, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, XCB_CW_OVERRIDE_REDIRECT,
0, (const uint32_t[]){1});
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual,
XCB_CW_OVERRIDE_REDIRECT, (const uint32_t []){1});
xcb_map_window(m->conn, m->monitor_win); xcb_map_window(m->conn, m->monitor_win);
/* Register for property changes on root window. This allows us to /* Register for property changes on root window. This allows us to
* catch e.g. window switches etc */ * catch e.g. window switches etc */
xcb_change_window_attributes( xcb_change_window_attributes(m->conn, screen->root, XCB_CW_EVENT_MASK,
m->conn, screen->root, XCB_CW_EVENT_MASK, (const uint32_t[]){XCB_EVENT_MASK_PROPERTY_CHANGE});
(const uint32_t []){XCB_EVENT_MASK_PROPERTY_CHANGE});
xcb_flush(m->conn); xcb_flush(m->conn);
@ -252,8 +243,7 @@ run(struct module *mod)
int xcb_fd = xcb_get_file_descriptor(m->conn); int xcb_fd = xcb_get_file_descriptor(m->conn);
while (true) { while (true) {
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}, {.fd = xcb_fd, .events = POLLIN}};
{.fd = xcb_fd, .events = POLLIN}};
if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) { if (poll(fds, sizeof(fds) / sizeof(fds[0]), -1) < 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
@ -267,10 +257,7 @@ run(struct module *mod)
break; break;
} }
for (xcb_generic_event_t *_e = xcb_wait_for_event(m->conn); for (xcb_generic_event_t *_e = xcb_wait_for_event(m->conn); _e != NULL; _e = xcb_poll_for_event(m->conn)) {
_e != NULL;
_e = xcb_poll_for_event(m->conn))
{
switch (XCB_EVENT_RESPONSE_TYPE(_e)) { switch (XCB_EVENT_RESPONSE_TYPE(_e)) {
case 0: case 0:
LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)_e)); LOG_ERR("XCB: %s", xcb_error((const xcb_generic_error_t *)_e));
@ -278,18 +265,13 @@ run(struct module *mod)
case XCB_PROPERTY_NOTIFY: { case XCB_PROPERTY_NOTIFY: {
xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)_e; xcb_property_notify_event_t *e = (xcb_property_notify_event_t *)_e;
if (e->atom == _NET_ACTIVE_WINDOW || if (e->atom == _NET_ACTIVE_WINDOW || e->atom == _NET_CURRENT_DESKTOP) {
e->atom == _NET_CURRENT_DESKTOP)
{
/* Active desktop and/or window changed */ /* Active desktop and/or window changed */
update_active_window(m); update_active_window(m);
update_application(mod); update_application(mod);
update_title(mod); update_title(mod);
mod->bar->refresh(mod->bar); mod->bar->refresh(mod->bar);
} else if (e->atom == _NET_WM_VISIBLE_NAME || } else if (e->atom == _NET_WM_VISIBLE_NAME || e->atom == _NET_WM_NAME || e->atom == XCB_ATOM_WM_NAME) {
e->atom == _NET_WM_NAME ||
e->atom == XCB_ATOM_WM_NAME)
{
assert(e->window == m->active_win); assert(e->window == m->active_win);
update_title(mod); update_title(mod);
mod->bar->refresh(mod->bar); mod->bar->refresh(mod->bar);

View file

@ -1,21 +1,21 @@
#include "particle.h" #include "particle.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#define LOG_MODULE "particle" #define LOG_MODULE "particle"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "log.h"
#include "bar/bar.h" #include "bar/bar.h"
#include "log.h"
void void
particle_default_destroy(struct particle *particle) particle_default_destroy(struct particle *particle)
@ -29,10 +29,8 @@ particle_default_destroy(struct particle *particle)
} }
struct particle * struct particle *
particle_common_new(int left_margin, int right_margin, particle_common_new(int left_margin, int right_margin, char **on_click_templates, struct fcft_font *font,
char **on_click_templates, enum font_shaping font_shaping, pixman_color_t foreground, struct deco *deco)
struct fcft_font *font, enum font_shaping font_shaping,
pixman_color_t foreground, struct deco *deco)
{ {
struct particle *p = calloc(1, sizeof(*p)); struct particle *p = calloc(1, sizeof(*p));
p->left_margin = left_margin; p->left_margin = left_margin;
@ -63,13 +61,11 @@ exposable_default_destroy(struct exposable *exposable)
} }
void void
exposable_render_deco(const struct exposable *exposable, exposable_render_deco(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height)
pixman_image_t *pix, int x, int y, int height)
{ {
const struct deco *deco = exposable->particle->deco; const struct deco *deco = exposable->particle->deco;
if (deco != NULL) if (deco != NULL)
deco->expose(deco, pix, x, y, exposable->width, height); deco->expose(deco, pix, x, y, exposable->width, height);
} }
static bool static bool
@ -114,9 +110,7 @@ tokenize_cmdline(char *cmdline, char ***argv)
return false; return false;
} }
if (!push_argv(argv, &argv_size, p, &idx) || if (!push_argv(argv, &argv_size, p, &idx) || !push_argv(argv, &argv_size, NULL, &idx)) {
!push_argv(argv, &argv_size, NULL, &idx))
{
goto err; goto err;
} else } else
return true; return true;
@ -152,8 +146,7 @@ err:
} }
void void
exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn,
enum mouse_event event, enum mouse_button btn,
int x, int y) int x, int y)
{ {
#if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG #if defined(LOG_ENABLE_DBG) && LOG_ENABLE_DBG
@ -168,17 +161,13 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
[MOUSE_BTN_PREVIOUS] = "previous", [MOUSE_BTN_PREVIOUS] = "previous",
[MOUSE_BTN_NEXT] = "next", [MOUSE_BTN_NEXT] = "next",
}; };
LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)", LOG_DBG("on_mouse: exposable=%p, event=%s, btn=%s, x=%d, y=%d (on-click=%s)", exposable,
exposable, event == ON_MOUSE_MOTION ? "motion" : "click", event == ON_MOUSE_MOTION ? "motion" : "click", button_name[btn], x, y, exposable->on_click[btn]);
button_name[btn], x, y, exposable->on_click[btn]);
#endif #endif
/* If we have a handler, change cursor to a hand */ /* If we have a handler, change cursor to a hand */
const char *cursor = const char *cursor
(exposable->particle != NULL && = (exposable->particle != NULL && exposable->particle->have_on_click_template) ? "hand2" : "left_ptr";
exposable->particle->have_on_click_template)
? "hand2"
: "left_ptr";
bar->set_cursor(bar, cursor); bar->set_cursor(bar, cursor);
/* If this is a mouse click, and we have a handler, execute it */ /* If this is a mouse click, and we have a handler, execute it */
@ -246,7 +235,7 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
case 0: case 0:
/* Child */ /* Child */
close(pipe_fds[0]); /* Close read end */ close(pipe_fds[0]); /* Close read end */
LOG_DBG("executing on-click handler: %s", cmd); LOG_DBG("executing on-click handler: %s", cmd);
@ -254,11 +243,8 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
sigemptyset(&mask); sigemptyset(&mask);
const struct sigaction sa = {.sa_handler = SIG_DFL}; const struct sigaction sa = {.sa_handler = SIG_DFL};
if (sigaction(SIGINT, &sa, NULL) < 0 || if (sigaction(SIGINT, &sa, NULL) < 0 || sigaction(SIGTERM, &sa, NULL) < 0
sigaction(SIGTERM, &sa, NULL) < 0 || || sigaction(SIGCHLD, &sa, NULL) < 0 || sigprocmask(SIG_SETMASK, &mask, NULL) < 0) {
sigaction(SIGCHLD, &sa, NULL) < 0 ||
sigprocmask(SIG_SETMASK, &mask, NULL) < 0)
{
goto fail; goto fail;
} }
@ -271,10 +257,8 @@ exposable_default_on_mouse(struct exposable *exposable, struct bar *bar,
goto fail; goto fail;
} }
if (dup2(dev_null_r, STDIN_FILENO) == -1 || if (dup2(dev_null_r, STDIN_FILENO) == -1 || dup2(dev_null_w, STDOUT_FILENO) == -1
dup2(dev_null_w, STDOUT_FILENO) == -1 || || dup2(dev_null_w, STDERR_FILENO) == -1) {
dup2(dev_null_w, STDERR_FILENO) == -1)
{
LOG_ERRNO("failed to redirect stdin/stdout/stderr"); LOG_ERRNO("failed to redirect stdin/stdout/stderr");
goto fail; goto fail;
} }
@ -316,10 +300,7 @@ exposable_common_new(const struct particle *particle, const struct tag_set *tags
exposable->particle = particle; exposable->particle = particle;
if (particle != NULL && particle->have_on_click_template) { if (particle != NULL && particle->have_on_click_template) {
tags_expand_templates( tags_expand_templates(exposable->on_click, (const char **)particle->on_click_templates, MOUSE_BTN_COUNT, tags);
exposable->on_click,
(const char **)particle->on_click_templates,
MOUSE_BTN_COUNT, tags);
} }
exposable->destroy = &exposable_default_destroy; exposable->destroy = &exposable_default_destroy;
exposable->on_mouse = &exposable_default_on_mouse; exposable->on_mouse = &exposable_default_on_mouse;

View file

@ -42,11 +42,9 @@ struct particle {
struct deco *deco; struct deco *deco;
void (*destroy)(struct particle *particle); void (*destroy)(struct particle *particle);
struct exposable *(*instantiate)(const struct particle *particle, struct exposable *(*instantiate)(const struct particle *particle, const struct tag_set *tags);
const struct tag_set *tags);
}; };
struct exposable { struct exposable {
const struct particle *particle; const struct particle *particle;
void *private; void *private;
@ -56,38 +54,31 @@ struct exposable {
void (*destroy)(struct exposable *exposable); void (*destroy)(struct exposable *exposable);
int (*begin_expose)(struct exposable *exposable); int (*begin_expose)(struct exposable *exposable);
void (*expose)(const struct exposable *exposable, pixman_image_t *pix, void (*expose)(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height);
int x, int y, int height);
void (*on_mouse)(struct exposable *exposable, struct bar *bar, void (*on_mouse)(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x,
enum mouse_event event, enum mouse_button btn, int x, int y); int y);
}; };
struct particle *particle_common_new( struct particle *particle_common_new(int left_margin, int right_margin, char *on_click_templates[],
int left_margin, int right_margin, char *on_click_templates[], struct fcft_font *font, enum font_shaping font_shaping, pixman_color_t foreground,
struct fcft_font *font, enum font_shaping font_shaping, struct deco *deco);
pixman_color_t foreground, struct deco *deco);
void particle_default_destroy(struct particle *particle); void particle_default_destroy(struct particle *particle);
struct exposable *exposable_common_new( struct exposable *exposable_common_new(const struct particle *particle, const struct tag_set *tags);
const struct particle *particle, const struct tag_set *tags);
void exposable_default_destroy(struct exposable *exposable); void exposable_default_destroy(struct exposable *exposable);
void exposable_render_deco( void exposable_render_deco(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height);
const struct exposable *exposable, pixman_image_t *pix, int x, int y, int height);
void exposable_default_on_mouse( void exposable_default_on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
struct exposable *exposable, struct bar *bar, enum mouse_button btn, int x, int y);
enum mouse_event event, enum mouse_button btn, int x, int y);
/* List of attributes *all* particles implement */ /* List of attributes *all* particles implement */
#define PARTICLE_COMMON_ATTRS \ #define PARTICLE_COMMON_ATTRS \
{"margin", false, &conf_verify_unsigned}, \ {"margin", false, &conf_verify_unsigned}, {"left-margin", false, &conf_verify_unsigned}, \
{"left-margin", false, &conf_verify_unsigned}, \ {"right-margin", false, &conf_verify_unsigned}, {"on-click", false, &conf_verify_on_click}, \
{"right-margin", false, &conf_verify_unsigned}, \ {"font", false, &conf_verify_font}, {"font-shaping", false, &conf_verify_font_shaping}, \
{"on-click", false, &conf_verify_on_click}, \ {"foreground", false, &conf_verify_color}, {"deco", false, &conf_verify_decoration}, \
{"font", false, &conf_verify_font}, \ { \
{"font-shaping", false, &conf_verify_font_shaping}, \ NULL, false, NULL \
{"foreground", false, &conf_verify_color}, \ }
{"deco", false, &conf_verify_decoration}, \
{NULL, false, NULL}

View file

@ -1,13 +1,14 @@
#include "dynlist.h" #include "dynlist.h"
#include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#define LOG_MODULE "dynlist" #define LOG_MODULE "dynlist"
#include "../log.h" #include "../log.h"
#include "../particle.h" #include "../particle.h"
struct private { struct private
{
int left_spacing; int left_spacing;
int right_spacing; int right_spacing;
@ -77,8 +78,7 @@ dynlist_expose(const struct exposable *exposable, pixman_image_t *pix, int x, in
} }
static void static void
on_mouse(struct exposable *exposable, struct bar *bar, on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)
enum mouse_event event, enum mouse_button btn, int x, int y)
{ {
const struct private *e = exposable->private; const struct private *e = exposable->private;
@ -87,12 +87,11 @@ on_mouse(struct exposable *exposable, struct bar *bar,
return; return;
} }
int px = /*p->left_margin;*/0; int px = /*p->left_margin;*/ 0;
for (size_t i = 0; i < e->count; i++) { for (size_t i = 0; i < e->count; i++) {
if (x >= px && x < px + e->exposables[i]->width) { if (x >= px && x < px + e->exposables[i]->width) {
if (e->exposables[i]->on_mouse != NULL) { if (e->exposables[i]->on_mouse != NULL) {
e->exposables[i]->on_mouse( e->exposables[i]->on_mouse(e->exposables[i], bar, event, btn, x - px, y);
e->exposables[i], bar, event, btn, x - px, y);
} }
return; return;
} }
@ -105,8 +104,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
} }
struct exposable * struct exposable *
dynlist_exposable_new(struct exposable **exposables, size_t count, dynlist_exposable_new(struct exposable **exposables, size_t count, int left_spacing, int right_spacing)
int left_spacing, int right_spacing)
{ {
struct private *e = calloc(1, sizeof(*e)); struct private *e = calloc(1, sizeof(*e));
e->count = count; e->count = count;

View file

@ -3,5 +3,5 @@
#include <stddef.h> #include <stddef.h>
struct particle; struct particle;
struct exposable *dynlist_exposable_new( struct exposable *dynlist_exposable_new(struct exposable **exposables, size_t count, int left_spacing,
struct exposable **exposables, size_t count, int left_spacing, int right_spacing); int right_spacing);

View file

@ -1,15 +1,14 @@
#include <stdlib.h> #include <stdlib.h>
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
static int static int
begin_expose(struct exposable *exposable) begin_expose(struct exposable *exposable)
{ {
exposable->width = exposable->particle->left_margin + exposable->width = exposable->particle->left_margin + exposable->particle->right_margin;
exposable->particle->right_margin;
return exposable->width; return exposable->width;
} }

View file

@ -2,13 +2,14 @@
#define LOG_MODULE "list" #define LOG_MODULE "list"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
struct particle **particles; struct particle **particles;
size_t count; size_t count;
int left_spacing, right_spacing; int left_spacing, right_spacing;
@ -21,7 +22,6 @@ struct eprivate {
int left_spacing, right_spacing; int left_spacing, right_spacing;
}; };
static void static void
exposable_destroy(struct exposable *exposable) exposable_destroy(struct exposable *exposable)
{ {
@ -86,16 +86,12 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
} }
static void static void
on_mouse(struct exposable *exposable, struct bar *bar, on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)
enum mouse_event event, enum mouse_button btn, int x, int y)
{ {
const struct particle *p = exposable->particle; const struct particle *p = exposable->particle;
const struct eprivate *e = exposable->private; const struct eprivate *e = exposable->private;
if ((event == ON_MOUSE_MOTION && if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) {
exposable->particle->have_on_click_template) ||
exposable->on_click[btn] != NULL)
{
/* We have our own handler */ /* We have our own handler */
exposable_default_on_mouse(exposable, bar, event, btn, x, y); exposable_default_on_mouse(exposable, bar, event, btn, x, y);
return; return;
@ -105,8 +101,7 @@ on_mouse(struct exposable *exposable, struct bar *bar,
for (size_t i = 0; i < e->count; i++) { for (size_t i = 0; i < e->count; i++) {
if (x >= px && x < px + e->exposables[i]->width) { if (x >= px && x < px + e->exposables[i]->width) {
if (e->exposables[i]->on_mouse != NULL) { if (e->exposables[i]->on_mouse != NULL) {
e->exposables[i]->on_mouse( e->exposables[i]->on_mouse(e->exposables[i], bar, event, btn, x - px, y);
e->exposables[i], bar, event, btn, x - px, y);
} }
return; return;
} }
@ -157,9 +152,8 @@ particle_destroy(struct particle *particle)
} }
struct particle * struct particle *
particle_list_new(struct particle *common, particle_list_new(struct particle *common, struct particle *particles[], size_t count, int left_spacing,
struct particle *particles[], size_t count, int right_spacing)
int left_spacing, int right_spacing)
{ {
struct private *p = calloc(1, sizeof(*p)); struct private *p = calloc(1, sizeof(*p));
p->particles = malloc(count * sizeof(p->particles[0])); p->particles = malloc(count * sizeof(p->particles[0]));
@ -184,21 +178,20 @@ from_conf(const struct yml_node *node, struct particle *common)
const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing"); const struct yml_node *_left_spacing = yml_get_value(node, "left-spacing");
const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing"); const struct yml_node *_right_spacing = yml_get_value(node, "right-spacing");
int left_spacing = spacing != NULL ? yml_value_as_int(spacing) : int left_spacing = spacing != NULL ? yml_value_as_int(spacing)
_left_spacing != NULL ? yml_value_as_int(_left_spacing) : 0; : _left_spacing != NULL ? yml_value_as_int(_left_spacing)
int right_spacing = spacing != NULL ? yml_value_as_int(spacing) : : 0;
_right_spacing != NULL ? yml_value_as_int(_right_spacing) : 2; int right_spacing = spacing != NULL ? yml_value_as_int(spacing)
: _right_spacing != NULL ? yml_value_as_int(_right_spacing)
: 2;
size_t count = yml_list_length(items); size_t count = yml_list_length(items);
struct particle *parts[count]; struct particle *parts[count];
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(items); for (struct yml_list_iter it = yml_list_iter(items); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL; parts[idx]
yml_list_next(&it), idx++) = conf_to_particle(it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
{
parts[idx] = conf_to_particle(
it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
} }
return particle_list_new(common, parts, count, left_spacing, right_spacing); return particle_list_new(common, parts, count, left_spacing, right_spacing);

View file

@ -1,12 +1,12 @@
#include <assert.h>
#include <errno.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <errno.h>
#include <assert.h>
#define LOG_MODULE "map" #define LOG_MODULE "map"
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
#include "dynlist.h" #include "dynlist.h"
@ -17,14 +17,22 @@ static bool
int_condition(const long tag_value, const long cond_value, enum map_op op) int_condition(const long tag_value, const long cond_value, enum map_op op)
{ {
switch (op) { switch (op) {
case MAP_OP_EQ: return tag_value == cond_value; case MAP_OP_EQ:
case MAP_OP_NE: return tag_value != cond_value; return tag_value == cond_value;
case MAP_OP_LE: return tag_value <= cond_value; case MAP_OP_NE:
case MAP_OP_LT: return tag_value < cond_value; return tag_value != cond_value;
case MAP_OP_GE: return tag_value >= cond_value; case MAP_OP_LE:
case MAP_OP_GT: return tag_value > cond_value; return tag_value <= cond_value;
case MAP_OP_SELF: LOG_WARN("using int tag as bool"); case MAP_OP_LT:
default: return false; return tag_value < cond_value;
case MAP_OP_GE:
return tag_value >= cond_value;
case MAP_OP_GT:
return tag_value > cond_value;
case MAP_OP_SELF:
LOG_WARN("using int tag as bool");
default:
return false;
} }
} }
@ -32,34 +40,50 @@ static bool
float_condition(const double tag_value, const double cond_value, enum map_op op) float_condition(const double tag_value, const double cond_value, enum map_op op)
{ {
switch (op) { switch (op) {
case MAP_OP_EQ: return tag_value == cond_value; case MAP_OP_EQ:
case MAP_OP_NE: return tag_value != cond_value; return tag_value == cond_value;
case MAP_OP_LE: return tag_value <= cond_value; case MAP_OP_NE:
case MAP_OP_LT: return tag_value < cond_value; return tag_value != cond_value;
case MAP_OP_GE: return tag_value >= cond_value; case MAP_OP_LE:
case MAP_OP_GT: return tag_value > cond_value; return tag_value <= cond_value;
case MAP_OP_SELF: LOG_WARN("using float tag as bool"); case MAP_OP_LT:
default: return false; return tag_value < cond_value;
case MAP_OP_GE:
return tag_value >= cond_value;
case MAP_OP_GT:
return tag_value > cond_value;
case MAP_OP_SELF:
LOG_WARN("using float tag as bool");
default:
return false;
} }
} }
static bool static bool
str_condition(const char* tag_value, const char* cond_value, enum map_op op) str_condition(const char *tag_value, const char *cond_value, enum map_op op)
{ {
switch (op) { switch (op) {
case MAP_OP_EQ: return strcmp(tag_value, cond_value) == 0; case MAP_OP_EQ:
case MAP_OP_NE: return strcmp(tag_value, cond_value) != 0; return strcmp(tag_value, cond_value) == 0;
case MAP_OP_LE: return strcmp(tag_value, cond_value) <= 0; case MAP_OP_NE:
case MAP_OP_LT: return strcmp(tag_value, cond_value) < 0; return strcmp(tag_value, cond_value) != 0;
case MAP_OP_GE: return strcmp(tag_value, cond_value) >= 0; case MAP_OP_LE:
case MAP_OP_GT: return strcmp(tag_value, cond_value) > 0; return strcmp(tag_value, cond_value) <= 0;
case MAP_OP_SELF: LOG_WARN("using String tag as bool"); case MAP_OP_LT:
default: return false; return strcmp(tag_value, cond_value) < 0;
case MAP_OP_GE:
return strcmp(tag_value, cond_value) >= 0;
case MAP_OP_GT:
return strcmp(tag_value, cond_value) > 0;
case MAP_OP_SELF:
LOG_WARN("using String tag as bool");
default:
return false;
} }
} }
static bool static bool
eval_comparison(const struct map_condition* map_cond, const struct tag_set *tags) eval_comparison(const struct map_condition *map_cond, const struct tag_set *tags)
{ {
const struct tag *tag = tag_for_name(tags, map_cond->tag); const struct tag *tag = tag_for_name(tags, map_cond->tag);
if (tag == NULL) { if (tag == NULL) {
@ -108,7 +132,7 @@ eval_comparison(const struct map_condition* map_cond, const struct tag_set *tags
return false; return false;
} }
case TAG_TYPE_STRING: { case TAG_TYPE_STRING: {
const char* tag_value = tag->as_string(tag); const char *tag_value = tag->as_string(tag);
return str_condition(tag_value, map_cond->value, map_cond->op); return str_condition(tag_value, map_cond->value, map_cond->op);
} }
} }
@ -116,19 +140,17 @@ eval_comparison(const struct map_condition* map_cond, const struct tag_set *tags
} }
static bool static bool
eval_map_condition(const struct map_condition* map_cond, const struct tag_set *tags) eval_map_condition(const struct map_condition *map_cond, const struct tag_set *tags)
{ {
switch(map_cond->op) { switch (map_cond->op) {
case MAP_OP_NOT: case MAP_OP_NOT:
return !eval_map_condition(map_cond->cond1, tags); return !eval_map_condition(map_cond->cond1, tags);
case MAP_OP_AND: case MAP_OP_AND:
return eval_map_condition(map_cond->cond1, tags) && return eval_map_condition(map_cond->cond1, tags) && eval_map_condition(map_cond->cond2, tags);
eval_map_condition(map_cond->cond2, tags);
case MAP_OP_OR: case MAP_OP_OR:
return eval_map_condition(map_cond->cond1, tags) || return eval_map_condition(map_cond->cond1, tags) || eval_map_condition(map_cond->cond2, tags);
eval_map_condition(map_cond->cond2, tags);
default: default:
return eval_comparison(map_cond, tags); return eval_comparison(map_cond, tags);
@ -136,28 +158,27 @@ eval_map_condition(const struct map_condition* map_cond, const struct tag_set *t
} }
void void
free_map_condition(struct map_condition* c) free_map_condition(struct map_condition *c)
{ {
switch (c->op) switch (c->op) {
{ case MAP_OP_EQ:
case MAP_OP_EQ: case MAP_OP_NE:
case MAP_OP_NE: case MAP_OP_LE:
case MAP_OP_LE: case MAP_OP_LT:
case MAP_OP_LT: case MAP_OP_GE:
case MAP_OP_GE: case MAP_OP_GT:
case MAP_OP_GT: free(c->value);
free(c->value); /* FALLTHROUGH */
/* FALLTHROUGH */ case MAP_OP_SELF:
case MAP_OP_SELF: free(c->tag);
free(c->tag); break;
break; case MAP_OP_AND:
case MAP_OP_AND: case MAP_OP_OR:
case MAP_OP_OR: free_map_condition(c->cond2);
free_map_condition(c->cond2); /* FALLTHROUGH */
/* FALLTHROUGH */ case MAP_OP_NOT:
case MAP_OP_NOT: free_map_condition(c->cond1);
free_map_condition(c->cond1); break;
break;
} }
free(c); free(c);
} }
@ -167,7 +188,8 @@ struct particle_map {
struct particle *particle; struct particle *particle;
}; };
struct private { struct private
{
struct particle *default_particle; struct particle *default_particle;
struct particle_map *map; struct particle_map *map;
size_t count; size_t count;
@ -208,21 +230,16 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
struct eprivate *e = exposable->private; struct eprivate *e = exposable->private;
exposable_render_deco(exposable, pix, x, y, height); exposable_render_deco(exposable, pix, x, y, height);
e->exposable->expose( e->exposable->expose(e->exposable, pix, x + exposable->particle->left_margin, y, height);
e->exposable, pix, x + exposable->particle->left_margin, y, height);
} }
static void static void
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)
enum mouse_button btn, int x, int y)
{ {
const struct particle *p = exposable->particle; const struct particle *p = exposable->particle;
const struct eprivate *e = exposable->private; const struct eprivate *e = exposable->private;
if ((event == ON_MOUSE_MOTION && if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) {
exposable->particle->have_on_click_template) ||
exposable->on_click[btn] != NULL)
{
/* We have our own handler */ /* We have our own handler */
exposable_default_on_mouse(exposable, bar, event, btn, x, y); exposable_default_on_mouse(exposable, bar, event, btn, x, y);
return; return;
@ -295,8 +312,8 @@ particle_destroy(struct particle *particle)
} }
static struct particle * static struct particle *
map_new(struct particle *common, const struct particle_map particle_map[], map_new(struct particle *common, const struct particle_map particle_map[], size_t count,
size_t count, struct particle *default_particle) struct particle *default_particle)
{ {
struct private *priv = calloc(1, sizeof(*priv)); struct private *priv = calloc(1, sizeof(*priv));
priv->default_particle = default_particle; priv->default_particle = default_particle;
@ -314,22 +331,16 @@ map_new(struct particle *common, const struct particle_map particle_map[],
return common; return common;
} }
static bool static bool
verify_map_conditions(keychain_t *chain, const struct yml_node *node) verify_map_conditions(keychain_t *chain, const struct yml_node *node)
{ {
if (!yml_is_dict(node)) { if (!yml_is_dict(node)) {
LOG_ERR( LOG_ERR("%s: must be a dictionary of workspace-name: particle mappings", conf_err_prefix(chain, node));
"%s: must be a dictionary of workspace-name: particle mappings",
conf_err_prefix(chain, node));
return false; return false;
} }
bool result = true; bool result = true;
for (struct yml_dict_iter it = yml_dict_iter(node); for (struct yml_dict_iter it = yml_dict_iter(node); it.key != NULL; yml_dict_next(&it)) {
it.key != NULL;
yml_dict_next(&it))
{
const char *key = yml_value_as_string(it.key); const char *key = yml_value_as_string(it.key);
if (key == NULL) { if (key == NULL) {
LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key)); LOG_ERR("%s: key must be a string", conf_err_prefix(chain, it.key));
@ -363,17 +374,11 @@ from_conf(const struct yml_node *node, struct particle *common)
struct particle_map particle_map[yml_dict_length(conditions)]; struct particle_map particle_map[yml_dict_length(conditions)];
struct conf_inherit inherited = { struct conf_inherit inherited
.font = common->font, = {.font = common->font, .font_shaping = common->font_shaping, .foreground = common->foreground};
.font_shaping = common->font_shaping,
.foreground = common->foreground
};
size_t idx = 0; size_t idx = 0;
for (struct yml_dict_iter it = yml_dict_iter(conditions); for (struct yml_dict_iter it = yml_dict_iter(conditions); it.key != NULL; yml_dict_next(&it), idx++) {
it.key != NULL;
yml_dict_next(&it), idx++)
{
/* Note we can skip the error checking here */ /* Note we can skip the error checking here */
char *key_clone = strdup(yml_value_as_string(it.key)); char *key_clone = strdup(yml_value_as_string(it.key));
YY_BUFFER_STATE buffer = yy_scan_string(key_clone); YY_BUFFER_STATE buffer = yy_scan_string(key_clone);
@ -384,8 +389,7 @@ from_conf(const struct yml_node *node, struct particle *common)
particle_map[idx].particle = conf_to_particle(it.value, inherited); particle_map[idx].particle = conf_to_particle(it.value, inherited);
} }
struct particle *default_particle = def != NULL struct particle *default_particle = def != NULL ? conf_to_particle(def, inherited) : NULL;
? conf_to_particle(def, inherited) : NULL;
return map_new(common, particle_map, yml_dict_length(conditions), default_particle); return map_new(common, particle_map, yml_dict_length(conditions), default_particle);
} }

View file

@ -28,7 +28,7 @@ struct map_condition {
void free_map_condition(struct map_condition *c); void free_map_condition(struct map_condition *c);
typedef struct yy_buffer_state* YY_BUFFER_STATE; typedef struct yy_buffer_state *YY_BUFFER_STATE;
YY_BUFFER_STATE yy_scan_string(const char *str); YY_BUFFER_STATE yy_scan_string(const char *str);
int yyparse(); int yyparse();
void yy_delete_buffer(YY_BUFFER_STATE buffer); void yy_delete_buffer(YY_BUFFER_STATE buffer);

View file

@ -1,16 +1,17 @@
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#define LOG_MODULE "progress_bar" #define LOG_MODULE "progress_bar"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
char *tag; char *tag;
int width; int width;
@ -74,8 +75,7 @@ begin_expose(struct exposable *exposable)
/* Margins */ /* Margins */
if (have_at_least_one) { if (have_at_least_one) {
exposable->width += exposable->particle->left_margin + exposable->width += exposable->particle->left_margin + exposable->particle->right_margin;
exposable->particle->right_margin;
} else } else
assert(exposable->width == 0); assert(exposable->width == 0);
@ -97,8 +97,7 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
} }
static void static void
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)
enum mouse_button btn, int x, int y)
{ {
const struct particle *p = exposable->particle; const struct particle *p = exposable->particle;
const struct eprivate *e = exposable->private; const struct eprivate *e = exposable->private;
@ -161,18 +160,14 @@ on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event,
original[i] = exposable->on_click[i]; original[i] = exposable->on_click[i];
if (event == ON_MOUSE_CLICK) { if (event == ON_MOUSE_CLICK) {
long where = clickable_width > 0 long where = clickable_width > 0 ? 100 * (x - x_offset) / clickable_width : 0;
? 100 * (x - x_offset) / clickable_width
: 0;
struct tag_set tags = { struct tag_set tags = {
.tags = (struct tag *[]){tag_new_int(NULL, "where", where)}, .tags = (struct tag *[]){tag_new_int(NULL, "where", where)},
.count = 1, .count = 1,
}; };
tags_expand_templates( tags_expand_templates(exposable->on_click, (const char **)exposable->on_click, MOUSE_BTN_COUNT, &tags);
exposable->on_click, (const char **)exposable->on_click,
MOUSE_BTN_COUNT, &tags);
tag_set_destroy(&tags); tag_set_destroy(&tags);
} }
@ -198,19 +193,17 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
long min = tag != NULL ? tag->min(tag) : 0; long min = tag != NULL ? tag->min(tag) : 0;
long max = tag != NULL ? tag->max(tag) : 0; long max = tag != NULL ? tag->max(tag) : 0;
LOG_DBG("%s: value=%ld, min=%ld, max=%ld", LOG_DBG("%s: value=%ld, min=%ld, max=%ld", tag != NULL ? tag->name(tag) : "<no tag>", value, min, max);
tag != NULL ? tag->name(tag) : "<no tag>", value, min, max);
long fill_count = max == min ? 0 : p->width * value / (max - min); long fill_count = max == min ? 0 : p->width * value / (max - min);
long empty_count = p->width - fill_count; long empty_count = p->width - fill_count;
struct eprivate *epriv = calloc(1, sizeof(*epriv)); struct eprivate *epriv = calloc(1, sizeof(*epriv));
epriv->count = ( epriv->count = (1 + /* Start marker */
1 + /* Start marker */ fill_count + /* Before current position */
fill_count + /* Before current position */ 1 + /* Current position indicator */
1 + /* Current position indicator */ empty_count + /* After current position */
empty_count + /* After current position */ 1); /* End marker */
1); /* End marker */
epriv->exposables = malloc(epriv->count * sizeof(epriv->exposables[0])); epriv->exposables = malloc(epriv->count * sizeof(epriv->exposables[0]));
@ -259,8 +252,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
LOG_DBG("tag: %s, value: %ld, " LOG_DBG("tag: %s, value: %ld, "
"units-per-segment: %f, units-filled: %f, units-til-next: %f", "units-per-segment: %f, units-filled: %f, units-til-next: %f",
tag->name(tag), value, tag->name(tag), value, units_per_segment, units_filled, units_til_next_segment);
units_per_segment, units_filled, units_til_next_segment);
#endif #endif
@ -271,10 +263,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
} }
static struct particle * static struct particle *
progress_bar_new(struct particle *common, const char *tag, int width, progress_bar_new(struct particle *common, const char *tag, int width, struct particle *start_marker,
struct particle *start_marker, struct particle *end_marker, struct particle *end_marker, struct particle *fill, struct particle *empty, struct particle *indicator)
struct particle *fill, struct particle *empty,
struct particle *indicator)
{ {
struct private *priv = calloc(1, sizeof(*priv)); struct private *priv = calloc(1, sizeof(*priv));
priv->tag = strdup(tag); priv->tag = strdup(tag);
@ -308,15 +298,10 @@ from_conf(const struct yml_node *node, struct particle *common)
.foreground = common->foreground, .foreground = common->foreground,
}; };
return progress_bar_new( return progress_bar_new(common, yml_value_as_string(tag), yml_value_as_int(length),
common, conf_to_particle(start, inherited), conf_to_particle(end, inherited),
yml_value_as_string(tag), conf_to_particle(fill, inherited), conf_to_particle(empty, inherited),
yml_value_as_int(length), conf_to_particle(indicator, inherited));
conf_to_particle(start, inherited),
conf_to_particle(end, inherited),
conf_to_particle(fill, inherited),
conf_to_particle(empty, inherited),
conf_to_particle(indicator, inherited));
} }
static bool static bool

View file

@ -1,18 +1,19 @@
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#define LOG_MODULE "ramp" #define LOG_MODULE "ramp"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
struct private { struct private
{
char *tag; char *tag;
bool use_custom_min; bool use_custom_min;
long min; long min;
@ -57,21 +58,16 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
struct eprivate *e = exposable->private; struct eprivate *e = exposable->private;
exposable_render_deco(exposable, pix, x, y, height); exposable_render_deco(exposable, pix, x, y, height);
e->exposable->expose( e->exposable->expose(e->exposable, pix, x + exposable->particle->left_margin, y, height);
e->exposable, pix, x + exposable->particle->left_margin, y, height);
} }
static void static void
on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, on_mouse(struct exposable *exposable, struct bar *bar, enum mouse_event event, enum mouse_button btn, int x, int y)
enum mouse_button btn, int x, int y)
{ {
const struct particle *p = exposable->particle; const struct particle *p = exposable->particle;
const struct eprivate *e = exposable->private; const struct eprivate *e = exposable->private;
if ((event == ON_MOUSE_MOTION && if ((event == ON_MOUSE_MOTION && exposable->particle->have_on_click_template) || exposable->on_click[btn] != NULL) {
exposable->particle->have_on_click_template) ||
exposable->on_click[btn] != NULL)
{
/* We have our own handler */ /* We have our own handler */
exposable_default_on_mouse(exposable, bar, event, btn, x, y); exposable_default_on_mouse(exposable, bar, event, btn, x, y);
return; return;
@ -118,22 +114,22 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
max = p->use_custom_max ? p->max : max; max = p->use_custom_max ? p->max : max;
if (min > max) { if (min > max) {
LOG_WARN( LOG_WARN("tag's minimum value is greater than its maximum: "
"tag's minimum value is greater than its maximum: " "tag=\"%s\", min=%ld, max=%ld",
"tag=\"%s\", min=%ld, max=%ld", p->tag, min, max); p->tag, min, max);
min = max; min = max;
} }
if (value < min) { if (value < min) {
LOG_WARN( LOG_WARN("tag's value is less than its minimum value: "
"tag's value is less than its minimum value: " "tag=\"%s\", min=%ld, value=%ld",
"tag=\"%s\", min=%ld, value=%ld", p->tag, min, value); p->tag, min, value);
value = min; value = min;
} }
if (value > max) { if (value > max) {
LOG_WARN( LOG_WARN("tag's value is greater than its maximum value: "
"tag's value is greater than its maximum value: " "tag=\"%s\", max=%ld, value=%ld",
"tag=\"%s\", max=%ld, value=%ld", p->tag, max, value); p->tag, max, value);
value = max; value = max;
} }
@ -168,10 +164,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
} }
static struct particle * static struct particle *
ramp_new(struct particle *common, const char *tag, ramp_new(struct particle *common, const char *tag, struct particle *particles[], size_t count, bool use_custom_min,
struct particle *particles[], size_t count, long min, bool use_custom_max, long max)
bool use_custom_min, long min,
bool use_custom_max, long max)
{ {
struct private *priv = calloc(1, sizeof(*priv)); struct private *priv = calloc(1, sizeof(*priv));
@ -204,19 +198,15 @@ from_conf(const struct yml_node *node, struct particle *common)
struct particle *parts[count]; struct particle *parts[count];
size_t idx = 0; size_t idx = 0;
for (struct yml_list_iter it = yml_list_iter(items); for (struct yml_list_iter it = yml_list_iter(items); it.node != NULL; yml_list_next(&it), idx++) {
it.node != NULL; parts[idx]
yml_list_next(&it), idx++) = conf_to_particle(it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
{
parts[idx] = conf_to_particle(
it.node, (struct conf_inherit){common->font, common->font_shaping, common->foreground});
} }
long min_v = min != NULL ? yml_value_as_int(min) : 0; long min_v = min != NULL ? yml_value_as_int(min) : 0;
long max_v = max != NULL ? yml_value_as_int(max) : 0; long max_v = max != NULL ? yml_value_as_int(max) : 0;
return ramp_new(common, yml_value_as_string(tag), parts, count, min != NULL, return ramp_new(common, yml_value_as_string(tag), parts, count, min != NULL, min_v, max != NULL, max_v);
min_v, max != NULL, max_v);
} }
static bool static bool

View file

@ -1,13 +1,13 @@
#include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#define LOG_MODULE "string" #define LOG_MODULE "string"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "../log.h"
#include "../char32.h" #include "../char32.h"
#include "../config.h"
#include "../config-verify.h" #include "../config-verify.h"
#include "../config.h"
#include "../log.h"
#include "../particle.h" #include "../particle.h"
#include "../plugin.h" #include "../plugin.h"
@ -18,7 +18,8 @@ struct text_run_cache {
bool in_use; bool in_use;
}; };
struct private { struct private
{
char *text; char *text;
size_t max_len; size_t max_len;
@ -51,9 +52,7 @@ begin_expose(struct exposable *exposable)
struct eprivate *e = exposable->private; struct eprivate *e = exposable->private;
struct private *p = exposable->particle->private; struct private *p = exposable->particle->private;
exposable->width = exposable->width = exposable->particle->left_margin + exposable->particle->right_margin;
exposable->particle->left_margin +
exposable->particle->right_margin;
if (e->cache_idx >= 0) { if (e->cache_idx >= 0) {
exposable->width += p->cache[e->cache_idx].width; exposable->width += p->cache[e->cache_idx].width;
@ -97,9 +96,8 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
* any real facts, but works very well with e.g. the "Awesome 6" * any real facts, but works very well with e.g. the "Awesome 6"
* font family. * font family.
*/ */
const double baseline = (double)y + const double baseline
(double)(height + font->ascent + font->descent) / 2.0 - = (double)y + (double)(height + font->ascent + font->descent) / 2.0 - (font->descent > 0 ? font->descent : 0);
(font->descent > 0 ? font->descent : 0);
x += exposable->particle->left_margin; x += exposable->particle->left_margin;
@ -112,17 +110,13 @@ expose(const struct exposable *exposable, pixman_image_t *pix, int x, int y, int
if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) { if (pixman_image_get_format(glyph->pix) == PIXMAN_a8r8g8b8) {
/* Glyph surface is a pre-rendered image (typically a color emoji...) */ /* Glyph surface is a pre-rendered image (typically a color emoji...) */
pixman_image_composite32( pixman_image_composite32(PIXMAN_OP_OVER, glyph->pix, NULL, pix, 0, 0, 0, 0, x + glyph->x,
PIXMAN_OP_OVER, glyph->pix, NULL, pix, 0, 0, 0, 0, baseline - glyph->y, glyph->width, glyph->height);
x + glyph->x, baseline - glyph->y,
glyph->width, glyph->height);
} else { } else {
/* Glyph surface is an alpha mask */ /* Glyph surface is an alpha mask */
pixman_image_t *src = pixman_image_create_solid_fill(&exposable->particle->foreground); pixman_image_t *src = pixman_image_create_solid_fill(&exposable->particle->foreground);
pixman_image_composite32( pixman_image_composite32(PIXMAN_OP_OVER, src, glyph->pix, pix, 0, 0, 0, 0, x + glyph->x,
PIXMAN_OP_OVER, src, glyph->pix, pix, 0, 0, 0, 0, baseline - glyph->y, glyph->width, glyph->height);
x + glyph->x, baseline - glyph->y,
glyph->width, glyph->height);
pixman_image_unref(src); pixman_image_unref(src);
} }
@ -188,11 +182,8 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
e->kern_x = calloc(chars, sizeof(e->kern_x[0])); e->kern_x = calloc(chars, sizeof(e->kern_x[0]));
if (particle->font_shaping == FONT_SHAPE_FULL && if (particle->font_shaping == FONT_SHAPE_FULL && fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) {
fcft_capabilities() & FCFT_CAPABILITY_TEXT_RUN_SHAPING) struct fcft_text_run *run = fcft_rasterize_text_run_utf32(font, chars, wtext, FCFT_SUBPIXEL_NONE);
{
struct fcft_text_run *run = fcft_rasterize_text_run_utf32(
font, chars, wtext, FCFT_SUBPIXEL_NONE);
if (run != NULL) { if (run != NULL) {
int w = 0; int w = 0;
@ -210,8 +201,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
if (cache_idx < 0) { if (cache_idx < 0) {
size_t new_size = p->cache_size + 1; size_t new_size = p->cache_size + 1;
struct text_run_cache *new_cache = realloc( struct text_run_cache *new_cache = realloc(p->cache, new_size * sizeof(new_cache[0]));
p->cache, new_size * sizeof(new_cache[0]));
p->cache_size = new_size; p->cache_size = new_size;
p->cache = new_cache; p->cache = new_cache;
@ -235,8 +225,7 @@ instantiate(const struct particle *particle, const struct tag_set *tags)
/* Convert text to glyph masks/images. */ /* Convert text to glyph masks/images. */
for (size_t i = 0; i < chars; i++) { for (size_t i = 0; i < chars; i++) {
const struct fcft_glyph *glyph = fcft_rasterize_char_utf32( const struct fcft_glyph *glyph = fcft_rasterize_char_utf32(font, wtext[i], FCFT_SUBPIXEL_NONE);
font, wtext[i], FCFT_SUBPIXEL_NONE);
if (glyph == NULL) if (glyph == NULL)
continue; continue;
@ -297,10 +286,7 @@ from_conf(const struct yml_node *node, struct particle *common)
const struct yml_node *text = yml_get_value(node, "text"); const struct yml_node *text = yml_get_value(node, "text");
const struct yml_node *max = yml_get_value(node, "max"); const struct yml_node *max = yml_get_value(node, "max");
return string_new( return string_new(common, yml_value_as_string(text), max != NULL ? yml_value_as_int(max) : 0);
common,
yml_value_as_string(text),
max != NULL ? yml_value_as_int(max) : 0);
} }
static bool static bool

132
plugin.c
View file

@ -1,99 +1,94 @@
#include "plugin.h" #include "plugin.h"
#include <string.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <string.h>
#include <tllist.h> #include <tllist.h>
#define LOG_MODULE "plugin" #define LOG_MODULE "plugin"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 0
#include "log.h"
#include "config.h" #include "config.h"
#include "log.h"
#if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) #if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
#define EXTERN_MODULE(plug_name) \ #define EXTERN_MODULE(plug_name) \
extern const struct module_iface module_##plug_name##_iface; \ extern const struct module_iface module_##plug_name##_iface; \
extern bool plug_name##_verify_conf( \ extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \
keychain_t *chain, const struct yml_node *node); \ extern struct module *plug_name##_from_conf(const struct yml_node *node, struct conf_inherit inherited);
extern struct module *plug_name##_from_conf( \
const struct yml_node *node, struct conf_inherit inherited);
#define EXTERN_PARTICLE(plug_name) \ #define EXTERN_PARTICLE(plug_name) \
extern const struct particle_iface particle_##plug_name##_iface; \ extern const struct particle_iface particle_##plug_name##_iface; \
extern bool plug_name##_verify_conf( \ extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \
keychain_t *chain, const struct yml_node *node); \ extern struct particle *plug_name##_from_conf(const struct yml_node *node, struct particle *common);
extern struct particle *plug_name##_from_conf( \
const struct yml_node *node, struct particle *common);
#define EXTERN_DECORATION(plug_name) \ #define EXTERN_DECORATION(plug_name) \
extern const struct deco_iface deco_##plug_name##_iface; \ extern const struct deco_iface deco_##plug_name##_iface; \
extern bool plug_name##_verify_conf( \ extern bool plug_name##_verify_conf(keychain_t *chain, const struct yml_node *node); \
keychain_t *chain, const struct yml_node *node); \
extern struct deco *plug_name##_from_conf(const struct yml_node *node); extern struct deco *plug_name##_from_conf(const struct yml_node *node);
#if defined(HAVE_PLUGIN_alsa) #if defined(HAVE_PLUGIN_alsa)
EXTERN_MODULE(alsa); EXTERN_MODULE(alsa);
#endif #endif
#if defined(HAVE_PLUGIN_backlight) #if defined(HAVE_PLUGIN_backlight)
EXTERN_MODULE(backlight); EXTERN_MODULE(backlight);
#endif #endif
#if defined(HAVE_PLUGIN_battery) #if defined(HAVE_PLUGIN_battery)
EXTERN_MODULE(battery); EXTERN_MODULE(battery);
#endif #endif
#if defined(HAVE_PLUGIN_clock) #if defined(HAVE_PLUGIN_clock)
EXTERN_MODULE(clock); EXTERN_MODULE(clock);
#endif #endif
#if defined(HAVE_PLUGIN_cpu) #if defined(HAVE_PLUGIN_cpu)
EXTERN_MODULE(cpu); EXTERN_MODULE(cpu);
#endif #endif
#if defined(HAVE_PLUGIN_disk_io) #if defined(HAVE_PLUGIN_disk_io)
EXTERN_MODULE(disk_io); EXTERN_MODULE(disk_io);
#endif #endif
#if defined(HAVE_PLUGIN_dwl) #if defined(HAVE_PLUGIN_dwl)
EXTERN_MODULE(dwl); EXTERN_MODULE(dwl);
#endif #endif
#if defined(HAVE_PLUGIN_foreign_toplevel) #if defined(HAVE_PLUGIN_foreign_toplevel)
EXTERN_MODULE(foreign_toplevel); EXTERN_MODULE(foreign_toplevel);
#endif #endif
#if defined(HAVE_PLUGIN_mem) #if defined(HAVE_PLUGIN_mem)
EXTERN_MODULE(mem); EXTERN_MODULE(mem);
#endif #endif
#if defined(HAVE_PLUGIN_mpd) #if defined(HAVE_PLUGIN_mpd)
EXTERN_MODULE(mpd); EXTERN_MODULE(mpd);
#endif #endif
#if defined(HAVE_PLUGIN_i3) #if defined(HAVE_PLUGIN_i3)
EXTERN_MODULE(i3); EXTERN_MODULE(i3);
#endif #endif
#if defined(HAVE_PLUGIN_label) #if defined(HAVE_PLUGIN_label)
EXTERN_MODULE(label); EXTERN_MODULE(label);
#endif #endif
#if defined(HAVE_PLUGIN_network) #if defined(HAVE_PLUGIN_network)
EXTERN_MODULE(network); EXTERN_MODULE(network);
#endif #endif
#if defined(HAVE_PLUGIN_pipewire) #if defined(HAVE_PLUGIN_pipewire)
EXTERN_MODULE(pipewire); EXTERN_MODULE(pipewire);
#endif #endif
#if defined(HAVE_PLUGIN_pulse) #if defined(HAVE_PLUGIN_pulse)
EXTERN_MODULE(pulse); EXTERN_MODULE(pulse);
#endif #endif
#if defined(HAVE_PLUGIN_removables) #if defined(HAVE_PLUGIN_removables)
EXTERN_MODULE(removables); EXTERN_MODULE(removables);
#endif #endif
#if defined(HAVE_PLUGIN_river) #if defined(HAVE_PLUGIN_river)
EXTERN_MODULE(river); EXTERN_MODULE(river);
#endif #endif
#if defined(HAVE_PLUGIN_script) #if defined(HAVE_PLUGIN_script)
EXTERN_MODULE(script); EXTERN_MODULE(script);
#endif #endif
#if defined(HAVE_PLUGIN_sway_xkb) #if defined(HAVE_PLUGIN_sway_xkb)
EXTERN_MODULE(sway_xkb); EXTERN_MODULE(sway_xkb);
#endif #endif
#if defined(HAVE_PLUGIN_xkb) #if defined(HAVE_PLUGIN_xkb)
EXTERN_MODULE(xkb); EXTERN_MODULE(xkb);
#endif #endif
#if defined(HAVE_PLUGIN_xwindow) #if defined(HAVE_PLUGIN_xwindow)
EXTERN_MODULE(xwindow); EXTERN_MODULE(xwindow);
#endif #endif
EXTERN_PARTICLE(empty); EXTERN_PARTICLE(empty);
@ -121,42 +116,45 @@ static const char *
type2str(enum plugin_type type) type2str(enum plugin_type type)
{ {
switch (type) { switch (type) {
case PLUGIN_MODULE: return "module"; case PLUGIN_MODULE:
case PLUGIN_PARTICLE: return "particle"; return "module";
case PLUGIN_DECORATION: return "decoration"; case PLUGIN_PARTICLE:
return "particle";
case PLUGIN_DECORATION:
return "decoration";
} }
assert(false && "invalid type"); assert(false && "invalid type");
return ""; return "";
} }
static void __attribute__((constructor)) static void __attribute__((constructor)) init(void)
init(void)
{ {
#if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES) #if !defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
#define REGISTER_CORE_PLUGIN(plug_name, func_prefix, plug_type) \ #define REGISTER_CORE_PLUGIN(plug_name, func_prefix, plug_type) \
do { \ do { \
tll_push_back( \ tll_push_back(plugins, ((struct plugin){ \
plugins, \ .name = strdup(#plug_name), \
((struct plugin){ \ .type = (plug_type), \
.name = strdup(#plug_name), \ .lib = RTLD_DEFAULT, \
.type = (plug_type), \ })); \
.lib = RTLD_DEFAULT, \
})); \
} while (0) } while (0)
#define REGISTER_CORE_MODULE(plug_name, func_prefix) do { \ #define REGISTER_CORE_MODULE(plug_name, func_prefix) \
REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_MODULE); \ do { \
tll_back(plugins).module = &module_##func_prefix##_iface; \ REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_MODULE); \
tll_back(plugins).module = &module_##func_prefix##_iface; \
} while (0) } while (0)
#define REGISTER_CORE_PARTICLE(plug_name, func_prefix) do { \ #define REGISTER_CORE_PARTICLE(plug_name, func_prefix) \
REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_PARTICLE); \ do { \
tll_back(plugins).particle = &particle_##func_prefix##_iface; \ REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_PARTICLE); \
tll_back(plugins).particle = &particle_##func_prefix##_iface; \
} while (0) } while (0)
#define REGISTER_CORE_DECORATION(plug_name, func_prefix) do { \ #define REGISTER_CORE_DECORATION(plug_name, func_prefix) \
REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_DECORATION); \ do { \
tll_back(plugins).decoration = &deco_##func_prefix##_iface; \ REGISTER_CORE_PLUGIN(plug_name, func_prefix, PLUGIN_DECORATION); \
tll_back(plugins).decoration = &deco_##func_prefix##_iface; \
} while (0) } while (0)
#if defined(HAVE_PLUGIN_alsa) #if defined(HAVE_PLUGIN_alsa)
@ -258,16 +256,13 @@ free_plugin(struct plugin plug)
free(plug.name); free(plug.name);
} }
static void __attribute__((destructor)) static void __attribute__((destructor)) fini(void) { tll_free_and_free(plugins, free_plugin); }
fini(void)
{
tll_free_and_free(plugins, free_plugin);
}
const struct plugin * const struct plugin *
plugin_load(const char *name, enum plugin_type type) plugin_load(const char *name, enum plugin_type type)
{ {
tll_foreach(plugins, plug) { tll_foreach(plugins, plug)
{
if (plug->item.type == type && strcmp(plug->item.name, name) == 0) { if (plug->item.type == type && strcmp(plug->item.name, name) == 0) {
LOG_DBG("%s: %s already loaded: %p", type2str(type), name, plug->item.lib); LOG_DBG("%s: %s already loaded: %p", type2str(type), name, plug->item.lib);
assert(plug->item.dummy != NULL); assert(plug->item.dummy != NULL);
@ -275,7 +270,6 @@ plugin_load(const char *name, enum plugin_type type)
} }
} }
char path[128]; char path[128];
snprintf(path, sizeof(path), "%s_%s.so", type2str(type), name); snprintf(path, sizeof(path), "%s_%s.so", type2str(type), name);

View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "config.h"
#include "config-verify.h" #include "config-verify.h"
#include "config.h"
#include "module.h" #include "module.h"
#include "particle.h" #include "particle.h"
@ -9,14 +9,12 @@ typedef bool (*verify_func_t)(keychain_t *chain, const struct yml_node *node);
struct module_iface { struct module_iface {
verify_func_t verify_conf; verify_func_t verify_conf;
struct module *(*from_conf)( struct module *(*from_conf)(const struct yml_node *node, struct conf_inherit inherited);
const struct yml_node *node, struct conf_inherit inherited);
}; };
struct particle_iface { struct particle_iface {
verify_func_t verify_conf; verify_func_t verify_conf;
struct particle *(*from_conf)( struct particle *(*from_conf)(const struct yml_node *node, struct particle *common);
const struct yml_node *node, struct particle *common);
}; };
struct deco_iface { struct deco_iface {

118
tag.c
View file

@ -1,19 +1,20 @@
#include "tag.h" #include "tag.h"
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h> #include <assert.h>
#include<errno.h> #include <ctype.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LOG_MODULE "tag" #define LOG_MODULE "tag"
#define LOG_ENABLE_DBG 1 #define LOG_ENABLE_DBG 1
#include "log.h" #include "log.h"
#include "module.h" #include "module.h"
struct private { struct private
{
char *name; char *name;
union { union {
struct { struct {
@ -156,8 +157,8 @@ int_refresh_in(const struct tag *tag, long units)
if (tag->owner == NULL || tag->owner->refresh_in == NULL) if (tag->owner == NULL || tag->owner->refresh_in == NULL)
return false; return false;
assert(priv->value_as_int.realtime_unit == TAG_REALTIME_SECS || assert(priv->value_as_int.realtime_unit == TAG_REALTIME_SECS
priv->value_as_int.realtime_unit == TAG_REALTIME_MSECS); || priv->value_as_int.realtime_unit == TAG_REALTIME_MSECS);
long milli_seconds = units; long milli_seconds = units;
if (priv->value_as_int.realtime_unit == TAG_REALTIME_SECS) if (priv->value_as_int.realtime_unit == TAG_REALTIME_SECS)
@ -269,15 +270,14 @@ tag_new_int(struct module *owner, const char *name, long value)
} }
struct tag * struct tag *
tag_new_int_range(struct module *owner, const char *name, long value, tag_new_int_range(struct module *owner, const char *name, long value, long min, long max)
long min, long max)
{ {
return tag_new_int_realtime(owner, name, value, min, max, TAG_REALTIME_NONE); return tag_new_int_realtime(owner, name, value, min, max, TAG_REALTIME_NONE);
} }
struct tag * struct tag *
tag_new_int_realtime(struct module *owner, const char *name, long value, tag_new_int_realtime(struct module *owner, const char *name, long value, long min, long max,
long min, long max, enum tag_realtime_unit unit) enum tag_realtime_unit unit)
{ {
struct private *priv = malloc(sizeof(*priv)); struct private *priv = malloc(sizeof(*priv));
priv->name = strdup(name); priv->name = strdup(name);
@ -414,7 +414,7 @@ sbuf_append_at_most(struct sbuf *s1, const char *s2, size_t n)
s1->size = 2 * required_size; s1->size = 2 * required_size;
s1->s = realloc(s1->s, s1->size); s1->s = realloc(s1->s, s1->size);
//s1->s[s1->len] = '\0'; // s1->s[s1->len] = '\0';
} }
memcpy(&s1->s[s1->len], s2, n); memcpy(&s1->s[s1->len], s2, n);
@ -516,14 +516,16 @@ tags_expand_template(const char *template, const struct tag_set *tags)
FMT_KIBYTE, FMT_KIBYTE,
FMT_MIBYTE, FMT_MIBYTE,
FMT_GIBYTE, FMT_GIBYTE,
} format = FMT_DEFAULT; } format
= FMT_DEFAULT;
enum { enum {
VALUE_VALUE, VALUE_VALUE,
VALUE_MIN, VALUE_MIN,
VALUE_MAX, VALUE_MAX,
VALUE_UNIT, VALUE_UNIT,
} kind = VALUE_VALUE; } kind
= VALUE_VALUE;
int digits = 0; int digits = 0;
int decimals = 2; int decimals = 2;
@ -567,22 +569,17 @@ tags_expand_template(const char *template, const struct tag_set *tags)
if (digits_str[0] != '\0') { // guards against i.e. "{tag:.3}" if (digits_str[0] != '\0') { // guards against i.e. "{tag:.3}"
if (!is_number(digits_str, &digits)) { if (!is_number(digits_str, &digits)) {
LOG_WARN( LOG_WARN("tag `%s`: invalid field width formatter. Ignoring...", tag_name);
"tag `%s`: invalid field width formatter. Ignoring...",
tag_name);
} }
} }
if (decimals_str[0] != '\0') { // guards against i.e. "{tag:3.}" if (decimals_str[0] != '\0') { // guards against i.e. "{tag:3.}"
if (!is_number(decimals_str, &decimals)) { if (!is_number(decimals_str, &decimals)) {
LOG_WARN( LOG_WARN("tag `%s`: invalid decimals formatter. Ignoring...", tag_name);
"tag `%s`: invalid decimals formatter. Ignoring...",
tag_name);
} }
} }
zero_pad = digits_str[0] == '0'; zero_pad = digits_str[0] == '0';
} } else
else
LOG_WARN("invalid tag formatter: %s", tag_args[i]); LOG_WARN("invalid tag formatter: %s", tag_args[i]);
} }
@ -593,7 +590,7 @@ tags_expand_template(const char *template, const struct tag_set *tags)
case FMT_DEFAULT: { case FMT_DEFAULT: {
switch (tag->type(tag)) { switch (tag->type(tag)) {
case TAG_TYPE_FLOAT: { case TAG_TYPE_FLOAT: {
const char* fmt = zero_pad ? "%0*.*f" : "%*.*f"; const char *fmt = zero_pad ? "%0*.*f" : "%*.*f";
char str[24]; char str[24];
snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag)); snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag));
sbuf_append(&formatted, str); sbuf_append(&formatted, str);
@ -601,7 +598,7 @@ tags_expand_template(const char *template, const struct tag_set *tags)
} }
case TAG_TYPE_INT: { case TAG_TYPE_INT: {
const char* fmt = zero_pad ? "%0*ld" : "%*ld"; const char *fmt = zero_pad ? "%0*ld" : "%*ld";
char str[24]; char str[24];
snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag)); snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag));
sbuf_append(&formatted, str); sbuf_append(&formatted, str);
@ -618,9 +615,7 @@ tags_expand_template(const char *template, const struct tag_set *tags)
case FMT_HEX: case FMT_HEX:
case FMT_OCT: { case FMT_OCT: {
const char* fmt = format == FMT_HEX ? const char *fmt = format == FMT_HEX ? zero_pad ? "%0*lx" : "%*lx" : zero_pad ? "%0*lo" : "%*lo";
zero_pad ? "%0*lx" : "%*lx" :
zero_pad ? "%0*lo" : "%*lo";
char str[24]; char str[24];
snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag)); snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag));
sbuf_append(&formatted, str); sbuf_append(&formatted, str);
@ -632,7 +627,7 @@ tags_expand_template(const char *template, const struct tag_set *tags)
const long max = tag->max(tag); const long max = tag->max(tag);
const long cur = tag->as_int(tag); const long cur = tag->as_int(tag);
const char* fmt = zero_pad ? "%0*lu" : "%*lu"; const char *fmt = zero_pad ? "%0*lu" : "%*lu";
char str[4]; char str[4];
snprintf(str, sizeof(str), fmt, digits, (cur - min) * 100 / (max - min)); snprintf(str, sizeof(str), fmt, digits, (cur - min) * 100 / (max - min));
sbuf_append(&formatted, str); sbuf_append(&formatted, str);
@ -645,21 +640,20 @@ tags_expand_template(const char *template, const struct tag_set *tags)
case FMT_KIBYTE: case FMT_KIBYTE:
case FMT_MIBYTE: case FMT_MIBYTE:
case FMT_GIBYTE: { case FMT_GIBYTE: {
const long divider = const long divider = format == FMT_KBYTE ? 1000
format == FMT_KBYTE ? 1000 : : format == FMT_MBYTE ? 1000 * 1000
format == FMT_MBYTE ? 1000 * 1000 : : format == FMT_GBYTE ? 1000 * 1000 * 1000
format == FMT_GBYTE ? 1000 * 1000 * 1000 : : format == FMT_KIBYTE ? 1024
format == FMT_KIBYTE ? 1024 : : format == FMT_MIBYTE ? 1024 * 1024
format == FMT_MIBYTE ? 1024 * 1024 : : format == FMT_GIBYTE ? 1024 * 1024 * 1024
format == FMT_GIBYTE ? 1024 * 1024 * 1024 : : 1;
1;
char str[24]; char str[24];
if (tag->type(tag) == TAG_TYPE_FLOAT) { if (tag->type(tag) == TAG_TYPE_FLOAT) {
const char* fmt = zero_pad ? "%0*.*f" : "%*.*f"; const char *fmt = zero_pad ? "%0*.*f" : "%*.*f";
snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag) / (double)divider); snprintf(str, sizeof(str), fmt, digits, decimals, tag->as_float(tag) / (double)divider);
} else { } else {
const char* fmt = zero_pad ? "%0*lu" : "%*lu"; const char *fmt = zero_pad ? "%0*lu" : "%*lu";
snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag) / divider); snprintf(str, sizeof(str), fmt, digits, tag->as_int(tag) / divider);
} }
sbuf_append(&formatted, str); sbuf_append(&formatted, str);
@ -676,9 +670,15 @@ tags_expand_template(const char *template, const struct tag_set *tags)
const char *fmt = NULL; const char *fmt = NULL;
switch (format) { switch (format) {
case FMT_DEFAULT: fmt = zero_pad ? "%0*ld" : "%*ld"; break; case FMT_DEFAULT:
case FMT_HEX: fmt = zero_pad ? "%0*lx" : "%*lx"; break; fmt = zero_pad ? "%0*ld" : "%*ld";
case FMT_OCT: fmt = zero_pad ? "%0*lo" : "%*lo"; break; break;
case FMT_HEX:
fmt = zero_pad ? "%0*lx" : "%*lx";
break;
case FMT_OCT:
fmt = zero_pad ? "%0*lo" : "%*lo";
break;
case FMT_PERCENT: case FMT_PERCENT:
value = (value - min) * 100 / (max - min); value = (value - min) * 100 / (max - min);
fmt = zero_pad ? "%0*lu" : "%*lu"; fmt = zero_pad ? "%0*lu" : "%*lu";
@ -690,14 +690,13 @@ tags_expand_template(const char *template, const struct tag_set *tags)
case FMT_KIBYTE: case FMT_KIBYTE:
case FMT_MIBYTE: case FMT_MIBYTE:
case FMT_GIBYTE: { case FMT_GIBYTE: {
const long divider = const long divider = format == FMT_KBYTE ? 1024
format == FMT_KBYTE ? 1024 : : format == FMT_MBYTE ? 1024 * 1024
format == FMT_MBYTE ? 1024 * 1024 : : format == FMT_GBYTE ? 1024 * 1024 * 1024
format == FMT_GBYTE ? 1024 * 1024 * 1024 : : format == FMT_KIBYTE ? 1000
format == FMT_KIBYTE ? 1000 : : format == FMT_MIBYTE ? 1000 * 1000
format == FMT_MIBYTE ? 1000 * 1000 : : format == FMT_GIBYTE ? 1000 * 1000 * 1000
format == FMT_GIBYTE ? 1000 * 1000 * 1000 : : 1;
1;
value /= divider; value /= divider;
fmt = zero_pad ? "%0*lu" : "%*lu"; fmt = zero_pad ? "%0*lu" : "%*lu";
break; break;
@ -716,9 +715,15 @@ tags_expand_template(const char *template, const struct tag_set *tags)
const char *value = NULL; const char *value = NULL;
switch (tag->realtime(tag)) { switch (tag->realtime(tag)) {
case TAG_REALTIME_NONE: value = ""; break; case TAG_REALTIME_NONE:
case TAG_REALTIME_SECS: value = "s"; break; value = "";
case TAG_REALTIME_MSECS: value = "ms"; break; break;
case TAG_REALTIME_SECS:
value = "s";
break;
case TAG_REALTIME_MSECS:
value = "ms";
break;
} }
sbuf_append(&formatted, value); sbuf_append(&formatted, value);
@ -734,8 +739,7 @@ tags_expand_template(const char *template, const struct tag_set *tags)
} }
void void
tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, const struct tag_set *tags)
const struct tag_set *tags)
{ {
for (size_t i = 0; i < nmemb; i++) for (size_t i = 0; i < nmemb; i++)
expanded[i] = tags_expand_template(template[i], tags); expanded[i] = tags_expand_template(template[i], tags);

17
tag.h
View file

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
enum tag_type { enum tag_type {
TAG_TYPE_BOOL, TAG_TYPE_BOOL,
@ -43,21 +43,16 @@ struct tag_set {
}; };
struct tag *tag_new_int(struct module *owner, const char *name, long value); struct tag *tag_new_int(struct module *owner, const char *name, long value);
struct tag *tag_new_int_range( struct tag *tag_new_int_range(struct module *owner, const char *name, long value, long min, long max);
struct module *owner, const char *name, long value, long min, long max); struct tag *tag_new_int_realtime(struct module *owner, const char *name, long value, long min, long max,
struct tag *tag_new_int_realtime( enum tag_realtime_unit unit);
struct module *owner, const char *name, long value, long min,
long max, enum tag_realtime_unit unit);
struct tag *tag_new_bool(struct module *owner, const char *name, bool value); struct tag *tag_new_bool(struct module *owner, const char *name, bool value);
struct tag *tag_new_float(struct module *owner, const char *name, double value); struct tag *tag_new_float(struct module *owner, const char *name, double value);
struct tag *tag_new_string( struct tag *tag_new_string(struct module *owner, const char *name, const char *value);
struct module *owner, const char *name, const char *value);
const struct tag *tag_for_name(const struct tag_set *set, const char *name); const struct tag *tag_for_name(const struct tag_set *set, const char *name);
void tag_set_destroy(struct tag_set *set); void tag_set_destroy(struct tag_set *set);
/* Utility functions */ /* Utility functions */
char *tags_expand_template(const char *template, const struct tag_set *tags); char *tags_expand_template(const char *template, const struct tag_set *tags);
void tags_expand_templates( void tags_expand_templates(char *expanded[], const char *template[], size_t nmemb, const struct tag_set *tags);
char *expanded[], const char *template[], size_t nmemb,
const struct tag_set *tags);

82
xcb.c
View file

@ -1,16 +1,16 @@
#include "xcb.h" #include "xcb.h"
#include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <xcb/xcb.h>
#include <xcb/randr.h> #include <xcb/randr.h>
#include <xcb/render.h> #include <xcb/render.h>
#include <xcb/xcb.h>
#if defined(HAVE_XCB_ERRORS) #if defined(HAVE_XCB_ERRORS)
#include <xcb/xcb_errors.h> #include <xcb/xcb_errors.h>
#endif #endif
#define LOG_MODULE "xcb" #define LOG_MODULE "xcb"
@ -36,8 +36,7 @@ xcb_atom_t _NET_WM_NAME;
static xcb_errors_context_t *err_context; static xcb_errors_context_t *err_context;
#endif #endif
static void __attribute__((destructor)) static void __attribute__((destructor)) fini(void)
fini(void)
{ {
#if defined(HAVE_XCB_ERRORS) #if defined(HAVE_XCB_ERRORS)
xcb_errors_context_free(err_context); xcb_errors_context_free(err_context);
@ -63,19 +62,17 @@ xcb_init(void)
/* Vendor release number */ /* Vendor release number */
unsigned release = setup->release_number; unsigned release = setup->release_number;
unsigned major = release / 10000000; release %= 10000000; unsigned major = release / 10000000;
unsigned minor = release / 100000; release %= 100000; release %= 10000000;
unsigned minor = release / 100000;
release %= 100000;
unsigned patch = release / 1000; unsigned patch = release / 1000;
#endif #endif
LOG_DBG("%.*s %u.%u.%u (protocol: %u.%u)", LOG_DBG("%.*s %u.%u.%u (protocol: %u.%u)", xcb_setup_vendor_length(setup), xcb_setup_vendor(setup), major, minor,
xcb_setup_vendor_length(setup), xcb_setup_vendor(setup), patch, setup->protocol_major_version, setup->protocol_minor_version);
major, minor, patch,
setup->protocol_major_version,
setup->protocol_minor_version);
const xcb_query_extension_reply_t *randr = const xcb_query_extension_reply_t *randr = xcb_get_extension_data(conn, &xcb_randr_id);
xcb_get_extension_data(conn, &xcb_randr_id);
if (randr == NULL || !randr->present) { if (randr == NULL || !randr->present) {
LOG_ERR("RANDR extension not present"); LOG_ERR("RANDR extension not present");
@ -83,8 +80,7 @@ xcb_init(void)
return false; return false;
} }
const xcb_query_extension_reply_t *render = const xcb_query_extension_reply_t *render = xcb_get_extension_data(conn, &xcb_render_id);
xcb_get_extension_data(conn, &xcb_render_id);
if (render == NULL || !render->present) { if (render == NULL || !render->present) {
LOG_ERR("RENDER extension not present"); LOG_ERR("RENDER extension not present");
@ -92,18 +88,15 @@ xcb_init(void)
return false; return false;
} }
xcb_randr_query_version_cookie_t randr_cookie = xcb_randr_query_version_cookie_t randr_cookie
xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, = xcb_randr_query_version(conn, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION);
XCB_RANDR_MINOR_VERSION); xcb_render_query_version_cookie_t render_cookie
xcb_render_query_version_cookie_t render_cookie = = xcb_render_query_version(conn, XCB_RENDER_MAJOR_VERSION, XCB_RENDER_MINOR_VERSION);
xcb_render_query_version(conn, XCB_RENDER_MAJOR_VERSION,
XCB_RENDER_MINOR_VERSION);
xcb_flush(conn); xcb_flush(conn);
xcb_generic_error_t *e; xcb_generic_error_t *e;
xcb_randr_query_version_reply_t *randr_version = xcb_randr_query_version_reply_t *randr_version = xcb_randr_query_version_reply(conn, randr_cookie, &e);
xcb_randr_query_version_reply(conn, randr_cookie, &e);
if (e != NULL) { if (e != NULL) {
LOG_ERR("failed to query RANDR version: %s", xcb_error(e)); LOG_ERR("failed to query RANDR version: %s", xcb_error(e));
free(e); free(e);
@ -111,8 +104,7 @@ xcb_init(void)
return false; return false;
} }
xcb_render_query_version_reply_t *render_version = xcb_render_query_version_reply_t *render_version = xcb_render_query_version_reply(conn, render_cookie, &e);
xcb_render_query_version_reply(conn, render_cookie, &e);
if (e != NULL) { if (e != NULL) {
LOG_ERR("failed to query RENDER version: %s", xcb_error(e)); LOG_ERR("failed to query RENDER version: %s", xcb_error(e));
free(e); free(e);
@ -120,10 +112,8 @@ xcb_init(void)
return false; return false;
} }
LOG_DBG("RANDR: %u.%u", LOG_DBG("RANDR: %u.%u", randr_version->major_version, randr_version->minor_version);
randr_version->major_version, randr_version->minor_version); LOG_DBG("RENDER: %u.%u", render_version->major_version, render_version->minor_version);
LOG_DBG("RENDER: %u.%u",
render_version->major_version, render_version->minor_version);
free(randr_version); free(randr_version);
free(render_version); free(render_version);
@ -131,7 +121,7 @@ xcb_init(void)
/* Cache atoms */ /* Cache atoms */
UTF8_STRING = get_atom(conn, "UTF8_STRING"); UTF8_STRING = get_atom(conn, "UTF8_STRING");
_NET_WM_PID = get_atom(conn, "_NET_WM_PID"); _NET_WM_PID = get_atom(conn, "_NET_WM_PID");
_NET_WM_WINDOW_TYPE = get_atom(conn, "_NET_WM_WINDOW_TYPE"); _NET_WM_WINDOW_TYPE = get_atom(conn, "_NET_WM_WINDOW_TYPE");
_NET_WM_WINDOW_TYPE_DOCK = get_atom(conn, "_NET_WM_WINDOW_TYPE_DOCK"); _NET_WM_WINDOW_TYPE_DOCK = get_atom(conn, "_NET_WM_WINDOW_TYPE_DOCK");
_NET_WM_STATE = get_atom(conn, "_NET_WM_STATE"); _NET_WM_STATE = get_atom(conn, "_NET_WM_STATE");
_NET_WM_STATE_ABOVE = get_atom(conn, "_NET_WM_STATE_ABOVE"); _NET_WM_STATE_ABOVE = get_atom(conn, "_NET_WM_STATE_ABOVE");
@ -153,10 +143,7 @@ xcb_atom_t
get_atom(xcb_connection_t *conn, const char *name) get_atom(xcb_connection_t *conn, const char *name)
{ {
xcb_generic_error_t *e; xcb_generic_error_t *e;
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply( xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(conn, xcb_intern_atom(conn, 0, strlen(name), name), &e);
conn,
xcb_intern_atom(conn, 0, strlen(name), name),
&e);
if (e != NULL) { if (e != NULL) {
LOG_ERR("%s: failed to get atom for %s", name, xcb_error(e)); LOG_ERR("%s: failed to get atom for %s", name, xcb_error(e));
@ -182,8 +169,7 @@ char *
get_atom_name(xcb_connection_t *conn, xcb_atom_t atom) get_atom_name(xcb_connection_t *conn, xcb_atom_t atom)
{ {
xcb_generic_error_t *e; xcb_generic_error_t *e;
xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply( xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(conn, xcb_get_atom_name(conn, atom), &e);
conn, xcb_get_atom_name(conn, atom), &e);
if (e != NULL) { if (e != NULL) {
LOG_ERR("failed to get atom name: %s", xcb_error(e)); LOG_ERR("failed to get atom name: %s", xcb_error(e));
@ -192,8 +178,7 @@ get_atom_name(xcb_connection_t *conn, xcb_atom_t atom)
return NULL; return NULL;
} }
char *name = strndup( char *name = strndup(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
LOG_DBG("atom name: %s", name); LOG_DBG("atom name: %s", name);
@ -207,22 +192,17 @@ xcb_error(const xcb_generic_error_t *error)
static char msg[1024]; static char msg[1024];
#if defined(HAVE_XCB_ERRORS) #if defined(HAVE_XCB_ERRORS)
const char *major = xcb_errors_get_name_for_major_code( const char *major = xcb_errors_get_name_for_major_code(err_context, error->major_code);
err_context, error->major_code); const char *minor = xcb_errors_get_name_for_minor_code(err_context, error->major_code, error->minor_code);
const char *minor = xcb_errors_get_name_for_minor_code(
err_context, error->major_code, error->minor_code);
const char *extension; const char *extension;
const char *name = xcb_errors_get_name_for_error( const char *name = xcb_errors_get_name_for_error(err_context, error->error_code, &extension);
err_context, error->error_code, &extension);
snprintf(msg, sizeof(msg), snprintf(msg, sizeof(msg), "major=%s, minor=%s), code=%s, extension=%s, sequence=%u", major, minor, name, extension,
"major=%s, minor=%s), code=%s, extension=%s, sequence=%u",
major, minor, name, extension, error->sequence);
#else
snprintf(msg, sizeof(msg), "op %hhu:%hu, code %hhu, sequence %hu",
error->major_code, error->minor_code, error->error_code,
error->sequence); error->sequence);
#else
snprintf(msg, sizeof(msg), "op %hhu:%hu, code %hhu, sequence %hu", error->major_code, error->minor_code,
error->error_code, error->sequence);
#endif #endif
return msg; return msg;

186
yml.c
View file

@ -1,13 +1,13 @@
#include "yml.h" #include "yml.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <yaml.h>
#include <tllist.h> #include <tllist.h>
#include <yaml.h>
#define UNUSED __attribute__((unused)) #define UNUSED __attribute__((unused))
@ -78,7 +78,8 @@ clone_node(struct yml_node *parent, const struct yml_node *node)
break; break;
case DICT: case DICT:
tll_foreach(node->dict.pairs, it) { tll_foreach(node->dict.pairs, it)
{
struct dict_pair p = { struct dict_pair p = {
.key = clone_node(clone, it->item.key), .key = clone_node(clone, it->item.key),
.value = clone_node(clone, it->item.value), .value = clone_node(clone, it->item.value),
@ -88,8 +89,7 @@ clone_node(struct yml_node *parent, const struct yml_node *node)
break; break;
case LIST: case LIST:
tll_foreach(node->list.values, it) tll_foreach(node->list.values, it) tll_push_back(clone->list.values, clone_node(clone, it->item));
tll_push_back(clone->list.values, clone_node(clone, it->item));
break; break;
case ROOT: case ROOT:
@ -119,7 +119,8 @@ dict_has_key(const struct yml_node *node, const struct yml_node *key)
{ {
assert(node->type == DICT); assert(node->type == DICT);
tll_foreach(node->dict.pairs, pair) { tll_foreach(node->dict.pairs, pair)
{
if (node_equal(pair->item.key, key)) if (node_equal(pair->item.key, key))
return true; return true;
} }
@ -130,7 +131,7 @@ dict_has_key(const struct yml_node *node, const struct yml_node *key)
static enum yml_error static enum yml_error
add_node(struct yml_node *parent, struct yml_node *new_node, yaml_mark_t loc) add_node(struct yml_node *parent, struct yml_node *new_node, yaml_mark_t loc)
{ {
new_node->line = loc.line + 1; /* yaml uses 0-based line numbers */ new_node->line = loc.line + 1; /* yaml uses 0-based line numbers */
new_node->column = loc.column; new_node->column = loc.column;
switch (parent->type) { switch (parent->type) {
@ -168,8 +169,7 @@ add_node(struct yml_node *parent, struct yml_node *new_node, yaml_mark_t loc)
} }
static void static void
add_anchor(struct yml_node *root, const char *anchor, add_anchor(struct yml_node *root, const char *anchor, const struct yml_node *node)
const struct yml_node *node)
{ {
assert(root->type == ROOT); assert(root->type == ROOT);
@ -190,25 +190,23 @@ post_process(struct yml_node *node, char **error)
break; break;
case SCALAR: case SCALAR:
//assert(strcmp(node->scalar.value, "<<") != 0); // assert(strcmp(node->scalar.value, "<<") != 0);
break; break;
case LIST: case LIST:
tll_foreach(node->list.values, it) tll_foreach(node->list.values, it) if (!post_process(it->item, error)) return false;
if (!post_process(it->item, error))
return false;
break; break;
case DICT: case DICT:
tll_foreach(node->dict.pairs, it) { tll_foreach(node->dict.pairs, it)
if (!post_process(it->item.key, error) || {
!post_process(it->item.value, error)) if (!post_process(it->item.key, error) || !post_process(it->item.value, error)) {
{
return false; return false;
} }
} }
tll_foreach(node->dict.pairs, it) { tll_foreach(node->dict.pairs, it)
{
if (it->item.key->type != SCALAR) if (it->item.key->type != SCALAR)
continue; continue;
@ -220,19 +218,19 @@ post_process(struct yml_node *node, char **error)
* Merge value is a list (of dictionaries) * Merge value is a list (of dictionaries)
* e.g. <<: [*foo, *bar] * e.g. <<: [*foo, *bar]
*/ */
tll_foreach(it->item.value->list.values, v_it) { tll_foreach(it->item.value->list.values, v_it)
{
if (v_it->item->type != DICT) { if (v_it->item->type != DICT) {
int cnt = snprintf( int cnt = snprintf(NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->line,
NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->column);
v_it->item->line, v_it->item->column);
*error = malloc(cnt + 1); *error = malloc(cnt + 1);
snprintf( snprintf(*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->line,
*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", v_it->item->column);
v_it->item->line, v_it->item->column);
return false; return false;
} }
tll_foreach(v_it->item->dict.pairs, vv_it) { tll_foreach(v_it->item->dict.pairs, vv_it)
{
struct dict_pair p = { struct dict_pair p = {
.key = vv_it->item.key, .key = vv_it->item.key,
.value = vv_it->item.value, .value = vv_it->item.value,
@ -261,17 +259,16 @@ post_process(struct yml_node *node, char **error)
* e.g. <<: *foo * e.g. <<: *foo
*/ */
if (it->item.value->type != DICT) { if (it->item.value->type != DICT) {
int cnt = snprintf( int cnt = snprintf(NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->line,
NULL, 0, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->column);
it->item.value->line, it->item.value->column);
*error = malloc(cnt + 1); *error = malloc(cnt + 1);
snprintf( snprintf(*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->line,
*error, cnt + 1, "%zu:%zu: cannot merge non-dictionary anchor", it->item.value->column);
it->item.value->line, it->item.value->column);
return false; return false;
} }
tll_foreach(it->item.value->dict.pairs, v_it) { tll_foreach(it->item.value->dict.pairs, v_it)
{
struct dict_pair p = { struct dict_pair p = {
.key = v_it->item.key, .key = v_it->item.key,
.value = v_it->item.value, .value = v_it->item.value,
@ -307,10 +304,7 @@ post_process(struct yml_node *node, char **error)
} }
static const char * static const char *
format_error(enum yml_error err, format_error(enum yml_error err, const struct yml_node *parent, const struct yml_node *node, const char *anchor)
const struct yml_node *parent,
const struct yml_node *node,
const char *anchor)
{ {
static char err_str[512]; static char err_str[512];
@ -321,11 +315,9 @@ format_error(enum yml_error err,
case YML_ERR_DUPLICATE_KEY: { case YML_ERR_DUPLICATE_KEY: {
/* Find parent's key (i.e its name) */ /* Find parent's key (i.e its name) */
if (parent->parent != NULL && if (parent->parent != NULL && parent->parent->type == DICT && node->type == SCALAR) {
parent->parent->type == DICT && tll_foreach(parent->parent->dict.pairs, pair)
node->type == SCALAR) {
{
tll_foreach(parent->parent->dict.pairs, pair) {
if (pair->item.value != parent) if (pair->item.value != parent)
continue; continue;
@ -335,17 +327,14 @@ format_error(enum yml_error err,
assert(pair->item.key->type == SCALAR); assert(pair->item.key->type == SCALAR);
assert(node->type == SCALAR); assert(node->type == SCALAR);
snprintf(err_str, sizeof(err_str), snprintf(err_str, sizeof(err_str), "%s: duplicate key: '%s'", pair->item.key->scalar.value,
"%s: duplicate key: '%s'",
pair->item.key->scalar.value,
node->scalar.value); node->scalar.value);
return err_str; return err_str;
} }
} }
if (node->type == SCALAR) { if (node->type == SCALAR) {
snprintf(err_str, sizeof(err_str), snprintf(err_str, sizeof(err_str), "duplicate key: %s", node->scalar.value);
"duplicate key: %s", node->scalar.value);
} else } else
snprintf(err_str, sizeof(err_str), "duplicate key"); snprintf(err_str, sizeof(err_str), "duplicate key");
break; break;
@ -353,22 +342,20 @@ format_error(enum yml_error err,
case YML_ERR_INVALID_ANCHOR: case YML_ERR_INVALID_ANCHOR:
if (parent->parent != NULL && parent->parent->type == DICT) { if (parent->parent != NULL && parent->parent->type == DICT) {
tll_foreach(parent->parent->dict.pairs, pair) { tll_foreach(parent->parent->dict.pairs, pair)
{
if (pair->item.value != parent) if (pair->item.value != parent)
continue; continue;
if (pair->item.key->type != SCALAR) if (pair->item.key->type != SCALAR)
break; break;
snprintf(err_str, sizeof(err_str), snprintf(err_str, sizeof(err_str), "%s: invalid anchor: %s", pair->item.key->scalar.value,
"%s: invalid anchor: %s",
pair->item.key->scalar.value,
anchor != NULL ? anchor : "<unknown>"); anchor != NULL ? anchor : "<unknown>");
return err_str; return err_str;
} }
} }
snprintf(err_str, sizeof(err_str), "invalid anchor: %s", snprintf(err_str, sizeof(err_str), "invalid anchor: %s", anchor != NULL ? anchor : "<unknown>");
anchor != NULL ? anchor : "<unknown>");
break; break;
case YML_ERR_UNKNOWN: case YML_ERR_UNKNOWN:
@ -403,19 +390,12 @@ yml_load(FILE *yml, char **error)
yaml_event_t event; yaml_event_t event;
if (!yaml_parser_parse(&yaml, &event)) { if (!yaml_parser_parse(&yaml, &event)) {
if (error != NULL) { if (error != NULL) {
int cnt = snprintf( int cnt = snprintf(NULL, 0, "%zu:%zu: %s %s", yaml.problem_mark.line + 1, yaml.problem_mark.column,
NULL, 0, "%zu:%zu: %s %s", yaml.problem, yaml.context != NULL ? yaml.context : "");
yaml.problem_mark.line + 1,
yaml.problem_mark.column,
yaml.problem,
yaml.context != NULL ? yaml.context : "");
*error = malloc(cnt + 1); *error = malloc(cnt + 1);
snprintf(*error, cnt + 1, "%zu:%zu: %s %s", snprintf(*error, cnt + 1, "%zu:%zu: %s %s", yaml.problem_mark.line + 1, yaml.problem_mark.column,
yaml.problem_mark.line + 1, yaml.problem, yaml.context != NULL ? yaml.context : "");
yaml.problem_mark.column,
yaml.problem,
yaml.context != NULL ? yaml.context : "");
} }
goto err_no_error_formatting; goto err_no_error_formatting;
@ -466,9 +446,7 @@ yml_load(FILE *yml, char **error)
} }
if (!got_match) { if (!got_match) {
error_str = format_error( error_str = format_error(YML_ERR_INVALID_ANCHOR, n, NULL, (const char *)event.data.alias.anchor);
YML_ERR_INVALID_ANCHOR, n, NULL,
(const char *)event.data.alias.anchor);
yaml_event_delete(&event); yaml_event_delete(&event);
goto err; goto err;
} }
@ -478,8 +456,7 @@ yml_load(FILE *yml, char **error)
case YAML_SCALAR_EVENT: { case YAML_SCALAR_EVENT: {
struct yml_node *new_scalar = calloc(1, sizeof(*new_scalar)); struct yml_node *new_scalar = calloc(1, sizeof(*new_scalar));
new_scalar->type = SCALAR; new_scalar->type = SCALAR;
new_scalar->scalar.value = strndup( new_scalar->scalar.value = strndup((const char *)event.data.scalar.value, event.data.scalar.length);
(const char*)event.data.scalar.value, event.data.scalar.length);
enum yml_error err = add_node(n, new_scalar, event.start_mark); enum yml_error err = add_node(n, new_scalar, event.start_mark);
if (err != YML_ERR_NONE) { if (err != YML_ERR_NONE) {
@ -569,23 +546,13 @@ yml_load(FILE *yml, char **error)
err: err:
if (error_str != NULL) { if (error_str != NULL) {
int cnt = snprintf( int cnt = snprintf(NULL, 0, "%zu:%zu: %s", yaml.mark.line + 1, yaml.mark.column, error_str);
NULL, 0, "%zu:%zu: %s",
yaml.mark.line + 1,
yaml.mark.column,
error_str);
*error = malloc(cnt + 1); *error = malloc(cnt + 1);
snprintf( snprintf(*error, cnt + 1, "%zu:%zu: %s", yaml.mark.line + 1, yaml.mark.column, error_str);
*error, cnt + 1, "%zu:%zu: %s",
yaml.mark.line + 1,
yaml.mark.column,
error_str);
} else { } else {
int cnt = snprintf(NULL, 0, "%zu:%zu: unknown error", int cnt = snprintf(NULL, 0, "%zu:%zu: unknown error", yaml.mark.line + 1, yaml.mark.column);
yaml.mark.line + 1, yaml.mark.column);
*error = malloc(cnt + 1); *error = malloc(cnt + 1);
snprintf(*error, cnt + 1, "%zu:%zu: unknown error", snprintf(*error, cnt + 1, "%zu:%zu: unknown error", yaml.mark.line + 1, yaml.mark.column);
yaml.mark.line + 1, yaml.mark.column);
} }
err_no_error_formatting: err_no_error_formatting:
@ -617,7 +584,8 @@ yml_destroy(struct yml_node *node)
break; break;
case DICT: case DICT:
tll_foreach(node->dict.pairs, it) { tll_foreach(node->dict.pairs, it)
{
yml_destroy(it->item.key); yml_destroy(it->item.key);
yml_destroy(it->item.value); yml_destroy(it->item.value);
} }
@ -659,13 +627,12 @@ yml_get_(struct yml_node const *node, char const *_path, bool value)
char *path = strdup(_path); char *path = strdup(_path);
for (const char *part = strtok(path, "."), *next_part = strtok(NULL, "."); for (const char *part = strtok(path, "."), *next_part = strtok(NULL, "."); part != NULL;
part != NULL; part = next_part, next_part = strtok(NULL, ".")) {
part = next_part, next_part = strtok(NULL, "."))
{
assert(yml_is_dict(node)); assert(yml_is_dict(node));
tll_foreach(node->dict.pairs, it) { tll_foreach(node->dict.pairs, it)
{
assert(yml_is_scalar(it->item.key)); assert(yml_is_scalar(it->item.key));
if (strcmp(it->item.key->scalar.value, part) == 0) { if (strcmp(it->item.key->scalar.value, part) == 0) {
if (next_part == NULL) { if (next_part == NULL) {
@ -694,7 +661,8 @@ yml_get_value(const struct yml_node *node, const char *_path)
} }
struct yml_node const * struct yml_node const *
yml_get_key(struct yml_node const *node, char const *_path) { yml_get_key(struct yml_node const *node, char const *_path)
{
return yml_get_(node, _path, false); return yml_get_(node, _path, false);
} }
@ -702,7 +670,8 @@ struct yml_list_iter
yml_list_iter(const struct yml_node *list) yml_list_iter(const struct yml_node *list)
{ {
assert(yml_is_list(list)); assert(yml_is_list(list));
tll_foreach(list->list.values, it) { tll_foreach(list->list.values, it)
{
return (struct yml_list_iter){ return (struct yml_list_iter){
.node = it->item, .node = it->item,
.private = it, .private = it,
@ -735,9 +704,7 @@ yml_list_length(const struct yml_node *list)
assert(yml_is_list(list)); assert(yml_is_list(list));
size_t length = 0; size_t length = 0;
for (struct yml_list_iter it = yml_list_iter(list); for (struct yml_list_iter it = yml_list_iter(list); it.node != NULL; yml_list_next(&it), length++)
it.node != NULL;
yml_list_next(&it), length++)
; ;
return length; return length;
@ -748,7 +715,8 @@ yml_dict_iter(const struct yml_node *dict)
{ {
assert(yml_is_dict(dict)); assert(yml_is_dict(dict));
tll_foreach(dict->dict.pairs, it) { tll_foreach(dict->dict.pairs, it)
{
return (struct yml_dict_iter){ return (struct yml_dict_iter){
.key = it->item.key, .key = it->item.key,
.value = it->item.value, .value = it->item.value,
@ -756,7 +724,7 @@ yml_dict_iter(const struct yml_node *dict)
}; };
} }
return (struct yml_dict_iter) { return (struct yml_dict_iter){
.key = NULL, .key = NULL,
.value = NULL, .value = NULL,
.private1 = NULL, .private1 = NULL,
@ -827,18 +795,12 @@ _as_bool(const struct yml_node *value, bool *ret)
return false; return false;
const char *v = yml_value_as_string(value); const char *v = yml_value_as_string(value);
if (strcasecmp(v, "y") == 0 || if (strcasecmp(v, "y") == 0 || strcasecmp(v, "yes") == 0 || strcasecmp(v, "true") == 0
strcasecmp(v, "yes") == 0 || || strcasecmp(v, "on") == 0) {
strcasecmp(v, "true") == 0 ||
strcasecmp(v, "on") == 0)
{
*ret = true; *ret = true;
return true; return true;
} else if (strcasecmp(v, "n") == 0 || } else if (strcasecmp(v, "n") == 0 || strcasecmp(v, "no") == 0 || strcasecmp(v, "false") == 0
strcasecmp(v, "no") == 0 || || strcasecmp(v, "off") == 0) {
strcasecmp(v, "false") == 0 ||
strcasecmp(v, "off") == 0)
{
*ret = false; *ret = false;
return true; return true;
} }
@ -885,7 +847,8 @@ _print_node(const struct yml_node *n, int indent)
break; break;
case DICT: case DICT:
tll_foreach(n->dict.pairs, it) { tll_foreach(n->dict.pairs, it)
{
_print_node(it->item.key, indent); _print_node(it->item.key, indent);
printf(": "); printf(": ");
@ -900,7 +863,8 @@ _print_node(const struct yml_node *n, int indent)
break; break;
case LIST: case LIST:
tll_foreach(n->list.values, it) { tll_foreach(n->list.values, it)
{
printf("%*s- ", indent, ""); printf("%*s- ", indent, "");
if (it->item->type != SCALAR) { if (it->item->type != SCALAR) {
printf("\n"); printf("\n");

8
yml.h
View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h>
struct yml_node; struct yml_node;
@ -11,10 +11,8 @@ bool yml_is_scalar(const struct yml_node *node);
bool yml_is_dict(const struct yml_node *node); bool yml_is_dict(const struct yml_node *node);
bool yml_is_list(const struct yml_node *node); bool yml_is_list(const struct yml_node *node);
const struct yml_node *yml_get_value( const struct yml_node *yml_get_value(const struct yml_node *node, const char *path);
const struct yml_node *node, const char *path); const struct yml_node *yml_get_key(struct yml_node const *node, char const *path);
const struct yml_node *yml_get_key(
struct yml_node const *node, char const *path);
struct yml_list_iter { struct yml_list_iter {
const struct yml_node *node; const struct yml_node *node;