1 #define _POSIX_C_SOURCE 200809L
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <wlr/util/log.h>
6 #include <wlr/util/edges.h>
7 #include "types/wlr_xdg_shell.h"
8 #include "util/signal.h"
9 
handle_xdg_toplevel_ack_configure(struct wlr_xdg_surface * surface,struct wlr_xdg_surface_configure * configure)10 void handle_xdg_toplevel_ack_configure(
11 		struct wlr_xdg_surface *surface,
12 		struct wlr_xdg_surface_configure *configure) {
13 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
14 	assert(configure->toplevel_state != NULL);
15 
16 	surface->toplevel->last_acked = *configure->toplevel_state;
17 }
18 
compare_xdg_surface_toplevel_state(struct wlr_xdg_toplevel * state)19 bool compare_xdg_surface_toplevel_state(struct wlr_xdg_toplevel *state) {
20 	// is pending state different from current state?
21 	if (!state->base->configured) {
22 		return false;
23 	}
24 
25 	struct wlr_xdg_toplevel_state *configured = NULL;
26 	if (wl_list_empty(&state->base->configure_list)) {
27 		// There are currently no pending configures, so check against the last
28 		// state acked by the client.
29 		configured = &state->last_acked;
30 	} else {
31 		struct wlr_xdg_surface_configure *configure =
32 			wl_container_of(state->base->configure_list.prev, configure, link);
33 		configured = configure->toplevel_state;
34 	}
35 
36 	if (state->server_pending.activated != configured->activated) {
37 		return false;
38 	}
39 	if (state->server_pending.fullscreen != configured->fullscreen) {
40 		return false;
41 	}
42 	if (state->server_pending.maximized != configured->maximized) {
43 		return false;
44 	}
45 	if (state->server_pending.resizing != configured->resizing) {
46 		return false;
47 	}
48 	if (state->server_pending.tiled != configured->tiled) {
49 		return false;
50 	}
51 
52 	if (state->server_pending.width == configured->width &&
53 			state->server_pending.height == configured->height) {
54 		return true;
55 	}
56 
57 	if (state->server_pending.width == 0 && state->server_pending.height == 0) {
58 		return true;
59 	}
60 
61 	return false;
62 }
63 
send_xdg_toplevel_configure(struct wlr_xdg_surface * surface,struct wlr_xdg_surface_configure * configure)64 void send_xdg_toplevel_configure(struct wlr_xdg_surface *surface,
65 		struct wlr_xdg_surface_configure *configure) {
66 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
67 
68 	configure->toplevel_state = malloc(sizeof(*configure->toplevel_state));
69 	if (configure->toplevel_state == NULL) {
70 		wlr_log(WLR_ERROR, "Allocation failed");
71 		wl_resource_post_no_memory(surface->toplevel->resource);
72 		return;
73 	}
74 	*configure->toplevel_state = surface->toplevel->server_pending;
75 
76 	struct wl_array states;
77 	wl_array_init(&states);
78 	if (surface->toplevel->server_pending.maximized) {
79 		uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
80 		if (!s) {
81 			wlr_log(WLR_ERROR, "Could not allocate state for maximized xdg_toplevel");
82 			goto error_out;
83 		}
84 		*s = XDG_TOPLEVEL_STATE_MAXIMIZED;
85 	}
86 	if (surface->toplevel->server_pending.fullscreen) {
87 		uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
88 		if (!s) {
89 			wlr_log(WLR_ERROR, "Could not allocate state for fullscreen xdg_toplevel");
90 			goto error_out;
91 		}
92 		*s = XDG_TOPLEVEL_STATE_FULLSCREEN;
93 	}
94 	if (surface->toplevel->server_pending.resizing) {
95 		uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
96 		if (!s) {
97 			wlr_log(WLR_ERROR, "Could not allocate state for resizing xdg_toplevel");
98 			goto error_out;
99 		}
100 		*s = XDG_TOPLEVEL_STATE_RESIZING;
101 	}
102 	if (surface->toplevel->server_pending.activated) {
103 		uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
104 		if (!s) {
105 			wlr_log(WLR_ERROR, "Could not allocate state for activated xdg_toplevel");
106 			goto error_out;
107 		}
108 		*s = XDG_TOPLEVEL_STATE_ACTIVATED;
109 	}
110 	if (surface->toplevel->server_pending.tiled) {
111 		if (wl_resource_get_version(surface->resource) >=
112 				XDG_TOPLEVEL_STATE_TILED_LEFT_SINCE_VERSION) {
113 			const struct {
114 				enum wlr_edges edge;
115 				enum xdg_toplevel_state state;
116 			} tiled[] = {
117 				{ WLR_EDGE_LEFT, XDG_TOPLEVEL_STATE_TILED_LEFT },
118 				{ WLR_EDGE_RIGHT, XDG_TOPLEVEL_STATE_TILED_RIGHT },
119 				{ WLR_EDGE_TOP, XDG_TOPLEVEL_STATE_TILED_TOP },
120 				{ WLR_EDGE_BOTTOM, XDG_TOPLEVEL_STATE_TILED_BOTTOM },
121 			};
122 
123 			for (size_t i = 0; i < sizeof(tiled)/sizeof(tiled[0]); ++i) {
124 				if ((surface->toplevel->server_pending.tiled &
125 						tiled[i].edge) == 0) {
126 					continue;
127 				}
128 
129 				uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
130 				if (!s) {
131 					wlr_log(WLR_ERROR,
132 						"Could not allocate state for tiled xdg_toplevel");
133 					goto error_out;
134 				}
135 				*s = tiled[i].state;
136 			}
137 		} else if (!surface->toplevel->server_pending.maximized) {
138 			// This version doesn't support tiling, best we can do is make the
139 			// toplevel maximized
140 			uint32_t *s = wl_array_add(&states, sizeof(uint32_t));
141 			if (!s) {
142 				wlr_log(WLR_ERROR,
143 					"Could not allocate state for maximized xdg_toplevel");
144 				goto error_out;
145 			}
146 			*s = XDG_TOPLEVEL_STATE_MAXIMIZED;
147 		}
148 	}
149 
150 	uint32_t width = surface->toplevel->server_pending.width;
151 	uint32_t height = surface->toplevel->server_pending.height;
152 	xdg_toplevel_send_configure(surface->toplevel->resource, width, height,
153 		&states);
154 
155 	wl_array_release(&states);
156 	return;
157 
158 error_out:
159 	wl_array_release(&states);
160 	wl_resource_post_no_memory(surface->toplevel->resource);
161 }
162 
handle_xdg_surface_toplevel_committed(struct wlr_xdg_surface * surface)163 void handle_xdg_surface_toplevel_committed(struct wlr_xdg_surface *surface) {
164 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
165 
166 	if (!surface->toplevel->added) {
167 		// on the first commit, send a configure request to tell the client it
168 		// is added
169 		schedule_xdg_surface_configure(surface);
170 		surface->toplevel->added = true;
171 		return;
172 	}
173 
174 	// apply state from the last acked configure now that the client committed
175 	surface->toplevel->current = surface->toplevel->last_acked;
176 
177 	// update state from the client that doesn't need compositor approval
178 	surface->toplevel->current.max_width =
179 		surface->toplevel->client_pending.max_width;
180 	surface->toplevel->current.min_width =
181 		surface->toplevel->client_pending.min_width;
182 	surface->toplevel->current.max_height =
183 		surface->toplevel->client_pending.max_height;
184 	surface->toplevel->current.min_height =
185 		surface->toplevel->client_pending.min_height;
186 }
187 
188 static const struct xdg_toplevel_interface xdg_toplevel_implementation;
189 
wlr_xdg_surface_from_toplevel_resource(struct wl_resource * resource)190 struct wlr_xdg_surface *wlr_xdg_surface_from_toplevel_resource(
191 		struct wl_resource *resource) {
192 	assert(wl_resource_instance_of(resource, &xdg_toplevel_interface,
193 		&xdg_toplevel_implementation));
194 	return wl_resource_get_user_data(resource);
195 }
196 
197 static void set_parent(struct wlr_xdg_surface *surface,
198 		struct wlr_xdg_surface *parent);
199 
handle_parent_unmap(struct wl_listener * listener,void * data)200 static void handle_parent_unmap(struct wl_listener *listener, void *data) {
201 	struct wlr_xdg_toplevel *toplevel =
202 		wl_container_of(listener, toplevel, parent_unmap);
203 	set_parent(toplevel->base, toplevel->parent->toplevel->parent);
204 }
205 
set_parent(struct wlr_xdg_surface * surface,struct wlr_xdg_surface * parent)206 static void set_parent(struct wlr_xdg_surface *surface,
207 		struct wlr_xdg_surface *parent) {
208 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
209 	assert(!parent || parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
210 
211 	if (surface->toplevel->parent) {
212 		wl_list_remove(&surface->toplevel->parent_unmap.link);
213 	}
214 
215 	surface->toplevel->parent = parent;
216 	if (surface->toplevel->parent) {
217 		surface->toplevel->parent_unmap.notify = handle_parent_unmap;
218 		wl_signal_add(&surface->toplevel->parent->events.unmap,
219 				&surface->toplevel->parent_unmap);
220 	}
221 
222 	wlr_signal_emit_safe(&surface->toplevel->events.set_parent, surface);
223 }
224 
xdg_toplevel_handle_set_parent(struct wl_client * client,struct wl_resource * resource,struct wl_resource * parent_resource)225 static void xdg_toplevel_handle_set_parent(struct wl_client *client,
226 		struct wl_resource *resource, struct wl_resource *parent_resource) {
227 	struct wlr_xdg_surface *surface =
228 		wlr_xdg_surface_from_toplevel_resource(resource);
229 	struct wlr_xdg_surface *parent = NULL;
230 
231 	if (parent_resource != NULL) {
232 		parent = wlr_xdg_surface_from_toplevel_resource(parent_resource);
233 	}
234 
235 	set_parent(surface, parent);
236 }
237 
xdg_toplevel_handle_set_title(struct wl_client * client,struct wl_resource * resource,const char * title)238 static void xdg_toplevel_handle_set_title(struct wl_client *client,
239 		struct wl_resource *resource, const char *title) {
240 	struct wlr_xdg_surface *surface =
241 		wlr_xdg_surface_from_toplevel_resource(resource);
242 	char *tmp;
243 
244 	tmp = strdup(title);
245 	if (tmp == NULL) {
246 		return;
247 	}
248 
249 	free(surface->toplevel->title);
250 	surface->toplevel->title = tmp;
251 	wlr_signal_emit_safe(&surface->toplevel->events.set_title, surface);
252 }
253 
xdg_toplevel_handle_set_app_id(struct wl_client * client,struct wl_resource * resource,const char * app_id)254 static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
255 		struct wl_resource *resource, const char *app_id) {
256 	struct wlr_xdg_surface *surface =
257 		wlr_xdg_surface_from_toplevel_resource(resource);
258 	char *tmp;
259 
260 	tmp = strdup(app_id);
261 	if (tmp == NULL) {
262 		return;
263 	}
264 
265 	free(surface->toplevel->app_id);
266 	surface->toplevel->app_id = tmp;
267 	wlr_signal_emit_safe(&surface->toplevel->events.set_app_id, surface);
268 }
269 
xdg_toplevel_handle_show_window_menu(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat_resource,uint32_t serial,int32_t x,int32_t y)270 static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
271 		struct wl_resource *resource, struct wl_resource *seat_resource,
272 		uint32_t serial, int32_t x, int32_t y) {
273 	struct wlr_xdg_surface *surface =
274 		wlr_xdg_surface_from_toplevel_resource(resource);
275 	struct wlr_seat_client *seat =
276 		wlr_seat_client_from_resource(seat_resource);
277 
278 	if (!surface->configured) {
279 		wl_resource_post_error(surface->toplevel->resource,
280 			XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
281 			"surface has not been configured yet");
282 		return;
283 	}
284 
285 	if (!wlr_seat_validate_grab_serial(seat->seat, serial)) {
286 		wlr_log(WLR_DEBUG, "invalid serial for grab");
287 		return;
288 	}
289 
290 	struct wlr_xdg_toplevel_show_window_menu_event event = {
291 		.surface = surface,
292 		.seat = seat,
293 		.serial = serial,
294 		.x = x,
295 		.y = y,
296 	};
297 
298 	wlr_signal_emit_safe(&surface->toplevel->events.request_show_window_menu, &event);
299 }
300 
xdg_toplevel_handle_move(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat_resource,uint32_t serial)301 static void xdg_toplevel_handle_move(struct wl_client *client,
302 		struct wl_resource *resource, struct wl_resource *seat_resource,
303 		uint32_t serial) {
304 	struct wlr_xdg_surface *surface =
305 		wlr_xdg_surface_from_toplevel_resource(resource);
306 	struct wlr_seat_client *seat =
307 		wlr_seat_client_from_resource(seat_resource);
308 
309 	if (!surface->configured) {
310 		wl_resource_post_error(surface->toplevel->resource,
311 			XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
312 			"surface has not been configured yet");
313 		return;
314 	}
315 
316 	if (!wlr_seat_validate_grab_serial(seat->seat, serial)) {
317 		wlr_log(WLR_DEBUG, "invalid serial for grab");
318 		return;
319 	}
320 
321 	struct wlr_xdg_toplevel_move_event event = {
322 		.surface = surface,
323 		.seat = seat,
324 		.serial = serial,
325 	};
326 
327 	wlr_signal_emit_safe(&surface->toplevel->events.request_move, &event);
328 }
329 
xdg_toplevel_handle_resize(struct wl_client * client,struct wl_resource * resource,struct wl_resource * seat_resource,uint32_t serial,uint32_t edges)330 static void xdg_toplevel_handle_resize(struct wl_client *client,
331 		struct wl_resource *resource, struct wl_resource *seat_resource,
332 		uint32_t serial, uint32_t edges) {
333 	struct wlr_xdg_surface *surface =
334 		wlr_xdg_surface_from_toplevel_resource(resource);
335 	struct wlr_seat_client *seat =
336 		wlr_seat_client_from_resource(seat_resource);
337 
338 	if (!surface->configured) {
339 		wl_resource_post_error(surface->toplevel->resource,
340 			XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
341 			"surface has not been configured yet");
342 		return;
343 	}
344 
345 	if (!wlr_seat_validate_grab_serial(seat->seat, serial)) {
346 		wlr_log(WLR_DEBUG, "invalid serial for grab");
347 		return;
348 	}
349 
350 	struct wlr_xdg_toplevel_resize_event event = {
351 		.surface = surface,
352 		.seat = seat,
353 		.serial = serial,
354 		.edges = edges,
355 	};
356 
357 	wlr_signal_emit_safe(&surface->toplevel->events.request_resize, &event);
358 }
359 
xdg_toplevel_handle_set_max_size(struct wl_client * client,struct wl_resource * resource,int32_t width,int32_t height)360 static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
361 		struct wl_resource *resource, int32_t width, int32_t height) {
362 	struct wlr_xdg_surface *surface =
363 		wlr_xdg_surface_from_toplevel_resource(resource);
364 	surface->toplevel->client_pending.max_width = width;
365 	surface->toplevel->client_pending.max_height = height;
366 }
367 
xdg_toplevel_handle_set_min_size(struct wl_client * client,struct wl_resource * resource,int32_t width,int32_t height)368 static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
369 		struct wl_resource *resource, int32_t width, int32_t height) {
370 	struct wlr_xdg_surface *surface =
371 		wlr_xdg_surface_from_toplevel_resource(resource);
372 	surface->toplevel->client_pending.min_width = width;
373 	surface->toplevel->client_pending.min_height = height;
374 }
375 
xdg_toplevel_handle_set_maximized(struct wl_client * client,struct wl_resource * resource)376 static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
377 		struct wl_resource *resource) {
378 	struct wlr_xdg_surface *surface =
379 		wlr_xdg_surface_from_toplevel_resource(resource);
380 	surface->toplevel->client_pending.maximized = true;
381 	wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
382 }
383 
xdg_toplevel_handle_unset_maximized(struct wl_client * client,struct wl_resource * resource)384 static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
385 		struct wl_resource *resource) {
386 	struct wlr_xdg_surface *surface =
387 		wlr_xdg_surface_from_toplevel_resource(resource);
388 	surface->toplevel->client_pending.maximized = false;
389 	wlr_signal_emit_safe(&surface->toplevel->events.request_maximize, surface);
390 }
391 
handle_fullscreen_output_destroy(struct wl_listener * listener,void * data)392 static void handle_fullscreen_output_destroy(struct wl_listener *listener,
393 		void *data) {
394 	struct wlr_xdg_toplevel_state *state =
395 		wl_container_of(listener, state, fullscreen_output_destroy);
396 	state->fullscreen_output = NULL;
397 	wl_list_remove(&state->fullscreen_output_destroy.link);
398 }
399 
store_fullscreen_pending(struct wlr_xdg_surface * surface,bool fullscreen,struct wlr_output * output)400 static void store_fullscreen_pending(struct wlr_xdg_surface *surface,
401 		bool fullscreen, struct wlr_output *output) {
402 	struct wlr_xdg_toplevel_state *state = &surface->toplevel->client_pending;
403 	state->fullscreen = fullscreen;
404 	if (state->fullscreen_output) {
405 		wl_list_remove(&state->fullscreen_output_destroy.link);
406 	}
407 	state->fullscreen_output = output;
408 	if (state->fullscreen_output) {
409 		state->fullscreen_output_destroy.notify =
410 			handle_fullscreen_output_destroy;
411 		wl_signal_add(&state->fullscreen_output->events.destroy,
412 				&state->fullscreen_output_destroy);
413 	}
414 }
415 
xdg_toplevel_handle_set_fullscreen(struct wl_client * client,struct wl_resource * resource,struct wl_resource * output_resource)416 static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
417 		struct wl_resource *resource, struct wl_resource *output_resource) {
418 	struct wlr_xdg_surface *surface =
419 		wlr_xdg_surface_from_toplevel_resource(resource);
420 
421 	struct wlr_output *output = NULL;
422 	if (output_resource != NULL) {
423 		output = wlr_output_from_resource(output_resource);
424 	}
425 
426 	store_fullscreen_pending(surface, true, output);
427 
428 	struct wlr_xdg_toplevel_set_fullscreen_event event = {
429 		.surface = surface,
430 		.fullscreen = true,
431 		.output = output,
432 	};
433 
434 	wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
435 }
436 
xdg_toplevel_handle_unset_fullscreen(struct wl_client * client,struct wl_resource * resource)437 static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
438 		struct wl_resource *resource) {
439 	struct wlr_xdg_surface *surface =
440 		wlr_xdg_surface_from_toplevel_resource(resource);
441 
442 	store_fullscreen_pending(surface, false, NULL);
443 
444 	struct wlr_xdg_toplevel_set_fullscreen_event event = {
445 		.surface = surface,
446 		.fullscreen = false,
447 		.output = NULL,
448 	};
449 
450 	wlr_signal_emit_safe(&surface->toplevel->events.request_fullscreen, &event);
451 }
452 
xdg_toplevel_handle_set_minimized(struct wl_client * client,struct wl_resource * resource)453 static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
454 		struct wl_resource *resource) {
455 	struct wlr_xdg_surface *surface =
456 		wlr_xdg_surface_from_toplevel_resource(resource);
457 	wlr_signal_emit_safe(&surface->toplevel->events.request_minimize, surface);
458 }
459 
xdg_toplevel_handle_destroy(struct wl_client * client,struct wl_resource * resource)460 static void xdg_toplevel_handle_destroy(struct wl_client *client,
461 		struct wl_resource *resource) {
462 	wl_resource_destroy(resource);
463 }
464 
465 static const struct xdg_toplevel_interface xdg_toplevel_implementation = {
466 	.destroy = xdg_toplevel_handle_destroy,
467 	.set_parent = xdg_toplevel_handle_set_parent,
468 	.set_title = xdg_toplevel_handle_set_title,
469 	.set_app_id = xdg_toplevel_handle_set_app_id,
470 	.show_window_menu = xdg_toplevel_handle_show_window_menu,
471 	.move = xdg_toplevel_handle_move,
472 	.resize = xdg_toplevel_handle_resize,
473 	.set_max_size = xdg_toplevel_handle_set_max_size,
474 	.set_min_size = xdg_toplevel_handle_set_min_size,
475 	.set_maximized = xdg_toplevel_handle_set_maximized,
476 	.unset_maximized = xdg_toplevel_handle_unset_maximized,
477 	.set_fullscreen = xdg_toplevel_handle_set_fullscreen,
478 	.unset_fullscreen = xdg_toplevel_handle_unset_fullscreen,
479 	.set_minimized = xdg_toplevel_handle_set_minimized,
480 };
481 
xdg_toplevel_handle_resource_destroy(struct wl_resource * resource)482 static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) {
483 	struct wlr_xdg_surface *surface =
484 		wlr_xdg_surface_from_toplevel_resource(resource);
485 	destroy_xdg_toplevel(surface);
486 }
487 
488 const struct wlr_surface_role xdg_toplevel_surface_role = {
489 	.name = "xdg_toplevel",
490 	.commit = handle_xdg_surface_commit,
491 	.precommit = handle_xdg_surface_precommit,
492 };
493 
create_xdg_toplevel(struct wlr_xdg_surface * xdg_surface,uint32_t id)494 void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface,
495 		uint32_t id) {
496 	if (!wlr_surface_set_role(xdg_surface->surface, &xdg_toplevel_surface_role,
497 			xdg_surface, xdg_surface->resource, XDG_WM_BASE_ERROR_ROLE)) {
498 		return;
499 	}
500 
501 	if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
502 		wl_resource_post_error(xdg_surface->resource,
503 			XDG_SURFACE_ERROR_ALREADY_CONSTRUCTED,
504 			"xdg-surface has already been constructed");
505 		return;
506 	}
507 
508 	assert(xdg_surface->toplevel == NULL);
509 	xdg_surface->toplevel = calloc(1, sizeof(struct wlr_xdg_toplevel));
510 	if (xdg_surface->toplevel == NULL) {
511 		wl_resource_post_no_memory(xdg_surface->resource);
512 		return;
513 	}
514 	xdg_surface->toplevel->base = xdg_surface;
515 
516 	wl_signal_init(&xdg_surface->toplevel->events.request_maximize);
517 	wl_signal_init(&xdg_surface->toplevel->events.request_fullscreen);
518 	wl_signal_init(&xdg_surface->toplevel->events.request_minimize);
519 	wl_signal_init(&xdg_surface->toplevel->events.request_move);
520 	wl_signal_init(&xdg_surface->toplevel->events.request_resize);
521 	wl_signal_init(&xdg_surface->toplevel->events.request_show_window_menu);
522 	wl_signal_init(&xdg_surface->toplevel->events.set_parent);
523 	wl_signal_init(&xdg_surface->toplevel->events.set_title);
524 	wl_signal_init(&xdg_surface->toplevel->events.set_app_id);
525 
526 	xdg_surface->toplevel->resource = wl_resource_create(
527 		xdg_surface->client->client, &xdg_toplevel_interface,
528 		wl_resource_get_version(xdg_surface->resource), id);
529 	if (xdg_surface->toplevel->resource == NULL) {
530 		free(xdg_surface->toplevel);
531 		wl_resource_post_no_memory(xdg_surface->resource);
532 		return;
533 	}
534 	wl_resource_set_implementation(xdg_surface->toplevel->resource,
535 		&xdg_toplevel_implementation, xdg_surface,
536 		xdg_toplevel_handle_resource_destroy);
537 
538 	xdg_surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
539 }
540 
destroy_xdg_toplevel(struct wlr_xdg_surface * xdg_surface)541 void destroy_xdg_toplevel(struct wlr_xdg_surface *xdg_surface) {
542 	if (xdg_surface == NULL) {
543 		return;
544 	}
545 	assert(xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
546 	reset_xdg_surface(xdg_surface);
547 }
548 
wlr_xdg_toplevel_set_size(struct wlr_xdg_surface * surface,uint32_t width,uint32_t height)549 uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
550 		uint32_t width, uint32_t height) {
551 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
552 	surface->toplevel->server_pending.width = width;
553 	surface->toplevel->server_pending.height = height;
554 
555 	return schedule_xdg_surface_configure(surface);
556 }
557 
wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface * surface,bool activated)558 uint32_t wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface *surface,
559 		bool activated) {
560 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
561 	surface->toplevel->server_pending.activated = activated;
562 
563 	return schedule_xdg_surface_configure(surface);
564 }
565 
wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface * surface,bool maximized)566 uint32_t wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface *surface,
567 		bool maximized) {
568 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
569 	surface->toplevel->server_pending.maximized = maximized;
570 
571 	return schedule_xdg_surface_configure(surface);
572 }
573 
wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface * surface,bool fullscreen)574 uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface,
575 		bool fullscreen) {
576 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
577 	surface->toplevel->server_pending.fullscreen = fullscreen;
578 
579 	return schedule_xdg_surface_configure(surface);
580 }
581 
wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface * surface,bool resizing)582 uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface *surface,
583 		bool resizing) {
584 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
585 	surface->toplevel->server_pending.resizing = resizing;
586 
587 	return schedule_xdg_surface_configure(surface);
588 }
589 
wlr_xdg_toplevel_set_tiled(struct wlr_xdg_surface * surface,uint32_t tiled)590 uint32_t wlr_xdg_toplevel_set_tiled(struct wlr_xdg_surface *surface,
591 		uint32_t tiled) {
592 	assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
593 	surface->toplevel->server_pending.tiled = tiled;
594 
595 	return schedule_xdg_surface_configure(surface);
596 }
597