blob: d4b70da7861511754bfe538d424a960cc7728db2 [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
44struct output_info {
45 struct global_info global;
46
47 struct wl_output *output;
48
49 struct {
50 int32_t x, y;
51 int32_t physical_width, physical_height;
52 enum wl_output_subpixel subpixel;
53 enum wl_output_transform output_transform;
54 char *make;
55 char *model;
56 } geometry;
57
58 struct {
59 uint32_t flags;
60 int32_t width, height;
61 int32_t refresh;
62 } mode;
63};
64
65struct shm_format {
66 struct wl_list link;
67
68 uint32_t format;
69};
70
71struct shm_info {
72 struct global_info global;
73 struct wl_shm *shm;
74
75 struct wl_list formats;
76};
77
78struct seat_info {
79 struct global_info global;
80 struct wl_seat *seat;
81
82 uint32_t capabilities;
83};
84
85struct weston_info {
86 struct wl_display *display;
87
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020088 struct wl_list infos;
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +020089 bool roundtrip_needed;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020090};
91
92static void
93print_global_info(void *data)
94{
95 struct global_info *global = data;
96
97 printf("interface: '%s', version: %u, name: %u\n",
98 global->interface, global->version, global->id);
99}
100
101static void
102init_global_info(struct weston_info *info,
103 struct global_info *global, uint32_t id,
104 const char *interface, uint32_t version)
105{
106 global->id = id;
107 global->version = version;
108 global->interface = strdup(interface);
109
110 wl_list_insert(info->infos.prev, &global->link);
111}
112
113static void
114print_output_info(void *data)
115{
116 struct output_info *output = data;
117 const char *subpixel_orientation;
118 const char *transform;
119
120 print_global_info(data);
121
122 switch (output->geometry.subpixel) {
123 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
124 subpixel_orientation = "unknown";
125 break;
126 case WL_OUTPUT_SUBPIXEL_NONE:
127 subpixel_orientation = "none";
128 break;
129 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
130 subpixel_orientation = "horizontal rgb";
131 break;
132 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
133 subpixel_orientation = "horizontal bgr";
134 break;
135 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
136 subpixel_orientation = "vertical rgb";
137 break;
138 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
139 subpixel_orientation = "vertical bgr";
140 break;
141 default:
142 fprintf(stderr, "unknown subpixel orientation %u\n",
143 output->geometry.subpixel);
144 subpixel_orientation = "unexpected value";
145 break;
146 }
147
148 switch (output->geometry.output_transform) {
149 case WL_OUTPUT_TRANSFORM_NORMAL:
150 transform = "normal";
151 break;
152 case WL_OUTPUT_TRANSFORM_90:
153 transform = "90°";
154 break;
155 case WL_OUTPUT_TRANSFORM_180:
156 transform = "180°";
157 break;
158 case WL_OUTPUT_TRANSFORM_270:
159 transform = "270°";
160 break;
161 case WL_OUTPUT_TRANSFORM_FLIPPED:
162 transform = "flipped";
163 break;
164 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
165 transform = "flipped 90°";
166 break;
167 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
168 transform = "flipped 180°";
169 break;
170 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
171 transform = "flipped 270°";
172 break;
173 default:
174 fprintf(stderr, "unknown output transform %u\n",
175 output->geometry.output_transform);
176 transform = "unexpected value";
177 break;
178 }
179
180 printf("\tx: %d, y: %d, width: %d px, height %d px,\n",
181 output->geometry.x, output->geometry.y,
182 output->mode.width, output->mode.height);
183 printf("\tphysical_width: %d mm, physical_height: %d mm, refresh: %.f Hz,\n",
184 output->geometry.physical_width,
185 output->geometry.physical_height,
186 (float) output->mode.refresh / 1000);
187 printf("\tmake: '%s', model: '%s',\n",
188 output->geometry.make, output->geometry.model);
189 printf("\tsubpixel_orientation: %s, output_tranform: %s,\n",
190 subpixel_orientation, transform);
191 printf("\tflags:");
192 if (output->mode.flags & WL_OUTPUT_MODE_CURRENT)
193 printf(" current");
194 if (output->mode.flags & WL_OUTPUT_MODE_PREFERRED)
195 printf(" preferred");
196 printf("\n");
197}
198
199static void
200print_shm_info(void *data)
201{
202 struct shm_info *shm = data;
203 struct shm_format *format;
204
205 print_global_info(data);
206
207 printf("\tformats:");
208
209 wl_list_for_each(format, &shm->formats, link)
210 printf(" %s", (format->format == WL_SHM_FORMAT_ARGB8888) ?
211 "ARGB8888" : "XRGB8888");
212
213 printf("\n");
214}
215
216static void
217print_seat_info(void *data)
218{
219 struct seat_info *seat = data;
220
221 print_global_info(data);
222
223 printf("\tcapabilities:");
224
225 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
226 printf(" pointer");
227 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
228 printf(" keyboard");
229 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
230 printf(" touch");
231
232 printf("\n");
233}
234
235static void
236seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
237 enum wl_seat_capability caps)
238{
239 struct seat_info *seat = data;
240 seat->capabilities = caps;
241}
242
243static const struct wl_seat_listener seat_listener = {
244 seat_handle_capabilities,
245};
246
247static void
248add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
249{
250 struct seat_info *seat = malloc(sizeof *seat);
251
252 init_global_info(info, &seat->global, id, "wl_seat", version);
253 seat->global.print = print_seat_info;
254
255 seat->seat = wl_display_bind(info->display, id, &wl_seat_interface);
256 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200257
258 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200259}
260
261static void
262shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
263{
264 struct shm_info *shm = data;
265 struct shm_format *shm_format = malloc(sizeof *shm_format);
266
267 wl_list_insert(&shm->formats, &shm_format->link);
268 shm_format->format = format;
269}
270
271static const struct wl_shm_listener shm_listener = {
272 shm_handle_format,
273};
274
275static void
276add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
277{
278 struct shm_info *shm = malloc(sizeof *shm);
279
280 init_global_info(info, &shm->global, id, "wl_shm", version);
281 shm->global.print = print_shm_info;
282 wl_list_init(&shm->formats);
283
284 shm->shm = wl_display_bind(info->display, id, &wl_shm_interface);
285 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200286
287 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200288}
289
290static void
291output_handle_geometry(void *data, struct wl_output *wl_output,
292 int32_t x, int32_t y,
293 int32_t physical_width, int32_t physical_height,
294 int32_t subpixel,
295 const char *make, const char *model,
296 int32_t output_transform)
297{
298 struct output_info *output = data;
299
300 output->geometry.x = x;
301 output->geometry.y = y;
302 output->geometry.physical_width = physical_width;
303 output->geometry.physical_height = physical_height;
304 output->geometry.subpixel = subpixel;
305 output->geometry.make = strdup(make);
306 output->geometry.model = strdup(model);
307 output->geometry.output_transform = output_transform;
308}
309
310static void
311output_handle_mode(void *data, struct wl_output *wl_output,
312 uint32_t flags, int32_t width, int32_t height,
313 int32_t refresh)
314{
315 struct output_info *output = data;
316
317 output->mode.flags = flags;
318 output->mode.width = width;
319 output->mode.height = height;
320 output->mode.refresh = refresh;
321}
322
323static const struct wl_output_listener output_listener = {
324 output_handle_geometry,
325 output_handle_mode,
326};
327
328static void
329add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
330{
331 struct output_info *output = malloc(sizeof *output);
332
333 init_global_info(info, &output->global, id, "wl_output", version);
334 output->global.print = print_output_info;
335
336 output->output = wl_display_bind(info->display, id,
337 &wl_output_interface);
338 wl_output_add_listener(output->output, &output_listener,
339 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200340
341 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200342}
343
344static void
345add_global_info(struct weston_info *info, uint32_t id,
346 const char *interface, uint32_t version)
347{
348 struct global_info *global = malloc(sizeof *global);
349
350 init_global_info(info, global, id, interface, version);
351 global->print = print_global_info;
352}
353
354static void
355global_handler(struct wl_display *display, uint32_t id,
356 const char *interface, uint32_t version, void *data)
357{
358 struct weston_info *info = data;
359
360 if (!strcmp(interface, "wl_seat"))
361 add_seat_info(info, id, version);
362 else if (!strcmp(interface, "wl_shm"))
363 add_shm_info(info, id, version);
364 else if (!strcmp(interface, "wl_output"))
365 add_output_info(info, id, version);
366 else
367 add_global_info(info, id, interface, version);
368}
369
370static void
371print_infos(struct wl_list *infos)
372{
373 struct global_info *info;
374
375 wl_list_for_each(info, infos, link)
376 info->print(info);
377}
378
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200379int
380main(int argc, char **argv)
381{
382 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200383
384 info.display = wl_display_connect(NULL);
385 if (!info.display) {
386 fprintf(stderr, "failed to create display: %m\n");
387 return -1;
388 }
389
390 wl_list_init(&info.infos);
391
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200392 wl_display_add_global_listener(info.display,
393 global_handler,
394 &info);
395
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200396 do {
397 info.roundtrip_needed = false;
398 wl_display_roundtrip(info.display);
399 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200400
401 print_infos(&info.infos);
402
403 return 0;
404}