New paste Repaste Download
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "shm.h"
struct wb_color {
    uint32_t r, g, b;
};
static bool parse_color(const char *str, struct wb_color *color) {
    if (str[0] == '#') {
        str++;
    }
    uint32_t r, g, b;
    char dummy[2];
    int res = sscanf(str, "%02x%02x%02x%s", &r, &g, &b, dummy);
    if (res != 3 || dummy[0] != '\0') {
        return false;
    }
    color->r = r;
    color->g = g;
    color->b = b;
    return true;
}
struct wb_config {
    struct wb_color *bg_color;
};
static void print_config(struct wb_config *config) {
    struct wb_color *color = config->bg_color;
    printf("config:\n"
           " - color: [%d, %d, %d]\n",
           color->r, color->g, color->b);
}
struct wb_output {
    uint32_t wl_name;
    struct wl_output *wl_output;
    char *make, *model;
    uint32_t width, height;
    int32_t scale;
    bool configured;
    struct wl_list link;
};
struct wb_state {
    struct wl_display *display;
    struct wl_registry *registry;
    struct wl_compositor *compositor;
    struct wl_shm *shm;
    struct zwlr_layer_shell_v1 *layer_shell;
    struct wl_list outputs;
};
static void destroy_output(struct wb_output *output) {
    if (output == NULL) {
        return;
    }
    wl_list_remove(&output->link);
    wl_output_destroy(output->wl_output);
    free(output->make);
    free(output->model);
    free(output);
}
static void output_geometry(void *data, struct wl_output *wl_output, int32_t x,
                            int32_t y, int32_t width_mm, int32_t height_mm,
                            int32_t subpixel, const char *make,
                            const char *model, int32_t transform) {
    (void)wl_output;
    (void)x;
    (void)y;
    (void)width_mm;
    (void)height_mm;
    (void)subpixel;
    (void)transform;
    struct wb_output *output = data;
    free(output->make);
    free(output->model);
    if (make != NULL) {
        uint32_t len = strlen(make) + 1;
        char *new_make = malloc(len);
        if (new_make != NULL) {
            memcpy(new_make, make, len);
        }
        output->make = new_make;
    }
    if (model != NULL) {
        uint32_t len = strlen(model) + 1;
        char *new_model = malloc(len);
        if (new_model != NULL) {
            memcpy(new_model, model, len);
        }
        output->model = new_model;
    }
}
static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
                        int32_t width, int32_t height, int32_t refresh) {
    (void)wl_output;
    (void)refresh;
    /* is this necessary? */
    if ((flags & WL_OUTPUT_MODE_CURRENT) == 0) {
        return;
    }
    struct wb_output *output = data;
    output->width = width;
    output->height = height;
}
static void output_done(void *data, struct wl_output *wl_output) {
    (void)wl_output;
    struct wb_output *output = data;
    printf("output: %s %s (%dx%d, scale=%d)\n", output->make, output->model,
           output->width, output->height, output->scale);
}
static void output_scale(void *data, struct wl_output *wl_output,
                         int32_t factor) {
    (void)data;
    (void)wl_output;
    struct wb_output *output = data;
    output->scale = factor;
}
static const struct wl_output_listener output_listener = {
    .geometry = output_geometry,
    .mode = output_mode,
    .done = output_done,
    .scale = output_scale,
};
static void handle_global(void *data, struct wl_registry *registry,
                          uint32_t name, const char *interface,
                          uint32_t version) {
    (void)version;
    struct wb_state *state = data;
    if (strcmp(interface, wl_compositor_interface.name) == 0) {
        state->compositor =
            wl_registry_bind(registry, name, &wl_compositor_interface, 4);
    }
    else if (strcmp(interface, wl_shm_interface.name) == 0) {
        state->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
    }
    else if (strcmp(interface, wl_output_interface.name) == 0) {
        struct wb_output *output = calloc(1, sizeof(struct wb_output));
        output->wl_name = name;
        output->wl_output =
            wl_registry_bind(registry, name, &wl_output_interface, 3);
        wl_output_add_listener(output->wl_output, &output_listener, output);
        wl_list_insert(&state->outputs, &output->link);
    }
    else if (strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
        state->layer_shell =
            wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 1);
    }
}
static void handle_global_remove(void *data, struct wl_registry *registry,
                                 uint32_t name) {
    (void)registry;
    struct wb_state *state = data;
    struct wb_output *output, *tmp;
    wl_list_for_each_safe(output, tmp, &state->outputs, link) {
        if (output->wl_name == name) {
            destroy_output(output);
            break;
        }
    }
}
static const struct wl_registry_listener registry_listener = {
    .global = handle_global,
    .global_remove = handle_global_remove,
};
static bool init_wayland(struct wb_state *state) {
    state->display = wl_display_connect(NULL);
    if (state->display == NULL) {
        fprintf(stderr, "err: failed to connect to wayland display\n");
        return false;
    }
    state->registry = wl_display_get_registry(state->display);
    if (state->registry == NULL) {
        fprintf(stderr, "err: failed to get display registry\n");
        return false;
    }
    wl_list_init(&state->outputs);
    wl_registry_add_listener(state->registry, &registry_listener, state);
    wl_display_roundtrip(state->display);
    if (state->compositor == NULL || state->shm == NULL ||
        state->layer_shell == NULL) {
        fprintf(
            stderr,
            "err: one or multiple not found: compositor, shm, layer shell\n");
        return false;
    }
    return true;
}
static void finish_wayland(struct wb_state *state) {
    struct wb_output *output, *tmp;
    wl_list_for_each_safe(output, tmp, &state->outputs, link) {
        destroy_output(output);
    }
    if (state->compositor != NULL) {
        wl_compositor_destroy(state->compositor);
    }
    if (state->shm != NULL) {
        wl_shm_destroy(state->shm);
    }
    if (state->layer_shell != NULL) {
        zwlr_layer_shell_v1_destroy(state->layer_shell);
    }
    if (state->registry != NULL) {
        wl_registry_destroy(state->registry);
    }
    if (state->display != NULL) {
        wl_display_disconnect(state->display);
    }
}
static void usage(const char *progname) {
    fprintf(stderr,
            "usage: %s [-hV] [-c color]\n"
            "  -h, --help show usage message and exit\n"
            "  -V, --version show version information and exit\n"
            "  -c, --color set the background color option\n",
            progname);
}
/* NOTE: color configuration is kept, but no rendering is done yet */
int main(int argc, char *argv[]) {
    const char *progname = argv[0];
    const struct option longopts[] = {
        {"help", no_argument, 0, 'h'},
        {"version", no_argument, 0, 'V'},
        {"color", required_argument, 0, 'c'},
        {NULL, no_argument, 0, 0},
    };
    /* app config data + defaults */
    struct wb_color color = {18, 18, 18};
    struct wb_config config = {.bg_color = &color};
    int c;
    do {
        c = getopt_long(argc, argv, ":hVc:", longopts, NULL);
        switch (c) {
        case 'h':
            usage(progname);
            return EXIT_SUCCESS;
        case 'V':
            fprintf(stderr, "%s version " WAYBACK_VERSION "\n", progname);
            return EXIT_SUCCESS;
        case 'c':
            if (!parse_color(optarg, &color)) {
                fprintf(stderr, "%s: invalid color argument -- '%s'\n",
                        progname, optarg);
                return EXIT_FAILURE;
            }
            break;
        case ':':
            fprintf(stderr, "%s: option requires an argument -- '%c'\n",
                    progname, optopt);
            usage(progname);
            return EXIT_FAILURE;
        case '?':
            fprintf(stderr, "%s: invalid option -- '%c'\n", progname, optopt);
            usage(progname);
            return EXIT_FAILURE;
        }
    } while (c != -1);
    print_config(&config);
    putchar('\n');
    struct wb_state state = {0};
    if (!init_wayland(&state)) {
        finish_wayland(&state);
        return EXIT_FAILURE;
    }
    while (wl_display_dispatch(state.display) != -1) {
        /* err... what goes here? */
    }
    finish_wayland(&state);
    return EXIT_SUCCESS;
}
Filename: None. Size: 9kb. View raw, , hex, or download this file.

This paste expires on 2025-04-05 18:03:13.570544. Pasted through curl.