compositor: move the main() to a new main.c file

This commits starts to separate the libweston code from the weston
specific code. As such, the main() is moved, together with signals
handling and configuration handling.

The definition of DEFAULT_REPAINT_WINDOW is left in compositor.c, so the
config loading of repaint_msec is slightly modified to account that.

Acked-by: Bryce Harrington <bryce@osg.samsung.com>
Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
dev
Giulio Camuffo 10 years ago committed by Pekka Paalanen
parent 459137bfe6
commit bab996e571
  1. 1
      Makefile.am
  2. 805
      src/compositor.c
  3. 848
      src/main.c

@ -86,6 +86,7 @@ weston_SOURCES = \
src/timeline.c \
src/timeline.h \
src/timeline-object.h \
src/main.c \
shared/helpers.h \
shared/matrix.c \
shared/matrix.h \

@ -51,11 +51,6 @@
#include <time.h>
#include <errno.h>
#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#endif
#include "timeline.h"
#include "compositor.h"
@ -88,37 +83,6 @@ timespec_to_nsec(const struct timespec *a)
return (int64_t)a->tv_sec * NSEC_PER_SEC + a->tv_nsec;
}
static struct wl_list child_process_list;
static struct weston_compositor *segv_compositor;
static int
sigchld_handler(int signal_number, void *data)
{
struct weston_process *p;
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
wl_list_for_each(p, &child_process_list, link) {
if (p->pid == pid)
break;
}
if (&p->link == &child_process_list) {
weston_log("unknown child process exited\n");
continue;
}
wl_list_remove(&p->link);
p->cleanup(p, status);
}
if (pid < 0 && errno != ECHILD)
weston_log("waitpid error %m\n");
return 1;
}
static void
weston_output_transform_scale_init(struct weston_output *output,
uint32_t transform, uint32_t scale);
@ -290,12 +254,6 @@ weston_output_mode_switch_to_temporary(struct weston_output *output,
return 0;
}
WL_EXPORT void
weston_watch_process(struct weston_process *process)
{
wl_list_insert(&child_process_list, &process->link);
}
static void
child_client_exec(int sockfd, const char *path)
{
@ -4454,17 +4412,6 @@ compositor_bind(struct wl_client *client,
compositor, NULL);
}
static void
log_uname(void)
{
struct utsname usys;
uname(&usys);
weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
usys.version, usys.machine);
}
WL_EXPORT int
weston_environment_get_fd(const char *env)
{
@ -4539,6 +4486,7 @@ weston_compositor_create(struct wl_display *display, void *user_data)
ec->session_active = 1;
ec->output_id_pool = 0;
ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
if (!wl_global_create(ec->wl_display, &wl_compositor_interface, 3,
ec, compositor_bind))
@ -4596,47 +4544,6 @@ fail:
return NULL;
}
static int
weston_compositor_init_config(struct weston_compositor *ec,
struct weston_config *config)
{
struct xkb_rule_names xkb_names;
struct weston_config_section *s;
s = weston_config_get_section(config, "keyboard", NULL, NULL);
weston_config_section_get_string(s, "keymap_rules",
(char **) &xkb_names.rules, NULL);
weston_config_section_get_string(s, "keymap_model",
(char **) &xkb_names.model, NULL);
weston_config_section_get_string(s, "keymap_layout",
(char **) &xkb_names.layout, NULL);
weston_config_section_get_string(s, "keymap_variant",
(char **) &xkb_names.variant, NULL);
weston_config_section_get_string(s, "keymap_options",
(char **) &xkb_names.options, NULL);
if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
return -1;
weston_config_section_get_int(s, "repeat-rate",
&ec->kb_repeat_rate, 40);
weston_config_section_get_int(s, "repeat-delay",
&ec->kb_repeat_delay, 400);
s = weston_config_get_section(config, "core", NULL, NULL);
weston_config_section_get_int(s, "repaint-window", &ec->repaint_msec,
DEFAULT_REPAINT_WINDOW);
if (ec->repaint_msec < -10 || ec->repaint_msec > 1000) {
weston_log("Invalid repaint_window value in config: %d\n",
ec->repaint_msec);
ec->repaint_msec = DEFAULT_REPAINT_WINDOW;
}
weston_log("Output repaint window is %d ms maximum.\n",
ec->repaint_msec);
return 0;
}
WL_EXPORT void
weston_compositor_shutdown(struct weston_compositor *ec)
{
@ -4772,160 +4679,6 @@ weston_version(int *major, int *minor, int *micro)
*micro = WESTON_VERSION_MICRO;
}
static const char *
clock_name(clockid_t clk_id)
{
static const char *names[] = {
[CLOCK_REALTIME] = "CLOCK_REALTIME",
[CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
[CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
[CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
[CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
[CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
};
if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
return "unknown";
return names[clk_id];
}
static const struct {
uint32_t bit; /* enum weston_capability */
const char *desc;
} capability_strings[] = {
{ WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
{ WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
};
static void
weston_compositor_log_capabilities(struct weston_compositor *compositor)
{
unsigned i;
int yes;
weston_log("Compositor capabilities:\n");
for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
yes = compositor->capabilities & capability_strings[i].bit;
weston_log_continue(STAMP_SPACE "%s %s\n",
capability_strings[i].desc,
yes ? "yes" : "no");
}
weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
clock_name(compositor->presentation_clock),
compositor->presentation_clock);
}
static int on_term_signal(int signal_number, void *data)
{
struct wl_display *display = data;
weston_log("caught signal %d\n", signal_number);
wl_display_terminate(display);
return 1;
}
#ifdef HAVE_LIBUNWIND
static void
print_backtrace(void)
{
unw_cursor_t cursor;
unw_context_t context;
unw_word_t off;
unw_proc_info_t pip;
int ret, i = 0;
char procname[256];
const char *filename;
Dl_info dlinfo;
pip.unwind_info = NULL;
ret = unw_getcontext(&context);
if (ret) {
weston_log("unw_getcontext: %d\n", ret);
return;
}
ret = unw_init_local(&cursor, &context);
if (ret) {
weston_log("unw_init_local: %d\n", ret);
return;
}
ret = unw_step(&cursor);
while (ret > 0) {
ret = unw_get_proc_info(&cursor, &pip);
if (ret) {
weston_log("unw_get_proc_info: %d\n", ret);
break;
}
ret = unw_get_proc_name(&cursor, procname, 256, &off);
if (ret && ret != -UNW_ENOMEM) {
if (ret != -UNW_EUNSPEC)
weston_log("unw_get_proc_name: %d\n", ret);
procname[0] = '?';
procname[1] = 0;
}
if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
*dlinfo.dli_fname)
filename = dlinfo.dli_fname;
else
filename = "?";
weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
ret = unw_step(&cursor);
if (ret < 0)
weston_log("unw_step: %d\n", ret);
}
}
#else
static void
print_backtrace(void)
{
void *buffer[32];
int i, count;
Dl_info info;
count = backtrace(buffer, ARRAY_LENGTH(buffer));
for (i = 0; i < count; i++) {
dladdr(buffer[i], &info);
weston_log(" [%016lx] %s (%s)\n",
(long) buffer[i],
info.dli_sname ? info.dli_sname : "--",
info.dli_fname);
}
}
#endif
static void
on_caught_signal(int s, siginfo_t *siginfo, void *context)
{
/* This signal handler will do a best-effort backtrace, and
* then call the backend restore function, which will switch
* back to the vt we launched from or ungrab X etc and then
* raise SIGTRAP. If we run weston under gdb from X or a
* different vt, and tell gdb "handle *s* nostop", this
* will allow weston to switch back to gdb on crash and then
* gdb will catch the crash with SIGTRAP.*/
weston_log("caught signal: %d\n", s);
print_backtrace();
segv_compositor->backend->restore(segv_compositor);
raise(SIGTRAP);
}
WL_EXPORT void *
weston_load_module(const char *name, const char *entrypoint)
{
@ -4964,562 +4717,6 @@ weston_load_module(const char *name, const char *entrypoint)
return init;
}
static int
load_modules(struct weston_compositor *ec, const char *modules,
int *argc, char *argv[])
{
const char *p, *end;
char buffer[256];
int (*module_init)(struct weston_compositor *ec,
int *argc, char *argv[]);
if (modules == NULL)
return 0;
p = modules;
while (*p) {
end = strchrnul(p, ',');
snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
module_init = weston_load_module(buffer, "module_init");
if (!module_init)
return -1;
if (module_init(ec, argc, argv) < 0)
return -1;
p = end;
while (*p == ',')
p++;
}
return 0;
}
static const char xdg_error_message[] =
"fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
static const char xdg_wrong_message[] =
"fatal: environment variable XDG_RUNTIME_DIR\n"
"is set to \"%s\", which is not a directory.\n";
static const char xdg_wrong_mode_message[] =
"warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
"correctly. Unix access mode must be 0700 (current mode is %o),\n"
"and must be owned by the user (current owner is UID %d).\n";
static const char xdg_detail_message[] =
"Refer to your distribution on how to get it, or\n"
"http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
"on how to implement it.\n";
static void
verify_xdg_runtime_dir(void)
{
char *dir = getenv("XDG_RUNTIME_DIR");
struct stat s;
if (!dir) {
weston_log(xdg_error_message);
weston_log_continue(xdg_detail_message);
exit(EXIT_FAILURE);
}
if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
weston_log(xdg_wrong_message, dir);
weston_log_continue(xdg_detail_message);
exit(EXIT_FAILURE);
}
if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
weston_log(xdg_wrong_mode_message,
dir, s.st_mode & 0777, s.st_uid);
weston_log_continue(xdg_detail_message);
}
}
static int
usage(int error_code)
{
fprintf(stderr,
"Usage: weston [OPTIONS]\n\n"
"This is weston version " VERSION ", the Wayland reference compositor.\n"
"Weston supports multiple backends, and depending on which backend is in use\n"
"different options will be accepted.\n\n"
"Core options:\n\n"
" --version\t\tPrint weston version\n"
" -B, --backend=MODULE\tBackend module, one of\n"
#if defined(BUILD_DRM_COMPOSITOR)
"\t\t\t\tdrm-backend.so\n"
#endif
#if defined(BUILD_FBDEV_COMPOSITOR)
"\t\t\t\tfbdev-backend.so\n"
#endif
#if defined(BUILD_X11_COMPOSITOR)
"\t\t\t\tx11-backend.so\n"
#endif
#if defined(BUILD_WAYLAND_COMPOSITOR)
"\t\t\t\twayland-backend.so\n"
#endif
#if defined(BUILD_RDP_COMPOSITOR)
"\t\t\t\trdp-backend.so\n"
#endif
#if defined(BUILD_HEADLESS_COMPOSITOR)
"\t\t\t\theadless-backend.so\n"
#endif
#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
"\t\t\t\trpi-backend.so\n"
#endif
" --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
" -S, --socket=NAME\tName of socket to listen on\n"
" -i, --idle-time=SECS\tIdle time in seconds\n"
" --modules\t\tLoad the comma-separated list of modules\n"
" --log=FILE\t\tLog to the given file\n"
" -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
" --no-config\t\tDo not read weston.ini\n"
" -h, --help\t\tThis help message\n\n");
#if defined(BUILD_DRM_COMPOSITOR)
fprintf(stderr,
"Options for drm-backend.so:\n\n"
" --connector=ID\tBring up only this connector\n"
" --seat=SEAT\t\tThe seat that weston should run on\n"
" --tty=TTY\t\tThe tty to use\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
#endif
#if defined(BUILD_FBDEV_COMPOSITOR)
fprintf(stderr,
"Options for fbdev-backend.so:\n\n"
" --tty=TTY\t\tThe tty to use\n"
" --device=DEVICE\tThe framebuffer device to use\n"
" --use-gl\t\tUse the GL renderer\n\n");
#endif
#if defined(BUILD_X11_COMPOSITOR)
fprintf(stderr,
"Options for x11-backend.so:\n\n"
" --width=WIDTH\t\tWidth of X window\n"
" --height=HEIGHT\tHeight of X window\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --no-input\t\tDont create input devices\n\n");
#endif
#if defined(BUILD_WAYLAND_COMPOSITOR)
fprintf(stderr,
"Options for wayland-backend.so:\n\n"
" --width=WIDTH\t\tWidth of Wayland surface\n"
" --height=HEIGHT\tHeight of Wayland surface\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --sprawl\t\tCreate one fullscreen output for every parent output\n"
" --display=DISPLAY\tWayland display to connect to\n\n");
#endif
#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
fprintf(stderr,
"Options for rpi-backend.so:\n\n"
" --tty=TTY\t\tThe tty to use\n"
" --single-buffer\tUse single-buffered Dispmanx elements.\n"
" --transform=TR\tThe output transformation, TR is one of:\n"
"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
" --opaque-regions\tEnable support for opaque regions, can be "
"very slow without support in the GPU firmware.\n"
"\n");
#endif
#if defined(BUILD_RDP_COMPOSITOR)
fprintf(stderr,
"Options for rdp-backend.so:\n\n"
" --width=WIDTH\t\tWidth of desktop\n"
" --height=HEIGHT\tHeight of desktop\n"
" --env-socket=SOCKET\tUse that socket as peer connection\n"
" --address=ADDR\tThe address to bind\n"
" --port=PORT\t\tThe port to listen on\n"
" --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
" --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
" --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
" --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
"\n");
#endif
#if defined(BUILD_HEADLESS_COMPOSITOR)
fprintf(stderr,
"Options for headless-backend.so:\n\n"
" --width=WIDTH\t\tWidth of memory surface\n"
" --height=HEIGHT\tHeight of memory surface\n"
" --transform=TR\tThe output transformation, TR is one of:\n"
"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
" --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n\n");
#endif
exit(error_code);
}
static void
catch_signals(void)
{
struct sigaction action;
action.sa_flags = SA_SIGINFO | SA_RESETHAND;
action.sa_sigaction = on_caught_signal;
sigemptyset(&action.sa_mask);
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGABRT, &action, NULL);
}
static void
handle_primary_client_destroyed(struct wl_listener *listener, void *data)
{
struct wl_client *client = data;
weston_log("Primary client died. Closing...\n");
wl_display_terminate(wl_client_get_display(client));
}
static char *
weston_choose_default_backend(void)
{
char *backend = NULL;
if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
backend = strdup("wayland-backend.so");
else if (getenv("DISPLAY"))
backend = strdup("x11-backend.so");
else
backend = strdup(WESTON_NATIVE_BACKEND);
return backend;
}
static int
weston_create_listening_socket(struct wl_display *display, const char *socket_name)
{
if (socket_name) {
if (wl_display_add_socket(display, socket_name)) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
} else {
socket_name = wl_display_add_socket_auto(display);
if (!socket_name) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
}
setenv("WAYLAND_DISPLAY", socket_name, 1);
return 0;
}
static const struct { const char *name; uint32_t token; } transforms[] = {
{ "normal", WL_OUTPUT_TRANSFORM_NORMAL },
{ "90", WL_OUTPUT_TRANSFORM_90 },
{ "180", WL_OUTPUT_TRANSFORM_180 },
{ "270", WL_OUTPUT_TRANSFORM_270 },
{ "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
{ "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
{ "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
{ "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
};
WL_EXPORT int
weston_parse_transform(const char *transform, uint32_t *out)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(transforms); i++)
if (strcmp(transforms[i].name, transform) == 0) {
*out = transforms[i].token;
return 0;
}
*out = WL_OUTPUT_TRANSFORM_NORMAL;
return -1;
}
WL_EXPORT const char *
weston_transform_to_string(uint32_t output_transform)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(transforms); i++)
if (transforms[i].token == output_transform)
return transforms[i].name;
return "<illegal value>";
}
static int
load_configuration(struct weston_config **config, int32_t noconfig,
const char *config_file)
{
const char *file = "weston.ini";
const char *full_path;
*config = NULL;
if (config_file)
file = config_file;
if (noconfig == 0)
*config = weston_config_parse(file);
if (*config) {
full_path = weston_config_get_full_path(*config);
weston_log("Using config file '%s'\n", full_path);
setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
return 0;
}
if (config_file && noconfig == 0) {
weston_log("fatal: error opening or reading config file"
" '%s'.\n", config_file);
return -1;
}
weston_log("Starting with no config file.\n");
setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
return 0;
}
static void
handle_exit(struct weston_compositor *c)
{
wl_display_terminate(c->wl_display);
}
int main(int argc, char *argv[])
{
int ret = EXIT_FAILURE;
struct wl_display *display;
struct weston_compositor *ec;
struct wl_event_source *signals[4];
struct wl_event_loop *loop;
int (*backend_init)(struct weston_compositor *c,
int *argc, char *argv[],
struct weston_config *config);
int i, fd;
char *backend = NULL;
char *shell = NULL;
char *modules = NULL;
char *option_modules = NULL;
char *log = NULL;
char *server_socket = NULL, *end;
int32_t idle_time = -1;
int32_t help = 0;
char *socket_name = NULL;
int32_t version = 0;
int32_t noconfig = 0;
int32_t numlock_on;
char *config_file = NULL;
struct weston_config *config = NULL;
struct weston_config_section *section;
struct wl_client *primary_client;
struct wl_listener primary_client_destroyed;
struct weston_seat *seat;
const struct weston_option core_options[] = {
{ WESTON_OPTION_STRING, "backend", 'B', &backend },
{ WESTON_OPTION_STRING, "shell", 0, &shell },
{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
{ WESTON_OPTION_STRING, "modules", 0, &option_modules },
{ WESTON_OPTION_STRING, "log", 0, &log },
{ WESTON_OPTION_BOOLEAN, "help", 'h', &help },
{ WESTON_OPTION_BOOLEAN, "version", 0, &version },
{ WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
{ WESTON_OPTION_STRING, "config", 'c', &config_file },
};
parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
if (help)
usage(EXIT_SUCCESS);
if (version) {
printf(PACKAGE_STRING "\n");
return EXIT_SUCCESS;
}
weston_log_file_open(log);
weston_log("%s\n"
STAMP_SPACE "%s\n"
STAMP_SPACE "Bug reports to: %s\n"
STAMP_SPACE "Build: %s\n",
PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
BUILD_ID);
log_uname();
verify_xdg_runtime_dir();
display = wl_display_create();
loop = wl_display_get_event_loop(display);
signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
display);
signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
display);
signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
display);
wl_list_init(&child_process_list);
signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
NULL);
if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
goto out_signals;
if (load_configuration(&config, noconfig, config_file) < 0)
goto out_signals;
section = weston_config_get_section(config, "core", NULL, NULL);
if (!backend) {
weston_config_section_get_string(section, "backend", &backend,
NULL);
if (!backend)
backend = weston_choose_default_backend();
}
backend_init = weston_load_module(backend, "backend_init");
if (!backend_init)
goto out_signals;
ec = weston_compositor_create(display, NULL);
if (ec == NULL) {
weston_log("fatal: failed to create compositor\n");
goto out_signals;
}
ec->config = config;
if (weston_compositor_init_config(ec, config) < 0) {
ret = EXIT_FAILURE;
goto out_signals;
}
if (backend_init(ec, &argc, argv, config) < 0) {
weston_log("fatal: failed to create compositor backend\n");
ret = EXIT_FAILURE;
goto out_signals;
}
catch_signals();
segv_compositor = ec;
if (idle_time < 0)
weston_config_section_get_int(section, "idle-time", &idle_time, -1);
if (idle_time < 0)
idle_time = 300; /* default idle timeout, in seconds */
ec->idle_time = idle_time;
ec->default_pointer_grab = NULL;
ec->exit_code = EXIT_SUCCESS;
ec->exit = handle_exit;
weston_compositor_log_capabilities(ec);
server_socket = getenv("WAYLAND_SERVER_SOCKET");
if (server_socket) {
weston_log("Running with single client\n");
fd = strtol(server_socket, &end, 0);
if (*end != '\0')
fd = -1;
} else {
fd = -1;
}
if (fd != -1) {
primary_client = wl_client_create(display, fd);
if (!primary_client) {
weston_log("fatal: failed to add client: %m\n");
goto out;
}
primary_client_destroyed.notify =
handle_primary_client_destroyed;
wl_client_add_destroy_listener(primary_client,
&primary_client_destroyed);
} else if (weston_create_listening_socket(display, socket_name)) {
goto out;
}
if (!shell)
weston_config_section_get_string(section, "shell", &shell,
"desktop-shell.so");
if (load_modules(ec, shell, &argc, argv) < 0)
goto out;
weston_config_section_get_string(section, "modules", &modules, "");
if (load_modules(ec, modules, &argc, argv) < 0)
goto out;
if (load_modules(ec, option_modules, &argc, argv) < 0)
goto out;
section = weston_config_get_section(config, "keyboard", NULL, NULL);
weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
if (numlock_on) {
wl_list_for_each(seat, &ec->seat_list, link) {
if (seat->keyboard)
weston_keyboard_set_locks(seat->keyboard,
WESTON_NUM_LOCK,
WESTON_NUM_LOCK);
}
}
for (i = 1; i < argc; i++)
weston_log("fatal: unhandled option: %s\n", argv[i]);
if (argc > 1)
goto out;
weston_compositor_wake(ec);
wl_display_run(display);
/* Allow for setting return exit code after
* wl_display_run returns normally. This is
* useful for devs/testers and automated tests
* that want to indicate failure status to
* testing infrastructure above
*/
ret = ec->exit_code;
out:
weston_compositor_destroy(ec);
out_signals:
for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
if (signals[i])
wl_event_source_remove(signals[i]);
wl_display_destroy(display);
if (config)
weston_config_destroy(config);
weston_log_file_close();
free(config_file);
free(backend);
free(shell);
free(socket_name);
free(option_modules);
free(log);
free(modules);
return ret;
}
/** Destroys the compositor.
*

@ -0,0 +1,848 @@
/*
* Copyright © 2010-2011 Intel Corporation
* Copyright © 2008-2011 Kristian Høgsberg
* Copyright © 2012-2015 Collabora, Ltd.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "config.h"
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <dlfcn.h>
#include <string.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifdef HAVE_LIBUNWIND
#define UNW_LOCAL_ONLY
#include <libunwind.h>
#endif
#include "compositor.h"
#include "../shared/os-compatibility.h"
#include "../shared/helpers.h"
#include "git-version.h"
#include "version.h"
static struct wl_list child_process_list;
static struct weston_compositor *segv_compositor;
static int
sigchld_handler(int signal_number, void *data)
{
struct weston_process *p;
int status;
pid_t pid;
while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
wl_list_for_each(p, &child_process_list, link) {
if (p->pid == pid)
break;
}
if (&p->link == &child_process_list) {
weston_log("unknown child process exited\n");
continue;
}
wl_list_remove(&p->link);
p->cleanup(p, status);
}
if (pid < 0 && errno != ECHILD)
weston_log("waitpid error %m\n");
return 1;
}
#ifdef HAVE_LIBUNWIND
static void
print_backtrace(void)
{
unw_cursor_t cursor;
unw_context_t context;
unw_word_t off;
unw_proc_info_t pip;
int ret, i = 0;
char procname[256];
const char *filename;
Dl_info dlinfo;
pip.unwind_info = NULL;
ret = unw_getcontext(&context);
if (ret) {
weston_log("unw_getcontext: %d\n", ret);
return;
}
ret = unw_init_local(&cursor, &context);
if (ret) {
weston_log("unw_init_local: %d\n", ret);
return;
}
ret = unw_step(&cursor);
while (ret > 0) {
ret = unw_get_proc_info(&cursor, &pip);
if (ret) {
weston_log("unw_get_proc_info: %d\n", ret);
break;
}
ret = unw_get_proc_name(&cursor, procname, 256, &off);
if (ret && ret != -UNW_ENOMEM) {
if (ret != -UNW_EUNSPEC)
weston_log("unw_get_proc_name: %d\n", ret);
procname[0] = '?';
procname[1] = 0;
}
if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
*dlinfo.dli_fname)
filename = dlinfo.dli_fname;
else
filename = "?";
weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
ret = unw_step(&cursor);
if (ret < 0)
weston_log("unw_step: %d\n", ret);
}
}
#else
static void
print_backtrace(void)
{
void *buffer[32];
int i, count;
Dl_info info;
count = backtrace(buffer, ARRAY_LENGTH(buffer));
for (i = 0; i < count; i++) {
dladdr(buffer[i], &info);
weston_log(" [%016lx] %s (%s)\n",
(long) buffer[i],
info.dli_sname ? info.dli_sname : "--",
info.dli_fname);
}
}
#endif
WL_EXPORT void
weston_watch_process(struct weston_process *process)
{
wl_list_insert(&child_process_list, &process->link);
}
static void
log_uname(void)
{
struct utsname usys;
uname(&usys);
weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
usys.version, usys.machine);
}
static const char xdg_error_message[] =
"fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
static const char xdg_wrong_message[] =
"fatal: environment variable XDG_RUNTIME_DIR\n"
"is set to \"%s\", which is not a directory.\n";
static const char xdg_wrong_mode_message[] =
"warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
"correctly. Unix access mode must be 0700 (current mode is %o),\n"
"and must be owned by the user (current owner is UID %d).\n";
static const char xdg_detail_message[] =
"Refer to your distribution on how to get it, or\n"
"http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
"on how to implement it.\n";
static void
verify_xdg_runtime_dir(void)
{
char *dir = getenv("XDG_RUNTIME_DIR");
struct stat s;
if (!dir) {
weston_log(xdg_error_message);
weston_log_continue(xdg_detail_message);
exit(EXIT_FAILURE);
}
if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
weston_log(xdg_wrong_message, dir);
weston_log_continue(xdg_detail_message);
exit(EXIT_FAILURE);
}
if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
weston_log(xdg_wrong_mode_message,
dir, s.st_mode & 0777, s.st_uid);
weston_log_continue(xdg_detail_message);
}
}
static int
usage(int error_code)
{
fprintf(stderr,
"Usage: weston [OPTIONS]\n\n"
"This is weston version " VERSION ", the Wayland reference compositor.\n"
"Weston supports multiple backends, and depending on which backend is in use\n"
"different options will be accepted.\n\n"
"Core options:\n\n"
" --version\t\tPrint weston version\n"
" -B, --backend=MODULE\tBackend module, one of\n"
#if defined(BUILD_DRM_COMPOSITOR)
"\t\t\t\tdrm-backend.so\n"
#endif
#if defined(BUILD_FBDEV_COMPOSITOR)
"\t\t\t\tfbdev-backend.so\n"
#endif
#if defined(BUILD_X11_COMPOSITOR)
"\t\t\t\tx11-backend.so\n"
#endif
#if defined(BUILD_WAYLAND_COMPOSITOR)
"\t\t\t\twayland-backend.so\n"
#endif
#if defined(BUILD_RDP_COMPOSITOR)
"\t\t\t\trdp-backend.so\n"
#endif
#if defined(BUILD_HEADLESS_COMPOSITOR)
"\t\t\t\theadless-backend.so\n"
#endif
#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
"\t\t\t\trpi-backend.so\n"
#endif
" --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
" -S, --socket=NAME\tName of socket to listen on\n"
" -i, --idle-time=SECS\tIdle time in seconds\n"
" --modules\t\tLoad the comma-separated list of modules\n"
" --log=FILE\t\tLog to the given file\n"
" -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
" --no-config\t\tDo not read weston.ini\n"
" -h, --help\t\tThis help message\n\n");
#if defined(BUILD_DRM_COMPOSITOR)
fprintf(stderr,
"Options for drm-backend.so:\n\n"
" --connector=ID\tBring up only this connector\n"
" --seat=SEAT\t\tThe seat that weston should run on\n"
" --tty=TTY\t\tThe tty to use\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
#endif
#if defined(BUILD_FBDEV_COMPOSITOR)
fprintf(stderr,
"Options for fbdev-backend.so:\n\n"
" --tty=TTY\t\tThe tty to use\n"
" --device=DEVICE\tThe framebuffer device to use\n"
" --use-gl\t\tUse the GL renderer\n\n");
#endif
#if defined(BUILD_X11_COMPOSITOR)
fprintf(stderr,
"Options for x11-backend.so:\n\n"
" --width=WIDTH\t\tWidth of X window\n"
" --height=HEIGHT\tHeight of X window\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --no-input\t\tDont create input devices\n\n");
#endif
#if defined(BUILD_WAYLAND_COMPOSITOR)
fprintf(stderr,
"Options for wayland-backend.so:\n\n"
" --width=WIDTH\t\tWidth of Wayland surface\n"
" --height=HEIGHT\tHeight of Wayland surface\n"
" --scale=SCALE\t\tScale factor of output\n"
" --fullscreen\t\tRun in fullscreen mode\n"
" --use-pixman\t\tUse the pixman (CPU) renderer\n"
" --output-count=COUNT\tCreate multiple outputs\n"
" --sprawl\t\tCreate one fullscreen output for every parent output\n"
" --display=DISPLAY\tWayland display to connect to\n\n");
#endif
#if defined(BUILD_RPI_COMPOSITOR) && defined(HAVE_BCM_HOST)
fprintf(stderr,
"Options for rpi-backend.so:\n\n"
" --tty=TTY\t\tThe tty to use\n"
" --single-buffer\tUse single-buffered Dispmanx elements.\n"
" --transform=TR\tThe output transformation, TR is one of:\n"
"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
" --opaque-regions\tEnable support for opaque regions, can be "
"very slow without support in the GPU firmware.\n"
"\n");
#endif
#if defined(BUILD_RDP_COMPOSITOR)
fprintf(stderr,
"Options for rdp-backend.so:\n\n"
" --width=WIDTH\t\tWidth of desktop\n"
" --height=HEIGHT\tHeight of desktop\n"
" --env-socket=SOCKET\tUse that socket as peer connection\n"
" --address=ADDR\tThe address to bind\n"
" --port=PORT\t\tThe port to listen on\n"
" --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
" --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
" --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
" --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
"\n");
#endif
#if defined(BUILD_HEADLESS_COMPOSITOR)
fprintf(stderr,
"Options for headless-backend.so:\n\n"
" --width=WIDTH\t\tWidth of memory surface\n"
" --height=HEIGHT\tHeight of memory surface\n"
" --transform=TR\tThe output transformation, TR is one of:\n"
"\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
" --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n\n");
#endif
exit(error_code);
}
static int on_term_signal(int signal_number, void *data)
{
struct wl_display *display = data;
weston_log("caught signal %d\n", signal_number);
wl_display_terminate(display);
return 1;
}
static void
on_caught_signal(int s, siginfo_t *siginfo, void *context)
{
/* This signal handler will do a best-effort backtrace, and
* then call the backend restore function, which will switch
* back to the vt we launched from or ungrab X etc and then
* raise SIGTRAP. If we run weston under gdb from X or a
* different vt, and tell gdb "handle *s* nostop", this
* will allow weston to switch back to gdb on crash and then
* gdb will catch the crash with SIGTRAP.*/
weston_log("caught signal: %d\n", s);
print_backtrace();
segv_compositor->backend->restore(segv_compositor);
raise(SIGTRAP);
}
static void
catch_signals(void)
{
struct sigaction action;
action.sa_flags = SA_SIGINFO | SA_RESETHAND;
action.sa_sigaction = on_caught_signal;
sigemptyset(&action.sa_mask);
sigaction(SIGSEGV, &action, NULL);
sigaction(SIGABRT, &action, NULL);
}
static const char *
clock_name(clockid_t clk_id)
{
static const char *names[] = {
[CLOCK_REALTIME] = "CLOCK_REALTIME",
[CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
[CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
[CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
[CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
[CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
};
if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
return "unknown";
return names[clk_id];
}
static const struct {
uint32_t bit; /* enum weston_capability */
const char *desc;
} capability_strings[] = {
{ WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
{ WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
};
static void
weston_compositor_log_capabilities(struct weston_compositor *compositor)
{
unsigned i;
int yes;
weston_log("Compositor capabilities:\n");
for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
yes = compositor->capabilities & capability_strings[i].bit;
weston_log_continue(STAMP_SPACE "%s %s\n",
capability_strings[i].desc,
yes ? "yes" : "no");
}
weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
clock_name(compositor->presentation_clock),
compositor->presentation_clock);
}
static void
handle_primary_client_destroyed(struct wl_listener *listener, void *data)
{
struct wl_client *client = data;
weston_log("Primary client died. Closing...\n");
wl_display_terminate(wl_client_get_display(client));
}
static int
weston_create_listening_socket(struct wl_display *display, const char *socket_name)
{
if (socket_name) {
if (wl_display_add_socket(display, socket_name)) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
} else {
socket_name = wl_display_add_socket_auto(display);
if (!socket_name) {
weston_log("fatal: failed to add socket: %m\n");
return -1;
}
}
setenv("WAYLAND_DISPLAY", socket_name, 1);
return 0;
}
static int
load_modules(struct weston_compositor *ec, const char *modules,
int *argc, char *argv[])
{
const char *p, *end;
char buffer[256];
int (*module_init)(struct weston_compositor *ec,
int *argc, char *argv[]);
if (modules == NULL)
return 0;
p = modules;
while (*p) {
end = strchrnul(p, ',');
snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
module_init = weston_load_module(buffer, "module_init");
if (!module_init)
return -1;
if (module_init(ec, argc, argv) < 0)
return -1;
p = end;
while (*p == ',')
p++;
}
return 0;
}
static int
weston_compositor_init_config(struct weston_compositor *ec,
struct weston_config *config)
{
struct xkb_rule_names xkb_names;
struct weston_config_section *s;
int repaint_msec;
s = weston_config_get_section(config, "keyboard", NULL, NULL);
weston_config_section_get_string(s, "keymap_rules",
(char **) &xkb_names.rules, NULL);
weston_config_section_get_string(s, "keymap_model",
(char **) &xkb_names.model, NULL);
weston_config_section_get_string(s, "keymap_layout",
(char **) &xkb_names.layout, NULL);
weston_config_section_get_string(s, "keymap_variant",
(char **) &xkb_names.variant, NULL);
weston_config_section_get_string(s, "keymap_options",
(char **) &xkb_names.options, NULL);
if (weston_compositor_xkb_init(ec, &xkb_names) < 0)
return -1;
weston_config_section_get_int(s, "repeat-rate",
&ec->kb_repeat_rate, 40);
weston_config_section_get_int(s, "repeat-delay",
&ec->kb_repeat_delay, 400);
s = weston_config_get_section(config, "core", NULL, NULL);
weston_config_section_get_int(s, "repaint-window", &repaint_msec,
ec->repaint_msec);
if (repaint_msec < -10 || repaint_msec > 1000) {
weston_log("Invalid repaint_window value in config: %d\n",
repaint_msec);
} else {
ec->repaint_msec = repaint_msec;
}
weston_log("Output repaint window is %d ms maximum.\n",
ec->repaint_msec);
return 0;
}
static char *
weston_choose_default_backend(void)
{
char *backend = NULL;
if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
backend = strdup("wayland-backend.so");
else if (getenv("DISPLAY"))
backend = strdup("x11-backend.so");
else
backend = strdup(WESTON_NATIVE_BACKEND);
return backend;
}
static const struct { const char *name; uint32_t token; } transforms[] = {
{ "normal", WL_OUTPUT_TRANSFORM_NORMAL },
{ "90", WL_OUTPUT_TRANSFORM_90 },
{ "180", WL_OUTPUT_TRANSFORM_180 },
{ "270", WL_OUTPUT_TRANSFORM_270 },
{ "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
{ "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
{ "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
{ "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
};
WL_EXPORT int
weston_parse_transform(const char *transform, uint32_t *out)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(transforms); i++)
if (strcmp(transforms[i].name, transform) == 0) {
*out = transforms[i].token;
return 0;
}
*out = WL_OUTPUT_TRANSFORM_NORMAL;
return -1;
}
WL_EXPORT const char *
weston_transform_to_string(uint32_t output_transform)
{
unsigned int i;
for (i = 0; i < ARRAY_LENGTH(transforms); i++)
if (transforms[i].token == output_transform)
return transforms[i].name;
return "<illegal value>";
}
static int
load_configuration(struct weston_config **config, int32_t noconfig,
const char *config_file)
{
const char *file = "weston.ini";
const char *full_path;
*config = NULL;
if (config_file)
file = config_file;
if (noconfig == 0)
*config = weston_config_parse(file);
if (*config) {
full_path = weston_config_get_full_path(*config);
weston_log("Using config file '%s'\n", full_path);
setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
return 0;
}
if (config_file && noconfig == 0) {
weston_log("fatal: error opening or reading config file"
" '%s'.\n", config_file);
return -1;
}
weston_log("Starting with no config file.\n");
setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
return 0;
}
static void
handle_exit(struct weston_compositor *c)
{
wl_display_terminate(c->wl_display);
}
int main(int argc, char *argv[])
{
int ret = EXIT_FAILURE;
struct wl_display *display;
struct weston_compositor *ec;
struct wl_event_source *signals[4];
struct wl_event_loop *loop;
int (*backend_init)(struct weston_compositor *c,
int *argc, char *argv[],
struct weston_config *config);
int i, fd;
char *backend = NULL;
char *shell = NULL;
char *modules = NULL;
char *option_modules = NULL;
char *log = NULL;
char *server_socket = NULL, *end;
int32_t idle_time = -1;
int32_t help = 0;
char *socket_name = NULL;
int32_t version = 0;
int32_t noconfig = 0;
int32_t numlock_on;
char *config_file = NULL;
struct weston_config *config = NULL;
struct weston_config_section *section;
struct wl_client *primary_client;
struct wl_listener primary_client_destroyed;
struct weston_seat *seat;
const struct weston_option core_options[] = {
{ WESTON_OPTION_STRING, "backend", 'B', &backend },
{ WESTON_OPTION_STRING, "shell", 0, &shell },
{ WESTON_OPTION_STRING, "socket", 'S', &socket_name },
{ WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
{ WESTON_OPTION_STRING, "modules", 0, &option_modules },
{ WESTON_OPTION_STRING, "log", 0, &log },
{ WESTON_OPTION_BOOLEAN, "help", 'h', &help },
{ WESTON_OPTION_BOOLEAN, "version", 0, &version },
{ WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
{ WESTON_OPTION_STRING, "config", 'c', &config_file },
};
parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
if (help)
usage(EXIT_SUCCESS);
if (version) {
printf(PACKAGE_STRING "\n");
return EXIT_SUCCESS;
}
weston_log_file_open(log);
weston_log("%s\n"
STAMP_SPACE "%s\n"
STAMP_SPACE "Bug reports to: %s\n"
STAMP_SPACE "Build: %s\n",
PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
BUILD_ID);
log_uname();
verify_xdg_runtime_dir();
display = wl_display_create();
loop = wl_display_get_event_loop(display);
signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
display);
signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
display);
signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
display);
wl_list_init(&child_process_list);
signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
NULL);
if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
goto out_signals;
if (load_configuration(&config, noconfig, config_file) < 0)
goto out_signals;
section = weston_config_get_section(config, "core", NULL, NULL);
if (!backend) {
weston_config_section_get_string(section, "backend", &backend,
NULL);
if (!backend)
backend = weston_choose_default_backend();
}
backend_init = weston_load_module(backend, "backend_init");
if (!backend_init)
goto out_signals;
ec = weston_compositor_create(display, NULL);
if (ec == NULL) {
weston_log("fatal: failed to create compositor\n");
goto out_signals;
}
ec->config = config;
if (weston_compositor_init_config(ec, config) < 0)
goto out_signals;
if (backend_init(ec, &argc, argv, config) < 0) {
weston_log("fatal: failed to create compositor backend\n");
goto out_signals;
}
catch_signals();
segv_compositor = ec;
if (idle_time < 0)
weston_config_section_get_int(section, "idle-time", &idle_time, -1);
if (idle_time < 0)
idle_time = 300; /* default idle timeout, in seconds */
ec->idle_time = idle_time;
ec->default_pointer_grab = NULL;
ec->exit = handle_exit;
weston_compositor_log_capabilities(ec);
server_socket = getenv("WAYLAND_SERVER_SOCKET");
if (server_socket) {
weston_log("Running with single client\n");
fd = strtol(server_socket, &end, 0);
if (*end != '\0')
fd = -1;
} else {
fd = -1;
}
if (fd != -1) {
primary_client = wl_client_create(display, fd);
if (!primary_client) {
weston_log("fatal: failed to add client: %m\n");
goto out;
}
primary_client_destroyed.notify =
handle_primary_client_destroyed;
wl_client_add_destroy_listener(primary_client,
&primary_client_destroyed);
} else if (weston_create_listening_socket(display, socket_name)) {
goto out;
}
if (!shell)
weston_config_section_get_string(section, "shell", &shell,
"desktop-shell.so");
if (load_modules(ec, shell, &argc, argv) < 0)
goto out;
weston_config_section_get_string(section, "modules", &modules, "");
if (load_modules(ec, modules, &argc, argv) < 0)
goto out;
if (load_modules(ec, option_modules, &argc, argv) < 0)
goto out;
section = weston_config_get_section(config, "keyboard", NULL, NULL);
weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
if (numlock_on) {
wl_list_for_each(seat, &ec->seat_list, link) {
if (seat->keyboard)
weston_keyboard_set_locks(seat->keyboard,
WESTON_NUM_LOCK,
WESTON_NUM_LOCK);
}
}
for (i = 1; i < argc; i++)
weston_log("fatal: unhandled option: %s\n", argv[i]);
if (argc > 1)
goto out;
weston_compositor_wake(ec);
wl_display_run(display);
/* Allow for setting return exit code after
* wl_display_run returns normally. This is
* useful for devs/testers and automated tests
* that want to indicate failure status to
* testing infrastructure above
*/
ret = ec->exit_code;
out:
weston_compositor_destroy(ec);
out_signals:
for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
if (signals[i])
wl_event_source_remove(signals[i]);
wl_display_destroy(display);
weston_log_file_close();
if (config)
weston_config_destroy(config);
free(config_file);
free(backend);
free(shell);
free(socket_name);
free(option_modules);
free(log);
free(modules);
return ret;
}
Loading…
Cancel
Save