blob: c07134d16ff46be223db98399f4edfdd4d1cd215 [file] [log] [blame]
Philipp Brüschweiler585acb02012-08-15 17:12:00 +02001/*
2 * Copyright © 2012 Philipp Brüschweiler
3 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -07004 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020010 *
Bryce Harrington1f6b0d12015-06-10 22:48:59 -070011 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020022 */
23
U. Artie Eoff86c68b32014-01-15 13:02:28 -080024#include "config.h"
25
26#include <errno.h>
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020027#include <stdbool.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030028#include <stdint.h>
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020029#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
Pekka Paalanen93a6afd2014-09-23 22:08:44 -040032#include <time.h>
Pekka Paalanen78dc6a92017-02-13 16:35:00 +020033#include <assert.h>
34#include <ctype.h>
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020035
36#include <wayland-client.h>
37
Jon Cruz35b2eaa2015-06-15 15:37:08 -070038#include "shared/helpers.h"
Jon Cruz4678bab2015-06-15 15:37:07 -070039#include "shared/os-compatibility.h"
Bryce Harringtone99e4bf2016-03-16 14:15:18 -070040#include "shared/xalloc.h"
Bryce Harrington0d1a6222016-02-11 16:42:49 -080041#include "shared/zalloc.h"
Pekka Paalanenb00c79b2016-02-18 16:53:27 +020042#include "presentation-time-client-protocol.h"
Pekka Paalanen93a6afd2014-09-23 22:08:44 -040043
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020044typedef void (*print_info_t)(void *info);
U. Artie Eoff86c68b32014-01-15 13:02:28 -080045typedef void (*destroy_info_t)(void *info);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020046
47struct global_info {
48 struct wl_list link;
49
50 uint32_t id;
51 uint32_t version;
52 char *interface;
53
54 print_info_t print;
U. Artie Eoff86c68b32014-01-15 13:02:28 -080055 destroy_info_t destroy;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020056};
57
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +020058struct output_mode {
59 struct wl_list link;
60
61 uint32_t flags;
62 int32_t width, height;
63 int32_t refresh;
64};
65
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020066struct output_info {
67 struct global_info global;
68
69 struct wl_output *output;
70
Jonny Lambba9dca02015-12-17 12:31:56 +000071 int32_t version;
72
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020073 struct {
74 int32_t x, y;
Jonny Lambba9dca02015-12-17 12:31:56 +000075 int32_t scale;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020076 int32_t physical_width, physical_height;
77 enum wl_output_subpixel subpixel;
78 enum wl_output_transform output_transform;
79 char *make;
80 char *model;
81 } geometry;
82
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +020083 struct wl_list modes;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +020084};
85
86struct shm_format {
87 struct wl_list link;
88
89 uint32_t format;
90};
91
92struct shm_info {
93 struct global_info global;
94 struct wl_shm *shm;
95
96 struct wl_list formats;
97};
98
99struct seat_info {
100 struct global_info global;
101 struct wl_seat *seat;
Jonny Lamb06959082014-08-12 14:58:27 +0200102 struct weston_info *info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200103
104 uint32_t capabilities;
Rob Bradford14a76012013-05-31 18:09:52 +0100105 char *name;
Jonny Lamb06959082014-08-12 14:58:27 +0200106
107 int32_t repeat_rate;
108 int32_t repeat_delay;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200109};
110
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400111struct presentation_info {
112 struct global_info global;
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200113 struct wp_presentation *presentation;
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400114
115 clockid_t clk_id;
116};
117
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200118struct weston_info {
119 struct wl_display *display;
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400120 struct wl_registry *registry;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200121
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200122 struct wl_list infos;
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200123 bool roundtrip_needed;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200124};
125
126static void
127print_global_info(void *data)
128{
129 struct global_info *global = data;
130
131 printf("interface: '%s', version: %u, name: %u\n",
132 global->interface, global->version, global->id);
133}
134
135static void
136init_global_info(struct weston_info *info,
137 struct global_info *global, uint32_t id,
138 const char *interface, uint32_t version)
139{
140 global->id = id;
141 global->version = version;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800142 global->interface = xstrdup(interface);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200143
144 wl_list_insert(info->infos.prev, &global->link);
145}
146
147static void
148print_output_info(void *data)
149{
150 struct output_info *output = data;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200151 struct output_mode *mode;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200152 const char *subpixel_orientation;
153 const char *transform;
154
155 print_global_info(data);
156
157 switch (output->geometry.subpixel) {
158 case WL_OUTPUT_SUBPIXEL_UNKNOWN:
159 subpixel_orientation = "unknown";
160 break;
161 case WL_OUTPUT_SUBPIXEL_NONE:
162 subpixel_orientation = "none";
163 break;
164 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
165 subpixel_orientation = "horizontal rgb";
166 break;
167 case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
168 subpixel_orientation = "horizontal bgr";
169 break;
170 case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
171 subpixel_orientation = "vertical rgb";
172 break;
173 case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
174 subpixel_orientation = "vertical bgr";
175 break;
176 default:
177 fprintf(stderr, "unknown subpixel orientation %u\n",
178 output->geometry.subpixel);
179 subpixel_orientation = "unexpected value";
180 break;
181 }
182
183 switch (output->geometry.output_transform) {
184 case WL_OUTPUT_TRANSFORM_NORMAL:
185 transform = "normal";
186 break;
187 case WL_OUTPUT_TRANSFORM_90:
188 transform = "90°";
189 break;
190 case WL_OUTPUT_TRANSFORM_180:
191 transform = "180°";
192 break;
193 case WL_OUTPUT_TRANSFORM_270:
194 transform = "270°";
195 break;
196 case WL_OUTPUT_TRANSFORM_FLIPPED:
197 transform = "flipped";
198 break;
199 case WL_OUTPUT_TRANSFORM_FLIPPED_90:
200 transform = "flipped 90°";
201 break;
202 case WL_OUTPUT_TRANSFORM_FLIPPED_180:
203 transform = "flipped 180°";
204 break;
205 case WL_OUTPUT_TRANSFORM_FLIPPED_270:
206 transform = "flipped 270°";
207 break;
208 default:
209 fprintf(stderr, "unknown output transform %u\n",
210 output->geometry.output_transform);
211 transform = "unexpected value";
212 break;
213 }
214
Jonny Lambba9dca02015-12-17 12:31:56 +0000215 printf("\tx: %d, y: %d,",
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200216 output->geometry.x, output->geometry.y);
Jonny Lambba9dca02015-12-17 12:31:56 +0000217 if (output->version >= 2)
218 printf(" scale: %d,", output->geometry.scale);
219 printf("\n");
220
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200221 printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200222 output->geometry.physical_width,
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200223 output->geometry.physical_height);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200224 printf("\tmake: '%s', model: '%s',\n",
225 output->geometry.make, output->geometry.model);
U. Artie Eoffcb0e3572014-04-18 09:30:07 -0700226 printf("\tsubpixel_orientation: %s, output_transform: %s,\n",
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200227 subpixel_orientation, transform);
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200228
229 wl_list_for_each(mode, &output->modes, link) {
230 printf("\tmode:\n");
231
Pekka Paalanen48fbb542016-04-12 11:05:23 +0300232 printf("\t\twidth: %d px, height: %d px, refresh: %.3f Hz,\n",
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200233 mode->width, mode->height,
234 (float) mode->refresh / 1000);
235
236 printf("\t\tflags:");
237 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
238 printf(" current");
239 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
240 printf(" preferred");
241 printf("\n");
242 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200243}
244
Pekka Paalanen78dc6a92017-02-13 16:35:00 +0200245static char
246bits2graph(uint32_t value, unsigned bitoffset)
247{
248 int c = (value >> bitoffset) & 0xff;
249
250 if (isgraph(c) || isspace(c))
251 return c;
252
253 return '?';
254}
255
256static void
257fourcc2str(uint32_t format, char *str, int len)
258{
259 int i;
260
261 assert(len >= 5);
262
263 for (i = 0; i < 4; i++)
264 str[i] = bits2graph(format, i * 8);
265 str[i] = '\0';
266}
267
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200268static void
269print_shm_info(void *data)
270{
Pekka Paalanen78dc6a92017-02-13 16:35:00 +0200271 char str[5];
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200272 struct shm_info *shm = data;
273 struct shm_format *format;
274
275 print_global_info(data);
276
277 printf("\tformats:");
278
279 wl_list_for_each(format, &shm->formats, link)
Kristian Høgsberg8b66ebd2013-11-20 13:54:00 -0800280 switch (format->format) {
281 case WL_SHM_FORMAT_ARGB8888:
282 printf(" ARGB8888");
283 break;
284 case WL_SHM_FORMAT_XRGB8888:
285 printf(" XRGB8888");
286 break;
287 case WL_SHM_FORMAT_RGB565:
288 printf(" RGB565");
289 break;
290 default:
Pekka Paalanen78dc6a92017-02-13 16:35:00 +0200291 fourcc2str(format->format, str, sizeof(str));
292 printf(" '%s'(0x%08x)", str, format->format);
Kristian Høgsberg8b66ebd2013-11-20 13:54:00 -0800293 break;
294 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200295
296 printf("\n");
297}
298
299static void
300print_seat_info(void *data)
301{
302 struct seat_info *seat = data;
303
304 print_global_info(data);
305
Rob Bradford14a76012013-05-31 18:09:52 +0100306 printf("\tname: %s\n", seat->name);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200307 printf("\tcapabilities:");
308
309 if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
310 printf(" pointer");
311 if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
312 printf(" keyboard");
313 if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
314 printf(" touch");
315
316 printf("\n");
Jonny Lamb06959082014-08-12 14:58:27 +0200317
318 if (seat->repeat_rate > 0)
319 printf("\tkeyboard repeat rate: %d\n", seat->repeat_rate);
320 if (seat->repeat_delay > 0)
321 printf("\tkeyboard repeat delay: %d\n", seat->repeat_delay);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200322}
323
324static void
Jonny Lamb06959082014-08-12 14:58:27 +0200325keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
326 uint32_t format, int fd, uint32_t size)
327{
328}
329
330static void
331keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
332 uint32_t serial, struct wl_surface *surface,
333 struct wl_array *keys)
334{
335}
336
337static void
338keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
339 uint32_t serial, struct wl_surface *surface)
340{
341}
342
343static void
344keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
345 uint32_t serial, uint32_t time, uint32_t key,
346 uint32_t state)
347{
348}
349
350static void
351keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
352 uint32_t serial, uint32_t mods_depressed,
353 uint32_t mods_latched, uint32_t mods_locked,
354 uint32_t group)
355{
356}
357
358static void
359keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
360 int32_t rate, int32_t delay)
361{
362 struct seat_info *seat = data;
363
364 seat->repeat_rate = rate;
365 seat->repeat_delay = delay;
366}
367
368static const struct wl_keyboard_listener keyboard_listener = {
369 keyboard_handle_keymap,
370 keyboard_handle_enter,
371 keyboard_handle_leave,
372 keyboard_handle_key,
373 keyboard_handle_modifiers,
374 keyboard_handle_repeat_info,
375};
376
377static void
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200378seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
379 enum wl_seat_capability caps)
380{
381 struct seat_info *seat = data;
Jonny Lamb06959082014-08-12 14:58:27 +0200382
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200383 seat->capabilities = caps;
Jonny Lamb06959082014-08-12 14:58:27 +0200384
385 /* we want listen for repeat_info from wl_keyboard, but only
386 * do so if the seat info is >= 4 and if we actually have a
387 * keyboard */
388 if (seat->global.version < 4)
389 return;
390
391 if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
392 struct wl_keyboard *keyboard;
393
394 keyboard = wl_seat_get_keyboard(seat->seat);
395 wl_keyboard_add_listener(keyboard, &keyboard_listener,
396 seat);
397
398 seat->info->roundtrip_needed = true;
399 }
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200400}
401
Rob Bradford14a76012013-05-31 18:09:52 +0100402static void
403seat_handle_name(void *data, struct wl_seat *wl_seat,
404 const char *name)
405{
406 struct seat_info *seat = data;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800407 seat->name = xstrdup(name);
Rob Bradford14a76012013-05-31 18:09:52 +0100408}
409
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200410static const struct wl_seat_listener seat_listener = {
411 seat_handle_capabilities,
Rob Bradford14a76012013-05-31 18:09:52 +0100412 seat_handle_name,
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200413};
414
415static void
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800416destroy_seat_info(void *data)
417{
418 struct seat_info *seat = data;
419
420 wl_seat_destroy(seat->seat);
421
422 if (seat->name != NULL)
423 free(seat->name);
424}
425
426static void
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200427add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
428{
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800429 struct seat_info *seat = xzalloc(sizeof *seat);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200430
Jonny Lamb06959082014-08-12 14:58:27 +0200431 /* required to set roundtrip_needed to true in capabilities
432 * handler */
433 seat->info = info;
434
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200435 init_global_info(info, &seat->global, id, "wl_seat", version);
436 seat->global.print = print_seat_info;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800437 seat->global.destroy = destroy_seat_info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200438
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400439 seat->seat = wl_registry_bind(info->registry,
Jonny Lamb06959082014-08-12 14:58:27 +0200440 id, &wl_seat_interface, MIN(version, 4));
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200441 wl_seat_add_listener(seat->seat, &seat_listener, seat);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200442
Jonny Lamb06959082014-08-12 14:58:27 +0200443 seat->repeat_rate = seat->repeat_delay = -1;
444
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200445 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200446}
447
448static void
449shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
450{
451 struct shm_info *shm = data;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800452 struct shm_format *shm_format = xzalloc(sizeof *shm_format);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200453
454 wl_list_insert(&shm->formats, &shm_format->link);
455 shm_format->format = format;
456}
457
458static const struct wl_shm_listener shm_listener = {
459 shm_handle_format,
460};
461
462static void
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800463destroy_shm_info(void *data)
464{
465 struct shm_info *shm = data;
466 struct shm_format *format, *tmp;
467
468 wl_list_for_each_safe(format, tmp, &shm->formats, link) {
469 wl_list_remove(&format->link);
470 free(format);
471 }
472
473 wl_shm_destroy(shm->shm);
474}
475
476static void
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200477add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
478{
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800479 struct shm_info *shm = xzalloc(sizeof *shm);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200480
481 init_global_info(info, &shm->global, id, "wl_shm", version);
482 shm->global.print = print_shm_info;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800483 shm->global.destroy = destroy_shm_info;
484
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200485 wl_list_init(&shm->formats);
486
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400487 shm->shm = wl_registry_bind(info->registry,
488 id, &wl_shm_interface, 1);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200489 wl_shm_add_listener(shm->shm, &shm_listener, shm);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200490
491 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200492}
493
494static void
495output_handle_geometry(void *data, struct wl_output *wl_output,
496 int32_t x, int32_t y,
497 int32_t physical_width, int32_t physical_height,
498 int32_t subpixel,
499 const char *make, const char *model,
500 int32_t output_transform)
501{
502 struct output_info *output = data;
503
504 output->geometry.x = x;
505 output->geometry.y = y;
506 output->geometry.physical_width = physical_width;
507 output->geometry.physical_height = physical_height;
508 output->geometry.subpixel = subpixel;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800509 output->geometry.make = xstrdup(make);
510 output->geometry.model = xstrdup(model);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200511 output->geometry.output_transform = output_transform;
512}
513
514static void
515output_handle_mode(void *data, struct wl_output *wl_output,
516 uint32_t flags, int32_t width, int32_t height,
517 int32_t refresh)
518{
519 struct output_info *output = data;
Kristian Høgsberg06b16c22013-08-15 14:20:53 -0700520 struct output_mode *mode = xmalloc(sizeof *mode);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200521
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200522 mode->flags = flags;
523 mode->width = width;
524 mode->height = height;
525 mode->refresh = refresh;
526
527 wl_list_insert(output->modes.prev, &mode->link);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200528}
529
Jonny Lambba9dca02015-12-17 12:31:56 +0000530static void
531output_handle_done(void *data, struct wl_output *wl_output)
532{
533 /* don't bother waiting for this; there's no good reason a
534 * compositor will wait more than one roundtrip before sending
535 * these initial events. */
536}
537
538static void
539output_handle_scale(void *data, struct wl_output *wl_output,
540 int32_t scale)
541{
542 struct output_info *output = data;
543
544 output->geometry.scale = scale;
545}
546
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200547static const struct wl_output_listener output_listener = {
548 output_handle_geometry,
549 output_handle_mode,
Jonny Lambba9dca02015-12-17 12:31:56 +0000550 output_handle_done,
551 output_handle_scale,
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200552};
553
554static void
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800555destroy_output_info(void *data)
556{
557 struct output_info *output = data;
558 struct output_mode *mode, *tmp;
559
560 wl_output_destroy(output->output);
561
562 if (output->geometry.make != NULL)
563 free(output->geometry.make);
564 if (output->geometry.model != NULL)
565 free(output->geometry.model);
566
567 wl_list_for_each_safe(mode, tmp, &output->modes, link) {
568 wl_list_remove(&mode->link);
569 free(mode);
570 }
571}
572
573static void
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200574add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
575{
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800576 struct output_info *output = xzalloc(sizeof *output);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200577
578 init_global_info(info, &output->global, id, "wl_output", version);
579 output->global.print = print_output_info;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800580 output->global.destroy = destroy_output_info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200581
Jonny Lambba9dca02015-12-17 12:31:56 +0000582 output->version = MIN(version, 2);
583 output->geometry.scale = 1;
Philipp Brüschweiler97cb62a2012-08-15 21:57:24 +0200584 wl_list_init(&output->modes);
585
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400586 output->output = wl_registry_bind(info->registry, id,
Jonny Lambba9dca02015-12-17 12:31:56 +0000587 &wl_output_interface, output->version);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200588 wl_output_add_listener(output->output, &output_listener,
589 output);
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200590
591 info->roundtrip_needed = true;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200592}
593
594static void
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400595destroy_presentation_info(void *info)
596{
597 struct presentation_info *prinfo = info;
598
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200599 wp_presentation_destroy(prinfo->presentation);
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400600}
601
602static const char *
603clock_name(clockid_t clk_id)
604{
605 static const char *names[] = {
606 [CLOCK_REALTIME] = "CLOCK_REALTIME",
607 [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
608 [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
609 [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
610 [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
Derek Foreman32838c92015-06-29 13:20:34 -0500611#ifdef CLOCK_BOOTTIME
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400612 [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
Derek Foreman32838c92015-06-29 13:20:34 -0500613#endif
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400614 };
615
616 if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
617 return "unknown";
618
619 return names[clk_id];
620}
621
622static void
623print_presentation_info(void *info)
624{
625 struct presentation_info *prinfo = info;
626
627 print_global_info(info);
628
629 printf("\tpresentation clock id: %d (%s)\n",
630 prinfo->clk_id, clock_name(prinfo->clk_id));
631}
632
633static void
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200634presentation_handle_clock_id(void *data, struct wp_presentation *presentation,
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400635 uint32_t clk_id)
636{
637 struct presentation_info *prinfo = data;
638
639 prinfo->clk_id = clk_id;
640}
641
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200642static const struct wp_presentation_listener presentation_listener = {
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400643 presentation_handle_clock_id
644};
645
646static void
647add_presentation_info(struct weston_info *info, uint32_t id, uint32_t version)
648{
649 struct presentation_info *prinfo = xzalloc(sizeof *prinfo);
650
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200651 init_global_info(info, &prinfo->global, id,
652 wp_presentation_interface.name, version);
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400653 prinfo->global.print = print_presentation_info;
654 prinfo->global.destroy = destroy_presentation_info;
655
656 prinfo->clk_id = -1;
657 prinfo->presentation = wl_registry_bind(info->registry, id,
Pekka Paalanenb00c79b2016-02-18 16:53:27 +0200658 &wp_presentation_interface, 1);
659 wp_presentation_add_listener(prinfo->presentation,
660 &presentation_listener, prinfo);
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400661
662 info->roundtrip_needed = true;
663}
664
665static void
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800666destroy_global_info(void *data)
667{
668}
669
670static void
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200671add_global_info(struct weston_info *info, uint32_t id,
672 const char *interface, uint32_t version)
673{
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800674 struct global_info *global = xzalloc(sizeof *global);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200675
676 init_global_info(info, global, id, interface, version);
677 global->print = print_global_info;
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800678 global->destroy = destroy_global_info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200679}
680
681static void
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400682global_handler(void *data, struct wl_registry *registry, uint32_t id,
683 const char *interface, uint32_t version)
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200684{
685 struct weston_info *info = data;
686
687 if (!strcmp(interface, "wl_seat"))
688 add_seat_info(info, id, version);
689 else if (!strcmp(interface, "wl_shm"))
690 add_shm_info(info, id, version);
691 else if (!strcmp(interface, "wl_output"))
692 add_output_info(info, id, version);
Pekka Paalanen13a26e02016-04-19 16:16:29 +0300693 else if (!strcmp(interface, wp_presentation_interface.name))
Pekka Paalanen93a6afd2014-09-23 22:08:44 -0400694 add_presentation_info(info, id, version);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200695 else
696 add_global_info(info, id, interface, version);
697}
698
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200699static void
700global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
701{
702}
703
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400704static const struct wl_registry_listener registry_listener = {
Pekka Paalanen0eab05d2013-01-22 14:53:55 +0200705 global_handler,
706 global_remove_handler
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400707};
708
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200709static void
710print_infos(struct wl_list *infos)
711{
712 struct global_info *info;
713
714 wl_list_for_each(info, infos, link)
715 info->print(info);
716}
717
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800718static void
719destroy_info(void *data)
720{
721 struct global_info *global = data;
722
723 global->destroy(data);
724 wl_list_remove(&global->link);
725 free(global->interface);
726 free(data);
727}
728
729static void
730destroy_infos(struct wl_list *infos)
731{
732 struct global_info *info, *tmp;
733 wl_list_for_each_safe(info, tmp, infos, link)
734 destroy_info(info);
735}
736
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200737int
738main(int argc, char **argv)
739{
740 struct weston_info info;
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200741
742 info.display = wl_display_connect(NULL);
743 if (!info.display) {
744 fprintf(stderr, "failed to create display: %m\n");
745 return -1;
746 }
747
748 wl_list_init(&info.infos);
749
Kristian Høgsbergfa80e112012-10-10 21:34:26 -0400750 info.registry = wl_display_get_registry(info.display);
751 wl_registry_add_listener(info.registry, &registry_listener, &info);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200752
Philipp Brüschweilerbb0d4b92012-08-15 21:57:23 +0200753 do {
754 info.roundtrip_needed = false;
755 wl_display_roundtrip(info.display);
756 } while (info.roundtrip_needed);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200757
758 print_infos(&info.infos);
U. Artie Eoff86c68b32014-01-15 13:02:28 -0800759 destroy_infos(&info.infos);
760
761 wl_registry_destroy(info.registry);
762 wl_display_disconnect(info.display);
Philipp Brüschweiler585acb02012-08-15 17:12:00 +0200763
764 return 0;
765}