| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Cage: A Wayland kiosk. | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-01-26 11:56:59 +01:00
										 |  |  |  * Copyright (C) 2018-2020 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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:07:03 +01:00
										 |  |  | #include <fcntl.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>
 | 
					
						
							| 
									
										
										
										
											2019-12-20 17:16:53 +01:00
										 |  |  | #include <wayland-server-core.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #include <wlr/backend.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:31:14 +02:00
										 |  |  | #include <wlr/render/allocator.h>
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | #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 16:58:56 +01:00
										 |  |  | #include <wlr/types/wlr_export_dmabuf_v1.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>
 | 
					
						
							| 
									
										
										
										
											2023-07-21 15:37:38 +02:00
										 |  |  | #include <wlr/types/wlr_output_management_v1.h>
 | 
					
						
							| 
									
										
										
										
											2021-12-17 12:06:01 +01:00
										 |  |  | #include <wlr/types/wlr_presentation_time.h>
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:14:37 +01:00
										 |  |  | #include <wlr/types/wlr_relative_pointer_v1.h>
 | 
					
						
							| 
									
										
										
										
											2021-08-09 20:06:57 +02:00
										 |  |  | #include <wlr/types/wlr_scene.h>
 | 
					
						
							| 
									
										
										
										
											2019-12-20 16:58:56 +01:00
										 |  |  | #include <wlr/types/wlr_screencopy_v1.h>
 | 
					
						
							| 
									
										
										
										
											2019-02-23 17:05:02 +01:00
										 |  |  | #include <wlr/types/wlr_server_decoration.h>
 | 
					
						
							| 
									
										
										
										
											2022-12-16 05:43:10 -05:00
										 |  |  | #include <wlr/types/wlr_single_pixel_buffer_v1.h>
 | 
					
						
							| 
									
										
										
										
											2022-01-20 11:13:10 +00:00
										 |  |  | #include <wlr/types/wlr_subcompositor.h>
 | 
					
						
							| 
									
										
										
										
											2021-12-17 12:02:42 +01:00
										 |  |  | #include <wlr/types/wlr_viewporter.h>
 | 
					
						
							| 
									
										
										
										
											2023-01-07 14:28:40 +00:00
										 |  |  | #include <wlr/types/wlr_virtual_keyboard_v1.h>
 | 
					
						
							|  |  |  | #include <wlr/types/wlr_virtual_pointer_v1.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>
 | 
					
						
							| 
									
										
										
										
											2019-08-16 17:04:28 +00:00
										 |  |  | #include <wlr/types/wlr_xdg_output_v1.h>
 | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | #include <wlr/types/wlr_xdg_shell.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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | static int | 
					
						
							|  |  |  | sigchld_handler(int fd, uint32_t mask, void *data) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	struct cg_server *server = data; | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Close Cage's read pipe. */ | 
					
						
							|  |  |  | 	close(fd); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (mask & WL_EVENT_HANGUP) { | 
					
						
							|  |  |  | 		wlr_log(WLR_DEBUG, "Child process closed normally"); | 
					
						
							|  |  |  | 	} else if (mask & WL_EVENT_ERROR) { | 
					
						
							|  |  |  | 		wlr_log(WLR_DEBUG, "Connection closed by server"); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	server->return_app_code = true; | 
					
						
							|  |  |  | 	wl_display_terminate(server->wl_display); | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:07:03 +01:00
										 |  |  | static bool | 
					
						
							|  |  |  | set_cloexec(int fd) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int flags = fcntl(fd, F_GETFD); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (flags == -1) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to set the CLOEXEC flag: fnctl failed"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	flags = flags | FD_CLOEXEC; | 
					
						
							|  |  |  | 	if (fcntl(fd, F_SETFD, flags) == -1) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to set the CLOEXEC flag: fnctl failed"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | static bool | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | spawn_primary_client(struct cg_server *server, char *argv[], pid_t *pid_out, struct wl_event_source **sigchld_source) | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 	int fd[2]; | 
					
						
							|  |  |  | 	if (pipe(fd) != 0) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create pipe"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 		/* Close read, we only need write in the primary client process. */ | 
					
						
							|  |  |  | 		close(fd[0]); | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 		execvp(argv[0], argv); | 
					
						
							| 
									
										
										
										
											2023-07-17 18:28:54 +02:00
										 |  |  | 		/* execvp() returns only on failure */ | 
					
						
							|  |  |  | 		wlr_log_errno(WLR_ERROR, "Failed to spawn client"); | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 		_exit(1); | 
					
						
							|  |  |  | 	} else if (pid == -1) { | 
					
						
							|  |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to fork"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 18:55:07 +01:00
										 |  |  | 	/* Set this early so that if we fail, the client process will be cleaned up properly. */ | 
					
						
							|  |  |  | 	*pid_out = pid; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-06 23:07:03 +01:00
										 |  |  | 	if (!set_cloexec(fd[0]) || !set_cloexec(fd[1])) { | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 	/* Close write, we only need read in Cage. */ | 
					
						
							|  |  |  | 	close(fd[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	struct wl_event_loop *event_loop = wl_display_get_event_loop(server->wl_display); | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 	uint32_t mask = WL_EVENT_HANGUP | WL_EVENT_ERROR; | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	*sigchld_source = wl_event_loop_add_fd(event_loop, fd[0], mask, sigchld_handler, server); | 
					
						
							| 
									
										
										
										
											2020-01-28 21:32:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 	wlr_log(WLR_DEBUG, "Child process created with pid %d", pid); | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | static int | 
					
						
							| 
									
										
										
										
											2020-01-26 15:00:34 +01:00
										 |  |  | cleanup_primary_client(pid_t pid) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	waitpid(pid, &status, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (WIFEXITED(status)) { | 
					
						
							|  |  |  | 		wlr_log(WLR_DEBUG, "Child exited normally with exit status %d", WEXITSTATUS(status)); | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 		return WEXITSTATUS(status); | 
					
						
							| 
									
										
										
										
											2020-01-26 15:00:34 +01:00
										 |  |  | 	} else if (WIFSIGNALED(status)) { | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 		/* Mimic Bash and other shells for the exit status */ | 
					
						
							| 
									
										
										
										
											2020-01-26 15:00:34 +01:00
										 |  |  | 		wlr_log(WLR_DEBUG, "Child was terminated by a signal (%d)", WTERMSIG(status)); | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 		return 128 + WTERMSIG(status); | 
					
						
							| 
									
										
										
										
											2020-01-26 15:00:34 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return 0; | 
					
						
							| 
									
										
										
										
											2020-01-26 15:00:34 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | static bool | 
					
						
							|  |  |  | drop_permissions(void) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2021-09-13 13:30:59 +00:00
										 |  |  | 	if (getuid() == 0 || getgid() == 0) { | 
					
						
							|  |  |  | 		wlr_log(WLR_INFO, "Running as root user, this is dangerous"); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | 	if (getuid() != geteuid() || getgid() != getegid()) { | 
					
						
							| 
									
										
										
										
											2021-09-13 13:30:59 +00:00
										 |  |  | 		wlr_log(WLR_INFO, "setuid/setgid bit detected, dropping permissions"); | 
					
						
							| 
									
										
										
										
											2020-04-17 21:58:26 +02:00
										 |  |  | 		// Set the gid and uid in the correct order.
 | 
					
						
							|  |  |  | 		if (setgid(getgid()) != 0 || setuid(getuid()) != 0) { | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | 			wlr_log(WLR_ERROR, "Unable to drop root, refusing to start"); | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 21:58:26 +02:00
										 |  |  | 	if (setgid(0) != -1 || setuid(0) != -1) { | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, | 
					
						
							|  |  |  | 			"Unable to drop root (we shouldn't be able to restore it after setuid), refusing to start"); | 
					
						
							| 
									
										
										
										
											2019-04-25 07:08:04 +00:00
										 |  |  | 		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: | 
					
						
							| 
									
										
										
										
											2020-01-26 11:53:10 +01:00
										 |  |  | 		return 0; | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | static void | 
					
						
							|  |  |  | usage(FILE *file, const char *cage) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +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-02-26 18:56:23 +01:00
										 |  |  | 		" -h\t Display this help message\n" | 
					
						
							| 
									
										
										
										
											2020-05-31 16:20:59 +02:00
										 |  |  | 		" -m extend Extend the display across all connected outputs (default)\n" | 
					
						
							|  |  |  | 		" -m last Use only the last connected output\n" | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 		" -s\t Allow VT switching\n" | 
					
						
							| 
									
										
										
										
											2020-01-26 17:49:26 +01:00
										 |  |  | 		" -v\t Show the version number and exit\n" | 
					
						
							| 
									
										
										
										
											2019-02-26 18:56:23 +01:00
										 |  |  | 		"\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; | 
					
						
							| 
									
										
										
										
											2022-01-14 21:22:11 +01:00
										 |  |  | 	while ((c = getopt(argc, argv, "dhm:sv")) != -1) { | 
					
						
							| 
									
										
										
										
											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-01-25 15:36:04 +01:00
										 |  |  | 		case 'h': | 
					
						
							|  |  |  | 			usage(stdout, argv[0]); | 
					
						
							|  |  |  | 			return false; | 
					
						
							| 
									
										
										
										
											2020-05-31 16:20:59 +02:00
										 |  |  | 		case 'm': | 
					
						
							|  |  |  | 			if (strcmp(optarg, "last") == 0) { | 
					
						
							|  |  |  | 				server->output_mode = CAGE_MULTI_OUTPUT_MODE_LAST; | 
					
						
							|  |  |  | 			} else if (strcmp(optarg, "extend") == 0) { | 
					
						
							|  |  |  | 				server->output_mode = CAGE_MULTI_OUTPUT_MODE_EXTEND; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 		case 's': | 
					
						
							|  |  |  | 			server->allow_vt_switch = true; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2020-01-26 17:49:26 +01:00
										 |  |  | 		case 'v': | 
					
						
							|  |  |  | 			fprintf(stdout, "Cage version " CAGE_VERSION "\n"); | 
					
						
							|  |  |  | 			exit(0); | 
					
						
							| 
									
										
										
										
											2019-01-25 15:36:04 +01:00
										 |  |  | 		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}; | 
					
						
							| 
									
										
										
										
											2019-02-27 18:27:25 +01:00
										 |  |  | 	struct wl_event_source *sigchld_source = NULL; | 
					
						
							| 
									
										
										
										
											2020-02-07 18:55:07 +01:00
										 |  |  | 	pid_t pid = 0; | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	int ret = 0, app_ret = 0; | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-01-25 22:51:15 +01:00
										 |  |  | 	/* Wayland requires XDG_RUNTIME_DIR to be set. */ | 
					
						
							|  |  |  | 	if (!getenv("XDG_RUNTIME_DIR")) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "XDG_RUNTIME_DIR is not set in the environment"); | 
					
						
							|  |  |  | 		return 1; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wl_event_loop *event_loop = wl_display_get_event_loop(server.wl_display); | 
					
						
							|  |  |  | 	struct wl_event_source *sigint_source = | 
					
						
							|  |  |  | 		wl_event_loop_add_signal(event_loop, SIGINT, handle_signal, &server.wl_display); | 
					
						
							|  |  |  | 	struct wl_event_source *sigterm_source = | 
					
						
							|  |  |  | 		wl_event_loop_add_signal(event_loop, SIGTERM, handle_signal, &server.wl_display); | 
					
						
							| 
									
										
										
										
											2018-12-16 21:58:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-05 09:02:58 +00:00
										 |  |  | 	server.backend = wlr_backend_autocreate(server.wl_display); | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 	if (!server.backend) { | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 		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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-11 11:31:14 +02:00
										 |  |  | 	server.renderer = wlr_renderer_autocreate(server.backend); | 
					
						
							|  |  |  | 	if (!server.renderer) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the wlroots renderer"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	server.allocator = wlr_allocator_autocreate(server.backend, server.renderer); | 
					
						
							|  |  |  | 	if (!server.allocator) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the wlroots allocator"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wlr_renderer_init_wl_display(server.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); | 
					
						
							| 
									
										
										
										
											2019-12-21 16:10:11 +01:00
										 |  |  | 	wl_list_init(&server.outputs); | 
					
						
							| 
									
										
										
										
											2019-02-17 22:17:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2021-08-09 20:06:57 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-07-21 15:37:38 +02:00
										 |  |  | 	server.output_layout_change.notify = handle_output_layout_change; | 
					
						
							|  |  |  | 	wl_signal_add(&server.output_layout->events.change, &server.output_layout_change); | 
					
						
							| 
									
										
										
										
											2021-08-09 20:06:57 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	server.scene = wlr_scene_create(); | 
					
						
							|  |  |  | 	if (!server.scene) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create scene"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 12:18:23 +02:00
										 |  |  | 	wlr_scene_attach_output_layout(server.scene, server.output_layout); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_compositor *compositor = wlr_compositor_create(server.wl_display, server.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; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_subcompositor_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2022-01-20 11:13:10 +00:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the wlroots subcompositor"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_data_device_manager_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 	wl_signal_add(&server.backend->events.new_output, &server.new_output); | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 	server.seat = seat_create(&server, server.backend); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_xdg_shell *xdg_shell = wlr_xdg_shell_create(server.wl_display, 4); | 
					
						
							| 
									
										
										
										
											2018-12-31 00:12:33 +01:00
										 |  |  | 	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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_xdg_decoration_manager_v1 *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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_server_decoration_manager *server_decoration_manager = | 
					
						
							|  |  |  | 		wlr_server_decoration_manager_create(server.wl_display); | 
					
						
							| 
									
										
										
										
											2019-02-23 17:05:02 +01:00
										 |  |  | 	if (!server_decoration_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the server decoration manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | 	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-02-23 17:05:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_viewporter_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2021-12-17 12:02:42 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the viewporter interface"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_presentation *presentation = wlr_presentation_create(server.wl_display, server.backend); | 
					
						
							| 
									
										
										
										
											2021-12-17 12:06:01 +01:00
										 |  |  | 	if (!presentation) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the presentation interface"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wlr_scene_set_presentation(server.scene, presentation); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_export_dmabuf_manager_v1_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2019-12-20 16:58:56 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the export DMABUF manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_screencopy_manager_v1_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2019-08-16 16:46:51 +00:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the screencopy manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_single_pixel_buffer_manager_v1_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2022-12-16 05:43:10 -05:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the single pixel buffer manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_xdg_output_manager_v1_create(server.wl_display, server.output_layout)) { | 
					
						
							| 
									
										
										
										
											2019-08-16 17:04:28 +00:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the output manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-21 15:37:38 +02:00
										 |  |  | 	server.output_manager_v1 = wlr_output_manager_v1_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!server.output_manager_v1) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the output manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	server.output_manager_apply.notify = handle_output_manager_apply; | 
					
						
							|  |  |  | 	wl_signal_add(&server.output_manager_v1->events.apply, &server.output_manager_apply); | 
					
						
							|  |  |  | 	server.output_manager_test.notify = handle_output_manager_test; | 
					
						
							|  |  |  | 	wl_signal_add(&server.output_manager_v1->events.test, &server.output_manager_test); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	if (!wlr_gamma_control_manager_v1_create(server.wl_display)) { | 
					
						
							| 
									
										
										
										
											2019-12-20 12:23:16 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Unable to create the gamma control manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_virtual_keyboard_manager_v1 *virtual_keyboard = | 
					
						
							|  |  |  | 		wlr_virtual_keyboard_manager_v1_create(server.wl_display); | 
					
						
							| 
									
										
										
										
											2023-01-07 14:28:40 +00:00
										 |  |  | 	if (!virtual_keyboard) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the virtual keyboard manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wl_signal_add(&virtual_keyboard->events.new_virtual_keyboard, &server.new_virtual_keyboard); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_virtual_pointer_manager_v1 *virtual_pointer = | 
					
						
							|  |  |  | 		wlr_virtual_pointer_manager_v1_create(server.wl_display); | 
					
						
							| 
									
										
										
										
											2023-01-07 14:28:40 +00:00
										 |  |  | 	if (!virtual_pointer) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the virtual pointer manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	wl_signal_add(&virtual_pointer->events.new_virtual_pointer, &server.new_virtual_pointer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:14:37 +01:00
										 |  |  | 	server.relative_pointer_manager = wlr_relative_pointer_manager_v1_create(server.wl_display); | 
					
						
							|  |  |  | 	if (!server.relative_pointer_manager) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "Unable to create the relative pointer manager"); | 
					
						
							|  |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | #if CAGE_HAS_XWAYLAND
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-09 17:27:32 +01:00
										 |  |  | 	struct wlr_xcursor_manager *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"); | 
					
						
							| 
									
										
										
										
											2020-01-05 13:42:17 +01:00
										 |  |  | 		ret = 1; | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | 		wlr_log_errno(WLR_ERROR, "Unable to set DISPLAY for XWayland. Clients may not be able to connect"); | 
					
						
							| 
									
										
										
										
											2019-03-23 16:42:31 +01:00
										 |  |  | 	} 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
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-16 15:21:17 +02:00
										 |  |  | 	if (!wlr_xcursor_manager_load(xcursor_manager, 1)) { | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 		wlr_log(WLR_ERROR, "Cannot load XWayland XCursor theme"); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | 	struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(xcursor_manager, DEFAULT_XCURSOR, 1); | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 	if (xcursor) { | 
					
						
							|  |  |  | 		struct wlr_xcursor_image *image = xcursor->images[0]; | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +01:00
										 |  |  | 		wlr_xwayland_set_cursor(xwayland, image->buffer, image->width * 4, image->width, image->height, | 
					
						
							| 
									
										
										
										
											2018-12-31 17:24:21 +01:00
										 |  |  | 					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; | 
					
						
							| 
									
										
										
										
											2020-01-05 13:42:17 +01:00
										 |  |  | 		goto end; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-15 16:50:38 +02:00
										 |  |  | 	if (!wlr_backend_start(server.backend)) { | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 		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) { | 
					
						
							| 
									
										
										
										
											2020-02-17 19:49:47 +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 { | 
					
						
							| 
									
										
										
										
											2020-01-26 17:49:26 +01:00
										 |  |  | 		wlr_log(WLR_DEBUG, "Cage " CAGE_VERSION " 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
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	if (!spawn_primary_client(&server, argv + optind, &pid, &sigchld_source)) { | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 		ret = 1; | 
					
						
							|  |  |  | 		goto end; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-11-08 17:22:06 +01:00
										 |  |  | 	seat_center_cursor(server.seat); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 18:55:07 +01:00
										 |  |  | end: | 
					
						
							| 
									
										
										
										
											2023-08-18 15:25:21 +02:00
										 |  |  | 	app_ret = cleanup_primary_client(pid); | 
					
						
							|  |  |  | 	if (!ret && server.return_app_code) | 
					
						
							|  |  |  | 		ret = app_ret; | 
					
						
							| 
									
										
										
										
											2018-12-16 21:51:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-21 11:38:30 +01:00
										 |  |  | 	wl_event_source_remove(sigint_source); | 
					
						
							|  |  |  | 	wl_event_source_remove(sigterm_source); | 
					
						
							| 
									
										
										
										
											2020-02-22 00:23:03 +01:00
										 |  |  | 	if (sigchld_source) { | 
					
						
							|  |  |  | 		wl_event_source_remove(sigchld_source); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-02-02 17:13:10 +01:00
										 |  |  | 	seat_destroy(server.seat); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	/* 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); | 
					
						
							| 
									
										
										
										
											2020-01-28 21:19:50 +01:00
										 |  |  | 	wlr_output_layout_destroy(server.output_layout); | 
					
						
							| 
									
										
										
										
											2018-12-14 17:06:36 +01:00
										 |  |  | 	return ret; | 
					
						
							| 
									
										
										
										
											2018-11-22 19:59:06 +01:00
										 |  |  | } |