1 /*
2  * This an unstable interface of wlroots. No guarantees are made regarding the
3  * future consistency of this API.
4  */
5 #ifndef WLR_USE_UNSTABLE
6 #error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
7 #endif
8 
9 #ifndef WLR_XWAYLAND_H
10 #define WLR_XWAYLAND_H
11 
12 #include <stdbool.h>
13 #include <time.h>
14 #include <wlr/config.h>
15 #include <wlr/types/wlr_compositor.h>
16 #include <wlr/types/wlr_seat.h>
17 #include <xcb/xcb.h>
18 
19 struct wlr_xwm;
20 struct wlr_xwayland_cursor;
21 
22 struct wlr_xwayland_server {
23 	pid_t pid;
24 	struct wl_client *client;
25 	struct wl_event_source *sigusr1_source;
26 	int wm_fd[2], wl_fd[2];
27 
28 	time_t server_start;
29 
30 	int32_t scale;
31 
32 	/* Anything above display is reset on Xwayland restart, rest is conserved */
33 
34 	int display;
35 	char display_name[16];
36 	int x_fd[2];
37 	struct wl_event_source *x_fd_read_event[2];
38 	bool lazy;
39 	bool enable_wm;
40 
41 	struct wl_display *wl_display;
42 
43 	struct {
44 		struct wl_signal ready;
45 		struct wl_signal destroy;
46 	} events;
47 
48 	struct wl_listener client_destroy;
49 	struct wl_listener display_destroy;
50 
51 	void *data;
52 };
53 
54 struct wlr_xwayland_server_options {
55 	bool lazy;
56 	bool enable_wm;
57 };
58 
59 struct wlr_xwayland_server_ready_event {
60 	struct wlr_xwayland_server *server;
61 	int wm_fd;
62 };
63 
64 struct wlr_xwayland {
65 	struct wlr_xwayland_server *server;
66 	struct wlr_xwm *xwm;
67 	struct wlr_xwayland_cursor *cursor;
68 
69 	const char *display_name;
70 
71 	struct wl_display *wl_display;
72 	struct wlr_compositor *compositor;
73 	struct wlr_seat *seat;
74 
75 	struct {
76 		struct wl_signal ready;
77 		struct wl_signal new_surface;
78 	} events;
79 
80 	/**
81 	 * Add a custom event handler to xwayland. Return 1 if the event was
82 	 * handled or 0 to use the default wlr-xwayland handler. wlr-xwayland will
83 	 * free the event.
84 	 */
85 	int (*user_event_handler)(struct wlr_xwm *xwm, xcb_generic_event_t *event);
86 
87 	struct wl_listener server_ready;
88 	struct wl_listener server_destroy;
89 	struct wl_listener seat_destroy;
90 
91 	void *data;
92 };
93 
94 enum wlr_xwayland_surface_decorations {
95 	WLR_XWAYLAND_SURFACE_DECORATIONS_ALL = 0,
96 	WLR_XWAYLAND_SURFACE_DECORATIONS_NO_BORDER = 1,
97 	WLR_XWAYLAND_SURFACE_DECORATIONS_NO_TITLE = 2,
98 };
99 
100 struct wlr_xwayland_surface_hints {
101 	uint32_t flags;
102 	uint32_t input;
103 	int32_t initial_state;
104 	xcb_pixmap_t icon_pixmap;
105 	xcb_window_t icon_window;
106 	int32_t icon_x, icon_y;
107 	xcb_pixmap_t icon_mask;
108 	xcb_window_t window_group;
109 };
110 
111 struct wlr_xwayland_surface_size_hints {
112 	uint32_t flags;
113 	int32_t x, y;
114 	int32_t width, height;
115 	int32_t min_width, min_height;
116 	int32_t max_width, max_height;
117 	int32_t width_inc, height_inc;
118 	int32_t base_width, base_height;
119 	int32_t min_aspect_num, min_aspect_den;
120 	int32_t max_aspect_num, max_aspect_den;
121 	uint32_t win_gravity;
122 };
123 
124 /**
125  * An Xwayland user interface component. It has an absolute position in
126  * layout-local coordinates.
127  *
128  * When a surface is ready to be displayed, the `map` event is emitted. When a
129  * surface should no longer be displayed, the `unmap` event is emitted. The
130  * `unmap` event is guaranteed to be emitted before the `destroy` event if the
131  * view is destroyed when mapped.
132  */
133 struct wlr_xwayland_surface {
134 	xcb_window_t window_id;
135 	struct wlr_xwm *xwm;
136 	uint32_t surface_id;
137 
138 	struct wl_list link;
139 	struct wl_list unpaired_link;
140 
141 	struct wlr_surface *surface;
142 	int16_t x, y;
143 	uint16_t width, height;
144 	uint16_t saved_width, saved_height;
145 	bool override_redirect;
146 	bool mapped;
147 
148 	char *title;
149 	char *class;
150 	char *instance;
151 	char *role;
152 	pid_t pid;
153 	bool has_utf8_title;
154 
155 	struct wl_list children; // wlr_xwayland_surface::parent_link
156 	struct wlr_xwayland_surface *parent;
157 	struct wl_list parent_link; // wlr_xwayland_surface::children
158 
159 	xcb_atom_t *window_type;
160 	size_t window_type_len;
161 
162 	xcb_atom_t *protocols;
163 	size_t protocols_len;
164 
165 	uint32_t decorations;
166 	struct wlr_xwayland_surface_hints *hints;
167 	uint32_t hints_urgency;
168 	struct wlr_xwayland_surface_size_hints *size_hints;
169 
170 	bool pinging;
171 	struct wl_event_source *ping_timer;
172 
173 	// _NET_WM_STATE
174 	bool modal;
175 	bool fullscreen;
176 	bool maximized_vert, maximized_horz;
177 	bool minimized;
178 
179 	bool has_alpha;
180 
181 	struct {
182 		struct wl_signal destroy;
183 		struct wl_signal request_configure;
184 		struct wl_signal request_move;
185 		struct wl_signal request_resize;
186 		struct wl_signal request_minimize;
187 		struct wl_signal request_maximize;
188 		struct wl_signal request_fullscreen;
189 		struct wl_signal request_activate;
190 
191 		struct wl_signal map;
192 		struct wl_signal unmap;
193 		struct wl_signal set_title;
194 		struct wl_signal set_class;
195 		struct wl_signal set_role;
196 		struct wl_signal set_parent;
197 		struct wl_signal set_pid;
198 		struct wl_signal set_window_type;
199 		struct wl_signal set_hints;
200 		struct wl_signal set_decorations;
201 		struct wl_signal set_override_redirect;
202 		struct wl_signal set_geometry;
203 		struct wl_signal ping_timeout;
204 	} events;
205 
206 	struct wl_listener surface_destroy;
207 
208 	void *data;
209 };
210 
211 struct wlr_xwayland_surface_configure_event {
212 	struct wlr_xwayland_surface *surface;
213 	int16_t x, y;
214 	uint16_t width, height;
215 	uint16_t mask; // xcb_config_window_t
216 };
217 
218 // TODO: maybe add a seat to these
219 struct wlr_xwayland_move_event {
220 	struct wlr_xwayland_surface *surface;
221 };
222 
223 struct wlr_xwayland_resize_event {
224 	struct wlr_xwayland_surface *surface;
225 	uint32_t edges;
226 };
227 
228 struct wlr_xwayland_minimize_event {
229 	struct wlr_xwayland_surface *surface;
230 	bool minimize;
231 };
232 
233 struct wlr_xwayland_server *wlr_xwayland_server_create(
234 	struct wl_display *display, struct wlr_xwayland_server_options *options);
235 void wlr_xwayland_server_destroy(struct wlr_xwayland_server *server);
236 
237 /** Create an Xwayland server and XWM.
238  *
239  * The server supports a lazy mode in which Xwayland is only started when a
240  * client tries to connect.
241  *
242  * Note: wlr_xwayland will setup a global SIGUSR1 handler on the compositor
243  * process.
244  */
245 struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
246 	struct wlr_compositor *compositor, bool lazy);
247 
248 void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland);
249 
250 void wlr_xwayland_set_scale(struct wlr_xwayland *wlr_xwayland, int32_t scale);
251 
252 void wlr_xwayland_set_cursor(struct wlr_xwayland *wlr_xwayland,
253 	uint8_t *pixels, uint32_t stride, uint32_t width, uint32_t height,
254 	int32_t hotspot_x, int32_t hotspot_y);
255 
256 void wlr_xwayland_surface_activate(struct wlr_xwayland_surface *surface,
257 	bool activated);
258 
259 void wlr_xwayland_surface_configure(struct wlr_xwayland_surface *surface,
260 	int16_t x, int16_t y, uint16_t width, uint16_t height);
261 
262 void wlr_xwayland_surface_close(struct wlr_xwayland_surface *surface);
263 
264 void wlr_xwayland_surface_set_minimized(struct wlr_xwayland_surface *surface,
265 	bool minimized);
266 
267 void wlr_xwayland_surface_set_maximized(struct wlr_xwayland_surface *surface,
268 	bool maximized);
269 
270 void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland_surface *surface,
271 	bool fullscreen);
272 
273 void wlr_xwayland_set_seat(struct wlr_xwayland *xwayland,
274 	struct wlr_seat *seat);
275 
276 bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface);
277 
278 struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface(
279 	struct wlr_surface *surface);
280 
281 void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface);
282 
283 /** Metric to guess if an OR window should "receive" focus
284  *
285  * In the pure X setups, window managers usually straight up ignore override
286  * redirect windows, and never touch them. (we have to handle them for mapping)
287  *
288  * When such a window wants to receive keyboard input (e.g. rofi/dzen) it will
289  * use mechanics we don't support (sniffing/grabbing input).
290  * [Sadly this is unrelated to xwayland-keyboard-grab]
291  *
292  * To still support these windows, while keeping general OR semantics as is, we
293  * need to hand a subset of windows focus.
294  * The dirty truth is, we need to hand focus to any Xwayland window, though
295  * pretending this window has focus makes it easier to handle unmap.
296  *
297  * This function provides a handy metric based on the window type to guess if
298  * the OR window wants focus.
299  * It's probably not perfect, nor exactly intended but works in practice.
300  *
301  * Returns: true if the window should receive focus
302  *          false if it should be ignored
303  */
304 bool wlr_xwayland_or_surface_wants_focus(
305 	const struct wlr_xwayland_surface *surface);
306 
307 
308 #endif
309