mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Merge pull request #468 from emersion/display-destroy
Use destroy listeners on wl_display
This commit is contained in:
		
						commit
						46ac8e1243
					
				
					 36 changed files with 446 additions and 199 deletions
				
			
		| 
						 | 
					@ -34,6 +34,10 @@ static void wlr_drm_backend_destroy(struct wlr_backend *backend) {
 | 
				
			||||||
		wlr_output_destroy(&conn->output);
 | 
							wlr_output_destroy(&conn->output);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&drm->display_destroy.link);
 | 
				
			||||||
 | 
						wl_list_remove(&drm->session_signal.link);
 | 
				
			||||||
 | 
						wl_list_remove(&drm->drm_invalidated.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_drm_resources_free(drm);
 | 
						wlr_drm_resources_free(drm);
 | 
				
			||||||
	wlr_drm_renderer_finish(&drm->renderer);
 | 
						wlr_drm_renderer_finish(&drm->renderer);
 | 
				
			||||||
	wlr_session_close_file(drm->session, drm->fd);
 | 
						wlr_session_close_file(drm->session, drm->fd);
 | 
				
			||||||
| 
						 | 
					@ -57,7 +61,8 @@ bool wlr_backend_is_drm(struct wlr_backend *b) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void session_signal(struct wl_listener *listener, void *data) {
 | 
					static void session_signal(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	struct wlr_drm_backend *drm = wl_container_of(listener, drm, session_signal);
 | 
						struct wlr_drm_backend *drm =
 | 
				
			||||||
 | 
							wl_container_of(listener, drm, session_signal);
 | 
				
			||||||
	struct wlr_session *session = data;
 | 
						struct wlr_session *session = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (session->active) {
 | 
						if (session->active) {
 | 
				
			||||||
| 
						 | 
					@ -84,7 +89,8 @@ static void session_signal(struct wl_listener *listener, void *data) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void drm_invalidated(struct wl_listener *listener, void *data) {
 | 
					static void drm_invalidated(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	struct wlr_drm_backend *drm = wl_container_of(listener, drm, drm_invalidated);
 | 
						struct wlr_drm_backend *drm =
 | 
				
			||||||
 | 
							wl_container_of(listener, drm, drm_invalidated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *name = drmGetDeviceNameFromFd2(drm->fd);
 | 
						char *name = drmGetDeviceNameFromFd2(drm->fd);
 | 
				
			||||||
	wlr_log(L_DEBUG, "%s invalidated", name);
 | 
						wlr_log(L_DEBUG, "%s invalidated", name);
 | 
				
			||||||
| 
						 | 
					@ -93,6 +99,12 @@ static void drm_invalidated(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	wlr_drm_scan_connectors(drm);
 | 
						wlr_drm_scan_connectors(drm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_drm_backend *drm =
 | 
				
			||||||
 | 
							wl_container_of(listener, drm, display_destroy);
 | 
				
			||||||
 | 
						wlr_drm_backend_destroy(&drm->backend);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
 | 
					struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
 | 
				
			||||||
		struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) {
 | 
							struct wlr_session *session, int gpu_fd, struct wlr_backend *parent) {
 | 
				
			||||||
	assert(display && session && gpu_fd >= 0);
 | 
						assert(display && session && gpu_fd >= 0);
 | 
				
			||||||
| 
						 | 
					@ -150,6 +162,9 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
 | 
				
			||||||
		wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error());
 | 
							wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drm->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &drm->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &drm->backend;
 | 
						return &drm->backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_event:
 | 
					error_event:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ bool wlr_drm_renderer_init(struct wlr_drm_backend *drm,
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_egl:
 | 
					error_egl:
 | 
				
			||||||
	wlr_egl_free(&renderer->egl);
 | 
						wlr_egl_finish(&renderer->egl);
 | 
				
			||||||
error_gbm:
 | 
					error_gbm:
 | 
				
			||||||
	gbm_device_destroy(renderer->gbm);
 | 
						gbm_device_destroy(renderer->gbm);
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					@ -51,7 +51,7 @@ void wlr_drm_renderer_finish(struct wlr_drm_renderer *renderer) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_renderer_destroy(renderer->wlr_rend);
 | 
						wlr_renderer_destroy(renderer->wlr_rend);
 | 
				
			||||||
	wlr_egl_free(&renderer->egl);
 | 
						wlr_egl_finish(&renderer->egl);
 | 
				
			||||||
	gbm_device_destroy(renderer->gbm);
 | 
						gbm_device_destroy(renderer->gbm);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,10 +43,12 @@ static void wlr_libinput_log(struct libinput *libinput_context,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool wlr_libinput_backend_start(struct wlr_backend *_backend) {
 | 
					static bool wlr_libinput_backend_start(struct wlr_backend *_backend) {
 | 
				
			||||||
	struct wlr_libinput_backend *backend = (struct wlr_libinput_backend *)_backend;
 | 
						struct wlr_libinput_backend *backend =
 | 
				
			||||||
 | 
							(struct wlr_libinput_backend *)_backend;
 | 
				
			||||||
	wlr_log(L_DEBUG, "Initializing libinput");
 | 
						wlr_log(L_DEBUG, "Initializing libinput");
 | 
				
			||||||
	backend->libinput_context = libinput_udev_create_context(&libinput_impl, backend,
 | 
					
 | 
				
			||||||
			backend->session->udev);
 | 
						backend->libinput_context = libinput_udev_create_context(&libinput_impl,
 | 
				
			||||||
 | 
							backend, backend->session->udev);
 | 
				
			||||||
	if (!backend->libinput_context) {
 | 
						if (!backend->libinput_context) {
 | 
				
			||||||
		wlr_log(L_ERROR, "Failed to create libinput context");
 | 
							wlr_log(L_ERROR, "Failed to create libinput context");
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -99,6 +101,7 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct wlr_libinput_backend *backend =
 | 
						struct wlr_libinput_backend *backend =
 | 
				
			||||||
		(struct wlr_libinput_backend *)_backend;
 | 
							(struct wlr_libinput_backend *)_backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (size_t i = 0; i < backend->wlr_device_lists.length; i++) {
 | 
						for (size_t i = 0; i < backend->wlr_device_lists.length; i++) {
 | 
				
			||||||
		struct wl_list *wlr_devices = backend->wlr_device_lists.items[i];
 | 
							struct wl_list *wlr_devices = backend->wlr_device_lists.items[i];
 | 
				
			||||||
		struct wlr_input_device *wlr_dev, *next;
 | 
							struct wlr_input_device *wlr_dev, *next;
 | 
				
			||||||
| 
						 | 
					@ -108,6 +111,10 @@ static void wlr_libinput_backend_destroy(struct wlr_backend *_backend) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		free(wlr_devices);
 | 
							free(wlr_devices);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&backend->display_destroy.link);
 | 
				
			||||||
 | 
						wl_list_remove(&backend->session_signal.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_list_finish(&backend->wlr_device_lists);
 | 
						wlr_list_finish(&backend->wlr_device_lists);
 | 
				
			||||||
	wl_event_source_remove(backend->input_event);
 | 
						wl_event_source_remove(backend->input_event);
 | 
				
			||||||
	libinput_unref(backend->libinput_context);
 | 
						libinput_unref(backend->libinput_context);
 | 
				
			||||||
| 
						 | 
					@ -124,7 +131,8 @@ bool wlr_backend_is_libinput(struct wlr_backend *b) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void session_signal(struct wl_listener *listener, void *data) {
 | 
					static void session_signal(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	struct wlr_libinput_backend *backend = wl_container_of(listener, backend, session_signal);
 | 
						struct wlr_libinput_backend *backend =
 | 
				
			||||||
 | 
							wl_container_of(listener, backend, session_signal);
 | 
				
			||||||
	struct wlr_session *session = data;
 | 
						struct wlr_session *session = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!backend->libinput_context) {
 | 
						if (!backend->libinput_context) {
 | 
				
			||||||
| 
						 | 
					@ -138,6 +146,12 @@ static void session_signal(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_libinput_backend *backend =
 | 
				
			||||||
 | 
							wl_container_of(listener, backend, display_destroy);
 | 
				
			||||||
 | 
						wlr_libinput_backend_destroy(&backend->backend);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
 | 
					struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
 | 
				
			||||||
		struct wlr_session *session) {
 | 
							struct wlr_session *session) {
 | 
				
			||||||
	assert(display && session);
 | 
						assert(display && session);
 | 
				
			||||||
| 
						 | 
					@ -160,6 +174,9 @@ struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
 | 
				
			||||||
	backend->session_signal.notify = session_signal;
 | 
						backend->session_signal.notify = session_signal;
 | 
				
			||||||
	wl_signal_add(&session->session_signal, &backend->session_signal);
 | 
						wl_signal_add(&session->session_signal, &backend->session_signal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backend->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &backend->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &backend->backend;
 | 
						return &backend->backend;
 | 
				
			||||||
error_backend:
 | 
					error_backend:
 | 
				
			||||||
	free(backend);
 | 
						free(backend);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,6 @@ static void multi_backend_destroy(struct wlr_backend *_backend) {
 | 
				
			||||||
		wlr_backend_destroy(sub->backend);
 | 
							wlr_backend_destroy(sub->backend);
 | 
				
			||||||
		free(sub);
 | 
							free(sub);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wlr_session_destroy(backend->session);
 | 
					 | 
				
			||||||
	free(backend);
 | 
						free(backend);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,6 +58,12 @@ out:
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_session *session =
 | 
				
			||||||
 | 
							wl_container_of(listener, session, display_destroy);
 | 
				
			||||||
 | 
						wlr_session_destroy(session);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_session *wlr_session_create(struct wl_display *disp) {
 | 
					struct wlr_session *wlr_session_create(struct wl_display *disp) {
 | 
				
			||||||
	struct wlr_session *session = NULL;
 | 
						struct wlr_session *session = NULL;
 | 
				
			||||||
	const struct session_impl **iter;
 | 
						const struct session_impl **iter;
 | 
				
			||||||
| 
						 | 
					@ -100,6 +106,9 @@ struct wlr_session *wlr_session_create(struct wl_display *disp) {
 | 
				
			||||||
		goto error_mon;
 | 
							goto error_mon;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(disp, &session->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return session;
 | 
						return session;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_mon:
 | 
					error_mon:
 | 
				
			||||||
| 
						 | 
					@ -107,7 +116,7 @@ error_mon:
 | 
				
			||||||
error_udev:
 | 
					error_udev:
 | 
				
			||||||
	udev_unref(session->udev);
 | 
						udev_unref(session->udev);
 | 
				
			||||||
error_session:
 | 
					error_session:
 | 
				
			||||||
	wlr_session_destroy(session);
 | 
						session->impl->destroy(session);
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,6 +125,8 @@ void wlr_session_destroy(struct wlr_session *session) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&session->display_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_source_remove(session->udev_event);
 | 
						wl_event_source_remove(session->udev_event);
 | 
				
			||||||
	udev_monitor_unref(session->mon);
 | 
						udev_monitor_unref(session->mon);
 | 
				
			||||||
	udev_unref(session->udev);
 | 
						udev_unref(session->udev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,10 +79,12 @@ static void wlr_wl_backend_destroy(struct wlr_backend *_backend) {
 | 
				
			||||||
		wlr_input_device_destroy(input_device);
 | 
							wlr_input_device_destroy(input_device);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&backend->local_display_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(backend->seat_name);
 | 
						free(backend->seat_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_source_remove(backend->remote_display_src);
 | 
						wl_event_source_remove(backend->remote_display_src);
 | 
				
			||||||
	wlr_egl_free(&backend->egl);
 | 
						wlr_egl_finish(&backend->egl);
 | 
				
			||||||
	if (backend->seat) wl_seat_destroy(backend->seat);
 | 
						if (backend->seat) wl_seat_destroy(backend->seat);
 | 
				
			||||||
	if (backend->shm) wl_shm_destroy(backend->shm);
 | 
						if (backend->shm) wl_shm_destroy(backend->shm);
 | 
				
			||||||
	if (backend->shell) zxdg_shell_v6_destroy(backend->shell);
 | 
						if (backend->shell) zxdg_shell_v6_destroy(backend->shell);
 | 
				
			||||||
| 
						 | 
					@ -150,6 +152,12 @@ void wlr_wl_output_layout_get_box(struct wlr_wl_backend *backend,
 | 
				
			||||||
	box->height = max_y - min_y;
 | 
						box->height = max_y - min_y;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_wl_backend *backend =
 | 
				
			||||||
 | 
							wl_container_of(listener, backend, local_display_destroy);
 | 
				
			||||||
 | 
						wlr_wl_backend_destroy(&backend->backend);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
 | 
					struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
 | 
				
			||||||
	wlr_log(L_INFO, "Creating wayland backend");
 | 
						wlr_log(L_INFO, "Creating wayland backend");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -176,8 +184,12 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_display *display) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT, WL_SHM_FORMAT_ARGB8888, backend->remote_display);
 | 
						wlr_egl_init(&backend->egl, EGL_PLATFORM_WAYLAND_EXT,
 | 
				
			||||||
 | 
							WL_SHM_FORMAT_ARGB8888, backend->remote_display);
 | 
				
			||||||
	wlr_egl_bind_display(&backend->egl, backend->local_display);
 | 
						wlr_egl_bind_display(&backend->egl, backend->local_display);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backend->local_display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &backend->local_display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &backend->backend;
 | 
						return &backend->backend;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,69 +183,6 @@ static void init_atom(struct wlr_x11_backend *x11, struct wlr_x11_atom *atom,
 | 
				
			||||||
	atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL);
 | 
						atom->reply = xcb_intern_atom_reply(x11->xcb_conn, atom->cookie, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
 | 
					 | 
				
			||||||
		const char *x11_display) {
 | 
					 | 
				
			||||||
	struct wlr_x11_backend *x11 = calloc(1, sizeof(*x11));
 | 
					 | 
				
			||||||
	if (!x11) {
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_backend_init(&x11->backend, &backend_impl);
 | 
					 | 
				
			||||||
	x11->wl_display = display;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	x11->xlib_conn = XOpenDisplay(x11_display);
 | 
					 | 
				
			||||||
	if (!x11->xlib_conn) {
 | 
					 | 
				
			||||||
		wlr_log(L_ERROR, "Failed to open X connection");
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	x11->xcb_conn = XGetXCBConnection(x11->xlib_conn);
 | 
					 | 
				
			||||||
	if (!x11->xcb_conn || xcb_connection_has_error(x11->xcb_conn)) {
 | 
					 | 
				
			||||||
		wlr_log(L_ERROR, "Failed to open xcb connection");
 | 
					 | 
				
			||||||
		goto error_x11;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	XSetEventQueueOwner(x11->xlib_conn, XCBOwnsEventQueue);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int fd = xcb_get_file_descriptor(x11->xcb_conn);
 | 
					 | 
				
			||||||
	struct wl_event_loop *ev = wl_display_get_event_loop(display);
 | 
					 | 
				
			||||||
	int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
 | 
					 | 
				
			||||||
	x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
 | 
					 | 
				
			||||||
	if (!x11->event_source) {
 | 
					 | 
				
			||||||
		wlr_log(L_ERROR, "Could not create event source");
 | 
					 | 
				
			||||||
		goto error_x11;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	x11->frame_timer = wl_event_loop_add_timer(ev, signal_frame, x11);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!wlr_egl_init(&x11->egl, EGL_PLATFORM_X11_KHR,
 | 
					 | 
				
			||||||
			x11->screen->root_visual, x11->xlib_conn)) {
 | 
					 | 
				
			||||||
		goto error_event;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD,
 | 
					 | 
				
			||||||
		NULL, "X11 keyboard", 0, 0);
 | 
					 | 
				
			||||||
	wlr_keyboard_init(&x11->keyboard, NULL);
 | 
					 | 
				
			||||||
	x11->keyboard_dev.keyboard = &x11->keyboard;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_input_device_init(&x11->pointer_dev, WLR_INPUT_DEVICE_POINTER,
 | 
					 | 
				
			||||||
		NULL, "X11 pointer", 0, 0);
 | 
					 | 
				
			||||||
	wlr_pointer_init(&x11->pointer, NULL);
 | 
					 | 
				
			||||||
	x11->pointer_dev.pointer = &x11->pointer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &x11->backend;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
error_event:
 | 
					 | 
				
			||||||
	wl_event_source_remove(x11->event_source);
 | 
					 | 
				
			||||||
error_x11:
 | 
					 | 
				
			||||||
	xcb_disconnect(x11->xcb_conn);
 | 
					 | 
				
			||||||
	XCloseDisplay(x11->xlib_conn);
 | 
					 | 
				
			||||||
	free(x11);
 | 
					 | 
				
			||||||
	return NULL;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static bool wlr_x11_backend_start(struct wlr_backend *backend) {
 | 
					static bool wlr_x11_backend_start(struct wlr_backend *backend) {
 | 
				
			||||||
	struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend;
 | 
						struct wlr_x11_backend *x11 = (struct wlr_x11_backend *)backend;
 | 
				
			||||||
	struct wlr_x11_output *output = &x11->output;
 | 
						struct wlr_x11_output *output = &x11->output;
 | 
				
			||||||
| 
						 | 
					@ -306,8 +243,10 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) {
 | 
				
			||||||
	struct wlr_x11_output *output = &x11->output;
 | 
						struct wlr_x11_output *output = &x11->output;
 | 
				
			||||||
	wlr_output_destroy(&output->wlr_output);
 | 
						wlr_output_destroy(&output->wlr_output);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&x11->display_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_event_source_remove(x11->frame_timer);
 | 
						wl_event_source_remove(x11->frame_timer);
 | 
				
			||||||
	wlr_egl_free(&x11->egl);
 | 
						wlr_egl_finish(&x11->egl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xcb_disconnect(x11->xcb_conn);
 | 
						xcb_disconnect(x11->xcb_conn);
 | 
				
			||||||
	free(x11);
 | 
						free(x11);
 | 
				
			||||||
| 
						 | 
					@ -328,6 +267,78 @@ static struct wlr_backend_impl backend_impl = {
 | 
				
			||||||
	.get_egl = wlr_x11_backend_get_egl,
 | 
						.get_egl = wlr_x11_backend_get_egl,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_x11_backend *x11 =
 | 
				
			||||||
 | 
							wl_container_of(listener, x11, display_destroy);
 | 
				
			||||||
 | 
						wlr_x11_backend_destroy(&x11->backend);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct wlr_backend *wlr_x11_backend_create(struct wl_display *display,
 | 
				
			||||||
 | 
							const char *x11_display) {
 | 
				
			||||||
 | 
						struct wlr_x11_backend *x11 = calloc(1, sizeof(*x11));
 | 
				
			||||||
 | 
						if (!x11) {
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_backend_init(&x11->backend, &backend_impl);
 | 
				
			||||||
 | 
						x11->wl_display = display;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11->xlib_conn = XOpenDisplay(x11_display);
 | 
				
			||||||
 | 
						if (!x11->xlib_conn) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to open X connection");
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11->xcb_conn = XGetXCBConnection(x11->xlib_conn);
 | 
				
			||||||
 | 
						if (!x11->xcb_conn || xcb_connection_has_error(x11->xcb_conn)) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Failed to open xcb connection");
 | 
				
			||||||
 | 
							goto error_x11;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						XSetEventQueueOwner(x11->xlib_conn, XCBOwnsEventQueue);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int fd = xcb_get_file_descriptor(x11->xcb_conn);
 | 
				
			||||||
 | 
						struct wl_event_loop *ev = wl_display_get_event_loop(display);
 | 
				
			||||||
 | 
						int events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
 | 
				
			||||||
 | 
						x11->event_source = wl_event_loop_add_fd(ev, fd, events, x11_event, x11);
 | 
				
			||||||
 | 
						if (!x11->event_source) {
 | 
				
			||||||
 | 
							wlr_log(L_ERROR, "Could not create event source");
 | 
				
			||||||
 | 
							goto error_x11;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11->frame_timer = wl_event_loop_add_timer(ev, signal_frame, x11);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11->screen = xcb_setup_roots_iterator(xcb_get_setup(x11->xcb_conn)).data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!wlr_egl_init(&x11->egl, EGL_PLATFORM_X11_KHR,
 | 
				
			||||||
 | 
								x11->screen->root_visual, x11->xlib_conn)) {
 | 
				
			||||||
 | 
							goto error_event;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_input_device_init(&x11->keyboard_dev, WLR_INPUT_DEVICE_KEYBOARD,
 | 
				
			||||||
 | 
							NULL, "X11 keyboard", 0, 0);
 | 
				
			||||||
 | 
						wlr_keyboard_init(&x11->keyboard, NULL);
 | 
				
			||||||
 | 
						x11->keyboard_dev.keyboard = &x11->keyboard;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_input_device_init(&x11->pointer_dev, WLR_INPUT_DEVICE_POINTER,
 | 
				
			||||||
 | 
							NULL, "X11 pointer", 0, 0);
 | 
				
			||||||
 | 
						wlr_pointer_init(&x11->pointer, NULL);
 | 
				
			||||||
 | 
						x11->pointer_dev.pointer = &x11->pointer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						x11->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &x11->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &x11->backend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					error_event:
 | 
				
			||||||
 | 
						wl_event_source_remove(x11->event_source);
 | 
				
			||||||
 | 
					error_x11:
 | 
				
			||||||
 | 
						xcb_disconnect(x11->xcb_conn);
 | 
				
			||||||
 | 
						XCloseDisplay(x11->xlib_conn);
 | 
				
			||||||
 | 
						free(x11);
 | 
				
			||||||
 | 
						return NULL;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width,
 | 
					static bool output_set_custom_mode(struct wlr_output *wlr_output, int32_t width,
 | 
				
			||||||
		int32_t height, int32_t refresh) {
 | 
							int32_t height, int32_t refresh) {
 | 
				
			||||||
	struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output;
 | 
						struct wlr_x11_output *output = (struct wlr_x11_output *)wlr_output;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,7 @@ struct wlr_drm_backend {
 | 
				
			||||||
	struct wl_display *display;
 | 
						struct wl_display *display;
 | 
				
			||||||
	struct wl_event_source *drm_event;
 | 
						struct wl_event_source *drm_event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
	struct wl_listener session_signal;
 | 
						struct wl_listener session_signal;
 | 
				
			||||||
	struct wl_listener drm_invalidated;
 | 
						struct wl_listener drm_invalidated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,6 +16,7 @@ struct wlr_libinput_backend {
 | 
				
			||||||
	struct libinput *libinput_context;
 | 
						struct libinput *libinput_context;
 | 
				
			||||||
	struct wl_event_source *input_event;
 | 
						struct wl_event_source *input_event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
	struct wl_listener session_signal;
 | 
						struct wl_listener session_signal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_list wlr_device_lists; // list of struct wl_list
 | 
						struct wlr_list wlr_device_lists; // list of struct wl_list
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ struct wlr_wl_backend {
 | 
				
			||||||
	struct wl_list outputs;
 | 
						struct wl_list outputs;
 | 
				
			||||||
	struct wlr_egl egl;
 | 
						struct wlr_egl egl;
 | 
				
			||||||
	size_t requested_outputs;
 | 
						size_t requested_outputs;
 | 
				
			||||||
 | 
						struct wl_listener local_display_destroy;
 | 
				
			||||||
	/* remote state */
 | 
						/* remote state */
 | 
				
			||||||
	struct wl_display *remote_display;
 | 
						struct wl_display *remote_display;
 | 
				
			||||||
	struct wl_event_source *remote_display_src;
 | 
						struct wl_event_source *remote_display_src;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,8 @@ struct wlr_x11_backend {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// The time we last received an event
 | 
						// The time we last received an event
 | 
				
			||||||
	xcb_timestamp_t time;
 | 
						xcb_timestamp_t time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,8 @@ struct wlr_session {
 | 
				
			||||||
	struct wl_event_source *udev_event;
 | 
						struct wl_event_source *udev_event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_list devices;
 | 
						struct wl_list devices;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,6 +4,7 @@
 | 
				
			||||||
#include <EGL/egl.h>
 | 
					#include <EGL/egl.h>
 | 
				
			||||||
#include <EGL/eglext.h>
 | 
					#include <EGL/eglext.h>
 | 
				
			||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
 | 
					#include <wayland-server.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_egl {
 | 
					struct wlr_egl {
 | 
				
			||||||
	EGLDisplay display;
 | 
						EGLDisplay display;
 | 
				
			||||||
| 
						 | 
					@ -27,7 +28,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, EGLint visual_id, void
 | 
				
			||||||
 * Frees all related egl resources, makes the context not-current and
 | 
					 * Frees all related egl resources, makes the context not-current and
 | 
				
			||||||
 * unbinds a bound wayland display.
 | 
					 * unbinds a bound wayland display.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void wlr_egl_free(struct wlr_egl *egl);
 | 
					void wlr_egl_finish(struct wlr_egl *egl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Binds the given display to the egl instance.
 | 
					 * Binds the given display to the egl instance.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,8 @@ struct wlr_compositor {
 | 
				
			||||||
	struct wl_list wl_resources;
 | 
						struct wl_list wl_resources;
 | 
				
			||||||
	struct wlr_renderer *renderer;
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
	struct wl_list surfaces;
 | 
						struct wl_list surfaces;
 | 
				
			||||||
	struct wl_listener destroy_surface_listener;
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal create_surface;
 | 
							struct wl_signal create_surface;
 | 
				
			||||||
| 
						 | 
					@ -20,8 +21,4 @@ void wlr_compositor_destroy(struct wlr_compositor *wlr_compositor);
 | 
				
			||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
					struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
				
			||||||
		struct wlr_renderer *renderer);
 | 
							struct wlr_renderer *renderer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_surface;
 | 
					 | 
				
			||||||
void wl_compositor_surface_destroyed(struct wlr_compositor *wlr_compositor,
 | 
					 | 
				
			||||||
		struct wlr_surface *surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,8 @@ wlr_touch_grab_interface wlr_data_device_touch_drag_interface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_data_device_manager {
 | 
					struct wlr_data_device_manager {
 | 
				
			||||||
	struct wl_global *global;
 | 
						struct wl_global *global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_data_offer {
 | 
					struct wlr_data_offer {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_gamma_control_manager {
 | 
					struct wlr_gamma_control_manager {
 | 
				
			||||||
	struct wl_global *wl_global;
 | 
						struct wl_global *wl_global;
 | 
				
			||||||
	struct wl_list controls; // list of wlr_gamma_control
 | 
						struct wl_list controls; // wlr_gamma_control::link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,6 +77,8 @@ struct wlr_output {
 | 
				
			||||||
	// the output position in layout space reported to clients
 | 
						// the output position in layout space reported to clients
 | 
				
			||||||
	int32_t lx, ly;
 | 
						int32_t lx, ly;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,9 @@
 | 
				
			||||||
struct wlr_screenshooter {
 | 
					struct wlr_screenshooter {
 | 
				
			||||||
	struct wl_global *wl_global;
 | 
						struct wl_global *wl_global;
 | 
				
			||||||
	struct wlr_renderer *renderer;
 | 
						struct wlr_renderer *renderer;
 | 
				
			||||||
 | 
						struct wl_list screenshots; // wlr_screenshot::link
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void *data;
 | 
						void *data;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -12,6 +15,7 @@ struct wlr_screenshooter {
 | 
				
			||||||
struct wlr_screenshot {
 | 
					struct wlr_screenshot {
 | 
				
			||||||
	struct wl_resource *resource;
 | 
						struct wl_resource *resource;
 | 
				
			||||||
	struct wl_resource *output_resource;
 | 
						struct wl_resource *output_resource;
 | 
				
			||||||
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_output *output;
 | 
						struct wlr_output *output;
 | 
				
			||||||
	struct wlr_screenshooter *screenshooter;
 | 
						struct wlr_screenshooter *screenshooter;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -184,6 +184,7 @@ struct wlr_seat {
 | 
				
			||||||
	struct wlr_seat_keyboard_state keyboard_state;
 | 
						struct wlr_seat_keyboard_state keyboard_state;
 | 
				
			||||||
	struct wlr_seat_touch_state touch_state;
 | 
						struct wlr_seat_touch_state touch_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
	struct wl_listener selection_data_source_destroy;
 | 
						struct wl_listener selection_data_source_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,8 @@ struct wlr_server_decoration_manager {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t default_mode; // enum wlr_server_decoration_manager_mode
 | 
						uint32_t default_mode; // enum wlr_server_decoration_manager_mode
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal new_decoration;
 | 
							struct wl_signal new_decoration;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,8 @@ struct wlr_wl_shell {
 | 
				
			||||||
	struct wl_list popup_grabs;
 | 
						struct wl_list popup_grabs;
 | 
				
			||||||
	uint32_t ping_timeout;
 | 
						uint32_t ping_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal new_surface;
 | 
							struct wl_signal new_surface;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,8 @@ struct wlr_xdg_shell_v6 {
 | 
				
			||||||
	struct wl_list popup_grabs;
 | 
						struct wl_list popup_grabs;
 | 
				
			||||||
	uint32_t ping_timeout;
 | 
						uint32_t ping_timeout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal new_surface;
 | 
							struct wl_signal new_surface;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,8 @@ struct wlr_xwayland {
 | 
				
			||||||
	time_t server_start;
 | 
						time_t server_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_event_source *sigusr1_source;
 | 
						struct wl_event_source *sigusr1_source;
 | 
				
			||||||
	struct wl_listener destroy_listener;
 | 
						struct wl_listener client_destroy;
 | 
				
			||||||
 | 
						struct wl_listener display_destroy;
 | 
				
			||||||
	struct wlr_xwm *xwm;
 | 
						struct wlr_xwm *xwm;
 | 
				
			||||||
	struct wlr_xwayland_cursor *cursor;
 | 
						struct wlr_xwayland_cursor *cursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,7 +141,7 @@ error:
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_egl_free(struct wlr_egl *egl) {
 | 
					void wlr_egl_finish(struct wlr_egl *egl) {
 | 
				
			||||||
	eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | 
						eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
 | 
				
			||||||
	if (egl->wl_display && eglUnbindWaylandDisplayWL) {
 | 
						if (egl->wl_display && eglUnbindWaylandDisplayWL) {
 | 
				
			||||||
		eglUnbindWaylandDisplayWL(egl->display, egl->wl_display);
 | 
							eglUnbindWaylandDisplayWL(egl->display, egl->wl_display);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,6 +51,7 @@ int main(int argc, char **argv) {
 | 
				
			||||||
	if (!wlr_backend_start(server.backend)) {
 | 
						if (!wlr_backend_start(server.backend)) {
 | 
				
			||||||
		wlr_log(L_ERROR, "Failed to start backend");
 | 
							wlr_log(L_ERROR, "Failed to start backend");
 | 
				
			||||||
		wlr_backend_destroy(server.backend);
 | 
							wlr_backend_destroy(server.backend);
 | 
				
			||||||
 | 
							wl_display_destroy(server.wl_display);
 | 
				
			||||||
		return 1;
 | 
							return 1;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -69,5 +70,6 @@ int main(int argc, char **argv) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_display_run(server.wl_display);
 | 
						wl_display_run(server.wl_display);
 | 
				
			||||||
	wlr_backend_destroy(server.backend);
 | 
						wlr_backend_destroy(server.backend);
 | 
				
			||||||
 | 
						wl_display_destroy(server.wl_display);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,6 +78,10 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *data,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_compositor_destroy(struct wlr_compositor *compositor) {
 | 
					void wlr_compositor_destroy(struct wlr_compositor *compositor) {
 | 
				
			||||||
 | 
						if (compositor == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&compositor->display_destroy.link);
 | 
				
			||||||
	wl_global_destroy(compositor->wl_global);
 | 
						wl_global_destroy(compositor->wl_global);
 | 
				
			||||||
	free(compositor);
 | 
						free(compositor);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -151,6 +155,12 @@ static void subcompositor_bind(struct wl_client *client, void *data,
 | 
				
			||||||
		compositor, NULL);
 | 
							compositor, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_compositor *compositor =
 | 
				
			||||||
 | 
							wl_container_of(listener, compositor, display_destroy);
 | 
				
			||||||
 | 
						wlr_compositor_destroy(compositor);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
					struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
				
			||||||
		struct wlr_renderer *renderer) {
 | 
							struct wlr_renderer *renderer) {
 | 
				
			||||||
	struct wlr_compositor *compositor =
 | 
						struct wlr_compositor *compositor =
 | 
				
			||||||
| 
						 | 
					@ -162,7 +172,11 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_global *compositor_global = wl_global_create(display,
 | 
						struct wl_global *compositor_global = wl_global_create(display,
 | 
				
			||||||
		&wl_compositor_interface, 4, compositor, wl_compositor_bind);
 | 
							&wl_compositor_interface, 4, compositor, wl_compositor_bind);
 | 
				
			||||||
 | 
						if (!compositor_global) {
 | 
				
			||||||
 | 
							wlr_log_errno(L_ERROR, "Could not allocate compositor global");
 | 
				
			||||||
 | 
							free(compositor);
 | 
				
			||||||
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	compositor->wl_global = compositor_global;
 | 
						compositor->wl_global = compositor_global;
 | 
				
			||||||
	compositor->renderer = renderer;
 | 
						compositor->renderer = renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,5 +187,8 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display,
 | 
				
			||||||
	wl_list_init(&compositor->surfaces);
 | 
						wl_list_init(&compositor->surfaces);
 | 
				
			||||||
	wl_signal_init(&compositor->events.create_surface);
 | 
						wl_signal_init(&compositor->events.create_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						compositor->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &compositor->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return compositor;
 | 
						return compositor;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -949,6 +949,21 @@ static void data_device_manager_bind(struct wl_client *client,
 | 
				
			||||||
		NULL, NULL);
 | 
							NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
 | 
				
			||||||
 | 
						if (!manager) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&manager->display_destroy.link);
 | 
				
			||||||
 | 
						wl_global_destroy(manager->global);
 | 
				
			||||||
 | 
						free(manager);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_data_device_manager *manager =
 | 
				
			||||||
 | 
							wl_container_of(listener, manager, display_destroy);
 | 
				
			||||||
 | 
						wlr_data_device_manager_destroy(manager);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_data_device_manager *wlr_data_device_manager_create(
 | 
					struct wlr_data_device_manager *wlr_data_device_manager_create(
 | 
				
			||||||
		struct wl_display *display) {
 | 
							struct wl_display *display) {
 | 
				
			||||||
	struct wlr_data_device_manager *manager =
 | 
						struct wlr_data_device_manager *manager =
 | 
				
			||||||
| 
						 | 
					@ -967,13 +982,8 @@ struct wlr_data_device_manager *wlr_data_device_manager_create(
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &manager->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return manager;
 | 
						return manager;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void wlr_data_device_manager_destroy(struct wlr_data_device_manager *manager) {
 | 
					 | 
				
			||||||
	if (!manager) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wl_global_destroy(manager->global);
 | 
					 | 
				
			||||||
	free(manager);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,6 +12,9 @@ static void resource_destroy(struct wl_client *client,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) {
 | 
					static void gamma_control_destroy(struct wlr_gamma_control *gamma_control) {
 | 
				
			||||||
 | 
						if (gamma_control == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	wl_signal_emit(&gamma_control->events.destroy, gamma_control);
 | 
						wl_signal_emit(&gamma_control->events.destroy, gamma_control);
 | 
				
			||||||
	wl_list_remove(&gamma_control->output_destroy_listener.link);
 | 
						wl_list_remove(&gamma_control->output_destroy_listener.link);
 | 
				
			||||||
	wl_resource_set_user_data(gamma_control->resource, NULL);
 | 
						wl_resource_set_user_data(gamma_control->resource, NULL);
 | 
				
			||||||
| 
						 | 
					@ -67,7 +70,7 @@ static const struct gamma_control_interface gamma_control_impl = {
 | 
				
			||||||
static void gamma_control_manager_get_gamma_control(struct wl_client *client,
 | 
					static void gamma_control_manager_get_gamma_control(struct wl_client *client,
 | 
				
			||||||
		struct wl_resource *gamma_control_manager_resource, uint32_t id,
 | 
							struct wl_resource *gamma_control_manager_resource, uint32_t id,
 | 
				
			||||||
		struct wl_resource *output_resource) {
 | 
							struct wl_resource *output_resource) {
 | 
				
			||||||
	struct wlr_gamma_control_manager *gamma_control_manager =
 | 
						struct wlr_gamma_control_manager *manager =
 | 
				
			||||||
		wl_resource_get_user_data(gamma_control_manager_resource);
 | 
							wl_resource_get_user_data(gamma_control_manager_resource);
 | 
				
			||||||
	struct wlr_output *output = wl_resource_get_user_data(output_resource);
 | 
						struct wlr_output *output = wl_resource_get_user_data(output_resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +102,7 @@ static void gamma_control_manager_get_gamma_control(struct wl_client *client,
 | 
				
			||||||
	gamma_control->output_destroy_listener.notify =
 | 
						gamma_control->output_destroy_listener.notify =
 | 
				
			||||||
		gamma_control_handle_output_destroy;
 | 
							gamma_control_handle_output_destroy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_insert(&gamma_control_manager->controls, &gamma_control->link);
 | 
						wl_list_insert(&manager->controls, &gamma_control->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gamma_control_send_gamma_size(gamma_control->resource,
 | 
						gamma_control_send_gamma_size(gamma_control->resource,
 | 
				
			||||||
		wlr_output_get_gamma_size(output));
 | 
							wlr_output_get_gamma_size(output));
 | 
				
			||||||
| 
						 | 
					@ -111,8 +114,8 @@ static struct gamma_control_manager_interface gamma_control_manager_impl = {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void gamma_control_manager_bind(struct wl_client *client, void *data,
 | 
					static void gamma_control_manager_bind(struct wl_client *client, void *data,
 | 
				
			||||||
		uint32_t version, uint32_t id) {
 | 
							uint32_t version, uint32_t id) {
 | 
				
			||||||
	struct wlr_gamma_control_manager *gamma_control_manager = data;
 | 
						struct wlr_gamma_control_manager *manager = data;
 | 
				
			||||||
	assert(client && gamma_control_manager);
 | 
						assert(client && manager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_resource *resource = wl_resource_create(client,
 | 
						struct wl_resource *resource = wl_resource_create(client,
 | 
				
			||||||
		&gamma_control_manager_interface, version, id);
 | 
							&gamma_control_manager_interface, version, id);
 | 
				
			||||||
| 
						 | 
					@ -121,41 +124,49 @@ static void gamma_control_manager_bind(struct wl_client *client, void *data,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wl_resource_set_implementation(resource, &gamma_control_manager_impl,
 | 
						wl_resource_set_implementation(resource, &gamma_control_manager_impl,
 | 
				
			||||||
		gamma_control_manager, NULL);
 | 
							manager, NULL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_gamma_control_manager_destroy(
 | 
				
			||||||
 | 
							struct wlr_gamma_control_manager *manager) {
 | 
				
			||||||
 | 
						if (!manager) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&manager->display_destroy.link);
 | 
				
			||||||
 | 
						struct wlr_gamma_control *gamma_control, *tmp;
 | 
				
			||||||
 | 
						wl_list_for_each_safe(gamma_control, tmp, &manager->controls, link) {
 | 
				
			||||||
 | 
							gamma_control_destroy(gamma_control);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_global_destroy(manager->wl_global);
 | 
				
			||||||
 | 
						free(manager);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_gamma_control_manager *manager =
 | 
				
			||||||
 | 
							wl_container_of(listener, manager, display_destroy);
 | 
				
			||||||
 | 
						wlr_gamma_control_manager_destroy(manager);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_gamma_control_manager *wlr_gamma_control_manager_create(
 | 
					struct wlr_gamma_control_manager *wlr_gamma_control_manager_create(
 | 
				
			||||||
		struct wl_display *display) {
 | 
							struct wl_display *display) {
 | 
				
			||||||
	struct wlr_gamma_control_manager *gamma_control_manager =
 | 
						struct wlr_gamma_control_manager *manager =
 | 
				
			||||||
		calloc(1, sizeof(struct wlr_gamma_control_manager));
 | 
							calloc(1, sizeof(struct wlr_gamma_control_manager));
 | 
				
			||||||
	if (!gamma_control_manager) {
 | 
						if (!manager) {
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct wl_global *wl_global = wl_global_create(display,
 | 
						struct wl_global *wl_global = wl_global_create(display,
 | 
				
			||||||
		&gamma_control_manager_interface, 1, gamma_control_manager,
 | 
							&gamma_control_manager_interface, 1, manager,
 | 
				
			||||||
		gamma_control_manager_bind);
 | 
							gamma_control_manager_bind);
 | 
				
			||||||
	if (!wl_global) {
 | 
						if (!wl_global) {
 | 
				
			||||||
		free(gamma_control_manager);
 | 
							free(manager);
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	gamma_control_manager->wl_global = wl_global;
 | 
						manager->wl_global = wl_global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_list_init(&gamma_control_manager->controls);
 | 
						wl_list_init(&manager->controls);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return gamma_control_manager;
 | 
						manager->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
}
 | 
						wl_display_add_destroy_listener(display, &manager->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_gamma_control_manager_destroy(
 | 
						return manager;
 | 
				
			||||||
		struct wlr_gamma_control_manager *gamma_control_manager) {
 | 
					 | 
				
			||||||
	if (!gamma_control_manager) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	struct wlr_gamma_control *gamma_control, *tmp;
 | 
					 | 
				
			||||||
	wl_list_for_each_safe(gamma_control, tmp, &gamma_control_manager->controls,
 | 
					 | 
				
			||||||
			link) {
 | 
					 | 
				
			||||||
		gamma_control_destroy(gamma_control);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: this segfault (wl_display->registry_resource_list is not init)
 | 
					 | 
				
			||||||
	// wl_global_destroy(gamma_control_manager->wl_global);
 | 
					 | 
				
			||||||
	free(gamma_control_manager);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -112,6 +112,12 @@ static void wl_output_bind(struct wl_client *wl_client, void *data,
 | 
				
			||||||
	wl_output_send_to_resource(wl_resource);
 | 
						wl_output_send_to_resource(wl_resource);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_output *output =
 | 
				
			||||||
 | 
							wl_container_of(listener, output, display_destroy);
 | 
				
			||||||
 | 
						wlr_output_destroy_global(output);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
 | 
					struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
 | 
				
			||||||
		struct wl_display *display) {
 | 
							struct wl_display *display) {
 | 
				
			||||||
	if (wlr_output->wl_global != NULL) {
 | 
						if (wlr_output->wl_global != NULL) {
 | 
				
			||||||
| 
						 | 
					@ -120,6 +126,10 @@ struct wl_global *wlr_output_create_global(struct wlr_output *wlr_output,
 | 
				
			||||||
	struct wl_global *wl_global = wl_global_create(display,
 | 
						struct wl_global *wl_global = wl_global_create(display,
 | 
				
			||||||
		&wl_output_interface, 3, wlr_output, wl_output_bind);
 | 
							&wl_output_interface, 3, wlr_output, wl_output_bind);
 | 
				
			||||||
	wlr_output->wl_global = wl_global;
 | 
						wlr_output->wl_global = wl_global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_output->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &wlr_output->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return wl_global;
 | 
						return wl_global;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -127,6 +137,7 @@ void wlr_output_destroy_global(struct wlr_output *wlr_output) {
 | 
				
			||||||
	if (wlr_output->wl_global == NULL) {
 | 
						if (wlr_output->wl_global == NULL) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&wlr_output->display_destroy.link);
 | 
				
			||||||
	struct wl_resource *resource, *tmp;
 | 
						struct wl_resource *resource, *tmp;
 | 
				
			||||||
	wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) {
 | 
						wl_resource_for_each_safe(resource, tmp, &wlr_output->wl_resources) {
 | 
				
			||||||
		struct wl_list *link = wl_resource_get_link(resource);
 | 
							struct wl_list *link = wl_resource_get_link(resource);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -26,6 +26,21 @@ struct screenshot_state {
 | 
				
			||||||
	struct wl_listener frame_listener;
 | 
						struct wl_listener frame_listener;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void screenshot_destroy(struct wlr_screenshot *screenshot) {
 | 
				
			||||||
 | 
						wl_list_remove(&screenshot->link);
 | 
				
			||||||
 | 
						wl_resource_set_user_data(screenshot->resource, NULL);
 | 
				
			||||||
 | 
						free(screenshot);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_screenshot_resource_destroy(
 | 
				
			||||||
 | 
							struct wl_resource *screenshot_resource) {
 | 
				
			||||||
 | 
						struct wlr_screenshot *screenshot =
 | 
				
			||||||
 | 
							wl_resource_get_user_data(screenshot_resource);
 | 
				
			||||||
 | 
						if (screenshot != NULL) {
 | 
				
			||||||
 | 
							screenshot_destroy(screenshot);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void output_frame_notify(struct wl_listener *listener, void *_data) {
 | 
					static void output_frame_notify(struct wl_listener *listener, void *_data) {
 | 
				
			||||||
	struct screenshot_state *state = wl_container_of(listener, state,
 | 
						struct screenshot_state *state = wl_container_of(listener, state,
 | 
				
			||||||
		frame_listener);
 | 
							frame_listener);
 | 
				
			||||||
| 
						 | 
					@ -102,7 +117,8 @@ static void screenshooter_shoot(struct wl_client *client,
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wl_resource_set_implementation(screenshot->resource, NULL, screenshot,
 | 
						wl_resource_set_implementation(screenshot->resource, NULL, screenshot,
 | 
				
			||||||
		NULL);
 | 
							handle_screenshot_resource_destroy);
 | 
				
			||||||
 | 
						wl_list_insert(&screenshooter->screenshots, &screenshot->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_log(L_DEBUG, "new screenshot %p (res %p)", screenshot,
 | 
						wlr_log(L_DEBUG, "new screenshot %p (res %p)", screenshot,
 | 
				
			||||||
		screenshot->resource);
 | 
							screenshot->resource);
 | 
				
			||||||
| 
						 | 
					@ -144,6 +160,25 @@ static void screenshooter_bind(struct wl_client *wl_client, void *data,
 | 
				
			||||||
		screenshooter, NULL);
 | 
							screenshooter, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) {
 | 
				
			||||||
 | 
						if (!screenshooter) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&screenshooter->display_destroy.link);
 | 
				
			||||||
 | 
						struct wlr_screenshot *screenshot, *tmp;
 | 
				
			||||||
 | 
						wl_list_for_each_safe(screenshot, tmp, &screenshooter->screenshots, link) {
 | 
				
			||||||
 | 
							screenshot_destroy(screenshot);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_global_destroy(screenshooter->wl_global);
 | 
				
			||||||
 | 
						free(screenshooter);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_screenshooter *screenshooter =
 | 
				
			||||||
 | 
							wl_container_of(listener, screenshooter, display_destroy);
 | 
				
			||||||
 | 
						wlr_screenshooter_destroy(screenshooter);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
 | 
					struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
 | 
				
			||||||
		struct wlr_renderer *renderer) {
 | 
							struct wlr_renderer *renderer) {
 | 
				
			||||||
	struct wlr_screenshooter *screenshooter =
 | 
						struct wlr_screenshooter *screenshooter =
 | 
				
			||||||
| 
						 | 
					@ -153,6 +188,11 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	screenshooter->renderer = renderer;
 | 
						screenshooter->renderer = renderer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_init(&screenshooter->screenshots);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						screenshooter->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &screenshooter->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	screenshooter->wl_global = wl_global_create(display,
 | 
						screenshooter->wl_global = wl_global_create(display,
 | 
				
			||||||
		&orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind);
 | 
							&orbital_screenshooter_interface, 1, screenshooter, screenshooter_bind);
 | 
				
			||||||
	if (screenshooter->wl_global == NULL) {
 | 
						if (screenshooter->wl_global == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -162,12 +202,3 @@ struct wlr_screenshooter *wlr_screenshooter_create(struct wl_display *display,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return screenshooter;
 | 
						return screenshooter;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void wlr_screenshooter_destroy(struct wlr_screenshooter *screenshooter) {
 | 
					 | 
				
			||||||
	if (!screenshooter) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// TODO: this segfault (wl_display->registry_resource_list is not init)
 | 
					 | 
				
			||||||
	// wl_global_destroy(screenshooter->wl_global);
 | 
					 | 
				
			||||||
	free(screenshooter);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -346,6 +346,34 @@ static const struct wlr_touch_grab_interface default_touch_grab_impl = {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_seat_destroy(struct wlr_seat *wlr_seat) {
 | 
				
			||||||
 | 
						if (!wlr_seat) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&wlr_seat->display_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_seat_client *client, *tmp;
 | 
				
			||||||
 | 
						wl_list_for_each_safe(client, tmp, &wlr_seat->clients, link) {
 | 
				
			||||||
 | 
							// will destroy other resources as well
 | 
				
			||||||
 | 
							wl_resource_destroy(client->wl_resource);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_global_destroy(wlr_seat->wl_global);
 | 
				
			||||||
 | 
						free(wlr_seat->pointer_state.default_grab);
 | 
				
			||||||
 | 
						free(wlr_seat->keyboard_state.default_grab);
 | 
				
			||||||
 | 
						free(wlr_seat->touch_state.default_grab);
 | 
				
			||||||
 | 
						free(wlr_seat->data_device);
 | 
				
			||||||
 | 
						free(wlr_seat->name);
 | 
				
			||||||
 | 
						free(wlr_seat);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_seat *seat =
 | 
				
			||||||
 | 
							wl_container_of(listener, seat, display_destroy);
 | 
				
			||||||
 | 
						wlr_seat_destroy(seat);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
 | 
					struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
 | 
				
			||||||
	struct wlr_seat *wlr_seat = calloc(1, sizeof(struct wlr_seat));
 | 
						struct wlr_seat *wlr_seat = calloc(1, sizeof(struct wlr_seat));
 | 
				
			||||||
	if (!wlr_seat) {
 | 
						if (!wlr_seat) {
 | 
				
			||||||
| 
						 | 
					@ -427,29 +455,12 @@ struct wlr_seat *wlr_seat_create(struct wl_display *display, const char *name) {
 | 
				
			||||||
	wl_signal_init(&wlr_seat->events.touch_grab_begin);
 | 
						wl_signal_init(&wlr_seat->events.touch_grab_begin);
 | 
				
			||||||
	wl_signal_init(&wlr_seat->events.touch_grab_end);
 | 
						wl_signal_init(&wlr_seat->events.touch_grab_end);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_seat->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &wlr_seat->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return wlr_seat;
 | 
						return wlr_seat;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_seat_destroy(struct wlr_seat *wlr_seat) {
 | 
					 | 
				
			||||||
	if (!wlr_seat) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_seat_client *client, *tmp;
 | 
					 | 
				
			||||||
	wl_list_for_each_safe(client, tmp, &wlr_seat->clients, link) {
 | 
					 | 
				
			||||||
		// will destroy other resources as well
 | 
					 | 
				
			||||||
		wl_resource_destroy(client->wl_resource);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wl_global_destroy(wlr_seat->wl_global);
 | 
					 | 
				
			||||||
	free(wlr_seat->pointer_state.default_grab);
 | 
					 | 
				
			||||||
	free(wlr_seat->keyboard_state.default_grab);
 | 
					 | 
				
			||||||
	free(wlr_seat->touch_state.default_grab);
 | 
					 | 
				
			||||||
	free(wlr_seat->data_device);
 | 
					 | 
				
			||||||
	free(wlr_seat->name);
 | 
					 | 
				
			||||||
	free(wlr_seat);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
 | 
					struct wlr_seat_client *wlr_seat_client_for_wl_client(struct wlr_seat *wlr_seat,
 | 
				
			||||||
		struct wl_client *wl_client) {
 | 
							struct wl_client *wl_client) {
 | 
				
			||||||
	assert(wlr_seat);
 | 
						assert(wlr_seat);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,6 +140,31 @@ static void server_decoration_manager_bind(struct wl_client *client, void *data,
 | 
				
			||||||
		manager->default_mode);
 | 
							manager->default_mode);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_server_decoration_manager_destroy(
 | 
				
			||||||
 | 
							struct wlr_server_decoration_manager *manager) {
 | 
				
			||||||
 | 
						if (manager == NULL) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&manager->display_destroy.link);
 | 
				
			||||||
 | 
						struct wlr_server_decoration *decoration, *tmp_decoration;
 | 
				
			||||||
 | 
						wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
 | 
				
			||||||
 | 
								link) {
 | 
				
			||||||
 | 
							server_decoration_destroy(decoration);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						struct wl_resource *resource, *tmp_resource;
 | 
				
			||||||
 | 
						wl_resource_for_each_safe(resource, tmp_resource, &manager->wl_resources) {
 | 
				
			||||||
 | 
							server_decoration_manager_destroy_resource(resource);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wl_global_destroy(manager->wl_global);
 | 
				
			||||||
 | 
						free(manager);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_server_decoration_manager *manager =
 | 
				
			||||||
 | 
							wl_container_of(listener, manager, display_destroy);
 | 
				
			||||||
 | 
						wlr_server_decoration_manager_destroy(manager);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
 | 
					struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
 | 
				
			||||||
		struct wl_display *display) {
 | 
							struct wl_display *display) {
 | 
				
			||||||
	struct wlr_server_decoration_manager *manager =
 | 
						struct wlr_server_decoration_manager *manager =
 | 
				
			||||||
| 
						 | 
					@ -158,23 +183,9 @@ struct wlr_server_decoration_manager *wlr_server_decoration_manager_create(
 | 
				
			||||||
	wl_list_init(&manager->wl_resources);
 | 
						wl_list_init(&manager->wl_resources);
 | 
				
			||||||
	wl_list_init(&manager->decorations);
 | 
						wl_list_init(&manager->decorations);
 | 
				
			||||||
	wl_signal_init(&manager->events.new_decoration);
 | 
						wl_signal_init(&manager->events.new_decoration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						manager->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &manager->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return manager;
 | 
						return manager;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void wlr_server_decoration_manager_destroy(
 | 
					 | 
				
			||||||
		struct wlr_server_decoration_manager *manager) {
 | 
					 | 
				
			||||||
	if (manager == NULL) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	struct wlr_server_decoration *decoration, *tmp_decoration;
 | 
					 | 
				
			||||||
	wl_list_for_each_safe(decoration, tmp_decoration, &manager->decorations,
 | 
					 | 
				
			||||||
			link) {
 | 
					 | 
				
			||||||
		server_decoration_destroy(decoration);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	struct wl_resource *resource, *tmp_resource;
 | 
					 | 
				
			||||||
	wl_resource_for_each_safe(resource, tmp_resource, &manager->wl_resources) {
 | 
					 | 
				
			||||||
		server_decoration_manager_destroy_resource(resource);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wl_global_destroy(manager->wl_global);
 | 
					 | 
				
			||||||
	free(manager);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -564,6 +564,12 @@ static void shell_bind(struct wl_client *wl_client, void *data,
 | 
				
			||||||
	wl_list_insert(&wl_shell->wl_resources, wl_resource_get_link(wl_resource));
 | 
						wl_list_insert(&wl_shell->wl_resources, wl_resource_get_link(wl_resource));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_wl_shell *wl_shell =
 | 
				
			||||||
 | 
							wl_container_of(listener, wl_shell, display_destroy);
 | 
				
			||||||
 | 
						wlr_wl_shell_destroy(wl_shell);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) {
 | 
					struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) {
 | 
				
			||||||
	struct wlr_wl_shell *wl_shell = calloc(1, sizeof(struct wlr_wl_shell));
 | 
						struct wlr_wl_shell *wl_shell = calloc(1, sizeof(struct wlr_wl_shell));
 | 
				
			||||||
	if (!wl_shell) {
 | 
						if (!wl_shell) {
 | 
				
			||||||
| 
						 | 
					@ -581,6 +587,10 @@ struct wlr_wl_shell *wlr_wl_shell_create(struct wl_display *display) {
 | 
				
			||||||
	wl_list_init(&wl_shell->surfaces);
 | 
						wl_list_init(&wl_shell->surfaces);
 | 
				
			||||||
	wl_list_init(&wl_shell->popup_grabs);
 | 
						wl_list_init(&wl_shell->popup_grabs);
 | 
				
			||||||
	wl_signal_init(&wl_shell->events.new_surface);
 | 
						wl_signal_init(&wl_shell->events.new_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_shell->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &wl_shell->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return wl_shell;
 | 
						return wl_shell;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -588,14 +598,14 @@ void wlr_wl_shell_destroy(struct wlr_wl_shell *wlr_wl_shell) {
 | 
				
			||||||
	if (!wlr_wl_shell) {
 | 
						if (!wlr_wl_shell) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wl_list_remove(&wlr_wl_shell->display_destroy.link);
 | 
				
			||||||
	struct wl_resource *resource = NULL, *temp = NULL;
 | 
						struct wl_resource *resource = NULL, *temp = NULL;
 | 
				
			||||||
	wl_resource_for_each_safe(resource, temp, &wlr_wl_shell->wl_resources) {
 | 
						wl_resource_for_each_safe(resource, temp, &wlr_wl_shell->wl_resources) {
 | 
				
			||||||
		struct wl_list *link = wl_resource_get_link(resource);
 | 
							// shell_destroy will remove the resource from the list
 | 
				
			||||||
		wl_list_remove(link);
 | 
							wl_resource_destroy(resource);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: destroy surfaces
 | 
						// TODO: destroy surfaces
 | 
				
			||||||
	// TODO: this segfault (wl_display->registry_resource_list is not init)
 | 
						wl_global_destroy(wlr_wl_shell->wl_global);
 | 
				
			||||||
	// wl_global_destroy(wlr_wl_shell->wl_global);
 | 
					 | 
				
			||||||
	free(wlr_wl_shell);
 | 
						free(wlr_wl_shell);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1250,6 +1250,12 @@ static void xdg_shell_bind(struct wl_client *wl_client, void *data,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_xdg_shell_v6 *xdg_shell =
 | 
				
			||||||
 | 
							wl_container_of(listener, xdg_shell, display_destroy);
 | 
				
			||||||
 | 
						wlr_xdg_shell_v6_destroy(xdg_shell);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
 | 
					struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
 | 
				
			||||||
	struct wlr_xdg_shell_v6 *xdg_shell =
 | 
						struct wlr_xdg_shell_v6 *xdg_shell =
 | 
				
			||||||
		calloc(1, sizeof(struct wlr_xdg_shell_v6));
 | 
							calloc(1, sizeof(struct wlr_xdg_shell_v6));
 | 
				
			||||||
| 
						 | 
					@ -1272,6 +1278,9 @@ struct wlr_xdg_shell_v6 *wlr_xdg_shell_v6_create(struct wl_display *display) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_signal_init(&xdg_shell->events.new_surface);
 | 
						wl_signal_init(&xdg_shell->events.new_surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xdg_shell->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(display, &xdg_shell->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return xdg_shell;
 | 
						return xdg_shell;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1279,8 +1288,8 @@ void wlr_xdg_shell_v6_destroy(struct wlr_xdg_shell_v6 *xdg_shell) {
 | 
				
			||||||
	if (!xdg_shell) {
 | 
						if (!xdg_shell) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: this segfault (wl_display->registry_resource_list is not init)
 | 
						wl_list_remove(&xdg_shell->display_destroy.link);
 | 
				
			||||||
	// wl_global_destroy(xdg_shell->wl_global);
 | 
						wl_global_destroy(xdg_shell->wl_global);
 | 
				
			||||||
	free(xdg_shell);
 | 
						free(xdg_shell);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,38 +125,25 @@ static void exec_xwayland(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
	execvp("Xwayland", argv);
 | 
						execvp("Xwayland", argv);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
 | 
					 | 
				
			||||||
	struct wl_display *wl_display, struct wlr_compositor *compositor);
 | 
					 | 
				
			||||||
static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void xwayland_destroy_event(struct wl_listener *listener, void *data) {
 | 
					 | 
				
			||||||
	struct wlr_xwayland *wlr_xwayland = wl_container_of(listener, wlr_xwayland, destroy_listener);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	/* don't call client destroy */
 | 
					 | 
				
			||||||
	wlr_xwayland->client = NULL;
 | 
					 | 
				
			||||||
	wl_list_remove(&wlr_xwayland->destroy_listener.link);
 | 
					 | 
				
			||||||
	wlr_xwayland_finish(wlr_xwayland);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (time(NULL) - wlr_xwayland->server_start > 5) {
 | 
					 | 
				
			||||||
		wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display,
 | 
					 | 
				
			||||||
			wlr_xwayland->compositor);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
 | 
					static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
	if (!wlr_xwayland || wlr_xwayland->display == -1) {
 | 
						if (!wlr_xwayland || wlr_xwayland->display == -1) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (wlr_xwayland->cursor != NULL) {
 | 
				
			||||||
 | 
							free(wlr_xwayland->cursor);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						xwm_destroy(wlr_xwayland->xwm);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (wlr_xwayland->client) {
 | 
						if (wlr_xwayland->client) {
 | 
				
			||||||
		wl_list_remove(&wlr_xwayland->destroy_listener.link);
 | 
							wl_list_remove(&wlr_xwayland->client_destroy.link);
 | 
				
			||||||
		wl_client_destroy(wlr_xwayland->client);
 | 
							wl_client_destroy(wlr_xwayland->client);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (wlr_xwayland->sigusr1_source) {
 | 
						if (wlr_xwayland->sigusr1_source) {
 | 
				
			||||||
		wl_event_source_remove(wlr_xwayland->sigusr1_source);
 | 
							wl_event_source_remove(wlr_xwayland->sigusr1_source);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xwm_destroy(wlr_xwayland->xwm);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	safe_close(wlr_xwayland->x_fd[0]);
 | 
						safe_close(wlr_xwayland->x_fd[0]);
 | 
				
			||||||
	safe_close(wlr_xwayland->x_fd[1]);
 | 
						safe_close(wlr_xwayland->x_fd[1]);
 | 
				
			||||||
	safe_close(wlr_xwayland->wl_fd[0]);
 | 
						safe_close(wlr_xwayland->wl_fd[0]);
 | 
				
			||||||
| 
						 | 
					@ -164,6 +151,8 @@ static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
	safe_close(wlr_xwayland->wm_fd[0]);
 | 
						safe_close(wlr_xwayland->wm_fd[0]);
 | 
				
			||||||
	safe_close(wlr_xwayland->wm_fd[1]);
 | 
						safe_close(wlr_xwayland->wm_fd[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wl_list_remove(&wlr_xwayland->display_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unlink_display_sockets(wlr_xwayland->display);
 | 
						unlink_display_sockets(wlr_xwayland->display);
 | 
				
			||||||
	wlr_xwayland->display = -1;
 | 
						wlr_xwayland->display = -1;
 | 
				
			||||||
	unsetenv("DISPLAY");
 | 
						unsetenv("DISPLAY");
 | 
				
			||||||
| 
						 | 
					@ -173,6 +162,39 @@ static void wlr_xwayland_finish(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
						struct wl_display *wl_display, struct wlr_compositor *compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_client_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_xwayland *wlr_xwayland =
 | 
				
			||||||
 | 
							wl_container_of(listener, wlr_xwayland, client_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Don't call client destroy: it's being destroyed already
 | 
				
			||||||
 | 
						wlr_xwayland->client = NULL;
 | 
				
			||||||
 | 
						wl_list_remove(&wlr_xwayland->client_destroy.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_xwayland_finish(wlr_xwayland);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (time(NULL) - wlr_xwayland->server_start > 5) {
 | 
				
			||||||
 | 
							wlr_log(L_INFO, "Restarting Xwayland");
 | 
				
			||||||
 | 
							wlr_xwayland_init(wlr_xwayland, wlr_xwayland->wl_display,
 | 
				
			||||||
 | 
								wlr_xwayland->compositor);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_display_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
						struct wlr_xwayland *wlr_xwayland =
 | 
				
			||||||
 | 
							wl_container_of(listener, wlr_xwayland, display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Don't call client destroy: the display is being destroyed, it's too late
 | 
				
			||||||
 | 
						if (wlr_xwayland->client) {
 | 
				
			||||||
 | 
							wlr_xwayland->client = NULL;
 | 
				
			||||||
 | 
							wl_list_remove(&wlr_xwayland->client_destroy.link);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_xwayland_destroy(wlr_xwayland);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int xserver_handle_ready(int signal_number, void *data) {
 | 
					static int xserver_handle_ready(int signal_number, void *data) {
 | 
				
			||||||
	struct wlr_xwayland *wlr_xwayland = data;
 | 
						struct wlr_xwayland *wlr_xwayland = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -227,6 +249,9 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
	wl_signal_init(&wlr_xwayland->events.new_surface);
 | 
						wl_signal_init(&wlr_xwayland->events.new_surface);
 | 
				
			||||||
	wl_signal_init(&wlr_xwayland->events.ready);
 | 
						wl_signal_init(&wlr_xwayland->events.ready);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_xwayland->display_destroy.notify = handle_display_destroy;
 | 
				
			||||||
 | 
						wl_display_add_destroy_listener(wl_display, &wlr_xwayland->display_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_xwayland->display = open_display_sockets(wlr_xwayland->x_fd);
 | 
						wlr_xwayland->display = open_display_sockets(wlr_xwayland->x_fd);
 | 
				
			||||||
	if (wlr_xwayland->display < 0) {
 | 
						if (wlr_xwayland->display < 0) {
 | 
				
			||||||
		wlr_xwayland_finish(wlr_xwayland);
 | 
							wlr_xwayland_finish(wlr_xwayland);
 | 
				
			||||||
| 
						 | 
					@ -252,11 +277,13 @@ static bool wlr_xwayland_init(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */
 | 
						wlr_xwayland->wl_fd[0] = -1; /* not ours anymore */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wlr_xwayland->destroy_listener.notify = xwayland_destroy_event;
 | 
						wlr_xwayland->client_destroy.notify = handle_client_destroy;
 | 
				
			||||||
	wl_client_add_destroy_listener(wlr_xwayland->client, &wlr_xwayland->destroy_listener);
 | 
						wl_client_add_destroy_listener(wlr_xwayland->client,
 | 
				
			||||||
 | 
							&wlr_xwayland->client_destroy);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_event_loop *loop = wl_display_get_event_loop(wl_display);
 | 
						struct wl_event_loop *loop = wl_display_get_event_loop(wl_display);
 | 
				
			||||||
	wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1, xserver_handle_ready, wlr_xwayland);
 | 
						wlr_xwayland->sigusr1_source = wl_event_loop_add_signal(loop, SIGUSR1,
 | 
				
			||||||
 | 
							xserver_handle_ready, wlr_xwayland);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((wlr_xwayland->pid = fork()) == 0) {
 | 
						if ((wlr_xwayland->pid = fork()) == 0) {
 | 
				
			||||||
		/* Double-fork, but we need to forward SIGUSR1 once Xserver(1)
 | 
							/* Double-fork, but we need to forward SIGUSR1 once Xserver(1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1081,6 +1081,12 @@ void xwm_destroy(struct wlr_xwm *xwm) {
 | 
				
			||||||
	if (xwm->cursor) {
 | 
						if (xwm->cursor) {
 | 
				
			||||||
		xcb_free_cursor(xwm->xcb_conn, xwm->cursor);
 | 
							xcb_free_cursor(xwm->xcb_conn, xwm->cursor);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if (xwm->colormap) {
 | 
				
			||||||
 | 
							xcb_free_colormap(xwm->xcb_conn, xwm->colormap);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (xwm->window) {
 | 
				
			||||||
 | 
							xcb_destroy_window(xwm->xcb_conn, xwm->window);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (xwm->event_source) {
 | 
						if (xwm->event_source) {
 | 
				
			||||||
		wl_event_source_remove(xwm->event_source);
 | 
							wl_event_source_remove(xwm->event_source);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1088,6 +1094,9 @@ void xwm_destroy(struct wlr_xwm *xwm) {
 | 
				
			||||||
	wl_list_for_each_safe(xsurface, tmp, &xwm->surfaces, link) {
 | 
						wl_list_for_each_safe(xsurface, tmp, &xwm->surfaces, link) {
 | 
				
			||||||
		wlr_xwayland_surface_destroy(xsurface);
 | 
							wlr_xwayland_surface_destroy(xsurface);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						wl_list_for_each_safe(xsurface, tmp, &xwm->unpaired_surfaces, link) {
 | 
				
			||||||
 | 
							wlr_xwayland_surface_destroy(xsurface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	wl_list_remove(&xwm->compositor_surface_create.link);
 | 
						wl_list_remove(&xwm->compositor_surface_create.link);
 | 
				
			||||||
	xcb_disconnect(xwm->xcb_conn);
 | 
						xcb_disconnect(xwm->xcb_conn);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue