6606117a99eb37e48d36412016511924068241d5
[platform/upstream/weston.git] / clients / weston-info.c
1 /*
2  * Copyright © 2012 Philipp Brüschweiler
3  *
4  * 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:
10  *
11  * 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.
22  */
23
24 #include "config.h"
25
26 #include <errno.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <assert.h>
34 #include <ctype.h>
35
36 #include <wayland-client.h>
37
38 #include "shared/helpers.h"
39 #include "shared/os-compatibility.h"
40 #include "shared/xalloc.h"
41 #include "shared/zalloc.h"
42 #include "presentation-time-client-protocol.h"
43 #include "linux-dmabuf-unstable-v1-client-protocol.h"
44 #include "tablet-unstable-v2-client-protocol.h"
45
46 typedef void (*print_info_t)(void *info);
47 typedef void (*destroy_info_t)(void *info);
48
49 struct global_info {
50         struct wl_list link;
51
52         uint32_t id;
53         uint32_t version;
54         char *interface;
55
56         print_info_t print;
57         destroy_info_t destroy;
58 };
59
60 struct output_mode {
61         struct wl_list link;
62
63         uint32_t flags;
64         int32_t width, height;
65         int32_t refresh;
66 };
67
68 struct output_info {
69         struct global_info global;
70
71         struct wl_output *output;
72
73         int32_t version;
74
75         struct {
76                 int32_t x, y;
77                 int32_t scale;
78                 int32_t physical_width, physical_height;
79                 enum wl_output_subpixel subpixel;
80                 enum wl_output_transform output_transform;
81                 char *make;
82                 char *model;
83         } geometry;
84
85         struct wl_list modes;
86 };
87
88 struct shm_format {
89         struct wl_list link;
90
91         uint32_t format;
92 };
93
94 struct shm_info {
95         struct global_info global;
96         struct wl_shm *shm;
97
98         struct wl_list formats;
99 };
100
101 struct linux_dmabuf_modifier {
102         struct wl_list link;
103
104         uint32_t format;
105         uint64_t modifier;
106 };
107
108 struct linux_dmabuf_info {
109         struct global_info global;
110         struct zwp_linux_dmabuf_v1 *dmabuf;
111
112         struct wl_list modifiers;
113 };
114
115 struct seat_info {
116         struct global_info global;
117         struct wl_list global_link;
118         struct wl_seat *seat;
119         struct weston_info *info;
120
121         uint32_t capabilities;
122         char *name;
123
124         int32_t repeat_rate;
125         int32_t repeat_delay;
126 };
127
128 struct tablet_v2_path {
129         struct wl_list link;
130         char *path;
131 };
132
133 struct tablet_tool_info {
134         struct wl_list link;
135         struct zwp_tablet_tool_v2 *tool;
136
137         uint64_t hardware_serial;
138         uint64_t hardware_id_wacom;
139         enum zwp_tablet_tool_v2_type type;
140         
141         bool has_tilt;
142         bool has_pressure;
143         bool has_distance;
144         bool has_rotation;
145         bool has_slider;
146         bool has_wheel;
147 };
148
149 struct tablet_pad_group_info {
150         struct wl_list link;
151         struct zwp_tablet_pad_group_v2 *group;
152
153         uint32_t modes;
154         size_t button_count;
155         int *buttons;
156         size_t strips;
157         size_t rings;
158 };
159
160 struct tablet_pad_info {
161         struct wl_list link;
162         struct zwp_tablet_pad_v2 *pad;
163
164         uint32_t buttons;
165         struct wl_list paths;
166         struct wl_list groups;
167 };
168
169 struct tablet_info {
170         struct wl_list link;
171         struct zwp_tablet_v2 *tablet;
172
173         char *name;
174         uint32_t vid, pid;
175         struct wl_list paths;
176 };
177
178 struct tablet_seat_info {
179         struct wl_list link;
180
181         struct zwp_tablet_seat_v2 *seat;
182         struct seat_info *seat_info;
183
184         struct wl_list tablets;
185         struct wl_list tools;
186         struct wl_list pads;
187 };
188
189 struct tablet_v2_info {
190         struct global_info global;
191         struct zwp_tablet_manager_v2 *manager;
192         struct weston_info *info;
193
194         struct wl_list seats;
195 };
196
197 struct presentation_info {
198         struct global_info global;
199         struct wp_presentation *presentation;
200
201         clockid_t clk_id;
202 };
203
204 struct weston_info {
205         struct wl_display *display;
206         struct wl_registry *registry;
207
208         struct wl_list infos;
209         bool roundtrip_needed;
210
211         /* required for tablet-unstable-v2 */
212         struct wl_list seats;
213         struct tablet_v2_info *tablet_info;
214 };
215
216 static void
217 print_global_info(void *data)
218 {
219         struct global_info *global = data;
220
221         printf("interface: '%s', version: %u, name: %u\n",
222                global->interface, global->version, global->id);
223 }
224
225 static void
226 init_global_info(struct weston_info *info,
227                  struct global_info *global, uint32_t id,
228                  const char *interface, uint32_t version)
229 {
230         global->id = id;
231         global->version = version;
232         global->interface = xstrdup(interface);
233
234         wl_list_insert(info->infos.prev, &global->link);
235 }
236
237 static void
238 print_output_info(void *data)
239 {
240         struct output_info *output = data;
241         struct output_mode *mode;
242         const char *subpixel_orientation;
243         const char *transform;
244
245         print_global_info(data);
246
247         switch (output->geometry.subpixel) {
248         case WL_OUTPUT_SUBPIXEL_UNKNOWN:
249                 subpixel_orientation = "unknown";
250                 break;
251         case WL_OUTPUT_SUBPIXEL_NONE:
252                 subpixel_orientation = "none";
253                 break;
254         case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
255                 subpixel_orientation = "horizontal rgb";
256                 break;
257         case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
258                 subpixel_orientation = "horizontal bgr";
259                 break;
260         case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
261                 subpixel_orientation = "vertical rgb";
262                 break;
263         case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
264                 subpixel_orientation = "vertical bgr";
265                 break;
266         default:
267                 fprintf(stderr, "unknown subpixel orientation %u\n",
268                         output->geometry.subpixel);
269                 subpixel_orientation = "unexpected value";
270                 break;
271         }
272
273         switch (output->geometry.output_transform) {
274         case WL_OUTPUT_TRANSFORM_NORMAL:
275                 transform = "normal";
276                 break;
277         case WL_OUTPUT_TRANSFORM_90:
278                 transform = "90°";
279                 break;
280         case WL_OUTPUT_TRANSFORM_180:
281                 transform = "180°";
282                 break;
283         case WL_OUTPUT_TRANSFORM_270:
284                 transform = "270°";
285                 break;
286         case WL_OUTPUT_TRANSFORM_FLIPPED:
287                 transform = "flipped";
288                 break;
289         case WL_OUTPUT_TRANSFORM_FLIPPED_90:
290                 transform = "flipped 90°";
291                 break;
292         case WL_OUTPUT_TRANSFORM_FLIPPED_180:
293                 transform = "flipped 180°";
294                 break;
295         case WL_OUTPUT_TRANSFORM_FLIPPED_270:
296                 transform = "flipped 270°";
297                 break;
298         default:
299                 fprintf(stderr, "unknown output transform %u\n",
300                         output->geometry.output_transform);
301                 transform = "unexpected value";
302                 break;
303         }
304
305         printf("\tx: %d, y: %d,",
306                output->geometry.x, output->geometry.y);
307         if (output->version >= 2)
308                 printf(" scale: %d,", output->geometry.scale);
309         printf("\n");
310
311         printf("\tphysical_width: %d mm, physical_height: %d mm,\n",
312                output->geometry.physical_width,
313                output->geometry.physical_height);
314         printf("\tmake: '%s', model: '%s',\n",
315                output->geometry.make, output->geometry.model);
316         printf("\tsubpixel_orientation: %s, output_transform: %s,\n",
317                subpixel_orientation, transform);
318
319         wl_list_for_each(mode, &output->modes, link) {
320                 printf("\tmode:\n");
321
322                 printf("\t\twidth: %d px, height: %d px, refresh: %.3f Hz,\n",
323                        mode->width, mode->height,
324                        (float) mode->refresh / 1000);
325
326                 printf("\t\tflags:");
327                 if (mode->flags & WL_OUTPUT_MODE_CURRENT)
328                         printf(" current");
329                 if (mode->flags & WL_OUTPUT_MODE_PREFERRED)
330                         printf(" preferred");
331                 printf("\n");
332         }
333 }
334
335 static char
336 bits2graph(uint32_t value, unsigned bitoffset)
337 {
338         int c = (value >> bitoffset) & 0xff;
339
340         if (isgraph(c) || isspace(c))
341                 return c;
342
343         return '?';
344 }
345
346 static void
347 fourcc2str(uint32_t format, char *str, int len)
348 {
349         int i;
350
351         assert(len >= 5);
352
353         for (i = 0; i < 4; i++)
354                 str[i] = bits2graph(format, i * 8);
355         str[i] = '\0';
356 }
357
358 static void
359 print_shm_info(void *data)
360 {
361         char str[5];
362         struct shm_info *shm = data;
363         struct shm_format *format;
364
365         print_global_info(data);
366
367         printf("\tformats:");
368
369         wl_list_for_each(format, &shm->formats, link)
370                 switch (format->format) {
371                 case WL_SHM_FORMAT_ARGB8888:
372                         printf(" ARGB8888");
373                         break;
374                 case WL_SHM_FORMAT_XRGB8888:
375                         printf(" XRGB8888");
376                         break;
377                 case WL_SHM_FORMAT_RGB565:
378                         printf(" RGB565");
379                         break;
380                 default:
381                         fourcc2str(format->format, str, sizeof(str));
382                         printf(" '%s'(0x%08x)", str, format->format);
383                         break;
384                 }
385
386         printf("\n");
387 }
388
389 static void
390 print_linux_dmabuf_info(void *data)
391 {
392         char str[5];
393         struct linux_dmabuf_info *dmabuf = data;
394         struct linux_dmabuf_modifier *modifier;
395
396         print_global_info(data);
397
398         printf("\tformats:");
399
400         wl_list_for_each(modifier, &dmabuf->modifiers, link) {
401                 fourcc2str(modifier->format, str, sizeof(str));
402                 printf("\n\t'%s'(0x%08x), modifier: 0x%016"PRIx64, str, modifier->format, modifier->modifier);
403         }
404
405         printf("\n");
406 }
407
408 static void
409 print_seat_info(void *data)
410 {
411         struct seat_info *seat = data;
412
413         print_global_info(data);
414
415         printf("\tname: %s\n", seat->name);
416         printf("\tcapabilities:");
417
418         if (seat->capabilities & WL_SEAT_CAPABILITY_POINTER)
419                 printf(" pointer");
420         if (seat->capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
421                 printf(" keyboard");
422         if (seat->capabilities & WL_SEAT_CAPABILITY_TOUCH)
423                 printf(" touch");
424
425         printf("\n");
426
427         if (seat->repeat_rate > 0)
428                 printf("\tkeyboard repeat rate: %d\n", seat->repeat_rate);
429         if (seat->repeat_delay > 0)
430                 printf("\tkeyboard repeat delay: %d\n", seat->repeat_delay);
431 }
432
433 static void
434 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
435                        uint32_t format, int fd, uint32_t size)
436 {
437 }
438
439 static void
440 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
441                       uint32_t serial, struct wl_surface *surface,
442                       struct wl_array *keys)
443 {
444 }
445
446 static void
447 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
448                       uint32_t serial, struct wl_surface *surface)
449 {
450 }
451
452 static void
453 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
454                     uint32_t serial, uint32_t time, uint32_t key,
455                     uint32_t state)
456 {
457 }
458
459 static void
460 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
461                           uint32_t serial, uint32_t mods_depressed,
462                           uint32_t mods_latched, uint32_t mods_locked,
463                           uint32_t group)
464 {
465 }
466
467 static void
468 keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
469                             int32_t rate, int32_t delay)
470 {
471         struct seat_info *seat = data;
472
473         seat->repeat_rate = rate;
474         seat->repeat_delay = delay;
475 }
476
477 static const struct wl_keyboard_listener keyboard_listener = {
478         keyboard_handle_keymap,
479         keyboard_handle_enter,
480         keyboard_handle_leave,
481         keyboard_handle_key,
482         keyboard_handle_modifiers,
483         keyboard_handle_repeat_info,
484 };
485
486 static void
487 seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
488                          enum wl_seat_capability caps)
489 {
490         struct seat_info *seat = data;
491
492         seat->capabilities = caps;
493
494         /* we want listen for repeat_info from wl_keyboard, but only
495          * do so if the seat info is >= 4 and if we actually have a
496          * keyboard */
497         if (seat->global.version < 4)
498                 return;
499
500         if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
501                 struct wl_keyboard *keyboard;
502
503                 keyboard = wl_seat_get_keyboard(seat->seat);
504                 wl_keyboard_add_listener(keyboard, &keyboard_listener,
505                                          seat);
506
507                 seat->info->roundtrip_needed = true;
508         }
509 }
510
511 static void
512 seat_handle_name(void *data, struct wl_seat *wl_seat,
513                  const char *name)
514 {
515         struct seat_info *seat = data;
516         seat->name = xstrdup(name);
517 }
518
519 static const struct wl_seat_listener seat_listener = {
520         seat_handle_capabilities,
521         seat_handle_name,
522 };
523
524 static void
525 destroy_seat_info(void *data)
526 {
527         struct seat_info *seat = data;
528
529         wl_seat_destroy(seat->seat);
530
531         if (seat->name != NULL)
532                 free(seat->name);
533
534         wl_list_remove(&seat->global_link);
535 }
536
537 static const char *
538 tablet_tool_type_to_str(enum zwp_tablet_tool_v2_type type)
539 {
540         switch (type) {
541         case ZWP_TABLET_TOOL_V2_TYPE_PEN:
542                 return "pen";
543         case ZWP_TABLET_TOOL_V2_TYPE_ERASER:
544                 return "eraser";
545         case ZWP_TABLET_TOOL_V2_TYPE_BRUSH:
546                 return "brush";
547         case ZWP_TABLET_TOOL_V2_TYPE_PENCIL:
548                 return "pencil";
549         case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH:
550                 return "airbrush";
551         case ZWP_TABLET_TOOL_V2_TYPE_FINGER:
552                 return "finger";
553         case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
554                 return "mouse";
555         case ZWP_TABLET_TOOL_V2_TYPE_LENS:
556                 return "lens";
557         }
558
559         return "Unknown type";
560 }
561
562 static void
563 print_tablet_tool_info(const struct tablet_tool_info *info)
564 {
565         printf("\t\ttablet_tool: %s\n", tablet_tool_type_to_str(info->type));
566         if (info->hardware_serial) {
567                 printf("\t\t\thardware serial: %lx\n", info->hardware_serial);
568         }
569         if (info->hardware_id_wacom) {
570                 printf("\t\t\thardware wacom: %lx\n", info->hardware_id_wacom);
571         }
572
573         printf("\t\t\tcapabilities:");
574
575         if (info->has_tilt) {
576                 printf(" tilt");
577         }
578         if (info->has_pressure) {
579                 printf(" pressure");
580         }
581         if (info->has_distance) {
582                 printf(" distance");
583         }
584         if (info->has_rotation) {
585                 printf(" rotation");
586         }
587         if (info->has_slider) {
588                 printf(" slider");
589         }
590         if (info->has_wheel) {
591                 printf(" wheel");
592         }
593         printf("\n");
594 }
595
596 static void
597 destroy_tablet_tool_info(struct tablet_tool_info *info)
598 {
599         wl_list_remove(&info->link);
600         zwp_tablet_tool_v2_destroy(info->tool);
601         free(info);
602 }
603
604 static void
605 print_tablet_pad_group_info(const struct tablet_pad_group_info *info)
606 {
607         size_t i;
608         printf("\t\t\tgroup:\n");
609         printf("\t\t\t\tmodes: %u\n", info->modes);
610         printf("\t\t\t\tstrips: %zu\n", info->strips);
611         printf("\t\t\t\trings: %zu\n", info->rings);
612         printf("\t\t\t\tbuttons:");
613
614         for (i = 0; i < info->button_count; ++i) {
615                 printf(" %d", info->buttons[i]);
616         }
617
618         printf("\n");
619 }
620
621 static void
622 destroy_tablet_pad_group_info(struct tablet_pad_group_info *info)
623 {
624         wl_list_remove(&info->link);
625         zwp_tablet_pad_group_v2_destroy(info->group);
626
627         if (info->buttons) {
628                 free(info->buttons);
629         }
630         free(info);
631 }
632
633 static void
634 print_tablet_pad_info(const struct tablet_pad_info *info)
635 {
636         const struct tablet_v2_path *path;
637         const struct tablet_pad_group_info *group;
638
639         printf("\t\tpad:\n");
640         printf("\t\t\tbuttons: %u\n", info->buttons);
641
642         wl_list_for_each(path, &info->paths, link) {
643                 printf("\t\t\tpath: %s\n", path->path);
644         }
645
646         wl_list_for_each(group, &info->groups, link) {
647                 print_tablet_pad_group_info(group);
648         }
649 }
650
651 static void
652 destroy_tablet_pad_info(struct tablet_pad_info *info)
653 {
654         struct tablet_v2_path *path;
655         struct tablet_v2_path *tmp_path;
656         struct tablet_pad_group_info *group;
657         struct tablet_pad_group_info *tmp_group;
658
659         wl_list_remove(&info->link);
660         zwp_tablet_pad_v2_destroy(info->pad);
661
662         wl_list_for_each_safe(path, tmp_path, &info->paths, link) {
663                 wl_list_remove(&path->link);
664                 free(path->path);
665                 free(path);
666         }
667
668         wl_list_for_each_safe(group, tmp_group, &info->groups, link) {
669                 destroy_tablet_pad_group_info(group);
670         }
671
672         free(info);
673 }
674
675 static void
676 print_tablet_info(const struct tablet_info *info)
677 {
678         const struct tablet_v2_path *path;
679
680         printf("\t\ttablet: %s\n", info->name);
681         printf("\t\t\tvendor: %u\n", info->vid);
682         printf("\t\t\tproduct: %u\n", info->pid);
683
684         wl_list_for_each(path, &info->paths, link) {
685                 printf("\t\t\tpath: %s\n", path->path);
686         }
687 }
688
689 static void
690 destroy_tablet_info(struct tablet_info *info)
691 {
692         struct tablet_v2_path *path;
693         struct tablet_v2_path *tmp;
694
695         wl_list_remove(&info->link);
696         zwp_tablet_v2_destroy(info->tablet);
697
698         if (info->name) {
699                 free(info->name);
700         }
701
702         wl_list_for_each_safe(path, tmp, &info->paths, link) {
703                 wl_list_remove(&path->link);
704                 free(path->path);
705                 free(path);
706         }
707
708         free(info);
709 }
710
711 static void
712 print_tablet_seat_info(const struct tablet_seat_info *info)
713 {
714         const struct tablet_info *tablet;
715         const struct tablet_pad_info *pad;
716         const struct tablet_tool_info *tool;
717
718         printf("\ttablet_seat: %s\n", info->seat_info->name);
719
720         wl_list_for_each(tablet, &info->tablets, link) {
721                 print_tablet_info(tablet);
722         }
723
724         wl_list_for_each(pad, &info->pads, link) {
725                 print_tablet_pad_info(pad);
726         }
727
728         wl_list_for_each(tool, &info->tools, link) {
729                 print_tablet_tool_info(tool);
730         }
731 }
732
733 static void
734 destroy_tablet_seat_info(struct tablet_seat_info *info)
735 {
736         struct tablet_info *tablet;
737         struct tablet_info *tmp_tablet;
738         struct tablet_pad_info *pad;
739         struct tablet_pad_info *tmp_pad;
740         struct tablet_tool_info *tool;
741         struct tablet_tool_info *tmp_tool;
742
743         wl_list_remove(&info->link);
744         zwp_tablet_seat_v2_destroy(info->seat);
745
746         wl_list_for_each_safe(tablet, tmp_tablet, &info->tablets, link) {
747                 destroy_tablet_info(tablet);
748         }
749
750         wl_list_for_each_safe(pad, tmp_pad, &info->pads, link) {
751                 destroy_tablet_pad_info(pad);
752         }
753
754         wl_list_for_each_safe(tool, tmp_tool, &info->tools, link) {
755                 destroy_tablet_tool_info(tool);
756         }
757
758         free(info);
759 }
760
761 static void
762 print_tablet_v2_info(void *data)
763 {
764         struct tablet_v2_info *info = data;
765         struct tablet_seat_info *seat;
766         print_global_info(data);
767
768         wl_list_for_each(seat, &info->seats, link) {
769                 /* Skip tablet_seats without a tablet, they are irrelevant */
770                 if (wl_list_empty(&seat->pads) &&
771                     wl_list_empty(&seat->tablets) &&
772                     wl_list_empty(&seat->tools)) {
773                         continue;
774                 }
775
776                 print_tablet_seat_info(seat);
777         }
778 }
779
780 static void
781 destroy_tablet_v2_info(void *data)
782 {
783         struct tablet_v2_info *info = data;
784         struct tablet_seat_info *seat;
785         struct tablet_seat_info *tmp;
786
787         zwp_tablet_manager_v2_destroy(info->manager);
788
789         wl_list_for_each_safe(seat, tmp, &info->seats, link) {
790                 destroy_tablet_seat_info(seat);
791         }
792 }
793
794 static void
795 handle_tablet_v2_tablet_tool_done(void *data, struct zwp_tablet_tool_v2 *tool)
796 {
797         /* don't bother waiting for this; there's no good reason a
798          * compositor will wait more than one roundtrip before sending
799          * these initial events. */
800 }
801
802 static void
803 handle_tablet_v2_tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *tool)
804 {
805         /* don't bother waiting for this; we never make any request either way. */
806 }
807
808 static void
809 handle_tablet_v2_tablet_tool_type(void *data, struct zwp_tablet_tool_v2 *tool,
810                                   uint32_t tool_type)
811 {
812         struct tablet_tool_info *info = data;
813         info->type = tool_type;
814 }
815
816 static void
817 handle_tablet_v2_tablet_tool_hardware_serial(void *data,
818                                              struct zwp_tablet_tool_v2 *tool,
819                                              uint32_t serial_hi,
820                                              uint32_t serial_lo)
821 {
822         struct tablet_tool_info *info = data;
823
824         info->hardware_serial = ((uint64_t) serial_hi) << 32 |
825                 (uint64_t) serial_lo;
826 }
827
828 static void
829 handle_tablet_v2_tablet_tool_hardware_id_wacom(void *data,
830                                                struct zwp_tablet_tool_v2 *tool,
831                                                uint32_t id_hi, uint32_t id_lo)
832 {
833         struct tablet_tool_info *info = data;
834
835         info->hardware_id_wacom = ((uint64_t) id_hi) << 32 | (uint64_t) id_lo;
836 }
837
838 static void
839 handle_tablet_v2_tablet_tool_capability(void *data,
840                                         struct zwp_tablet_tool_v2 *tool,
841                                         uint32_t capability)
842 {
843         struct tablet_tool_info *info = data;
844         enum zwp_tablet_tool_v2_capability cap = capability;
845         
846         switch(cap) {
847         case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT:
848                 info->has_tilt = true;
849                 break;
850         case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE:
851                 info->has_pressure = true;
852                 break;
853         case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE:
854                 info->has_distance = true;
855                 break;
856         case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION:
857                 info->has_rotation = true;
858                 break;
859         case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER:
860                 info->has_slider = true;
861                 break;
862         case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL:
863                 info->has_wheel = true;
864                 break;
865         }
866 }
867
868 static void
869 handle_tablet_v2_tablet_tool_proximity_in(void *data,
870                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
871                                  uint32_t serial, struct zwp_tablet_v2 *tablet,
872                                  struct wl_surface *surface)
873 {
874
875 }
876
877 static void
878 handle_tablet_v2_tablet_tool_proximity_out(void *data,
879                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
880 {
881
882 }
883
884 static void
885 handle_tablet_v2_tablet_tool_down(void *data,
886                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
887                                  uint32_t serial)
888 {
889
890 }
891
892 static void
893 handle_tablet_v2_tablet_tool_up(void *data,
894                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
895 {
896
897 }
898
899
900 static void
901 handle_tablet_v2_tablet_tool_motion(void *data,
902                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
903                                  wl_fixed_t x,
904                                  wl_fixed_t y)
905 {
906
907 }
908
909 static void
910 handle_tablet_v2_tablet_tool_pressure(void *data,
911                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
912                                  uint32_t pressure)
913 {
914
915 }
916
917 static void
918 handle_tablet_v2_tablet_tool_distance(void *data,
919                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
920                                  uint32_t distance)
921 {
922
923 }
924
925 static void
926 handle_tablet_v2_tablet_tool_tilt(void *data,
927                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
928                                  wl_fixed_t tilt_x,
929                                  wl_fixed_t tilt_y)
930 {
931
932 }
933
934 static void
935 handle_tablet_v2_tablet_tool_rotation(void *data,
936                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
937                                  wl_fixed_t degrees)
938 {
939
940 }
941
942 static void
943 handle_tablet_v2_tablet_tool_slider(void *data,
944                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
945                                  int32_t position)
946 {
947
948 }
949
950 static void
951 handle_tablet_v2_tablet_tool_wheel(void *data,
952                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
953                                  wl_fixed_t degrees,
954                                  int32_t clicks)
955 {
956
957 }
958
959 static void
960 handle_tablet_v2_tablet_tool_button(void *data,
961                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
962                                  uint32_t serial,
963                                  uint32_t button,
964                                  uint32_t state)
965 {
966
967 }
968
969 static void
970 handle_tablet_v2_tablet_tool_frame(void *data,
971                                  struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
972                                  uint32_t time)
973 {
974
975 }
976
977 static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
978         .removed = handle_tablet_v2_tablet_tool_removed,
979         .done = handle_tablet_v2_tablet_tool_done,
980         .type = handle_tablet_v2_tablet_tool_type,
981         .hardware_serial = handle_tablet_v2_tablet_tool_hardware_serial,
982         .hardware_id_wacom = handle_tablet_v2_tablet_tool_hardware_id_wacom,
983         .capability = handle_tablet_v2_tablet_tool_capability,
984
985         .proximity_in = handle_tablet_v2_tablet_tool_proximity_in,
986         .proximity_out = handle_tablet_v2_tablet_tool_proximity_out,
987         .down = handle_tablet_v2_tablet_tool_down,
988         .up = handle_tablet_v2_tablet_tool_up,
989
990         .motion = handle_tablet_v2_tablet_tool_motion,
991         .pressure = handle_tablet_v2_tablet_tool_pressure,
992         .distance = handle_tablet_v2_tablet_tool_distance,
993         .tilt = handle_tablet_v2_tablet_tool_tilt,
994         .rotation = handle_tablet_v2_tablet_tool_rotation,
995         .slider = handle_tablet_v2_tablet_tool_slider,
996         .wheel = handle_tablet_v2_tablet_tool_wheel,
997         .button = handle_tablet_v2_tablet_tool_button,
998         .frame = handle_tablet_v2_tablet_tool_frame,
999 };
1000
1001 static void add_tablet_v2_tablet_tool_info(void *data,
1002                                      struct zwp_tablet_seat_v2 *tablet_seat_v2,
1003                                      struct zwp_tablet_tool_v2 *tool)
1004 {
1005         struct tablet_seat_info *tablet_seat = data;
1006         struct tablet_tool_info *tool_info = xzalloc(sizeof *tool_info);
1007
1008         tool_info->tool = tool;
1009         wl_list_insert(&tablet_seat->tools, &tool_info->link);
1010
1011         zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, tool_info);
1012 }
1013
1014 static void
1015 handle_tablet_v2_tablet_pad_group_mode_switch(void *data,
1016                        struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
1017                        uint32_t time, uint32_t serial, uint32_t mode)
1018 {
1019         /* This shouldn't ever happen  */
1020 }
1021
1022 static void
1023 handle_tablet_v2_tablet_pad_group_done(void *data,
1024                                        struct zwp_tablet_pad_group_v2 *group)
1025 {
1026         /* don't bother waiting for this; there's no good reason a
1027          * compositor will wait more than one roundtrip before sending
1028          * these initial events. */
1029 }
1030
1031 static void
1032 handle_tablet_v2_tablet_pad_group_modes(void *data,
1033                                         struct zwp_tablet_pad_group_v2 *group,
1034                                         uint32_t modes)
1035 {
1036         struct tablet_pad_group_info *info = data;
1037         info->modes = modes;
1038 }
1039
1040 static void
1041 handle_tablet_v2_tablet_pad_group_buttons(void *data,
1042                                           struct zwp_tablet_pad_group_v2 *group,
1043                                           struct wl_array *buttons)
1044 {
1045         struct tablet_pad_group_info *info = data;
1046
1047         info->button_count = buttons->size / sizeof(int);
1048         info->buttons = xzalloc(buttons->size);
1049         memcpy(info->buttons, buttons->data, buttons->size);
1050 }
1051
1052 static void
1053 handle_tablet_v2_tablet_pad_group_ring(void *data,
1054                                        struct zwp_tablet_pad_group_v2 *group,
1055                                        struct zwp_tablet_pad_ring_v2 *ring)
1056 {
1057         struct tablet_pad_group_info *info = data;
1058         ++info->rings;
1059
1060         zwp_tablet_pad_ring_v2_destroy(ring);
1061 }
1062
1063 static void
1064 handle_tablet_v2_tablet_pad_group_strip(void *data,
1065                                         struct zwp_tablet_pad_group_v2 *group,
1066                                         struct zwp_tablet_pad_strip_v2 *strip)
1067 {
1068         struct tablet_pad_group_info *info = data;
1069         ++info->strips;
1070
1071         zwp_tablet_pad_strip_v2_destroy(strip);
1072 }
1073
1074 static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = {
1075         .buttons = handle_tablet_v2_tablet_pad_group_buttons,
1076         .modes = handle_tablet_v2_tablet_pad_group_modes,
1077         .ring = handle_tablet_v2_tablet_pad_group_ring,
1078         .strip = handle_tablet_v2_tablet_pad_group_strip,
1079         .done = handle_tablet_v2_tablet_pad_group_done,
1080         .mode_switch = handle_tablet_v2_tablet_pad_group_mode_switch,
1081 };
1082
1083 static void
1084 handle_tablet_v2_tablet_pad_group(void *data,
1085                                   struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
1086                                   struct zwp_tablet_pad_group_v2 *pad_group)
1087 {
1088         struct tablet_pad_info *pad_info = data;
1089         struct tablet_pad_group_info *group = xzalloc(sizeof *group);
1090
1091         wl_list_insert(&pad_info->groups, &group->link);
1092         group->group = pad_group;
1093         zwp_tablet_pad_group_v2_add_listener(pad_group,
1094                                              &tablet_pad_group_listener, group);
1095 }
1096
1097 static void
1098 handle_tablet_v2_tablet_pad_path(void *data, struct zwp_tablet_pad_v2 *pad,
1099                                  const char *path)
1100 {
1101         struct tablet_pad_info *pad_info = data;
1102         struct tablet_v2_path *path_elem = xzalloc(sizeof *path_elem);
1103         path_elem->path = xstrdup(path);
1104
1105         wl_list_insert(&pad_info->paths, &path_elem->link);
1106 }
1107
1108 static void
1109 handle_tablet_v2_tablet_pad_buttons(void *data, struct zwp_tablet_pad_v2 *pad,
1110                                     uint32_t buttons)
1111 {
1112         struct tablet_pad_info *pad_info = data;
1113
1114         pad_info->buttons = buttons;
1115 }
1116
1117 static void
1118 handle_tablet_v2_tablet_pad_done(void *data, struct zwp_tablet_pad_v2 *pad)
1119 {
1120         /* don't bother waiting for this; there's no good reason a
1121          * compositor will wait more than one roundtrip before sending
1122          * these initial events. */
1123 }
1124
1125 static void
1126 handle_tablet_v2_tablet_pad_removed(void *data, struct zwp_tablet_pad_v2 *pad)
1127 {
1128         /* don't bother waiting for this; We never make any request that's not
1129          * allowed to be issued either way. */
1130 }
1131
1132 static void
1133 handle_tablet_v2_tablet_pad_button(void *data, struct zwp_tablet_pad_v2 *pad,
1134                                    uint32_t time, uint32_t button, uint32_t state)
1135 {
1136         /* we don't have a surface, so this can't ever happen */
1137 }
1138
1139 static void
1140 handle_tablet_v2_tablet_pad_enter(void *data, struct zwp_tablet_pad_v2 *pad,
1141                                   uint32_t serial,
1142                                   struct zwp_tablet_v2 *tablet,
1143                                   struct wl_surface *surface)
1144 {
1145         /* we don't have a surface, so this can't ever happen */
1146 }
1147
1148 static void
1149 handle_tablet_v2_tablet_pad_leave(void *data, struct zwp_tablet_pad_v2 *pad,
1150                 uint32_t serial, struct wl_surface *surface)
1151 {
1152         /* we don't have a surface, so this can't ever happen */
1153 }
1154
1155 static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
1156         .group = handle_tablet_v2_tablet_pad_group,
1157         .path = handle_tablet_v2_tablet_pad_path,
1158         .buttons = handle_tablet_v2_tablet_pad_buttons,
1159         .done = handle_tablet_v2_tablet_pad_done,
1160         .removed = handle_tablet_v2_tablet_pad_removed,
1161         .button = handle_tablet_v2_tablet_pad_button,
1162         .enter = handle_tablet_v2_tablet_pad_enter,
1163         .leave = handle_tablet_v2_tablet_pad_leave,
1164 };
1165
1166 static void add_tablet_v2_tablet_pad_info(void *data,
1167                                      struct zwp_tablet_seat_v2 *tablet_seat_v2,
1168                                      struct zwp_tablet_pad_v2 *pad)
1169 {
1170         struct tablet_seat_info *tablet_seat = data;
1171         struct tablet_pad_info *pad_info = xzalloc(sizeof *pad_info);
1172
1173         wl_list_init(&pad_info->paths);
1174         wl_list_init(&pad_info->groups);
1175         pad_info->pad = pad;
1176         wl_list_insert(&tablet_seat->pads, &pad_info->link);
1177
1178         zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener, pad_info);
1179 }
1180
1181 static void
1182 handle_tablet_v2_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
1183                              const char *name)
1184 {
1185         struct tablet_info *tablet_info = data;
1186         tablet_info->name = xstrdup(name);
1187 }
1188
1189 static void
1190 handle_tablet_v2_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
1191                              const char *path)
1192 {
1193         struct tablet_info *tablet_info = data;
1194         struct tablet_v2_path *path_elem = xzalloc(sizeof *path_elem);
1195         path_elem->path = xstrdup(path);
1196
1197         wl_list_insert(&tablet_info->paths, &path_elem->link);
1198 }
1199
1200 static void
1201 handle_tablet_v2_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
1202                            uint32_t vid, uint32_t pid)
1203 {
1204         struct tablet_info *tablet_info = data;
1205
1206         tablet_info->vid = vid;
1207         tablet_info->pid = pid;
1208 }
1209
1210 static void
1211 handle_tablet_v2_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2)
1212 {
1213         /* don't bother waiting for this; there's no good reason a
1214          * compositor will wait more than one roundtrip before sending
1215          * these initial events. */
1216 }
1217
1218 static void
1219 handle_tablet_v2_tablet_removed(void *data, struct zwp_tablet_v2 *zwp_tablet_v2)
1220 {
1221         /* don't bother waiting for this; We never make any request that's not
1222          * allowed to be issued either way. */
1223 }
1224
1225 static const struct zwp_tablet_v2_listener tablet_listener = {
1226         .name = handle_tablet_v2_tablet_name,
1227         .id = handle_tablet_v2_tablet_id,
1228         .path = handle_tablet_v2_tablet_path,
1229         .done = handle_tablet_v2_tablet_done,
1230         .removed = handle_tablet_v2_tablet_removed
1231 };
1232
1233 static void
1234 add_tablet_v2_tablet_info(void *data, struct zwp_tablet_seat_v2 *tablet_seat_v2,
1235                           struct zwp_tablet_v2 *tablet)
1236 {
1237         struct tablet_seat_info *tablet_seat = data;
1238         struct tablet_info *tablet_info = xzalloc(sizeof *tablet_info);
1239
1240         wl_list_init(&tablet_info->paths);
1241         tablet_info->tablet = tablet;
1242         wl_list_insert(&tablet_seat->tablets, &tablet_info->link);
1243
1244         zwp_tablet_v2_add_listener(tablet, &tablet_listener, tablet_info);
1245 }
1246
1247 static const struct zwp_tablet_seat_v2_listener tablet_seat_listener =  {
1248         .tablet_added = add_tablet_v2_tablet_info,
1249         .pad_added = add_tablet_v2_tablet_pad_info,
1250         .tool_added = add_tablet_v2_tablet_tool_info,
1251 };
1252
1253 static void
1254 add_tablet_seat_info(struct tablet_v2_info *tablet_info, struct seat_info *seat)
1255 {
1256         struct tablet_seat_info *tablet_seat = xzalloc(sizeof *tablet_seat);
1257
1258         wl_list_insert(&tablet_info->seats, &tablet_seat->link);
1259         tablet_seat->seat = zwp_tablet_manager_v2_get_tablet_seat(
1260                 tablet_info->manager, seat->seat);
1261         zwp_tablet_seat_v2_add_listener(tablet_seat->seat,
1262                 &tablet_seat_listener, tablet_seat);
1263
1264         wl_list_init(&tablet_seat->pads);
1265         wl_list_init(&tablet_seat->tablets);
1266         wl_list_init(&tablet_seat->tools);
1267         tablet_seat->seat_info = seat;
1268
1269         tablet_info->info->roundtrip_needed = true;
1270 }
1271
1272 static void
1273 add_tablet_v2_info(struct weston_info *info, uint32_t id, uint32_t version)
1274 {
1275         struct seat_info *seat;
1276         struct tablet_v2_info *tablet = xzalloc(sizeof *tablet);
1277
1278         wl_list_init(&tablet->seats);
1279         tablet->info = info;
1280
1281         init_global_info(info, &tablet->global, id,
1282                 zwp_tablet_manager_v2_interface.name, version);
1283         tablet->global.print = print_tablet_v2_info;
1284         tablet->global.destroy = destroy_tablet_v2_info;
1285
1286         tablet->manager = wl_registry_bind(info->registry,
1287                 id, &zwp_tablet_manager_v2_interface, 1);
1288
1289         wl_list_for_each(seat, &info->seats, global_link) {
1290                 add_tablet_seat_info(tablet, seat);
1291         }
1292
1293         info->tablet_info = tablet;
1294 }
1295
1296 static void
1297 add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
1298 {
1299         struct seat_info *seat = xzalloc(sizeof *seat);
1300
1301         /* required to set roundtrip_needed to true in capabilities
1302          * handler */
1303         seat->info = info;
1304
1305         init_global_info(info, &seat->global, id, "wl_seat", version);
1306         seat->global.print = print_seat_info;
1307         seat->global.destroy = destroy_seat_info;
1308
1309         seat->seat = wl_registry_bind(info->registry,
1310                                       id, &wl_seat_interface, MIN(version, 4));
1311         wl_seat_add_listener(seat->seat, &seat_listener, seat);
1312
1313         seat->repeat_rate = seat->repeat_delay = -1;
1314
1315         info->roundtrip_needed = true;
1316         wl_list_insert(&info->seats, &seat->global_link);
1317
1318         if (info->tablet_info) {
1319                 add_tablet_seat_info(info->tablet_info, seat);
1320         }
1321 }
1322
1323 static void
1324 shm_handle_format(void *data, struct wl_shm *wl_shm, uint32_t format)
1325 {
1326         struct shm_info *shm = data;
1327         struct shm_format *shm_format = xzalloc(sizeof *shm_format);
1328
1329         wl_list_insert(&shm->formats, &shm_format->link);
1330         shm_format->format = format;
1331 }
1332
1333 static const struct wl_shm_listener shm_listener = {
1334         shm_handle_format,
1335 };
1336
1337 static void
1338 destroy_shm_info(void *data)
1339 {
1340         struct shm_info *shm = data;
1341         struct shm_format *format, *tmp;
1342
1343         wl_list_for_each_safe(format, tmp, &shm->formats, link) {
1344                 wl_list_remove(&format->link);
1345                 free(format);
1346         }
1347
1348         wl_shm_destroy(shm->shm);
1349 }
1350
1351 static void
1352 add_shm_info(struct weston_info *info, uint32_t id, uint32_t version)
1353 {
1354         struct shm_info *shm = xzalloc(sizeof *shm);
1355
1356         init_global_info(info, &shm->global, id, "wl_shm", version);
1357         shm->global.print = print_shm_info;
1358         shm->global.destroy = destroy_shm_info;
1359
1360         wl_list_init(&shm->formats);
1361
1362         shm->shm = wl_registry_bind(info->registry,
1363                                     id, &wl_shm_interface, 1);
1364         wl_shm_add_listener(shm->shm, &shm_listener, shm);
1365
1366         info->roundtrip_needed = true;
1367 }
1368
1369 static void
1370 linux_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1, uint32_t format)
1371 {
1372         /* This is a deprecated event, don’t use it. */
1373 }
1374
1375 static void
1376 linux_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1, uint32_t format, uint32_t modifier_hi, uint32_t modifier_lo)
1377 {
1378         struct linux_dmabuf_info *dmabuf = data;
1379         struct linux_dmabuf_modifier *linux_dmabuf_modifier = xzalloc(sizeof *linux_dmabuf_modifier);
1380
1381         wl_list_insert(&dmabuf->modifiers, &linux_dmabuf_modifier->link);
1382         linux_dmabuf_modifier->format = format;
1383         linux_dmabuf_modifier->modifier = ((uint64_t)modifier_hi) << 32 | modifier_lo;
1384 }
1385
1386 static const struct zwp_linux_dmabuf_v1_listener linux_dmabuf_listener = {
1387         linux_dmabuf_handle_format,
1388         linux_dmabuf_handle_modifier,
1389 };
1390
1391 static void
1392 destroy_linux_dmabuf_info(void *data)
1393 {
1394         struct linux_dmabuf_info *dmabuf = data;
1395         struct linux_dmabuf_modifier *modifier, *tmp;
1396
1397         wl_list_for_each_safe(modifier, tmp, &dmabuf->modifiers, link) {
1398                 wl_list_remove(&modifier->link);
1399                 free(modifier);
1400         }
1401
1402         zwp_linux_dmabuf_v1_destroy(dmabuf->dmabuf);
1403 }
1404
1405 static void
1406 add_linux_dmabuf_info(struct weston_info *info, uint32_t id, uint32_t version)
1407 {
1408         struct linux_dmabuf_info *dmabuf = xzalloc(sizeof *dmabuf);
1409
1410         init_global_info(info, &dmabuf->global, id, "zwp_linux_dmabuf_v1", version);
1411         dmabuf->global.print = print_linux_dmabuf_info;
1412         dmabuf->global.destroy = destroy_linux_dmabuf_info;
1413
1414         wl_list_init(&dmabuf->modifiers);
1415
1416         if (version >= 3) {
1417                 dmabuf->dmabuf = wl_registry_bind(info->registry,
1418                                                   id, &zwp_linux_dmabuf_v1_interface, 3);
1419                 zwp_linux_dmabuf_v1_add_listener(dmabuf->dmabuf, &linux_dmabuf_listener, dmabuf);
1420
1421                 info->roundtrip_needed = true;
1422         }
1423 }
1424
1425 static void
1426 output_handle_geometry(void *data, struct wl_output *wl_output,
1427                        int32_t x, int32_t y,
1428                        int32_t physical_width, int32_t physical_height,
1429                        int32_t subpixel,
1430                        const char *make, const char *model,
1431                        int32_t output_transform)
1432 {
1433         struct output_info *output = data;
1434
1435         output->geometry.x = x;
1436         output->geometry.y = y;
1437         output->geometry.physical_width = physical_width;
1438         output->geometry.physical_height = physical_height;
1439         output->geometry.subpixel = subpixel;
1440         output->geometry.make = xstrdup(make);
1441         output->geometry.model = xstrdup(model);
1442         output->geometry.output_transform = output_transform;
1443 }
1444
1445 static void
1446 output_handle_mode(void *data, struct wl_output *wl_output,
1447                    uint32_t flags, int32_t width, int32_t height,
1448                    int32_t refresh)
1449 {
1450         struct output_info *output = data;
1451         struct output_mode *mode = xmalloc(sizeof *mode);
1452
1453         mode->flags = flags;
1454         mode->width = width;
1455         mode->height = height;
1456         mode->refresh = refresh;
1457
1458         wl_list_insert(output->modes.prev, &mode->link);
1459 }
1460
1461 static void
1462 output_handle_done(void *data, struct wl_output *wl_output)
1463 {
1464         /* don't bother waiting for this; there's no good reason a
1465          * compositor will wait more than one roundtrip before sending
1466          * these initial events. */
1467 }
1468
1469 static void
1470 output_handle_scale(void *data, struct wl_output *wl_output,
1471                     int32_t scale)
1472 {
1473         struct output_info *output = data;
1474
1475         output->geometry.scale = scale;
1476 }
1477
1478 static const struct wl_output_listener output_listener = {
1479         output_handle_geometry,
1480         output_handle_mode,
1481         output_handle_done,
1482         output_handle_scale,
1483 };
1484
1485 static void
1486 destroy_output_info(void *data)
1487 {
1488         struct output_info *output = data;
1489         struct output_mode *mode, *tmp;
1490
1491         wl_output_destroy(output->output);
1492
1493         if (output->geometry.make != NULL)
1494                 free(output->geometry.make);
1495         if (output->geometry.model != NULL)
1496                 free(output->geometry.model);
1497
1498         wl_list_for_each_safe(mode, tmp, &output->modes, link) {
1499                 wl_list_remove(&mode->link);
1500                 free(mode);
1501         }
1502 }
1503
1504 static void
1505 add_output_info(struct weston_info *info, uint32_t id, uint32_t version)
1506 {
1507         struct output_info *output = xzalloc(sizeof *output);
1508
1509         init_global_info(info, &output->global, id, "wl_output", version);
1510         output->global.print = print_output_info;
1511         output->global.destroy = destroy_output_info;
1512
1513         output->version = MIN(version, 2);
1514         output->geometry.scale = 1;
1515         wl_list_init(&output->modes);
1516
1517         output->output = wl_registry_bind(info->registry, id,
1518                                           &wl_output_interface, output->version);
1519         wl_output_add_listener(output->output, &output_listener,
1520                                output);
1521
1522         info->roundtrip_needed = true;
1523 }
1524
1525 static void
1526 destroy_presentation_info(void *info)
1527 {
1528         struct presentation_info *prinfo = info;
1529
1530         wp_presentation_destroy(prinfo->presentation);
1531 }
1532
1533 static const char *
1534 clock_name(clockid_t clk_id)
1535 {
1536         static const char *names[] = {
1537                 [CLOCK_REALTIME] =              "CLOCK_REALTIME",
1538                 [CLOCK_MONOTONIC] =             "CLOCK_MONOTONIC",
1539                 [CLOCK_MONOTONIC_RAW] =         "CLOCK_MONOTONIC_RAW",
1540                 [CLOCK_REALTIME_COARSE] =       "CLOCK_REALTIME_COARSE",
1541                 [CLOCK_MONOTONIC_COARSE] =      "CLOCK_MONOTONIC_COARSE",
1542 #ifdef CLOCK_BOOTTIME
1543                 [CLOCK_BOOTTIME] =              "CLOCK_BOOTTIME",
1544 #endif
1545         };
1546
1547         if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
1548                 return "unknown";
1549
1550         return names[clk_id];
1551 }
1552
1553 static void
1554 print_presentation_info(void *info)
1555 {
1556         struct presentation_info *prinfo = info;
1557
1558         print_global_info(info);
1559
1560         printf("\tpresentation clock id: %d (%s)\n",
1561                 prinfo->clk_id, clock_name(prinfo->clk_id));
1562 }
1563
1564 static void
1565 presentation_handle_clock_id(void *data, struct wp_presentation *presentation,
1566                              uint32_t clk_id)
1567 {
1568         struct presentation_info *prinfo = data;
1569
1570         prinfo->clk_id = clk_id;
1571 }
1572
1573 static const struct wp_presentation_listener presentation_listener = {
1574         presentation_handle_clock_id
1575 };
1576
1577 static void
1578 add_presentation_info(struct weston_info *info, uint32_t id, uint32_t version)
1579 {
1580         struct presentation_info *prinfo = xzalloc(sizeof *prinfo);
1581
1582         init_global_info(info, &prinfo->global, id,
1583                          wp_presentation_interface.name, version);
1584         prinfo->global.print = print_presentation_info;
1585         prinfo->global.destroy = destroy_presentation_info;
1586
1587         prinfo->clk_id = -1;
1588         prinfo->presentation = wl_registry_bind(info->registry, id,
1589                                                 &wp_presentation_interface, 1);
1590         wp_presentation_add_listener(prinfo->presentation,
1591                                      &presentation_listener, prinfo);
1592
1593         info->roundtrip_needed = true;
1594 }
1595
1596 static void
1597 destroy_global_info(void *data)
1598 {
1599 }
1600
1601 static void
1602 add_global_info(struct weston_info *info, uint32_t id,
1603                 const char *interface, uint32_t version)
1604 {
1605         struct global_info *global = xzalloc(sizeof *global);
1606
1607         init_global_info(info, global, id, interface, version);
1608         global->print = print_global_info;
1609         global->destroy = destroy_global_info;
1610 }
1611
1612 static void
1613 global_handler(void *data, struct wl_registry *registry, uint32_t id,
1614                const char *interface, uint32_t version)
1615 {
1616         struct weston_info *info = data;
1617
1618         if (!strcmp(interface, "wl_seat"))
1619                 add_seat_info(info, id, version);
1620         else if (!strcmp(interface, "wl_shm"))
1621                 add_shm_info(info, id, version);
1622         else if (!strcmp(interface, "zwp_linux_dmabuf_v1"))
1623                 add_linux_dmabuf_info(info, id, version);
1624         else if (!strcmp(interface, "wl_output"))
1625                 add_output_info(info, id, version);
1626         else if (!strcmp(interface, wp_presentation_interface.name))
1627                 add_presentation_info(info, id, version);
1628         else if (!strcmp(interface, zwp_tablet_manager_v2_interface.name))
1629                 add_tablet_v2_info(info, id, version);
1630         else
1631                 add_global_info(info, id, interface, version);
1632 }
1633
1634 static void
1635 global_remove_handler(void *data, struct wl_registry *registry, uint32_t name)
1636 {
1637 }
1638
1639 static const struct wl_registry_listener registry_listener = {
1640         global_handler,
1641         global_remove_handler
1642 };
1643
1644 static void
1645 print_infos(struct wl_list *infos)
1646 {
1647         struct global_info *info;
1648
1649         wl_list_for_each(info, infos, link)
1650                 info->print(info);
1651 }
1652
1653 static void
1654 destroy_info(void *data)
1655 {
1656         struct global_info *global = data;
1657
1658         global->destroy(data);
1659         wl_list_remove(&global->link);
1660         free(global->interface);
1661         free(data);
1662 }
1663
1664 static void
1665 destroy_infos(struct wl_list *infos)
1666 {
1667         struct global_info *info, *tmp;
1668         wl_list_for_each_safe(info, tmp, infos, link)
1669                 destroy_info(info);
1670 }
1671
1672 int
1673 main(int argc, char **argv)
1674 {
1675         struct weston_info info;
1676
1677         info.display = wl_display_connect(NULL);
1678         if (!info.display) {
1679                 fprintf(stderr, "failed to create display: %m\n");
1680                 return -1;
1681         }
1682
1683         info.tablet_info = NULL;
1684         wl_list_init(&info.infos);
1685         wl_list_init(&info.seats);
1686
1687         info.registry = wl_display_get_registry(info.display);
1688         wl_registry_add_listener(info.registry, &registry_listener, &info);
1689
1690         do {
1691                 info.roundtrip_needed = false;
1692                 wl_display_roundtrip(info.display);
1693         } while (info.roundtrip_needed);
1694
1695         print_infos(&info.infos);
1696         destroy_infos(&info.infos);
1697
1698         wl_registry_destroy(info.registry);
1699         wl_display_disconnect(info.display);
1700
1701         return 0;
1702 }