blob: 6746e3a2af9b6a3ed0aae55eae1054e78c3beb68 [file] [log] [blame]
Giulio Camuffobab996e2014-10-12 00:24:25 +03001/*
2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012-2015 Collabora, Ltd.
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02005 * Copyright © 2010-2011 Benjamin Franzke
6 * Copyright © 2013 Jason Ekstrand
Giulio Camuffobab996e2014-10-12 00:24:25 +03007 *
8 * Permission is hereby granted, free of charge, to any person obtaining
9 * a copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sublicense, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial
18 * portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
24 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
26 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * SOFTWARE.
28 */
29
30#include "config.h"
31
32#include <unistd.h>
33#include <signal.h>
34#include <errno.h>
35#include <dlfcn.h>
Jussi Kukkonen649bbce2016-07-19 14:16:27 +030036#include <stdint.h>
Giulio Camuffobab996e2014-10-12 00:24:25 +030037#include <string.h>
38#include <sys/utsname.h>
39#include <sys/stat.h>
40#include <sys/wait.h>
Giulio Camuffofba27fb2016-06-02 21:48:10 +030041#include <sys/socket.h>
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +030042#include <libinput.h>
Giulio Camuffobe2b11a2016-06-02 21:48:13 +030043#include <sys/time.h>
Giulio Camuffo179fcda2016-06-02 21:48:14 +030044#include <linux/limits.h>
Giulio Camuffobab996e2014-10-12 00:24:25 +030045
46#ifdef HAVE_LIBUNWIND
47#define UNW_LOCAL_ONLY
48#include <libunwind.h>
49#endif
50
Giulio Camuffo179fcda2016-06-02 21:48:14 +030051#include "weston.h"
Giulio Camuffobab996e2014-10-12 00:24:25 +030052#include "compositor.h"
53#include "../shared/os-compatibility.h"
54#include "../shared/helpers.h"
55#include "git-version.h"
56#include "version.h"
Giulio Camuffofba27fb2016-06-02 21:48:10 +030057#include "weston.h"
Giulio Camuffobab996e2014-10-12 00:24:25 +030058
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -070059#include "compositor-drm.h"
Benoit Gschwind3c530942016-04-15 20:28:32 -070060#include "compositor-headless.h"
Benoit Gschwindbd573102016-04-22 17:05:26 +020061#include "compositor-rdp.h"
Benoit Gschwind934e89a2016-04-27 23:56:42 +020062#include "compositor-fbdev.h"
Benoit Gschwinde16acab2016-04-15 20:28:31 -070063#include "compositor-x11.h"
Benoit Gschwind3ff10da2016-05-10 22:47:49 +020064#include "compositor-wayland.h"
65
66#define WINDOW_TITLE "Weston Compositor"
Benoit Gschwind3c530942016-04-15 20:28:32 -070067
Armin Krezović78a36372016-08-01 18:51:46 +020068struct wet_compositor {
69 struct weston_config *config;
70};
71
Giulio Camuffobe2b11a2016-06-02 21:48:13 +030072static FILE *weston_logfile = NULL;
73
74static int cached_tm_mday = -1;
75
76static int weston_log_timestamp(void)
77{
78 struct timeval tv;
79 struct tm *brokendown_time;
80 char string[128];
81
82 gettimeofday(&tv, NULL);
83
84 brokendown_time = localtime(&tv.tv_sec);
85 if (brokendown_time == NULL)
86 return fprintf(weston_logfile, "[(NULL)localtime] ");
87
88 if (brokendown_time->tm_mday != cached_tm_mday) {
89 strftime(string, sizeof string, "%Y-%m-%d %Z", brokendown_time);
90 fprintf(weston_logfile, "Date: %s\n", string);
91
92 cached_tm_mday = brokendown_time->tm_mday;
93 }
94
95 strftime(string, sizeof string, "%H:%M:%S", brokendown_time);
96
97 return fprintf(weston_logfile, "[%s.%03li] ", string, tv.tv_usec/1000);
98}
99
100static void
101custom_handler(const char *fmt, va_list arg)
102{
103 weston_log_timestamp();
104 fprintf(weston_logfile, "libwayland: ");
105 vfprintf(weston_logfile, fmt, arg);
106}
107
108static void
109weston_log_file_open(const char *filename)
110{
111 wl_log_set_handler_server(custom_handler);
112
113 if (filename != NULL) {
114 weston_logfile = fopen(filename, "a");
115 if (weston_logfile)
116 os_fd_set_cloexec(fileno(weston_logfile));
117 }
118
119 if (weston_logfile == NULL)
120 weston_logfile = stderr;
121 else
122 setvbuf(weston_logfile, NULL, _IOLBF, 256);
123}
124
125static void
126weston_log_file_close(void)
127{
128 if ((weston_logfile != stderr) && (weston_logfile != NULL))
129 fclose(weston_logfile);
130 weston_logfile = stderr;
131}
132
133static int
134vlog(const char *fmt, va_list ap)
135{
136 int l;
137
138 l = weston_log_timestamp();
139 l += vfprintf(weston_logfile, fmt, ap);
140
141 return l;
142}
143
144static int
145vlog_continue(const char *fmt, va_list argp)
146{
147 return vfprintf(weston_logfile, fmt, argp);
148}
149
Giulio Camuffobab996e2014-10-12 00:24:25 +0300150static struct wl_list child_process_list;
151static struct weston_compositor *segv_compositor;
152
153static int
154sigchld_handler(int signal_number, void *data)
155{
156 struct weston_process *p;
157 int status;
158 pid_t pid;
159
160 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
161 wl_list_for_each(p, &child_process_list, link) {
162 if (p->pid == pid)
163 break;
164 }
165
166 if (&p->link == &child_process_list) {
167 weston_log("unknown child process exited\n");
168 continue;
169 }
170
171 wl_list_remove(&p->link);
172 p->cleanup(p, status);
173 }
174
175 if (pid < 0 && errno != ECHILD)
176 weston_log("waitpid error %m\n");
177
178 return 1;
179}
180
181#ifdef HAVE_LIBUNWIND
182
183static void
184print_backtrace(void)
185{
186 unw_cursor_t cursor;
187 unw_context_t context;
188 unw_word_t off;
189 unw_proc_info_t pip;
190 int ret, i = 0;
191 char procname[256];
192 const char *filename;
193 Dl_info dlinfo;
194
195 pip.unwind_info = NULL;
196 ret = unw_getcontext(&context);
197 if (ret) {
198 weston_log("unw_getcontext: %d\n", ret);
199 return;
200 }
201
202 ret = unw_init_local(&cursor, &context);
203 if (ret) {
204 weston_log("unw_init_local: %d\n", ret);
205 return;
206 }
207
208 ret = unw_step(&cursor);
209 while (ret > 0) {
210 ret = unw_get_proc_info(&cursor, &pip);
211 if (ret) {
212 weston_log("unw_get_proc_info: %d\n", ret);
213 break;
214 }
215
216 ret = unw_get_proc_name(&cursor, procname, 256, &off);
217 if (ret && ret != -UNW_ENOMEM) {
218 if (ret != -UNW_EUNSPEC)
219 weston_log("unw_get_proc_name: %d\n", ret);
220 procname[0] = '?';
221 procname[1] = 0;
222 }
223
224 if (dladdr((void *)(pip.start_ip + off), &dlinfo) && dlinfo.dli_fname &&
225 *dlinfo.dli_fname)
226 filename = dlinfo.dli_fname;
227 else
228 filename = "?";
229
230 weston_log("%u: %s (%s%s+0x%x) [%p]\n", i++, filename, procname,
231 ret == -UNW_ENOMEM ? "..." : "", (int)off, (void *)(pip.start_ip + off));
232
233 ret = unw_step(&cursor);
234 if (ret < 0)
235 weston_log("unw_step: %d\n", ret);
236 }
237}
238
239#else
240
241static void
242print_backtrace(void)
243{
244 void *buffer[32];
245 int i, count;
246 Dl_info info;
247
248 count = backtrace(buffer, ARRAY_LENGTH(buffer));
249 for (i = 0; i < count; i++) {
250 dladdr(buffer[i], &info);
251 weston_log(" [%016lx] %s (%s)\n",
252 (long) buffer[i],
253 info.dli_sname ? info.dli_sname : "--",
254 info.dli_fname);
255 }
256}
257
258#endif
259
Giulio Camuffofba27fb2016-06-02 21:48:10 +0300260static void
261child_client_exec(int sockfd, const char *path)
262{
263 int clientfd;
264 char s[32];
265 sigset_t allsigs;
266
267 /* do not give our signal mask to the new process */
268 sigfillset(&allsigs);
269 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
270
271 /* Launch clients as the user. Do not lauch clients with wrong euid.*/
272 if (seteuid(getuid()) == -1) {
273 weston_log("compositor: failed seteuid\n");
274 return;
275 }
276
277 /* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
278 * non-CLOEXEC fd to pass through exec. */
279 clientfd = dup(sockfd);
280 if (clientfd == -1) {
281 weston_log("compositor: dup failed: %m\n");
282 return;
283 }
284
285 snprintf(s, sizeof s, "%d", clientfd);
286 setenv("WAYLAND_SOCKET", s, 1);
287
288 if (execl(path, path, NULL) < 0)
289 weston_log("compositor: executing '%s' failed: %m\n",
290 path);
291}
292
293WL_EXPORT struct wl_client *
294weston_client_launch(struct weston_compositor *compositor,
295 struct weston_process *proc,
296 const char *path,
297 weston_process_cleanup_func_t cleanup)
298{
299 int sv[2];
300 pid_t pid;
301 struct wl_client *client;
302
303 weston_log("launching '%s'\n", path);
304
305 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
306 weston_log("weston_client_launch: "
307 "socketpair failed while launching '%s': %m\n",
308 path);
309 return NULL;
310 }
311
312 pid = fork();
313 if (pid == -1) {
314 close(sv[0]);
315 close(sv[1]);
316 weston_log("weston_client_launch: "
317 "fork failed while launching '%s': %m\n", path);
318 return NULL;
319 }
320
321 if (pid == 0) {
322 child_client_exec(sv[1], path);
323 _exit(-1);
324 }
325
326 close(sv[1]);
327
328 client = wl_client_create(compositor->wl_display, sv[0]);
329 if (!client) {
330 close(sv[0]);
331 weston_log("weston_client_launch: "
332 "wl_client_create failed while launching '%s'.\n",
333 path);
334 return NULL;
335 }
336
337 proc->pid = pid;
338 proc->cleanup = cleanup;
339 weston_watch_process(proc);
340
341 return client;
342}
343
Giulio Camuffobab996e2014-10-12 00:24:25 +0300344WL_EXPORT void
345weston_watch_process(struct weston_process *process)
346{
347 wl_list_insert(&child_process_list, &process->link);
348}
349
Giulio Camuffofba27fb2016-06-02 21:48:10 +0300350struct process_info {
351 struct weston_process proc;
352 char *path;
353};
354
355static void
356process_handle_sigchld(struct weston_process *process, int status)
357{
358 struct process_info *pinfo =
359 container_of(process, struct process_info, proc);
360
361 /*
362 * There are no guarantees whether this runs before or after
363 * the wl_client destructor.
364 */
365
366 if (WIFEXITED(status)) {
367 weston_log("%s exited with status %d\n", pinfo->path,
368 WEXITSTATUS(status));
369 } else if (WIFSIGNALED(status)) {
370 weston_log("%s died on signal %d\n", pinfo->path,
371 WTERMSIG(status));
372 } else {
373 weston_log("%s disappeared\n", pinfo->path);
374 }
375
376 free(pinfo->path);
377 free(pinfo);
378}
379
380WL_EXPORT struct wl_client *
381weston_client_start(struct weston_compositor *compositor, const char *path)
382{
383 struct process_info *pinfo;
384 struct wl_client *client;
385
386 pinfo = zalloc(sizeof *pinfo);
387 if (!pinfo)
388 return NULL;
389
390 pinfo->path = strdup(path);
391 if (!pinfo->path)
392 goto out_free;
393
394 client = weston_client_launch(compositor, &pinfo->proc, path,
395 process_handle_sigchld);
396 if (!client)
397 goto out_str;
398
399 return client;
400
401out_str:
402 free(pinfo->path);
403
404out_free:
405 free(pinfo);
406
407 return NULL;
408}
409
Giulio Camuffobab996e2014-10-12 00:24:25 +0300410static void
411log_uname(void)
412{
413 struct utsname usys;
414
415 uname(&usys);
416
417 weston_log("OS: %s, %s, %s, %s\n", usys.sysname, usys.release,
418 usys.version, usys.machine);
419}
420
Armin Krezović78a36372016-08-01 18:51:46 +0200421static struct wet_compositor *
422to_wet_compositor(struct weston_compositor *compositor)
Giulio Camuffod52f3b72016-06-02 21:48:11 +0300423{
424 return weston_compositor_get_user_data(compositor);
425}
426
Armin Krezović78a36372016-08-01 18:51:46 +0200427WL_EXPORT struct weston_config *
428wet_get_config(struct weston_compositor *ec)
429{
430 struct wet_compositor *compositor = to_wet_compositor(ec);
431
432 return compositor->config;
433}
434
Giulio Camuffobab996e2014-10-12 00:24:25 +0300435static const char xdg_error_message[] =
436 "fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
437
438static const char xdg_wrong_message[] =
439 "fatal: environment variable XDG_RUNTIME_DIR\n"
440 "is set to \"%s\", which is not a directory.\n";
441
442static const char xdg_wrong_mode_message[] =
443 "warning: XDG_RUNTIME_DIR \"%s\" is not configured\n"
444 "correctly. Unix access mode must be 0700 (current mode is %o),\n"
445 "and must be owned by the user (current owner is UID %d).\n";
446
447static const char xdg_detail_message[] =
448 "Refer to your distribution on how to get it, or\n"
449 "http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
450 "on how to implement it.\n";
451
452static void
453verify_xdg_runtime_dir(void)
454{
455 char *dir = getenv("XDG_RUNTIME_DIR");
456 struct stat s;
457
458 if (!dir) {
459 weston_log(xdg_error_message);
460 weston_log_continue(xdg_detail_message);
461 exit(EXIT_FAILURE);
462 }
463
464 if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
465 weston_log(xdg_wrong_message, dir);
466 weston_log_continue(xdg_detail_message);
467 exit(EXIT_FAILURE);
468 }
469
470 if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
471 weston_log(xdg_wrong_mode_message,
472 dir, s.st_mode & 0777, s.st_uid);
473 weston_log_continue(xdg_detail_message);
474 }
475}
476
477static int
478usage(int error_code)
479{
480 fprintf(stderr,
481 "Usage: weston [OPTIONS]\n\n"
482 "This is weston version " VERSION ", the Wayland reference compositor.\n"
483 "Weston supports multiple backends, and depending on which backend is in use\n"
484 "different options will be accepted.\n\n"
485
486
487 "Core options:\n\n"
488 " --version\t\tPrint weston version\n"
489 " -B, --backend=MODULE\tBackend module, one of\n"
490#if defined(BUILD_DRM_COMPOSITOR)
491 "\t\t\t\tdrm-backend.so\n"
492#endif
493#if defined(BUILD_FBDEV_COMPOSITOR)
494 "\t\t\t\tfbdev-backend.so\n"
495#endif
Dawid Gajownik71f57042015-07-31 17:39:00 -0300496#if defined(BUILD_HEADLESS_COMPOSITOR)
497 "\t\t\t\theadless-backend.so\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300498#endif
499#if defined(BUILD_RDP_COMPOSITOR)
500 "\t\t\t\trdp-backend.so\n"
501#endif
Dawid Gajownik71f57042015-07-31 17:39:00 -0300502#if defined(BUILD_WAYLAND_COMPOSITOR)
503 "\t\t\t\twayland-backend.so\n"
504#endif
505#if defined(BUILD_X11_COMPOSITOR)
506 "\t\t\t\tx11-backend.so\n"
507#endif
Giulio Camuffobab996e2014-10-12 00:24:25 +0300508 " --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
509 " -S, --socket=NAME\tName of socket to listen on\n"
510 " -i, --idle-time=SECS\tIdle time in seconds\n"
511 " --modules\t\tLoad the comma-separated list of modules\n"
512 " --log=FILE\t\tLog to the given file\n"
513 " -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
514 " --no-config\t\tDo not read weston.ini\n"
515 " -h, --help\t\tThis help message\n\n");
516
517#if defined(BUILD_DRM_COMPOSITOR)
518 fprintf(stderr,
519 "Options for drm-backend.so:\n\n"
520 " --connector=ID\tBring up only this connector\n"
521 " --seat=SEAT\t\tThe seat that weston should run on\n"
522 " --tty=TTY\t\tThe tty to use\n"
523 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
524 " --current-mode\tPrefer current KMS mode over EDID preferred mode\n\n");
525#endif
526
527#if defined(BUILD_FBDEV_COMPOSITOR)
528 fprintf(stderr,
529 "Options for fbdev-backend.so:\n\n"
530 " --tty=TTY\t\tThe tty to use\n"
531 " --device=DEVICE\tThe framebuffer device to use\n"
Pekka Paalanene77f8ad2016-06-08 17:39:37 +0300532 "\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300533#endif
534
Dawid Gajownik71f57042015-07-31 17:39:00 -0300535#if defined(BUILD_HEADLESS_COMPOSITOR)
Giulio Camuffobab996e2014-10-12 00:24:25 +0300536 fprintf(stderr,
Dawid Gajownik71f57042015-07-31 17:39:00 -0300537 "Options for headless-backend.so:\n\n"
538 " --width=WIDTH\t\tWidth of memory surface\n"
539 " --height=HEIGHT\tHeight of memory surface\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300540 " --transform=TR\tThe output transformation, TR is one of:\n"
541 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
Armin Krezovićd84deeb2016-06-23 11:59:29 +0200542 " --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n"
543 " --no-outputs\t\tDo not create any virtual outputs\n"
544 "\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300545#endif
546
547#if defined(BUILD_RDP_COMPOSITOR)
548 fprintf(stderr,
549 "Options for rdp-backend.so:\n\n"
550 " --width=WIDTH\t\tWidth of desktop\n"
551 " --height=HEIGHT\tHeight of desktop\n"
Dawid Gajownikd99a0502015-07-31 14:49:57 -0300552 " --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
Giulio Camuffobab996e2014-10-12 00:24:25 +0300553 " --address=ADDR\tThe address to bind\n"
554 " --port=PORT\t\tThe port to listen on\n"
555 " --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
556 " --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
557 " --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
558 " --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
559 "\n");
560#endif
561
Dawid Gajownik71f57042015-07-31 17:39:00 -0300562#if defined(BUILD_WAYLAND_COMPOSITOR)
563 fprintf(stderr,
564 "Options for wayland-backend.so:\n\n"
565 " --width=WIDTH\t\tWidth of Wayland surface\n"
566 " --height=HEIGHT\tHeight of Wayland surface\n"
567 " --scale=SCALE\t\tScale factor of output\n"
568 " --fullscreen\t\tRun in fullscreen mode\n"
569 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
570 " --output-count=COUNT\tCreate multiple outputs\n"
571 " --sprawl\t\tCreate one fullscreen output for every parent output\n"
572 " --display=DISPLAY\tWayland display to connect to\n\n");
573#endif
574
575#if defined(BUILD_X11_COMPOSITOR)
576 fprintf(stderr,
577 "Options for x11-backend.so:\n\n"
578 " --width=WIDTH\t\tWidth of X window\n"
579 " --height=HEIGHT\tHeight of X window\n"
580 " --scale=SCALE\t\tScale factor of output\n"
581 " --fullscreen\t\tRun in fullscreen mode\n"
582 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
583 " --output-count=COUNT\tCreate multiple outputs\n"
584 " --no-input\t\tDont create input devices\n\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300585#endif
586
587 exit(error_code);
588}
589
590static int on_term_signal(int signal_number, void *data)
591{
592 struct wl_display *display = data;
593
594 weston_log("caught signal %d\n", signal_number);
595 wl_display_terminate(display);
596
597 return 1;
598}
599
600static void
601on_caught_signal(int s, siginfo_t *siginfo, void *context)
602{
603 /* This signal handler will do a best-effort backtrace, and
604 * then call the backend restore function, which will switch
605 * back to the vt we launched from or ungrab X etc and then
606 * raise SIGTRAP. If we run weston under gdb from X or a
607 * different vt, and tell gdb "handle *s* nostop", this
608 * will allow weston to switch back to gdb on crash and then
609 * gdb will catch the crash with SIGTRAP.*/
610
611 weston_log("caught signal: %d\n", s);
612
613 print_backtrace();
614
615 segv_compositor->backend->restore(segv_compositor);
616
617 raise(SIGTRAP);
618}
619
620static void
621catch_signals(void)
622{
623 struct sigaction action;
624
625 action.sa_flags = SA_SIGINFO | SA_RESETHAND;
626 action.sa_sigaction = on_caught_signal;
627 sigemptyset(&action.sa_mask);
628 sigaction(SIGSEGV, &action, NULL);
629 sigaction(SIGABRT, &action, NULL);
630}
631
632static const char *
633clock_name(clockid_t clk_id)
634{
635 static const char *names[] = {
636 [CLOCK_REALTIME] = "CLOCK_REALTIME",
637 [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
638 [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
639 [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
640 [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
Derek Foreman32838c92015-06-29 13:20:34 -0500641#ifdef CLOCK_BOOTTIME
Giulio Camuffobab996e2014-10-12 00:24:25 +0300642 [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
Derek Foreman32838c92015-06-29 13:20:34 -0500643#endif
Giulio Camuffobab996e2014-10-12 00:24:25 +0300644 };
645
646 if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
647 return "unknown";
648
649 return names[clk_id];
650}
651
652static const struct {
653 uint32_t bit; /* enum weston_capability */
654 const char *desc;
655} capability_strings[] = {
656 { WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
657 { WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
658};
659
660static void
661weston_compositor_log_capabilities(struct weston_compositor *compositor)
662{
663 unsigned i;
664 int yes;
Pekka Paalanenbe112d42016-04-18 15:53:38 +0300665 struct timespec res;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300666
667 weston_log("Compositor capabilities:\n");
668 for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
669 yes = compositor->capabilities & capability_strings[i].bit;
670 weston_log_continue(STAMP_SPACE "%s %s\n",
671 capability_strings[i].desc,
672 yes ? "yes" : "no");
673 }
674
675 weston_log_continue(STAMP_SPACE "presentation clock: %s, id %d\n",
676 clock_name(compositor->presentation_clock),
677 compositor->presentation_clock);
Pekka Paalanenbe112d42016-04-18 15:53:38 +0300678
679 if (clock_getres(compositor->presentation_clock, &res) == 0)
680 weston_log_continue(STAMP_SPACE
681 "presentation clock resolution: %d.%09ld s\n",
682 (int)res.tv_sec, res.tv_nsec);
683 else
684 weston_log_continue(STAMP_SPACE
685 "presentation clock resolution: N/A\n");
Giulio Camuffobab996e2014-10-12 00:24:25 +0300686}
687
688static void
689handle_primary_client_destroyed(struct wl_listener *listener, void *data)
690{
691 struct wl_client *client = data;
692
693 weston_log("Primary client died. Closing...\n");
694
695 wl_display_terminate(wl_client_get_display(client));
696}
697
698static int
699weston_create_listening_socket(struct wl_display *display, const char *socket_name)
700{
701 if (socket_name) {
702 if (wl_display_add_socket(display, socket_name)) {
703 weston_log("fatal: failed to add socket: %m\n");
704 return -1;
705 }
706 } else {
707 socket_name = wl_display_add_socket_auto(display);
708 if (!socket_name) {
709 weston_log("fatal: failed to add socket: %m\n");
710 return -1;
711 }
712 }
713
714 setenv("WAYLAND_DISPLAY", socket_name, 1);
715
716 return 0;
717}
718
Giulio Camuffo179fcda2016-06-02 21:48:14 +0300719WL_EXPORT void *
720wet_load_module(const char *name, const char *entrypoint)
721{
722 const char *builddir = getenv("WESTON_BUILD_DIR");
723 char path[PATH_MAX];
724 void *module, *init;
725
726 if (name == NULL)
727 return NULL;
728
729 if (name[0] != '/') {
730 if (builddir)
731 snprintf(path, sizeof path, "%s/.libs/%s", builddir, name);
732 else
733 snprintf(path, sizeof path, "%s/%s", MODULEDIR, name);
734 } else {
735 snprintf(path, sizeof path, "%s", name);
736 }
737
738 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
739 if (module) {
740 weston_log("Module '%s' already loaded\n", path);
741 dlclose(module);
742 return NULL;
743 }
744
745 weston_log("Loading module '%s'\n", path);
746 module = dlopen(path, RTLD_NOW);
747 if (!module) {
748 weston_log("Failed to load module: %s\n", dlerror());
749 return NULL;
750 }
751
752 init = dlsym(module, entrypoint);
753 if (!init) {
754 weston_log("Failed to lookup init function: %s\n", dlerror());
755 dlclose(module);
756 return NULL;
757 }
758
759 return init;
760}
761
Giulio Camuffobab996e2014-10-12 00:24:25 +0300762static int
763load_modules(struct weston_compositor *ec, const char *modules,
764 int *argc, char *argv[])
765{
766 const char *p, *end;
767 char buffer[256];
768 int (*module_init)(struct weston_compositor *ec,
769 int *argc, char *argv[]);
770
771 if (modules == NULL)
772 return 0;
773
774 p = modules;
775 while (*p) {
776 end = strchrnul(p, ',');
777 snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
Giulio Camuffo9c764df2016-06-29 11:54:27 +0200778
779 if (strstr(buffer, "xwayland.so")) {
780 if (wet_load_xwayland(ec) < 0)
781 return -1;
782 } else {
783 module_init = wet_load_module(buffer, "module_init");
784 if (!module_init)
785 return -1;
786 if (module_init(ec, argc, argv) < 0)
787 return -1;
788 }
Giulio Camuffobab996e2014-10-12 00:24:25 +0300789 p = end;
790 while (*p == ',')
791 p++;
792
793 }
794
795 return 0;
796}
797
798static int
799weston_compositor_init_config(struct weston_compositor *ec,
800 struct weston_config *config)
801{
802 struct xkb_rule_names xkb_names;
803 struct weston_config_section *s;
804 int repaint_msec;
Bob Ham91880f12016-01-12 10:21:47 +0000805 int vt_switching;
Giulio Camuffobab996e2014-10-12 00:24:25 +0300806
807 s = weston_config_get_section(config, "keyboard", NULL, NULL);
808 weston_config_section_get_string(s, "keymap_rules",
809 (char **) &xkb_names.rules, NULL);
810 weston_config_section_get_string(s, "keymap_model",
811 (char **) &xkb_names.model, NULL);
812 weston_config_section_get_string(s, "keymap_layout",
813 (char **) &xkb_names.layout, NULL);
814 weston_config_section_get_string(s, "keymap_variant",
815 (char **) &xkb_names.variant, NULL);
816 weston_config_section_get_string(s, "keymap_options",
817 (char **) &xkb_names.options, NULL);
818
Giulio Camuffo0358af42016-06-02 21:48:08 +0300819 if (weston_compositor_set_xkb_rule_names(ec, &xkb_names) < 0)
Giulio Camuffobab996e2014-10-12 00:24:25 +0300820 return -1;
821
822 weston_config_section_get_int(s, "repeat-rate",
823 &ec->kb_repeat_rate, 40);
824 weston_config_section_get_int(s, "repeat-delay",
825 &ec->kb_repeat_delay, 400);
826
Bob Ham91880f12016-01-12 10:21:47 +0000827 weston_config_section_get_bool(s, "vt-switching",
828 &vt_switching, true);
829 ec->vt_switching = vt_switching;
830
Giulio Camuffobab996e2014-10-12 00:24:25 +0300831 s = weston_config_get_section(config, "core", NULL, NULL);
832 weston_config_section_get_int(s, "repaint-window", &repaint_msec,
833 ec->repaint_msec);
834 if (repaint_msec < -10 || repaint_msec > 1000) {
835 weston_log("Invalid repaint_window value in config: %d\n",
836 repaint_msec);
837 } else {
838 ec->repaint_msec = repaint_msec;
839 }
840 weston_log("Output repaint window is %d ms maximum.\n",
841 ec->repaint_msec);
842
843 return 0;
844}
845
846static char *
847weston_choose_default_backend(void)
848{
849 char *backend = NULL;
850
851 if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
852 backend = strdup("wayland-backend.so");
853 else if (getenv("DISPLAY"))
854 backend = strdup("x11-backend.so");
855 else
856 backend = strdup(WESTON_NATIVE_BACKEND);
857
858 return backend;
859}
860
861static const struct { const char *name; uint32_t token; } transforms[] = {
862 { "normal", WL_OUTPUT_TRANSFORM_NORMAL },
863 { "90", WL_OUTPUT_TRANSFORM_90 },
864 { "180", WL_OUTPUT_TRANSFORM_180 },
865 { "270", WL_OUTPUT_TRANSFORM_270 },
866 { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
867 { "flipped-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
868 { "flipped-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
869 { "flipped-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
870};
871
872WL_EXPORT int
873weston_parse_transform(const char *transform, uint32_t *out)
874{
875 unsigned int i;
876
877 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
878 if (strcmp(transforms[i].name, transform) == 0) {
879 *out = transforms[i].token;
880 return 0;
881 }
882
883 *out = WL_OUTPUT_TRANSFORM_NORMAL;
884 return -1;
885}
886
887WL_EXPORT const char *
888weston_transform_to_string(uint32_t output_transform)
889{
890 unsigned int i;
891
892 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
893 if (transforms[i].token == output_transform)
894 return transforms[i].name;
895
896 return "<illegal value>";
897}
898
899static int
900load_configuration(struct weston_config **config, int32_t noconfig,
901 const char *config_file)
902{
903 const char *file = "weston.ini";
904 const char *full_path;
905
906 *config = NULL;
907
908 if (config_file)
909 file = config_file;
910
911 if (noconfig == 0)
912 *config = weston_config_parse(file);
913
914 if (*config) {
915 full_path = weston_config_get_full_path(*config);
916
917 weston_log("Using config file '%s'\n", full_path);
918 setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
919
920 return 0;
921 }
922
923 if (config_file && noconfig == 0) {
924 weston_log("fatal: error opening or reading config file"
925 " '%s'.\n", config_file);
926
927 return -1;
928 }
929
930 weston_log("Starting with no config file.\n");
931 setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
932
933 return 0;
934}
935
936static void
937handle_exit(struct weston_compositor *c)
938{
939 wl_display_terminate(c->wl_display);
940}
941
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -0700942static enum weston_drm_backend_output_mode
943drm_configure_output(struct weston_compositor *c,
944 bool use_current_mode,
945 const char *name,
946 struct weston_drm_backend_output_config *config)
947{
Giulio Camuffod52f3b72016-06-02 21:48:11 +0300948 struct weston_config *wc = wet_get_config(c);
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -0700949 struct weston_config_section *section;
950 char *s;
951 int scale;
952 enum weston_drm_backend_output_mode mode =
953 WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
954
955 section = weston_config_get_section(wc, "output", "name", name);
956 weston_config_section_get_string(section, "mode", &s, "preferred");
957 if (strcmp(s, "off") == 0) {
958 free(s);
959 return WESTON_DRM_BACKEND_OUTPUT_OFF;
960 }
961
962 if (use_current_mode || strcmp(s, "current") == 0) {
963 mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
964 } else if (strcmp(s, "preferred") != 0) {
965 config->modeline = s;
966 s = NULL;
967 }
968 free(s);
969
970 weston_config_section_get_int(section, "scale", &scale, 1);
971 config->base.scale = scale >= 1 ? scale : 1;
972 weston_config_section_get_string(section, "transform", &s, "normal");
973 if (weston_parse_transform(s, &config->base.transform) < 0)
974 weston_log("Invalid transform \"%s\" for output %s\n",
975 s, name);
976 free(s);
977
978 weston_config_section_get_string(section,
979 "gbm-format", &config->gbm_format, NULL);
980 weston_config_section_get_string(section, "seat", &config->seat, "");
981 return mode;
982}
983
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +0300984static void
985configure_input_device(struct weston_compositor *compositor,
986 struct libinput_device *device)
987{
988 struct weston_config_section *s;
989 struct weston_config *config = wet_get_config(compositor);
990 int enable_tap;
991 int enable_tap_default;
992
993 s = weston_config_get_section(config,
994 "libinput", NULL, NULL);
995
996 if (libinput_device_config_tap_get_finger_count(device) > 0) {
997 enable_tap_default =
998 libinput_device_config_tap_get_default_enabled(
999 device);
1000 weston_config_section_get_bool(s, "enable_tap",
1001 &enable_tap,
1002 enable_tap_default);
1003 libinput_device_config_tap_set_enabled(device,
1004 enable_tap);
1005 }
1006}
1007
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -07001008static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001009load_drm_backend(struct weston_compositor *c,
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -07001010 int *argc, char **argv, struct weston_config *wc)
1011{
1012 struct weston_drm_backend_config config = {{ 0, }};
1013 struct weston_config_section *section;
1014 int ret = 0;
1015
1016 const struct weston_option options[] = {
1017 { WESTON_OPTION_INTEGER, "connector", 0, &config.connector },
1018 { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
1019 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
1020 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &config.use_current_mode },
1021 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1022 };
1023
1024 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1025
1026 section = weston_config_get_section(wc, "core", NULL, NULL);
1027 weston_config_section_get_string(section,
1028 "gbm-format", &config.gbm_format,
1029 NULL);
1030
1031 config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
1032 config.base.struct_size = sizeof(struct weston_drm_backend_config);
1033 config.configure_output = drm_configure_output;
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +03001034 config.configure_device = configure_input_device;
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -07001035
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001036 ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
1037 &config.base);
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -07001038
1039 free(config.gbm_format);
1040 free(config.seat_id);
1041
1042 return ret;
1043}
1044
Giulio Camuffo43008c72015-10-17 19:24:15 +03001045static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001046load_headless_backend(struct weston_compositor *c,
Benoit Gschwind3c530942016-04-15 20:28:32 -07001047 int *argc, char **argv, struct weston_config *wc)
1048{
1049 struct weston_headless_backend_config config = {{ 0, }};
1050 int ret = 0;
Benoit Gschwind2da6d0c2016-04-29 15:21:54 +02001051 char *transform = NULL;
Benoit Gschwind3c530942016-04-15 20:28:32 -07001052
1053 config.width = 1024;
1054 config.height = 640;
1055
1056 const struct weston_option options[] = {
1057 { WESTON_OPTION_INTEGER, "width", 0, &config.width },
1058 { WESTON_OPTION_INTEGER, "height", 0, &config.height },
1059 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1060 { WESTON_OPTION_STRING, "transform", 0, &transform },
Armin Krezovićd84deeb2016-06-23 11:59:29 +02001061 { WESTON_OPTION_BOOLEAN, "no-outputs", 0, &config.no_outputs },
Benoit Gschwind3c530942016-04-15 20:28:32 -07001062 };
1063
1064 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1065
Benoit Gschwind2da6d0c2016-04-29 15:21:54 +02001066 config.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1067 if (transform) {
1068 if (weston_parse_transform(transform, &config.transform) < 0)
1069 weston_log("Invalid transform \"%s\"\n", transform);
1070 free(transform);
1071 }
Benoit Gschwind3c530942016-04-15 20:28:32 -07001072
1073 config.base.struct_version = WESTON_HEADLESS_BACKEND_CONFIG_VERSION;
1074 config.base.struct_size = sizeof(struct weston_headless_backend_config);
1075
1076 /* load the actual wayland backend and configure it */
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001077 ret = weston_compositor_load_backend(c, WESTON_BACKEND_HEADLESS,
1078 &config.base);
Benoit Gschwind3c530942016-04-15 20:28:32 -07001079
1080 return ret;
1081}
1082
Benoit Gschwindbd573102016-04-22 17:05:26 +02001083static void
1084weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
1085{
1086 config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
1087 config->base.struct_size = sizeof(struct weston_rdp_backend_config);
1088
1089 config->width = 640;
1090 config->height = 480;
1091 config->bind_address = NULL;
1092 config->port = 3389;
1093 config->rdp_key = NULL;
1094 config->server_cert = NULL;
1095 config->server_key = NULL;
1096 config->env_socket = 0;
1097 config->no_clients_resize = 0;
1098}
1099
1100static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001101load_rdp_backend(struct weston_compositor *c,
Benoit Gschwindbd573102016-04-22 17:05:26 +02001102 int *argc, char *argv[], struct weston_config *wc)
1103{
1104 struct weston_rdp_backend_config config = {{ 0, }};
1105 int ret = 0;
1106
1107 weston_rdp_backend_config_init(&config);
1108
1109 const struct weston_option rdp_options[] = {
1110 { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
1111 { WESTON_OPTION_INTEGER, "width", 0, &config.width },
1112 { WESTON_OPTION_INTEGER, "height", 0, &config.height },
1113 { WESTON_OPTION_STRING, "address", 0, &config.bind_address },
1114 { WESTON_OPTION_INTEGER, "port", 0, &config.port },
1115 { WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
1116 { WESTON_OPTION_STRING, "rdp4-key", 0, &config.rdp_key },
1117 { WESTON_OPTION_STRING, "rdp-tls-cert", 0, &config.server_cert },
1118 { WESTON_OPTION_STRING, "rdp-tls-key", 0, &config.server_key }
1119 };
1120
1121 parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
1122
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001123 ret = weston_compositor_load_backend(c, WESTON_BACKEND_RDP,
1124 &config.base);
Benoit Gschwindbd573102016-04-22 17:05:26 +02001125
1126 free(config.bind_address);
1127 free(config.rdp_key);
1128 free(config.server_cert);
1129 free(config.server_key);
1130 return ret;
1131}
1132
Benoit Gschwind3c530942016-04-15 20:28:32 -07001133static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001134load_fbdev_backend(struct weston_compositor *c,
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001135 int *argc, char **argv, struct weston_config *wc)
1136{
1137 struct weston_fbdev_backend_config config = {{ 0, }};
1138 struct weston_config_section *section;
1139 char *s = NULL;
1140 int ret = 0;
1141
1142 const struct weston_option fbdev_options[] = {
1143 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
1144 { WESTON_OPTION_STRING, "device", 0, &config.device },
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001145 };
1146
1147 parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
1148
1149 if (!config.device)
1150 config.device = strdup("/dev/fb0");
1151
1152 section = weston_config_get_section(wc, "output", "name", "fbdev");
1153 weston_config_section_get_string(section, "transform", &s, "normal");
1154 if (weston_parse_transform(s, &config.output_transform) < 0)
1155 weston_log("Invalid transform \"%s\" for output fbdev\n", s);
1156 free(s);
1157
1158 config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
1159 config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
Giulio Camuffo8aedf7b2016-06-02 21:48:12 +03001160 config.configure_device = configure_input_device;
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001161
1162 /* load the actual wayland backend and configure it */
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001163 ret = weston_compositor_load_backend(c, WESTON_BACKEND_FBDEV,
1164 &config.base);
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001165
1166 free(config.device);
Benoit Gschwinde16acab2016-04-15 20:28:31 -07001167
1168 return ret;
1169}
1170
1171static int
1172weston_x11_backend_config_append_output_config(struct weston_x11_backend_config *config,
1173 struct weston_x11_backend_output_config *output_config) {
1174 struct weston_x11_backend_output_config *new_outputs;
1175
1176 new_outputs = realloc(config->outputs, (config->num_outputs+1) *
1177 sizeof(struct weston_x11_backend_output_config));
1178 if (new_outputs == NULL)
1179 return -1;
1180
1181 config->outputs = new_outputs;
1182 config->outputs[config->num_outputs].width = output_config->width;
1183 config->outputs[config->num_outputs].height = output_config->height;
1184 config->outputs[config->num_outputs].transform = output_config->transform;
1185 config->outputs[config->num_outputs].scale = output_config->scale;
1186 config->outputs[config->num_outputs].name = strdup(output_config->name);
1187 config->num_outputs++;
1188
1189 return 0;
1190}
1191
1192static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001193load_x11_backend(struct weston_compositor *c,
Benoit Gschwinde16acab2016-04-15 20:28:31 -07001194 int *argc, char **argv, struct weston_config *wc)
1195{
1196 struct weston_x11_backend_output_config default_output;
1197 struct weston_x11_backend_config config = {{ 0, }};
1198 struct weston_config_section *section;
1199 int ret = 0;
1200 int option_width = 0;
1201 int option_height = 0;
1202 int option_scale = 0;
1203 int option_count = 1;
1204 int output_count = 0;
1205 char const *section_name;
1206 int i;
1207 uint32_t j;
1208
1209 const struct weston_option options[] = {
1210 { WESTON_OPTION_INTEGER, "width", 0, &option_width },
1211 { WESTON_OPTION_INTEGER, "height", 0, &option_height },
1212 { WESTON_OPTION_INTEGER, "scale", 0, &option_scale },
1213 { WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
1214 { WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
1215 { WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
1216 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
1217 };
1218
1219 parse_options(options, ARRAY_LENGTH(options), argc, argv);
1220
1221 section = NULL;
1222 while (weston_config_next_section(wc, &section, &section_name)) {
1223 struct weston_x11_backend_output_config current_output = { 0, };
1224 char *t;
1225 char *mode;
1226
1227 if (strcmp(section_name, "output") != 0) {
1228 continue;
1229 }
1230
1231 weston_config_section_get_string(section, "name", &current_output.name, NULL);
1232 if (current_output.name == NULL || current_output.name[0] != 'X') {
1233 free(current_output.name);
1234 continue;
1235 }
1236
1237 weston_config_section_get_string(section, "mode", &mode, "1024x600");
1238 if (sscanf(mode, "%dx%d", &current_output.width,
1239 &current_output.height) != 2) {
1240 weston_log("Invalid mode \"%s\" for output %s\n",
1241 mode, current_output.name);
1242 current_output.width = 1024;
1243 current_output.height = 600;
1244 }
1245 free(mode);
1246 if (current_output.width < 1)
1247 current_output.width = 1024;
1248 if (current_output.height < 1)
1249 current_output.height = 600;
1250 if (option_width)
1251 current_output.width = option_width;
1252 if (option_height)
1253 current_output.height = option_height;
1254
1255 weston_config_section_get_int(section, "scale", &current_output.scale, 1);
1256 if (option_scale)
1257 current_output.scale = option_scale;
1258
1259 weston_config_section_get_string(section,
1260 "transform", &t, "normal");
1261 if (weston_parse_transform(t, &current_output.transform) < 0)
1262 weston_log("Invalid transform \"%s\" for output %s\n",
1263 t, current_output.name);
1264 free(t);
1265
1266 if (weston_x11_backend_config_append_output_config(&config, &current_output) < 0) {
1267 ret = -1;
1268 goto out;
1269 }
1270
1271 output_count++;
Bryce Harringtonaa258982016-05-03 01:34:23 -07001272 if (output_count >= option_count)
Benoit Gschwinde16acab2016-04-15 20:28:31 -07001273 break;
1274 }
1275
1276 default_output.name = NULL;
1277 default_output.width = option_width ? option_width : 1024;
1278 default_output.height = option_height ? option_height : 600;
1279 default_output.scale = option_scale ? option_scale : 1;
1280 default_output.transform = WL_OUTPUT_TRANSFORM_NORMAL;
1281
1282 for (i = output_count; i < option_count; i++) {
1283 if (asprintf(&default_output.name, "screen%d", i) < 0) {
1284 ret = -1;
1285 goto out;
1286 }
1287
1288 if (weston_x11_backend_config_append_output_config(&config, &default_output) < 0) {
1289 ret = -1;
1290 free(default_output.name);
1291 goto out;
1292 }
1293 free(default_output.name);
1294 }
1295
1296 config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
1297 config.base.struct_size = sizeof(struct weston_x11_backend_config);
1298
1299 /* load the actual backend and configure it */
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001300 ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
1301 &config.base);
Benoit Gschwinde16acab2016-04-15 20:28:31 -07001302
1303out:
1304 for (j = 0; j < config.num_outputs; ++j)
1305 free(config.outputs[j].name);
1306 free(config.outputs);
1307
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001308 return ret;
1309}
1310
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001311static void
1312weston_wayland_output_config_init(struct weston_wayland_backend_output_config *output_config,
1313 struct weston_config_section *config_section,
1314 int option_width, int option_height,
1315 int option_scale)
1316{
1317 char *mode, *t, *str;
1318 unsigned int slen;
1319
1320 weston_config_section_get_string(config_section, "name", &output_config->name,
1321 NULL);
1322 if (output_config->name) {
1323 slen = strlen(output_config->name);
1324 slen += strlen(WINDOW_TITLE " - ");
1325 str = malloc(slen + 1);
1326 if (str)
1327 snprintf(str, slen + 1, WINDOW_TITLE " - %s",
1328 output_config->name);
1329 free(output_config->name);
1330 output_config->name = str;
1331 }
1332 if (!output_config->name)
1333 output_config->name = strdup(WINDOW_TITLE);
1334
1335 weston_config_section_get_string(config_section,
1336 "mode", &mode, "1024x600");
1337 if (sscanf(mode, "%dx%d", &output_config->width, &output_config->height) != 2) {
1338 weston_log("Invalid mode \"%s\" for output %s\n",
1339 mode, output_config->name);
1340 output_config->width = 1024;
1341 output_config->height = 640;
1342 }
1343 free(mode);
1344
1345 if (option_width)
1346 output_config->width = option_width;
1347 if (option_height)
1348 output_config->height = option_height;
1349
1350 weston_config_section_get_int(config_section, "scale", &output_config->scale, 1);
1351
1352 if (option_scale)
1353 output_config->scale = option_scale;
1354
1355 weston_config_section_get_string(config_section,
1356 "transform", &t, "normal");
1357 if (weston_parse_transform(t, &output_config->transform) < 0)
1358 weston_log("Invalid transform \"%s\" for output %s\n",
1359 t, output_config->name);
1360 free(t);
1361
1362}
1363
1364static void
Benoit Gschwinde48ab5f2016-05-10 22:47:55 +02001365weston_wayland_backend_config_release(struct weston_wayland_backend_config *config)
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001366{
1367 int i;
1368
Benoit Gschwinde48ab5f2016-05-10 22:47:55 +02001369 for (i = 0; i < config->num_outputs; ++i) {
1370 free(config->outputs[i].name);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001371 }
Benoit Gschwinde48ab5f2016-05-10 22:47:55 +02001372 free(config->cursor_theme);
1373 free(config->display_name);
1374 free(config->outputs);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001375}
1376
1377/*
1378 * Append a new output struct at the end of new_config.outputs and return a
1379 * pointer to the newly allocated structure or NULL if fail. The allocated
1380 * structure is NOT cleared nor set to default values.
1381 */
1382static struct weston_wayland_backend_output_config *
Benoit Gschwind44e302b2016-05-10 22:47:56 +02001383weston_wayland_backend_config_add_new_output(struct weston_wayland_backend_config *config)
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001384{
1385 struct weston_wayland_backend_output_config *outputs;
1386 const size_t element_size = sizeof(struct weston_wayland_backend_output_config);
1387
Benoit Gschwind44e302b2016-05-10 22:47:56 +02001388 outputs = realloc(config->outputs,
1389 (config->num_outputs + 1) * element_size);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001390 if (!outputs)
1391 return NULL;
Benoit Gschwind44e302b2016-05-10 22:47:56 +02001392 config->num_outputs += 1;
1393 config->outputs = outputs;
1394 return &(config->outputs[config->num_outputs - 1]);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001395}
1396
1397static int
1398load_wayland_backend_config(struct weston_compositor *compositor, int *argc,
Benoit Gschwind6c1cd2f2016-05-10 22:47:50 +02001399 char *argv[], struct weston_config *wc,
Benoit Gschwind55a22882016-05-10 22:47:51 +02001400 struct weston_wayland_backend_config *config)
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001401{
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001402 struct weston_config_section *section;
1403 struct weston_wayland_backend_output_config *oc;
1404 int count, width, height, scale;
1405 const char *section_name;
1406 char *name;
1407
1408 const struct weston_option wayland_options[] = {
1409 { WESTON_OPTION_INTEGER, "width", 0, &width },
1410 { WESTON_OPTION_INTEGER, "height", 0, &height },
1411 { WESTON_OPTION_INTEGER, "scale", 0, &scale },
Benoit Gschwind55a22882016-05-10 22:47:51 +02001412 { WESTON_OPTION_STRING, "display", 0, &config->display_name },
1413 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config->use_pixman },
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001414 { WESTON_OPTION_INTEGER, "output-count", 0, &count },
Benoit Gschwind55a22882016-05-10 22:47:51 +02001415 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &config->fullscreen },
1416 { WESTON_OPTION_BOOLEAN, "sprawl", 0, &config->sprawl },
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001417 };
1418
1419 width = 0;
1420 height = 0;
1421 scale = 0;
Benoit Gschwind55a22882016-05-10 22:47:51 +02001422 config->display_name = NULL;
1423 config->use_pixman = 0;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001424 count = 1;
Benoit Gschwind55a22882016-05-10 22:47:51 +02001425 config->fullscreen = 0;
1426 config->sprawl = 0;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001427 parse_options(wayland_options,
1428 ARRAY_LENGTH(wayland_options), argc, argv);
1429
Benoit Gschwind55a22882016-05-10 22:47:51 +02001430 config->cursor_size = 32;
1431 config->cursor_theme = NULL;
1432 config->base.struct_size = sizeof(struct weston_wayland_backend_config);
1433 config->base.struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001434
Benoit Gschwind6c1cd2f2016-05-10 22:47:50 +02001435 section = weston_config_get_section(wc, "shell", NULL, NULL);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001436 weston_config_section_get_string(section, "cursor-theme",
Benoit Gschwind55a22882016-05-10 22:47:51 +02001437 &config->cursor_theme, NULL);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001438 weston_config_section_get_int(section, "cursor-size",
Benoit Gschwind55a22882016-05-10 22:47:51 +02001439 &config->cursor_size, 32);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001440
Benoit Gschwind55a22882016-05-10 22:47:51 +02001441 if (config->sprawl) {
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001442 /* do nothing, everything is already set */
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001443 return 0;
1444 }
1445
Benoit Gschwind55a22882016-05-10 22:47:51 +02001446 if (config->fullscreen) {
Benoit Gschwind390af6d2016-05-10 22:47:52 +02001447 oc = weston_wayland_backend_config_add_new_output(config);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001448 if (!oc)
Benoit Gschwind53753842016-05-10 22:47:57 +02001449 return -1;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001450
1451 oc->width = width;
1452 oc->height = height;
1453 oc->name = NULL;
1454 oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
1455 oc->scale = 1;
1456
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001457 return 0;
1458 }
1459
1460 section = NULL;
Benoit Gschwind6c1cd2f2016-05-10 22:47:50 +02001461 while (weston_config_next_section(wc, &section, &section_name)) {
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001462 if (!section_name || strcmp(section_name, "output") != 0)
1463 continue;
1464 weston_config_section_get_string(section, "name", &name, NULL);
1465 if (name == NULL)
1466 continue;
1467
1468 if (name[0] != 'W' || name[1] != 'L') {
1469 free(name);
1470 continue;
1471 }
1472 free(name);
1473
Benoit Gschwind390af6d2016-05-10 22:47:52 +02001474 oc = weston_wayland_backend_config_add_new_output(config);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001475 if (!oc)
Benoit Gschwind53753842016-05-10 22:47:57 +02001476 return -1;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001477
1478 weston_wayland_output_config_init(oc, section, width,
1479 height, scale);
1480 --count;
1481 }
1482
1483 if (!width)
1484 width = 1024;
1485 if (!height)
1486 height = 640;
1487 if (!scale)
1488 scale = 1;
Benoit Gschwind55a22882016-05-10 22:47:51 +02001489
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001490 while (count > 0) {
Benoit Gschwind390af6d2016-05-10 22:47:52 +02001491 oc = weston_wayland_backend_config_add_new_output(config);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001492 if (!oc)
Benoit Gschwind53753842016-05-10 22:47:57 +02001493 return -1;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001494
1495 oc->width = width;
1496 oc->height = height;
1497 oc->name = NULL;
1498 oc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
1499 oc->scale = scale;
1500
1501 --count;
1502 }
1503
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001504 return 0;
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001505}
1506
1507static int
Pekka Paalanen321ede72016-06-03 15:28:40 +03001508load_wayland_backend(struct weston_compositor *c,
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001509 int *argc, char **argv, struct weston_config *wc)
1510{
1511 struct weston_wayland_backend_config config = {{ 0, }};
1512 int ret = 0;
1513
1514 ret = load_wayland_backend_config(c, argc, argv, wc, &config);
Bryce Harrington1dbdc0b2016-07-12 16:59:05 -07001515 if (ret < 0) {
Benoit Gschwind53753842016-05-10 22:47:57 +02001516 weston_wayland_backend_config_release(&config);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001517 return ret;
1518 }
1519
1520 /* load the actual wayland backend and configure it */
Pekka Paalanen50dbf382016-06-03 15:23:46 +03001521 ret = weston_compositor_load_backend(c, WESTON_BACKEND_WAYLAND,
1522 &config.base);
Benoit Gschwind68d6a6c2016-05-10 22:47:53 +02001523 weston_wayland_backend_config_release(&config);
Benoit Gschwind3ff10da2016-05-10 22:47:49 +02001524 return ret;
1525}
1526
1527
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001528static int
Giulio Camuffo43008c72015-10-17 19:24:15 +03001529load_backend(struct weston_compositor *compositor, const char *backend,
1530 int *argc, char **argv, struct weston_config *config)
1531{
Benoit Gschwind3c530942016-04-15 20:28:32 -07001532 if (strstr(backend, "headless-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001533 return load_headless_backend(compositor, argc, argv, config);
Benoit Gschwindbd573102016-04-22 17:05:26 +02001534 else if (strstr(backend, "rdp-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001535 return load_rdp_backend(compositor, argc, argv, config);
Benoit Gschwind934e89a2016-04-27 23:56:42 +02001536 else if (strstr(backend, "fbdev-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001537 return load_fbdev_backend(compositor, argc, argv, config);
Giulio Camuffo1c0e40d2016-04-29 15:40:34 -07001538 else if (strstr(backend, "drm-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001539 return load_drm_backend(compositor, argc, argv, config);
Benoit Gschwinde16acab2016-04-15 20:28:31 -07001540 else if (strstr(backend, "x11-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001541 return load_x11_backend(compositor, argc, argv, config);
Giulio Camuffo43008c72015-10-17 19:24:15 +03001542 else if (strstr(backend, "wayland-backend.so"))
Pekka Paalanen321ede72016-06-03 15:28:40 +03001543 return load_wayland_backend(compositor, argc, argv, config);
Giulio Camuffo43008c72015-10-17 19:24:15 +03001544
Pekka Paalanen808b0062016-06-03 13:56:17 +03001545 weston_log("Error: unknown backend \"%s\"\n", backend);
1546 return -1;
Giulio Camuffo43008c72015-10-17 19:24:15 +03001547}
1548
Pekka Paalanen20436e22016-02-11 14:42:21 +02001549static char *
1550copy_command_line(int argc, char * const argv[])
1551{
1552 FILE *fp;
1553 char *str = NULL;
1554 size_t size = 0;
1555 int i;
1556
1557 fp = open_memstream(&str, &size);
1558 if (!fp)
1559 return NULL;
1560
1561 fprintf(fp, "%s", argv[0]);
1562 for (i = 1; i < argc; i++)
1563 fprintf(fp, " %s", argv[i]);
1564 fclose(fp);
1565
1566 return str;
1567}
1568
Giulio Camuffobab996e2014-10-12 00:24:25 +03001569int main(int argc, char *argv[])
1570{
1571 int ret = EXIT_FAILURE;
Pekka Paalanen20436e22016-02-11 14:42:21 +02001572 char *cmdline;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001573 struct wl_display *display;
1574 struct weston_compositor *ec;
1575 struct wl_event_source *signals[4];
1576 struct wl_event_loop *loop;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001577 int i, fd;
1578 char *backend = NULL;
1579 char *shell = NULL;
1580 char *modules = NULL;
1581 char *option_modules = NULL;
1582 char *log = NULL;
1583 char *server_socket = NULL, *end;
1584 int32_t idle_time = -1;
1585 int32_t help = 0;
1586 char *socket_name = NULL;
1587 int32_t version = 0;
1588 int32_t noconfig = 0;
1589 int32_t numlock_on;
1590 char *config_file = NULL;
1591 struct weston_config *config = NULL;
1592 struct weston_config_section *section;
1593 struct wl_client *primary_client;
1594 struct wl_listener primary_client_destroyed;
1595 struct weston_seat *seat;
Armin Krezović78a36372016-08-01 18:51:46 +02001596 struct wet_compositor user_data;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001597
1598 const struct weston_option core_options[] = {
1599 { WESTON_OPTION_STRING, "backend", 'B', &backend },
1600 { WESTON_OPTION_STRING, "shell", 0, &shell },
1601 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
1602 { WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
1603 { WESTON_OPTION_STRING, "modules", 0, &option_modules },
1604 { WESTON_OPTION_STRING, "log", 0, &log },
1605 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
1606 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
1607 { WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
1608 { WESTON_OPTION_STRING, "config", 'c', &config_file },
1609 };
1610
Pekka Paalanen20436e22016-02-11 14:42:21 +02001611 cmdline = copy_command_line(argc, argv);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001612 parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
1613
Pekka Paalanen20436e22016-02-11 14:42:21 +02001614 if (help) {
1615 free(cmdline);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001616 usage(EXIT_SUCCESS);
Pekka Paalanen20436e22016-02-11 14:42:21 +02001617 }
Giulio Camuffobab996e2014-10-12 00:24:25 +03001618
1619 if (version) {
1620 printf(PACKAGE_STRING "\n");
Pekka Paalanen20436e22016-02-11 14:42:21 +02001621 free(cmdline);
1622
Giulio Camuffobab996e2014-10-12 00:24:25 +03001623 return EXIT_SUCCESS;
1624 }
1625
Giulio Camuffobe2b11a2016-06-02 21:48:13 +03001626 weston_log_set_handler(vlog, vlog_continue);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001627 weston_log_file_open(log);
1628
1629 weston_log("%s\n"
1630 STAMP_SPACE "%s\n"
1631 STAMP_SPACE "Bug reports to: %s\n"
1632 STAMP_SPACE "Build: %s\n",
1633 PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
1634 BUILD_ID);
Pekka Paalanen20436e22016-02-11 14:42:21 +02001635 weston_log("Command line: %s\n", cmdline);
1636 free(cmdline);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001637 log_uname();
1638
1639 verify_xdg_runtime_dir();
1640
1641 display = wl_display_create();
1642
1643 loop = wl_display_get_event_loop(display);
1644 signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
1645 display);
1646 signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
1647 display);
1648 signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
1649 display);
1650
1651 wl_list_init(&child_process_list);
1652 signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
1653 NULL);
1654
1655 if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
1656 goto out_signals;
1657
1658 if (load_configuration(&config, noconfig, config_file) < 0)
1659 goto out_signals;
Armin Krezović78a36372016-08-01 18:51:46 +02001660 user_data.config = config;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001661
1662 section = weston_config_get_section(config, "core", NULL, NULL);
1663
1664 if (!backend) {
1665 weston_config_section_get_string(section, "backend", &backend,
1666 NULL);
1667 if (!backend)
1668 backend = weston_choose_default_backend();
1669 }
1670
Armin Krezović78a36372016-08-01 18:51:46 +02001671 ec = weston_compositor_create(display, &user_data);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001672 if (ec == NULL) {
1673 weston_log("fatal: failed to create compositor\n");
Giulio Camuffo3c241b12015-10-03 16:25:16 +03001674 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001675 }
1676
Giulio Camuffobab996e2014-10-12 00:24:25 +03001677 if (weston_compositor_init_config(ec, config) < 0)
Giulio Camuffo3c241b12015-10-03 16:25:16 +03001678 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001679
Giulio Camuffo43008c72015-10-17 19:24:15 +03001680 if (load_backend(ec, backend, &argc, argv, config) < 0) {
Giulio Camuffobab996e2014-10-12 00:24:25 +03001681 weston_log("fatal: failed to create compositor backend\n");
Giulio Camuffo3c241b12015-10-03 16:25:16 +03001682 goto out;
Giulio Camuffobab996e2014-10-12 00:24:25 +03001683 }
1684
1685 catch_signals();
1686 segv_compositor = ec;
1687
1688 if (idle_time < 0)
1689 weston_config_section_get_int(section, "idle-time", &idle_time, -1);
1690 if (idle_time < 0)
1691 idle_time = 300; /* default idle timeout, in seconds */
1692
1693 ec->idle_time = idle_time;
1694 ec->default_pointer_grab = NULL;
1695 ec->exit = handle_exit;
1696
1697 weston_compositor_log_capabilities(ec);
1698
1699 server_socket = getenv("WAYLAND_SERVER_SOCKET");
1700 if (server_socket) {
1701 weston_log("Running with single client\n");
Bryce Harrington375759e2016-07-12 16:51:27 -07001702 fd = strtol(server_socket, &end, 10);
Giulio Camuffobab996e2014-10-12 00:24:25 +03001703 if (*end != '\0')
1704 fd = -1;
1705 } else {
1706 fd = -1;
1707 }
1708
1709 if (fd != -1) {
1710 primary_client = wl_client_create(display, fd);
1711 if (!primary_client) {
1712 weston_log("fatal: failed to add client: %m\n");
1713 goto out;
1714 }
1715 primary_client_destroyed.notify =
1716 handle_primary_client_destroyed;
1717 wl_client_add_destroy_listener(primary_client,
1718 &primary_client_destroyed);
1719 } else if (weston_create_listening_socket(display, socket_name)) {
1720 goto out;
1721 }
1722
1723 if (!shell)
1724 weston_config_section_get_string(section, "shell", &shell,
1725 "desktop-shell.so");
1726
1727 if (load_modules(ec, shell, &argc, argv) < 0)
1728 goto out;
1729
1730 weston_config_section_get_string(section, "modules", &modules, "");
1731 if (load_modules(ec, modules, &argc, argv) < 0)
1732 goto out;
1733
1734 if (load_modules(ec, option_modules, &argc, argv) < 0)
1735 goto out;
1736
1737 section = weston_config_get_section(config, "keyboard", NULL, NULL);
1738 weston_config_section_get_bool(section, "numlock-on", &numlock_on, 0);
1739 if (numlock_on) {
1740 wl_list_for_each(seat, &ec->seat_list, link) {
Derek Foreman1281a362015-07-31 16:55:32 -05001741 struct weston_keyboard *keyboard =
1742 weston_seat_get_keyboard(seat);
1743
1744 if (keyboard)
1745 weston_keyboard_set_locks(keyboard,
Giulio Camuffobab996e2014-10-12 00:24:25 +03001746 WESTON_NUM_LOCK,
1747 WESTON_NUM_LOCK);
1748 }
1749 }
1750
1751 for (i = 1; i < argc; i++)
1752 weston_log("fatal: unhandled option: %s\n", argv[i]);
1753 if (argc > 1)
1754 goto out;
1755
1756 weston_compositor_wake(ec);
1757
1758 wl_display_run(display);
1759
1760 /* Allow for setting return exit code after
1761 * wl_display_run returns normally. This is
1762 * useful for devs/testers and automated tests
1763 * that want to indicate failure status to
1764 * testing infrastructure above
1765 */
1766 ret = ec->exit_code;
1767
1768out:
1769 weston_compositor_destroy(ec);
1770
1771out_signals:
1772 for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
1773 if (signals[i])
1774 wl_event_source_remove(signals[i]);
1775
1776 wl_display_destroy(display);
1777
1778 weston_log_file_close();
1779
1780 if (config)
1781 weston_config_destroy(config);
1782 free(config_file);
1783 free(backend);
1784 free(shell);
1785 free(socket_name);
1786 free(option_modules);
1787 free(log);
1788 free(modules);
1789
1790 return ret;
1791}