blob: 8f915b2bf11f573eda9fe7d8ba46754c2d134b80 [file] [log] [blame]
Giulio Camuffobab996e2014-10-12 00:24:25 +03001/*
2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012-2015 Collabora, Ltd.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 */
27
28#include "config.h"
29
30#include <unistd.h>
31#include <signal.h>
32#include <errno.h>
33#include <dlfcn.h>
34#include <string.h>
35#include <sys/utsname.h>
36#include <sys/stat.h>
37#include <sys/wait.h>
38
39#ifdef HAVE_LIBUNWIND
40#define UNW_LOCAL_ONLY
41#include <libunwind.h>
42#endif
43
44#include "compositor.h"
45#include "../shared/os-compatibility.h"
46#include "../shared/helpers.h"
47#include "git-version.h"
48#include "version.h"
49
Benoit Gschwind3c530942016-04-15 20:28:32 -070050#include "compositor-headless.h"
Benoit Gschwindbd573102016-04-22 17:05:26 +020051#include "compositor-rdp.h"
Benoit Gschwind934e89a2016-04-27 23:56:42 +020052#include "compositor-fbdev.h"
Benoit Gschwind3c530942016-04-15 20:28:32 -070053
Giulio Camuffobab996e2014-10-12 00:24:25 +030054static struct wl_list child_process_list;
55static struct weston_compositor *segv_compositor;
56
57static int
58sigchld_handler(int signal_number, void *data)
59{
60 struct weston_process *p;
61 int status;
62 pid_t pid;
63
64 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
65 wl_list_for_each(p, &child_process_list, link) {
66 if (p->pid == pid)
67 break;
68 }
69
70 if (&p->link == &child_process_list) {
71 weston_log("unknown child process exited\n");
72 continue;
73 }
74
75 wl_list_remove(&p->link);
76 p->cleanup(p, status);
77 }
78
79 if (pid < 0 && errno != ECHILD)
80 weston_log("waitpid error %m\n");
81
82 return 1;
83}
84
85#ifdef HAVE_LIBUNWIND
86
87static void
88print_backtrace(void)
89{
90 unw_cursor_t cursor;
91 unw_context_t context;
92 unw_word_t off;
93 unw_proc_info_t pip;
94 int ret, i = 0;
95 char procname[256];
96 const char *filename;
97 Dl_info dlinfo;
98
99 pip.unwind_info = NULL;
100 ret = unw_getcontext(&context);
101 if (ret) {
102 weston_log("unw_getcontext: %d\n", ret);
103 return;
104 }
105
106 ret = unw_init_local(&cursor, &context);
107 if (ret) {
108 weston_log("unw_init_local: %d\n", ret);
109 return;
110 }
111
112 ret = unw_step(&cursor);
113 while (ret > 0) {
114 ret = unw_get_proc_info(&cursor, &pip);
115 if (ret) {
116 weston_log("unw_get_proc_info: %d\n", ret);
117 break;
118 }
119
120 ret = unw_get_proc_name(&cursor, procname, 256, &off);
121 if (ret && ret != -UNW_ENOMEM) {
122 if (ret != -UNW_EUNSPEC)
123 weston_log("unw_get_proc_name: %d\n", ret);
124 procname[0] = '?';
125 procname[1] = 0;
126 }
127
128 if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
129 *dlinfo.dli_fname)
130 filename = dlinfo.dli_fname;
131 else
132 filename = "?";
133
134 weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
135 ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
136
137 ret = unw_step(&cursor);
138 if (ret < 0)
139 weston_log("unw_step: %d\n", ret);
140 }
141}
142
143#else
144
145static void
146print_backtrace(void)
147{
148 void *buffer[32];
149 int i, count;
150 Dl_info info;
151
152 count = backtrace(buffer, ARRAY_LENGTH(buffer));
153 for (i = 0; i < count; i++) {
154 dladdr(buffer[i], &info);
155 weston_log(" [%016lx] %s (%s)\n",
156 (long) buffer[i],
157 info.dli_sname ? info.dli_sname : "--",
158 info.dli_fname);
159 }
160}
161
162#endif
163
164WL_EXPORT void
165weston_watch_process(struct weston_process *process)
166{
167 wl_list_insert(&child_process_list, &process->link);
168}
169
170static void
171log_uname(void)
172{
173 struct utsname usys;
174
175 uname(&usys);
176
177 weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
178 usys.version, usys.machine);
179}
180
181static const char xdg_error_message[] =
182 "fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
183
184static const char xdg_wrong_message[] =
185 "fatal: environment variable XDG_RUNTIME_DIR\n"
186 "is set to \"%s\", which is not a directory.\n";
187
188static const char xdg_wrong_mode_message[] =
189 "warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
190 "correctly. Unix access mode must be 0700 (current mode is %o),\n"
191 "and must be owned by the user (current owner is UID %d).\n";
192
193static const char xdg_detail_message[] =
194 "Refer to your distribution on how to get it, or\n"
195 "http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
196 "on how to implement it.\n";
197
198static void
199verify_xdg_runtime_dir(void)
200{
201 char *dir = getenv("XDG_RUNTIME_DIR");
202 struct stat s;
203
204 if (!dir) {
205 weston_log(xdg_error_message);
206 weston_log_continue(xdg_detail_message);
207 exit(EXIT_FAILURE);
208 }
209
210 if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
211 weston_log(xdg_wrong_message, dir);
212 weston_log_continue(xdg_detail_message);
213 exit(EXIT_FAILURE);
214 }
215
216 if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
217 weston_log(xdg_wrong_mode_message,
218 dir, s.st_mode & 0777, s.st_uid);
219 weston_log_continue(xdg_detail_message);
220 }
221}
222
223static int
224usage(int error_code)
225{
226 fprintf(stderr,
227 "Usage: weston [OPTIONS]\n\n"
228 "This is weston version " VERSION ", the Wayland reference compositor.\n"
229 "Weston supports multiple backends, and depending on which backend is in use\n"
230 "different options will be accepted.\n\n"
231
232
233 "Core options:\n\n"
234 " --version\t\tPrint weston version\n"
235 " -B, --backend=MODULE\tBackend module, one of\n"
236#if defined(BUILD_DRM_COMPOSITOR)
237 "\t\t\t\tdrm-backend.so\n"
238#endif
239#if defined(BUILD_FBDEV_COMPOSITOR)
240 "\t\t\t\tfbdev-backend.so\n"
241#endif
Dawid Gajownik71f57042015-07-31 17:39:00 -0300242#if defined(BUILD_HEADLESS_COMPOSITOR)
243 "\t\t\t\theadless-backend.so\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300244#endif
245#if defined(BUILD_RDP_COMPOSITOR)
246 "\t\t\t\trdp-backend.so\n"
247#endif
Giulio Camuffobab996e2014-10-12 00:24:25 +0300248#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
249 "\t\t\t\trpi-backend.so\n"
250#endif
Dawid Gajownik71f57042015-07-31 17:39:00 -0300251#if defined(BUILD_WAYLAND_COMPOSITOR)
252 "\t\t\t\twayland-backend.so\n"
253#endif
254#if defined(BUILD_X11_COMPOSITOR)
255 "\t\t\t\tx11-backend.so\n"
256#endif
Giulio Camuffobab996e2014-10-12 00:24:25 +0300257 " --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
258 " -S, --socket=NAME\tName of socket to listen on\n"
259 " -i, --idle-time=SECS\tIdle time in seconds\n"
260 " --modules\t\tLoad the comma-separated list of modules\n"
261 " --log=FILE\t\tLog to the given file\n"
262 " -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
263 " --no-config\t\tDo not read weston.ini\n"
264 " -h, --help\t\tThis help message\n\n");
265
266#if defined(BUILD_DRM_COMPOSITOR)
267 fprintf(stderr,
268 "Options for drm-backend.so:\n\n"
269 " --connector=ID\tBring up only this connector\n"
270 " --seat=SEAT\t\tThe seat that weston should run on\n"
271 " --tty=TTY\t\tThe tty to use\n"
272 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
273 " --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
274#endif
275
276#if defined(BUILD_FBDEV_COMPOSITOR)
277 fprintf(stderr,
278 "Options for fbdev-backend.so:\n\n"
279 " --tty=TTY\t\tThe tty to use\n"
280 " --device=DEVICE\tThe framebuffer device to use\n"
281 " --use-gl\t\tUse the GL renderer\n\n");
282#endif
283
Dawid Gajownik71f57042015-07-31 17:39:00 -0300284#if defined(BUILD_HEADLESS_COMPOSITOR)
Giulio Camuffobab996e2014-10-12 00:24:25 +0300285 fprintf(stderr,
Dawid Gajownik71f57042015-07-31 17:39:00 -0300286 "Options for headless-backend.so:\n\n"
287 " --width=WIDTH\t\tWidth of memory surface\n"
288 " --height=HEIGHT\tHeight of memory surface\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300289 " --transform=TR\tThe output transformation, TR is one of:\n"
290 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
Dawid Gajownik71f57042015-07-31 17:39:00 -0300291 " --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300292#endif
293
294#if defined(BUILD_RDP_COMPOSITOR)
295 fprintf(stderr,
296 "Options for rdp-backend.so:\n\n"
297 " --width=WIDTH\t\tWidth of desktop\n"
298 " --height=HEIGHT\tHeight of desktop\n"
Dawid Gajownikd99a0502015-07-31 14:49:57 -0300299 " --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300300 " --address=ADDR\tThe address to bind\n"
301 " --port=PORT\t\tThe port to listen on\n"
302 " --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
303 " --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
304 " --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
305 " --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
306 "\n");
307#endif
308
Dawid Gajownik71f57042015-07-31 17:39:00 -0300309#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
Giulio Camuffobab996e2014-10-12 00:24:25 +0300310 fprintf(stderr,
Dawid Gajownik71f57042015-07-31 17:39:00 -0300311 "Options for rpi-backend.so:\n\n"
312 " --tty=TTY\t\tThe tty to use\n"
313 " --single-buffer\tUse single-buffered Dispmanx elements.\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300314 " --transform=TR\tThe output transformation, TR is one of:\n"
315 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
Dawid Gajownik71f57042015-07-31 17:39:00 -0300316 " --opaque-regions\tEnable support for opaque regions, can be "
317 "very slow without support in the GPU firmware.\n"
318 "\n");
319#endif
320
321#if defined(BUILD_WAYLAND_COMPOSITOR)
322 fprintf(stderr,
323 "Options for wayland-backend.so:\n\n"
324 " --width=WIDTH\t\tWidth of Wayland surface\n"
325 " --height=HEIGHT\tHeight of Wayland surface\n"
326 " --scale=SCALE\t\tScale factor of output\n"
327 " --fullscreen\t\tRun in fullscreen mode\n"
328 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
329 " --output-count=COUNT\tCreate multiple outputs\n"
330 " --sprawl\t\tCreate one fullscreen output for every parent output\n"
331 " --display=DISPLAY\tWayland display to connect to\n\n");
332#endif
333
334#if defined(BUILD_X11_COMPOSITOR)
335 fprintf(stderr,
336 "Options for x11-backend.so:\n\n"
337 " --width=WIDTH\t\tWidth of X window\n"
338 " --height=HEIGHT\tHeight of X window\n"
339 " --scale=SCALE\t\tScale factor of output\n"
340 " --fullscreen\t\tRun in fullscreen mode\n"
341 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
342 " --output-count=COUNT\tCreate multiple outputs\n"
343 " --no-input\t\tDont create input devices\n\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300344#endif
345
346 exit(error_code);
347}
348
349static int on_term_signal(int signal_number, void *data)
350{
351 struct wl_display *display = data;
352
353 weston_log("caught signal %d\n", signal_number);
354 wl_display_terminate(display);
355
356 return 1;
357}
358
359static void
360on_caught_signal(int s, siginfo_t *siginfo, void *context)
361{
362 /* This signal handler will do a best-effort backtrace, and
363 * then call the backend restore function, which will switch
364 * back to the vt we launched from or ungrab X etc and then
365 * raise SIGTRAP. If we run weston under gdb from X or a
366 * different vt, and tell gdb "handle *s* nostop", this
367 * will allow weston to switch back to gdb on crash and then
368 * gdb will catch the crash with SIGTRAP.*/
369
370 weston_log("caught signal: %d\n", s);
371
372 print_backtrace();
373
374 segv_compositor->backend->restore(segv_compositor);
375
376 raise(SIGTRAP);
377}
378
379static void
380catch_signals(void)
381{
382 struct sigaction action;
383
384 action.sa_flags = SA_SIGINFO | SA_RESETHAND;
385 action.sa_sigaction = on_caught_signal;
386 sigemptyset(&action.sa_mask);
387 sigaction(SIGSEGV, &action, NULL);
388 sigaction(SIGABRT, &action, NULL);
389}
390
391static const char *
392clock_name(clockid_t clk_id)
393{
394 static const char *names[] = {
395 [CLOCK_REALTIME] = "CLOCK_REALTIME",
396 [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
397 [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
398 [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
399 [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
Derek Foreman32838c92015-06-29 13:20:34 -0500400#ifdef CLOCK_BOOTTIME
Giulio Camuffobab996e2014-10-12 00:24:25 +0300401 [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
Derek Foreman32838c92015-06-29 13:20:34 -0500402#endif
Giulio Camuffobab996e2014-10-12 00:24:25 +0300403 };
404
405 if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
406 return "unknown";
407
408 return names[clk_id];
409}
410
411static const struct {
412 uint32_t bit; /* enum weston_capability */
413 const char *desc;
414} capability_strings[] = {
415 { WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
416 { WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
417};
418
419static void
420weston_compositor_log_capabilities(struct weston_compositor *compositor)
421{
422 unsigned i;
423 int yes;
424
425 weston_log("Compositor capabilities:\n");
426 for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
427 yes = compositor->capabilities & capability_strings[i].bit;
428 weston_log_continue(STAMP_SPACE "%s %s\n",
429 capability_strings[i].desc,
430 yes ? "yes" : "no");
431 }
432
433 weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
434 clock_name(compositor->presentation_clock),
435 compositor->presentation_clock);
436}
437
438static void
439handle_primary_client_destroyed(struct wl_listener *listener, void *data)
440{
441 struct wl_client *client = data;
442
443 weston_log("Primary client died. Closing...\n");
444
445 wl_display_terminate(wl_client_get_display(client));
446}
447
448static int
449weston_create_listening_socket(struct wl_display *display, const char *socket_name)
450{
451 if (socket_name) {
452 if (wl_display_add_socket(display, socket_name)) {
453 weston_log("fatal: failed to add socket: %m\n");
454 return -1;
455 }
456 } else {
457 socket_name = wl_display_add_socket_auto(display);
458 if (!socket_name) {
459 weston_log("fatal: failed to add socket: %m\n");
460 return -1;
461 }
462 }
463
464 setenv("WAYLAND_DISPLAY", socket_name, 1);
465
466 return 0;
467}
468
469static int
470load_modules(struct weston_compositor *ec, const char *modules,
471 int *argc, char *argv[])
472{
473 const char *p, *end;
474 char buffer[256];
475 int (*module_init)(struct weston_compositor *ec,
476 int *argc, char *argv[]);
477
478 if (modules == NULL)
479 return 0;
480
481 p = modules;
482 while (*p) {
483 end = strchrnul(p, ',');
484 snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
485 module_init = weston_load_module(buffer, "module_init");
486 if (!module_init)
487 return -1;
488 if (module_init(ec, argc, argv) < 0)
489 return -1;
490 p = end;
491 while (*p == ',')
492 p++;
493
494 }
495
496 return 0;
497}
498
499static int
500weston_compositor_init_config(struct weston_compositor *ec,
501 struct weston_config *config)
502{
503 struct xkb_rule_names xkb_names;
504 struct weston_config_section *s;
505 int repaint_msec;
Bob Ham91880f12016-01-12 10:21:47 +0000506 int vt_switching;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300507
508 s = weston_config_get_section(config, "keyboard", NULL, NULL);
509 weston_config_section_get_string(s, "keymap_rules",
510 (char **) &xkb_names.rules, NULL);
511 weston_config_section_get_string(s, "keymap_model",
512 (char **) &xkb_names.model, NULL);
513 weston_config_section_get_string(s, "keymap_layout",
514 (char **) &xkb_names.layout, NULL);
515 weston_config_section_get_string(s, "keymap_variant",
516 (char **) &xkb_names.variant, NULL);
517 weston_config_section_get_string(s, "keymap_options",
518 (char **) &xkb_names.options, NULL);
519
520 if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
521 return -1;
522
523 weston_config_section_get_int(s, "repeat-rate",
524 &ec->kb_repeat_rate, 40);
525 weston_config_section_get_int(s, "repeat-delay",
526 &ec->kb_repeat_delay, 400);
527
Bob Ham91880f12016-01-12 10:21:47 +0000528 weston_config_section_get_bool(s, "vt-switching",
529 &vt_switching, true);
530 ec->vt_switching = vt_switching;
531
Giulio Camuffobab996e2014-10-12 00:24:25 +0300532 s = weston_config_get_section(config, "core", NULL, NULL);
533 weston_config_section_get_int(s, "repaint-window", &repaint_msec,
534 ec->repaint_msec);
535 if (repaint_msec < -10 || repaint_msec > 1000) {
536 weston_log("Invalid repaint_window value in config: %d\n",
537 repaint_msec);
538 } else {
539 ec->repaint_msec = repaint_msec;
540 }
541 weston_log("Output repaint window is %d ms maximum.\n",
542 ec->repaint_msec);
543
544 return 0;
545}
546
547static char *
548weston_choose_default_backend(void)
549{
550 char *backend = NULL;
551
552 if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
553 backend = strdup("wayland-backend.so");
554 else if (getenv("DISPLAY"))
555 backend = strdup("x11-backend.so");
556 else
557 backend = strdup(WESTON_NATIVE_BACKEND);
558
559 return backend;
560}
561
562static const struct { const char *name; uint32_t token; } transforms[] = {
563 { "normal", WL_OUTPUT_TRANSFORM_NORMAL },
564 { "90", WL_OUTPUT_TRANSFORM_90 },
565 { "180", WL_OUTPUT_TRANSFORM_180 },
566 { "270", WL_OUTPUT_TRANSFORM_270 },
567 { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
568 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
569 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
570 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
571};
572
573WL_EXPORT int
574weston_parse_transform(const char *transform, uint32_t *out)
575{
576 unsigned int i;
577
578 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
579 if (strcmp(transforms[i].name, transform) == 0) {
580 *out = transforms[i].token;
581 return 0;
582 }
583
584 *out = WL_OUTPUT_TRANSFORM_NORMAL;
585 return -1;
586}
587
588WL_EXPORT const char *
589weston_transform_to_string(uint32_t output_transform)
590{
591 unsigned int i;
592
593 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
594 if (transforms[i].token == output_transform)
595 return transforms[i].name;
596
597 return "<illegal value>";
598}
599
600static int
601load_configuration(struct weston_config **config, int32_t noconfig,
602 const char *config_file)
603{
604 const char *file = "weston.ini";
605 const char *full_path;
606
607 *config = NULL;
608
609 if (config_file)
610 file = config_file;
611
612 if (noconfig == 0)
613 *config = weston_config_parse(file);
614
615 if (*config) {
616 full_path = weston_config_get_full_path(*config);
617
618 weston_log("Using config file '%s'\n", full_path);
619 setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
620
621 return 0;
622 }
623
624 if (config_file && noconfig == 0) {
625 weston_log("fatal: error opening or reading config file"
626 " '%s'.\n", config_file);
627
628 return -1;
629 }
630
631 weston_log("Starting with no config file.\n");
632 setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
633
634 return 0;
635}
636
637static void
638handle_exit(struct weston_compositor *c)
639{
640 wl_display_terminate(c->wl_display);
641}
642
Giulio Camuffo43008c72015-10-17 19:24:15 +0300643/* Temporary function to be removed when all backends are converted. */
644static int
645load_backend_old(struct weston_compositor *compositor, const char *backend,
646 int *argc, char **argv, struct weston_config *wc)
647{
648 int (*backend_init)(struct weston_compositor *c,
649 int *argc, char *argv[],
650 struct weston_config *config,
651 struct weston_backend_config *config_base);
652
653 backend_init = weston_load_module(backend, "backend_init");
654 if (!backend_init)
655 return -1;
656
657 return backend_init(compositor, argc, argv, wc, NULL);
658}
659
Bryce Harrington98ab08b2016-04-15 20:28:36 -0700660/** Main module call-point for backends.
661 *
662 * All backends should use this routine to access their init routine.
663 * Backends may subclass weston_backend_config to add their own
664 * configuration data, setting the major/minor version in config_base
665 * accordingly.
666 *
667 * The config_base object should be treated as temporary, and any data
668 * copied out of it by backend_init before returning. The load_backend_new
669 * callers may then free the config_base object.
670 *
671 * NOTE: This is a temporary function intended to eventually be replaced
672 * by weston_compositor_load_backend().
673 */
Bryce Harrington6ca25b32016-04-15 20:28:27 -0700674static int
675load_backend_new(struct weston_compositor *compositor, const char *backend,
676 struct weston_backend_config *config_base)
677{
678 int (*backend_init)(struct weston_compositor *c,
679 int *argc, char *argv[],
680 struct weston_config *config,
681 struct weston_backend_config *config_base);
682
683 backend_init = weston_load_module(backend, "backend_init");
684 if (!backend_init)
685 return -1;
686
687 return backend_init(compositor, NULL, NULL, NULL, config_base);
688}
689
Giulio Camuffo43008c72015-10-17 19:24:15 +0300690static int
Benoit Gschwind3c530942016-04-15 20:28:32 -0700691load_headless_backend(struct weston_compositor *c, char const * backend,
692 int *argc, char **argv, struct weston_config *wc)
693{
694 struct weston_headless_backend_config config = {{ 0, }};
695 int ret = 0;
Benoit Gschwind2da6d0c2016-04-29 15:21:54 +0200696 char *transform = NULL;
Benoit Gschwind3c530942016-04-15 20:28:32 -0700697
698 config.width = 1024;
699 config.height = 640;
700
701 const struct weston_option options[] = {
702 { WESTON_OPTION_INTEGER, "width", 0, &config.width },
703 { WESTON_OPTION_INTEGER, "height", 0, &config.height },
704 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
705 { WESTON_OPTION_STRING, "transform", 0, &transform },
706 };
707
708 parse_options(options, ARRAY_LENGTH(options), argc, argv);
709
Benoit Gschwind2da6d0c2016-04-29 15:21:54 +0200710 config.transform = WL_OUTPUT_TRANSFORM_NORMAL;
711 if (transform) {
712 if (weston_parse_transform(transform, &config.transform) < 0)
713 weston_log("Invalid transform \"%s\"\n", transform);
714 free(transform);
715 }
Benoit Gschwind3c530942016-04-15 20:28:32 -0700716
717 config.base.struct_version = WESTON_HEADLESS_BACKEND_CONFIG_VERSION;
718 config.base.struct_size = sizeof(struct weston_headless_backend_config);
719
720 /* load the actual wayland backend and configure it */
721 ret = load_backend_new(c, backend, &config.base);
722
723 return ret;
724}
725
Benoit Gschwindbd573102016-04-22 17:05:26 +0200726static void
727weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
728{
729 config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
730 config->base.struct_size = sizeof(struct weston_rdp_backend_config);
731
732 config->width = 640;
733 config->height = 480;
734 config->bind_address = NULL;
735 config->port = 3389;
736 config->rdp_key = NULL;
737 config->server_cert = NULL;
738 config->server_key = NULL;
739 config->env_socket = 0;
740 config->no_clients_resize = 0;
741}
742
743static int
744load_rdp_backend(struct weston_compositor *c, char const * backend,
745 int *argc, char *argv[], struct weston_config *wc)
746{
747 struct weston_rdp_backend_config config = {{ 0, }};
748 int ret = 0;
749
750 weston_rdp_backend_config_init(&config);
751
752 const struct weston_option rdp_options[] = {
753 { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
754 { WESTON_OPTION_INTEGER, "width", 0, &config.width },
755 { WESTON_OPTION_INTEGER, "height", 0, &config.height },
756 { WESTON_OPTION_STRING, "address", 0, &config.bind_address },
757 { WESTON_OPTION_INTEGER, "port", 0, &config.port },
758 { WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
759 { WESTON_OPTION_STRING, "rdp4-key", 0, &config.rdp_key },
760 { WESTON_OPTION_STRING, "rdp-tls-cert", 0, &config.server_cert },
761 { WESTON_OPTION_STRING, "rdp-tls-key", 0, &config.server_key }
762 };
763
764 parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
765
766 ret = load_backend_new(c, backend, &config.base);
767
768 free(config.bind_address);
769 free(config.rdp_key);
770 free(config.server_cert);
771 free(config.server_key);
772 return ret;
773}
774
Benoit Gschwind3c530942016-04-15 20:28:32 -0700775static int
Benoit Gschwind934e89a2016-04-27 23:56:42 +0200776load_fbdev_backend(struct weston_compositor *c, char const * backend,
777 int *argc, char **argv, struct weston_config *wc)
778{
779 struct weston_fbdev_backend_config config = {{ 0, }};
780 struct weston_config_section *section;
781 char *s = NULL;
782 int ret = 0;
783
784 const struct weston_option fbdev_options[] = {
785 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
786 { WESTON_OPTION_STRING, "device", 0, &config.device },
787 { WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
788 };
789
790 parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
791
792 if (!config.device)
793 config.device = strdup("/dev/fb0");
794
795 section = weston_config_get_section(wc, "output", "name", "fbdev");
796 weston_config_section_get_string(section, "transform", &s, "normal");
797 if (weston_parse_transform(s, &config.output_transform) < 0)
798 weston_log("Invalid transform \"%s\" for output fbdev\n", s);
799 free(s);
800
801 config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
802 config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
803
804 /* load the actual wayland backend and configure it */
805 ret = load_backend_new(c, backend, &config.base);
806
807 free(config.device);
808 return ret;
809}
810
811static int
Giulio Camuffo43008c72015-10-17 19:24:15 +0300812load_backend(struct weston_compositor *compositor, const char *backend,
813 int *argc, char **argv, struct weston_config *config)
814{
Benoit Gschwind3c530942016-04-15 20:28:32 -0700815 if (strstr(backend, "headless-backend.so"))
816 return load_headless_backend(compositor, backend, argc, argv, config);
Benoit Gschwindbd573102016-04-22 17:05:26 +0200817 else if (strstr(backend, "rdp-backend.so"))
818 return load_rdp_backend(compositor, backend, argc, argv, config);
Benoit Gschwind934e89a2016-04-27 23:56:42 +0200819 else if (strstr(backend, "fbdev-backend.so"))
820 return load_fbdev_backend(compositor, backend, argc, argv, config);
Giulio Camuffo43008c72015-10-17 19:24:15 +0300821#if 0
Benoit Gschwind3c530942016-04-15 20:28:32 -0700822 else if (strstr(backend, "drm-backend.so"))
Giulio Camuffo43008c72015-10-17 19:24:15 +0300823 return load_drm_backend(compositor, backend, argc, argv, config);
824 else if (strstr(backend, "wayland-backend.so"))
825 return load_wayland_backend(compositor, backend, argc, argv, config);
826 else if (strstr(backend, "x11-backend.so"))
827 return load_x11_backend(compositor, backend, argc, argv, config);
Giulio Camuffo43008c72015-10-17 19:24:15 +0300828 else if (strstr(backend, "rpi-backend.so"))
829 return load_rpi_backend(compositor, backend, argc, argv, config);
Giulio Camuffo43008c72015-10-17 19:24:15 +0300830#endif
831
832 return load_backend_old(compositor, backend, argc, argv, config);
833}
834
Giulio Camuffobab996e2014-10-12 00:24:25 +0300835int main(int argc, char *argv[])
836{
837 int ret = EXIT_FAILURE;
838 struct wl_display *display;
839 struct weston_compositor *ec;
840 struct wl_event_source *signals[4];
841 struct wl_event_loop *loop;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300842 int i, fd;
843 char *backend = NULL;
844 char *shell = NULL;
845 char *modules = NULL;
846 char *option_modules = NULL;
847 char *log = NULL;
848 char *server_socket = NULL, *end;
849 int32_t idle_time = -1;
850 int32_t help = 0;
851 char *socket_name = NULL;
852 int32_t version = 0;
853 int32_t noconfig = 0;
854 int32_t numlock_on;
855 char *config_file = NULL;
856 struct weston_config *config = NULL;
857 struct weston_config_section *section;
858 struct wl_client *primary_client;
859 struct wl_listener primary_client_destroyed;
860 struct weston_seat *seat;
861
862 const struct weston_option core_options[] = {
863 { WESTON_OPTION_STRING, "backend", 'B', &backend },
864 { WESTON_OPTION_STRING, "shell", 0, &shell },
865 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
866 { WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
867 { WESTON_OPTION_STRING, "modules", 0, &option_modules },
868 { WESTON_OPTION_STRING, "log", 0, &log },
869 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
870 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
871 { WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
872 { WESTON_OPTION_STRING, "config", 'c', &config_file },
873 };
874
875 parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
876
877 if (help)
878 usage(EXIT_SUCCESS);
879
880 if (version) {
881 printf(PACKAGE_STRING "\n");
882 return EXIT_SUCCESS;
883 }
884
885 weston_log_file_open(log);
886
887 weston_log("%s\n"
888 STAMP_SPACE "%s\n"
889 STAMP_SPACE "Bug reports to: %s\n"
890 STAMP_SPACE "Build: %s\n",
891 PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
892 BUILD_ID);
893 log_uname();
894
895 verify_xdg_runtime_dir();
896
897 display = wl_display_create();
898
899 loop = wl_display_get_event_loop(display);
900 signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
901 display);
902 signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
903 display);
904 signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
905 display);
906
907 wl_list_init(&child_process_list);
908 signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
909 NULL);
910
911 if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
912 goto out_signals;
913
914 if (load_configuration(&config, noconfig, config_file) < 0)
915 goto out_signals;
916
917 section = weston_config_get_section(config, "core", NULL, NULL);
918
919 if (!backend) {
920 weston_config_section_get_string(section, "backend", &backend,
921 NULL);
922 if (!backend)
923 backend = weston_choose_default_backend();
924 }
925
Giulio Camuffobab996e2014-10-12 00:24:25 +0300926 ec = weston_compositor_create(display, NULL);
927 if (ec == NULL) {
928 weston_log("fatal: failed to create compositor\n");
Giulio Camuffo3c241b12015-10-03 16:25:16 +0300929 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300930 }
931
932 ec->config = config;
933 if (weston_compositor_init_config(ec, config) < 0)
Giulio Camuffo3c241b12015-10-03 16:25:16 +0300934 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300935
Giulio Camuffo43008c72015-10-17 19:24:15 +0300936 if (load_backend(ec, backend, &argc, argv, config) < 0) {
Giulio Camuffobab996e2014-10-12 00:24:25 +0300937 weston_log("fatal: failed to create compositor backend\n");
Giulio Camuffo3c241b12015-10-03 16:25:16 +0300938 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300939 }
940
941 catch_signals();
942 segv_compositor = ec;
943
944 if (idle_time < 0)
945 weston_config_section_get_int(section, "idle-time", &idle_time, -1);
946 if (idle_time < 0)
947 idle_time = 300; /* default idle timeout, in seconds */
948
949 ec->idle_time = idle_time;
950 ec->default_pointer_grab = NULL;
951 ec->exit = handle_exit;
952
953 weston_compositor_log_capabilities(ec);
954
955 server_socket = getenv("WAYLAND_SERVER_SOCKET");
956 if (server_socket) {
957 weston_log("Running with single client\n");
958 fd = strtol(server_socket, &end, 0);
959 if (*end != '\0')
960 fd = -1;
961 } else {
962 fd = -1;
963 }
964
965 if (fd != -1) {
966 primary_client = wl_client_create(display, fd);
967 if (!primary_client) {
968 weston_log("fatal: failed to add client: %m\n");
969 goto out;
970 }
971 primary_client_destroyed.notify =
972 handle_primary_client_destroyed;
973 wl_client_add_destroy_listener(primary_client,
974 &primary_client_destroyed);
975 } else if (weston_create_listening_socket(display, socket_name)) {
976 goto out;
977 }
978
979 if (!shell)
980 weston_config_section_get_string(section, "shell", &shell,
981 "desktop-shell.so");
982
983 if (load_modules(ec, shell, &argc, argv) < 0)
984 goto out;
985
986 weston_config_section_get_string(section, "modules", &modules, "");
987 if (load_modules(ec, modules, &argc, argv) < 0)
988 goto out;
989
990 if (load_modules(ec, option_modules, &argc, argv) < 0)
991 goto out;
992
993 section = weston_config_get_section(config, "keyboard", NULL, NULL);
994 weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
995 if (numlock_on) {
996 wl_list_for_each(seat, &ec->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -0500997 struct weston_keyboard *keyboard =
998 weston_seat_get_keyboard(seat);
999
1000 if (keyboard)
1001 weston_keyboard_set_locks(keyboard,
Giulio Camuffobab996e2014-10-12 00:24:25 +03001002 WESTON_NUM_LOCK,
1003 WESTON_NUM_LOCK);
1004 }
1005 }
1006
1007 for (i = 1; i < argc; i++)
1008 weston_log("fatal: unhandled option: %s\n", argv[i]);
1009 if (argc > 1)
1010 goto out;
1011
1012 weston_compositor_wake(ec);
1013
1014 wl_display_run(display);
1015
1016 /* Allow for setting return exit code after
1017 * wl_display_run returns normally. This is
1018 * useful for devs/testers and automated tests
1019 * that want to indicate failure status to
1020 * testing infrastructure above
1021 */
1022 ret = ec->exit_code;
1023
1024out:
1025 weston_compositor_destroy(ec);
1026
1027out_signals:
1028 for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
1029 if (signals[i])
1030 wl_event_source_remove(signals[i]);
1031
1032 wl_display_destroy(display);
1033
1034 weston_log_file_close();
1035
1036 if (config)
1037 weston_config_destroy(config);
1038 free(config_file);
1039 free(backend);
1040 free(shell);
1041 free(socket_name);
1042 free(option_modules);
1043 free(log);
1044 free(modules);
1045
1046 return ret;
1047}