diff options
Diffstat (limited to 'uwac/libuwac/uwac-output.c')
-rw-r--r-- | uwac/libuwac/uwac-output.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/uwac/libuwac/uwac-output.c b/uwac/libuwac/uwac-output.c new file mode 100644 index 0000000..079018e --- /dev/null +++ b/uwac/libuwac/uwac-output.c @@ -0,0 +1,183 @@ +/* + * Copyright © 2014 David FORT <contact@hardening-consulting.com> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#define TARGET_OUTPUT_INTERFACE 2U + +static bool dupstr(char** dst, const char* src) +{ + assert(dst); + free(*dst); + *dst = NULL; + if (!src) + return true; + *dst = strdup(src); + return *dst != NULL; +} + +static void output_handle_geometry(void* data, struct wl_output* wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char* make, const char* model, int transform) +{ + UwacOutput* output = data; + assert(output); + + output->position.x = x; + output->position.y = y; + output->transform = transform; + + if (!dupstr(&output->make, make)) + { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", + __func__)); + } + + if (!dupstr(&output->model, model)) + { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, + "%s: unable to strdup model\n", __func__)); + } + + UwacEvent* event = UwacDisplayNewEvent(output->display, UWAC_EVENT_OUTPUT_GEOMETRY); + event->output_geometry.output = output; + event->output_geometry.x = x; + event->output_geometry.y = y; + event->output_geometry.physical_width = physical_width; + event->output_geometry.physical_height = physical_height; + event->output_geometry.subpixel = subpixel; + event->output_geometry.make = output->make; + event->output_geometry.model = output->model; + event->output_geometry.transform = transform; +} + +static void output_handle_done(void* data, struct wl_output* wl_output) +{ + UwacOutput* output = data; + assert(output); + + output->doneReceived = true; +} + +static void output_handle_scale(void* data, struct wl_output* wl_output, int32_t scale) +{ + UwacOutput* output = data; + assert(output); + + output->scale = scale; + if (scale > output->display->actual_scale) + output->display->actual_scale = scale; +} + +static void output_handle_name(void* data, struct wl_output* wl_output, const char* name) +{ + UwacOutput* output = data; + assert(output); + + if (!dupstr(&output->name, name)) + { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", + __func__)); + } +} + +static void output_handle_description(void* data, struct wl_output* wl_output, + const char* description) +{ + UwacOutput* output = data; + assert(output); + + if (!dupstr(&output->description, description)) + { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", + __func__)); + } +} + +static void output_handle_mode(void* data, struct wl_output* wl_output, uint32_t flags, int width, + int height, int refresh) +{ + UwacOutput* output = data; + assert(output); + // UwacDisplay *display = output->display; + + if (output->doneNeeded && output->doneReceived) + { + /* TODO: we should clear the mode list */ + } + + if (flags & WL_OUTPUT_MODE_CURRENT) + { + output->resolution.width = width; + output->resolution.height = height; + /* output->allocation.width = width; + output->allocation.height = height; + if (display->output_configure_handler) + (*display->output_configure_handler)( + output, display->user_data);*/ + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, output_handle_mode, output_handle_done, + output_handle_scale, output_handle_name, output_handle_description +}; + +UwacOutput* UwacCreateOutput(UwacDisplay* d, uint32_t id, uint32_t version) +{ + UwacOutput* o = xzalloc(sizeof *o); + if (!o) + return NULL; + + o->display = d; + o->server_output_id = id; + o->doneNeeded = (version > 1); + o->doneReceived = false; + o->output = wl_registry_bind(d->registry, id, &wl_output_interface, + min(TARGET_OUTPUT_INTERFACE, version)); + wl_output_add_listener(o->output, &output_listener, o); + + wl_list_insert(d->outputs.prev, &o->link); + return o; +} + +int UwacDestroyOutput(UwacOutput* output) +{ + if (!output) + return UWAC_SUCCESS; + + free(output->make); + free(output->model); + free(output->name); + free(output->description); + + wl_output_destroy(output->output); + wl_list_remove(&output->link); + free(output); + + return UWAC_SUCCESS; +} |