2 * Copyright © 2012 Philipp Brüschweiler
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.
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.
31 #include <wayland-client.h>
33 #include "../shared/os-compatibility.h"
35 typedef void (*print_info_t)(void *info);
36 typedef void (*destroy_info_t)(void *info);
46 destroy_info_t destroy;
53 int32_t width, height;
58 struct global_info global;
60 struct wl_output *output;
64 int32_t physical_width, physical_height;
65 enum wl_output_subpixel subpixel;
66 enum wl_output_transform output_transform;
81 struct global_info global;
84 struct wl_list formats;
88 struct global_info global;
91 uint32_t capabilities;
96 struct wl_display *display;
97 struct wl_registry *registry;
100 bool roundtrip_needed;
104 fail_on_null(void *p)
107 fprintf(stderr, "%s: out of memory\n", program_invocation_short_name);
117 return fail_on_null(malloc(s));
123 return fail_on_null(calloc(1, s));
127 xstrdup(const char *s)
129 return fail_on_null(strdup(s));
133 print_global_info(void *data)
135 struct global_info *global = data;
137 printf("interface: '%s', version: %u, name: %u\n",
138 global->interface, global->version, global->id);
142 init_global_info(struct weston_info *info,
143 struct global_info *global, uint32_t id,
144 const char *interface, uint32_t version)
147 global->version = version;
148 global->interface = xstrdup(interface);
150 wl_list_insert(info->infos.prev, &global->link);
154 print_output_info(void *data)
156 struct output_info *output = data;
157 struct output_mode *mode;
158 const char *subpixel_orientation;
159 const char *transform;
161 print_global_info(data);
163 switch (output->geometry.subpixel) {
164 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
165 subpixel_orientation = "unknown";
167 case WL_OUTPUT_SUBPIXEL_NONE:
168 subpixel_orientation = "none";
170 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
171 subpixel_orientation = "horizontal rgb";
173 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
174 subpixel_orientation = "horizontal bgr";
176 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
177 subpixel_orientation = "vertical rgb";
179 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
180 subpixel_orientation = "vertical bgr";
183 fprintf(stderr, "unknown subpixel orientation %u\n",
184 output->geometry.subpixel);
185 subpixel_orientation = "unexpected value";
189 switch (output->geometry.output_transform) {
190 case WL_OUTPUT_TRANSFORM_NORMAL:
191 transform = "normal";
193 case WL_OUTPUT_TRANSFORM_90:
196 case WL_OUTPUT_TRANSFORM_180:
199 case WL_OUTPUT_TRANSFORM_270:
202 case WL_OUTPUT_TRANSFORM_FLIPPED:
203 transform = "flipped";
205 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
206 transform = "flipped 90°";
208 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
209 transform = "flipped 180°";
211 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
212 transform = "flipped 270°";
215 fprintf(stderr, "unknown output transform %u\n",
216 output->geometry.output_transform);
217 transform = "unexpected value";
221 printf("\tx: %d, y: %d,\n",
222 output->geometry.x, output->geometry.y);
223 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
224 output->geometry.physical_width,
225 output->geometry.physical_height);
226 printf("\tmake: '%s', model: '%s',\n",
227 output->geometry.make, output->geometry.model);
228 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
229 subpixel_orientation, transform);
231 wl_list_for_each(mode, &output->modes, link) {
234 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
235 mode->width, mode->height,
236 (float) mode->refresh / 1000);
238 printf("\t\tflags:");
239 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
241 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
242 printf(" preferred");
248 print_shm_info(void *data)
250 struct shm_info *shm = data;
251 struct shm_format *format;
253 print_global_info(data);
255 printf("\tformats:");
257 wl_list_for_each(format, &shm->formats, link)
258 switch (format->format) {
259 case WL_SHM_FORMAT_ARGB8888:
262 case WL_SHM_FORMAT_XRGB8888:
265 case WL_SHM_FORMAT_RGB565:
269 printf(" unknown(%08x)", format->format);
277 print_seat_info(void *data)
279 struct seat_info *seat = data;
281 print_global_info(data);
283 printf("\tname: %s\n", seat->name);
284 printf("\tcapabilities:");
286 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
288 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
290 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
297 seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
298 enum wl_seat_capability caps)
300 struct seat_info *seat = data;
301 seat->capabilities = caps;
305 seat_handle_name(void *data, struct wl_seat *wl_seat,
308 struct seat_info *seat = data;
309 seat->name = xstrdup(name);
312 static const struct wl_seat_listener seat_listener = {
313 seat_handle_capabilities,
318 destroy_seat_info(void *data)
320 struct seat_info *seat = data;
322 wl_seat_destroy(seat->seat);
324 if (seat->name != NULL)
329 add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
331 struct seat_info *seat = xzalloc(sizeof *seat);
333 init_global_info(info, &seat->global, id, "wl_seat", version);
334 seat->global.print = print_seat_info;
335 seat->global.destroy = destroy_seat_info;
337 seat->seat = wl_registry_bind(info->registry,
338 id, &wl_seat_interface, 2);
339 wl_seat_add_listener(seat->seat, &seat_listener, seat);
341 info->roundtrip_needed = true;
345 shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
347 struct shm_info *shm = data;
348 struct shm_format *shm_format = xzalloc(sizeof *shm_format);
350 wl_list_insert(&shm->formats, &shm_format->link);
351 shm_format->format = format;
354 static const struct wl_shm_listener shm_listener = {
359 destroy_shm_info(void *data)
361 struct shm_info *shm = data;
362 struct shm_format *format, *tmp;
364 wl_list_for_each_safe(format, tmp, &shm->formats, link) {
365 wl_list_remove(&format->link);
369 wl_shm_destroy(shm->shm);
373 add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
375 struct shm_info *shm = xzalloc(sizeof *shm);
377 init_global_info(info, &shm->global, id, "wl_shm", version);
378 shm->global.print = print_shm_info;
379 shm->global.destroy = destroy_shm_info;
381 wl_list_init(&shm->formats);
383 shm->shm = wl_registry_bind(info->registry,
384 id, &wl_shm_interface, 1);
385 wl_shm_add_listener(shm->shm, &shm_listener, shm);
387 info->roundtrip_needed = true;
391 output_handle_geometry(void *data, struct wl_output *wl_output,
392 int32_t x, int32_t y,
393 int32_t physical_width, int32_t physical_height,
395 const char *make, const char *model,
396 int32_t output_transform)
398 struct output_info *output = data;
400 output->geometry.x = x;
401 output->geometry.y = y;
402 output->geometry.physical_width = physical_width;
403 output->geometry.physical_height = physical_height;
404 output->geometry.subpixel = subpixel;
405 output->geometry.make = xstrdup(make);
406 output->geometry.model = xstrdup(model);
407 output->geometry.output_transform = output_transform;
411 output_handle_mode(void *data, struct wl_output *wl_output,
412 uint32_t flags, int32_t width, int32_t height,
415 struct output_info *output = data;
416 struct output_mode *mode = xmalloc(sizeof *mode);
420 mode->height = height;
421 mode->refresh = refresh;
423 wl_list_insert(output->modes.prev, &mode->link);
426 static const struct wl_output_listener output_listener = {
427 output_handle_geometry,
432 destroy_output_info(void *data)
434 struct output_info *output = data;
435 struct output_mode *mode, *tmp;
437 wl_output_destroy(output->output);
439 if (output->geometry.make != NULL)
440 free(output->geometry.make);
441 if (output->geometry.model != NULL)
442 free(output->geometry.model);
444 wl_list_for_each_safe(mode, tmp, &output->modes, link) {
445 wl_list_remove(&mode->link);
451 add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
453 struct output_info *output = xzalloc(sizeof *output);
455 init_global_info(info, &output->global, id, "wl_output", version);
456 output->global.print = print_output_info;
457 output->global.destroy = destroy_output_info;
459 wl_list_init(&output->modes);
461 output->output = wl_registry_bind(info->registry, id,
462 &wl_output_interface, 1);
463 wl_output_add_listener(output->output, &output_listener,
466 info->roundtrip_needed = true;
470 destroy_global_info(void *data)
475 add_global_info(struct weston_info *info, uint32_t id,
476 const char *interface, uint32_t version)
478 struct global_info *global = xzalloc(sizeof *global);
480 init_global_info(info, global, id, interface, version);
481 global->print = print_global_info;
482 global->destroy = destroy_global_info;
486 global_handler(void *data, struct wl_registry *registry, uint32_t id,
487 const char *interface, uint32_t version)
489 struct weston_info *info = data;
491 if (!strcmp(interface, "wl_seat"))
492 add_seat_info(info, id, version);
493 else if (!strcmp(interface, "wl_shm"))
494 add_shm_info(info, id, version);
495 else if (!strcmp(interface, "wl_output"))
496 add_output_info(info, id, version);
498 add_global_info(info, id, interface, version);
502 global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
506 static const struct wl_registry_listener registry_listener = {
508 global_remove_handler
512 print_infos(struct wl_list *infos)
514 struct global_info *info;
516 wl_list_for_each(info, infos, link)
521 destroy_info(void *data)
523 struct global_info *global = data;
525 global->destroy(data);
526 wl_list_remove(&global->link);
527 free(global->interface);
532 destroy_infos(struct wl_list *infos)
534 struct global_info *info, *tmp;
535 wl_list_for_each_safe(info, tmp, infos, link)
540 main(int argc, char **argv)
542 struct weston_info info;
544 info.display = wl_display_connect(NULL);
546 fprintf(stderr, "failed to create display: %m\n");
550 wl_list_init(&info.infos);
552 info.registry = wl_display_get_registry(info.display);
553 wl_registry_add_listener(info.registry, ®istry_listener, &info);
556 info.roundtrip_needed = false;
557 wl_display_roundtrip(info.display);
558 } while (info.roundtrip_needed);
560 print_infos(&info.infos);
561 destroy_infos(&info.infos);
563 wl_registry_destroy(info.registry);
564 wl_display_disconnect(info.display);