On Mon, Jun 22, 2015 at 11:02:50PM +0300, Giulio Camuffo wrote: > 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. > --- > Makefile.am | 1 + > src/compositor.c | 801 +--------------------------------------------------- > src/weston.c | 843 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++
Just to avoid any ambiguity, perhaps name this new file main.c? Apart from that, this seems like a straightforward refactoring. I see no reason why it couldn't be landed now, independently of the rest of the libweston set. > 3 files changed, 845 insertions(+), 800 deletions(-) > create mode 100644 src/weston.c > > diff --git a/Makefile.am b/Makefile.am > index 6b2d6c7..fa90853 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -86,6 +86,7 @@ weston_SOURCES = \ > src/timeline.c \ > src/timeline.h \ > src/timeline-object.h \ > + src/weston.c \ > shared/helpers.h \ > shared/matrix.c \ > shared/matrix.h \ > diff --git a/src/compositor.c b/src/compositor.c > index 1924e6a..6e111f1 100644 > --- a/src/compositor.c > +++ b/src/compositor.c > @@ -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; Is this an unrelated change? If so maybe move to its own patch? > 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]; > -} It kind of seems like clock_name() ought to stay with weston_compositor_read_presentation_clock() just to keep all the clock stuff together. (I also wonder if this could be easier as just a macro?) > -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,558 +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_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\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" > - " --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; > -} > - > /** \brief Destroys the compositor. > * > * This function cleans up the compositor state and destroys it. > diff --git a/src/weston.c b/src/weston.c > new file mode 100644 > index 0000000..404e5f8 > --- /dev/null > +++ b/src/weston.c > @@ -0,0 +1,843 @@ > +/* > + * 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_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\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" > + " --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; > +} > -- > 2.4.4 > > _______________________________________________ > wayland-devel mailing list > wayland-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/wayland-devel _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel