main: We don't have weston-debug extension available
[src/agl-compositor.git] / src / main.c
1 /*
2  * Copyright © 2012-2019 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "ivi-compositor.h"
27 #include "policy.h"
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <signal.h>
32 #include <stdarg.h>
33 #include <stdbool.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <linux/input.h>
39
40 #include <libweston/backend-drm.h>
41 #include <libweston/backend-wayland.h>
42 #ifdef HAVE_BACKEND_X11
43 #include <libweston/backend-x11.h>
44 #endif
45 #include <libweston/libweston.h>
46 #include <libweston/windowed-output-api.h>
47 #include <libweston/config-parser.h>
48 #include <libweston/weston-log.h>
49
50 #include "shared/os-compatibility.h"
51 #include "shared/helpers.h"
52
53 #include "agl-shell-server-protocol.h"
54
55 struct ivi_compositor *
56 to_ivi_compositor(struct weston_compositor *ec)
57 {
58         return weston_compositor_get_user_data(ec);
59 }
60
61 static void
62 handle_output_destroy(struct wl_listener *listener, void *data)
63 {
64         struct ivi_output *output;
65
66         output = wl_container_of(listener, output, output_destroy);
67         assert(output->output == data);
68
69         output->output = NULL;
70         wl_list_remove(&output->output_destroy.link);
71 }
72
73 struct ivi_output *
74 to_ivi_output(struct weston_output *o)
75 {
76         struct wl_listener *listener;
77         struct ivi_output *output;
78
79         listener = weston_output_get_destroy_listener(o, handle_output_destroy);
80         output = wl_container_of(listener, output, output_destroy);
81
82         return output;
83 }
84
85 static struct ivi_output *
86 ivi_ensure_output(struct ivi_compositor *ivi, char *name,
87                   struct weston_config_section *config)
88 {
89         struct ivi_output *output = NULL;
90         wl_list_for_each(output, &ivi->outputs, link) {
91                 if (strcmp(output->name, name) == 0) {
92                         free(name);
93                         return output;
94                 }
95         }
96
97         output = zalloc(sizeof *output);
98         if (!output) {
99                 free(name);
100                 return NULL;
101         }
102
103         output->ivi = ivi;
104         output->name = name;
105         output->config = config;
106
107         output->output = weston_compositor_create_output(ivi->compositor, name);
108         if (!output->output) {
109                 free(output->name);
110                 free(output);
111                 return NULL;
112         }
113
114         output->output_destroy.notify = handle_output_destroy;
115         weston_output_add_destroy_listener(output->output,
116                                            &output->output_destroy);
117
118         wl_list_insert(&ivi->outputs, &output->link);
119         return output;
120 }
121
122 static int
123 count_heads(struct weston_output *output)
124 {
125         struct weston_head *iter = NULL;
126         int n = 0;
127
128         while ((iter = weston_output_iterate_heads(output, iter)))
129                 ++n;
130
131         return n;
132 }
133
134 static void
135 handle_head_destroy(struct wl_listener *listener, void *data)
136 {
137         struct weston_head *head = data;
138         struct weston_output *output;
139
140         wl_list_remove(&listener->link);
141         free(listener);
142
143         output = weston_head_get_output(head);
144
145         /* On shutdown path, the output might be already gone. */
146         if (!output)
147                 return;
148
149         /* We're the last head */
150         if (count_heads(output) <= 1)
151                 weston_output_destroy(output);
152 }
153
154 static void
155 add_head_destroyed_listener(struct weston_head *head)
156 {
157         /* We already have a destroy listener */
158         if (weston_head_get_destroy_listener(head, handle_head_destroy))
159                 return;
160
161         struct wl_listener *listener = zalloc(sizeof *listener);
162         if (!listener)
163                 return;
164
165         listener->notify = handle_head_destroy;
166         weston_head_add_destroy_listener(head, listener);
167 }
168
169 static int
170 drm_configure_output(struct ivi_output *output)
171 {
172         struct ivi_compositor *ivi = output->ivi;
173         struct weston_config_section *section = output->config;
174         enum weston_drm_backend_output_mode mode =
175                 WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
176         char *modeline = NULL;
177         char *gbm_format = NULL;
178         char *seat = NULL;
179
180         if (section) {
181                 char *m;
182                 weston_config_section_get_string(section, "mode", &m, "preferred");
183
184                 /* This should have been handled earlier */
185                 assert(strcmp(m, "off") != 0);
186
187                 if (ivi->cmdline.use_current_mode || strcmp(m, "current") == 0) {
188                         mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
189                 } else if (strcmp(m, "preferred") != 0) {
190                         modeline = m;
191                         m = NULL;
192                 }
193                 free(m);
194
195                 weston_config_section_get_string(section, "gbm-format",
196                                                  &gbm_format, NULL);
197
198                 weston_config_section_get_string(section, "seat", &seat, "");
199         }
200
201         if (ivi->drm_api->set_mode(output->output, mode, modeline) < 0) {
202                 weston_log("Cannot configure output using weston_drm_output_api.\n");
203                 free(modeline);
204                 return -1;
205         }
206         free(modeline);
207
208         ivi->drm_api->set_gbm_format(output->output, gbm_format);
209         free(gbm_format);
210
211         ivi->drm_api->set_seat(output->output, seat);
212         free(seat);
213
214         return 0;
215 }
216
217 #define WINDOWED_DEFAULT_WIDTH 1024
218 #define WINDOWED_DEFAULT_HEIGHT 768
219
220 static int
221 windowed_configure_output(struct ivi_output *output)
222 {
223         struct ivi_compositor *ivi = output->ivi;
224         struct weston_config_section *section = output->config;
225         int width = WINDOWED_DEFAULT_WIDTH;
226         int height = WINDOWED_DEFAULT_HEIGHT;
227
228         if (section) {
229                 char *mode;
230
231                 weston_config_section_get_string(section, "mode", &mode, NULL);
232                 if (!mode || sscanf(mode, "%dx%d", &width, &height) != 2) {
233                         weston_log("Invalid mode for output %s. Using defaults.\n",
234                                    output->name);
235                         width = WINDOWED_DEFAULT_WIDTH;
236                         height = WINDOWED_DEFAULT_HEIGHT;
237                 }
238                 free(mode);
239         }
240
241         if (ivi->cmdline.width)
242                 width = ivi->cmdline.width;
243         if (ivi->cmdline.height)
244                 height = ivi->cmdline.height;
245         if (ivi->cmdline.scale)
246                 weston_output_set_scale(output->output, ivi->cmdline.scale);
247
248         if (ivi->window_api->output_set_size(output->output, width, height) < 0) {
249                 weston_log("Cannot configure output '%s' using weston_windowed_output_api.\n",
250                            output->name);
251                 return -1;
252         }
253
254         return 0;
255 }
256
257 static int
258 parse_transform(const char *transform, uint32_t *out)
259 {
260         static const struct { const char *name; uint32_t token; } transforms[] = {
261                 { "normal",     WL_OUTPUT_TRANSFORM_NORMAL },
262                 { "90",         WL_OUTPUT_TRANSFORM_90 },
263                 { "180",        WL_OUTPUT_TRANSFORM_180 },
264                 { "270",        WL_OUTPUT_TRANSFORM_270 },
265                 { "flipped",    WL_OUTPUT_TRANSFORM_FLIPPED },
266                 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
267                 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
268                 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
269         };
270
271         for (size_t i = 0; i < ARRAY_LENGTH(transforms); i++)
272                 if (strcmp(transforms[i].name, transform) == 0) {
273                         *out = transforms[i].token;
274                         return 0;
275                 }
276
277         *out = WL_OUTPUT_TRANSFORM_NORMAL;
278         return -1;
279 }
280
281 static int
282 configure_output(struct ivi_output *output)
283 {
284         struct ivi_compositor *ivi = output->ivi;
285         struct weston_config_section *section = output->config;
286         int32_t scale = 1;
287         uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL;
288
289         /*
290          * This can happen with the wayland backend with 'sprawl'. The config
291          * is hard-coded, so we don't need to do anything.
292          */
293         if (!ivi->drm_api && !ivi->window_api)
294                 return 0;
295
296         if (section) {
297                 char *t;
298
299                 weston_config_section_get_int(section, "scale", &scale, 1);
300                 weston_config_section_get_string(section, "transform", &t, "normal");
301                 if (parse_transform(t, &transform) < 0)
302                         weston_log("Invalid transform \"%s\" for output %s\n",
303                                    t, output->name);
304                 free(t);
305         }
306
307         weston_output_set_scale(output->output, scale);
308         weston_output_set_transform(output->output, transform);
309
310         if (ivi->drm_api)
311                 return drm_configure_output(output);
312         else
313                 return windowed_configure_output(output);
314 }
315
316 /*
317  * Reorgainizes the output's add array into two sections.
318  * add[0..ret-1] are the heads that failed to get attached.
319  * add[ret..add_len] are the heads that were successfully attached.
320  *
321  * The order between elements in each section is stable.
322  */
323 static size_t
324 try_attach_heads(struct ivi_output *output)
325 {
326         size_t fail_len = 0;
327
328         for (size_t i = 0; i < output->add_len; ++i) {
329                 if (weston_output_attach_head(output->output, output->add[i]) < 0) {
330                         struct weston_head *tmp = output->add[i];
331                         memmove(&output->add[fail_len + 1], output->add[fail_len],
332                                 sizeof output->add[0] * (i - fail_len));
333                         output->add[fail_len++] = tmp;
334                 }
335         }
336
337         return fail_len;
338 }
339
340 /*
341  * Like try_attach_heads, this reorganizes the output's add array into a failed
342  * and successful section.
343  * i is the number of heads that already failed the previous step.
344  */
345 static size_t
346 try_enable_output(struct ivi_output *output, size_t i)
347 {
348         for (; i < output->add_len; ++i) {
349                 struct weston_head *head;
350
351                 if (weston_output_enable(output->output) == 0)
352                         break;
353
354                 head = output->add[output->add_len - 1];
355                 memmove(&output->add[i + 1], &output->add[i],
356                         sizeof output->add[0] * (output->add_len - i));
357                 output->add[i] = head;
358
359                 weston_head_detach(head);
360         }
361
362         return i;
363 }
364
365 static int
366 try_attach_enable_heads(struct ivi_output *output)
367 {
368         size_t fail_len;
369         assert(!output->output->enabled);
370
371         fail_len = try_attach_heads(output);
372
373         if (configure_output(output) < 0)
374                 return -1;
375
376         fail_len = try_enable_output(output, fail_len);
377
378         /* All heads failed to be attached */
379         if (fail_len == output->add_len)
380                 return -1;
381
382         /* For each successful head attached */
383         for (size_t i = fail_len; i < output->add_len; ++i)
384                 add_head_destroyed_listener(output->add[i]);
385
386         output->add_len = fail_len;
387         return 0;
388 }
389
390 static int
391 process_output(struct ivi_output *output)
392 {
393         if (output->output->enabled) {
394                 output->add_len = try_attach_heads(output);
395                 return output->add_len == 0 ? 0 : -1;
396         }
397
398         return try_attach_enable_heads(output);
399 }
400
401 static void
402 head_disable(struct ivi_compositor *ivi, struct weston_head *head)
403 {
404         struct weston_output *output;
405         struct ivi_output *ivi_output;
406         struct wl_listener *listener;
407
408         output = weston_head_get_output(head);
409         assert(output);
410
411         listener = weston_output_get_destroy_listener(output,
412                                                       handle_output_destroy);
413         assert(listener);
414
415         ivi_output = wl_container_of(listener, ivi_output, output_destroy);
416         assert(ivi_output->output == output);
417
418         weston_head_detach(head);
419         if (count_heads(ivi_output->output) == 0) {
420                 weston_output_disable(ivi_output->output);
421         }
422 }
423
424 static struct weston_config_section *
425 find_controlling_output_config(struct weston_config *config,
426                                const char *name)
427 {
428         struct weston_config_section *section;
429         char *same_as;
430         int depth = 0;
431
432         same_as = strdup(name);
433         do {
434                 section = weston_config_get_section(config, "output",
435                                                     "name", same_as);
436                 if (!section && depth > 0)
437                         weston_log("Configuration error: output section reffered"
438                                    "to by same-as=%s not found.\n", same_as);
439                 free(same_as);
440
441                 if (!section)
442                         return NULL;
443
444                 if (depth++ > 8) {
445                         weston_log("Configuration error: same-as nested too "
446                                    "deep for output '%s'.\n", name);
447                         return NULL;
448                 }
449
450                 weston_config_section_get_string(section, "same-as",
451                                                  &same_as, NULL);
452         } while (same_as);
453
454         return section;
455 }
456
457 static void
458 head_prepare_enable(struct ivi_compositor *ivi, struct weston_head *head)
459 {
460         const char *name = weston_head_get_name(head);
461         struct weston_config_section *section;
462         struct ivi_output *output;
463         char *output_name = NULL;
464
465         section = find_controlling_output_config(ivi->config, name);
466         if (section) {
467                 char *mode;
468
469                 weston_config_section_get_string(section, "mode", &mode, NULL);
470                 if (mode && strcmp(mode, "off") == 0) {
471                         free(mode);
472                         return;
473                 }
474                 free(mode);
475
476                 weston_config_section_get_string(section, "name",
477                                                  &output_name, NULL);
478         } else {
479                 output_name = strdup(name);
480         }
481
482         if (!output_name)
483                 return;
484
485         output = ivi_ensure_output(ivi, output_name, section);
486         if (!output)
487                 return;
488
489         if (output->add_len >= ARRAY_LENGTH(output->add))
490                 return;
491
492         output->add[output->add_len++] = head;
493 }
494
495 static void
496 heads_changed(struct wl_listener *listener, void *arg)
497 {
498         struct weston_compositor *compositor = arg;
499         struct weston_head *head = NULL;
500         struct ivi_compositor *ivi = to_ivi_compositor(compositor);
501         struct ivi_output *output;
502
503         while ((head = weston_compositor_iterate_heads(ivi->compositor, head))) {
504                 bool connected = weston_head_is_connected(head);
505                 bool enabled = weston_head_is_enabled(head);
506                 bool changed = weston_head_is_device_changed(head);
507                 bool non_desktop = weston_head_is_non_desktop(head);
508
509                 if (connected && !enabled && !non_desktop)
510                         head_prepare_enable(ivi, head);
511                 else if (!connected && enabled)
512                         head_disable(ivi, head);
513                 else if (enabled && changed)
514                         weston_log("Detected a monitor change on head '%s', "
515                                    "not bothering to do anything about it.\n",
516                                    weston_head_get_name(head));
517
518                 weston_head_reset_device_changed(head);
519         }
520
521         wl_list_for_each(output, &ivi->outputs, link) {
522                 if (output->add_len == 0)
523                         continue;
524
525                 if (process_output(output) < 0) {
526                         output->add_len = 0;
527                         ivi->init_failed = true;
528                 }
529         }
530 }
531
532 static int
533 load_drm_backend(struct ivi_compositor *ivi, int *argc, char *argv[])
534 {
535         struct weston_drm_backend_config config = {
536                 .base = {
537                         .struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION,
538                         .struct_size = sizeof config,
539                 },
540         };
541         struct weston_config_section *section;
542         int use_current_mode = 0;
543         int use_pixman = 0;
544         bool use_shadow;
545         int ret;
546
547         const struct weston_option options[] = {
548                 { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
549                 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
550                 { WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
551                 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &use_current_mode },
552                 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman },
553         };
554
555         parse_options(options, ARRAY_LENGTH(options), argc, argv);
556         config.use_pixman = use_pixman;
557         ivi->cmdline.use_current_mode = use_current_mode;
558
559         section = weston_config_get_section(ivi->config, "core", NULL, NULL);
560         weston_config_section_get_string(section, "gbm-format",
561                                          &config.gbm_format, NULL);
562         weston_config_section_get_uint(section, "pageflip-timeout",
563                                        &config.pageflip_timeout, 0);
564         weston_config_section_get_bool(section, "pixman-shadow", &use_shadow, 1);
565         config.use_pixman_shadow = use_shadow;
566
567         ret = weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_DRM,
568                                              &config.base);
569         if (ret < 0)
570                 return ret;
571
572         ivi->drm_api = weston_drm_output_get_api(ivi->compositor);
573         if (!ivi->drm_api) {
574                 weston_log("Cannot use drm output api.\n");
575                 ret = -1;
576                 goto error;
577         }
578
579 error:
580         free(config.gbm_format);
581         free(config.seat_id);
582         return ret;
583 }
584
585 static void
586 windowed_parse_common_options(struct ivi_compositor *ivi, int *argc, char *argv[],
587                               bool *use_pixman, bool *fullscreen, int *output_count)
588 {
589         struct weston_config_section *section;
590         bool pixman;
591         int fs = 0;
592
593         const struct weston_option options[] = {
594                 { WESTON_OPTION_INTEGER, "width", 0, &ivi->cmdline.width },
595                 { WESTON_OPTION_INTEGER, "height", 0, &ivi->cmdline.height },
596                 { WESTON_OPTION_INTEGER, "scale", 0, &ivi->cmdline.scale },
597                 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &pixman },
598                 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fs },
599                 { WESTON_OPTION_INTEGER, "output-count", 0, output_count },
600         };
601
602         section = weston_config_get_section(ivi->config, "core", NULL, NULL);
603         weston_config_section_get_bool(section, "use-pixman", &pixman, 0);
604
605         *output_count = 1;
606         parse_options(options, ARRAY_LENGTH(options), argc, argv);
607         *use_pixman = pixman;
608         *fullscreen = fs;
609 }
610
611 static int
612 windowed_create_outputs(struct ivi_compositor *ivi, int output_count,
613                         const char *match_prefix, const char *name_prefix)
614 {
615         struct weston_config_section *section = NULL;
616         const char *section_name;
617         char *default_output = NULL;
618         int i = 0;
619         size_t match_len = strlen(match_prefix);
620
621         while (weston_config_next_section(ivi->config, &section, &section_name)) {
622                 char *output_name;
623
624                 if (i >= output_count)
625                         break;
626
627                 if (strcmp(section_name, "output") != 0)
628                         continue;
629
630                 weston_config_section_get_string(section, "name", &output_name, NULL);
631                 if (output_name == NULL)
632                         continue;
633                 if (strncmp(output_name, match_prefix, match_len) != 0) {
634                         free(output_name);
635                         continue;
636                 }
637
638                 if (ivi->window_api->create_head(ivi->compositor, output_name) < 0) {
639                         free(output_name);
640                         return -1;
641                 }
642
643                 free(output_name);
644                 ++i;
645         }
646
647         for (; i < output_count; ++i) {
648                 if (asprintf(&default_output, "%s%d", name_prefix, i) < 0)
649                         return -1;
650
651                 if (ivi->window_api->create_head(ivi->compositor, default_output) < 0) {
652                         free(default_output);
653                         return -1;
654                 }
655
656                 free(default_output);
657         }
658
659         return 0;
660 }
661
662 static int
663 load_wayland_backend(struct ivi_compositor *ivi, int *argc, char *argv[])
664 {
665         struct weston_wayland_backend_config config = {
666                 .base = {
667                         .struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION,
668                         .struct_size = sizeof config,
669                 },
670         };
671         struct weston_config_section *section;
672         int sprawl = 0;
673         int output_count;
674         int ret;
675
676         const struct weston_option options[] = {
677                 { WESTON_OPTION_STRING, "display", 0, &config.display_name },
678                 { WESTON_OPTION_STRING, "sprawl", 0, &sprawl },
679         };
680
681         windowed_parse_common_options(ivi, argc, argv, &config.use_pixman,
682                                       &config.fullscreen, &output_count);
683
684         parse_options(options, ARRAY_LENGTH(options), argc, argv);
685         config.sprawl = sprawl;
686
687         section = weston_config_get_section(ivi->config, "shell", NULL, NULL);
688         weston_config_section_get_string(section, "cursor-theme",
689                                          &config.cursor_theme, NULL);
690         weston_config_section_get_int(section, "cursor-size",
691                                       &config.cursor_size, 32);
692
693         ret = weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_WAYLAND,
694                                              &config.base);
695
696         free(config.cursor_theme);
697         free(config.display_name);
698
699         if (ret < 0)
700                 return ret;
701
702         ivi->window_api = weston_windowed_output_get_api(ivi->compositor);
703
704         /*
705          * We will just assume if load_backend() finished cleanly and
706          * windowed_output_api is not present that wayland backend is started
707          * with --sprawl or runs on fullscreen-shell. In this case, all values
708          * are hardcoded, so nothing can be configured; simply create and
709          * enable an output.
710          */
711         if (ivi->window_api == NULL)
712                 return 0;
713
714         return windowed_create_outputs(ivi, output_count, "WL", "wayland");
715 }
716
717 #ifdef HAVE_BACKEND_X11
718 static int
719 load_x11_backend(struct ivi_compositor *ivi, int *argc, char *argv[])
720 {
721         struct weston_x11_backend_config config = {
722                 .base = {
723                         .struct_version = WESTON_X11_BACKEND_CONFIG_VERSION,
724                         .struct_size = sizeof config,
725                 },
726         };
727         int no_input = 0;
728         int output_count;
729         int ret;
730
731         const struct weston_option options[] = {
732                { WESTON_OPTION_BOOLEAN, "no-input", 0, &no_input },
733         };
734
735         windowed_parse_common_options(ivi, argc, argv, &config.use_pixman,
736                                       &config.fullscreen, &output_count);
737
738         parse_options(options, ARRAY_LENGTH(options), argc, argv);
739         config.no_input = no_input;
740
741         ret = weston_compositor_load_backend(ivi->compositor, WESTON_BACKEND_X11,
742                                              &config.base);
743
744         if (ret < 0)
745                 return ret;
746
747         ivi->window_api = weston_windowed_output_get_api(ivi->compositor);
748         if (!ivi->window_api) {
749                 weston_log("Cannot use weston_windowed_output_api.\n");
750                 return -1;
751         }
752
753         return windowed_create_outputs(ivi, output_count, "X", "screen");
754 }
755 #else
756 static int
757 load_x11_backend(struct ivi_compositor *ivi, int *argc, char *argv[])
758 {
759         return -1;
760 }
761 #endif
762
763 static int
764 load_backend(struct ivi_compositor *ivi, const char *backend,
765              int *argc, char *argv[])
766 {
767         if (strcmp(backend, "drm-backend.so") == 0) {
768                 return load_drm_backend(ivi, argc, argv);
769         } else if (strcmp(backend, "wayland-backend.so") == 0) {
770                 return load_wayland_backend(ivi, argc, argv);
771         } else if (strcmp(backend, "x11-backend.so") == 0) {
772                 return load_x11_backend(ivi, argc, argv);
773         }
774
775         weston_log("fatal: unknown backend '%s'.\n", backend);
776         return -1;
777 }
778
779 static char *
780 choose_default_backend(void)
781 {
782         char *backend = NULL;
783
784         if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
785                 backend = strdup("wayland-backend.so");
786         else if (getenv("DISPLAY"))
787                 backend = strdup("x11-backend.so");
788         else
789                 backend = strdup("drm-backend.so");
790
791         return backend;
792 }
793
794 static int
795 compositor_init_config(struct weston_compositor *compositor,
796                        struct weston_config *config)
797 {
798         struct xkb_rule_names xkb_names;
799         struct weston_config_section *section;
800         int repaint_msec;
801         bool vt_switching;
802         bool require_input;
803
804         /* agl-compositor.ini [keyboard] */
805         section = weston_config_get_section(config, "keyboard", NULL, NULL);
806         weston_config_section_get_string(section, "keymap_rules",
807                                          (char **) &xkb_names.rules, NULL);
808         weston_config_section_get_string(section, "keymap_model",
809                                          (char **) &xkb_names.model, NULL);
810         weston_config_section_get_string(section, "keymap_layout",
811                                          (char **) &xkb_names.layout, NULL);
812         weston_config_section_get_string(section, "keymap_variant",
813                                          (char **) &xkb_names.variant, NULL);
814         weston_config_section_get_string(section, "keymap_options",
815                                          (char **) &xkb_names.options, NULL);
816
817         if (weston_compositor_set_xkb_rule_names(compositor, &xkb_names) < 0)
818                 return -1;
819
820         weston_config_section_get_int(section, "repeat-rate",
821                                       &compositor->kb_repeat_rate, 40);
822         weston_config_section_get_int(section, "repeat-delay",
823                                       &compositor->kb_repeat_delay, 400);
824
825         weston_config_section_get_bool(section, "vt-switching",
826                                        &vt_switching, true);
827         compositor->vt_switching = vt_switching;
828
829         /* agl-compositor.ini [core] */
830         section = weston_config_get_section(config, "core", NULL, NULL);
831
832         weston_config_section_get_bool(section, "require-input", &require_input, true);
833         compositor->require_input = require_input;
834
835         weston_config_section_get_int(section, "repaint-window", &repaint_msec,
836                                       compositor->repaint_msec);
837         if (repaint_msec < -10 || repaint_msec > 1000) {
838                 weston_log("Invalid repaint_window value in config: %d\n",
839                            repaint_msec);
840         } else {
841                 compositor->repaint_msec = repaint_msec;
842         }
843         weston_log("Output repaint window is %d ms maximum.\n",
844                    compositor->repaint_msec);
845
846         return 0;
847 }
848
849 struct ivi_surface *
850 to_ivi_surface(struct weston_surface *surface)
851 {
852         struct weston_desktop_surface *dsurface;
853
854         dsurface = weston_surface_get_desktop_surface(surface);
855         if (!dsurface)
856                 return NULL;
857
858         return weston_desktop_surface_get_user_data(dsurface);
859 }
860
861 static void
862 activate_binding(struct weston_seat *seat,
863                  struct weston_view *focus_view)
864 {
865         struct weston_surface *focus = focus_view->surface;
866         struct weston_surface *main_surface =
867                 weston_surface_get_main_surface(focus);
868         struct ivi_surface *surface;
869
870         surface = to_ivi_surface(main_surface);
871         if (!surface)
872                 return;
873
874         weston_seat_set_keyboard_focus(seat, focus);
875 }
876
877 static void
878 click_to_activate_binding(struct weston_pointer *pointer,
879                           const struct timespec *time,
880                           uint32_t button, void *data)
881 {
882         if (pointer->grab != &pointer->default_grab)
883                 return;
884         if (pointer->focus == NULL)
885                 return;
886
887         activate_binding(pointer->seat, pointer->focus);
888 }
889
890 static void
891 touch_to_activate_binding(struct weston_touch *touch,
892                           const struct timespec *time,
893                           void *data)
894 {
895         if (touch->grab != &touch->default_grab)
896                 return;
897         if (touch->focus == NULL)
898                 return;
899
900         activate_binding(touch->seat, touch->focus);
901 }
902
903 static void
904 add_bindings(struct weston_compositor *compositor)
905 {
906         weston_compositor_add_button_binding(compositor, BTN_LEFT, 0,
907                                              click_to_activate_binding,
908                                              NULL);
909         weston_compositor_add_button_binding(compositor, BTN_RIGHT, 0,
910                                              click_to_activate_binding,
911                                              NULL);
912         weston_compositor_add_touch_binding(compositor, 0,
913                                             touch_to_activate_binding,
914                                             NULL);
915 }
916
917 static int
918 create_listening_socket(struct wl_display *display, const char *socket_name)
919 {
920         if (socket_name) {
921                 if (wl_display_add_socket(display, socket_name)) {
922                         weston_log("fatal: failed to add socket: %s\n",
923                                    strerror(errno));
924                         return -1;
925                 }
926         } else {
927                 socket_name = wl_display_add_socket_auto(display);
928                 if (!socket_name) {
929                         weston_log("fatal: failed to add socket: %s\n",
930                                    strerror(errno));
931                         return -1;
932                 }
933         }
934
935         setenv("WAYLAND_DISPLAY", socket_name, 1);
936
937         return 0;
938 }
939
940 static bool
941 global_filter(const struct wl_client *client, const struct wl_global *global,
942               void *data)
943 {
944         return true;
945 }
946
947 static int
948 load_config(struct weston_config **config, bool no_config,
949             const char *config_file)
950 {
951         const char *file = "agl-compositor.ini";
952         const char *full_path;
953
954         if (config_file)
955                 file = config_file;
956
957         if (!no_config)
958                 *config = weston_config_parse(file);
959
960         if (*config) {
961                 full_path = weston_config_get_full_path(*config);
962
963                 weston_log("Using config file '%s'.\n", full_path);
964                 setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
965
966                 return 0;
967         }
968
969         if (config_file && !no_config) {
970                 weston_log("fatal: error opening or reading config file '%s'.\n",
971                         config_file);
972
973                 return -1;
974         }
975
976         weston_log("Starting with no config file.\n");
977         setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
978
979         return 0;
980 }
981
982 static FILE *logfile;
983
984 static int
985 log_timestamp(void)
986 {
987         static int cached_tm_mday = -1;
988         struct timespec ts;
989         struct tm brokendown_time;
990         char buf[128];
991
992         clock_gettime(CLOCK_REALTIME, &ts);
993         if (!localtime_r(&ts.tv_sec, &brokendown_time))
994                 return fprintf(logfile, "[(NULL)localtime] ");
995
996         if (brokendown_time.tm_mday != cached_tm_mday) {
997                 strftime(buf, sizeof buf, "%Y-%m-%d %Z", &brokendown_time);
998                 fprintf(logfile, "Date: %s\n", buf);
999
1000                 cached_tm_mday = brokendown_time.tm_mday;
1001         }
1002
1003         strftime(buf, sizeof buf, "%H:%M:%S", &brokendown_time);
1004
1005         return fprintf(logfile, "[%s.%03ld] ", buf, ts.tv_nsec / 1000000);
1006 }
1007
1008 static void
1009 custom_handler(const char *fmt, va_list arg)
1010 {
1011         log_timestamp();
1012         fprintf(logfile, "libwayland: ");
1013         vfprintf(logfile, fmt, arg);
1014 }
1015
1016 static void
1017 log_file_open(const char *filename)
1018 {
1019         wl_log_set_handler_server(custom_handler);
1020
1021         if (filename)
1022                 logfile = fopen(filename, "a");
1023
1024         if (!logfile) {
1025                 logfile = stderr;
1026         } else {
1027                 os_fd_set_cloexec(fileno(logfile));
1028                 setvbuf(logfile, NULL, _IOLBF, 256);
1029         }
1030 }
1031
1032 static void
1033 log_file_close(void)
1034 {
1035         if (logfile && logfile != stderr)
1036                 fclose(logfile);
1037         logfile = stderr;
1038 }
1039
1040 static int
1041 vlog(const char *fmt, va_list ap)
1042 {
1043         int l;
1044
1045         l = log_timestamp();
1046         l += vfprintf(logfile, fmt, ap);
1047
1048         return l;
1049 }
1050
1051 static int
1052 vlog_continue(const char *fmt, va_list ap)
1053 {
1054         return vfprintf(logfile, fmt, ap);
1055 }
1056
1057 static int
1058 on_term_signal(int signo, void *data)
1059 {
1060         struct wl_display *display = data;
1061
1062         weston_log("caught signal %d\n", signo);
1063         wl_display_terminate(display);
1064
1065         return 1;
1066 }
1067
1068 static void
1069 handle_exit(struct weston_compositor *compositor)
1070 {
1071         wl_display_terminate(compositor->wl_display);
1072 }
1073
1074 static void
1075 usage(int error_code)
1076 {
1077         FILE *out = error_code == EXIT_SUCCESS ? stdout : stderr;
1078         fprintf(out,
1079                 "Usage: agl-compositor [OPTIONS]\n"
1080                 "\n"
1081                 "This is " PACKAGE_STRING ", the reference compositor for\n"
1082                 "Automotive Grade Linux. Weston-ivi supports multiple backends, and depending\n"
1083                 "on which backend is in use different options will be accepted.\n"
1084                 "\n"
1085                 "Core options:\n"
1086                 "\n"
1087                 "  --version\t\tPrint agl-compositor version\n"
1088                 "  -B, --backend=MODULE\tBackend module, one of\n"
1089                         "\t\t\t\tdrm-backend.so\n"
1090                         "\t\t\t\twayland-backend.so\n"
1091                         "\t\t\t\tx11-backend.so\n"
1092                 "  -S, --socket=NAME\tName of socket to listen on\n"
1093                 "  --log=FILE\t\tLog to the given file\n"
1094                 "  -c, --config=FILE\tConfig file to load, defaults to agl-compositor.ini\n"
1095                 "  --no-config\t\tDo not read agl-compositor.ini\n"
1096                 "  --debug\t\tEnable debug extension\n"
1097                 "  -h, --help\t\tThis help message\n"
1098                 "\n");
1099         exit(error_code);
1100 }
1101
1102 static void
1103 ivi_compositor_get_quirks(struct ivi_compositor *ivi)
1104 {
1105         struct weston_config_section *section;
1106
1107         if (!ivi->config)
1108                 return;
1109
1110         section = weston_config_get_section(ivi->config, "shell", NULL, NULL);
1111         weston_config_section_get_bool(section, "activate-by-default",
1112                         &ivi->quirks.activate_apps_by_default, 0);
1113
1114 }
1115
1116 int main(int argc, char *argv[])
1117 {
1118         struct ivi_compositor ivi = { 0 };
1119         struct wl_display *display = NULL;
1120         struct wl_event_loop *loop;
1121         struct wl_event_source *signals[3] = { 0 };
1122         struct weston_config_section *section;
1123         /* Command line options */
1124         char *backend = NULL;
1125         char *socket_name = NULL;
1126         char *log = NULL;
1127         int help = 0;
1128         int version = 0;
1129         int no_config = 0;
1130         char *config_file = NULL;
1131         struct weston_log_context *log_ctx = NULL;
1132         struct weston_log_scope *log_scope;
1133         struct weston_log_subscriber *logger;
1134
1135         const struct weston_option core_options[] = {
1136                 { WESTON_OPTION_STRING, "backend", 'B', &backend },
1137                 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
1138                 { WESTON_OPTION_STRING, "log", 0, &log },
1139                 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
1140                 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
1141                 { WESTON_OPTION_BOOLEAN, "no-config", 0, &no_config },
1142                 { WESTON_OPTION_STRING, "config", 'c', &config_file },
1143         };
1144
1145         wl_list_init(&ivi.outputs);
1146         wl_list_init(&ivi.surfaces);
1147         wl_list_init(&ivi.pending_surfaces);
1148         wl_list_init(&ivi.popup_pending_apps);
1149         wl_list_init(&ivi.desktop_clients);
1150
1151         /* Prevent any clients we spawn getting our stdin */
1152         os_fd_set_cloexec(STDIN_FILENO);
1153
1154         parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
1155
1156         if (help)
1157                 usage(EXIT_SUCCESS);
1158
1159         if (version) {
1160                 printf(PACKAGE_STRING "\n");
1161                 return EXIT_SUCCESS;
1162         }
1163
1164         log_ctx = weston_log_ctx_compositor_create();
1165         if (!log_ctx) {
1166                 fprintf(stderr, "Failed to initialize weston debug framework.\n");
1167                 return EXIT_FAILURE;
1168         }
1169
1170         log_scope = weston_compositor_add_log_scope(log_ctx, "log",
1171                                                     "agl-compositor log\n",
1172                                                     NULL, NULL, NULL);
1173
1174         log_file_open(log);
1175         weston_log_set_handler(vlog, vlog_continue);
1176
1177         logger = weston_log_subscriber_create_log(logfile);
1178         weston_log_subscribe(log_ctx, logger, "log");
1179
1180         if (load_config(&ivi.config, no_config, config_file) < 0)
1181                 goto error_signals;
1182         section = weston_config_get_section(ivi.config, "core", NULL, NULL);
1183         if (!backend) {
1184                 weston_config_section_get_string(section, "backend", &backend,
1185                                                  NULL);
1186                 if (!backend)
1187                         backend = choose_default_backend();
1188         }
1189
1190         ivi_compositor_get_quirks(&ivi);
1191
1192         display = wl_display_create();
1193         loop = wl_display_get_event_loop(display);
1194
1195         wl_display_set_global_filter(display,
1196                                      global_filter, &ivi);
1197
1198         /* Register signal handlers so we shut down cleanly */
1199
1200         signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
1201                                               display);
1202         signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
1203                                               display);
1204         signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
1205                                               display);
1206
1207         for (size_t i = 0; i < ARRAY_LENGTH(signals); ++i)
1208                 if (!signals[i])
1209                         goto error_signals;
1210
1211         ivi.compositor = weston_compositor_create(display, log_ctx, &ivi);
1212         if (!ivi.compositor) {
1213                 weston_log("fatal: failed to create compositor.\n");
1214                 goto error_signals;
1215         }
1216
1217         if (compositor_init_config(ivi.compositor, ivi.config) < 0)
1218                 goto error_compositor;
1219
1220         if (load_backend(&ivi, backend, &argc, argv) < 0) {
1221                 weston_log("fatal: failed to create compositor backend.\n");
1222                 goto error_compositor;
1223         }
1224
1225         ivi.heads_changed.notify = heads_changed;
1226         weston_compositor_add_heads_changed_listener(ivi.compositor,
1227                                                      &ivi.heads_changed);
1228
1229         if (ivi_desktop_init(&ivi) < 0)
1230                 goto error_compositor;
1231
1232         if (ivi_policy_init(&ivi) < 0)
1233                 goto error_compositor;
1234
1235         if (ivi_shell_init(&ivi) < 0)
1236                 goto error_compositor;
1237
1238         add_bindings(ivi.compositor);
1239
1240         weston_compositor_flush_heads_changed(ivi.compositor);
1241
1242         ivi_shell_init_black_fs(&ivi);
1243
1244         if (create_listening_socket(display, socket_name) < 0)
1245                 goto error_compositor;
1246
1247         ivi.compositor->exit = handle_exit;
1248
1249         weston_compositor_wake(ivi.compositor);
1250
1251         ivi_shell_create_global(&ivi);
1252         ivi_launch_shell_client(&ivi);
1253         ivi_agl_systemd_notify(&ivi);
1254
1255         wl_display_run(display);
1256
1257         wl_display_destroy_clients(display);
1258
1259 error_compositor:
1260         weston_compositor_tear_down(ivi.compositor);
1261
1262         weston_compositor_log_scope_destroy(log_scope);
1263         log_scope = NULL;
1264
1265         weston_log_ctx_compositor_destroy(ivi.compositor);
1266         weston_compositor_destroy(ivi.compositor);
1267
1268         weston_log_subscriber_destroy_log(logger);
1269
1270         ivi_policy_destroy(ivi.policy);
1271
1272 error_signals:
1273         for (size_t i = 0; i < ARRAY_LENGTH(signals); ++i)
1274                 if (signals[i])
1275                         wl_event_source_remove(signals[i]);
1276
1277         wl_display_destroy(display);
1278
1279         log_file_close();
1280         if (ivi.config)
1281                 weston_config_destroy(ivi.config);
1282 }