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