mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Add wlr_xwayland_surface_ping
This commit is contained in:
		
							parent
							
								
									cedd151e17
								
							
						
					
					
						commit
						17d0440b75
					
				
					 4 changed files with 102 additions and 27 deletions
				
			
		| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					@ -190,4 +194,6 @@ 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,24 +1259,15 @@ 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) {
 | 
				
			||||||
	if (!xwm) {
 | 
						if (!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…
	
	Add table
		Add a link
		
	
		Reference in a new issue