2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012-2015 Collabora, Ltd.
5 * Copyright © 2010-2011 Benjamin Franzke
6 * Copyright © 2013 Jason Ekstrand
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #include <sys/utsname.h>
41 #include <sys/socket.h>
44 #include <linux/limits.h>
47 #include "compositor.h"
48 #include "../shared/os-compatibility.h"
49 #include "../shared/helpers.h"
50 #include "../shared/string-helpers.h"
51 #include "git-version.h"
55 #include "compositor-drm.h"
56 #include "compositor-headless.h"
57 #include "compositor-rdp.h"
58 #include "compositor-fbdev.h"
59 #include "compositor-x11.h"
60 #include "compositor-wayland.h"
61 #include "windowed-output-api.h"
63 #define WINDOW_TITLE "Weston Compositor"
65 struct wet_output_config {
72 struct wet_compositor;
74 struct wet_head_tracker {
75 struct wl_listener head_destroy_listener;
78 struct wet_compositor {
79 struct weston_config *config;
80 struct wet_output_config *parsed_options;
81 struct wl_listener pending_output_listener;
82 bool drm_use_current_mode;
83 struct wl_listener heads_changed_listener;
84 int (*simple_output_configure)(struct weston_output *output);
88 static FILE *weston_logfile = NULL;
90 static int cached_tm_mday = -1;
92 static int weston_log_timestamp(void)
95 struct tm *brokendown_time;
98 gettimeofday(&tv, NULL);
100 brokendown_time = localtime(&tv.tv_sec);
101 if (brokendown_time == NULL)
102 return fprintf(weston_logfile, "[(NULL)localtime] ");
104 if (brokendown_time->tm_mday != cached_tm_mday) {
105 strftime(string, sizeof string, "%Y-%m-%d %Z", brokendown_time);
106 fprintf(weston_logfile, "Date: %s\n", string);
108 cached_tm_mday = brokendown_time->tm_mday;
111 strftime(string, sizeof string, "%H:%M:%S", brokendown_time);
113 return fprintf(weston_logfile, "[%s.%03li] ", string, tv.tv_usec/1000);
117 custom_handler(const char *fmt, va_list arg)
119 weston_log_timestamp();
120 fprintf(weston_logfile, "libwayland: ");
121 vfprintf(weston_logfile, fmt, arg);
125 weston_log_file_open(const char *filename)
127 wl_log_set_handler_server(custom_handler);
129 if (filename != NULL) {
130 weston_logfile = fopen(filename, "a");
132 os_fd_set_cloexec(fileno(weston_logfile));
135 if (weston_logfile == NULL)
136 weston_logfile = stderr;
138 setvbuf(weston_logfile, NULL, _IOLBF, 256);
142 weston_log_file_close(void)
144 if ((weston_logfile != stderr) && (weston_logfile != NULL))
145 fclose(weston_logfile);
146 weston_logfile = stderr;
150 vlog(const char *fmt, va_list ap)
154 l = weston_log_timestamp();
155 l += vfprintf(weston_logfile, fmt, ap);
161 vlog_continue(const char *fmt, va_list argp)
163 return vfprintf(weston_logfile, fmt, argp);
166 static struct wl_list child_process_list;
167 static struct weston_compositor *segv_compositor;
170 sigchld_handler(int signal_number, void *data)
172 struct weston_process *p;
176 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
177 wl_list_for_each(p, &child_process_list, link) {
182 if (&p->link == &child_process_list) {
183 weston_log("unknown child process exited\n");
187 wl_list_remove(&p->link);
188 p->cleanup(p, status);
191 if (pid < 0 && errno != ECHILD)
192 weston_log("waitpid error %m\n");
198 child_client_exec(int sockfd, const char *path)
204 /* do not give our signal mask to the new process */
205 sigfillset(&allsigs);
206 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
208 /* Launch clients as the user. Do not lauch clients with wrong euid.*/
209 if (seteuid(getuid()) == -1) {
210 weston_log("compositor: failed seteuid\n");
214 /* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
215 * non-CLOEXEC fd to pass through exec. */
216 clientfd = dup(sockfd);
217 if (clientfd == -1) {
218 weston_log("compositor: dup failed: %m\n");
222 snprintf(s, sizeof s, "%d", clientfd);
223 setenv("WAYLAND_SOCKET", s, 1);
225 if (execl(path, path, NULL) < 0)
226 weston_log("compositor: executing '%s' failed: %m\n",
230 WL_EXPORT struct wl_client *
231 weston_client_launch(struct weston_compositor *compositor,
232 struct weston_process *proc,
234 weston_process_cleanup_func_t cleanup)
238 struct wl_client *client;
240 weston_log("launching '%s'\n", path);
242 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
243 weston_log("weston_client_launch: "
244 "socketpair failed while launching '%s': %m\n",
253 weston_log("weston_client_launch: "
254 "fork failed while launching '%s': %m\n", path);
259 child_client_exec(sv[1], path);
265 client = wl_client_create(compositor->wl_display, sv[0]);
268 weston_log("weston_client_launch: "
269 "wl_client_create failed while launching '%s'.\n",
275 proc->cleanup = cleanup;
276 weston_watch_process(proc);
282 weston_watch_process(struct weston_process *process)
284 wl_list_insert(&child_process_list, &process->link);
287 struct process_info {
288 struct weston_process proc;
293 process_handle_sigchld(struct weston_process *process, int status)
295 struct process_info *pinfo =
296 container_of(process, struct process_info, proc);
299 * There are no guarantees whether this runs before or after
300 * the wl_client destructor.
303 if (WIFEXITED(status)) {
304 weston_log("%s exited with status %d\n", pinfo->path,
305 WEXITSTATUS(status));
306 } else if (WIFSIGNALED(status)) {
307 weston_log("%s died on signal %d\n", pinfo->path,
310 weston_log("%s disappeared\n", pinfo->path);
317 WL_EXPORT struct wl_client *
318 weston_client_start(struct weston_compositor *compositor, const char *path)
320 struct process_info *pinfo;
321 struct wl_client *client;
323 pinfo = zalloc(sizeof *pinfo);
327 pinfo->path = strdup(path);
331 client = weston_client_launch(compositor, &pinfo->proc, path,
332 process_handle_sigchld);
354 weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
355 usys.version, usys.machine);
358 static struct wet_compositor *
359 to_wet_compositor(struct weston_compositor *compositor)
361 return weston_compositor_get_user_data(compositor);
365 wet_set_pending_output_handler(struct weston_compositor *ec,
366 wl_notify_func_t handler)
368 struct wet_compositor *compositor = to_wet_compositor(ec);
370 compositor->pending_output_listener.notify = handler;
371 wl_signal_add(&ec->output_pending_signal, &compositor->pending_output_listener);
374 static struct wet_output_config *
375 wet_init_parsed_options(struct weston_compositor *ec)
377 struct wet_compositor *compositor = to_wet_compositor(ec);
378 struct wet_output_config *config;
380 config = zalloc(sizeof *config);
383 perror("out of memory");
390 config->transform = UINT32_MAX;
392 compositor->parsed_options = config;
397 WL_EXPORT struct weston_config *
398 wet_get_config(struct weston_compositor *ec)
400 struct wet_compositor *compositor = to_wet_compositor(ec);
402 return compositor->config;
405 static const char xdg_error_message[] =
406 "fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
408 static const char xdg_wrong_message[] =
409 "fatal: environment variable XDG_RUNTIME_DIR\n"
410 "is set to \"%s\", which is not a directory.\n";
412 static const char xdg_wrong_mode_message[] =
413 "warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
414 "correctly. Unix access mode must be 0700 (current mode is %o),\n"
415 "and must be owned by the user (current owner is UID %d).\n";
417 static const char xdg_detail_message[] =
418 "Refer to your distribution on how to get it, or\n"
419 "http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
420 "on how to implement it.\n";
423 verify_xdg_runtime_dir(void)
425 char *dir = getenv("XDG_RUNTIME_DIR");
429 weston_log(xdg_error_message);
430 weston_log_continue(xdg_detail_message);
434 if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
435 weston_log(xdg_wrong_message, dir);
436 weston_log_continue(xdg_detail_message);
440 if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
441 weston_log(xdg_wrong_mode_message,
442 dir, s.st_mode & 0777, s.st_uid);
443 weston_log_continue(xdg_detail_message);
448 usage(int error_code)
451 "Usage: weston [OPTIONS]\n\n"
452 "This is weston version " VERSION ", the Wayland reference compositor.\n"
453 "Weston supports multiple backends, and depending on which backend is in use\n"
454 "different options will be accepted.\n\n"
458 " --version\t\tPrint weston version\n"
459 " -B, --backend=MODULE\tBackend module, one of\n"
460 #if defined(BUILD_DRM_COMPOSITOR)
461 "\t\t\t\tdrm-backend.so\n"
463 #if defined(BUILD_FBDEV_COMPOSITOR)
464 "\t\t\t\tfbdev-backend.so\n"
466 #if defined(BUILD_HEADLESS_COMPOSITOR)
467 "\t\t\t\theadless-backend.so\n"
469 #if defined(BUILD_RDP_COMPOSITOR)
470 "\t\t\t\trdp-backend.so\n"
472 #if defined(BUILD_WAYLAND_COMPOSITOR)
473 "\t\t\t\twayland-backend.so\n"
475 #if defined(BUILD_X11_COMPOSITOR)
476 "\t\t\t\tx11-backend.so\n"
478 " --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
479 " -S, --socket=NAME\tName of socket to listen on\n"
480 " -i, --idle-time=SECS\tIdle time in seconds\n"
481 " --xwayland\t\tLoad the xwayland module\n"
482 " --modules\t\tLoad the comma-separated list of modules\n"
483 " --log=FILE\t\tLog to the given file\n"
484 " -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
485 " --no-config\t\tDo not read weston.ini\n"
486 " --wait-for-debugger\tRaise SIGSTOP on start-up\n"
487 " -h, --help\t\tThis help message\n\n");
489 #if defined(BUILD_DRM_COMPOSITOR)
491 "Options for drm-backend.so:\n\n"
492 " --seat=SEAT\t\tThe seat that weston should run on\n"
493 " --tty=TTY\t\tThe tty to use\n"
494 " --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
495 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
496 " --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
499 #if defined(BUILD_FBDEV_COMPOSITOR)
501 "Options for fbdev-backend.so:\n\n"
502 " --tty=TTY\t\tThe tty to use\n"
503 " --device=DEVICE\tThe framebuffer device to use\n"
507 #if defined(BUILD_HEADLESS_COMPOSITOR)
509 "Options for headless-backend.so:\n\n"
510 " --width=WIDTH\t\tWidth of memory surface\n"
511 " --height=HEIGHT\tHeight of memory surface\n"
512 " --transform=TR\tThe output transformation, TR is one of:\n"
513 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
514 " --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n"
515 " --no-outputs\t\tDo not create any virtual outputs\n"
519 #if defined(BUILD_RDP_COMPOSITOR)
521 "Options for rdp-backend.so:\n\n"
522 " --width=WIDTH\t\tWidth of desktop\n"
523 " --height=HEIGHT\tHeight of desktop\n"
524 " --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
525 " --address=ADDR\tThe address to bind\n"
526 " --port=PORT\t\tThe port to listen on\n"
527 " --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
528 " --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
529 " --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
530 " --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
534 #if defined(BUILD_WAYLAND_COMPOSITOR)
536 "Options for wayland-backend.so:\n\n"
537 " --width=WIDTH\t\tWidth of Wayland surface\n"
538 " --height=HEIGHT\tHeight of Wayland surface\n"
539 " --scale=SCALE\t\tScale factor of output\n"
540 " --fullscreen\t\tRun in fullscreen mode\n"
541 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
542 " --output-count=COUNT\tCreate multiple outputs\n"
543 " --sprawl\t\tCreate one fullscreen output for every parent output\n"
544 " --display=DISPLAY\tWayland display to connect to\n\n");
547 #if defined(BUILD_X11_COMPOSITOR)
549 "Options for x11-backend.so:\n\n"
550 " --width=WIDTH\t\tWidth of X window\n"
551 " --height=HEIGHT\tHeight of X window\n"
552 " --scale=SCALE\t\tScale factor of output\n"
553 " --fullscreen\t\tRun in fullscreen mode\n"
554 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
555 " --output-count=COUNT\tCreate multiple outputs\n"
556 " --no-input\t\tDont create input devices\n\n");
562 static int on_term_signal(int signal_number, void *data)
564 struct wl_display *display = data;
566 weston_log("caught signal %d\n", signal_number);
567 wl_display_terminate(display);
573 clock_name(clockid_t clk_id)
575 static const char *names[] = {
576 [CLOCK_REALTIME] = "CLOCK_REALTIME",
577 [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
578 [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
579 [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
580 [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
581 #ifdef CLOCK_BOOTTIME
582 [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
586 if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
589 return names[clk_id];
592 static const struct {
593 uint32_t bit; /* enum weston_capability */
595 } capability_strings[] = {
596 { WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
597 { WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
601 weston_compositor_log_capabilities(struct weston_compositor *compositor)
607 weston_log("Compositor capabilities:\n");
608 for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
609 yes = compositor->capabilities & capability_strings[i].bit;
610 weston_log_continue(STAMP_SPACE "%s %s\n",
611 capability_strings[i].desc,
615 weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
616 clock_name(compositor->presentation_clock),
617 compositor->presentation_clock);
619 if (clock_getres(compositor->presentation_clock, &res) == 0)
620 weston_log_continue(STAMP_SPACE
621 "presentation clock resolution: %d.%09ld s\n",
622 (int)res.tv_sec, res.tv_nsec);
624 weston_log_continue(STAMP_SPACE
625 "presentation clock resolution: N/A\n");
629 handle_primary_client_destroyed(struct wl_listener *listener, void *data)
631 struct wl_client *client = data;
633 weston_log("Primary client died. Closing...\n");
635 wl_display_terminate(wl_client_get_display(client));
639 weston_create_listening_socket(struct wl_display *display, const char *socket_name)
642 if (wl_display_add_socket(display, socket_name)) {
643 weston_log("fatal: failed to add socket: %m\n");
647 socket_name = wl_display_add_socket_auto(display);
649 weston_log("fatal: failed to add socket: %m\n");
654 setenv("WAYLAND_DISPLAY", socket_name, 1);
660 wet_load_module_entrypoint(const char *name, const char *entrypoint)
662 const char *builddir = getenv("WESTON_BUILD_DIR");
670 if (name[0] != '/') {
672 len = snprintf(path, sizeof path, "%s/.libs/%s", builddir,
675 len = snprintf(path, sizeof path, "%s/%s", MODULEDIR,
678 len = snprintf(path, sizeof path, "%s", name);
681 /* snprintf returns the length of the string it would've written,
682 * _excluding_ the NUL byte. So even being equal to the size of
683 * our buffer is an error here. */
684 if (len >= sizeof path)
687 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
689 weston_log("Module '%s' already loaded\n", path);
694 weston_log("Loading module '%s'\n", path);
695 module = dlopen(path, RTLD_NOW);
697 weston_log("Failed to load module: %s\n", dlerror());
701 init = dlsym(module, entrypoint);
703 weston_log("Failed to lookup init function: %s\n", dlerror());
713 wet_load_module(struct weston_compositor *compositor,
714 const char *name, int *argc, char *argv[])
716 int (*module_init)(struct weston_compositor *ec,
717 int *argc, char *argv[]);
719 module_init = wet_load_module_entrypoint(name, "wet_module_init");
722 if (module_init(compositor, argc, argv) < 0)
728 wet_load_shell(struct weston_compositor *compositor,
729 const char *name, int *argc, char *argv[])
731 int (*shell_init)(struct weston_compositor *ec,
732 int *argc, char *argv[]);
734 shell_init = wet_load_module_entrypoint(name, "wet_shell_init");
737 if (shell_init(compositor, argc, argv) < 0)
743 load_modules(struct weston_compositor *ec, const char *modules,
744 int *argc, char *argv[], int32_t *xwayland)
754 end = strchrnul(p, ',');
755 snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
757 if (strstr(buffer, "xwayland.so")) {
758 weston_log("Old Xwayland module loading detected: "
759 "Please use --xwayland command line option "
760 "or set xwayland=true in the [core] section "
764 if (wet_load_module(ec, buffer, argc, argv) < 0)
777 weston_compositor_init_config(struct weston_compositor *ec,
778 struct weston_config *config)
780 struct xkb_rule_names xkb_names;
781 struct weston_config_section *s;
785 s = weston_config_get_section(config, "keyboard", NULL, NULL);
786 weston_config_section_get_string(s, "keymap_rules",
787 (char **) &xkb_names.rules, NULL);
788 weston_config_section_get_string(s, "keymap_model",
789 (char **) &xkb_names.model, NULL);
790 weston_config_section_get_string(s, "keymap_layout",
791 (char **) &xkb_names.layout, NULL);
792 weston_config_section_get_string(s, "keymap_variant",
793 (char **) &xkb_names.variant, NULL);
794 weston_config_section_get_string(s, "keymap_options",
795 (char **) &xkb_names.options, NULL);
797 if (weston_compositor_set_xkb_rule_names(ec, &xkb_names) < 0)
800 weston_config_section_get_int(s, "repeat-rate",
801 &ec->kb_repeat_rate, 40);
802 weston_config_section_get_int(s, "repeat-delay",
803 &ec->kb_repeat_delay, 400);
805 weston_config_section_get_bool(s, "vt-switching",
806 &vt_switching, true);
807 ec->vt_switching = vt_switching;
809 s = weston_config_get_section(config, "core", NULL, NULL);
810 weston_config_section_get_int(s, "repaint-window", &repaint_msec,
812 if (repaint_msec < -10 || repaint_msec > 1000) {
813 weston_log("Invalid repaint_window value in config: %d\n",
816 ec->repaint_msec = repaint_msec;
818 weston_log("Output repaint window is %d ms maximum.\n",
825 weston_choose_default_backend(void)
827 char *backend = NULL;
829 if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
830 backend = strdup("wayland-backend.so");
831 else if (getenv("DISPLAY"))
832 backend = strdup("x11-backend.so");
834 backend = strdup(WESTON_NATIVE_BACKEND);
839 static const struct { const char *name; uint32_t token; } transforms[] = {
840 { "normal", WL_OUTPUT_TRANSFORM_NORMAL },
841 { "90", WL_OUTPUT_TRANSFORM_90 },
842 { "180", WL_OUTPUT_TRANSFORM_180 },
843 { "270", WL_OUTPUT_TRANSFORM_270 },
844 { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
845 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
846 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
847 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
851 weston_parse_transform(const char *transform, uint32_t *out)
855 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
856 if (strcmp(transforms[i].name, transform) == 0) {
857 *out = transforms[i].token;
861 *out = WL_OUTPUT_TRANSFORM_NORMAL;
865 WL_EXPORT const char *
866 weston_transform_to_string(uint32_t output_transform)
870 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
871 if (transforms[i].token == output_transform)
872 return transforms[i].name;
874 return "<illegal value>";
878 load_configuration(struct weston_config **config, int32_t noconfig,
879 const char *config_file)
881 const char *file = "weston.ini";
882 const char *full_path;
890 *config = weston_config_parse(file);
893 full_path = weston_config_get_full_path(*config);
895 weston_log("Using config file '%s'\n", full_path);
896 setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
901 if (config_file && noconfig == 0) {
902 weston_log("fatal: error opening or reading config file"
903 " '%s'.\n", config_file);
908 weston_log("Starting with no config file.\n");
909 setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
915 handle_exit(struct weston_compositor *c)
917 wl_display_terminate(c->wl_display);
921 wet_output_set_scale(struct weston_output *output,
922 struct weston_config_section *section,
923 int32_t default_scale,
924 int32_t parsed_scale)
926 int32_t scale = default_scale;
929 weston_config_section_get_int(section, "scale", &scale, default_scale);
932 scale = parsed_scale;
934 weston_output_set_scale(output, scale);
937 /* UINT32_MAX is treated as invalid because 0 is a valid
938 * enumeration value and the parameter is unsigned
941 wet_output_set_transform(struct weston_output *output,
942 struct weston_config_section *section,
943 uint32_t default_transform,
944 uint32_t parsed_transform)
947 uint32_t transform = default_transform;
950 weston_config_section_get_string(section,
951 "transform", &t, "normal");
953 if (weston_parse_transform(t, &transform) < 0) {
954 weston_log("Invalid transform \"%s\" for output %s\n",
956 transform = default_transform;
961 if (parsed_transform != UINT32_MAX)
962 transform = parsed_transform;
964 weston_output_set_transform(output, transform);
968 wet_configure_windowed_output_from_config(struct weston_output *output,
969 struct wet_output_config *defaults)
971 const struct weston_windowed_output_api *api =
972 weston_windowed_output_get_api(output->compositor);
974 struct weston_config *wc = wet_get_config(output->compositor);
975 struct weston_config_section *section = NULL;
976 struct wet_compositor *compositor = to_wet_compositor(output->compositor);
977 struct wet_output_config *parsed_options = compositor->parsed_options;
978 int width = defaults->width;
979 int height = defaults->height;
981 assert(parsed_options);
984 weston_log("Cannot use weston_windowed_output_api.\n");
988 section = weston_config_get_section(wc, "output", "name", output->name);
993 weston_config_section_get_string(section, "mode", &mode, NULL);
994 if (!mode || sscanf(mode, "%dx%d", &width,
996 weston_log("Invalid mode for output %s. Using defaults.\n",
998 width = defaults->width;
999 height = defaults->height;
1004 if (parsed_options->width)
1005 width = parsed_options->width;
1007 if (parsed_options->height)
1008 height = parsed_options->height;
1010 wet_output_set_scale(output, section, defaults->scale, parsed_options->scale);
1011 wet_output_set_transform(output, section, defaults->transform, parsed_options->transform);
1013 if (api->output_set_size(output, width, height) < 0) {
1014 weston_log("Cannot configure output \"%s\" using weston_windowed_output_api.\n",
1023 count_remaining_heads(struct weston_output *output, struct weston_head *to_go)
1025 struct weston_head *iter = NULL;
1028 while ((iter = weston_output_iterate_heads(output, iter))) {
1037 wet_head_tracker_destroy(struct wet_head_tracker *track)
1039 wl_list_remove(&track->head_destroy_listener.link);
1044 handle_head_destroy(struct wl_listener *listener, void *data)
1046 struct weston_head *head = data;
1047 struct weston_output *output;
1048 struct wet_head_tracker *track =
1049 container_of(listener, struct wet_head_tracker,
1050 head_destroy_listener);
1052 wet_head_tracker_destroy(track);
1054 output = weston_head_get_output(head);
1056 /* On shutdown path, the output might be already gone. */
1060 if (count_remaining_heads(output, head) > 0)
1063 weston_output_destroy(output);
1066 static struct wet_head_tracker *
1067 wet_head_tracker_from_head(struct weston_head *head)
1069 struct wl_listener *lis;
1071 lis = weston_head_get_destroy_listener(head, handle_head_destroy);
1075 return container_of(lis, struct wet_head_tracker,
1076 head_destroy_listener);
1079 /* Listen for head destroy signal.
1081 * If a head is destroyed and it was the last head on the output, we
1082 * destroy the associated output.
1084 * Do not bother destroying the head trackers on shutdown, the backend will
1085 * destroy the heads which calls our handler to destroy the trackers.
1088 wet_head_tracker_create(struct wet_compositor *compositor,
1089 struct weston_head *head)
1091 struct wet_head_tracker *track;
1093 track = zalloc(sizeof *track);
1097 track->head_destroy_listener.notify = handle_head_destroy;
1098 weston_head_add_destroy_listener(head, &track->head_destroy_listener);
1102 simple_head_enable(struct weston_compositor *compositor, struct weston_head *head)
1104 struct wet_compositor *wet = to_wet_compositor(compositor);
1105 struct weston_output *output;
1108 output = weston_compositor_create_output_with_head(compositor, head);
1110 weston_log("Could not create an output for head \"%s\".\n",
1111 weston_head_get_name(head));
1112 wet->init_failed = true;
1117 if (wet->simple_output_configure)
1118 ret = wet->simple_output_configure(output);
1120 weston_log("Cannot configure output \"%s\".\n",
1121 weston_head_get_name(head));
1122 weston_output_destroy(output);
1123 wet->init_failed = true;
1128 if (weston_output_enable(output) < 0) {
1129 weston_log("Enabling output \"%s\" failed.\n",
1130 weston_head_get_name(head));
1131 weston_output_destroy(output);
1132 wet->init_failed = true;
1137 wet_head_tracker_create(wet, head);
1139 /* The weston_compositor will track and destroy the output on exit. */
1143 simple_head_disable(struct weston_head *head)
1145 struct weston_output *output;
1146 struct wet_head_tracker *track;
1148 track = wet_head_tracker_from_head(head);
1150 wet_head_tracker_destroy(track);
1152 output = weston_head_get_output(head);
1154 weston_output_destroy(output);
1158 simple_heads_changed(struct wl_listener *listener, void *arg)
1160 struct weston_compositor *compositor = arg;
1161 struct weston_head *head = NULL;
1166 while ((head = weston_compositor_iterate_heads(compositor, head))) {
1167 connected = weston_head_is_connected(head);
1168 enabled = weston_head_is_enabled(head);
1169 changed = weston_head_is_device_changed(head);
1171 if (connected && !enabled) {
1172 simple_head_enable(compositor, head);
1173 } else if (!connected && enabled) {
1174 simple_head_disable(head);
1175 } else if (enabled && changed) {
1176 weston_log("Detected a monitor change on head '%s', "
1177 "not bothering to do anything about it.\n",
1178 weston_head_get_name(head));
1180 weston_head_reset_device_changed(head);
1185 wet_set_simple_head_configurator(struct weston_compositor *compositor,
1186 int (*fn)(struct weston_output *))
1188 struct wet_compositor *wet = to_wet_compositor(compositor);
1190 wet->simple_output_configure = fn;
1192 wet->heads_changed_listener.notify = simple_heads_changed;
1193 weston_compositor_add_heads_changed_listener(compositor,
1194 &wet->heads_changed_listener);
1198 configure_input_device(struct weston_compositor *compositor,
1199 struct libinput_device *device)
1201 struct weston_config_section *s;
1202 struct weston_config *config = wet_get_config(compositor);
1204 int enable_tap_default;
1206 s = weston_config_get_section(config,
1207 "libinput", NULL, NULL);
1209 if (libinput_device_config_tap_get_finger_count(device) > 0) {
1210 enable_tap_default =
1211 libinput_device_config_tap_get_default_enabled(
1213 weston_config_section_get_bool(s, "enable_tap",
1215 enable_tap_default);
1216 libinput_device_config_tap_set_enabled(device,
1222 drm_backend_output_configure(struct wl_listener *listener, void *data)
1224 struct weston_output *output = data;
1225 struct weston_config *wc = wet_get_config(output->compositor);
1226 struct wet_compositor *wet = to_wet_compositor(output->compositor);
1227 struct weston_config_section *section;
1228 const struct weston_drm_output_api *api = weston_drm_output_get_api(output->compositor);
1229 enum weston_drm_backend_output_mode mode =
1230 WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
1233 char *modeline = NULL;
1234 char *gbm_format = NULL;
1238 weston_log("Cannot use weston_drm_output_api.\n");
1242 section = weston_config_get_section(wc, "output", "name", output->name);
1243 weston_config_section_get_string(section, "mode", &s, "preferred");
1245 if (strcmp(s, "off") == 0) {
1246 weston_output_disable(output);
1249 } else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) {
1250 mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
1251 } else if (strcmp(s, "preferred") != 0) {
1257 if (api->set_mode(output, mode, modeline) < 0) {
1258 weston_log("Cannot configure an output using weston_drm_output_api.\n");
1264 wet_output_set_scale(output, section, 1, 0);
1265 wet_output_set_transform(output, section, WL_OUTPUT_TRANSFORM_NORMAL, UINT32_MAX);
1267 weston_config_section_get_string(section,
1268 "gbm-format", &gbm_format, NULL);
1270 api->set_gbm_format(output, gbm_format);
1273 weston_config_section_get_string(section, "seat", &seat, "");
1275 api->set_seat(output, seat);
1278 weston_output_enable(output);
1282 load_drm_backend(struct weston_compositor *c,
1283 int *argc, char **argv, struct weston_config *wc)
1285 struct weston_drm_backend_config config = {{ 0, }};
1286 struct weston_config_section *section;
1287 struct wet_compositor *wet = to_wet_compositor(c);
1290 wet->drm_use_current_mode = false;
1292 const struct weston_option options[] = {
1293 { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
1294 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
1295 { WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
1296 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
1297 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1300 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1302 section = weston_config_get_section(wc, "core", NULL, NULL);
1303 weston_config_section_get_string(section,
1304 "gbm-format", &config.gbm_format,
1306 weston_config_section_get_uint(section, "pageflip-timeout",
1307 &config.pageflip_timeout, 0);
1309 config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
1310 config.base.struct_size = sizeof(struct weston_drm_backend_config);
1311 config.configure_device = configure_input_device;
1313 ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
1316 wet_set_pending_output_handler(c, drm_backend_output_configure);
1318 free(config.gbm_format);
1319 free(config.seat_id);
1325 headless_backend_output_configure(struct weston_output *output)
1327 struct wet_output_config defaults = {
1331 .transform = WL_OUTPUT_TRANSFORM_NORMAL
1334 return wet_configure_windowed_output_from_config(output, &defaults);
1338 load_headless_backend(struct weston_compositor *c,
1339 int *argc, char **argv, struct weston_config *wc)
1341 const struct weston_windowed_output_api *api;
1342 struct weston_headless_backend_config config = {{ 0, }};
1345 char *transform = NULL;
1347 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
1348 if (!parsed_options)
1351 const struct weston_option options[] = {
1352 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
1353 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
1354 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1355 { WESTON_OPTION_STRING, "transform", 0, &transform },
1356 { WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
1359 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1362 if (weston_parse_transform(transform, &parsed_options->transform) < 0) {
1363 weston_log("Invalid transform \"%s\"\n", transform);
1364 parsed_options->transform = UINT32_MAX;
1369 config.base.struct_version = WESTON_HEADLESS_BACKEND_CONFIG_VERSION;
1370 config.base.struct_size = sizeof(struct weston_headless_backend_config);
1372 wet_set_simple_head_configurator(c, headless_backend_output_configure);
1374 /* load the actual wayland backend and configure it */
1375 ret = weston_compositor_load_backend(c, WESTON_BACKEND_HEADLESS,
1382 api = weston_windowed_output_get_api(c);
1385 weston_log("Cannot use weston_windowed_output_api.\n");
1389 if (api->output_create(c, "headless") < 0)
1397 rdp_backend_output_configure(struct wl_listener *listener, void *data)
1399 struct weston_output *output = data;
1400 struct wet_compositor *compositor = to_wet_compositor(output->compositor);
1401 struct wet_output_config *parsed_options = compositor->parsed_options;
1402 const struct weston_rdp_output_api *api = weston_rdp_output_get_api(output->compositor);
1406 assert(parsed_options);
1409 weston_log("Cannot use weston_rdp_output_api.\n");
1413 if (parsed_options->width)
1414 width = parsed_options->width;
1416 if (parsed_options->height)
1417 height = parsed_options->height;
1419 weston_output_set_scale(output, 1);
1420 weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
1422 if (api->output_set_size(output, width, height) < 0) {
1423 weston_log("Cannot configure output \"%s\" using weston_rdp_output_api.\n",
1428 weston_output_enable(output);
1432 weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
1434 config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
1435 config->base.struct_size = sizeof(struct weston_rdp_backend_config);
1437 config->bind_address = NULL;
1438 config->port = 3389;
1439 config->rdp_key = NULL;
1440 config->server_cert = NULL;
1441 config->server_key = NULL;
1442 config->env_socket = 0;
1443 config->no_clients_resize = 0;
1447 load_rdp_backend(struct weston_compositor *c,
1448 int *argc, char *argv[], struct weston_config *wc)
1450 struct weston_rdp_backend_config config = {{ 0, }};
1453 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
1454 if (!parsed_options)
1457 weston_rdp_backend_config_init(&config);
1459 const struct weston_option rdp_options[] = {
1460 { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
1461 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
1462 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
1463 { WESTON_OPTION_STRING, "address", 0, &config.bind_address },
1464 { WESTON_OPTION_INTEGER, "port", 0, &config.port },
1465 { WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
1466 { WESTON_OPTION_STRING, "rdp4-key", 0, &config.rdp_key },
1467 { WESTON_OPTION_STRING, "rdp-tls-cert", 0, &config.server_cert },
1468 { WESTON_OPTION_STRING, "rdp-tls-key", 0, &config.server_key }
1471 parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
1473 ret = weston_compositor_load_backend(c, WESTON_BACKEND_RDP,
1479 wet_set_pending_output_handler(c, rdp_backend_output_configure);
1482 free(config.bind_address);
1483 free(config.rdp_key);
1484 free(config.server_cert);
1485 free(config.server_key);
1491 fbdev_backend_output_configure(struct wl_listener *listener, void *data)
1493 struct weston_output *output = data;
1494 struct weston_config *wc = wet_get_config(output->compositor);
1495 struct weston_config_section *section;
1497 section = weston_config_get_section(wc, "output", "name", "fbdev");
1499 wet_output_set_transform(output, section, WL_OUTPUT_TRANSFORM_NORMAL, UINT32_MAX);
1500 weston_output_set_scale(output, 1);
1502 weston_output_enable(output);
1506 load_fbdev_backend(struct weston_compositor *c,
1507 int *argc, char **argv, struct weston_config *wc)
1509 struct weston_fbdev_backend_config config = {{ 0, }};
1512 const struct weston_option fbdev_options[] = {
1513 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
1514 { WESTON_OPTION_STRING, "device", 0, &config.device },
1517 parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
1520 config.device = strdup("/dev/fb0");
1522 config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
1523 config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
1524 config.configure_device = configure_input_device;
1526 /* load the actual wayland backend and configure it */
1527 ret = weston_compositor_load_backend(c, WESTON_BACKEND_FBDEV,
1533 wet_set_pending_output_handler(c, fbdev_backend_output_configure);
1536 free(config.device);
1541 x11_backend_output_configure(struct weston_output *output)
1543 struct wet_output_config defaults = {
1547 .transform = WL_OUTPUT_TRANSFORM_NORMAL
1550 return wet_configure_windowed_output_from_config(output, &defaults);
1554 load_x11_backend(struct weston_compositor *c,
1555 int *argc, char **argv, struct weston_config *wc)
1557 char *default_output;
1558 const struct weston_windowed_output_api *api;
1559 struct weston_x11_backend_config config = {{ 0, }};
1560 struct weston_config_section *section;
1562 int option_count = 1;
1563 int output_count = 0;
1564 char const *section_name;
1567 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
1568 if (!parsed_options)
1571 const struct weston_option options[] = {
1572 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
1573 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
1574 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
1575 { WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
1576 { WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
1577 { WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
1578 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1581 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1583 config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
1584 config.base.struct_size = sizeof(struct weston_x11_backend_config);
1586 wet_set_simple_head_configurator(c, x11_backend_output_configure);
1588 /* load the actual backend and configure it */
1589 ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
1595 api = weston_windowed_output_get_api(c);
1598 weston_log("Cannot use weston_windowed_output_api.\n");
1603 while (weston_config_next_section(wc, §ion, §ion_name)) {
1606 if (output_count >= option_count)
1609 if (strcmp(section_name, "output") != 0) {
1613 weston_config_section_get_string(section, "name", &output_name, NULL);
1614 if (output_name == NULL || output_name[0] != 'X') {
1619 if (api->output_create(c, output_name) < 0) {
1628 default_output = NULL;
1630 for (i = output_count; i < option_count; i++) {
1631 if (asprintf(&default_output, "screen%d", i) < 0) {
1635 if (api->output_create(c, default_output) < 0) {
1636 free(default_output);
1639 free(default_output);
1646 wayland_backend_output_configure_hotplug(struct wl_listener *listener, void *data)
1648 struct weston_output *output = data;
1650 /* This backend has all values hardcoded, so nothing can be configured here */
1651 weston_output_enable(output);
1655 wayland_backend_output_configure(struct wl_listener *listener, void *data)
1657 struct weston_output *output = data;
1658 struct wet_output_config defaults = {
1662 .transform = WL_OUTPUT_TRANSFORM_NORMAL
1665 if (wet_configure_windowed_output_from_config(output, &defaults) < 0)
1666 weston_log("Cannot configure output \"%s\".\n", output->name);
1668 weston_output_enable(output);
1672 load_wayland_backend(struct weston_compositor *c,
1673 int *argc, char **argv, struct weston_config *wc)
1675 struct weston_wayland_backend_config config = {{ 0, }};
1676 struct weston_config_section *section;
1677 const struct weston_windowed_output_api *api;
1678 const char *section_name;
1679 char *output_name = NULL;
1683 int32_t use_pixman_ = 0;
1684 int32_t sprawl_ = 0;
1685 int32_t fullscreen_ = 0;
1687 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
1688 if (!parsed_options)
1691 config.cursor_size = 32;
1692 config.cursor_theme = NULL;
1693 config.display_name = NULL;
1695 const struct weston_option wayland_options[] = {
1696 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
1697 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
1698 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
1699 { WESTON_OPTION_STRING, "display", 0, &config.display_name },
1700 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &use_pixman_ },
1701 { WESTON_OPTION_INTEGER, "output-count", 0, &count },
1702 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen_ },
1703 { WESTON_OPTION_BOOLEAN, "sprawl", 0, &sprawl_ },
1706 parse_options(wayland_options, ARRAY_LENGTH(wayland_options), argc, argv);
1707 config.sprawl = sprawl_;
1708 config.use_pixman = use_pixman_;
1709 config.fullscreen = fullscreen_;
1711 section = weston_config_get_section(wc, "shell", NULL, NULL);
1712 weston_config_section_get_string(section, "cursor-theme",
1713 &config.cursor_theme, NULL);
1714 weston_config_section_get_int(section, "cursor-size",
1715 &config.cursor_size, 32);
1717 config.base.struct_size = sizeof(struct weston_wayland_backend_config);
1718 config.base.struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION;
1720 /* load the actual wayland backend and configure it */
1721 ret = weston_compositor_load_backend(c, WESTON_BACKEND_WAYLAND,
1724 free(config.cursor_theme);
1725 free(config.display_name);
1730 api = weston_windowed_output_get_api(c);
1733 /* We will just assume if load_backend() finished cleanly and
1734 * windowed_output_api is not present that wayland backend is
1735 * started with --sprawl or runs on fullscreen-shell. */
1736 wet_set_pending_output_handler(c, wayland_backend_output_configure_hotplug);
1741 wet_set_pending_output_handler(c, wayland_backend_output_configure);
1744 while (weston_config_next_section(wc, §ion, §ion_name)) {
1748 if (strcmp(section_name, "output") != 0) {
1752 weston_config_section_get_string(section, "name", &output_name, NULL);
1754 if (output_name == NULL)
1757 if (output_name[0] != 'W' || output_name[1] != 'L') {
1762 if (api->output_create(c, output_name) < 0) {
1771 for (i = 0; i < count; i++) {
1772 if (asprintf(&output_name, "wayland%d", i) < 0)
1775 if (api->output_create(c, output_name) < 0) {
1787 load_backend(struct weston_compositor *compositor, const char *backend,
1788 int *argc, char **argv, struct weston_config *config)
1790 if (strstr(backend, "headless-backend.so"))
1791 return load_headless_backend(compositor, argc, argv, config);
1792 else if (strstr(backend, "rdp-backend.so"))
1793 return load_rdp_backend(compositor, argc, argv, config);
1794 else if (strstr(backend, "fbdev-backend.so"))
1795 return load_fbdev_backend(compositor, argc, argv, config);
1796 else if (strstr(backend, "drm-backend.so"))
1797 return load_drm_backend(compositor, argc, argv, config);
1798 else if (strstr(backend, "x11-backend.so"))
1799 return load_x11_backend(compositor, argc, argv, config);
1800 else if (strstr(backend, "wayland-backend.so"))
1801 return load_wayland_backend(compositor, argc, argv, config);
1803 weston_log("Error: unknown backend \"%s\"\n", backend);
1808 copy_command_line(int argc, char * const argv[])
1815 fp = open_memstream(&str, &size);
1819 fprintf(fp, "%s", argv[0]);
1820 for (i = 1; i < argc; i++)
1821 fprintf(fp, " %s", argv[i]);
1827 int main(int argc, char *argv[])
1829 int ret = EXIT_FAILURE;
1831 struct wl_display *display;
1832 struct weston_compositor *ec;
1833 struct wl_event_source *signals[4];
1834 struct wl_event_loop *loop;
1836 char *backend = NULL;
1838 int32_t xwayland = 0;
1839 char *modules = NULL;
1840 char *option_modules = NULL;
1842 char *server_socket = NULL;
1843 int32_t idle_time = -1;
1845 char *socket_name = NULL;
1846 int32_t version = 0;
1847 int32_t noconfig = 0;
1849 char *config_file = NULL;
1850 struct weston_config *config = NULL;
1851 struct weston_config_section *section;
1852 struct wl_client *primary_client;
1853 struct wl_listener primary_client_destroyed;
1854 struct weston_seat *seat;
1855 struct wet_compositor user_data = { 0 };
1857 int32_t wait_for_debugger = 0;
1859 const struct weston_option core_options[] = {
1860 { WESTON_OPTION_STRING, "backend", 'B', &backend },
1861 { WESTON_OPTION_STRING, "shell", 0, &shell },
1862 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
1863 { WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
1864 { WESTON_OPTION_BOOLEAN, "xwayland", 0, &xwayland },
1865 { WESTON_OPTION_STRING, "modules", 0, &option_modules },
1866 { WESTON_OPTION_STRING, "log", 0, &log },
1867 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
1868 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
1869 { WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
1870 { WESTON_OPTION_STRING, "config", 'c', &config_file },
1871 { WESTON_OPTION_BOOLEAN, "wait-for-debugger", 0, &wait_for_debugger },
1874 if (os_fd_set_cloexec(fileno(stdin))) {
1875 printf("Unable to set stdin as close on exec().\n");
1876 return EXIT_FAILURE;
1879 cmdline = copy_command_line(argc, argv);
1880 parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
1884 usage(EXIT_SUCCESS);
1888 printf(PACKAGE_STRING "\n");
1891 return EXIT_SUCCESS;
1894 weston_log_set_handler(vlog, vlog_continue);
1895 weston_log_file_open(log);
1899 STAMP_SPACE "Bug reports to: %s\n"
1900 STAMP_SPACE "Build: %s\n",
1901 PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
1903 weston_log("Command line: %s\n", cmdline);
1907 verify_xdg_runtime_dir();
1909 display = wl_display_create();
1911 loop = wl_display_get_event_loop(display);
1912 signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
1914 signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
1916 signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
1919 wl_list_init(&child_process_list);
1920 signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
1923 if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
1926 if (load_configuration(&config, noconfig, config_file) < 0)
1928 user_data.config = config;
1929 user_data.parsed_options = NULL;
1931 section = weston_config_get_section(config, "core", NULL, NULL);
1933 if (!wait_for_debugger)
1934 weston_config_section_get_bool(section, "wait-for-debugger",
1935 &wait_for_debugger, 0);
1936 if (wait_for_debugger) {
1937 weston_log("Weston PID is %ld - "
1938 "waiting for debugger, send SIGCONT to continue...\n",
1944 weston_config_section_get_string(section, "backend", &backend,
1947 backend = weston_choose_default_backend();
1950 ec = weston_compositor_create(display, &user_data);
1952 weston_log("fatal: failed to create compositor\n");
1955 segv_compositor = ec;
1957 if (weston_compositor_init_config(ec, config) < 0)
1960 weston_config_section_get_bool(section, "require-input",
1961 &require_input, true);
1962 ec->require_input = require_input;
1964 if (load_backend(ec, backend, &argc, argv, config) < 0) {
1965 weston_log("fatal: failed to create compositor backend\n");
1969 weston_pending_output_coldplug(ec);
1970 if (user_data.init_failed)
1974 weston_config_section_get_int(section, "idle-time", &idle_time, -1);
1976 idle_time = 300; /* default idle timeout, in seconds */
1978 ec->idle_time = idle_time;
1979 ec->default_pointer_grab = NULL;
1980 ec->exit = handle_exit;
1982 weston_compositor_log_capabilities(ec);
1984 server_socket = getenv("WAYLAND_SERVER_SOCKET");
1985 if (server_socket) {
1986 weston_log("Running with single client\n");
1987 if (!safe_strtoint(server_socket, &fd))
1994 primary_client = wl_client_create(display, fd);
1995 if (!primary_client) {
1996 weston_log("fatal: failed to add client: %m\n");
1999 primary_client_destroyed.notify =
2000 handle_primary_client_destroyed;
2001 wl_client_add_destroy_listener(primary_client,
2002 &primary_client_destroyed);
2003 } else if (weston_create_listening_socket(display, socket_name)) {
2008 weston_config_section_get_string(section, "shell", &shell,
2009 "desktop-shell.so");
2011 if (wet_load_shell(ec, shell, &argc, argv) < 0)
2014 weston_config_section_get_string(section, "modules", &modules, "");
2015 if (load_modules(ec, modules, &argc, argv, &xwayland) < 0)
2018 if (load_modules(ec, option_modules, &argc, argv, &xwayland) < 0)
2022 weston_config_section_get_bool(section, "xwayland", &xwayland,
2025 if (wet_load_xwayland(ec) < 0)
2029 section = weston_config_get_section(config, "keyboard", NULL, NULL);
2030 weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
2032 wl_list_for_each(seat, &ec->seat_list, link) {
2033 struct weston_keyboard *keyboard =
2034 weston_seat_get_keyboard(seat);
2037 weston_keyboard_set_locks(keyboard,
2043 for (i = 1; i < argc; i++)
2044 weston_log("fatal: unhandled option: %s\n", argv[i]);
2048 weston_compositor_wake(ec);
2050 wl_display_run(display);
2052 /* Allow for setting return exit code after
2053 * wl_display_run returns normally. This is
2054 * useful for devs/testers and automated tests
2055 * that want to indicate failure status to
2056 * testing infrastructure above
2058 ret = ec->exit_code;
2061 /* free(NULL) is valid, and it won't be NULL if it's used */
2062 free(user_data.parsed_options);
2064 weston_compositor_destroy(ec);
2067 for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
2069 wl_event_source_remove(signals[i]);
2071 wl_display_destroy(display);
2073 weston_log_file_close();
2076 weston_config_destroy(config);
2081 free(option_modules);