| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | #include <assert.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include <errno.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-19 17:59:31 +02:00
										 |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #include <signal.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-19 17:59:31 +02:00
										 |  |  | #include <sys/socket.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-23 23:19:15 +02:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <sys/wait.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-19 17:59:31 +02:00
										 |  |  | #include <time.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-14 17:53:56 +02:00
										 |  |  | #include <wlr/types/wlr_seat.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 09:12:31 +01:00
										 |  |  | #include <wlr/util/log.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | #include <wlr/xwayland/shell.h>
 | 
					
						
							| 
									
										
										
										
											2022-10-14 17:53:56 +02:00
										 |  |  | #include <wlr/xwayland/xwayland.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-20 07:59:03 +02:00
										 |  |  | #include "sockets.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-03 17:03:19 +01:00
										 |  |  | #include "xwayland/xwm.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-19 17:59:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | struct wlr_xwayland_cursor { | 
					
						
							|  |  |  | 	uint8_t *pixels; | 
					
						
							|  |  |  | 	uint32_t stride; | 
					
						
							|  |  |  | 	uint32_t width; | 
					
						
							|  |  |  | 	uint32_t height; | 
					
						
							|  |  |  | 	int32_t hotspot_x; | 
					
						
							|  |  |  | 	int32_t hotspot_y; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | static void handle_server_destroy(struct wl_listener *listener, void *data) { | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = | 
					
						
							|  |  |  | 		wl_container_of(listener, xwayland, server_destroy); | 
					
						
							| 
									
										
										
										
											2022-04-20 17:50:55 +02:00
										 |  |  | 	// Server is being destroyed so avoid destroying it once again.
 | 
					
						
							|  |  |  | 	xwayland->server = NULL; | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	wlr_xwayland_destroy(xwayland); | 
					
						
							| 
									
										
										
										
											2017-08-19 17:59:31 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | static void handle_server_start(struct wl_listener *listener, void *data) { | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = | 
					
						
							|  |  |  | 		wl_container_of(listener, xwayland, server_start); | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	if (xwayland->shell_v1 != NULL) { | 
					
						
							|  |  |  | 		wlr_xwayland_shell_v1_set_client(xwayland->shell_v1, xwayland->server->client); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | static void xwayland_mark_ready(struct wlr_xwayland *xwayland) { | 
					
						
							|  |  |  | 	assert(xwayland->server->wm_fd[0] >= 0); | 
					
						
							|  |  |  | 	xwayland->xwm = xwm_create(xwayland, xwayland->server->wm_fd[0]); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (!xwayland->xwm) { | 
					
						
							| 
									
										
										
										
											2018-05-07 00:43:26 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (xwayland->seat) { | 
					
						
							|  |  |  | 		xwm_set_seat(xwayland->xwm, xwayland->seat); | 
					
						
							| 
									
										
										
										
											2017-11-22 08:23:23 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (xwayland->cursor != NULL) { | 
					
						
							|  |  |  | 		struct wlr_xwayland_cursor *cur = xwayland->cursor; | 
					
						
							|  |  |  | 		xwm_set_cursor(xwayland->xwm, cur->pixels, cur->stride, cur->width, | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 			cur->height, cur->hotspot_x, cur->hotspot_y); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&xwayland->events.ready, NULL); | 
					
						
							| 
									
										
										
										
											2018-05-06 20:23:10 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | static void handle_server_ready(struct wl_listener *listener, void *data) { | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = | 
					
						
							|  |  |  | 		wl_container_of(listener, xwayland, server_ready); | 
					
						
							|  |  |  | 	xwayland_mark_ready(xwayland); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 21:36:56 +08:00
										 |  |  | static void handle_shell_destroy(struct wl_listener *listener, void *data) { | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = | 
					
						
							|  |  |  | 		wl_container_of(listener, xwayland, shell_destroy); | 
					
						
							|  |  |  | 	xwayland->shell_v1 = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) { | 
					
						
							|  |  |  | 	if (!xwayland) { | 
					
						
							| 
									
										
										
										
											2018-09-08 13:00:56 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-22 20:37:39 +03:00
										 |  |  | 	wl_signal_emit_mutable(&xwayland->events.destroy, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	wl_list_remove(&xwayland->server_destroy.link); | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | 	wl_list_remove(&xwayland->server_start.link); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	wl_list_remove(&xwayland->server_ready.link); | 
					
						
							| 
									
										
										
										
											2023-09-08 21:36:56 +08:00
										 |  |  | 	wl_list_remove(&xwayland->shell_destroy.link); | 
					
						
							| 
									
										
										
										
											2021-01-17 22:26:10 +11:00
										 |  |  | 	free(xwayland->cursor); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	wlr_xwayland_set_seat(xwayland, NULL); | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	if (xwayland->own_server) { | 
					
						
							|  |  |  | 		wlr_xwayland_server_destroy(xwayland->server); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2023-06-22 16:28:43 +02:00
										 |  |  | 	xwayland->server = NULL; | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | 	wlr_xwayland_shell_v1_destroy(xwayland->shell_v1); | 
					
						
							| 
									
										
										
										
											2024-08-11 16:41:19 +00:00
										 |  |  | 	xwm_destroy(xwayland->xwm); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	free(xwayland); | 
					
						
							| 
									
										
										
										
											2017-08-20 07:59:03 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | struct wlr_xwayland *wlr_xwayland_create_with_server(struct wl_display *wl_display, | 
					
						
							|  |  |  | 		struct wlr_compositor *compositor, struct wlr_xwayland_server *server) { | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	struct wlr_xwayland *xwayland = calloc(1, sizeof(*xwayland)); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (!xwayland) { | 
					
						
							| 
									
										
										
										
											2018-05-08 22:22:35 +02:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-06 20:23:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	xwayland->wl_display = wl_display; | 
					
						
							|  |  |  | 	xwayland->compositor = compositor; | 
					
						
							| 
									
										
										
										
											2018-05-06 20:23:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-22 20:37:39 +03:00
										 |  |  | 	wl_signal_init(&xwayland->events.destroy); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	wl_signal_init(&xwayland->events.new_surface); | 
					
						
							|  |  |  | 	wl_signal_init(&xwayland->events.ready); | 
					
						
							| 
									
										
										
										
											2021-01-29 16:45:44 +01:00
										 |  |  | 	wl_signal_init(&xwayland->events.remove_startup_info); | 
					
						
							| 
									
										
										
										
											2017-12-29 20:50:50 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	xwayland->server = server; | 
					
						
							|  |  |  | 	xwayland->display_name = xwayland->server->display_name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xwayland->server_destroy.notify = handle_server_destroy; | 
					
						
							|  |  |  | 	wl_signal_add(&xwayland->server->events.destroy, &xwayland->server_destroy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xwayland->server_start.notify = handle_server_start; | 
					
						
							|  |  |  | 	wl_signal_add(&xwayland->server->events.start, &xwayland->server_start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	xwayland->server_ready.notify = handle_server_ready; | 
					
						
							|  |  |  | 	wl_signal_add(&xwayland->server->events.ready, &xwayland->server_ready); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl_list_init(&xwayland->shell_destroy.link); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (server->ready) { | 
					
						
							|  |  |  | 		xwayland_mark_ready(xwayland); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return xwayland; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display, | 
					
						
							|  |  |  | 		struct wlr_compositor *compositor, bool lazy) { | 
					
						
							|  |  |  | 	struct wlr_xwayland_shell_v1 *shell_v1 = wlr_xwayland_shell_v1_create(wl_display, 1); | 
					
						
							|  |  |  | 	if (shell_v1 == NULL) { | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-19 17:28:23 +02:00
										 |  |  | 	struct wlr_xwayland_server_options options = { | 
					
						
							|  |  |  | 		.lazy = lazy, | 
					
						
							|  |  |  | 		.enable_wm = true, | 
					
						
							| 
									
										
										
										
											2022-12-08 02:04:58 +01:00
										 |  |  | #if HAVE_XCB_XFIXES_SET_CLIENT_DISCONNECT_MODE
 | 
					
						
							| 
									
										
										
										
											2021-06-25 13:49:47 +02:00
										 |  |  | 		.terminate_delay = lazy ? 10 : 0, | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2020-05-19 17:28:23 +02:00
										 |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	struct wlr_xwayland_server *server = wlr_xwayland_server_create(wl_display, &options); | 
					
						
							|  |  |  | 	if (server == NULL) { | 
					
						
							|  |  |  | 		goto error_shell_v1; | 
					
						
							| 
									
										
										
										
											2018-05-06 20:23:10 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	struct wlr_xwayland *xwayland = wlr_xwayland_create_with_server(wl_display, compositor, server); | 
					
						
							|  |  |  | 	if (xwayland == NULL) { | 
					
						
							|  |  |  | 		goto error_server; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-10-18 13:09:17 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 	xwayland->shell_v1 = shell_v1; | 
					
						
							|  |  |  | 	xwayland->own_server = true; | 
					
						
							| 
									
										
										
										
											2018-05-06 20:23:10 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-08 21:36:56 +08:00
										 |  |  | 	xwayland->shell_destroy.notify = handle_shell_destroy; | 
					
						
							|  |  |  | 	wl_signal_add(&xwayland->shell_v1->events.destroy, &xwayland->shell_destroy); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	return xwayland; | 
					
						
							| 
									
										
										
										
											2023-10-09 10:58:00 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | error_server: | 
					
						
							|  |  |  | 	wlr_xwayland_server_destroy(server); | 
					
						
							|  |  |  | error_shell_v1: | 
					
						
							|  |  |  | 	wlr_xwayland_shell_v1_destroy(shell_v1); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2017-08-20 07:59:03 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | void wlr_xwayland_set_cursor(struct wlr_xwayland *xwayland, | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 		uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height, | 
					
						
							|  |  |  | 		int32_t hotspot_x, int32_t hotspot_y) { | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (xwayland->xwm != NULL) { | 
					
						
							|  |  |  | 		xwm_set_cursor(xwayland->xwm, pixels, stride, width, height, | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 			hotspot_x, hotspot_y); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	free(xwayland->cursor); | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	xwayland->cursor = calloc(1, sizeof(*xwayland->cursor)); | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	if (xwayland->cursor == NULL) { | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-05 10:24:08 +02:00
										 |  |  | 	xwayland->cursor->pixels = pixels; | 
					
						
							|  |  |  | 	xwayland->cursor->stride = stride; | 
					
						
							|  |  |  | 	xwayland->cursor->width = width; | 
					
						
							|  |  |  | 	xwayland->cursor->height = height; | 
					
						
							|  |  |  | 	xwayland->cursor->hotspot_x = hotspot_x; | 
					
						
							|  |  |  | 	xwayland->cursor->hotspot_y = hotspot_y; | 
					
						
							| 
									
										
										
										
											2017-11-02 16:49:22 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-11-22 08:10:06 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static void xwayland_handle_seat_destroy(struct wl_listener *listener, | 
					
						
							| 
									
										
										
										
											2017-12-29 17:55:16 +01:00
										 |  |  | 		void *data) { | 
					
						
							|  |  |  | 	struct wlr_xwayland *xwayland = | 
					
						
							|  |  |  | 		wl_container_of(listener, xwayland, seat_destroy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wlr_xwayland_set_seat(xwayland, NULL); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 08:10:06 -05:00
										 |  |  | void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland, | 
					
						
							|  |  |  | 		struct wlr_seat *seat) { | 
					
						
							| 
									
										
										
										
											2017-12-29 17:55:16 +01:00
										 |  |  | 	if (xwayland->seat) { | 
					
						
							|  |  |  | 		wl_list_remove(&xwayland->seat_destroy.link); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-22 08:23:23 -05:00
										 |  |  | 	xwayland->seat = seat; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (xwayland->xwm) { | 
					
						
							|  |  |  | 		xwm_set_seat(xwayland->xwm, seat); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-12-29 17:55:16 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (seat == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | 	xwayland->seat_destroy.notify = xwayland_handle_seat_destroy; | 
					
						
							| 
									
										
										
										
											2017-12-29 17:55:16 +01:00
										 |  |  | 	wl_signal_add(&seat->events.destroy, &xwayland->seat_destroy); | 
					
						
							| 
									
										
										
										
											2017-11-22 08:10:06 -05:00
										 |  |  | } |