Add wlr_xwayland_surface_ping
This commit is contained in:
		
							parent
							
								
									cedd151e17
								
							
						
					
					
						commit
						17d0440b75
					
				|  | @ -111,6 +111,9 @@ struct wlr_xwayland_surface { | ||||||
| 	uint32_t hints_urgency; | 	uint32_t hints_urgency; | ||||||
| 	struct wlr_xwayland_surface_size_hints *size_hints; | 	struct wlr_xwayland_surface_size_hints *size_hints; | ||||||
| 
 | 
 | ||||||
|  | 	bool pinging; | ||||||
|  | 	struct wl_event_source *ping_timer; | ||||||
|  | 
 | ||||||
| 	// _NET_WM_STATE
 | 	// _NET_WM_STATE
 | ||||||
| 	bool fullscreen; | 	bool fullscreen; | ||||||
| 	bool maximized_vert; | 	bool maximized_vert; | ||||||
|  | @ -133,6 +136,7 @@ struct wlr_xwayland_surface { | ||||||
| 		struct wl_signal set_parent; | 		struct wl_signal set_parent; | ||||||
| 		struct wl_signal set_pid; | 		struct wl_signal set_pid; | ||||||
| 		struct wl_signal set_window_type; | 		struct wl_signal set_window_type; | ||||||
|  | 		struct wl_signal ping_timeout; | ||||||
| 	} events; | 	} events; | ||||||
| 
 | 
 | ||||||
| 	struct wl_listener surface_destroy; | 	struct wl_listener surface_destroy; | ||||||
|  | @ -188,6 +192,8 @@ bool wlr_xwayland_surface_is_unmanaged( | ||||||
| bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface); | bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface); | ||||||
| 
 | 
 | ||||||
| struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( | struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( | ||||||
| 		struct wlr_surface *surface); | 	struct wlr_surface *surface); | ||||||
|  | 
 | ||||||
|  | void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface); | ||||||
| 
 | 
 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ enum atom_name { | ||||||
| 	_NET_WM_STATE_FULLSCREEN, | 	_NET_WM_STATE_FULLSCREEN, | ||||||
| 	_NET_WM_STATE_MAXIMIZED_VERT, | 	_NET_WM_STATE_MAXIMIZED_VERT, | ||||||
| 	_NET_WM_STATE_MAXIMIZED_HORZ, | 	_NET_WM_STATE_MAXIMIZED_HORZ, | ||||||
|  | 	_NET_WM_PING, | ||||||
| 	WM_STATE, | 	WM_STATE, | ||||||
| 	CLIPBOARD, | 	CLIPBOARD, | ||||||
| 	PRIMARY, | 	PRIMARY, | ||||||
|  | @ -90,6 +91,7 @@ struct wlr_xwm { | ||||||
| 	struct wlr_xwayland *xwayland; | 	struct wlr_xwayland *xwayland; | ||||||
| 	struct wl_event_source *event_source; | 	struct wl_event_source *event_source; | ||||||
| 	struct wlr_seat *seat; | 	struct wlr_seat *seat; | ||||||
|  | 	uint32_t ping_timeout; | ||||||
| 
 | 
 | ||||||
| 	xcb_atom_t atoms[ATOM_LAST]; | 	xcb_atom_t atoms[ATOM_LAST]; | ||||||
| 	xcb_connection_t *xcb_conn; | 	xcb_connection_t *xcb_conn; | ||||||
|  |  | ||||||
|  | @ -260,6 +260,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) { | ||||||
| 	struct wlr_xwayland_surface *surface = data; | 	struct wlr_xwayland_surface *surface = data; | ||||||
| 	wlr_log(L_DEBUG, "new xwayland surface: title=%s, class=%s, instance=%s", | 	wlr_log(L_DEBUG, "new xwayland surface: title=%s, class=%s, instance=%s", | ||||||
| 		surface->title, surface->class, surface->instance); | 		surface->title, surface->class, surface->instance); | ||||||
|  | 	wlr_xwayland_surface_ping(surface); | ||||||
| 
 | 
 | ||||||
| 	struct roots_xwayland_surface *roots_surface = | 	struct roots_xwayland_surface *roots_surface = | ||||||
| 		calloc(1, sizeof(struct roots_xwayland_surface)); | 		calloc(1, sizeof(struct roots_xwayland_surface)); | ||||||
|  |  | ||||||
							
								
								
									
										118
									
								
								xwayland/xwm.c
								
								
								
								
							
							
						
						
									
										118
									
								
								xwayland/xwm.c
								
								
								
								
							|  | @ -42,6 +42,7 @@ const char *atom_map[ATOM_LAST] = { | ||||||
| 	"_NET_WM_STATE_FULLSCREEN", | 	"_NET_WM_STATE_FULLSCREEN", | ||||||
| 	"_NET_WM_STATE_MAXIMIZED_VERT", | 	"_NET_WM_STATE_MAXIMIZED_VERT", | ||||||
| 	"_NET_WM_STATE_MAXIMIZED_HORZ", | 	"_NET_WM_STATE_MAXIMIZED_HORZ", | ||||||
|  | 	"_NET_WM_PING", | ||||||
| 	"WM_STATE", | 	"WM_STATE", | ||||||
| 	"CLIPBOARD", | 	"CLIPBOARD", | ||||||
| 	"PRIMARY", | 	"PRIMARY", | ||||||
|  | @ -100,6 +101,14 @@ static struct wlr_xwayland_surface *lookup_surface(struct wlr_xwm *xwm, | ||||||
| 	return NULL; | 	return NULL; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int xwayland_surface_handle_ping_timeout(void *data) { | ||||||
|  | 	struct wlr_xwayland_surface *surface = data; | ||||||
|  | 
 | ||||||
|  | 	wlr_signal_emit_safe(&surface->events.ping_timeout, surface); | ||||||
|  | 	surface->pinging = false; | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static struct wlr_xwayland_surface *wlr_xwayland_surface_create( | static struct wlr_xwayland_surface *wlr_xwayland_surface_create( | ||||||
| 		struct wlr_xwm *xwm, xcb_window_t window_id, int16_t x, int16_t y, | 		struct wlr_xwm *xwm, xcb_window_t window_id, int16_t x, int16_t y, | ||||||
| 		uint16_t width, uint16_t height, bool override_redirect) { | 		uint16_t width, uint16_t height, bool override_redirect) { | ||||||
|  | @ -143,16 +152,25 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create( | ||||||
| 	wl_signal_init(&surface->events.set_parent); | 	wl_signal_init(&surface->events.set_parent); | ||||||
| 	wl_signal_init(&surface->events.set_pid); | 	wl_signal_init(&surface->events.set_pid); | ||||||
| 	wl_signal_init(&surface->events.set_window_type); | 	wl_signal_init(&surface->events.set_window_type); | ||||||
|  | 	wl_signal_init(&surface->events.ping_timeout); | ||||||
| 
 | 
 | ||||||
| 	xcb_get_geometry_reply_t *geometry_reply = | 	xcb_get_geometry_reply_t *geometry_reply = | ||||||
| 		xcb_get_geometry_reply(xwm->xcb_conn, geometry_cookie, NULL); | 		xcb_get_geometry_reply(xwm->xcb_conn, geometry_cookie, NULL); | ||||||
| 
 |  | ||||||
| 	if (geometry_reply != NULL) { | 	if (geometry_reply != NULL) { | ||||||
| 		surface->has_alpha = geometry_reply->depth == 32; | 		surface->has_alpha = geometry_reply->depth == 32; | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	free(geometry_reply); | 	free(geometry_reply); | ||||||
| 
 | 
 | ||||||
|  | 	struct wl_display *display = xwm->xwayland->wl_display; | ||||||
|  | 	struct wl_event_loop *loop = wl_display_get_event_loop(display); | ||||||
|  | 	surface->ping_timer = wl_event_loop_add_timer(loop, | ||||||
|  | 		xwayland_surface_handle_ping_timeout, surface); | ||||||
|  | 	if (surface->ping_timer == NULL) { | ||||||
|  | 		free(surface); | ||||||
|  | 		wlr_log(L_ERROR, "Could not add timer to event loop"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	return surface; | 	return surface; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -163,6 +181,27 @@ static void xwm_set_net_active_window(struct wlr_xwm *xwm, | ||||||
| 			xwm->atoms[WINDOW], 32, 1, &window); | 			xwm->atoms[WINDOW], 32, 1, &window); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void xwm_send_wm_message(struct wlr_xwayland_surface *surface, | ||||||
|  | 		xcb_client_message_data_t *data) { | ||||||
|  | 	struct wlr_xwm *xwm = surface->xwm; | ||||||
|  | 
 | ||||||
|  | 	xcb_client_message_event_t event = { | ||||||
|  | 		.response_type = XCB_CLIENT_MESSAGE, | ||||||
|  | 		.format = 32, | ||||||
|  | 		.sequence = 0, | ||||||
|  | 		.window = surface->window_id, | ||||||
|  | 		.type = xwm->atoms[WM_PROTOCOLS], | ||||||
|  | 		.data = *data, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	xcb_send_event(xwm->xcb_conn, | ||||||
|  | 		0, // propagate
 | ||||||
|  | 		surface->window_id, | ||||||
|  | 		XCB_EVENT_MASK_NO_EVENT, | ||||||
|  | 		(const char *)&event); | ||||||
|  | 	xcb_flush(xwm->xcb_conn); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void xwm_send_focus_window(struct wlr_xwm *xwm, | static void xwm_send_focus_window(struct wlr_xwm *xwm, | ||||||
| 		struct wlr_xwayland_surface *xsurface) { | 		struct wlr_xwayland_surface *xsurface) { | ||||||
| 	if (!xsurface) { | 	if (!xsurface) { | ||||||
|  | @ -174,16 +213,10 @@ static void xwm_send_focus_window(struct wlr_xwm *xwm, | ||||||
| 		return; | 		return; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	xcb_client_message_event_t client_message; | 	xcb_client_message_data_t message_data = { 0 }; | ||||||
| 	client_message.response_type = XCB_CLIENT_MESSAGE; | 	message_data.data32[0] = xwm->atoms[WM_TAKE_FOCUS]; | ||||||
| 	client_message.format = 32; | 	message_data.data32[1] = XCB_TIME_CURRENT_TIME; | ||||||
| 	client_message.window = xsurface->window_id; | 	xwm_send_wm_message(xsurface, &message_data); | ||||||
| 	client_message.type = xwm->atoms[WM_PROTOCOLS]; |  | ||||||
| 	client_message.data.data32[0] = xwm->atoms[WM_TAKE_FOCUS]; |  | ||||||
| 	client_message.data.data32[1] = XCB_TIME_CURRENT_TIME; |  | ||||||
| 
 |  | ||||||
| 	xcb_send_event(xwm->xcb_conn, 0, xsurface->window_id, |  | ||||||
| 		XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (char*)&client_message); |  | ||||||
| 
 | 
 | ||||||
| 	xcb_set_input_focus(xwm->xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT, | 	xcb_set_input_focus(xwm->xcb_conn, XCB_INPUT_FOCUS_POINTER_ROOT, | ||||||
| 		xsurface->window_id, XCB_CURRENT_TIME); | 		xsurface->window_id, XCB_CURRENT_TIME); | ||||||
|  | @ -968,6 +1001,32 @@ static void xwm_handle_net_wm_state_message(struct wlr_xwm *xwm, | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void xwm_handle_wm_protocols_message(struct wlr_xwm *xwm, | ||||||
|  | 		xcb_client_message_event_t *ev) { | ||||||
|  | 	xcb_atom_t type = ev->data.data32[0]; | ||||||
|  | 
 | ||||||
|  | 	if (type == xwm->atoms[_NET_WM_PING]) { | ||||||
|  | 		xcb_window_t window_id = ev->data.data32[2]; | ||||||
|  | 
 | ||||||
|  | 		struct wlr_xwayland_surface *surface = lookup_surface(xwm, window_id); | ||||||
|  | 		if (surface == NULL) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (!surface->pinging) { | ||||||
|  | 			return; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		wl_event_source_timer_update(surface->ping_timer, 0); | ||||||
|  | 		surface->pinging = false; | ||||||
|  | 	} else { | ||||||
|  | 		char *type_name = xwm_get_atom_name(xwm, type); | ||||||
|  | 		wlr_log(L_DEBUG, "unhandled WM_PROTOCOLS client message %u (%s)", | ||||||
|  | 			type, type_name); | ||||||
|  | 		free(type_name); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void xwm_handle_client_message(struct wlr_xwm *xwm, | static void xwm_handle_client_message(struct wlr_xwm *xwm, | ||||||
| 		xcb_client_message_event_t *ev) { | 		xcb_client_message_event_t *ev) { | ||||||
| 	wlr_log(L_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window); | 	wlr_log(L_DEBUG, "XCB_CLIENT_MESSAGE (%u)", ev->window); | ||||||
|  | @ -978,6 +1037,8 @@ static void xwm_handle_client_message(struct wlr_xwm *xwm, | ||||||
| 		xwm_handle_net_wm_state_message(xwm, ev); | 		xwm_handle_net_wm_state_message(xwm, ev); | ||||||
| 	} else if (ev->type == xwm->atoms[_NET_WM_MOVERESIZE]) { | 	} else if (ev->type == xwm->atoms[_NET_WM_MOVERESIZE]) { | ||||||
| 		xwm_handle_net_wm_moveresize_message(xwm, ev); | 		xwm_handle_net_wm_moveresize_message(xwm, ev); | ||||||
|  | 	} else if (ev->type == xwm->atoms[WM_PROTOCOLS]) { | ||||||
|  | 		xwm_handle_wm_protocols_message(xwm, ev); | ||||||
| 	} else if (!xwm_handle_selection_client_message(xwm, ev)) { | 	} else if (!xwm_handle_selection_client_message(xwm, ev)) { | ||||||
| 		char *type_name = xwm_get_atom_name(xwm, ev->type); | 		char *type_name = xwm_get_atom_name(xwm, ev->type); | ||||||
| 		wlr_log(L_DEBUG, "unhandled x11 client message %u (%s)", ev->type, | 		wlr_log(L_DEBUG, "unhandled x11 client message %u (%s)", ev->type, | ||||||
|  | @ -1198,23 +1259,14 @@ void wlr_xwayland_surface_close(struct wlr_xwayland_surface *xsurface) { | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (supports_delete) { | 	if (supports_delete) { | ||||||
| 		xcb_client_message_event_t ev = {0}; | 		xcb_client_message_data_t message_data = {0}; | ||||||
| 		ev.response_type = XCB_CLIENT_MESSAGE; | 		message_data.data32[0] = xwm->atoms[WM_DELETE_WINDOW]; | ||||||
| 		ev.window = xsurface->window_id; | 		message_data.data32[1] = XCB_CURRENT_TIME; | ||||||
| 		ev.format = 32; | 		xwm_send_wm_message(xsurface, &message_data); | ||||||
| 		ev.sequence = 0; |  | ||||||
| 		ev.type = xwm->atoms[WM_PROTOCOLS]; |  | ||||||
| 		ev.data.data32[0] = xwm->atoms[WM_DELETE_WINDOW]; |  | ||||||
| 		ev.data.data32[1] = XCB_CURRENT_TIME; |  | ||||||
| 		xcb_send_event(xwm->xcb_conn, 0, |  | ||||||
| 			xsurface->window_id, |  | ||||||
| 			XCB_EVENT_MASK_NO_EVENT, |  | ||||||
| 			(char *)&ev); |  | ||||||
| 	} else { | 	} else { | ||||||
| 		xcb_kill_client(xwm->xcb_conn, xsurface->window_id); | 		xcb_kill_client(xwm->xcb_conn, xsurface->window_id); | ||||||
|  | 		xcb_flush(xwm->xcb_conn); | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	xcb_flush(xwm->xcb_conn); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void xwm_destroy(struct wlr_xwm *xwm) { | void xwm_destroy(struct wlr_xwm *xwm) { | ||||||
|  | @ -1463,6 +1515,7 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) { | ||||||
| 	xwm->xwayland = wlr_xwayland; | 	xwm->xwayland = wlr_xwayland; | ||||||
| 	wl_list_init(&xwm->surfaces); | 	wl_list_init(&xwm->surfaces); | ||||||
| 	wl_list_init(&xwm->unpaired_surfaces); | 	wl_list_init(&xwm->unpaired_surfaces); | ||||||
|  | 	xwm->ping_timeout = 10000; | ||||||
| 
 | 
 | ||||||
| 	xwm->xcb_conn = xcb_connect_to_fd(wlr_xwayland->wm_fd[0], NULL); | 	xwm->xcb_conn = xcb_connect_to_fd(wlr_xwayland->wm_fd[0], NULL); | ||||||
| 
 | 
 | ||||||
|  | @ -1599,3 +1652,16 @@ bool wlr_xwayland_surface_is_unmanaged( | ||||||
| 
 | 
 | ||||||
| 	return false; | 	return false; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { | ||||||
|  | 	xcb_client_message_data_t data = { 0 }; | ||||||
|  | 	data.data32[0] = surface->xwm->atoms[_NET_WM_PING]; | ||||||
|  | 	data.data32[1] = XCB_CURRENT_TIME; | ||||||
|  | 	data.data32[2] = surface->window_id; | ||||||
|  | 
 | ||||||
|  | 	xwm_send_wm_message(surface, &data); | ||||||
|  | 
 | ||||||
|  | 	wl_event_source_timer_update(surface->ping_timer, | ||||||
|  | 		surface->xwm->ping_timeout); | ||||||
|  | 	surface->pinging = true; | ||||||
|  | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue