blob: 03b4c40118ed1374d35261dc92f11a6e2e73fc3c [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
98static void
99print_global_info(void *data)
100{
101 struct global_info *global = data;
102
103 printf("interface: '%s', version: %u, name: %u\n",
104 global->interface, global->version, global->id);
105}
106
107static void
108init_global_info(struct weston_info *info,
109 struct global_info *global, uint32_t id,
110 const char *interface, uint32_t version)
111{
112 global->id = id;
113 global->version = version;
114 global->interface = strdup(interface);
115
116 wl_list_insert(info->infos.prev, &global->link);
117}
118
119static void
120print_output_info(void *data)
121{
122 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200123 struct output_mode *mode;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200124 const char *subpixel_orientation;
125 const char *transform;
126
127 print_global_info(data);
128
129 switch (output->geometry.subpixel) {
130 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
131 subpixel_orientation = "unknown";
132 break;
133 case WL_OUTPUT_SUBPIXEL_NONE:
134 subpixel_orientation = "none";
135 break;
136 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
137 subpixel_orientation = "horizontal rgb";
138 break;
139 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
140 subpixel_orientation = "horizontal bgr";
141 break;
142 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
143 subpixel_orientation = "vertical rgb";
144 break;
145 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
146 subpixel_orientation = "vertical bgr";
147 break;
148 default:
149 fprintf(stderr, "unknown subpixel orientation %u\n",
150 output->geometry.subpixel);
151 subpixel_orientation = "unexpected value";
152 break;
153 }
154
155 switch (output->geometry.output_transform) {
156 case WL_OUTPUT_TRANSFORM_NORMAL:
157 transform = "normal";
158 break;
159 case WL_OUTPUT_TRANSFORM_90:
160 transform = "90°";
161 break;
162 case WL_OUTPUT_TRANSFORM_180:
163 transform = "180°";
164 break;
165 case WL_OUTPUT_TRANSFORM_270:
166 transform = "270°";
167 break;
168 case WL_OUTPUT_TRANSFORM_FLIPPED:
169 transform = "flipped";
170 break;
171 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
172 transform = "flipped 90°";
173 break;
174 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
175 transform = "flipped 180°";
176 break;
177 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
178 transform = "flipped 270°";
179 break;
180 default:
181 fprintf(stderr, "unknown output transform %u\n",
182 output->geometry.output_transform);
183 transform = "unexpected value";
184 break;
185 }
186
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200187 printf("\tx: %d, y: %d,\n",
188 output->geometry.x, output->geometry.y);
189 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200190 output->geometry.physical_width,
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200191 output->geometry.physical_height);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200192 printf("\tmake: '%s', model: '%s',\n",
193 output->geometry.make, output->geometry.model);
194 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
195 subpixel_orientation, transform);
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200196
197 wl_list_for_each(mode, &output->modes, link) {
198 printf("\tmode:\n");
199
200 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
201 mode->width, mode->height,
202 (float) mode->refresh / 1000);
203
204 printf("\t\tflags:");
205 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
206 printf(" current");
207 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
208 printf(" preferred");
209 printf("\n");
210 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200211}
212
213static void
214print_shm_info(void *data)
215{
216 struct shm_info *shm = data;
217 struct shm_format *format;
218
219 print_global_info(data);
220
221 printf("\tformats:");
222
223 wl_list_for_each(format, &shm->formats, link)
224 printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
225 "ARGB8888" : "XRGB8888");
226
227 printf("\n");
228}
229
230static void
231print_seat_info(void *data)
232{
233 struct seat_info *seat = data;
234
235 print_global_info(data);
236
Rob Bradford14a76012013-05-31 18:09:52 +0100237 printf("\tname: %s\n", seat->name);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200238 printf("\tcapabilities:");
239
240 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
241 printf(" pointer");
242 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
243 printf(" keyboard");
244 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
245 printf(" touch");
246
247 printf("\n");
248}
249
250static void
251seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
252 enum wl_seat_capability caps)
253{
254 struct seat_info *seat = data;
255 seat->capabilities = caps;
256}
257
Rob Bradford14a76012013-05-31 18:09:52 +0100258static void
259seat_handle_name(void *data, struct wl_seat *wl_seat,
260 const char *name)
261{
262 struct seat_info *seat = data;
263 seat->name = strdup(name);
264}
265
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200266static const struct wl_seat_listener seat_listener = {
267 seat_handle_capabilities,
Rob Bradford14a76012013-05-31 18:09:52 +0100268 seat_handle_name,
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200269};
270
271static void
272add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
273{
274 struct seat_info *seat = malloc(sizeof *seat);
275
276 init_global_info(info, &seat->global, id, "wl_seat", version);
277 seat->global.print = print_seat_info;
278
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400279 seat->seat = wl_registry_bind(info->registry,
Rob Bradford14a76012013-05-31 18:09:52 +0100280 id, &wl_seat_interface, 2);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200281 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200282
283 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200284}
285
286static void
287shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
288{
289 struct shm_info *shm = data;
290 struct shm_format *shm_format = malloc(sizeof *shm_format);
291
292 wl_list_insert(&shm->formats, &shm_format->link);
293 shm_format->format = format;
294}
295
296static const struct wl_shm_listener shm_listener = {
297 shm_handle_format,
298};
299
300static void
301add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
302{
303 struct shm_info *shm = malloc(sizeof *shm);
304
305 init_global_info(info, &shm->global, id, "wl_shm", version);
306 shm->global.print = print_shm_info;
307 wl_list_init(&shm->formats);
308
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400309 shm->shm = wl_registry_bind(info->registry,
310 id, &wl_shm_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200311 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200312
313 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200314}
315
316static void
317output_handle_geometry(void *data, struct wl_output *wl_output,
318 int32_t x, int32_t y,
319 int32_t physical_width, int32_t physical_height,
320 int32_t subpixel,
321 const char *make, const char *model,
322 int32_t output_transform)
323{
324 struct output_info *output = data;
325
326 output->geometry.x = x;
327 output->geometry.y = y;
328 output->geometry.physical_width = physical_width;
329 output->geometry.physical_height = physical_height;
330 output->geometry.subpixel = subpixel;
331 output->geometry.make = strdup(make);
332 output->geometry.model = strdup(model);
333 output->geometry.output_transform = output_transform;
334}
335
336static void
337output_handle_mode(void *data, struct wl_output *wl_output,
338 uint32_t flags, int32_t width, int32_t height,
339 int32_t refresh)
340{
341 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200342 struct output_mode *mode = malloc(sizeof *mode);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200343
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200344 mode->flags = flags;
345 mode->width = width;
346 mode->height = height;
347 mode->refresh = refresh;
348
349 wl_list_insert(output->modes.prev, &mode->link);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200350}
351
352static const struct wl_output_listener output_listener = {
353 output_handle_geometry,
354 output_handle_mode,
355};
356
357static void
358add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
359{
360 struct output_info *output = malloc(sizeof *output);
361
362 init_global_info(info, &output->global, id, "wl_output", version);
363 output->global.print = print_output_info;
364
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200365 wl_list_init(&output->modes);
366
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400367 output->output = wl_registry_bind(info->registry, id,
368 &wl_output_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200369 wl_output_add_listener(output->output, &output_listener,
370 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200371
372 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200373}
374
375static void
376add_global_info(struct weston_info *info, uint32_t id,
377 const char *interface, uint32_t version)
378{
379 struct global_info *global = malloc(sizeof *global);
380
381 init_global_info(info, global, id, interface, version);
382 global->print = print_global_info;
383}
384
385static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400386global_handler(void *data, struct wl_registry *registry, uint32_t id,
387 const char *interface, uint32_t version)
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200388{
389 struct weston_info *info = data;
390
391 if (!strcmp(interface, "wl_seat"))
392 add_seat_info(info, id, version);
393 else if (!strcmp(interface, "wl_shm"))
394 add_shm_info(info, id, version);
395 else if (!strcmp(interface, "wl_output"))
396 add_output_info(info, id, version);
397 else
398 add_global_info(info, id, interface, version);
399}
400
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200401static void
402global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
403{
404}
405
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400406static const struct wl_registry_listener registry_listener = {
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200407 global_handler,
408 global_remove_handler
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400409};
410
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200411static void
412print_infos(struct wl_list *infos)
413{
414 struct global_info *info;
415
416 wl_list_for_each(info, infos, link)
417 info->print(info);
418}
419
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200420int
421main(int argc, char **argv)
422{
423 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200424
425 info.display = wl_display_connect(NULL);
426 if (!info.display) {
427 fprintf(stderr, "failed to create display: %m\n");
428 return -1;
429 }
430
431 wl_list_init(&info.infos);
432
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400433 info.registry = wl_display_get_registry(info.display);
434 wl_registry_add_listener(info.registry, &registry_listener, &info);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200435
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200436 do {
437 info.roundtrip_needed = false;
438 wl_display_roundtrip(info.display);
439 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200440
441 print_infos(&info.infos);
442
443 return 0;
444}