1 /*
2 * Copyright © 2010-2011 Intel Corporation
3 * Copyright © 2008-2011 Kristian Høgsberg
4 * Copyright © 2012-2018 Collabora, Ltd.
5 * Copyright © 2010-2011 Benjamin Franzke
6 * Copyright © 2013 Jason Ekstrand
7 * Copyright © 2017, 2018 General Electric Company
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sublicense, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial
19 * portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
25 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
26 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 * SOFTWARE.
29 */
30
31 #include "config.h"
32
33 #include <unistd.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <dlfcn.h>
37 #include <stdint.h>
38 #include <string.h>
39 #include <sys/utsname.h>
40 #include <sys/stat.h>
41 #include <sys/wait.h>
42 #include <sys/socket.h>
43 #include <libinput.h>
44 #include <libevdev/libevdev.h>
45 #include <linux/input.h>
46 #include <sys/time.h>
47 #include <linux/limits.h>
48 #include <pthread.h>
49
50 #include "weston.h"
51 #include <libweston/libweston.h>
52 #include "shared/os-compatibility.h"
53 #include "shared/helpers.h"
54 #include "shared/string-helpers.h"
55 #include "git-version.h"
56 #include <libweston/version.h>
57 #include "weston.h"
58
59 #include "libweston/soft_vsync.h" // OHOS vsync module
60 #include <vsync_module_c.h> // OHOS vsync module
61
62 #include <libweston/backend-drm.h>
63 #include <libweston/backend-headless.h>
64 #include <libweston/backend-hdi.h>
65 #include <libweston/backend-rdp.h>
66 #include <libweston/backend-fbdev.h>
67 #include <libweston/backend-x11.h>
68 #include <libweston/backend-wayland.h>
69 #include <libweston/windowed-output-api.h>
70 #include <libweston/weston-log.h>
71 #include "../remoting/remoting-plugin.h"
72 #include "../pipewire/pipewire-plugin.h"
73
74 #include "libweston/trace.h"
75 DEFINE_LOG_LABEL("Weston");
76
77 #define WINDOW_TITLE "Weston Compositor"
78 /* flight recorder size (in bytes) */
79 #define DEFAULT_FLIGHT_REC_SIZE (5 * 1024 * 1024)
80
81 struct wet_output_config {
82 int width;
83 int height;
84 int32_t scale;
85 uint32_t transform;
86 };
87
88 struct wet_compositor;
89 struct wet_layoutput;
90
91 struct wet_head_tracker {
92 struct wl_listener head_destroy_listener;
93 };
94
95 /** User data for each weston_output */
96 struct wet_output {
97 struct weston_output *output;
98 struct wl_listener output_destroy_listener;
99 struct wet_layoutput *layoutput;
100 struct wl_list link; /**< in wet_layoutput::output_list */
101 };
102
103 #define MAX_CLONE_HEADS 16
104
105 struct wet_head_array {
106 struct weston_head *heads[MAX_CLONE_HEADS]; /**< heads to add */
107 unsigned n; /**< the number of heads */
108 };
109
110 /** A layout output
111 *
112 * Contains wet_outputs that are all clones (independent CRTCs).
113 * Stores output layout information in the future.
114 */
115 struct wet_layoutput {
116 struct wet_compositor *compositor;
117 struct wl_list compositor_link; /**< in wet_compositor::layoutput_list */
118 struct wl_list output_list; /**< wet_output::link */
119 char *name;
120 struct weston_config_section *section;
121 struct wet_head_array add; /**< tmp: heads to add as clones */
122 };
123
124 struct wet_compositor {
125 struct weston_compositor *compositor;
126 struct weston_config *config;
127 struct wet_output_config *parsed_options;
128 bool drm_use_current_mode;
129 struct wl_listener heads_changed_listener;
130 int (*simple_output_configure)(struct weston_output *output);
131 bool init_failed;
132 struct wl_list layoutput_list; /**< wet_layoutput::compositor_link */
133 };
134
135 static FILE *weston_logfile = NULL;
136 // OHOS remove logger
137 //static struct weston_log_scope *log_scope;
138 //static struct weston_log_scope *protocol_scope;
139 static int cached_tm_mday = -1;
140
141 // OHOS remove logger
142 //static char *
143 //weston_log_timestamp(char *buf, size_t len)
144 //{
145 // struct timeval tv;
146 // struct tm *brokendown_time;
147 // char datestr[128];
148 // char timestr[128];
149 //
150 // gettimeofday(&tv, NULL);
151 //
152 // brokendown_time = localtime(&tv.tv_sec);
153 // if (brokendown_time == NULL) {
154 // snprintf(buf, len, "%{public}s", "[(NULL)localtime] ");
155 // return buf;
156 // }
157 //
158 // memset(datestr, 0, sizeof(datestr));
159 // if (brokendown_time->tm_mday != cached_tm_mday) {
160 // strftime(datestr, sizeof(datestr), "Date: %Y-%m-%d %Z\n",
161 // brokendown_time);
162 // cached_tm_mday = brokendown_time->tm_mday;
163 // }
164 //
165 // strftime(timestr, sizeof(timestr), "%H:%M:%S", brokendown_time);
166 // /* if datestr is empty it prints only timestr*/
167 // snprintf(buf, len, "%{public}s[%{public}s.%03li]", datestr,
168 // timestr, (tv.tv_usec / 1000));
169 //
170 // return buf;
171 //}
172 //
173 //static void
174 //custom_handler(const char *fmt, va_list arg)
175 //{
176 // char timestr[512];
177 //
178 // weston_log_scope_printf(log_scope, "%{public}s libwayland: ",
179 // weston_log_timestamp(timestr,
180 // sizeof(timestr)));
181 // weston_log_scope_vprintf(log_scope, fmt, arg);
182 //}
183 //
184 //static bool
185 //weston_log_file_open(const char *filename)
186 //{
187 // wl_log_set_handler_server(custom_handler);
188 //
189 // if (filename != NULL) {
190 // weston_logfile = fopen(filename, "a");
191 // if (weston_logfile) {
192 // os_fd_set_cloexec(fileno(weston_logfile));
193 // } else {
194 // fprintf(stderr, "Failed to open %{public}s: %{public}s\n", filename, strerror(errno));
195 // return false;
196 // }
197 // }
198 //
199 // if (weston_logfile == NULL)
200 // weston_logfile = stderr;
201 // else
202 // setvbuf(weston_logfile, NULL, _IOLBF, 256);
203 //
204 // return true;
205 //}
206 //
207 //static void
208 //weston_log_file_close(void)
209 //{
210 // if ((weston_logfile != stderr) && (weston_logfile != NULL))
211 // fclose(weston_logfile);
212 // weston_logfile = stderr;
213 //}
214 //
215 //static int
216 //vlog(const char *fmt, va_list ap)
217 //{
218 // const char *oom = "Out of memory";
219 // char timestr[128];
220 // int len = 0;
221 // char *str;
222 //
223 // if (weston_log_scope_is_enabled(log_scope)) {
224 // int len_va;
225 // char *log_timestamp = weston_log_timestamp(timestr,
226 // sizeof(timestr));
227 // len_va = vasprintf(&str, fmt, ap);
228 // if (len_va >= 0) {
229 // len = weston_log_scope_printf(log_scope, "%{public}s %{public}s",
230 // log_timestamp, str);
231 // free(str);
232 // } else {
233 // len = weston_log_scope_printf(log_scope, "%{public}s %{public}s",
234 // log_timestamp, oom);
235 // }
236 // }
237 //
238 // return len;
239 //}
240 //
241 //static int
242 //vlog_continue(const char *fmt, va_list argp)
243 //{
244 // return weston_log_scope_vprintf(log_scope, fmt, argp);
245 //}
246 //
247 //static const char *
248 //get_next_argument(const char *signature, char* type)
249 //{
250 // for(; *signature; ++signature) {
251 // switch(*signature) {
252 // case 'i':
253 // case 'u':
254 // case 'f':
255 // case 's':
256 // case 'o':
257 // case 'n':
258 // case 'a':
259 // case 'h':
260 // *type = *signature;
261 // return signature + 1;
262 // }
263 // }
264 // *type = '\0';
265 // return signature;
266 //}
267 //
268 //static void
269 //protocol_log_fn(void *user_data,
270 // enum wl_protocol_logger_type direction,
271 // const struct wl_protocol_logger_message *message)
272 //{
273 // FILE *fp;
274 // char *logstr;
275 // size_t logsize;
276 // char timestr[128];
277 // struct wl_resource *res = message->resource;
278 // const char *signature = message->message->signature;
279 // int i;
280 // char type;
281 //
282 // if (!weston_log_scope_is_enabled(protocol_scope))
283 // return;
284 //
285 // fp = open_memstream(&logstr, &logsize);
286 // if (!fp)
287 // return;
288 //
289 // weston_log_scope_timestamp(protocol_scope,
290 // timestr, sizeof timestr);
291 // fprintf(fp, "%{public}s ", timestr);
292 // fprintf(fp, "client %p %{public}s ", wl_resource_get_client(res),
293 // direction == WL_PROTOCOL_LOGGER_REQUEST ? "rq" : "ev");
294 // fprintf(fp, "%{public}s@%u.%{public}s(",
295 // wl_resource_get_class(res),
296 // wl_resource_get_id(res),
297 // message->message->name);
298 //
299 // for (i = 0; i < message->arguments_count; i++) {
300 // signature = get_next_argument(signature, &type);
301 //
302 // if (i > 0)
303 // fprintf(fp, ", ");
304 //
305 // switch (type) {
306 // case 'u':
307 // fprintf(fp, "%u", message->arguments[i].u);
308 // break;
309 // case 'i':
310 // fprintf(fp, "%d", message->arguments[i].i);
311 // break;
312 // case 'f':
313 // fprintf(fp, "%f",
314 // wl_fixed_to_double(message->arguments[i].f));
315 // break;
316 // case 's':
317 // fprintf(fp, "\"%{public}s\"", message->arguments[i].s);
318 // break;
319 // case 'o':
320 // if (message->arguments[i].o) {
321 // struct wl_resource* resource;
322 // resource = (struct wl_resource*) message->arguments[i].o;
323 // fprintf(fp, "%{public}s@%u",
324 // wl_resource_get_class(resource),
325 // wl_resource_get_id(resource));
326 // }
327 // else
328 // fprintf(fp, "nil");
329 // break;
330 // case 'n':
331 // fprintf(fp, "new id %{public}s@",
332 // (message->message->types[i]) ?
333 // message->message->types[i]->name :
334 // "[unknown]");
335 // if (message->arguments[i].n != 0)
336 // fprintf(fp, "%u", message->arguments[i].n);
337 // else
338 // fprintf(fp, "nil");
339 // break;
340 // case 'a':
341 // fprintf(fp, "array");
342 // break;
343 // case 'h':
344 // fprintf(fp, "fd %d", message->arguments[i].h);
345 // break;
346 // }
347 // }
348 //
349 // fprintf(fp, ")\n");
350 //
351 // if (fclose(fp) == 0)
352 // weston_log_scope_write(protocol_scope, logstr, logsize);
353 //
354 // free(logstr);
355 //}
356
357 static struct wl_list child_process_list;
358 static struct weston_compositor *segv_compositor;
359
360 static int
sigchld_handler(int signal_number,void * data)361 sigchld_handler(int signal_number, void *data)
362 {
363 struct weston_process *p;
364 int status;
365 pid_t pid;
366
367 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
368 wl_list_for_each(p, &child_process_list, link) {
369 if (p->pid == pid)
370 break;
371 }
372
373 if (&p->link == &child_process_list) {
374 weston_log("unknown child process exited\n");
375 continue;
376 }
377
378 wl_list_remove(&p->link);
379 p->cleanup(p, status);
380 }
381
382 if (pid < 0 && errno != ECHILD)
383 weston_log("waitpid error %{public}s\n", strerror(errno));
384
385 return 1;
386 }
387
388 static void
child_client_exec(int sockfd,const char * path)389 child_client_exec(int sockfd, const char *path)
390 {
391 int clientfd;
392 char s[32];
393 sigset_t allsigs;
394
395 /* do not give our signal mask to the new process */
396 sigfillset(&allsigs);
397 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
398
399 /* Launch clients as the user. Do not launch clients with wrong euid. */
400 if (seteuid(getuid()) == -1) {
401 weston_log("compositor: failed seteuid\n");
402 return;
403 }
404
405 /* SOCK_CLOEXEC closes both ends, so we dup the fd to get a
406 * non-CLOEXEC fd to pass through exec. */
407 clientfd = dup(sockfd);
408 if (clientfd == -1) {
409 weston_log("compositor: dup failed: %{public}s\n", strerror(errno));
410 return;
411 }
412
413 snprintf(s, sizeof s, "%d", clientfd);
414 setenv("WAYLAND_SOCKET", s, 1);
415
416 if (execl(path, path, NULL) < 0)
417 weston_log("compositor: executing '%{public}s' failed: %{public}s\n",
418 path, strerror(errno));
419 }
420
421 WL_EXPORT struct wl_client *
weston_client_launch(struct weston_compositor * compositor,struct weston_process * proc,const char * path,weston_process_cleanup_func_t cleanup)422 weston_client_launch(struct weston_compositor *compositor,
423 struct weston_process *proc,
424 const char *path,
425 weston_process_cleanup_func_t cleanup)
426 {
427 int sv[2];
428 pid_t pid;
429 struct wl_client *client;
430
431 weston_log("launching '%{public}s'\n", path);
432
433 if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
434 weston_log("weston_client_launch: "
435 "socketpair failed while launching '%{public}s': %{public}s\n",
436 path, strerror(errno));
437 return NULL;
438 }
439
440 pid = fork();
441 if (pid == -1) {
442 close(sv[0]);
443 close(sv[1]);
444 weston_log("weston_client_launch: "
445 "fork failed while launching '%{public}s': %{public}s\n", path,
446 strerror(errno));
447 return NULL;
448 }
449
450 if (pid == 0) {
451 child_client_exec(sv[1], path);
452 _exit(-1);
453 }
454
455 close(sv[1]);
456
457 client = wl_client_create(compositor->wl_display, sv[0]);
458 if (!client) {
459 close(sv[0]);
460 weston_log("weston_client_launch: "
461 "wl_client_create failed while launching '%{public}s'.\n",
462 path);
463 return NULL;
464 }
465
466 proc->pid = pid;
467 proc->cleanup = cleanup;
468 weston_watch_process(proc);
469
470 return client;
471 }
472
473 WL_EXPORT void
weston_watch_process(struct weston_process * process)474 weston_watch_process(struct weston_process *process)
475 {
476 wl_list_insert(&child_process_list, &process->link);
477 }
478
479 struct process_info {
480 struct weston_process proc;
481 char *path;
482 };
483
484 static void
process_handle_sigchld(struct weston_process * process,int status)485 process_handle_sigchld(struct weston_process *process, int status)
486 {
487 struct process_info *pinfo =
488 container_of(process, struct process_info, proc);
489
490 /*
491 * There are no guarantees whether this runs before or after
492 * the wl_client destructor.
493 */
494
495 if (WIFEXITED(status)) {
496 weston_log("%{public}s exited with status %d\n", pinfo->path,
497 WEXITSTATUS(status));
498 } else if (WIFSIGNALED(status)) {
499 weston_log("%{public}s died on signal %d\n", pinfo->path,
500 WTERMSIG(status));
501 } else {
502 weston_log("%{public}s disappeared\n", pinfo->path);
503 }
504
505 free(pinfo->path);
506 free(pinfo);
507 }
508
509 WL_EXPORT struct wl_client *
weston_client_start(struct weston_compositor * compositor,const char * path)510 weston_client_start(struct weston_compositor *compositor, const char *path)
511 {
512 struct process_info *pinfo;
513 struct wl_client *client;
514
515 pinfo = zalloc(sizeof *pinfo);
516 if (!pinfo)
517 return NULL;
518
519 pinfo->path = strdup(path);
520 if (!pinfo->path)
521 goto out_free;
522
523 client = weston_client_launch(compositor, &pinfo->proc, path,
524 process_handle_sigchld);
525 if (!client)
526 goto out_str;
527
528 return client;
529
530 out_str:
531 free(pinfo->path);
532
533 out_free:
534 free(pinfo);
535
536 return NULL;
537 }
538
539 static void
log_uname(void)540 log_uname(void)
541 {
542 struct utsname usys;
543
544 uname(&usys);
545
546 weston_log("OS: %{public}s, %{public}s, %{public}s, %{public}s\n", usys.sysname, usys.release,
547 usys.version, usys.machine);
548 }
549
550 static struct wet_compositor *
to_wet_compositor(struct weston_compositor * compositor)551 to_wet_compositor(struct weston_compositor *compositor)
552 {
553 return weston_compositor_get_user_data(compositor);
554 }
555
556 static struct wet_output_config *
wet_init_parsed_options(struct weston_compositor * ec)557 wet_init_parsed_options(struct weston_compositor *ec)
558 {
559 struct wet_compositor *compositor = to_wet_compositor(ec);
560 struct wet_output_config *config;
561
562 config = zalloc(sizeof *config);
563
564 if (!config) {
565 perror("out of memory");
566 return NULL;
567 }
568
569 config->width = 0;
570 config->height = 0;
571 config->scale = 0;
572 config->transform = UINT32_MAX;
573
574 compositor->parsed_options = config;
575
576 return config;
577 }
578
579 WL_EXPORT struct weston_config *
wet_get_config(struct weston_compositor * ec)580 wet_get_config(struct weston_compositor *ec)
581 {
582 struct wet_compositor *compositor = to_wet_compositor(ec);
583
584 return compositor->config;
585 }
586
587 static const char xdg_error_message[] =
588 "fatal: environment variable XDG_RUNTIME_DIR is not set.\n";
589
590 static const char xdg_wrong_message[] =
591 "fatal: environment variable XDG_RUNTIME_DIR\n"
592 "is set to \"%{public}s\", which is not a directory.\n";
593
594 static const char xdg_wrong_mode_message[] =
595 "warning: XDG_RUNTIME_DIR \"%{public}s\" is not configured\n"
596 "correctly. Unix access mode must be 0700 (current mode is %o),\n"
597 "and must be owned by the user (current owner is UID %d).\n";
598
599 static const char xdg_detail_message[] =
600 "Refer to your distribution on how to get it, or\n"
601 "http://www.freedesktop.org/wiki/Specifications/basedir-spec\n"
602 "on how to implement it.\n";
603
604 static void
verify_xdg_runtime_dir(void)605 verify_xdg_runtime_dir(void)
606 {
607 char *dir = getenv("XDG_RUNTIME_DIR");
608 struct stat s;
609
610 if (!dir) {
611 weston_log(xdg_error_message);
612 weston_log_continue(xdg_detail_message);
613 exit(EXIT_FAILURE);
614 }
615
616 if (stat(dir, &s) || !S_ISDIR(s.st_mode)) {
617 weston_log(xdg_wrong_message, dir);
618 weston_log_continue(xdg_detail_message);
619 exit(EXIT_FAILURE);
620 }
621
622 if ((s.st_mode & 0777) != 0700 || s.st_uid != getuid()) {
623 weston_log(xdg_wrong_mode_message,
624 dir, s.st_mode & 0777, s.st_uid);
625 weston_log_continue(xdg_detail_message);
626 }
627 }
628
629 static int
usage(int error_code)630 usage(int error_code)
631 {
632 FILE *out = error_code == EXIT_SUCCESS ? stdout : stderr;
633
634 fprintf(out,
635 "Usage: weston [OPTIONS]\n\n"
636 "This is weston version " VERSION ", the Wayland reference compositor.\n"
637 "Weston supports multiple backends, and depending on which backend is in use\n"
638 "different options will be accepted.\n\n"
639
640
641 "Core options:\n\n"
642 " --version\t\tPrint weston version\n"
643 " -B, --backend=MODULE\tBackend module, one of\n"
644 #if defined(BUILD_DRM_COMPOSITOR)
645 "\t\t\t\tdrm-backend.so\n"
646 #endif
647 #if defined(BUILD_FBDEV_COMPOSITOR)
648 "\t\t\t\tfbdev-backend.so\n"
649 #endif
650 #if defined(BUILD_HEADLESS_COMPOSITOR)
651 "\t\t\t\theadless-backend.so\n"
652 #endif
653 #if defined(BUILD_RDP_COMPOSITOR)
654 "\t\t\t\trdp-backend.so\n"
655 #endif
656 #if defined(BUILD_WAYLAND_COMPOSITOR)
657 "\t\t\t\twayland-backend.so\n"
658 #endif
659 #if defined(BUILD_X11_COMPOSITOR)
660 "\t\t\t\tx11-backend.so\n"
661 #endif
662 " --shell=MODULE\tShell module, defaults to desktop-shell.so\n"
663 " -S, --socket=NAME\tName of socket to listen on\n"
664 " -i, --idle-time=SECS\tIdle time in seconds\n"
665 #if defined(BUILD_XWAYLAND)
666 " --xwayland\t\tLoad the xwayland module\n"
667 #endif
668 " --modules\t\tLoad the comma-separated list of modules\n"
669 " --log=FILE\t\tLog to the given file\n"
670 " -c, --config=FILE\tConfig file to load, defaults to weston.ini\n"
671 " --no-config\t\tDo not read weston.ini\n"
672 " --wait-for-debugger\tRaise SIGSTOP on start-up\n"
673 " --debug\t\tEnable debug extension\n"
674 " -l, --logger-scopes=SCOPE\n\t\t\tSpecify log scopes to "
675 "subscribe to.\n\t\t\tCan specify multiple scopes, "
676 "each followed by comma\n"
677 " -f, --flight-rec-scopes=SCOPE\n\t\t\tSpecify log scopes to "
678 "subscribe to.\n\t\t\tCan specify multiple scopes, "
679 "each followed by comma\n"
680 " -h, --help\t\tThis help message\n\n");
681
682 #if defined(BUILD_DRM_COMPOSITOR)
683 fprintf(out,
684 "Options for drm-backend.so:\n\n"
685 " --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
686 " --tty=TTY\t\tThe tty to use\n"
687 " --drm-device=CARD\tThe DRM device to use, e.g. \"card0\".\n"
688 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
689 " --current-mode\tPrefer current KMS mode over EDID preferred mode\n"
690 " --continue-without-input\tAllow the compositor to start without input devices\n\n");
691 #endif
692
693 #if defined(BUILD_FBDEV_COMPOSITOR)
694 fprintf(out,
695 "Options for fbdev-backend.so:\n\n"
696 " --tty=TTY\t\tThe tty to use\n"
697 " --device=DEVICE\tThe framebuffer device to use\n"
698 " --seat=SEAT\t\tThe seat that weston should run on, instead of the seat defined in XDG_SEAT\n"
699 "\n");
700 #endif
701
702 #if defined(BUILD_HEADLESS_COMPOSITOR)
703 fprintf(out,
704 "Options for headless-backend.so:\n\n"
705 " --width=WIDTH\t\tWidth of memory surface\n"
706 " --height=HEIGHT\tHeight of memory surface\n"
707 " --scale=SCALE\t\tScale factor of output\n"
708 " --transform=TR\tThe output transformation, TR is one of:\n"
709 "\tnormal 90 180 270 flipped flipped-90 flipped-180 flipped-270\n"
710 " --use-pixman\t\tUse the pixman (CPU) renderer (default: no rendering)\n"
711 " --use-gl\t\tUse the GL renderer (default: no rendering)\n"
712 " --no-outputs\t\tDo not create any virtual outputs\n"
713 "\n");
714 #endif
715
716 #if defined(BUILD_RDP_COMPOSITOR)
717 fprintf(out,
718 "Options for rdp-backend.so:\n\n"
719 " --width=WIDTH\t\tWidth of desktop\n"
720 " --height=HEIGHT\tHeight of desktop\n"
721 " --env-socket\t\tUse socket defined in RDP_FD env variable as peer connection\n"
722 " --address=ADDR\tThe address to bind\n"
723 " --port=PORT\t\tThe port to listen on\n"
724 " --no-clients-resize\tThe RDP peers will be forced to the size of the desktop\n"
725 " --rdp4-key=FILE\tThe file containing the key for RDP4 encryption\n"
726 " --rdp-tls-cert=FILE\tThe file containing the certificate for TLS encryption\n"
727 " --rdp-tls-key=FILE\tThe file containing the private key for TLS encryption\n"
728 "\n");
729 #endif
730
731 #if defined(BUILD_WAYLAND_COMPOSITOR)
732 fprintf(out,
733 "Options for wayland-backend.so:\n\n"
734 " --width=WIDTH\t\tWidth of Wayland surface\n"
735 " --height=HEIGHT\tHeight of Wayland surface\n"
736 " --scale=SCALE\t\tScale factor of output\n"
737 " --fullscreen\t\tRun in fullscreen mode\n"
738 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
739 " --output-count=COUNT\tCreate multiple outputs\n"
740 " --sprawl\t\tCreate one fullscreen output for every parent output\n"
741 " --display=DISPLAY\tWayland display to connect to\n\n");
742 #endif
743
744 #if defined(BUILD_X11_COMPOSITOR)
745 fprintf(out,
746 "Options for x11-backend.so:\n\n"
747 " --width=WIDTH\t\tWidth of X window\n"
748 " --height=HEIGHT\tHeight of X window\n"
749 " --scale=SCALE\t\tScale factor of output\n"
750 " --fullscreen\t\tRun in fullscreen mode\n"
751 " --use-pixman\t\tUse the pixman (CPU) renderer\n"
752 " --output-count=COUNT\tCreate multiple outputs\n"
753 " --no-input\t\tDont create input devices\n\n");
754 #endif
755
756 exit(error_code);
757 }
758
on_term_signal(int signal_number,void * data)759 static int on_term_signal(int signal_number, void *data)
760 {
761 struct wl_display *display = data;
762
763 weston_log("caught signal %d\n", signal_number);
764 wl_display_terminate(display);
765
766 return 1;
767 }
768
769 static const char *
clock_name(clockid_t clk_id)770 clock_name(clockid_t clk_id)
771 {
772 static const char *names[] = {
773 [CLOCK_REALTIME] = "CLOCK_REALTIME",
774 [CLOCK_MONOTONIC] = "CLOCK_MONOTONIC",
775 [CLOCK_MONOTONIC_RAW] = "CLOCK_MONOTONIC_RAW",
776 [CLOCK_REALTIME_COARSE] = "CLOCK_REALTIME_COARSE",
777 [CLOCK_MONOTONIC_COARSE] = "CLOCK_MONOTONIC_COARSE",
778 #ifdef CLOCK_BOOTTIME
779 [CLOCK_BOOTTIME] = "CLOCK_BOOTTIME",
780 #endif
781 };
782
783 if (clk_id < 0 || (unsigned)clk_id >= ARRAY_LENGTH(names))
784 return "unknown";
785
786 return names[clk_id];
787 }
788
789 static const struct {
790 uint32_t bit; /* enum weston_capability */
791 const char *desc;
792 } capability_strings[] = {
793 { WESTON_CAP_ROTATION_ANY, "arbitrary surface rotation:" },
794 { WESTON_CAP_CAPTURE_YFLIP, "screen capture uses y-flip:" },
795 };
796
797 static void
weston_compositor_log_capabilities(struct weston_compositor * compositor)798 weston_compositor_log_capabilities(struct weston_compositor *compositor)
799 {
800 unsigned i;
801 int yes;
802 struct timespec res;
803
804 weston_log("Compositor capabilities:\n");
805 for (i = 0; i < ARRAY_LENGTH(capability_strings); i++) {
806 yes = compositor->capabilities & capability_strings[i].bit;
807 weston_log_continue(STAMP_SPACE "%{public}s %{public}s\n",
808 capability_strings[i].desc,
809 yes ? "yes" : "no");
810 }
811
812 weston_log_continue(STAMP_SPACE "presentation clock: %{public}s, id %d\n",
813 clock_name(compositor->presentation_clock),
814 compositor->presentation_clock);
815
816 if (clock_getres(compositor->presentation_clock, &res) == 0)
817 weston_log_continue(STAMP_SPACE
818 "presentation clock resolution: %d.%09ld s\n",
819 (int)res.tv_sec, res.tv_nsec);
820 else
821 weston_log_continue(STAMP_SPACE
822 "presentation clock resolution: N/A\n");
823 }
824
825 static void
handle_primary_client_destroyed(struct wl_listener * listener,void * data)826 handle_primary_client_destroyed(struct wl_listener *listener, void *data)
827 {
828 struct wl_client *client = data;
829
830 weston_log("Primary client died. Closing...\n");
831
832 wl_display_terminate(wl_client_get_display(client));
833 }
834
835 static int
weston_create_listening_socket(struct wl_display * display,const char * socket_name)836 weston_create_listening_socket(struct wl_display *display, const char *socket_name)
837 {
838 if (socket_name) {
839 if (wl_display_add_socket(display, socket_name)) {
840 weston_log("fatal: failed to add socket: %{public}s\n",
841 strerror(errno));
842 return -1;
843 }
844 } else {
845 socket_name = wl_display_add_socket_auto(display);
846 if (!socket_name) {
847 weston_log("fatal: failed to add socket: %{public}s\n",
848 strerror(errno));
849 return -1;
850 }
851 }
852
853 setenv("WAYLAND_DISPLAY", socket_name, 1);
854
855 return 0;
856 }
857
858 WL_EXPORT void *
wet_load_module_entrypoint(const char * name,const char * entrypoint)859 wet_load_module_entrypoint(const char *name, const char *entrypoint)
860 {
861 char path[PATH_MAX];
862 void *module, *init;
863 size_t len;
864
865 if (name == NULL)
866 return NULL;
867
868 if (name[0] != '/') {
869 len = weston_module_path_from_env(name, path, sizeof path);
870 if (len == 0)
871 len = snprintf(path, sizeof path, "%s/%s", MODULEDIR,
872 name);
873 } else {
874 len = snprintf(path, sizeof path, "%s", name);
875 }
876
877 /* snprintf returns the length of the string it would've written,
878 * _excluding_ the NUL byte. So even being equal to the size of
879 * our buffer is an error here. */
880 if (len >= sizeof path)
881 return NULL;
882
883 module = dlopen(path, RTLD_NOW | RTLD_NOLOAD);
884 if (module) {
885 weston_log("Module '%{public}s' already loaded\n", path);
886 } else {
887 weston_log("Loading module '%{public}s'\n", path);
888 module = dlopen(path, RTLD_NOW);
889 if (!module) {
890 weston_log("Failed to load module: %{public}s\n", dlerror());
891 return NULL;
892 }
893 }
894
895 init = dlsym(module, entrypoint);
896 if (!init) {
897 weston_log("Failed to lookup init function: %{public}s\n", dlerror());
898 dlclose(module);
899 return NULL;
900 }
901
902 return init;
903 }
904
905 WL_EXPORT int
wet_load_module(struct weston_compositor * compositor,const char * name,int * argc,char * argv[])906 wet_load_module(struct weston_compositor *compositor,
907 const char *name, int *argc, char *argv[])
908 {
909 int (*module_init)(struct weston_compositor *ec,
910 int *argc, char *argv[]);
911
912 module_init = wet_load_module_entrypoint(name, "wet_module_init");
913 if (!module_init)
914 return -1;
915 if (module_init(compositor, argc, argv) < 0)
916 return -1;
917 return 0;
918 }
919
920 static int
wet_load_shell(struct weston_compositor * compositor,const char * name,int * argc,char * argv[])921 wet_load_shell(struct weston_compositor *compositor,
922 const char *name, int *argc, char *argv[])
923 {
924 int (*shell_init)(struct weston_compositor *ec,
925 int *argc, char *argv[]);
926
927 shell_init = wet_load_module_entrypoint(name, "wet_shell_init");
928 if (!shell_init)
929 return -1;
930 if (shell_init(compositor, argc, argv) < 0)
931 return -1;
932 return 0;
933 }
934
935 static char *
wet_get_binary_path(const char * name,const char * dir)936 wet_get_binary_path(const char *name, const char *dir)
937 {
938 char path[PATH_MAX];
939 size_t len;
940
941 len = weston_module_path_from_env(name, path, sizeof path);
942 if (len > 0)
943 return strdup(path);
944
945 len = snprintf(path, sizeof path, "%s/%s", dir, name);
946 if (len >= sizeof path)
947 return NULL;
948
949 return strdup(path);
950 }
951
952 WL_EXPORT char *
wet_get_libexec_path(const char * name)953 wet_get_libexec_path(const char *name)
954 {
955 return wet_get_binary_path(name, LIBEXECDIR);
956 }
957
958 WL_EXPORT char *
wet_get_bindir_path(const char * name)959 wet_get_bindir_path(const char *name)
960 {
961 return wet_get_binary_path(name, BINDIR);
962 }
963
964 static int
load_modules(struct weston_compositor * ec,const char * modules,int * argc,char * argv[],bool * xwayland)965 load_modules(struct weston_compositor *ec, const char *modules,
966 int *argc, char *argv[], bool *xwayland)
967 {
968 const char *p, *end;
969 char buffer[256];
970
971 if (modules == NULL)
972 return 0;
973
974 p = modules;
975 while (*p) {
976 end = strchrnul(p, ',');
977 snprintf(buffer, sizeof buffer, "%.*s", (int) (end - p), p);
978
979 if (strstr(buffer, "xwayland.so")) {
980 weston_log("Old Xwayland module loading detected: "
981 "Please use --xwayland command line option "
982 "or set xwayland=true in the [core] section "
983 "in weston.ini\n");
984 *xwayland = true;
985 } else {
986 if (wet_load_module(ec, buffer, argc, argv) < 0)
987 return -1;
988 }
989
990 p = end;
991 while (*p == ',')
992 p++;
993 }
994
995 return 0;
996 }
997
998 static int
save_touch_device_calibration(struct weston_compositor * compositor,struct weston_touch_device * device,const struct weston_touch_device_matrix * calibration)999 save_touch_device_calibration(struct weston_compositor *compositor,
1000 struct weston_touch_device *device,
1001 const struct weston_touch_device_matrix *calibration)
1002 {
1003 struct weston_config_section *s;
1004 struct weston_config *config = wet_get_config(compositor);
1005 char *helper = NULL;
1006 char *helper_cmd = NULL;
1007 int ret = -1;
1008 int status;
1009 const float *m = calibration->m;
1010
1011 s = weston_config_get_section(config,
1012 "libinput", NULL, NULL);
1013
1014 weston_config_section_get_string(s, "calibration_helper",
1015 &helper, NULL);
1016
1017 if (!helper || strlen(helper) == 0) {
1018 ret = 0;
1019 goto out;
1020 }
1021
1022 if (asprintf(&helper_cmd, "\"%s\" '%s' %f %f %f %f %f %f",
1023 helper, device->syspath,
1024 m[0], m[1], m[2],
1025 m[3], m[4], m[5]) < 0)
1026 goto out;
1027
1028 status = system(helper_cmd);
1029 free(helper_cmd);
1030
1031 if (status < 0) {
1032 weston_log("Error: failed to run calibration helper '%{public}s'.\n",
1033 helper);
1034 goto out;
1035 }
1036
1037 if (!WIFEXITED(status)) {
1038 weston_log("Error: calibration helper '%{public}s' possibly killed.\n",
1039 helper);
1040 goto out;
1041 }
1042
1043 if (WEXITSTATUS(status) == 0) {
1044 ret = 0;
1045 } else {
1046 weston_log("Calibration helper '%{public}s' exited with status %d.\n",
1047 helper, WEXITSTATUS(status));
1048 }
1049
1050 out:
1051 free(helper);
1052
1053 return ret;
1054 }
1055
1056 static int
weston_compositor_init_config(struct weston_compositor * ec,struct weston_config * config)1057 weston_compositor_init_config(struct weston_compositor *ec,
1058 struct weston_config *config)
1059 {
1060 struct xkb_rule_names xkb_names;
1061 struct weston_config_section *s;
1062 int repaint_msec;
1063 bool cal;
1064
1065 /* weston.ini [keyboard] */
1066 s = weston_config_get_section(config, "keyboard", NULL, NULL);
1067 weston_config_section_get_string(s, "keymap_rules",
1068 (char **) &xkb_names.rules, NULL);
1069 weston_config_section_get_string(s, "keymap_model",
1070 (char **) &xkb_names.model, NULL);
1071 weston_config_section_get_string(s, "keymap_layout",
1072 (char **) &xkb_names.layout, NULL);
1073 weston_config_section_get_string(s, "keymap_variant",
1074 (char **) &xkb_names.variant, NULL);
1075 weston_config_section_get_string(s, "keymap_options",
1076 (char **) &xkb_names.options, NULL);
1077
1078 if (weston_compositor_set_xkb_rule_names(ec, &xkb_names) < 0)
1079 return -1;
1080
1081 weston_config_section_get_int(s, "repeat-rate",
1082 &ec->kb_repeat_rate, 40);
1083 weston_config_section_get_int(s, "repeat-delay",
1084 &ec->kb_repeat_delay, 400);
1085
1086 weston_config_section_get_bool(s, "vt-switching",
1087 &ec->vt_switching, true);
1088
1089 /* weston.ini [core] */
1090 s = weston_config_get_section(config, "core", NULL, NULL);
1091 weston_config_section_get_int(s, "repaint-window", &repaint_msec,
1092 ec->repaint_msec);
1093 if (repaint_msec < -10 || repaint_msec > 1000) {
1094 weston_log("Invalid repaint_window value in config: %d\n",
1095 repaint_msec);
1096 } else {
1097 ec->repaint_msec = repaint_msec;
1098 }
1099 weston_log("Output repaint window is %d ms maximum.\n",
1100 ec->repaint_msec);
1101
1102 /* weston.ini [libinput] */
1103 s = weston_config_get_section(config, "libinput", NULL, NULL);
1104 weston_config_section_get_bool(s, "touchscreen_calibrator", &cal, 0);
1105 if (cal)
1106 weston_compositor_enable_touch_calibrator(ec,
1107 save_touch_device_calibration);
1108
1109 return 0;
1110 }
1111
1112 static char *
weston_choose_default_backend(void)1113 weston_choose_default_backend(void)
1114 {
1115 char *backend = NULL;
1116
1117 if (getenv("WAYLAND_DISPLAY") || getenv("WAYLAND_SOCKET"))
1118 backend = strdup("wayland-backend.so");
1119 else if (getenv("DISPLAY"))
1120 backend = strdup("x11-backend.so");
1121 else
1122 backend = strdup(WESTON_NATIVE_BACKEND);
1123
1124 return backend;
1125 }
1126
1127 static const struct { const char *name; uint32_t token; } transforms[] = {
1128 { "normal", WL_OUTPUT_TRANSFORM_NORMAL },
1129 { "rotate-90", WL_OUTPUT_TRANSFORM_90 },
1130 { "rotate-180", WL_OUTPUT_TRANSFORM_180 },
1131 { "rotate-270", WL_OUTPUT_TRANSFORM_270 },
1132 { "flipped", WL_OUTPUT_TRANSFORM_FLIPPED },
1133 { "flipped-rotate-90", WL_OUTPUT_TRANSFORM_FLIPPED_90 },
1134 { "flipped-rotate-180", WL_OUTPUT_TRANSFORM_FLIPPED_180 },
1135 { "flipped-rotate-270", WL_OUTPUT_TRANSFORM_FLIPPED_270 },
1136 };
1137
1138 WL_EXPORT int
weston_parse_transform(const char * transform,uint32_t * out)1139 weston_parse_transform(const char *transform, uint32_t *out)
1140 {
1141 unsigned int i;
1142
1143 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
1144 if (strcmp(transforms[i].name, transform) == 0) {
1145 *out = transforms[i].token;
1146 return 0;
1147 }
1148
1149 *out = WL_OUTPUT_TRANSFORM_NORMAL;
1150 return -1;
1151 }
1152
1153 WL_EXPORT const char *
weston_transform_to_string(uint32_t output_transform)1154 weston_transform_to_string(uint32_t output_transform)
1155 {
1156 unsigned int i;
1157
1158 for (i = 0; i < ARRAY_LENGTH(transforms); i++)
1159 if (transforms[i].token == output_transform)
1160 return transforms[i].name;
1161
1162 return "<illegal value>";
1163 }
1164
1165 static int
load_configuration(struct weston_config ** config,int32_t noconfig,const char * config_file)1166 load_configuration(struct weston_config **config, int32_t noconfig,
1167 const char *config_file)
1168 {
1169 const char *file = "weston.ini";
1170 const char *full_path;
1171
1172 *config = NULL;
1173
1174 if (config_file)
1175 file = config_file;
1176
1177 if (noconfig == 0)
1178 *config = weston_config_parse(file);
1179
1180 if (*config) {
1181 full_path = weston_config_get_full_path(*config);
1182
1183 weston_log("Using config file '%{public}s'\n", full_path);
1184 setenv(WESTON_CONFIG_FILE_ENV_VAR, full_path, 1);
1185
1186 return 0;
1187 }
1188
1189 if (config_file && noconfig == 0) {
1190 weston_log("fatal: error opening or reading config file"
1191 " '%{public}s'.\n", config_file);
1192
1193 return -1;
1194 }
1195
1196 weston_log("Starting with no config file.\n");
1197 setenv(WESTON_CONFIG_FILE_ENV_VAR, "", 1);
1198
1199 return 0;
1200 }
1201
1202 static void
handle_exit(struct weston_compositor * c)1203 handle_exit(struct weston_compositor *c)
1204 {
1205 wl_display_terminate(c->wl_display);
1206 }
1207
1208 static void
wet_output_set_scale(struct weston_output * output,struct weston_config_section * section,int32_t default_scale,int32_t parsed_scale)1209 wet_output_set_scale(struct weston_output *output,
1210 struct weston_config_section *section,
1211 int32_t default_scale,
1212 int32_t parsed_scale)
1213 {
1214 int32_t scale = default_scale;
1215
1216 if (section)
1217 weston_config_section_get_int(section, "scale", &scale, default_scale);
1218
1219 if (parsed_scale)
1220 scale = parsed_scale;
1221
1222 weston_output_set_scale(output, scale);
1223 }
1224
1225 /* UINT32_MAX is treated as invalid because 0 is a valid
1226 * enumeration value and the parameter is unsigned
1227 */
1228 static int
wet_output_set_transform(struct weston_output * output,struct weston_config_section * section,uint32_t default_transform,uint32_t parsed_transform)1229 wet_output_set_transform(struct weston_output *output,
1230 struct weston_config_section *section,
1231 uint32_t default_transform,
1232 uint32_t parsed_transform)
1233 {
1234 char *t = NULL;
1235 uint32_t transform = default_transform;
1236
1237 if (section) {
1238 weston_config_section_get_string(section,
1239 "transform", &t, NULL);
1240 }
1241
1242 if (t) {
1243 if (weston_parse_transform(t, &transform) < 0) {
1244 weston_log("Invalid transform \"%{public}s\" for output %{public}s\n",
1245 t, output->name);
1246 return -1;
1247 }
1248 free(t);
1249 }
1250
1251 if (parsed_transform != UINT32_MAX)
1252 transform = parsed_transform;
1253
1254 weston_output_set_transform(output, transform);
1255
1256 return 0;
1257 }
1258
1259 static void
allow_content_protection(struct weston_output * output,struct weston_config_section * section)1260 allow_content_protection(struct weston_output *output,
1261 struct weston_config_section *section)
1262 {
1263 bool allow_hdcp = true;
1264
1265 if (section)
1266 weston_config_section_get_bool(section, "allow_hdcp",
1267 &allow_hdcp, true);
1268
1269 weston_output_allow_protection(output, allow_hdcp);
1270 }
1271
1272 static int
wet_configure_windowed_output_from_config(struct weston_output * output,struct wet_output_config * defaults)1273 wet_configure_windowed_output_from_config(struct weston_output *output,
1274 struct wet_output_config *defaults)
1275 {
1276 LOG_ENTER();
1277 const struct weston_windowed_output_api *api =
1278 weston_windowed_output_get_api(output->compositor);
1279
1280 struct weston_config *wc = wet_get_config(output->compositor);
1281 struct weston_config_section *section = NULL;
1282 struct wet_compositor *compositor = to_wet_compositor(output->compositor);
1283 struct wet_output_config *parsed_options = compositor->parsed_options;
1284 int width = defaults->width;
1285 int height = defaults->height;
1286
1287 assert(parsed_options);
1288
1289 if (!api) {
1290 weston_log("Cannot use weston_windowed_output_api.\n");
1291 LOG_EXIT();
1292 return -1;
1293 }
1294
1295 section = weston_config_get_section(wc, "output", "name", output->name);
1296
1297 if (section) {
1298 char *mode;
1299
1300 weston_config_section_get_string(section, "mode", &mode, NULL);
1301 if (!mode || sscanf(mode, "%dx%d", &width,
1302 &height) != 2) {
1303 weston_log("Invalid mode for output %{public}s. Using defaults.\n",
1304 output->name);
1305 width = defaults->width;
1306 height = defaults->height;
1307 }
1308 free(mode);
1309 }
1310
1311 allow_content_protection(output, section);
1312
1313 if (parsed_options->width)
1314 width = parsed_options->width;
1315
1316 if (parsed_options->height)
1317 height = parsed_options->height;
1318
1319 wet_output_set_scale(output, section, defaults->scale, parsed_options->scale);
1320 if (wet_output_set_transform(output, section, defaults->transform,
1321 parsed_options->transform) < 0) {
1322 LOG_EXIT();
1323 return -1;
1324 }
1325
1326 if (api->output_set_size(output, width, height) < 0) {
1327 weston_log("Cannot configure output \"%{public}s\" using weston_windowed_output_api.\n",
1328 output->name);
1329 return -1;
1330 }
1331
1332 LOG_EXIT();
1333 return 0;
1334 }
1335
1336 static int
count_remaining_heads(struct weston_output * output,struct weston_head * to_go)1337 count_remaining_heads(struct weston_output *output, struct weston_head *to_go)
1338 {
1339 struct weston_head *iter = NULL;
1340 int n = 0;
1341
1342 while ((iter = weston_output_iterate_heads(output, iter))) {
1343 if (iter != to_go)
1344 n++;
1345 }
1346
1347 return n;
1348 }
1349
1350 static void
wet_head_tracker_destroy(struct wet_head_tracker * track)1351 wet_head_tracker_destroy(struct wet_head_tracker *track)
1352 {
1353 wl_list_remove(&track->head_destroy_listener.link);
1354 free(track);
1355 }
1356
1357 static void
handle_head_destroy(struct wl_listener * listener,void * data)1358 handle_head_destroy(struct wl_listener *listener, void *data)
1359 {
1360 struct weston_head *head = data;
1361 struct weston_output *output;
1362 struct wet_head_tracker *track =
1363 container_of(listener, struct wet_head_tracker,
1364 head_destroy_listener);
1365
1366 wet_head_tracker_destroy(track);
1367
1368 output = weston_head_get_output(head);
1369
1370 /* On shutdown path, the output might be already gone. */
1371 if (!output)
1372 return;
1373
1374 if (count_remaining_heads(output, head) > 0)
1375 return;
1376
1377 weston_output_destroy(output);
1378 }
1379
1380 static struct wet_head_tracker *
wet_head_tracker_from_head(struct weston_head * head)1381 wet_head_tracker_from_head(struct weston_head *head)
1382 {
1383 struct wl_listener *lis;
1384
1385 lis = weston_head_get_destroy_listener(head, handle_head_destroy);
1386 if (!lis)
1387 return NULL;
1388
1389 return container_of(lis, struct wet_head_tracker,
1390 head_destroy_listener);
1391 }
1392
1393 /* Listen for head destroy signal.
1394 *
1395 * If a head is destroyed and it was the last head on the output, we
1396 * destroy the associated output.
1397 *
1398 * Do not bother destroying the head trackers on shutdown, the backend will
1399 * destroy the heads which calls our handler to destroy the trackers.
1400 */
1401 static void
wet_head_tracker_create(struct wet_compositor * compositor,struct weston_head * head)1402 wet_head_tracker_create(struct wet_compositor *compositor,
1403 struct weston_head *head)
1404 {
1405 struct wet_head_tracker *track;
1406
1407 track = zalloc(sizeof *track);
1408 if (!track)
1409 return;
1410
1411 track->head_destroy_listener.notify = handle_head_destroy;
1412 weston_head_add_destroy_listener(head, &track->head_destroy_listener);
1413 }
1414
1415 static void
simple_head_enable(struct wet_compositor * wet,struct weston_head * head)1416 simple_head_enable(struct wet_compositor *wet, struct weston_head *head)
1417 {
1418 struct weston_output *output;
1419 int ret = 0;
1420
1421 output = weston_compositor_create_output_with_head(wet->compositor,
1422 head);
1423 if (!output) {
1424 weston_log("Could not create an output for head \"%{public}s\".\n",
1425 weston_head_get_name(head));
1426 wet->init_failed = true;
1427
1428 return;
1429 }
1430
1431 if (wet->simple_output_configure)
1432 ret = wet->simple_output_configure(output);
1433 if (ret < 0) {
1434 weston_log("Cannot configure output \"%{public}s\".\n",
1435 weston_head_get_name(head));
1436 weston_output_destroy(output);
1437 wet->init_failed = true;
1438
1439 return;
1440 }
1441
1442 if (weston_output_enable(output) < 0) {
1443 weston_log("Enabling output \"%{public}s\" failed.\n",
1444 weston_head_get_name(head));
1445 weston_output_destroy(output);
1446 wet->init_failed = true;
1447
1448 return;
1449 }
1450
1451 wet_head_tracker_create(wet, head);
1452
1453 /* The weston_compositor will track and destroy the output on exit. */
1454 }
1455
1456 static void
simple_head_disable(struct weston_head * head)1457 simple_head_disable(struct weston_head *head)
1458 {
1459 struct weston_output *output;
1460 struct wet_head_tracker *track;
1461
1462 track = wet_head_tracker_from_head(head);
1463 if (track)
1464 wet_head_tracker_destroy(track);
1465
1466 output = weston_head_get_output(head);
1467 assert(output);
1468 weston_output_destroy(output);
1469 }
1470
1471 static void
simple_heads_changed(struct wl_listener * listener,void * arg)1472 simple_heads_changed(struct wl_listener *listener, void *arg)
1473 {
1474 LOG_ENTER();
1475 struct weston_compositor *compositor = arg;
1476 struct wet_compositor *wet = to_wet_compositor(compositor);
1477 struct weston_head *head = NULL;
1478 bool connected;
1479 bool enabled;
1480 bool changed;
1481 bool non_desktop;
1482
1483 while ((head = weston_compositor_iterate_heads(wet->compositor, head))) {
1484 connected = weston_head_is_connected(head);
1485 enabled = weston_head_is_enabled(head);
1486 changed = weston_head_is_device_changed(head);
1487 non_desktop = weston_head_is_non_desktop(head);
1488
1489 if (connected && !enabled && !non_desktop) {
1490 simple_head_enable(wet, head);
1491 } else if (!connected && enabled) {
1492 simple_head_disable(head);
1493 } else if (enabled && changed) {
1494 weston_log("Detected a monitor change on head '%{public}s', "
1495 "not bothering to do anything about it.\n",
1496 weston_head_get_name(head));
1497 }
1498 weston_head_reset_device_changed(head);
1499 }
1500 LOG_EXIT();
1501 }
1502
1503 static void
wet_set_simple_head_configurator(struct weston_compositor * compositor,int (* fn)(struct weston_output *))1504 wet_set_simple_head_configurator(struct weston_compositor *compositor,
1505 int (*fn)(struct weston_output *))
1506 {
1507 struct wet_compositor *wet = to_wet_compositor(compositor);
1508
1509 wet->simple_output_configure = fn;
1510
1511 wet->heads_changed_listener.notify = simple_heads_changed;
1512 weston_compositor_add_heads_changed_listener(compositor,
1513 &wet->heads_changed_listener);
1514 }
1515
1516 static void
configure_input_device_accel(struct weston_config_section * s,struct libinput_device * device)1517 configure_input_device_accel(struct weston_config_section *s,
1518 struct libinput_device *device)
1519 {
1520 char *profile_string = NULL;
1521 int is_a_profile = 1;
1522 uint32_t profiles;
1523 enum libinput_config_accel_profile profile;
1524 double speed;
1525
1526 if (weston_config_section_get_string(s, "accel-profile",
1527 &profile_string, NULL) == 0) {
1528 if (strcmp(profile_string, "flat") == 0)
1529 profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT;
1530 else if (strcmp(profile_string, "adaptive") == 0)
1531 profile = LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE;
1532 else {
1533 weston_log("warning: no such accel-profile: %{public}s\n",
1534 profile_string);
1535 is_a_profile = 0;
1536 }
1537
1538 profiles = libinput_device_config_accel_get_profiles(device);
1539 if (is_a_profile && (profile & profiles) != 0) {
1540 weston_log(" accel-profile=%{public}s\n",
1541 profile_string);
1542 libinput_device_config_accel_set_profile(device,
1543 profile);
1544 }
1545 }
1546
1547 if (weston_config_section_get_double(s, "accel-speed",
1548 &speed, 0) == 0 &&
1549 speed >= -1. && speed <= 1.) {
1550 weston_log(" accel-speed=%.3f\n", speed);
1551 libinput_device_config_accel_set_speed(device, speed);
1552 }
1553
1554 free(profile_string);
1555 }
1556
1557 static void
configure_input_device_scroll(struct weston_config_section * s,struct libinput_device * device)1558 configure_input_device_scroll(struct weston_config_section *s,
1559 struct libinput_device *device)
1560 {
1561 bool natural;
1562 char *method_string = NULL;
1563 uint32_t methods;
1564 enum libinput_config_scroll_method method;
1565 char *button_string = NULL;
1566 int button;
1567
1568 if (libinput_device_config_scroll_has_natural_scroll(device) &&
1569 weston_config_section_get_bool(s, "natural-scroll",
1570 &natural, false) == 0) {
1571 weston_log(" natural-scroll=%{public}s\n",
1572 natural ? "true" : "false");
1573 libinput_device_config_scroll_set_natural_scroll_enabled(
1574 device, natural);
1575 }
1576
1577 if (weston_config_section_get_string(s, "scroll-method",
1578 &method_string, NULL) != 0)
1579 goto done;
1580 if (strcmp(method_string, "two-finger") == 0)
1581 method = LIBINPUT_CONFIG_SCROLL_2FG;
1582 else if (strcmp(method_string, "edge") == 0)
1583 method = LIBINPUT_CONFIG_SCROLL_EDGE;
1584 else if (strcmp(method_string, "button") == 0)
1585 method = LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN;
1586 else if (strcmp(method_string, "none") == 0)
1587 method = LIBINPUT_CONFIG_SCROLL_NO_SCROLL;
1588 else {
1589 weston_log("warning: no such scroll-method: %{public}s\n",
1590 method_string);
1591 goto done;
1592 }
1593
1594 methods = libinput_device_config_scroll_get_methods(device);
1595 if (method != LIBINPUT_CONFIG_SCROLL_NO_SCROLL &&
1596 (method & methods) == 0)
1597 goto done;
1598
1599 weston_log(" scroll-method=%{public}s\n", method_string);
1600 libinput_device_config_scroll_set_method(device, method);
1601
1602 if (method == LIBINPUT_CONFIG_SCROLL_ON_BUTTON_DOWN) {
1603 if (weston_config_section_get_string(s, "scroll-button",
1604 &button_string,
1605 NULL) != 0)
1606 goto done;
1607
1608 button = libevdev_event_code_from_name(EV_KEY, button_string);
1609 if (button == -1) {
1610 weston_log(" Bad scroll-button: %{public}s\n",
1611 button_string);
1612 goto done;
1613 }
1614
1615 weston_log(" scroll-button=%{public}s\n", button_string);
1616 libinput_device_config_scroll_set_button(device, button);
1617 }
1618
1619 done:
1620 free(method_string);
1621 free(button_string);
1622 }
1623
1624 static void
configure_input_device(struct weston_compositor * compositor,struct libinput_device * device)1625 configure_input_device(struct weston_compositor *compositor,
1626 struct libinput_device *device)
1627 {
1628 struct weston_config_section *s;
1629 struct weston_config *config = wet_get_config(compositor);
1630 bool has_enable_tap = false;
1631 bool enable_tap;
1632 bool disable_while_typing;
1633 bool middle_emulation;
1634 bool tap_and_drag;
1635 bool tap_and_drag_lock;
1636 bool left_handed;
1637 unsigned int rotation;
1638
1639 weston_log("libinput: configuring device \"%{public}s\".\n",
1640 libinput_device_get_name(device));
1641
1642 s = weston_config_get_section(config,
1643 "libinput", NULL, NULL);
1644
1645 if (libinput_device_config_tap_get_finger_count(device) > 0) {
1646 if (weston_config_section_get_bool(s, "enable_tap",
1647 &enable_tap, false) == 0) {
1648 weston_log("!!DEPRECATION WARNING!!: In weston.ini, "
1649 "enable_tap is deprecated in favour of "
1650 "enable-tap. Support for it may be removed "
1651 "at any time!");
1652 has_enable_tap = true;
1653 }
1654 if (weston_config_section_get_bool(s, "enable-tap",
1655 &enable_tap, false) == 0)
1656 has_enable_tap = true;
1657 if (has_enable_tap) {
1658 weston_log(" enable-tap=%{public}s.\n",
1659 enable_tap ? "true" : "false");
1660 libinput_device_config_tap_set_enabled(device,
1661 enable_tap);
1662 }
1663 if (weston_config_section_get_bool(s, "tap-and-drag",
1664 &tap_and_drag, false) == 0) {
1665 weston_log(" tap-and-drag=%{public}s.\n",
1666 tap_and_drag ? "true" : "false");
1667 libinput_device_config_tap_set_drag_enabled(device,
1668 tap_and_drag);
1669 }
1670 if (weston_config_section_get_bool(s, "tap-and-drag-lock",
1671 &tap_and_drag_lock, false) == 0) {
1672 weston_log(" tap-and-drag-lock=%{public}s.\n",
1673 tap_and_drag_lock ? "true" : "false");
1674 libinput_device_config_tap_set_drag_lock_enabled(
1675 device, tap_and_drag_lock);
1676 }
1677 }
1678
1679 if (libinput_device_config_dwt_is_available(device) &&
1680 weston_config_section_get_bool(s, "disable-while-typing",
1681 &disable_while_typing, false) == 0) {
1682 weston_log(" disable-while-typing=%{public}s.\n",
1683 disable_while_typing ? "true" : "false");
1684 libinput_device_config_dwt_set_enabled(device,
1685 disable_while_typing);
1686 }
1687
1688 if (libinput_device_config_middle_emulation_is_available(device) &&
1689 weston_config_section_get_bool(s, "middle-button-emulation",
1690 &middle_emulation, false) == 0) {
1691 weston_log(" middle-button-emulation=%{public}s\n",
1692 middle_emulation ? "true" : "false");
1693 libinput_device_config_middle_emulation_set_enabled(
1694 device, middle_emulation);
1695 }
1696
1697 if (libinput_device_config_left_handed_is_available(device) &&
1698 weston_config_section_get_bool(s, "left-handed",
1699 &left_handed, false) == 0) {
1700 weston_log(" left-handed=%{public}s\n",
1701 left_handed ? "true" : "false");
1702 libinput_device_config_left_handed_set(device, left_handed);
1703 }
1704
1705 if (libinput_device_config_rotation_is_available(device) &&
1706 weston_config_section_get_uint(s, "rotation",
1707 &rotation, false) == 0) {
1708 weston_log(" rotation=%u\n", rotation);
1709 libinput_device_config_rotation_set_angle(device, rotation);
1710 }
1711
1712 if (libinput_device_config_accel_is_available(device))
1713 configure_input_device_accel(s, device);
1714
1715 configure_input_device_scroll(s, device);
1716 }
1717
1718 static int
drm_backend_output_configure(struct weston_output * output,struct weston_config_section * section)1719 drm_backend_output_configure(struct weston_output *output,
1720 struct weston_config_section *section)
1721 {
1722 struct wet_compositor *wet = to_wet_compositor(output->compositor);
1723 const struct weston_drm_output_api *api;
1724 enum weston_drm_backend_output_mode mode =
1725 WESTON_DRM_BACKEND_OUTPUT_PREFERRED;
1726 uint32_t transform = WL_OUTPUT_TRANSFORM_NORMAL;
1727 char *s;
1728 char *modeline = NULL;
1729 char *gbm_format = NULL;
1730 char *seat = NULL;
1731
1732 api = weston_drm_output_get_api(output->compositor);
1733 if (!api) {
1734 weston_log("Cannot use weston_drm_output_api.\n");
1735 return -1;
1736 }
1737
1738 weston_config_section_get_string(section, "mode", &s, "preferred");
1739
1740 if (strcmp(s, "off") == 0) {
1741 assert(0 && "off was supposed to be pruned");
1742 return -1;
1743 } else if (wet->drm_use_current_mode || strcmp(s, "current") == 0) {
1744 mode = WESTON_DRM_BACKEND_OUTPUT_CURRENT;
1745 } else if (strcmp(s, "preferred") != 0) {
1746 modeline = s;
1747 s = NULL;
1748 }
1749 free(s);
1750
1751 if (api->set_mode(output, mode, modeline) < 0) {
1752 weston_log("Cannot configure an output using weston_drm_output_api.\n");
1753 free(modeline);
1754 return -1;
1755 }
1756 free(modeline);
1757
1758 if (count_remaining_heads(output, NULL) == 1) {
1759 struct weston_head *head = weston_output_get_first_head(output);
1760 transform = weston_head_get_transform(head);
1761 }
1762
1763 wet_output_set_scale(output, section, 1, 0);
1764 if (wet_output_set_transform(output, section, transform,
1765 UINT32_MAX) < 0) {
1766 return -1;
1767 }
1768
1769 weston_config_section_get_string(section,
1770 "gbm-format", &gbm_format, NULL);
1771
1772 api->set_gbm_format(output, gbm_format);
1773 free(gbm_format);
1774
1775 weston_config_section_get_string(section, "seat", &seat, "");
1776
1777 api->set_seat(output, seat);
1778 free(seat);
1779
1780 allow_content_protection(output, section);
1781
1782 return 0;
1783 }
1784
1785 /* Find the output section to use for configuring the output with the
1786 * named head. If an output section with the given name contains
1787 * a "same-as" key, ignore all other settings in the output section and
1788 * instead find an output section named by the "same-as". Do this
1789 * recursively.
1790 */
1791 static struct weston_config_section *
drm_config_find_controlling_output_section(struct weston_config * config,const char * head_name)1792 drm_config_find_controlling_output_section(struct weston_config *config,
1793 const char *head_name)
1794 {
1795 struct weston_config_section *section;
1796 char *same_as;
1797 int depth = 0;
1798
1799 same_as = strdup(head_name);
1800 do {
1801 section = weston_config_get_section(config, "output",
1802 "name", same_as);
1803 if (!section && depth > 0)
1804 weston_log("Configuration error: "
1805 "output section referred to with "
1806 "'same-as=%{public}s' not found.\n", same_as);
1807
1808 free(same_as);
1809
1810 if (!section)
1811 return NULL;
1812
1813 if (++depth > 10) {
1814 weston_log("Configuration error: "
1815 "'same-as' nested too deep for output '%{public}s'.\n",
1816 head_name);
1817 return NULL;
1818 }
1819
1820 weston_config_section_get_string(section, "same-as",
1821 &same_as, NULL);
1822 } while (same_as);
1823
1824 return section;
1825 }
1826
1827 static struct wet_layoutput *
wet_compositor_create_layoutput(struct wet_compositor * compositor,const char * name,struct weston_config_section * section)1828 wet_compositor_create_layoutput(struct wet_compositor *compositor,
1829 const char *name,
1830 struct weston_config_section *section)
1831 {
1832 struct wet_layoutput *lo;
1833
1834 lo = zalloc(sizeof *lo);
1835 if (!lo)
1836 return NULL;
1837
1838 lo->compositor = compositor;
1839 wl_list_insert(compositor->layoutput_list.prev, &lo->compositor_link);
1840 wl_list_init(&lo->output_list);
1841 lo->name = strdup(name);
1842 lo->section = section;
1843
1844 return lo;
1845 }
1846
1847 static void
wet_layoutput_destroy(struct wet_layoutput * lo)1848 wet_layoutput_destroy(struct wet_layoutput *lo)
1849 {
1850 wl_list_remove(&lo->compositor_link);
1851 assert(wl_list_empty(&lo->output_list));
1852 free(lo->name);
1853 free(lo);
1854 }
1855
1856 static void
wet_output_handle_destroy(struct wl_listener * listener,void * data)1857 wet_output_handle_destroy(struct wl_listener *listener, void *data)
1858 {
1859 struct wet_output *output;
1860
1861 output = wl_container_of(listener, output, output_destroy_listener);
1862 assert(output->output == data);
1863
1864 output->output = NULL;
1865 wl_list_remove(&output->output_destroy_listener.link);
1866 }
1867
1868 static struct wet_output *
wet_layoutput_create_output(struct wet_layoutput * lo,const char * name)1869 wet_layoutput_create_output(struct wet_layoutput *lo, const char *name)
1870 {
1871 struct wet_output *output;
1872
1873 output = zalloc(sizeof *output);
1874 if (!output)
1875 return NULL;
1876
1877 output->output =
1878 weston_compositor_create_output(lo->compositor->compositor,
1879 name);
1880 if (!output->output) {
1881 free(output);
1882 return NULL;
1883 }
1884
1885 output->layoutput = lo;
1886 wl_list_insert(lo->output_list.prev, &output->link);
1887 output->output_destroy_listener.notify = wet_output_handle_destroy;
1888 weston_output_add_destroy_listener(output->output,
1889 &output->output_destroy_listener);
1890
1891 return output;
1892 }
1893
1894 static struct wet_output *
wet_output_from_weston_output(struct weston_output * base)1895 wet_output_from_weston_output(struct weston_output *base)
1896 {
1897 struct wl_listener *lis;
1898
1899 lis = weston_output_get_destroy_listener(base,
1900 wet_output_handle_destroy);
1901 if (!lis)
1902 return NULL;
1903
1904 return container_of(lis, struct wet_output, output_destroy_listener);
1905 }
1906
1907 static void
wet_output_destroy(struct wet_output * output)1908 wet_output_destroy(struct wet_output *output)
1909 {
1910 if (output->output) {
1911 /* output->output destruction may be deferred in some cases (see
1912 * drm_output_destroy()), so we need to forcibly trigger the
1913 * destruction callback now, or otherwise would later access
1914 * data that we are about to free
1915 */
1916 struct weston_output *save = output->output;
1917 wet_output_handle_destroy(&output->output_destroy_listener, save);
1918 weston_output_destroy(save);
1919 }
1920
1921 wl_list_remove(&output->link);
1922 free(output);
1923 }
1924
1925 static struct wet_layoutput *
wet_compositor_find_layoutput(struct wet_compositor * wet,const char * name)1926 wet_compositor_find_layoutput(struct wet_compositor *wet, const char *name)
1927 {
1928 struct wet_layoutput *lo;
1929
1930 wl_list_for_each(lo, &wet->layoutput_list, compositor_link)
1931 if (strcmp(lo->name, name) == 0)
1932 return lo;
1933
1934 return NULL;
1935 }
1936
1937 static void
wet_compositor_layoutput_add_head(struct wet_compositor * wet,const char * output_name,struct weston_config_section * section,struct weston_head * head)1938 wet_compositor_layoutput_add_head(struct wet_compositor *wet,
1939 const char *output_name,
1940 struct weston_config_section *section,
1941 struct weston_head *head)
1942 {
1943 struct wet_layoutput *lo;
1944
1945 lo = wet_compositor_find_layoutput(wet, output_name);
1946 if (!lo) {
1947 lo = wet_compositor_create_layoutput(wet, output_name, section);
1948 if (!lo)
1949 return;
1950 }
1951
1952 if (lo->add.n + 1 >= ARRAY_LENGTH(lo->add.heads))
1953 return;
1954
1955 lo->add.heads[lo->add.n++] = head;
1956 }
1957
1958 static void
wet_compositor_destroy_layout(struct wet_compositor * wet)1959 wet_compositor_destroy_layout(struct wet_compositor *wet)
1960 {
1961 struct wet_layoutput *lo, *lo_tmp;
1962 struct wet_output *output, *output_tmp;
1963
1964 wl_list_for_each_safe(lo, lo_tmp,
1965 &wet->layoutput_list, compositor_link) {
1966 wl_list_for_each_safe(output, output_tmp,
1967 &lo->output_list, link) {
1968 wet_output_destroy(output);
1969 }
1970 wet_layoutput_destroy(lo);
1971 }
1972 }
1973
1974 static void
drm_head_prepare_enable(struct wet_compositor * wet,struct weston_head * head)1975 drm_head_prepare_enable(struct wet_compositor *wet,
1976 struct weston_head *head)
1977 {
1978 const char *name = weston_head_get_name(head);
1979 struct weston_config_section *section;
1980 char *output_name = NULL;
1981 char *mode = NULL;
1982
1983 section = drm_config_find_controlling_output_section(wet->config, name);
1984 if (section) {
1985 /* skip outputs that are explicitly off, or non-desktop and not
1986 * explicitly enabled. The backend turns them off automatically.
1987 */
1988 weston_config_section_get_string(section, "mode", &mode, NULL);
1989 if (mode && strcmp(mode, "off") == 0) {
1990 free(mode);
1991 return;
1992 }
1993 if (!mode && weston_head_is_non_desktop(head))
1994 return;
1995 free(mode);
1996
1997 weston_config_section_get_string(section, "name",
1998 &output_name, NULL);
1999 assert(output_name);
2000
2001 wet_compositor_layoutput_add_head(wet, output_name,
2002 section, head);
2003 free(output_name);
2004 } else {
2005 wet_compositor_layoutput_add_head(wet, name, NULL, head);
2006 }
2007 }
2008
2009 static bool
drm_head_should_force_enable(struct wet_compositor * wet,struct weston_head * head)2010 drm_head_should_force_enable(struct wet_compositor *wet,
2011 struct weston_head *head)
2012 {
2013 const char *name = weston_head_get_name(head);
2014 struct weston_config_section *section;
2015 bool force;
2016
2017 section = drm_config_find_controlling_output_section(wet->config, name);
2018 if (!section)
2019 return false;
2020
2021 weston_config_section_get_bool(section, "force-on", &force, false);
2022 return force;
2023 }
2024
2025 static void
drm_try_attach(struct weston_output * output,struct wet_head_array * add,struct wet_head_array * failed)2026 drm_try_attach(struct weston_output *output,
2027 struct wet_head_array *add,
2028 struct wet_head_array *failed)
2029 {
2030 unsigned i;
2031
2032 /* try to attach all heads, this probably succeeds */
2033 for (i = 0; i < add->n; i++) {
2034 if (!add->heads[i])
2035 continue;
2036
2037 if (weston_output_attach_head(output, add->heads[i]) < 0) {
2038 assert(failed->n < ARRAY_LENGTH(failed->heads));
2039
2040 failed->heads[failed->n++] = add->heads[i];
2041 add->heads[i] = NULL;
2042 }
2043 }
2044 }
2045
2046 static int
drm_try_enable(struct weston_output * output,struct wet_head_array * undo,struct wet_head_array * failed)2047 drm_try_enable(struct weston_output *output,
2048 struct wet_head_array *undo,
2049 struct wet_head_array *failed)
2050 {
2051 /* Try to enable, and detach heads one by one until it succeeds. */
2052 while (!output->enabled) {
2053 if (weston_output_enable(output) == 0)
2054 return 0;
2055
2056 /* the next head to drop */
2057 while (undo->n > 0 && undo->heads[--undo->n] == NULL)
2058 ;
2059
2060 /* No heads left to undo and failed to enable. */
2061 if (undo->heads[undo->n] == NULL)
2062 return -1;
2063
2064 assert(failed->n < ARRAY_LENGTH(failed->heads));
2065
2066 /* undo one head */
2067 weston_head_detach(undo->heads[undo->n]);
2068 failed->heads[failed->n++] = undo->heads[undo->n];
2069 undo->heads[undo->n] = NULL;
2070 }
2071
2072 return 0;
2073 }
2074
2075 static int
drm_try_attach_enable(struct weston_output * output,struct wet_layoutput * lo)2076 drm_try_attach_enable(struct weston_output *output, struct wet_layoutput *lo)
2077 {
2078 struct wet_head_array failed = {};
2079 unsigned i;
2080
2081 assert(!output->enabled);
2082
2083 drm_try_attach(output, &lo->add, &failed);
2084 if (drm_backend_output_configure(output, lo->section) < 0)
2085 return -1;
2086
2087 if (drm_try_enable(output, &lo->add, &failed) < 0)
2088 return -1;
2089
2090 /* For all successfully attached/enabled heads */
2091 for (i = 0; i < lo->add.n; i++)
2092 if (lo->add.heads[i])
2093 wet_head_tracker_create(lo->compositor,
2094 lo->add.heads[i]);
2095
2096 /* Push failed heads to the next round. */
2097 lo->add = failed;
2098
2099 return 0;
2100 }
2101
2102 static int
drm_process_layoutput(struct wet_compositor * wet,struct wet_layoutput * lo)2103 drm_process_layoutput(struct wet_compositor *wet, struct wet_layoutput *lo)
2104 {
2105 struct wet_output *output, *tmp;
2106 char *name = NULL;
2107 int ret;
2108
2109 /*
2110 * For each existing wet_output:
2111 * try attach
2112 * While heads left to enable:
2113 * Create output
2114 * try attach, try enable
2115 */
2116
2117 wl_list_for_each_safe(output, tmp, &lo->output_list, link) {
2118 struct wet_head_array failed = {};
2119
2120 if (!output->output) {
2121 /* Clean up left-overs from destroyed heads. */
2122 wet_output_destroy(output);
2123 continue;
2124 }
2125
2126 assert(output->output->enabled);
2127
2128 drm_try_attach(output->output, &lo->add, &failed);
2129 lo->add = failed;
2130 if (lo->add.n == 0)
2131 return 0;
2132 }
2133
2134 if (!weston_compositor_find_output_by_name(wet->compositor, lo->name))
2135 name = strdup(lo->name);
2136
2137 while (lo->add.n > 0) {
2138 if (!wl_list_empty(&lo->output_list)) {
2139 weston_log("Error: independent-CRTC clone mode is not implemented.\n");
2140 return -1;
2141 }
2142
2143 if (!name) {
2144 ret = asprintf(&name, "%s:%s", lo->name,
2145 weston_head_get_name(lo->add.heads[0]));
2146 if (ret < 0)
2147 return -1;
2148 }
2149 output = wet_layoutput_create_output(lo, name);
2150 free(name);
2151 name = NULL;
2152
2153 if (!output)
2154 return -1;
2155
2156 if (drm_try_attach_enable(output->output, lo) < 0) {
2157 wet_output_destroy(output);
2158 return -1;
2159 }
2160 }
2161
2162 return 0;
2163 }
2164
2165 static int
drm_process_layoutputs(struct wet_compositor * wet)2166 drm_process_layoutputs(struct wet_compositor *wet)
2167 {
2168 struct wet_layoutput *lo;
2169 int ret = 0;
2170
2171 wl_list_for_each(lo, &wet->layoutput_list, compositor_link) {
2172 if (lo->add.n == 0)
2173 continue;
2174
2175 if (drm_process_layoutput(wet, lo) < 0) {
2176 lo->add = (struct wet_head_array){};
2177 ret = -1;
2178 }
2179 }
2180
2181 return ret;
2182 }
2183
2184 static void
drm_head_disable(struct weston_head * head)2185 drm_head_disable(struct weston_head *head)
2186 {
2187 struct weston_output *output_base;
2188 struct wet_output *output;
2189 struct wet_head_tracker *track;
2190
2191 track = wet_head_tracker_from_head(head);
2192 if (track)
2193 wet_head_tracker_destroy(track);
2194
2195 output_base = weston_head_get_output(head);
2196 assert(output_base);
2197 output = wet_output_from_weston_output(output_base);
2198 assert(output && output->output == output_base);
2199
2200 weston_head_detach(head);
2201 if (count_remaining_heads(output->output, NULL) == 0)
2202 wet_output_destroy(output);
2203 }
2204
2205 static void
drm_heads_changed(struct wl_listener * listener,void * arg)2206 drm_heads_changed(struct wl_listener *listener, void *arg)
2207 {
2208 struct weston_compositor *compositor = arg;
2209 struct wet_compositor *wet = to_wet_compositor(compositor);
2210 struct weston_head *head = NULL;
2211 bool connected;
2212 bool enabled;
2213 bool changed;
2214 bool forced;
2215
2216 /* We need to collect all cloned heads into outputs before enabling the
2217 * output.
2218 */
2219 while ((head = weston_compositor_iterate_heads(compositor, head))) {
2220 connected = weston_head_is_connected(head);
2221 enabled = weston_head_is_enabled(head);
2222 changed = weston_head_is_device_changed(head);
2223 forced = drm_head_should_force_enable(wet, head);
2224
2225 if ((connected || forced) && !enabled) {
2226 drm_head_prepare_enable(wet, head);
2227 } else if (!(connected || forced) && enabled) {
2228 drm_head_disable(head);
2229 } else if (enabled && changed) {
2230 weston_log("Detected a monitor change on head '%{public}s', "
2231 "not bothering to do anything about it.\n",
2232 weston_head_get_name(head));
2233 }
2234 weston_head_reset_device_changed(head);
2235 }
2236
2237 if (drm_process_layoutputs(wet) < 0)
2238 wet->init_failed = true;
2239 }
2240
2241 static int
drm_backend_remoted_output_configure(struct weston_output * output,struct weston_config_section * section,char * modeline,const struct weston_remoting_api * api)2242 drm_backend_remoted_output_configure(struct weston_output *output,
2243 struct weston_config_section *section,
2244 char *modeline,
2245 const struct weston_remoting_api *api)
2246 {
2247 char *gbm_format = NULL;
2248 char *seat = NULL;
2249 char *host = NULL;
2250 char *pipeline = NULL;
2251 int port, ret;
2252
2253 ret = api->set_mode(output, modeline);
2254 if (ret < 0) {
2255 weston_log("Cannot configure an output \"%{public}s\" using "
2256 "weston_remoting_api. Invalid mode\n",
2257 output->name);
2258 return -1;
2259 }
2260
2261 wet_output_set_scale(output, section, 1, 0);
2262 if (wet_output_set_transform(output, section,
2263 WL_OUTPUT_TRANSFORM_NORMAL,
2264 UINT32_MAX) < 0) {
2265 return -1;
2266 };
2267
2268 weston_config_section_get_string(section, "gbm-format", &gbm_format,
2269 NULL);
2270 api->set_gbm_format(output, gbm_format);
2271 free(gbm_format);
2272
2273 weston_config_section_get_string(section, "seat", &seat, "");
2274
2275 api->set_seat(output, seat);
2276 free(seat);
2277
2278 weston_config_section_get_string(section, "gst-pipeline", &pipeline,
2279 NULL);
2280 if (pipeline) {
2281 api->set_gst_pipeline(output, pipeline);
2282 free(pipeline);
2283 return 0;
2284 }
2285
2286 weston_config_section_get_string(section, "host", &host, NULL);
2287 weston_config_section_get_int(section, "port", &port, 0);
2288 if (!host || port <= 0 || 65533 < port) {
2289 weston_log("Cannot configure an output \"%{public}s\". "
2290 "Need to specify gst-pipeline or "
2291 "host and port (1-65533).\n", output->name);
2292 }
2293 api->set_host(output, host);
2294 free(host);
2295 api->set_port(output, port);
2296
2297 return 0;
2298 }
2299
2300 static void
remoted_output_init(struct weston_compositor * c,struct weston_config_section * section,const struct weston_remoting_api * api)2301 remoted_output_init(struct weston_compositor *c,
2302 struct weston_config_section *section,
2303 const struct weston_remoting_api *api)
2304 {
2305 struct weston_output *output = NULL;
2306 char *output_name, *modeline = NULL;
2307 int ret;
2308
2309 weston_config_section_get_string(section, "name", &output_name,
2310 NULL);
2311 if (!output_name)
2312 return;
2313
2314 weston_config_section_get_string(section, "mode", &modeline, "off");
2315 if (strcmp(modeline, "off") == 0)
2316 goto err;
2317
2318 output = api->create_output(c, output_name);
2319 if (!output) {
2320 weston_log("Cannot create remoted output \"%{public}s\".\n",
2321 output_name);
2322 goto err;
2323 }
2324
2325 ret = drm_backend_remoted_output_configure(output, section, modeline,
2326 api);
2327 if (ret < 0) {
2328 weston_log("Cannot configure remoted output \"%{public}s\".\n",
2329 output_name);
2330 goto err;
2331 }
2332
2333 if (weston_output_enable(output) < 0) {
2334 weston_log("Enabling remoted output \"%{public}s\" failed.\n",
2335 output_name);
2336 goto err;
2337 }
2338
2339 free(modeline);
2340 free(output_name);
2341 weston_log("remoted output '%{public}s' enabled\n", output->name);
2342 return;
2343
2344 err:
2345 free(modeline);
2346 free(output_name);
2347 if (output)
2348 weston_output_destroy(output);
2349 }
2350
2351 static void
load_remoting(struct weston_compositor * c,struct weston_config * wc)2352 load_remoting(struct weston_compositor *c, struct weston_config *wc)
2353 {
2354 const struct weston_remoting_api *api = NULL;
2355 int (*module_init)(struct weston_compositor *ec);
2356 struct weston_config_section *section = NULL;
2357 const char *section_name;
2358
2359 /* read remote-output section in weston.ini */
2360 while (weston_config_next_section(wc, §ion, §ion_name)) {
2361 if (strcmp(section_name, "remote-output"))
2362 continue;
2363
2364 if (!api) {
2365 char *module_name;
2366 struct weston_config_section *core_section =
2367 weston_config_get_section(wc, "core", NULL,
2368 NULL);
2369
2370 weston_config_section_get_string(core_section,
2371 "remoting",
2372 &module_name,
2373 "remoting-plugin.so");
2374 module_init = weston_load_module(module_name,
2375 "weston_module_init");
2376 free(module_name);
2377 if (!module_init) {
2378 weston_log("Can't load remoting-plugin\n");
2379 return;
2380 }
2381 if (module_init(c) < 0) {
2382 weston_log("Remoting-plugin init failed\n");
2383 return;
2384 }
2385
2386 api = weston_remoting_get_api(c);
2387 if (!api)
2388 return;
2389 }
2390
2391 remoted_output_init(c, section, api);
2392 }
2393 }
2394
2395 static int
drm_backend_pipewire_output_configure(struct weston_output * output,struct weston_config_section * section,char * modeline,const struct weston_pipewire_api * api)2396 drm_backend_pipewire_output_configure(struct weston_output *output,
2397 struct weston_config_section *section,
2398 char *modeline,
2399 const struct weston_pipewire_api *api)
2400 {
2401 char *seat = NULL;
2402 int ret;
2403
2404 ret = api->set_mode(output, modeline);
2405 if (ret < 0) {
2406 weston_log("Cannot configure an output \"%{public}s\" using "
2407 "weston_pipewire_api. Invalid mode\n",
2408 output->name);
2409 return -1;
2410 }
2411
2412 wet_output_set_scale(output, section, 1, 0);
2413 if (wet_output_set_transform(output, section,
2414 WL_OUTPUT_TRANSFORM_NORMAL,
2415 UINT32_MAX) < 0) {
2416 return -1;
2417 }
2418
2419 weston_config_section_get_string(section, "seat", &seat, "");
2420
2421 api->set_seat(output, seat);
2422 free(seat);
2423
2424 return 0;
2425 }
2426
2427 static void
pipewire_output_init(struct weston_compositor * c,struct weston_config_section * section,const struct weston_pipewire_api * api)2428 pipewire_output_init(struct weston_compositor *c,
2429 struct weston_config_section *section,
2430 const struct weston_pipewire_api *api)
2431 {
2432 struct weston_output *output = NULL;
2433 char *output_name, *modeline = NULL;
2434 int ret;
2435
2436 weston_config_section_get_string(section, "name", &output_name,
2437 NULL);
2438 if (!output_name)
2439 return;
2440
2441 weston_config_section_get_string(section, "mode", &modeline, "off");
2442 if (strcmp(modeline, "off") == 0)
2443 goto err;
2444
2445 output = api->create_output(c, output_name);
2446 if (!output) {
2447 weston_log("Cannot create pipewire output \"%{public}s\".\n",
2448 output_name);
2449 goto err;
2450 }
2451
2452 ret = drm_backend_pipewire_output_configure(output, section, modeline,
2453 api);
2454 if (ret < 0) {
2455 weston_log("Cannot configure pipewire output \"%{public}s\".\n",
2456 output_name);
2457 goto err;
2458 }
2459
2460 if (weston_output_enable(output) < 0) {
2461 weston_log("Enabling pipewire output \"%{public}s\" failed.\n",
2462 output_name);
2463 goto err;
2464 }
2465
2466 free(modeline);
2467 free(output_name);
2468 weston_log("pipewire output '%{public}s' enabled\n", output->name);
2469 return;
2470
2471 err:
2472 free(modeline);
2473 free(output_name);
2474 if (output)
2475 weston_output_destroy(output);
2476 }
2477
2478 static void
load_pipewire(struct weston_compositor * c,struct weston_config * wc)2479 load_pipewire(struct weston_compositor *c, struct weston_config *wc)
2480 {
2481 const struct weston_pipewire_api *api = NULL;
2482 int (*module_init)(struct weston_compositor *ec);
2483 struct weston_config_section *section = NULL;
2484 const char *section_name;
2485
2486 /* read pipewire-output section in weston.ini */
2487 while (weston_config_next_section(wc, §ion, §ion_name)) {
2488 if (strcmp(section_name, "pipewire-output"))
2489 continue;
2490
2491 if (!api) {
2492 char *module_name;
2493 struct weston_config_section *core_section =
2494 weston_config_get_section(wc, "core", NULL,
2495 NULL);
2496
2497 weston_config_section_get_string(core_section,
2498 "pipewire",
2499 &module_name,
2500 "pipewire-plugin.so");
2501 module_init = weston_load_module(module_name,
2502 "weston_module_init");
2503 free(module_name);
2504 if (!module_init) {
2505 weston_log("Can't load pipewire-plugin\n");
2506 return;
2507 }
2508 if (module_init(c) < 0) {
2509 weston_log("Pipewire-plugin init failed\n");
2510 return;
2511 }
2512
2513 api = weston_pipewire_get_api(c);
2514 if (!api)
2515 return;
2516 }
2517
2518 pipewire_output_init(c, section, api);
2519 }
2520 }
2521
2522 static int
load_drm_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2523 load_drm_backend(struct weston_compositor *c,
2524 int *argc, char **argv, struct weston_config *wc)
2525 {
2526 struct weston_drm_backend_config config = {{ 0, }};
2527 struct weston_config_section *section;
2528 struct wet_compositor *wet = to_wet_compositor(c);
2529 int ret = 0;
2530
2531 wet->drm_use_current_mode = false;
2532
2533 section = weston_config_get_section(wc, "core", NULL, NULL);
2534 weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2535 false);
2536
2537 const struct weston_option options[] = {
2538 { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
2539 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
2540 { WESTON_OPTION_STRING, "drm-device", 0, &config.specific_device },
2541 { WESTON_OPTION_BOOLEAN, "current-mode", 0, &wet->drm_use_current_mode },
2542 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2543 { WESTON_OPTION_BOOLEAN, "continue-without-input", 0, &config.continue_without_input },
2544 };
2545
2546 parse_options(options, ARRAY_LENGTH(options), argc, argv);
2547
2548 section = weston_config_get_section(wc, "core", NULL, NULL);
2549 weston_config_section_get_string(section,
2550 "gbm-format", &config.gbm_format,
2551 NULL);
2552 weston_config_section_get_uint(section, "pageflip-timeout",
2553 &config.pageflip_timeout, 0);
2554 weston_config_section_get_bool(section, "pixman-shadow",
2555 &config.use_pixman_shadow, true);
2556
2557 config.base.struct_version = WESTON_DRM_BACKEND_CONFIG_VERSION;
2558 config.base.struct_size = sizeof(struct weston_drm_backend_config);
2559 config.configure_device = configure_input_device;
2560
2561 wet->heads_changed_listener.notify = drm_heads_changed;
2562 weston_compositor_add_heads_changed_listener(c,
2563 &wet->heads_changed_listener);
2564
2565 ret = weston_compositor_load_backend(c, WESTON_BACKEND_DRM,
2566 &config.base);
2567
2568 /* remoting */
2569 load_remoting(c, wc);
2570
2571 /* pipewire */
2572 load_pipewire(c, wc);
2573
2574 free(config.gbm_format);
2575 free(config.seat_id);
2576
2577 return ret;
2578 }
2579
2580 static int
hdi_backend_output_configure(struct weston_output * output)2581 hdi_backend_output_configure(struct weston_output *output)
2582 {
2583 const struct weston_hdi_output_api *api = NULL;
2584 api = weston_hdi_output_get_api(output->compositor);
2585 if (api == NULL) {
2586 weston_log("Cannot use weston_hdi_output_api.\n");
2587 return -1;
2588 }
2589
2590 wet_output_set_scale(output, NULL, 1, 0);
2591 if (wet_output_set_transform(output, NULL,
2592 WL_OUTPUT_TRANSFORM_NORMAL, UINT32_MAX) < 0) {
2593 return -1;
2594 }
2595
2596 if (api->set_mode(output) < 0) {
2597 weston_log("Cannot configure an output using weston_hdi_output_api.\n");
2598 return -1;
2599 }
2600 return 0;
2601 }
2602
2603 static int
load_hdi_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2604 load_hdi_backend(struct weston_compositor *c,
2605 int *argc, char **argv, struct weston_config *wc)
2606 {
2607 const struct weston_windowed_output_api *api;
2608 struct weston_hdi_backend_config config = {};
2609 struct weston_config_section *section;
2610 bool no_outputs = false;
2611 int ret = 0;
2612 char *transform = NULL;
2613
2614 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2615 if (!parsed_options)
2616 return -1;
2617
2618 section = weston_config_get_section(wc, "core", NULL, NULL);
2619 weston_config_section_get_bool(section, "use-hdi", &config.use_hdi,
2620 false);
2621
2622 const struct weston_option options[] = {
2623 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2624 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2625 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2626 { WESTON_OPTION_BOOLEAN, "use-hdi", 0, &config.use_hdi },
2627 { WESTON_OPTION_STRING, "transform", 0, &transform },
2628 { WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
2629 };
2630
2631 parse_options(options, ARRAY_LENGTH(options), argc, argv);
2632
2633 if (transform) {
2634 if (weston_parse_transform(transform, &parsed_options->transform) < 0) {
2635 weston_log("Invalid transform \"%{public}s\"\n", transform);
2636 return -1;
2637 }
2638 free(transform);
2639 }
2640
2641 config.base.struct_version = WESTON_HDI_BACKEND_CONFIG_VERSION;
2642 config.base.struct_size = sizeof(struct weston_hdi_backend_config);
2643 config.configure_device = configure_input_device;
2644
2645 wet_set_simple_head_configurator(c, hdi_backend_output_configure);
2646
2647 /* load the actual wayland backend and configure it */
2648 ret = weston_compositor_load_backend(c, WESTON_BACKEND_HDI,
2649 &config.base);
2650
2651 if (ret < 0)
2652 return ret;
2653
2654 return 0;
2655 }
2656
2657 static int
headless_backend_output_configure(struct weston_output * output)2658 headless_backend_output_configure(struct weston_output *output)
2659 {
2660 struct wet_output_config defaults = {
2661 .width = 1024,
2662 .height = 640,
2663 .scale = 1,
2664 .transform = WL_OUTPUT_TRANSFORM_NORMAL
2665 };
2666
2667 return wet_configure_windowed_output_from_config(output, &defaults);
2668 }
2669
2670 static int
load_headless_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2671 load_headless_backend(struct weston_compositor *c,
2672 int *argc, char **argv, struct weston_config *wc)
2673 {
2674 const struct weston_windowed_output_api *api;
2675 struct weston_headless_backend_config config = {{ 0, }};
2676 struct weston_config_section *section;
2677 bool no_outputs = false;
2678 int ret = 0;
2679 char *transform = NULL;
2680
2681 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2682 if (!parsed_options)
2683 return -1;
2684
2685 section = weston_config_get_section(wc, "core", NULL, NULL);
2686 weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2687 false);
2688 weston_config_section_get_bool(section, "use-gl", &config.use_gl,
2689 false);
2690
2691 const struct weston_option options[] = {
2692 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2693 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2694 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2695 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2696 { WESTON_OPTION_BOOLEAN, "use-gl", 0, &config.use_gl },
2697 { WESTON_OPTION_STRING, "transform", 0, &transform },
2698 { WESTON_OPTION_BOOLEAN, "no-outputs", 0, &no_outputs },
2699 };
2700
2701 parse_options(options, ARRAY_LENGTH(options), argc, argv);
2702
2703 if (transform) {
2704 if (weston_parse_transform(transform, &parsed_options->transform) < 0) {
2705 weston_log("Invalid transform \"%{public}s\"\n", transform);
2706 return -1;
2707 }
2708 free(transform);
2709 }
2710
2711 config.base.struct_version = WESTON_HEADLESS_BACKEND_CONFIG_VERSION;
2712 config.base.struct_size = sizeof(struct weston_headless_backend_config);
2713
2714 wet_set_simple_head_configurator(c, headless_backend_output_configure);
2715
2716 /* load the actual wayland backend and configure it */
2717 ret = weston_compositor_load_backend(c, WESTON_BACKEND_HEADLESS,
2718 &config.base);
2719
2720 if (ret < 0)
2721 return ret;
2722
2723 if (!no_outputs) {
2724 api = weston_windowed_output_get_api(c);
2725
2726 if (!api) {
2727 weston_log("Cannot use weston_windowed_output_api.\n");
2728 return -1;
2729 }
2730
2731 if (api->create_head(c, "headless") < 0)
2732 return -1;
2733 }
2734
2735 return 0;
2736 }
2737
2738 static int
rdp_backend_output_configure(struct weston_output * output)2739 rdp_backend_output_configure(struct weston_output *output)
2740 {
2741 struct wet_compositor *compositor = to_wet_compositor(output->compositor);
2742 struct wet_output_config *parsed_options = compositor->parsed_options;
2743 const struct weston_rdp_output_api *api = weston_rdp_output_get_api(output->compositor);
2744 int width = 640;
2745 int height = 480;
2746
2747 assert(parsed_options);
2748
2749 if (!api) {
2750 weston_log("Cannot use weston_rdp_output_api.\n");
2751 return -1;
2752 }
2753
2754 if (parsed_options->width)
2755 width = parsed_options->width;
2756
2757 if (parsed_options->height)
2758 height = parsed_options->height;
2759
2760 weston_output_set_scale(output, 1);
2761 weston_output_set_transform(output, WL_OUTPUT_TRANSFORM_NORMAL);
2762
2763 if (api->output_set_size(output, width, height) < 0) {
2764 weston_log("Cannot configure output \"%{public}s\" using weston_rdp_output_api.\n",
2765 output->name);
2766 return -1;
2767 }
2768
2769 return 0;
2770 }
2771
2772 static void
weston_rdp_backend_config_init(struct weston_rdp_backend_config * config)2773 weston_rdp_backend_config_init(struct weston_rdp_backend_config *config)
2774 {
2775 config->base.struct_version = WESTON_RDP_BACKEND_CONFIG_VERSION;
2776 config->base.struct_size = sizeof(struct weston_rdp_backend_config);
2777
2778 config->bind_address = NULL;
2779 config->port = 3389;
2780 config->rdp_key = NULL;
2781 config->server_cert = NULL;
2782 config->server_key = NULL;
2783 config->env_socket = 0;
2784 config->no_clients_resize = 0;
2785 config->force_no_compression = 0;
2786 }
2787
2788 static int
load_rdp_backend(struct weston_compositor * c,int * argc,char * argv[],struct weston_config * wc)2789 load_rdp_backend(struct weston_compositor *c,
2790 int *argc, char *argv[], struct weston_config *wc)
2791 {
2792 struct weston_rdp_backend_config config = {{ 0, }};
2793 int ret = 0;
2794
2795 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2796 if (!parsed_options)
2797 return -1;
2798
2799 weston_rdp_backend_config_init(&config);
2800
2801 const struct weston_option rdp_options[] = {
2802 { WESTON_OPTION_BOOLEAN, "env-socket", 0, &config.env_socket },
2803 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2804 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2805 { WESTON_OPTION_STRING, "address", 0, &config.bind_address },
2806 { WESTON_OPTION_INTEGER, "port", 0, &config.port },
2807 { WESTON_OPTION_BOOLEAN, "no-clients-resize", 0, &config.no_clients_resize },
2808 { WESTON_OPTION_STRING, "rdp4-key", 0, &config.rdp_key },
2809 { WESTON_OPTION_STRING, "rdp-tls-cert", 0, &config.server_cert },
2810 { WESTON_OPTION_STRING, "rdp-tls-key", 0, &config.server_key },
2811 { WESTON_OPTION_BOOLEAN, "force-no-compression", 0, &config.force_no_compression },
2812 };
2813
2814 parse_options(rdp_options, ARRAY_LENGTH(rdp_options), argc, argv);
2815
2816 wet_set_simple_head_configurator(c, rdp_backend_output_configure);
2817
2818 ret = weston_compositor_load_backend(c, WESTON_BACKEND_RDP,
2819 &config.base);
2820
2821 free(config.bind_address);
2822 free(config.rdp_key);
2823 free(config.server_cert);
2824 free(config.server_key);
2825
2826 return ret;
2827 }
2828
2829 static int
fbdev_backend_output_configure(struct weston_output * output)2830 fbdev_backend_output_configure(struct weston_output *output)
2831 {
2832 struct weston_config *wc = wet_get_config(output->compositor);
2833 struct weston_config_section *section;
2834
2835 section = weston_config_get_section(wc, "output", "name", "fbdev");
2836
2837 if (wet_output_set_transform(output, section,
2838 WL_OUTPUT_TRANSFORM_NORMAL,
2839 UINT32_MAX) < 0) {
2840 return -1;
2841 }
2842
2843 weston_output_set_scale(output, 1);
2844
2845 return 0;
2846 }
2847
2848 static int
load_fbdev_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2849 load_fbdev_backend(struct weston_compositor *c,
2850 int *argc, char **argv, struct weston_config *wc)
2851 {
2852 struct weston_fbdev_backend_config config = {{ 0, }};
2853 int ret = 0;
2854
2855 const struct weston_option fbdev_options[] = {
2856 { WESTON_OPTION_INTEGER, "tty", 0, &config.tty },
2857 { WESTON_OPTION_STRING, "device", 0, &config.device },
2858 { WESTON_OPTION_STRING, "seat", 0, &config.seat_id },
2859 };
2860
2861 parse_options(fbdev_options, ARRAY_LENGTH(fbdev_options), argc, argv);
2862
2863 config.base.struct_version = WESTON_FBDEV_BACKEND_CONFIG_VERSION;
2864 config.base.struct_size = sizeof(struct weston_fbdev_backend_config);
2865 config.configure_device = configure_input_device;
2866
2867 wet_set_simple_head_configurator(c, fbdev_backend_output_configure);
2868
2869 /* load the actual wayland backend and configure it */
2870 ret = weston_compositor_load_backend(c, WESTON_BACKEND_FBDEV,
2871 &config.base);
2872
2873 free(config.device);
2874 return ret;
2875 }
2876
2877 static int
x11_backend_output_configure(struct weston_output * output)2878 x11_backend_output_configure(struct weston_output *output)
2879 {
2880 struct wet_output_config defaults = {
2881 .width = 1024,
2882 .height = 600,
2883 .scale = 1,
2884 .transform = WL_OUTPUT_TRANSFORM_NORMAL
2885 };
2886
2887 return wet_configure_windowed_output_from_config(output, &defaults);
2888 }
2889
2890 static int
load_x11_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)2891 load_x11_backend(struct weston_compositor *c,
2892 int *argc, char **argv, struct weston_config *wc)
2893 {
2894 char *default_output;
2895 const struct weston_windowed_output_api *api;
2896 struct weston_x11_backend_config config = {{ 0, }};
2897 struct weston_config_section *section;
2898 int ret = 0;
2899 int option_count = 1;
2900 int output_count = 0;
2901 char const *section_name;
2902 int i;
2903
2904 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
2905 if (!parsed_options)
2906 return -1;
2907
2908 section = weston_config_get_section(wc, "core", NULL, NULL);
2909 weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
2910 false);
2911
2912 const struct weston_option options[] = {
2913 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
2914 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
2915 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
2916 { WESTON_OPTION_BOOLEAN, "fullscreen", 'f', &config.fullscreen },
2917 { WESTON_OPTION_INTEGER, "output-count", 0, &option_count },
2918 { WESTON_OPTION_BOOLEAN, "no-input", 0, &config.no_input },
2919 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
2920 };
2921
2922 parse_options(options, ARRAY_LENGTH(options), argc, argv);
2923
2924 config.base.struct_version = WESTON_X11_BACKEND_CONFIG_VERSION;
2925 config.base.struct_size = sizeof(struct weston_x11_backend_config);
2926
2927 wet_set_simple_head_configurator(c, x11_backend_output_configure);
2928
2929 /* load the actual backend and configure it */
2930 ret = weston_compositor_load_backend(c, WESTON_BACKEND_X11,
2931 &config.base);
2932
2933 if (ret < 0)
2934 return ret;
2935
2936 api = weston_windowed_output_get_api(c);
2937
2938 if (!api) {
2939 weston_log("Cannot use weston_windowed_output_api.\n");
2940 return -1;
2941 }
2942
2943 section = NULL;
2944 while (weston_config_next_section(wc, §ion, §ion_name)) {
2945 char *output_name;
2946
2947 if (output_count >= option_count)
2948 break;
2949
2950 if (strcmp(section_name, "output") != 0) {
2951 continue;
2952 }
2953
2954 weston_config_section_get_string(section, "name", &output_name, NULL);
2955 if (output_name == NULL || output_name[0] != 'X') {
2956 free(output_name);
2957 continue;
2958 }
2959
2960 if (api->create_head(c, output_name) < 0) {
2961 free(output_name);
2962 return -1;
2963 }
2964 free(output_name);
2965
2966 output_count++;
2967 }
2968
2969 default_output = NULL;
2970
2971 for (i = output_count; i < option_count; i++) {
2972 if (asprintf(&default_output, "screen%d", i) < 0) {
2973 return -1;
2974 }
2975
2976 if (api->create_head(c, default_output) < 0) {
2977 free(default_output);
2978 return -1;
2979 }
2980 free(default_output);
2981 }
2982
2983 return 0;
2984 }
2985
2986 static int
wayland_backend_output_configure(struct weston_output * output)2987 wayland_backend_output_configure(struct weston_output *output)
2988 {
2989 struct wet_output_config defaults = {
2990 .width = 1024,
2991 .height = 640,
2992 .scale = 1,
2993 .transform = WL_OUTPUT_TRANSFORM_NORMAL
2994 };
2995
2996 return wet_configure_windowed_output_from_config(output, &defaults);
2997 }
2998
2999 static int
load_wayland_backend(struct weston_compositor * c,int * argc,char ** argv,struct weston_config * wc)3000 load_wayland_backend(struct weston_compositor *c,
3001 int *argc, char **argv, struct weston_config *wc)
3002 {
3003 struct weston_wayland_backend_config config = {{ 0, }};
3004 struct weston_config_section *section;
3005 const struct weston_windowed_output_api *api;
3006 const char *section_name;
3007 char *output_name = NULL;
3008 int count = 1;
3009 int ret = 0;
3010 int i;
3011
3012 struct wet_output_config *parsed_options = wet_init_parsed_options(c);
3013 if (!parsed_options)
3014 return -1;
3015
3016 config.cursor_size = 32;
3017 config.cursor_theme = NULL;
3018 config.display_name = NULL;
3019
3020 section = weston_config_get_section(wc, "core", NULL, NULL);
3021 weston_config_section_get_bool(section, "use-pixman", &config.use_pixman,
3022 false);
3023
3024 const struct weston_option wayland_options[] = {
3025 { WESTON_OPTION_INTEGER, "width", 0, &parsed_options->width },
3026 { WESTON_OPTION_INTEGER, "height", 0, &parsed_options->height },
3027 { WESTON_OPTION_INTEGER, "scale", 0, &parsed_options->scale },
3028 { WESTON_OPTION_STRING, "display", 0, &config.display_name },
3029 { WESTON_OPTION_BOOLEAN, "use-pixman", 0, &config.use_pixman },
3030 { WESTON_OPTION_BOOLEAN, "use-tde", 0, &config.use_tde }, // OHOS tde
3031 { WESTON_OPTION_INTEGER, "output-count", 0, &count },
3032 { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &config.fullscreen },
3033 { WESTON_OPTION_BOOLEAN, "sprawl", 0, &config.sprawl },
3034 };
3035
3036 parse_options(wayland_options, ARRAY_LENGTH(wayland_options), argc, argv);
3037
3038 section = weston_config_get_section(wc, "shell", NULL, NULL);
3039 weston_config_section_get_string(section, "cursor-theme",
3040 &config.cursor_theme, NULL);
3041 weston_config_section_get_int(section, "cursor-size",
3042 &config.cursor_size, 32);
3043
3044 config.base.struct_size = sizeof(struct weston_wayland_backend_config);
3045 config.base.struct_version = WESTON_WAYLAND_BACKEND_CONFIG_VERSION;
3046
3047 /* load the actual wayland backend and configure it */
3048 ret = weston_compositor_load_backend(c, WESTON_BACKEND_WAYLAND,
3049 &config.base);
3050
3051 free(config.cursor_theme);
3052 free(config.display_name);
3053
3054 if (ret < 0)
3055 return ret;
3056
3057 api = weston_windowed_output_get_api(c);
3058
3059 if (api == NULL) {
3060 /* We will just assume if load_backend() finished cleanly and
3061 * windowed_output_api is not present that wayland backend is
3062 * started with --sprawl or runs on fullscreen-shell.
3063 * In this case, all values are hardcoded, so nothing can be
3064 * configured; simply create and enable an output. */
3065 wet_set_simple_head_configurator(c, NULL);
3066
3067 return 0;
3068 }
3069
3070 wet_set_simple_head_configurator(c, wayland_backend_output_configure);
3071
3072 section = NULL;
3073 while (weston_config_next_section(wc, §ion, §ion_name)) {
3074 if (count == 0)
3075 break;
3076
3077 if (strcmp(section_name, "output") != 0) {
3078 continue;
3079 }
3080
3081 weston_config_section_get_string(section, "name", &output_name, NULL);
3082
3083 if (output_name == NULL)
3084 continue;
3085
3086 if (output_name[0] != 'W' || output_name[1] != 'L') {
3087 free(output_name);
3088 continue;
3089 }
3090
3091 if (api->create_head(c, output_name) < 0) {
3092 free(output_name);
3093 return -1;
3094 }
3095 free(output_name);
3096
3097 --count;
3098 }
3099
3100 for (i = 0; i < count; i++) {
3101 if (asprintf(&output_name, "wayland%d", i) < 0)
3102 return -1;
3103
3104 if (api->create_head(c, output_name) < 0) {
3105 free(output_name);
3106 return -1;
3107 }
3108 free(output_name);
3109 }
3110
3111 return 0;
3112 }
3113
3114
3115 static int
load_backend(struct weston_compositor * compositor,const char * backend,int * argc,char ** argv,struct weston_config * config)3116 load_backend(struct weston_compositor *compositor, const char *backend,
3117 int *argc, char **argv, struct weston_config *config)
3118 {
3119 if (strstr(backend, "headless-backend.so"))
3120 return load_headless_backend(compositor, argc, argv, config);
3121 if (strstr(backend, "hdi-backend.so"))
3122 return load_hdi_backend(compositor, argc, argv, config);
3123 else if (strstr(backend, "rdp-backend.so"))
3124 return load_rdp_backend(compositor, argc, argv, config);
3125 else if (strstr(backend, "fbdev-backend.so"))
3126 return load_fbdev_backend(compositor, argc, argv, config);
3127 else if (strstr(backend, "drm-backend.so"))
3128 return load_drm_backend(compositor, argc, argv, config);
3129 else if (strstr(backend, "x11-backend.so"))
3130 return load_x11_backend(compositor, argc, argv, config);
3131 else if (strstr(backend, "wayland-backend.so"))
3132 return load_wayland_backend(compositor, argc, argv, config);
3133
3134 weston_log("Error: unknown backend \"%{public}s\"\n", backend);
3135 return -1;
3136 }
3137
3138 static char *
copy_command_line(int argc,char * const argv[])3139 copy_command_line(int argc, char * const argv[])
3140 {
3141 FILE *fp;
3142 char *str = NULL;
3143 size_t size = 0;
3144 int i;
3145
3146 fp = open_memstream(&str, &size);
3147 if (!fp)
3148 return NULL;
3149
3150 fprintf(fp, "%s", argv[0]);
3151 for (i = 1; i < argc; i++)
3152 fprintf(fp, " %s", argv[i]);
3153 fclose(fp);
3154
3155 return str;
3156 }
3157
3158 #if !defined(BUILD_XWAYLAND)
3159 int
wet_load_xwayland(struct weston_compositor * comp)3160 wet_load_xwayland(struct weston_compositor *comp)
3161 {
3162 return -1;
3163 }
3164 #endif
3165
3166 // OHOS remove logger
3167 //static void
3168 //weston_log_setup_scopes(struct weston_log_context *log_ctx,
3169 // struct weston_log_subscriber *subscriber,
3170 // const char *names)
3171 //{
3172 // assert(log_ctx);
3173 // assert(subscriber);
3174 //
3175 // char *tokenize = strdup(names);
3176 // char *token = strtok(tokenize, ",");
3177 // while (token) {
3178 // weston_log_subscribe(log_ctx, subscriber, token);
3179 // token = strtok(NULL, ",");
3180 // }
3181 // free(tokenize);
3182 //}
3183 //
3184 //static void
3185 //flight_rec_key_binding_handler(struct weston_keyboard *keyboard,
3186 // const struct timespec *time, uint32_t key,
3187 // void *data)
3188 //{
3189 // struct weston_log_subscriber *flight_rec = data;
3190 // weston_log_subscriber_display_flight_rec(flight_rec);
3191 //}
3192 //
3193 //static void
3194 //weston_log_subscribe_to_scopes(struct weston_log_context *log_ctx,
3195 // struct weston_log_subscriber *logger,
3196 // struct weston_log_subscriber *flight_rec,
3197 // const char *log_scopes,
3198 // const char *flight_rec_scopes)
3199 //{
3200 // if (log_scopes)
3201 // weston_log_setup_scopes(log_ctx, logger, log_scopes);
3202 // else
3203 // weston_log_subscribe(log_ctx, logger, "log");
3204 //
3205 // if (flight_rec_scopes) {
3206 // weston_log_setup_scopes(log_ctx, flight_rec, flight_rec_scopes);
3207 // } else {
3208 // /* by default subscribe to 'log', and 'drm-backend' */
3209 // weston_log_subscribe(log_ctx, flight_rec, "log");
3210 // weston_log_subscribe(log_ctx, flight_rec, "drm-backend");
3211 // }
3212 //}
3213
3214 WL_EXPORT int
wet_main(int argc,char * argv[])3215 wet_main(int argc, char *argv[])
3216 {
3217 log_init();
3218 LOG_ENTERS("main");
3219 int ret = EXIT_FAILURE;
3220 char *cmdline;
3221 struct wl_display *display;
3222 struct wl_event_source *signals[4];
3223 struct wl_event_loop *loop;
3224 int i, fd;
3225 char *backend = NULL;
3226 char *shell = NULL;
3227 bool xwayland = false;
3228 char *modules = NULL;
3229 char *option_modules = NULL;
3230 char *log = NULL;
3231 char *log_scopes = NULL;
3232 char *flight_rec_scopes = NULL;
3233 char *server_socket = NULL;
3234 int32_t idle_time = -1;
3235 int32_t help = 0;
3236 char *socket_name = NULL;
3237 int32_t version = 0;
3238 int32_t noconfig = 0;
3239 int32_t debug_protocol = 0;
3240 bool numlock_on;
3241 char *config_file = NULL;
3242 struct weston_config *config = NULL;
3243 struct weston_config_section *section;
3244 struct wl_client *primary_client;
3245 struct wl_listener primary_client_destroyed;
3246 struct weston_seat *seat;
3247 struct wet_compositor wet = { 0 };
3248 // OHOS remove logger
3249 // struct weston_log_context *log_ctx = NULL;
3250 // struct weston_log_subscriber *logger = NULL;
3251 // struct weston_log_subscriber *flight_rec = NULL;
3252 sigset_t mask;
3253
3254 bool wait_for_debugger = false;
3255 struct wl_protocol_logger *protologger = NULL;
3256
3257 const struct weston_option core_options[] = {
3258 { WESTON_OPTION_STRING, "backend", 'B', &backend },
3259 { WESTON_OPTION_STRING, "shell", 0, &shell },
3260 { WESTON_OPTION_STRING, "socket", 'S', &socket_name },
3261 { WESTON_OPTION_INTEGER, "idle-time", 'i', &idle_time },
3262 #if defined(BUILD_XWAYLAND)
3263 { WESTON_OPTION_BOOLEAN, "xwayland", 0, &xwayland },
3264 #endif
3265 { WESTON_OPTION_STRING, "modules", 0, &option_modules },
3266 { WESTON_OPTION_STRING, "log", 0, &log },
3267 { WESTON_OPTION_BOOLEAN, "help", 'h', &help },
3268 { WESTON_OPTION_BOOLEAN, "version", 0, &version },
3269 { WESTON_OPTION_BOOLEAN, "no-config", 0, &noconfig },
3270 { WESTON_OPTION_STRING, "config", 'c', &config_file },
3271 { WESTON_OPTION_BOOLEAN, "wait-for-debugger", 0, &wait_for_debugger },
3272 { WESTON_OPTION_BOOLEAN, "debug", 0, &debug_protocol },
3273 { WESTON_OPTION_STRING, "logger-scopes", 'l', &log_scopes },
3274 { WESTON_OPTION_STRING, "flight-rec-scopes", 'f', &flight_rec_scopes },
3275 };
3276
3277 wl_list_init(&wet.layoutput_list);
3278
3279 os_fd_set_cloexec(fileno(stdin));
3280
3281 cmdline = copy_command_line(argc, argv);
3282 parse_options(core_options, ARRAY_LENGTH(core_options), &argc, argv);
3283
3284 if (help) {
3285 free(cmdline);
3286 usage(EXIT_SUCCESS);
3287 }
3288
3289 if (version) {
3290 printf(PACKAGE_STRING "\n");
3291 free(cmdline);
3292
3293 LOG_EXITS("main");
3294 return EXIT_SUCCESS;
3295 }
3296
3297 // OHOS remove logger
3298 // log_ctx = weston_log_ctx_create();
3299 // if (!log_ctx) {
3300 // fprintf(stderr, "Failed to initialize weston debug framework.\n");
3301 // return EXIT_FAILURE;
3302 // }
3303 //
3304 // log_scope = weston_log_ctx_add_log_scope(log_ctx, "log",
3305 // "Weston and Wayland log\n", NULL, NULL, NULL);
3306 //
3307 // if (!weston_log_file_open(log))
3308 // return EXIT_FAILURE;
3309 //
3310 // weston_log_set_handler(vlog, vlog_continue);
3311 //
3312 // logger = weston_log_subscriber_create_log(weston_logfile);
3313 // flight_rec = weston_log_subscriber_create_flight_rec(DEFAULT_FLIGHT_REC_SIZE);
3314 //
3315 // weston_log_subscribe_to_scopes(log_ctx, logger, flight_rec,
3316 // log_scopes, flight_rec_scopes);
3317
3318 weston_log("%{public}s\n"
3319 STAMP_SPACE "%{public}s\n"
3320 STAMP_SPACE "Bug reports to: %{public}s\n"
3321 STAMP_SPACE "Build: %{public}s\n",
3322 PACKAGE_STRING, PACKAGE_URL, PACKAGE_BUGREPORT,
3323 BUILD_ID);
3324 weston_log("Command line: %{public}s\n", cmdline);
3325 free(cmdline);
3326 log_uname();
3327
3328 verify_xdg_runtime_dir();
3329
3330 display = wl_display_create();
3331 if (display == NULL) {
3332 weston_log("fatal: failed to create display\n");
3333 goto out_display;
3334 }
3335
3336 loop = wl_display_get_event_loop(display);
3337 signals[0] = wl_event_loop_add_signal(loop, SIGTERM, on_term_signal,
3338 display);
3339 signals[1] = wl_event_loop_add_signal(loop, SIGINT, on_term_signal,
3340 display);
3341 signals[2] = wl_event_loop_add_signal(loop, SIGQUIT, on_term_signal,
3342 display);
3343
3344 wl_list_init(&child_process_list);
3345 signals[3] = wl_event_loop_add_signal(loop, SIGCHLD, sigchld_handler,
3346 NULL);
3347
3348 if (!signals[0] || !signals[1] || !signals[2] || !signals[3])
3349 goto out_signals;
3350
3351 /* Xwayland uses SIGUSR1 for communicating with weston. Since some
3352 weston plugins may create additional threads, set up any necessary
3353 signal blocking early so that these threads can inherit the settings
3354 when created. */
3355 sigemptyset(&mask);
3356 sigaddset(&mask, SIGUSR1);
3357 pthread_sigmask(SIG_BLOCK, &mask, NULL);
3358
3359 if (load_configuration(&config, noconfig, config_file) < 0)
3360 goto out_signals;
3361 wet.config = config;
3362 wet.parsed_options = NULL;
3363
3364 section = weston_config_get_section(config, "core", NULL, NULL);
3365
3366 // OHOS remove debugger
3367 // if (!wait_for_debugger) {
3368 // weston_config_section_get_bool(section, "wait-for-debugger",
3369 // &wait_for_debugger, false);
3370 // }
3371 // if (wait_for_debugger) {
3372 // weston_log("Weston PID is %ld - "
3373 // "waiting for debugger, send SIGCONT to continue...\n",
3374 // (long)getpid());
3375 // raise(SIGSTOP);
3376 // }
3377
3378 if (!backend) {
3379 weston_config_section_get_string(section, "backend", &backend,
3380 NULL);
3381 if (!backend)
3382 backend = weston_choose_default_backend();
3383 }
3384
3385 // OHOS remove logger
3386 // wet.compositor = weston_compositor_create(display, log_ctx, &wet);
3387 wet.compositor = weston_compositor_create(display, &wet);
3388 if (wet.compositor == NULL) {
3389 weston_log("fatal: failed to create compositor\n");
3390 goto out;
3391 }
3392 segv_compositor = wet.compositor;
3393
3394 // OHOS remove log, debugger
3395 // protocol_scope =
3396 // weston_log_ctx_add_log_scope(log_ctx, "proto",
3397 // "Wayland protocol dump for all clients.\n",
3398 // NULL, NULL, NULL);
3399 //
3400 // protologger = wl_display_add_protocol_logger(display,
3401 // protocol_log_fn,
3402 // NULL);
3403 // if (debug_protocol)
3404 // weston_compositor_enable_debug_protocol(wet.compositor);
3405 //
3406 // weston_compositor_add_debug_binding(wet.compositor, KEY_D,
3407 // flight_rec_key_binding_handler,
3408 // flight_rec);
3409
3410 if (weston_compositor_init_config(wet.compositor, config) < 0)
3411 goto out;
3412
3413 weston_config_section_get_bool(section, "require-input",
3414 &wet.compositor->require_input, true);
3415
3416 // OHOS vsync module
3417 StartSoftVsyncThread();
3418
3419 LOG_ENTERS("load_backend");
3420 if (load_backend(wet.compositor, backend, &argc, argv, config) < 0) {
3421 weston_log("fatal: failed to create compositor backend\n");
3422 goto out;
3423 }
3424 LOG_EXITS("load_backend");
3425
3426 LOG_ENTERS("weston_compositor_flush_heads_changed");
3427 weston_compositor_flush_heads_changed(wet.compositor);
3428 LOG_EXITS("weston_compositor_flush_heads_changed");
3429 // OHOS
3430 // if (wet.init_failed)
3431 // goto out;
3432 if (wet.init_failed && wl_list_empty(&wet.compositor->output_list))
3433 goto out;
3434
3435 if (idle_time < 0)
3436 weston_config_section_get_int(section, "idle-time", &idle_time, -1);
3437 if (idle_time < 0)
3438 idle_time = 300; /* default idle timeout, in seconds */
3439
3440 wet.compositor->idle_time = idle_time;
3441 wet.compositor->default_pointer_grab = NULL;
3442 wet.compositor->exit = handle_exit;
3443
3444 weston_compositor_log_capabilities(wet.compositor);
3445
3446 server_socket = getenv("WAYLAND_SERVER_SOCKET");
3447 if (server_socket) {
3448 weston_log("Running with single client\n");
3449 if (!safe_strtoint(server_socket, &fd))
3450 fd = -1;
3451 } else {
3452 fd = -1;
3453 }
3454
3455 if (fd != -1) {
3456 primary_client = wl_client_create(display, fd);
3457 if (!primary_client) {
3458 weston_log("fatal: failed to add client: %{public}s\n",
3459 strerror(errno));
3460 goto out;
3461 }
3462 primary_client_destroyed.notify =
3463 handle_primary_client_destroyed;
3464 wl_client_add_destroy_listener(primary_client,
3465 &primary_client_destroyed);
3466 } else if (weston_create_listening_socket(display, socket_name)) {
3467 goto out;
3468 }
3469
3470 if (!shell)
3471 weston_config_section_get_string(section, "shell", &shell,
3472 "desktop-shell.so");
3473
3474 if (wet_load_shell(wet.compositor, shell, &argc, argv) < 0)
3475 goto out;
3476
3477 weston_config_section_get_string(section, "modules", &modules, "");
3478 if (load_modules(wet.compositor, modules, &argc, argv, &xwayland) < 0)
3479 goto out;
3480
3481 if (load_modules(wet.compositor, option_modules, &argc, argv, &xwayland) < 0)
3482 goto out;
3483
3484 if (!xwayland) {
3485 weston_config_section_get_bool(section, "xwayland", &xwayland,
3486 false);
3487 }
3488 if (xwayland) {
3489 if (wet_load_xwayland(wet.compositor) < 0)
3490 goto out;
3491 }
3492
3493 section = weston_config_get_section(config, "keyboard", NULL, NULL);
3494 weston_config_section_get_bool(section, "numlock-on", &numlock_on, false);
3495 if (numlock_on) {
3496 wl_list_for_each(seat, &wet.compositor->seat_list, link) {
3497 struct weston_keyboard *keyboard =
3498 weston_seat_get_keyboard(seat);
3499
3500 if (keyboard)
3501 weston_keyboard_set_locks(keyboard,
3502 WESTON_NUM_LOCK,
3503 WESTON_NUM_LOCK);
3504 }
3505 }
3506
3507 for (i = 1; i < argc; i++)
3508 weston_log("fatal: unhandled option: %{public}s\n", argv[i]);
3509 if (argc > 1)
3510 goto out;
3511
3512 weston_compositor_wake(wet.compositor);
3513
3514 LOG_EXITS("main");
3515 LOG_ENTERS("wl_display_run");
3516 wl_display_run(display);
3517 LOG_EXITS("wl_display_run");
3518 LOG_ENTERS("exiting");
3519
3520 /* Allow for setting return exit code after
3521 * wl_display_run returns normally. This is
3522 * useful for devs/testers and automated tests
3523 * that want to indicate failure status to
3524 * testing infrastructure above
3525 */
3526 ret = wet.compositor->exit_code;
3527
3528 out:
3529 wet_compositor_destroy_layout(&wet);
3530
3531 /* free(NULL) is valid, and it won't be NULL if it's used */
3532 free(wet.parsed_options);
3533
3534 // OHOS remove logger
3535 // if (protologger)
3536 // wl_protocol_logger_destroy(protologger);
3537
3538 weston_compositor_destroy(wet.compositor);
3539
3540 // OHOS vsync module
3541 StopSoftVsyncThread();
3542 VsyncModuleStop();
3543
3544 // OHOS remove logger
3545 // weston_log_scope_destroy(protocol_scope);
3546 // protocol_scope = NULL;
3547 // weston_log_scope_destroy(log_scope);
3548 // log_scope = NULL;
3549 // weston_log_subscriber_destroy(logger);
3550 // weston_log_subscriber_destroy(flight_rec);
3551 // weston_log_ctx_destroy(log_ctx);
3552
3553 out_signals:
3554 for (i = ARRAY_LENGTH(signals) - 1; i >= 0; i--)
3555 if (signals[i])
3556 wl_event_source_remove(signals[i]);
3557
3558 wl_display_destroy(display);
3559
3560 out_display:
3561 // OHOS remove logger
3562 // weston_log_file_close();
3563
3564 if (config)
3565 weston_config_destroy(config);
3566 free(config_file);
3567 free(backend);
3568 free(shell);
3569 free(socket_name);
3570 free(option_modules);
3571 free(log);
3572 free(modules);
3573
3574 LOG_EXITS("main");
3575 return ret;
3576 }
3577