From f14acf7306b022c1d0dd98f5fd654dbdc38e64e5 Mon Sep 17 00:00:00 2001 From: Nathan Reiner Date: Sat, 22 Apr 2023 18:40:22 +0200 Subject: create ffbg --- ffbg.c | 357 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 ffbg.c (limited to 'ffbg.c') diff --git a/ffbg.c b/ffbg.c new file mode 100644 index 0000000..4fd5e25 --- /dev/null +++ b/ffbg.c @@ -0,0 +1,357 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "drw.h" +#include "util.h" +#include "wayland.h" + +/* type definitions */ +typedef struct BG BG; +struct BG { + unsigned width; + unsigned height; + uint32_t registry_name; + Canvas *canvas; + struct wl_output *wl_output; + struct wl_surface *wl_surface; + struct zwlr_layer_surface_v1 *zwlr_surface; + BG *next; +}; + +typedef struct { + uint32_t width; + uint32_t height; + uint32_t *buffer; +} Image; + +/* function declarations */ +static void update_bg(BG *bg); +static void wl_buffer_release(void *data, struct wl_buffer *wl_buffer); +static void remove_bg(BG *bg); +static void registry_global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version); +static void remove_global(void *data, struct wl_registry *wl_registry, uint32_t name); +static void layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h); +static void layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface); +static void dummy(); +static void wayland_flush(); +static void register_bg(BG *bg); +static void readimage(); +static void setup(); +struct wl_buffer *draw_frame(BG *bg); +static BG *add_bg(); + + +/* global variables */ +static const struct wl_buffer_listener wl_buffer_listener = { + .release = wl_buffer_release, +}; + +static const struct wl_registry_listener wl_registry_listener = { + .global = registry_global, + .global_remove = remove_global, +}; + +static const struct zwlr_layer_surface_v1_listener layer_surface_listener = { + .configure = layer_surface_configure, + .closed = layer_surface_closed +}; + +static BG *bgs = NULL; +static char statusline[1024] = ""; +struct client_state bg_state = { 0 }; +struct pollfd pollfds[2]; +int displayfd; +int ready = 0; +Image img; + +/* configuration */ +#include "config.h" + +/* function implementations */ +void +wl_buffer_release(void *data, struct wl_buffer *wl_buffer) +{ + wl_buffer_destroy(wl_buffer); +} + + +struct wl_buffer * +draw_frame(BG *bg) +{ + + Canvas *canvas = bg->canvas; + unsigned tx; + unsigned ty; + unsigned x; + unsigned y; + Color c; + Color colbg = to_color(background); + double strength; + + if (canvas == 0) + return 0; + + draw_rect(canvas, 0, 0, bg->width, bg->height, background); + + tx = (bg->width - img.width) / 2; + ty = (bg->height - img.height) / 2; + + for (x = 0; x < img.width; ++x) { + for (y = 0; y < img.height; ++y) { + c = to_color(img.buffer[x + img.width * y]); + strength = (double)(c.a) / 255; + + c.r = (strength * c.r) + ((1 - strength) * colbg.r); + c.g = (strength * c.g) + ((1 - strength) * colbg.g); + c.b = (strength * c.b) + ((1 - strength) * colbg.b); + c.a = 0xff; + + draw_point(canvas, x + tx, y + ty, to_uint32_t(c)); + } + } + + return canvas->buffer; +} + +void +update_bg(BG *bg) +{ + struct wl_buffer *buffer = draw_frame(bg); + + if (!buffer) + return; + + wl_surface_attach(bg->wl_surface, buffer, 0, 0); + wl_surface_damage_buffer(bg->wl_surface, 0, 0, bg->width, bg->height); + wl_surface_commit(bg->wl_surface); +} + + +void +registry_global(void *data, struct wl_registry *wl_registry, uint32_t name, const char *interface, uint32_t version) +{ + struct client_state *state = data; + BG *bg; + + if (strcmp(interface, wl_shm_interface.name) == 0) { + state->wl_shm = wl_registry_bind( + wl_registry, name, &wl_shm_interface, 1); + } else if (strcmp(interface, wl_compositor_interface.name) == 0) { + state->wl_compositor = wl_registry_bind( + wl_registry, name, &wl_compositor_interface, 4); + } else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) { + state->zwlr_layer = wl_registry_bind(wl_registry, name, &zwlr_layer_shell_v1_interface, 1); + } else if (strcmp(interface, wl_output_interface.name) == 0) { + bg = add_bg(); + bg->wl_output = wl_registry_bind(wl_registry, name, &wl_output_interface, 1); + bg->registry_name = name; + + if (ready) { + register_bg(bg); + } + } +} + + +void +remove_global(void *data, struct wl_registry *wl_registry, uint32_t name) +{ + BG *bg = bgs; + BG *prev = 0; + + for (; bg; bg = bg->next) { + if (bg->registry_name == name) { + if (prev) { + prev->next = bg->next; + } else { + bgs = bg->next; + } + + remove_bg(bg); + break; + } + + prev = bg; + } +} + + +void +layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface, uint32_t serial, uint32_t w, uint32_t h) +{ + BG *bg = data; + + bg->width = w; + bg->height = h; + + zwlr_layer_surface_v1_set_exclusive_zone(surface, -1); + zwlr_layer_surface_v1_ack_configure(surface, serial); + + bg->canvas = create_drw(bg_state.wl_shm, bg->width, bg->height); + + update_bg(bg); +} + + +void +layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface) +{ + BG *bg = data; + zwlr_layer_surface_v1_destroy(surface); + wl_surface_destroy(bg->wl_surface); +} + + +void +dummy() +{ + /* Who cares */ +} + + +BG * +add_bg() +{ + BG *bg = bgs; + + if (!bg) { + bgs = malloc(sizeof(BG)); + memset(bgs, 0, sizeof(BG)); + return bgs; + } + + for (; bg->next; bg = bg->next); + + bg->next = malloc(sizeof(BG)); + memset(bg->next, 0, sizeof(BG)); + + return bg->next; +} + + +void +remove_bg(BG *bg) +{ + wl_surface_destroy(bg->wl_surface); + zwlr_layer_surface_v1_destroy(bg->zwlr_surface); + wl_output_destroy(bg->wl_output); + free_drw(bg->canvas); + free(bg); +} + + +void +register_bg(BG *bg) +{ + char *namespace = "dbg"; + uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND; + uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP | ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM | ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT | ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT; + + bg->wl_surface = wl_compositor_create_surface(bg_state.wl_compositor); + bg->zwlr_surface = zwlr_layer_shell_v1_get_layer_surface(bg_state.zwlr_layer, bg->wl_surface, bg->wl_output, layer, namespace); + + zwlr_layer_surface_v1_add_listener(bg->zwlr_surface, &layer_surface_listener, bg); + + zwlr_layer_surface_v1_set_size(bg->zwlr_surface, bg->width, bg->height); + zwlr_layer_surface_v1_set_anchor(bg->zwlr_surface, anchor); + + wl_surface_commit(bg->wl_surface); + wl_display_roundtrip(bg_state.wl_display); +} + +void +readimage() +{ + uint32_t buf[4]; + size_t i; + size_t s = 0; + uint8_t r, g, b, a; + uint64_t *tmpbuf; + uint64_t color; + read(STDIN_FILENO, buf, sizeof(buf)); + + if (memcmp(buf, "farbfeld", sizeof("farbfeld") - 1)) { + die("input not farbfeld image"); + } + + img.width = ntohl(buf[2]); + img.height = ntohl(buf[3]); + img.buffer = malloc(img.width * img.height * sizeof(uint32_t)); + tmpbuf = malloc(img.width * img.height * sizeof(uint64_t)); + + for (i = 0; i < ((size_t)img.width * img.height * sizeof(uint64_t));) { + i += read(STDIN_FILENO, (char*)(tmpbuf) + i, 1); + } + + for (i = 0; i < img.width * img.height; ++i) { + color = tmpbuf[i]; + a = ((color & (0xffffl << 48)) >> 48) / 257; + b = ((color & (0xffffl << 32)) >> 32) / 257; + g = ((color & (0xffffl << 16)) >> 16) / 257; + r = (color & 0xffffl) / 257; + img.buffer[i] = (a << 24) | (r << 16) | (g << 8) | b; + } + + free(tmpbuf); +} + + +void +setup() +{ + BG *bg; + + bg_state.wl_display = wl_display_connect(NULL); + bg_state.wl_registry = wl_display_get_registry(bg_state.wl_display); + wl_registry_add_listener(bg_state.wl_registry, &wl_registry_listener, &bg_state); + wl_display_roundtrip(bg_state.wl_display); + + for (bg = bgs; bg; bg = bg->next) { + register_bg(bg); + } + + ready = 1; +} + + +void +wayland_flush() +{ + int i; + + wl_display_dispatch_pending(bg_state.wl_display); + + if (wl_display_flush(bg_state.wl_display) < 0 && errno == EAGAIN) { + for (i = 0; i < 2; ++i) { + if (pollfds[i].fd == displayfd) { + pollfds[i].events |= POLLOUT; + } + } + } +} + + +int +main(int argc, char *argv[]) +{ + readimage(); + setup(); + + while (wl_display_dispatch(bg_state.wl_display)) { + } + + return 0; +} -- cgit v1.2.3-70-g09d2