diff options
author | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-24 18:01:28 +0200 |
---|---|---|
committer | Leon Henrik Plickat <leonhenrik.plickat@stud.uni-goettingen.de> | 2020-09-24 18:01:28 +0200 |
commit | 9ff4f4959b8d78104fa4defb3c4cea9606e3c484 (patch) | |
tree | ac80aef7e1caff0d0af491ea4816ca63706a8116 /src/output.c | |
download | wlclock-9ff4f4959b8d78104fa4defb3c4cea9606e3c484.tar.gz wlclock-9ff4f4959b8d78104fa4defb3c4cea9606e3c484.tar.bz2 |
Init
Diffstat (limited to 'src/output.c')
-rw-r--r-- | src/output.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/output.c b/src/output.c new file mode 100644 index 0000000..102d510 --- /dev/null +++ b/src/output.c @@ -0,0 +1,169 @@ +#include<stdio.h> +#include<stdlib.h> +#include<stdbool.h> +#include<unistd.h> +#include<string.h> +#include<assert.h> + +#include<wayland-server.h> +#include<wayland-client.h> +#include<wayland-client-protocol.h> + +#include"xdg-output-unstable-v1-protocol.h" +#include"xdg-shell-protocol.h" + +#include"wlclock.h" +#include"misc.h" +#include"output.h" +#include"surface.h" + +/* No-Op function. */ +static void noop () {} + +static void output_handle_scale (void *data, struct wl_output *wl_output, + int32_t factor) +{ + struct Wlclock_output *output = (struct Wlclock_output *)data; + output->scale = (uint32_t)factor; + clocklog(output->clock, 1, "[output] Property update: global_name=%d scale=%d\n", + output->global_name, output->scale); +} + +static void output_update_surface (struct Wlclock_output *output) +{ + if ( ! output->configured || output->name == NULL ) + return; + + struct Wlclock *clock = output->clock; + if ( clock->output == NULL || ! strcmp(clock->output, output->name) ) + create_surface(output); +} + +static void output_handle_done (void *data, struct wl_output *wl_output) +{ + /* This event is sent after all output property changes (by wl_output + * and by xdg_output) have been advertised by preceding events. + */ + struct Wlclock_output *output = (struct Wlclock_output *)data; + clocklog(output->clock, 1, "[output] Atomic update complete: global_name=%d\n", + output->global_name); + if ( output->surface != NULL ) + update_surface(output->surface); + else + output_update_surface(output); +} + +static const struct wl_output_listener output_listener = { + .scale = output_handle_scale, + .geometry = noop, + .mode = noop, + .done = output_handle_done +}; + +static void xdg_output_handle_name (void *data, struct zxdg_output_v1 *xdg_output, + const char *name) +{ + struct Wlclock_output *output = (struct Wlclock_output *)data; + set_string(&output->name, (char *)name); + clocklog(output->clock, 1, "[output] Property update: global_name=%d name=%s\n", + output->global_name, name); +} + +static const struct zxdg_output_v1_listener xdg_output_listener = { + .name = xdg_output_handle_name, + .logical_size = noop, + .logical_position = noop, + .description = noop, + + /* Deprecated since version 3, xdg_output property changes now send wl_output.done */ + .done = noop +}; + +bool configure_output (struct Wlclock_output *output) +{ + struct Wlclock *clock = output->clock; + clocklog(clock, 1, "[output] Configuring: global_name=%d\n", output->global_name); + + /* Create xdg_output and attach listeners. */ + if ( NULL == (output->xdg_output = zxdg_output_manager_v1_get_xdg_output( + clock->xdg_output_manager, output->wl_output)) ) + { + clocklog(NULL, 0, "ERROR: Could not get XDG output.\n"); + return false; + } + + zxdg_output_v1_add_listener(output->xdg_output, &xdg_output_listener, output); + output->configured = true; + return true; +} + +bool create_output (struct Wlclock *clock, struct wl_registry *registry, + uint32_t name, const char *interface, uint32_t version) +{ + clocklog(clock, 1, "[output] Creating: global_name=%d\n", name); + + struct wl_output *wl_output = wl_registry_bind(registry, name, + &wl_output_interface, 3); + assert(wl_output); + + struct Wlclock_output *output = calloc(1, sizeof(struct Wlclock_output)); + if ( output == NULL ) + { + clocklog(NULL, 0, "ERROR: Could not allocate.\n"); + return false; + } + + output->clock = clock; + output->global_name = name; + output->scale = 1; + output->wl_output = wl_output; + output->configured = false; + output->name = NULL; + + wl_list_insert(&clock->outputs, &output->link); + wl_output_set_user_data(wl_output, output); + wl_output_add_listener(wl_output, &output_listener, output); + + /* We can only use the output if we have both xdg_output_manager and + * the layer_shell. If either one is not available yet, we have to + * configure the output later (see init_wayland()). + */ + if ( clock->xdg_output_manager != NULL && clock->layer_shell != NULL ) + { + if (! configure_output(output)) + return false; + } + else + clocklog(clock, 2, "[output] Not yet configureable.\n"); + + return true; +} + +struct Wlclock_output *get_output_from_global_name (struct Wlclock *clock, uint32_t name) +{ + struct Wlclock_output *op; + wl_list_for_each(op, &clock->outputs, link) + if ( op->global_name == name ) + return op; + return NULL; +} + +void destroy_output (struct Wlclock_output *output) +{ + if ( output == NULL ) + return; + if ( output->surface != NULL ) + destroy_surface(output->surface); + wl_list_remove(&output->link); + wl_output_destroy(output->wl_output); + free(output); +} + +void destroy_all_outputs (struct Wlclock *clock) +{ + clocklog(clock, 1, "[output] Destroying all outputs.\n"); + struct Wlclock_output *op, *tmp; + wl_list_for_each_safe(op, tmp, &clock->outputs, link) + destroy_output(op); +} + |