FreeRDP
uwac-output.c
1 /*
2  * Copyright © 2014 David FORT <contact@hardening-consulting.com>
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission. The copyright holders make no representations
11  * about the suitability of this software for any purpose. It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22 #include "uwac-priv.h"
23 #include "uwac-utils.h"
24 
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 
30 #define TARGET_OUTPUT_INTERFACE 2U
31 
32 static bool dupstr(char** dst, const char* src)
33 {
34  assert(dst);
35  free(*dst);
36  *dst = NULL;
37  if (!src)
38  return true;
39  *dst = strdup(src);
40  return *dst != NULL;
41 }
42 
43 static void output_handle_geometry(void* data, struct wl_output* wl_output, int x, int y,
44  int physical_width, int physical_height, int subpixel,
45  const char* make, const char* model, int transform)
46 {
47  UwacOutput* output = data;
48  assert(output);
49 
50  output->position.x = x;
51  output->position.y = y;
52  output->transform = transform;
53 
54  if (!dupstr(&output->make, make))
55  {
56  assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n",
57  __func__));
58  }
59 
60  if (!dupstr(&output->model, model))
61  {
62  assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY,
63  "%s: unable to strdup model\n", __func__));
64  }
65 
66  UwacEvent* event = UwacDisplayNewEvent(output->display, UWAC_EVENT_OUTPUT_GEOMETRY);
67  event->output_geometry.output = output;
68  event->output_geometry.x = x;
69  event->output_geometry.y = y;
70  event->output_geometry.physical_width = physical_width;
71  event->output_geometry.physical_height = physical_height;
72  event->output_geometry.subpixel = subpixel;
73  event->output_geometry.make = output->make;
74  event->output_geometry.model = output->model;
75  event->output_geometry.transform = transform;
76 }
77 
78 static void output_handle_done(void* data, struct wl_output* wl_output)
79 {
80  UwacOutput* output = data;
81  assert(output);
82 
83  output->doneReceived = true;
84 }
85 
86 static void output_handle_scale(void* data, struct wl_output* wl_output, int32_t scale)
87 {
88  UwacOutput* output = data;
89  assert(output);
90 
91  output->scale = scale;
92  if (scale > output->display->actual_scale)
93  output->display->actual_scale = scale;
94 }
95 
96 static void output_handle_name(void* data, struct wl_output* wl_output, const char* name)
97 {
98  UwacOutput* output = data;
99  assert(output);
100 
101  if (!dupstr(&output->name, name))
102  {
103  assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n",
104  __func__));
105  }
106 }
107 
108 static void output_handle_description(void* data, struct wl_output* wl_output,
109  const char* description)
110 {
111  UwacOutput* output = data;
112  assert(output);
113 
114  if (!dupstr(&output->description, description))
115  {
116  assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n",
117  __func__));
118  }
119 }
120 
121 static void output_handle_mode(void* data, struct wl_output* wl_output, uint32_t flags, int width,
122  int height, int refresh)
123 {
124  UwacOutput* output = data;
125  assert(output);
126  // UwacDisplay *display = output->display;
127 
128  if (output->doneNeeded && output->doneReceived)
129  {
130  /* TODO: we should clear the mode list */
131  }
132 
133  if (flags & WL_OUTPUT_MODE_CURRENT)
134  {
135  output->resolution.width = width;
136  output->resolution.height = height;
137  /* output->allocation.width = width;
138  output->allocation.height = height;
139  if (display->output_configure_handler)
140  (*display->output_configure_handler)(
141  output, display->user_data);*/
142  }
143 }
144 
145 static const struct wl_output_listener output_listener = {
146  output_handle_geometry, output_handle_mode, output_handle_done,
147  output_handle_scale, output_handle_name, output_handle_description
148 };
149 
150 UwacOutput* UwacCreateOutput(UwacDisplay* d, uint32_t id, uint32_t version)
151 {
152  UwacOutput* o = xzalloc(sizeof *o);
153  if (!o)
154  return NULL;
155 
156  o->display = d;
157  o->server_output_id = id;
158  o->doneNeeded = (version > 1);
159  o->doneReceived = false;
160  o->output = wl_registry_bind(d->registry, id, &wl_output_interface,
161  min(TARGET_OUTPUT_INTERFACE, version));
162  wl_output_add_listener(o->output, &output_listener, o);
163 
164  wl_list_insert(d->outputs.prev, &o->link);
165  return o;
166 }
167 
168 int UwacDestroyOutput(UwacOutput* output)
169 {
170  if (!output)
171  return UWAC_SUCCESS;
172 
173  free(output->make);
174  free(output->model);
175  free(output->name);
176  free(output->description);
177 
178  wl_output_destroy(output->output);
179  wl_list_remove(&output->link);
180  free(output);
181 
182  return UWAC_SUCCESS;
183 }