blob: 95e45b148c83af6a1a7f9518f8e5c5aecbc92dae [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;
91
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020092 struct wl_list infos;
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +020093 bool roundtrip_needed;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020094};
95
96static void
97print_global_info(void *data)
98{
99 struct global_info *global = data;
100
101 printf("interface: '%s', version: %u, name: %u\n",
102 global->interface, global->version, global->id);
103}
104
105static void
106init_global_info(struct weston_info *info,
107 struct global_info *global, uint32_t id,
108 const char *interface, uint32_t version)
109{
110 global->id = id;
111 global->version = version;
112 global->interface = strdup(interface);
113
114 wl_list_insert(info->infos.prev, &global->link);
115}
116
117static void
118print_output_info(void *data)
119{
120 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200121 struct output_mode *mode;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200122 const char *subpixel_orientation;
123 const char *transform;
124
125 print_global_info(data);
126
127 switch (output->geometry.subpixel) {
128 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
129 subpixel_orientation = "unknown";
130 break;
131 case WL_OUTPUT_SUBPIXEL_NONE:
132 subpixel_orientation = "none";
133 break;
134 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
135 subpixel_orientation = "horizontal rgb";
136 break;
137 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
138 subpixel_orientation = "horizontal bgr";
139 break;
140 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
141 subpixel_orientation = "vertical rgb";
142 break;
143 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
144 subpixel_orientation = "vertical bgr";
145 break;
146 default:
147 fprintf(stderr, "unknown subpixel orientation %u\n",
148 output->geometry.subpixel);
149 subpixel_orientation = "unexpected value";
150 break;
151 }
152
153 switch (output->geometry.output_transform) {
154 case WL_OUTPUT_TRANSFORM_NORMAL:
155 transform = "normal";
156 break;
157 case WL_OUTPUT_TRANSFORM_90:
158 transform = "90°";
159 break;
160 case WL_OUTPUT_TRANSFORM_180:
161 transform = "180°";
162 break;
163 case WL_OUTPUT_TRANSFORM_270:
164 transform = "270°";
165 break;
166 case WL_OUTPUT_TRANSFORM_FLIPPED:
167 transform = "flipped";
168 break;
169 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
170 transform = "flipped 90°";
171 break;
172 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
173 transform = "flipped 180°";
174 break;
175 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
176 transform = "flipped 270°";
177 break;
178 default:
179 fprintf(stderr, "unknown output transform %u\n",
180 output->geometry.output_transform);
181 transform = "unexpected value";
182 break;
183 }
184
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200185 printf("\tx: %d, y: %d,\n",
186 output->geometry.x, output->geometry.y);
187 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200188 output->geometry.physical_width,
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200189 output->geometry.physical_height);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200190 printf("\tmake: '%s', model: '%s',\n",
191 output->geometry.make, output->geometry.model);
192 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
193 subpixel_orientation, transform);
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200194
195 wl_list_for_each(mode, &output->modes, link) {
196 printf("\tmode:\n");
197
198 printf("\t\twidth: %d px, height: %d px, refresh: %.f Hz,\n",
199 mode->width, mode->height,
200 (float) mode->refresh / 1000);
201
202 printf("\t\tflags:");
203 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
204 printf(" current");
205 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
206 printf(" preferred");
207 printf("\n");
208 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200209}
210
211static void
212print_shm_info(void *data)
213{
214 struct shm_info *shm = data;
215 struct shm_format *format;
216
217 print_global_info(data);
218
219 printf("\tformats:");
220
221 wl_list_for_each(format, &shm->formats, link)
222 printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
223 "ARGB8888" : "XRGB8888");
224
225 printf("\n");
226}
227
228static void
229print_seat_info(void *data)
230{
231 struct seat_info *seat = data;
232
233 print_global_info(data);
234
235 printf("\tcapabilities:");
236
237 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
238 printf(" pointer");
239 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
240 printf(" keyboard");
241 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
242 printf(" touch");
243
244 printf("\n");
245}
246
247static void
248seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
249 enum wl_seat_capability caps)
250{
251 struct seat_info *seat = data;
252 seat->capabilities = caps;
253}
254
255static const struct wl_seat_listener seat_listener = {
256 seat_handle_capabilities,
257};
258
259static void
260add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
261{
262 struct seat_info *seat = malloc(sizeof *seat);
263
264 init_global_info(info, &seat->global, id, "wl_seat", version);
265 seat->global.print = print_seat_info;
266
267 seat->seat = wl_display_bind(info->display, id, &wl_seat_interface);
268 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200269
270 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200271}
272
273static void
274shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
275{
276 struct shm_info *shm = data;
277 struct shm_format *shm_format = malloc(sizeof *shm_format);
278
279 wl_list_insert(&shm->formats, &shm_format->link);
280 shm_format->format = format;
281}
282
283static const struct wl_shm_listener shm_listener = {
284 shm_handle_format,
285};
286
287static void
288add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
289{
290 struct shm_info *shm = malloc(sizeof *shm);
291
292 init_global_info(info, &shm->global, id, "wl_shm", version);
293 shm->global.print = print_shm_info;
294 wl_list_init(&shm->formats);
295
296 shm->shm = wl_display_bind(info->display, id, &wl_shm_interface);
297 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200298
299 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200300}
301
302static void
303output_handle_geometry(void *data, struct wl_output *wl_output,
304 int32_t x, int32_t y,
305 int32_t physical_width, int32_t physical_height,
306 int32_t subpixel,
307 const char *make, const char *model,
308 int32_t output_transform)
309{
310 struct output_info *output = data;
311
312 output->geometry.x = x;
313 output->geometry.y = y;
314 output->geometry.physical_width = physical_width;
315 output->geometry.physical_height = physical_height;
316 output->geometry.subpixel = subpixel;
317 output->geometry.make = strdup(make);
318 output->geometry.model = strdup(model);
319 output->geometry.output_transform = output_transform;
320}
321
322static void
323output_handle_mode(void *data, struct wl_output *wl_output,
324 uint32_t flags, int32_t width, int32_t height,
325 int32_t refresh)
326{
327 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200328 struct output_mode *mode = malloc(sizeof *mode);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200329
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200330 mode->flags = flags;
331 mode->width = width;
332 mode->height = height;
333 mode->refresh = refresh;
334
335 wl_list_insert(output->modes.prev, &mode->link);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200336}
337
338static const struct wl_output_listener output_listener = {
339 output_handle_geometry,
340 output_handle_mode,
341};
342
343static void
344add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
345{
346 struct output_info *output = malloc(sizeof *output);
347
348 init_global_info(info, &output->global, id, "wl_output", version);
349 output->global.print = print_output_info;
350
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200351 wl_list_init(&output->modes);
352
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200353 output->output = wl_display_bind(info->display, id,
354 &wl_output_interface);
355 wl_output_add_listener(output->output, &output_listener,
356 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200357
358 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200359}
360
361static void
362add_global_info(struct weston_info *info, uint32_t id,
363 const char *interface, uint32_t version)
364{
365 struct global_info *global = malloc(sizeof *global);
366
367 init_global_info(info, global, id, interface, version);
368 global->print = print_global_info;
369}
370
371static void
372global_handler(struct wl_display *display, uint32_t id,
373 const char *interface, uint32_t version, void *data)
374{
375 struct weston_info *info = data;
376
377 if (!strcmp(interface, "wl_seat"))
378 add_seat_info(info, id, version);
379 else if (!strcmp(interface, "wl_shm"))
380 add_shm_info(info, id, version);
381 else if (!strcmp(interface, "wl_output"))
382 add_output_info(info, id, version);
383 else
384 add_global_info(info, id, interface, version);
385}
386
387static void
388print_infos(struct wl_list *infos)
389{
390 struct global_info *info;
391
392 wl_list_for_each(info, infos, link)
393 info->print(info);
394}
395
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200396int
397main(int argc, char **argv)
398{
399 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200400
401 info.display = wl_display_connect(NULL);
402 if (!info.display) {
403 fprintf(stderr, "failed to create display: %m\n");
404 return -1;
405 }
406
407 wl_list_init(&info.infos);
408
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200409 wl_display_add_global_listener(info.display,
410 global_handler,
411 &info);
412
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200413 do {
414 info.roundtrip_needed = false;
415 wl_display_roundtrip(info.display);
416 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200417
418 print_infos(&info.infos);
419
420 return 0;
421}