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