blob: 5d928f54a674158ddb79f044f0a6b2637c5b3ae5 [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;
Rob Bradford14a76012013-05-31 18:09:52 +010087 char *name;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020088};
89
90struct weston_info {
91 struct wl_display *display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -040092 struct wl_registry *registry;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020093
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020094 struct wl_list infos;
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +020095 bool roundtrip_needed;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020096};
97
Kristian Høgsberg06b16c22013-08-15 14:20:53 -070098static void *
99xmalloc(size_t s)
100{
101 void *p = malloc(s);
102
103 if (p == NULL) {
104 fprintf(stderr, "out of memory\n");
105 exit(1);
106 }
107
108 return p;
109}
110
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200111static void
112print_global_info(void *data)
113{
114 struct global_info *global = data;
115
116 printf("interface: '%s', version: %u, name: %u\n",
117 global->interface, global->version, global->id);
118}
119
120static void
121init_global_info(struct weston_info *info,
122 struct global_info *global, uint32_t id,
123 const char *interface, uint32_t version)
124{
125 global->id = id;
126 global->version = version;
127 global->interface = strdup(interface);
128
129 wl_list_insert(info->infos.prev, &global->link);
130}
131
132static void
133print_output_info(void *data)
134{
135 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200136 struct output_mode *mode;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200137 const char *subpixel_orientation;
138 const char *transform;
139
140 print_global_info(data);
141
142 switch (output->geometry.subpixel) {
143 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
144 subpixel_orientation = "unknown";
145 break;
146 case WL_OUTPUT_SUBPIXEL_NONE:
147 subpixel_orientation = "none";
148 break;
149 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
150 subpixel_orientation = "horizontal rgb";
151 break;
152 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
153 subpixel_orientation = "horizontal bgr";
154 break;
155 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
156 subpixel_orientation = "vertical rgb";
157 break;
158 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
159 subpixel_orientation = "vertical bgr";
160 break;
161 default:
162 fprintf(stderr, "unknown subpixel orientation %u\n",
163 output->geometry.subpixel);
164 subpixel_orientation = "unexpected value";
165 break;
166 }
167
168 switch (output->geometry.output_transform) {
169 case WL_OUTPUT_TRANSFORM_NORMAL:
170 transform = "normal";
171 break;
172 case WL_OUTPUT_TRANSFORM_90:
173 transform = "90°";
174 break;
175 case WL_OUTPUT_TRANSFORM_180:
176 transform = "180°";
177 break;
178 case WL_OUTPUT_TRANSFORM_270:
179 transform = "270°";
180 break;
181 case WL_OUTPUT_TRANSFORM_FLIPPED:
182 transform = "flipped";
183 break;
184 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
185 transform = "flipped 90°";
186 break;
187 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
188 transform = "flipped 180°";
189 break;
190 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
191 transform = "flipped 270°";
192 break;
193 default:
194 fprintf(stderr, "unknown output transform %u\n",
195 output->geometry.output_transform);
196 transform = "unexpected value";
197 break;
198 }
199
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200200 printf("\tx: %d, y: %d,\n",
201 output->geometry.x, output->geometry.y);
202 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200203 output->geometry.physical_width,
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200204 output->geometry.physical_height);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200205 printf("\tmake: '%s', model: '%s',\n",
206 output->geometry.make, output->geometry.model);
207 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
208 subpixel_orientation, transform);
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200209
210 wl_list_for_each(mode, &output->modes, link) {
211 printf("\tmode:\n");
212
213 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
214 mode->width, mode->height,
215 (float) mode->refresh / 1000);
216
217 printf("\t\tflags:");
218 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
219 printf(" current");
220 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
221 printf(" preferred");
222 printf("\n");
223 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200224}
225
226static void
227print_shm_info(void *data)
228{
229 struct shm_info *shm = data;
230 struct shm_format *format;
231
232 print_global_info(data);
233
234 printf("\tformats:");
235
236 wl_list_for_each(format, &shm->formats, link)
237 printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
238 "ARGB8888" : "XRGB8888");
239
240 printf("\n");
241}
242
243static void
244print_seat_info(void *data)
245{
246 struct seat_info *seat = data;
247
248 print_global_info(data);
249
Rob Bradford14a76012013-05-31 18:09:52 +0100250 printf("\tname: %s\n", seat->name);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200251 printf("\tcapabilities:");
252
253 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
254 printf(" pointer");
255 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
256 printf(" keyboard");
257 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
258 printf(" touch");
259
260 printf("\n");
261}
262
263static void
264seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
265 enum wl_seat_capability caps)
266{
267 struct seat_info *seat = data;
268 seat->capabilities = caps;
269}
270
Rob Bradford14a76012013-05-31 18:09:52 +0100271static void
272seat_handle_name(void *data, struct wl_seat *wl_seat,
273 const char *name)
274{
275 struct seat_info *seat = data;
276 seat->name = strdup(name);
277}
278
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200279static const struct wl_seat_listener seat_listener = {
280 seat_handle_capabilities,
Rob Bradford14a76012013-05-31 18:09:52 +0100281 seat_handle_name,
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200282};
283
284static void
285add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
286{
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700287 struct seat_info *seat = xmalloc(sizeof *seat);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200288
289 init_global_info(info, &seat->global, id, "wl_seat", version);
290 seat->global.print = print_seat_info;
291
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400292 seat->seat = wl_registry_bind(info->registry,
Rob Bradford14a76012013-05-31 18:09:52 +0100293 id, &wl_seat_interface, 2);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200294 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200295
296 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200297}
298
299static void
300shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
301{
302 struct shm_info *shm = data;
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700303 struct shm_format *shm_format = xmalloc(sizeof *shm_format);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200304
305 wl_list_insert(&shm->formats, &shm_format->link);
306 shm_format->format = format;
307}
308
309static const struct wl_shm_listener shm_listener = {
310 shm_handle_format,
311};
312
313static void
314add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
315{
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700316 struct shm_info *shm = xmalloc(sizeof *shm);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200317
318 init_global_info(info, &shm->global, id, "wl_shm", version);
319 shm->global.print = print_shm_info;
320 wl_list_init(&shm->formats);
321
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400322 shm->shm = wl_registry_bind(info->registry,
323 id, &wl_shm_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200324 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200325
326 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200327}
328
329static void
330output_handle_geometry(void *data, struct wl_output *wl_output,
331 int32_t x, int32_t y,
332 int32_t physical_width, int32_t physical_height,
333 int32_t subpixel,
334 const char *make, const char *model,
335 int32_t output_transform)
336{
337 struct output_info *output = data;
338
339 output->geometry.x = x;
340 output->geometry.y = y;
341 output->geometry.physical_width = physical_width;
342 output->geometry.physical_height = physical_height;
343 output->geometry.subpixel = subpixel;
344 output->geometry.make = strdup(make);
345 output->geometry.model = strdup(model);
346 output->geometry.output_transform = output_transform;
347}
348
349static void
350output_handle_mode(void *data, struct wl_output *wl_output,
351 uint32_t flags, int32_t width, int32_t height,
352 int32_t refresh)
353{
354 struct output_info *output = data;
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700355 struct output_mode *mode = xmalloc(sizeof *mode);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200356
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200357 mode->flags = flags;
358 mode->width = width;
359 mode->height = height;
360 mode->refresh = refresh;
361
362 wl_list_insert(output->modes.prev, &mode->link);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200363}
364
365static const struct wl_output_listener output_listener = {
366 output_handle_geometry,
367 output_handle_mode,
368};
369
370static void
371add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
372{
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700373 struct output_info *output = xmalloc(sizeof *output);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200374
375 init_global_info(info, &output->global, id, "wl_output", version);
376 output->global.print = print_output_info;
377
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200378 wl_list_init(&output->modes);
379
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400380 output->output = wl_registry_bind(info->registry, id,
381 &wl_output_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200382 wl_output_add_listener(output->output, &output_listener,
383 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200384
385 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200386}
387
388static void
389add_global_info(struct weston_info *info, uint32_t id,
390 const char *interface, uint32_t version)
391{
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700392 struct global_info *global = xmalloc(sizeof *global);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200393
394 init_global_info(info, global, id, interface, version);
395 global->print = print_global_info;
396}
397
398static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400399global_handler(void *data, struct wl_registry *registry, uint32_t id,
400 const char *interface, uint32_t version)
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200401{
402 struct weston_info *info = data;
403
404 if (!strcmp(interface, "wl_seat"))
405 add_seat_info(info, id, version);
406 else if (!strcmp(interface, "wl_shm"))
407 add_shm_info(info, id, version);
408 else if (!strcmp(interface, "wl_output"))
409 add_output_info(info, id, version);
410 else
411 add_global_info(info, id, interface, version);
412}
413
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200414static void
415global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
416{
417}
418
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400419static const struct wl_registry_listener registry_listener = {
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200420 global_handler,
421 global_remove_handler
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400422};
423
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200424static void
425print_infos(struct wl_list *infos)
426{
427 struct global_info *info;
428
429 wl_list_for_each(info, infos, link)
430 info->print(info);
431}
432
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200433int
434main(int argc, char **argv)
435{
436 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200437
438 info.display = wl_display_connect(NULL);
439 if (!info.display) {
440 fprintf(stderr, "failed to create display: %m\n");
441 return -1;
442 }
443
444 wl_list_init(&info.infos);
445
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400446 info.registry = wl_display_get_registry(info.display);
447 wl_registry_add_listener(info.registry, &registry_listener, &info);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200448
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200449 do {
450 info.roundtrip_needed = false;
451 wl_display_roundtrip(info.display);
452 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200453
454 print_infos(&info.infos);
455
456 return 0;
457}