| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Cage: A Wayland kiosk. | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2019-01-02 20:58:39 +01:00
										 |  |  |  * Copyright (C) 2018-2019 Jente Hidskes | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  |  * | 
					
						
							|  |  |  |  * See the LICENSE file accompanying this file. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2018-11-25 22:11:08 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define _POSIX_C_SOURCE 200112L
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #include "config.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | #include <getopt.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <signal.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | #include <sys/wait.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <wayland-server.h>
 | 
					
						
							|  |  |  | #include <wlr/backend.h>
 | 
					
						
							|  |  |  | #include <wlr/render/wlr_renderer.h>
 | 
					
						
							|  |  |  | #include <wlr/types/wlr_compositor.h>
 | 
					
						
							| 
									
										
										
										
											2019-01-04 20:23:50 +01:00
										 |  |  | #include <wlr/types/wlr_data_device.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-20 12:23:16 +01:00
										 |  |  | #include <wlr/types/wlr_gamma_control_v1.h>
 | 
					
						
							| 
									
										
										
										
											2019-01-04 17:06:27 +01:00
										 |  |  | #include <wlr/types/wlr_idle.h>
 | 
					
						
							| 
									
										
										
										
											2019-01-08 23:24:51 +01:00
										 |  |  | #include <wlr/types/wlr_idle_inhibit_v1.h>
 | 
					
						
							| 
									
										
										
										
											2019-01-04 20:23:50 +01:00
										 |  |  | #include <wlr/types/wlr_output_layout.h>
 | 
					
						
							| 
									
										
										
										
											2019-02-23 17:05:02 +01:00
										 |  |  | #include <wlr/types/wlr_server_decoration.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | #include <wlr/types/wlr_xcursor_manager.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | #include <wlr/types/wlr_xdg_decoration_v1.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <wlr/types/wlr_xdg_shell.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-16 16:46:51 +00:00
										 |  |  | #include <wlr/types/wlr_screencopy_v1.h>
 | 
					
						
							| 
									
										
										
										
											2019-08-16 17:04:28 +00:00
										 |  |  | #include <wlr/types/wlr_xdg_output_v1.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <wlr/util/log.h>
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | #include <wlr/xwayland.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 23:24:51 +01:00
										 |  |  | #include "idle_inhibit_v1.h"
 | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | #include "output.h"
 | 
					
						
							|  |  |  | #include "seat.h"
 | 
					
						
							|  |  |  | #include "server.h"
 | 
					
						
							| 
									
										
										
										
											2019-01-24 14:14:15 +01:00
										 |  |  | #include "view.h"
 | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | #include "xdg_shell.h"
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | #include "xwayland.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | static bool | 
					
						
							|  |  |  | spawn_primary_client(char *argv[], pid_t *pid_out) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	pid_t pid = fork(); | 
					
						
							|  |  |  | 	if (pid == 0) { | 
					
						
							| 
									
										
										
										
											2019-02-17 21:14:31 +01:00
										 |  |  | 		sigset_t set; | 
					
						
							|  |  |  | 		sigemptyset(&set); | 
					
						
							|  |  |  | 		sigprocmask(SIG_SETMASK, &set, NULL); | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 		execvp(argv[0], argv); | 
					
						
							|  |  |  | 		_exit(1); | 
					
						
							|  |  |  | 	} else if (pid == -1) { | 
					
						
							|  |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to fork"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	*pid_out = pid; | 
					
						
							|  |  |  | 	wlr_log(WLR_DEBUG, "Child process created with pid %d", pid); | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | static bool | 
					
						
							|  |  |  | drop_permissions(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (getuid() != geteuid() || getgid() != getegid()) { | 
					
						
							|  |  |  | 		if (setuid(getuid()) != 0 || setgid(getgid()) != 0) { | 
					
						
							|  |  |  | 			wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (setuid(0) != -1) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to drop root (we shouldn't be able to " | 
					
						
							|  |  |  | 			"restore it after setuid), refusing to start"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | static int | 
					
						
							|  |  |  | handle_signal(int signal, void *data) | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | 	struct wl_display *display = data; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (signal) { | 
					
						
							|  |  |  | 	case SIGINT: | 
					
						
							|  |  |  | 		/* Fallthrough */ | 
					
						
							|  |  |  | 	case SIGTERM: | 
					
						
							|  |  |  | 		wl_display_terminate(display); | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | usage(FILE *file, const char *cage) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-02-26 18:56:23 +01:00
										 |  |  | 	fprintf(file, "Usage: %s [OPTIONS] [--] APPLICATION\n" | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		"\n" | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 		" -d\t Don't draw client side decorations, when possible\n" | 
					
						
							| 
									
										
										
										
											2019-04-14 01:50:12 +02:00
										 |  |  | 		" -r\t Rotate the output 90 degrees clockwise, specify up to three times\n" | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		" -D\t Turn on damage tracking debugging\n" | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-02-26 18:56:23 +01:00
										 |  |  | 		" -h\t Display this help message\n" | 
					
						
							|  |  |  | 		"\n" | 
					
						
							|  |  |  | 		" Use -- when you want to pass arguments to APPLICATION\n", | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		cage); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static bool | 
					
						
							|  |  |  | parse_args(struct cg_server *server, int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int c; | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2019-04-14 01:50:12 +02:00
										 |  |  | 	while ((c = getopt(argc, argv, "drDh")) != -1) { | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2019-04-14 01:50:12 +02:00
										 |  |  | 	while ((c = getopt(argc, argv, "drh")) != -1) { | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		switch (c) { | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 		case 'd': | 
					
						
							|  |  |  | 			server->xdg_decoration = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2019-04-14 01:50:12 +02:00
										 |  |  | 		case 'r': | 
					
						
							|  |  |  | 			server->output_transform++; | 
					
						
							|  |  |  | 			if (server->output_transform > WL_OUTPUT_TRANSFORM_270) { | 
					
						
							|  |  |  | 				server->output_transform = WL_OUTPUT_TRANSFORM_NORMAL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #ifdef DEBUG
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		case 'D': | 
					
						
							|  |  |  | 			server->debug_damage_tracking = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:37 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		case 'h': | 
					
						
							|  |  |  | 			usage(stdout, argv[0]); | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			usage(stderr, argv[0]); | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-26 18:56:23 +01:00
										 |  |  | 	if (optind >= argc) { | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		usage(stderr, argv[0]); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | int | 
					
						
							|  |  |  | main(int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | 	struct cg_server server = {0}; | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	struct wl_event_loop *event_loop = NULL; | 
					
						
							| 
									
										
										
										
											2019-02-21 11:38:30 +01:00
										 |  |  | 	struct wl_event_source *sigint_source = NULL; | 
					
						
							|  |  |  | 	struct wl_event_source *sigterm_source = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	struct wlr_renderer *renderer = NULL; | 
					
						
							|  |  |  | 	struct wlr_compositor *compositor = NULL; | 
					
						
							| 
									
										
										
										
											2019-12-20 12:33:15 +01:00
										 |  |  | 	struct wlr_data_device_manager *data_device_manager = NULL; | 
					
						
							| 
									
										
										
										
											2019-02-23 17:05:02 +01:00
										 |  |  | 	struct wlr_server_decoration_manager *server_decoration_manager = NULL; | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 	struct wlr_xdg_decoration_manager_v1 *xdg_decoration_manager = NULL; | 
					
						
							| 
									
										
										
										
											2019-08-16 16:46:51 +00:00
										 |  |  | 	struct wlr_screencopy_manager_v1 *screencopy_manager = NULL; | 
					
						
							| 
									
										
										
										
											2019-08-16 17:04:28 +00:00
										 |  |  | 	struct wlr_xdg_output_manager_v1 *output_manager = NULL; | 
					
						
							| 
									
										
										
										
											2019-12-20 12:23:16 +01:00
										 |  |  | 	struct wlr_gamma_control_manager_v1 *gamma_control_manager = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	struct wlr_xdg_shell *xdg_shell = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = NULL; | 
					
						
							| 
									
										
										
										
											2019-01-03 13:55:38 +01:00
										 |  |  | 	struct wlr_xcursor_manager *xcursor_manager = NULL; | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	int ret = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 	if (!parse_args(&server, argc, argv)) { | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef DEBUG
 | 
					
						
							|  |  |  | 	wlr_log_init(WLR_DEBUG, NULL); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	wlr_log_init(WLR_ERROR, NULL); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	server.wl_display = wl_display_create(); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	if (!server.wl_display) { | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Cannot allocate a Wayland display"); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	event_loop = wl_display_get_event_loop(server.wl_display); | 
					
						
							| 
									
										
										
										
											2019-02-21 11:38:30 +01:00
										 |  |  | 	sigint_source = wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server.wl_display); | 
					
						
							|  |  |  | 	sigterm_source = wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server.wl_display); | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	server.backend = wlr_backend_autocreate(server.wl_display, NULL); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	if (!server.backend) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the wlroots backend"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | 	if (!drop_permissions()) { | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	renderer = wlr_backend_get_renderer(server.backend); | 
					
						
							| 
									
										
										
										
											2018-11-27 22:06:04 +01:00
										 |  |  | 	wlr_renderer_init_wl_display(renderer, server.wl_display); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 	wl_list_init(&server.views); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	server.output_layout = wlr_output_layout_create(); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	if (!server.output_layout) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create output layout"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-25 20:27:58 +01:00
										 |  |  | 	compositor = wlr_compositor_create(server.wl_display, renderer); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	if (!compositor) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the wlroots compositor"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 12:33:15 +01:00
										 |  |  | 	data_device_manager = wlr_data_device_manager_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!data_device_manager) { | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the data device manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Configure a listener to be notified when new outputs are
 | 
					
						
							| 
									
										
										
										
											2018-11-23 00:11:18 +01:00
										 |  |  | 	 * available on the backend. We use this only to detect the | 
					
						
							|  |  |  | 	 * first output and ignore subsequent outputs. */ | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 	server.new_output.notify = handle_new_output; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	wl_signal_add(&server.backend->events.new_output, &server.new_output); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-31 14:43:54 +01:00
										 |  |  | 	server.seat = seat_create(&server); | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 	if (!server.seat) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the seat"); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-04 17:06:27 +01:00
										 |  |  | 	server.idle = wlr_idle_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!server.idle) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the idle tracker"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 23:24:51 +01:00
										 |  |  | 	server.idle_inhibit_v1 = wlr_idle_inhibit_v1_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!server.idle_inhibit_v1) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Cannot create the idle inhibitor"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	server.new_idle_inhibitor_v1.notify = handle_idle_inhibitor_v1_new; | 
					
						
							|  |  |  | 	wl_signal_add(&server.idle_inhibit_v1->events.new_inhibitor, &server.new_idle_inhibitor_v1); | 
					
						
							|  |  |  | 	wl_list_init(&server.inhibitors); | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 	xdg_shell = wlr_xdg_shell_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!xdg_shell) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the XDG shell interface"); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 	server.new_xdg_shell_surface.notify = handle_xdg_shell_surface_new; | 
					
						
							|  |  |  | 	wl_signal_add(&xdg_shell->events.new_surface, &server.new_xdg_shell_surface); | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 	xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(server.wl_display); | 
					
						
							| 
									
										
										
										
											2019-02-23 17:08:54 +01:00
										 |  |  | 	if (!xdg_decoration_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the XDG decoration manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 	wl_signal_add(&xdg_decoration_manager->events.new_toplevel_decoration, &server.xdg_toplevel_decoration); | 
					
						
							|  |  |  | 	server.xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-23 17:05:02 +01:00
										 |  |  | 	server_decoration_manager = wlr_server_decoration_manager_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!server_decoration_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the server decoration manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wlr_server_decoration_manager_set_default_mode(server_decoration_manager, | 
					
						
							|  |  |  | 						       server.xdg_decoration ? | 
					
						
							|  |  |  | 						       WLR_SERVER_DECORATION_MANAGER_MODE_SERVER : | 
					
						
							|  |  |  | 						       WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 16:46:51 +00:00
										 |  |  | 	screencopy_manager = wlr_screencopy_manager_v1_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!screencopy_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the screencopy manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-08-16 17:04:28 +00:00
										 |  |  | 	output_manager = wlr_xdg_output_manager_v1_create(server.wl_display, server.output_layout); | 
					
						
							|  |  |  | 	if (!output_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the output manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-20 12:23:16 +01:00
										 |  |  | 	gamma_control_manager = wlr_gamma_control_manager_v1_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!gamma_control_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | 	xwayland = wlr_xwayland_create(server.wl_display, compositor, true); | 
					
						
							| 
									
										
										
										
											2019-01-17 22:25:20 +01:00
										 |  |  | 	if (!xwayland) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Cannot create XWayland server"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 	server.new_xwayland_surface.notify = handle_xwayland_surface_new; | 
					
						
							|  |  |  | 	wl_signal_add(&xwayland->events.new_surface, &server.new_xwayland_surface); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-03 13:55:38 +01:00
										 |  |  | 	xcursor_manager = wlr_xcursor_manager_create(DEFAULT_XCURSOR, XCURSOR_SIZE); | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 	if (!xcursor_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Cannot create XWayland XCursor manager"); | 
					
						
							|  |  |  | 	        ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-03-23 16:42:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:13 +01:00
										 |  |  | 	if (setenv("DISPLAY", xwayland->display_name, true) < 0) { | 
					
						
							| 
									
										
										
										
											2019-03-23 16:42:31 +01:00
										 |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland.", | 
					
						
							|  |  |  | 			      "Clients may not be able to connect"); | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2019-04-20 15:49:46 +02:00
										 |  |  | 		wlr_log(WLR_DEBUG, "XWayland is running on display %s", xwayland->display_name); | 
					
						
							| 
									
										
										
										
											2019-03-23 16:42:31 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 	if (wlr_xcursor_manager_load(xcursor_manager, 1)) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	struct wlr_xcursor *xcursor = | 
					
						
							|  |  |  | 		wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1); | 
					
						
							|  |  |  | 	if (xcursor) { | 
					
						
							|  |  |  | 		struct wlr_xcursor_image *image = xcursor->images[0]; | 
					
						
							|  |  |  | 		wlr_xwayland_set_cursor(xwayland, image->buffer, | 
					
						
							|  |  |  | 					image->width * 4, image->width, image->height, | 
					
						
							|  |  |  | 					image->hotspot_x, image->hotspot_y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	const char *socket = wl_display_add_socket_auto(server.wl_display); | 
					
						
							|  |  |  | 	if (!socket) { | 
					
						
							|  |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to open Wayland socket"); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 	        goto end; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!wlr_backend_start(server.backend)) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to start the wlroots backend"); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-23 20:18:13 +01:00
										 |  |  | 	if (setenv("WAYLAND_DISPLAY", socket, true) < 0) { | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to set WAYLAND_DISPLAY.", | 
					
						
							|  |  |  | 			      "Clients may not be able to connect"); | 
					
						
							| 
									
										
										
										
											2019-01-17 21:46:32 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		wlr_log(WLR_DEBUG, "Cage is running on Wayland display %s", socket); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							| 
									
										
										
										
											2019-01-17 22:25:20 +01:00
										 |  |  | 	wlr_xwayland_set_seat(xwayland, server.seat->seat); | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 	pid_t pid; | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 	if (!spawn_primary_client(argv + optind, &pid)) { | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl_display_run(server.wl_display); | 
					
						
							| 
									
										
										
										
											2019-01-18 13:08:15 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							|  |  |  | 	wlr_xwayland_destroy(xwayland); | 
					
						
							|  |  |  | 	wlr_xcursor_manager_destroy(xcursor_manager); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	wl_display_destroy_clients(server.wl_display); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 	waitpid(pid, NULL, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | end: | 
					
						
							| 
									
										
										
										
											2019-02-21 11:38:30 +01:00
										 |  |  | 	wl_event_source_remove(sigint_source); | 
					
						
							|  |  |  | 	wl_event_source_remove(sigterm_source); | 
					
						
							| 
									
										
										
										
											2019-02-02 17:13:10 +01:00
										 |  |  | 	seat_destroy(server.seat); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	wlr_output_layout_destroy(server.output_layout); | 
					
						
							|  |  |  | 	/* This function is not null-safe, but we only ever get here
 | 
					
						
							|  |  |  | 	   with a proper wl_display. */ | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	wl_display_destroy(server.wl_display); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | } |