/* * Copyright © 2014 David FORT * * 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 #include #include #include #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; }