blob: edd826e05333164fb67f8fe709aa6f2f8f5b38ae [file] [log] [blame]
Philipp Brüschweiler585acb02012-08-15 17:12:00 +02001/*
2 * Copyright © 2012 Philipp Brüschweiler
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdbool.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020027
28#include <wayland-client.h>
29
30#include "../shared/os-compatibility.h"
31
32typedef void (*print_info_t)(void *info);
33
34struct global_info {
35 struct wl_list link;
36
37 uint32_t id;
38 uint32_t version;
39 char *interface;
40
41 print_info_t print;
42};
43
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +020044struct output_mode {
45 struct wl_list link;
46
47 uint32_t flags;
48 int32_t width, height;
49 int32_t refresh;
50};
51
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020052struct output_info {
53 struct global_info global;
54
55 struct wl_output *output;
56
57 struct {
58 int32_t x, y;
59 int32_t physical_width, physical_height;
60 enum wl_output_subpixel subpixel;
61 enum wl_output_transform output_transform;
62 char *make;
63 char *model;
64 } geometry;
65
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +020066 struct wl_list modes;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020067};
68
69struct shm_format {
70 struct wl_list link;
71
72 uint32_t format;
73};
74
75struct shm_info {
76 struct global_info global;
77 struct wl_shm *shm;
78
79 struct wl_list formats;
80};
81
82struct seat_info {
83 struct global_info global;
84 struct wl_seat *seat;
85
86 uint32_t capabilities;
87};
88
89struct weston_info {
90 struct wl_display *display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -040091 struct wl_registry *registry;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020092
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020093 struct wl_list infos;
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +020094 bool roundtrip_needed;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020095};
96
97static void
98print_global_info(void *data)
99{
100 struct global_info *global = data;
101
102 printf("interface: '%s', version: %u, name: %u\n",
103 global->interface, global->version, global->id);
104}
105
106static void
107init_global_info(struct weston_info *info,
108 struct global_info *global, uint32_t id,
109 const char *interface, uint32_t version)
110{
111 global->id = id;
112 global->version = version;
113 global->interface = strdup(interface);
114
115 wl_list_insert(info->infos.prev, &global->link);
116}
117
118static void
119print_output_info(void *data)
120{
121 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200122 struct output_mode *mode;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200123 const char *subpixel_orientation;
124 const char *transform;
125
126 print_global_info(data);
127
128 switch (output->geometry.subpixel) {
129 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
130 subpixel_orientation = "unknown";
131 break;
132 case WL_OUTPUT_SUBPIXEL_NONE:
133 subpixel_orientation = "none";
134 break;
135 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
136 subpixel_orientation = "horizontal rgb";
137 break;
138 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
139 subpixel_orientation = "horizontal bgr";
140 break;
141 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
142 subpixel_orientation = "vertical rgb";
143 break;
144 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
145 subpixel_orientation = "vertical bgr";
146 break;
147 default:
148 fprintf(stderr, "unknown subpixel orientation %u\n",
149 output->geometry.subpixel);
150 subpixel_orientation = "unexpected value";
151 break;
152 }
153
154 switch (output->geometry.output_transform) {
155 case WL_OUTPUT_TRANSFORM_NORMAL:
156 transform = "normal";
157 break;
158 case WL_OUTPUT_TRANSFORM_90:
159 transform = "90°";
160 break;
161 case WL_OUTPUT_TRANSFORM_180:
162 transform = "180°";
163 break;
164 case WL_OUTPUT_TRANSFORM_270:
165 transform = "270°";
166 break;
167 case WL_OUTPUT_TRANSFORM_FLIPPED:
168 transform = "flipped";
169 break;
170 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
171 transform = "flipped 90°";
172 break;
173 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
174 transform = "flipped 180°";
175 break;
176 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
177 transform = "flipped 270°";
178 break;
179 default:
180 fprintf(stderr, "unknown output transform %u\n",
181 output->geometry.output_transform);
182 transform = "unexpected value";
183 break;
184 }
185
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200186 printf("\tx: %d, y: %d,\n",
187 output->geometry.x, output->geometry.y);
188 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200189 output->geometry.physical_width,
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200190 output->geometry.physical_height);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200191 printf("\tmake: '%s', model: '%s',\n",
192 output->geometry.make, output->geometry.model);
193 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
194 subpixel_orientation, transform);
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200195
196 wl_list_for_each(mode, &output->modes, link) {
197 printf("\tmode:\n");
198
199 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
200 mode->width, mode->height,
201 (float) mode->refresh / 1000);
202
203 printf("\t\tflags:");
204 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
205 printf(" current");
206 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
207 printf(" preferred");
208 printf("\n");
209 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200210}
211
212static void
213print_shm_info(void *data)
214{
215 struct shm_info *shm = data;
216 struct shm_format *format;
217
218 print_global_info(data);
219
220 printf("\tformats:");
221
222 wl_list_for_each(format, &shm->formats, link)
223 printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
224 "ARGB8888" : "XRGB8888");
225
226 printf("\n");
227}
228
229static void
230print_seat_info(void *data)
231{
232 struct seat_info *seat = data;
233
234 print_global_info(data);
235
236 printf("\tcapabilities:");
237
238 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
239 printf(" pointer");
240 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
241 printf(" keyboard");
242 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
243 printf(" touch");
244
245 printf("\n");
246}
247
248static void
249seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
250 enum wl_seat_capability caps)
251{
252 struct seat_info *seat = data;
253 seat->capabilities = caps;
254}
255
256static const struct wl_seat_listener seat_listener = {
257 seat_handle_capabilities,
258};
259
260static void
261add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
262{
263 struct seat_info *seat = malloc(sizeof *seat);
264
265 init_global_info(info, &seat->global, id, "wl_seat", version);
266 seat->global.print = print_seat_info;
267
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400268 seat->seat = wl_registry_bind(info->registry,
269 id, &wl_seat_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200270 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200271
272 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200273}
274
275static void
276shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
277{
278 struct shm_info *shm = data;
279 struct shm_format *shm_format = malloc(sizeof *shm_format);
280
281 wl_list_insert(&shm->formats, &shm_format->link);
282 shm_format->format = format;
283}
284
285static const struct wl_shm_listener shm_listener = {
286 shm_handle_format,
287};
288
289static void
290add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
291{
292 struct shm_info *shm = malloc(sizeof *shm);
293
294 init_global_info(info, &shm->global, id, "wl_shm", version);
295 shm->global.print = print_shm_info;
296 wl_list_init(&shm->formats);
297
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400298 shm->shm = wl_registry_bind(info->registry,
299 id, &wl_shm_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200300 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200301
302 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200303}
304
305static void
306output_handle_geometry(void *data, struct wl_output *wl_output,
307 int32_t x, int32_t y,
308 int32_t physical_width, int32_t physical_height,
309 int32_t subpixel,
310 const char *make, const char *model,
311 int32_t output_transform)
312{
313 struct output_info *output = data;
314
315 output->geometry.x = x;
316 output->geometry.y = y;
317 output->geometry.physical_width = physical_width;
318 output->geometry.physical_height = physical_height;
319 output->geometry.subpixel = subpixel;
320 output->geometry.make = strdup(make);
321 output->geometry.model = strdup(model);
322 output->geometry.output_transform = output_transform;
323}
324
325static void
326output_handle_mode(void *data, struct wl_output *wl_output,
327 uint32_t flags, int32_t width, int32_t height,
328 int32_t refresh)
329{
330 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200331 struct output_mode *mode = malloc(sizeof *mode);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200332
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200333 mode->flags = flags;
334 mode->width = width;
335 mode->height = height;
336 mode->refresh = refresh;
337
338 wl_list_insert(output->modes.prev, &mode->link);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200339}
340
341static const struct wl_output_listener output_listener = {
342 output_handle_geometry,
343 output_handle_mode,
344};
345
346static void
347add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
348{
349 struct output_info *output = malloc(sizeof *output);
350
351 init_global_info(info, &output->global, id, "wl_output", version);
352 output->global.print = print_output_info;
353
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200354 wl_list_init(&output->modes);
355
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400356 output->output = wl_registry_bind(info->registry, id,
357 &wl_output_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200358 wl_output_add_listener(output->output, &output_listener,
359 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200360
361 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200362}
363
364static void
365add_global_info(struct weston_info *info, uint32_t id,
366 const char *interface, uint32_t version)
367{
368 struct global_info *global = malloc(sizeof *global);
369
370 init_global_info(info, global, id, interface, version);
371 global->print = print_global_info;
372}
373
374static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400375global_handler(void *data, struct wl_registry *registry, uint32_t id,
376 const char *interface, uint32_t version)
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200377{
378 struct weston_info *info = data;
379
380 if (!strcmp(interface, "wl_seat"))
381 add_seat_info(info, id, version);
382 else if (!strcmp(interface, "wl_shm"))
383 add_shm_info(info, id, version);
384 else if (!strcmp(interface, "wl_output"))
385 add_output_info(info, id, version);
386 else
387 add_global_info(info, id, interface, version);
388}
389
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400390static const struct wl_registry_listener registry_listener = {
391 global_handler
392};
393
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200394static void
395print_infos(struct wl_list *infos)
396{
397 struct global_info *info;
398
399 wl_list_for_each(info, infos, link)
400 info->print(info);
401}
402
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200403int
404main(int argc, char **argv)
405{
406 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200407
408 info.display = wl_display_connect(NULL);
409 if (!info.display) {
410 fprintf(stderr, "failed to create display: %m\n");
411 return -1;
412 }
413
414 wl_list_init(&info.infos);
415
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400416 info.registry = wl_display_get_registry(info.display);
417 wl_registry_add_listener(info.registry, &registry_listener, &info);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200418
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200419 do {
420 info.roundtrip_needed = false;
421 wl_display_roundtrip(info.display);
422 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200423
424 print_infos(&info.infos);
425
426 return 0;
427}