1 #define _POSIX_C_SOURCE 200809L
2 #include <errno.h>
3 #include <fcntl.h>
4 #include <signal.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdlib.h>
8 #include <sys/socket.h>
9 #include <sys/types.h>
10 #include <sys/wait.h>
11 #include <time.h>
12 #include <unistd.h>
13 #include <wayland-server-core.h>
14 #include <wlr/util/log.h>
15 #include <wlr/xwayland.h>
16 #include "sockets.h"
17 #include "util/signal.h"
18 #include "xwayland/xwm.h"
19 
20 struct wlr_xwayland_cursor {
21 	uint8_t *pixels;
22 	uint32_t stride;
23 	uint32_t width;
24 	uint32_t height;
25 	int32_t hotspot_x;
26 	int32_t hotspot_y;
27 };
28 
handle_server_destroy(struct wl_listener * listener,void * data)29 static void handle_server_destroy(struct wl_listener *listener, void *data) {
30 	struct wlr_xwayland *xwayland =
31 		wl_container_of(listener, xwayland, server_destroy);
32 	wlr_xwayland_destroy(xwayland);
33 }
34 
handle_server_ready(struct wl_listener * listener,void * data)35 static void handle_server_ready(struct wl_listener *listener, void *data) {
36 	struct wlr_xwayland *xwayland =
37 		wl_container_of(listener, xwayland, server_ready);
38 	struct wlr_xwayland_server_ready_event *event = data;
39 
40 	xwayland->xwm = xwm_create(xwayland, event->wm_fd);
41 	if (!xwayland->xwm) {
42 		return;
43 	}
44 
45 	if (xwayland->seat) {
46 		xwm_set_seat(xwayland->xwm, xwayland->seat);
47 	}
48 
49 	if (xwayland->cursor != NULL) {
50 		struct wlr_xwayland_cursor *cur = xwayland->cursor;
51 		xwm_set_cursor(xwayland->xwm, cur->pixels, cur->stride, cur->width,
52 			cur->height, cur->hotspot_x, cur->hotspot_y);
53 		free(cur);
54 		xwayland->cursor = NULL;
55 	}
56 
57 	wlr_signal_emit_safe(&xwayland->events.ready, NULL);
58 }
59 
wlr_xwayland_destroy(struct wlr_xwayland * xwayland)60 void wlr_xwayland_destroy(struct wlr_xwayland *xwayland) {
61 	if (!xwayland) {
62 		return;
63 	}
64 
65 	wl_list_remove(&xwayland->server_destroy.link);
66 	wl_list_remove(&xwayland->server_ready.link);
67 
68 	wlr_xwayland_set_seat(xwayland, NULL);
69 	wlr_xwayland_server_destroy(xwayland->server);
70 	free(xwayland);
71 }
72 
wlr_xwayland_create(struct wl_display * wl_display,struct wlr_compositor * compositor,bool lazy)73 struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
74 		struct wlr_compositor *compositor, bool lazy) {
75 	struct wlr_xwayland *xwayland = calloc(1, sizeof(struct wlr_xwayland));
76 	if (!xwayland) {
77 		return NULL;
78 	}
79 
80 	xwayland->wl_display = wl_display;
81 	xwayland->compositor = compositor;
82 
83 	wl_signal_init(&xwayland->events.new_surface);
84 	wl_signal_init(&xwayland->events.ready);
85 
86 	struct wlr_xwayland_server_options options = {
87 		.lazy = lazy,
88 		.enable_wm = true,
89 	};
90 	xwayland->server = wlr_xwayland_server_create(wl_display, &options);
91 	if (xwayland->server == NULL) {
92 		free(xwayland);
93 		return NULL;
94 	}
95 
96 	xwayland->display_name = xwayland->server->display_name;
97 
98 	xwayland->server_destroy.notify = handle_server_destroy;
99 	wl_signal_add(&xwayland->server->events.destroy, &xwayland->server_destroy);
100 
101 	xwayland->server_ready.notify = handle_server_ready;
102 	wl_signal_add(&xwayland->server->events.ready, &xwayland->server_ready);
103 
104 	return xwayland;
105 }
106 
wlr_xwayland_set_scale(struct wlr_xwayland * xwayland,int32_t scale)107 void wlr_xwayland_set_scale(struct wlr_xwayland *xwayland, int32_t scale) {
108 	xwayland->server->scale = scale;
109 	if (xwayland->xwm != NULL) {
110 		xwm_scale_changed(xwayland->xwm);
111 	}
112 }
113 
wlr_xwayland_set_cursor(struct wlr_xwayland * xwayland,uint8_t * pixels,uint32_t stride,uint32_t width,uint32_t height,int32_t hotspot_x,int32_t hotspot_y)114 void wlr_xwayland_set_cursor(struct wlr_xwayland *xwayland,
115 		uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height,
116 		int32_t hotspot_x, int32_t hotspot_y) {
117 	if (xwayland->xwm != NULL) {
118 		xwm_set_cursor(xwayland->xwm, pixels, stride, width, height,
119 			hotspot_x, hotspot_y);
120 		return;
121 	}
122 
123 	free(xwayland->cursor);
124 
125 	xwayland->cursor = calloc(1, sizeof(struct wlr_xwayland_cursor));
126 	if (xwayland->cursor == NULL) {
127 		return;
128 	}
129 	xwayland->cursor->pixels = pixels;
130 	xwayland->cursor->stride = stride;
131 	xwayland->cursor->width = width;
132 	xwayland->cursor->height = height;
133 	xwayland->cursor->hotspot_x = hotspot_x;
134 	xwayland->cursor->hotspot_y = hotspot_y;
135 }
136 
xwayland_handle_seat_destroy(struct wl_listener * listener,void * data)137 static void xwayland_handle_seat_destroy(struct wl_listener *listener,
138 		void *data) {
139 	struct wlr_xwayland *xwayland =
140 		wl_container_of(listener, xwayland, seat_destroy);
141 
142 	wlr_xwayland_set_seat(xwayland, NULL);
143 }
144 
wlr_xwayland_set_seat(struct wlr_xwayland * xwayland,struct wlr_seat * seat)145 void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
146 		struct wlr_seat *seat) {
147 	if (xwayland->seat) {
148 		wl_list_remove(&xwayland->seat_destroy.link);
149 	}
150 
151 	xwayland->seat = seat;
152 
153 	if (xwayland->xwm) {
154 		xwm_set_seat(xwayland->xwm, seat);
155 	}
156 
157 	if (seat == NULL) {
158 		return;
159 	}
160 
161 	xwayland->seat_destroy.notify = xwayland_handle_seat_destroy;
162 	wl_signal_add(&seat->events.destroy, &xwayland->seat_destroy);
163 }
164