#include #include #include #include #include #include #include #include #include "wlr-export-dmabuf-unstable-v1.h" #include "render.h" #include "dmabuf.h" #include "strlcpy.h" #include "logging.h" struct wayvnc { struct wl_display* display; struct wl_registry* registry; struct wl_list outputs; struct zwlr_export_dmabuf_manager_v1* export_manager; }; struct output { struct wl_output* wl_output; struct wl_list link; uint32_t id; uint32_t width; uint32_t height; char make[256]; char model[256]; }; static void output_handle_geometry(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t phys_width, int32_t phys_height, int32_t subpixel, const char* make, const char* model, int32_t transform) { struct output* output = data; strlcpy(output->make, make, sizeof(output->make)); strlcpy(output->model, model, sizeof(output->make)); } static void output_handle_mode(void* data, struct wl_output* wl_output, uint32_t flags, int32_t width, int32_t height, int32_t refresh) { struct output* output = data; if (!(flags & WL_OUTPUT_MODE_CURRENT)) return; output->width = width; output->height = height; } static void output_handle_done(void* data, struct wl_output* wl_output) { } static void output_handle_scale(void* data, struct wl_output* wl_output, int32_t factor) { } static const struct wl_output_listener output_listener = { .geometry = output_handle_geometry, .mode = output_handle_mode, .done = output_handle_done, .scale = output_handle_scale, }; void output_destroy(struct output* output) { wl_output_destroy(output->wl_output); free(output); } void output_list_destroy(struct wl_list* list) { struct output* output; struct output* tmp; wl_list_for_each_safe(output, tmp, list, link) { wl_list_remove(&output->link); output_destroy(output); } } static void registry_add(void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version) { struct wayvnc* self = data; if (strcmp(interface, wl_output_interface.name) == 0) { struct output* output = calloc(1, sizeof(*output)); if (!output) { log_error("OOM\n"); return; } output->id = id; output->wl_output = wl_registry_bind(registry, id, &wl_output_interface, version); wl_output_add_listener(output->wl_output, &output_listener, output); wl_list_insert(&self->outputs, &output->link); return; } if (strcmp(interface, zwlr_export_dmabuf_manager_v1_interface.name) == 0) { self->export_manager = wl_registry_bind(registry, id, &zwlr_export_dmabuf_manager_v1_interface, version); return; } } static void registry_remove(void* data, struct wl_registry* registry, uint32_t id) { /* TODO */ } void wayvnc_destroy(struct wayvnc* self) { output_list_destroy(&self->outputs); zwlr_export_dmabuf_manager_v1_destroy(self->export_manager); wl_display_disconnect(self->display); } static int init_wayland(struct wayvnc* self) { static const struct wl_registry_listener registry_listener = { .global = registry_add, .global_remove = registry_remove, }; self->display = wl_display_connect(NULL); if (!self->display) return -1; wl_list_init(&self->outputs); self->registry = wl_display_get_registry(self->display); if (!self->registry) goto failure; wl_registry_add_listener(self->registry, ®istry_listener, self); wl_display_roundtrip(self->display); wl_display_dispatch(self->display); if (!self->export_manager) { log_error("Compositor does not support %s.\n", zwlr_export_dmabuf_manager_v1_interface.name); goto export_manager_failure; } return 0; export_manager_failure: output_list_destroy(&self->outputs); failure: wl_display_disconnect(self->display); return -1; } int main(int argc, char* argv[]) { struct wayvnc self; if (init_wayland(&self) < 0) return 1; printf("Outputs:\n"); struct output* out; wl_list_for_each(out, &self.outputs, link) printf("%"PRIu32": Make: %s. Model: %s\n", out->id, out->make, out->model); return 0; }