#include <cerrno>
#include <cstdio>
#include <cstring>
#include <memory>
#include <vector>
#include <wayland-client.h>
#include "outputs.h"
std::vector<std::unique_ptr<struct output_info>> outputs = {};
static void handle_geometry(void *data, struct wl_output *wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform)
{
(void)wl_output;
(void)x;
(void)y;
(void)physical_width;
(void)physical_height;
(void)subpixel;
(void)transform;
struct output_info *output = static_cast<struct output_info *>(data);
output->make = make;
output->model = model;
}
static void handle_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;
struct output_info *output = static_cast<struct output_info *>(data);
if (flags & WL_OUTPUT_MODE_CURRENT)
output->default_resolution = output->resolutions.size();
output->resolutions.push_back({width, height});
}
static void handle_done(void *data, struct wl_output *wl_output)
{
(void)data;
(void)wl_output;
}
static void handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
{
(void)data;
(void)wl_output;
(void)factor;
}
static struct wl_output_listener output_listener = {
.geometry = handle_geometry,
.mode = handle_mode,
.done = handle_done,
.scale = handle_scale,
};
static void handle_global(void *data, struct wl_registry *registry, uint32_t name, const char *interface, uint32_t version)
{
(void)data;
if (strcmp(interface, wl_output_interface.name) == 0) {
std::unique_ptr<struct output_info> output = std::make_unique<struct output_info>();
int output_version = std::min(version, 1U);
output->global = static_cast<struct wl_output *>(wl_registry_bind(registry, name, &wl_output_interface, output_version));
wl_output_add_listener(output->global, &output_listener, output.get());
outputs.push_back(std::move(output));
}
}
static void handle_global_remove(void *data, struct wl_registry *registry, uint32_t name)
{
(void)data;
(void)registry;
(void)name;
}
static const struct wl_registry_listener registry_listener = {
.global = handle_global,
.global_remove = handle_global_remove,
};
int populate_wayland_outputs()
{
struct wl_display *display = wl_display_connect(NULL);
if (!display) {
fprintf(stderr, "Wayland: Failed to connect to display: %s\n", strerror(errno));
return -1;
}
struct wl_registry *registry = wl_display_get_registry(display);
if (!registry) {
fprintf(stderr, "Wayland: Failed to obtain a registry.\n");
return -1;
}
wl_registry_add_listener(registry, ®istry_listener, NULL);
wl_display_roundtrip(display);
wl_display_roundtrip(display);
for (const auto& output : outputs)
wl_output_destroy(output->global);
wl_registry_destroy(registry);
wl_display_disconnect(display);
return 0;
}