mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	xwm: net wm state
This commit is contained in:
		
							parent
							
								
									6a4290b86a
								
							
						
					
					
						commit
						be297d9d14
					
				
					 2 changed files with 129 additions and 6 deletions
				
			
		| 
						 | 
					@ -74,6 +74,7 @@ struct wlr_xwayland_surface {
 | 
				
			||||||
	struct wlr_surface *surface;
 | 
						struct wlr_surface *surface;
 | 
				
			||||||
	int16_t x, y;
 | 
						int16_t x, y;
 | 
				
			||||||
	uint16_t width, height;
 | 
						uint16_t width, height;
 | 
				
			||||||
 | 
						uint16_t saved_width, saved_height;
 | 
				
			||||||
	bool override_redirect;
 | 
						bool override_redirect;
 | 
				
			||||||
	bool mapped;
 | 
						bool mapped;
 | 
				
			||||||
	bool added;
 | 
						bool added;
 | 
				
			||||||
| 
						 | 
					@ -106,12 +107,14 @@ struct wlr_xwayland_surface {
 | 
				
			||||||
		struct wl_signal request_configure;
 | 
							struct wl_signal request_configure;
 | 
				
			||||||
		struct wl_signal request_move;
 | 
							struct wl_signal request_move;
 | 
				
			||||||
		struct wl_signal request_resize;
 | 
							struct wl_signal request_resize;
 | 
				
			||||||
 | 
							struct wl_signal request_maximize;
 | 
				
			||||||
 | 
							struct wl_signal request_fullscreen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		struct wl_signal map_notify;
 | 
							struct wl_signal map_notify;
 | 
				
			||||||
		struct wl_signal unmap_notify;
 | 
							struct wl_signal unmap_notify;
 | 
				
			||||||
		struct wl_signal set_title;
 | 
							struct wl_signal set_title;
 | 
				
			||||||
		struct wl_signal set_class;
 | 
							struct wl_signal set_class;
 | 
				
			||||||
		struct wl_signal set_parent;
 | 
							struct wl_signal set_parent;
 | 
				
			||||||
		struct wl_signal set_state;
 | 
					 | 
				
			||||||
		struct wl_signal set_pid;
 | 
							struct wl_signal set_pid;
 | 
				
			||||||
		struct wl_signal set_window_type;
 | 
							struct wl_signal set_window_type;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					@ -138,15 +141,25 @@ struct wlr_xwayland_resize_event {
 | 
				
			||||||
	uint32_t edges;
 | 
						uint32_t edges;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland);
 | 
					 | 
				
			||||||
struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
 | 
					struct wlr_xwayland *wlr_xwayland_create(struct wl_display *wl_display,
 | 
				
			||||||
	struct wlr_compositor *compositor);
 | 
						struct wlr_compositor *compositor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_xwayland_destroy(struct wlr_xwayland *wlr_xwayland);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland,
 | 
					void wlr_xwayland_surface_activate(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
	struct wlr_xwayland_surface *surface, bool activated);
 | 
						struct wlr_xwayland_surface *surface, bool activated);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland,
 | 
					void wlr_xwayland_surface_configure(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
	struct wlr_xwayland_surface *surface, int16_t x, int16_t y,
 | 
						struct wlr_xwayland_surface *surface, int16_t x, int16_t y,
 | 
				
			||||||
	uint16_t width, uint16_t height);
 | 
						uint16_t width, uint16_t height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void wlr_xwayland_surface_close(struct wlr_xwayland *wlr_xwayland,
 | 
					void wlr_xwayland_surface_close(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
	struct wlr_xwayland_surface *surface);
 | 
						struct wlr_xwayland_surface *surface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_xwayland_surface_set_maximized(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
						struct wlr_xwayland_surface *surface, bool maximized);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
						struct wlr_xwayland_surface *surface, bool fullscreen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										118
									
								
								xwayland/xwm.c
									
										
									
									
									
								
							
							
						
						
									
										118
									
								
								xwayland/xwm.c
									
										
									
									
									
								
							| 
						 | 
					@ -79,17 +79,17 @@ static struct wlr_xwayland_surface *wlr_xwayland_surface_create(
 | 
				
			||||||
	surface->height = height;
 | 
						surface->height = height;
 | 
				
			||||||
	surface->override_redirect = override_redirect;
 | 
						surface->override_redirect = override_redirect;
 | 
				
			||||||
	wl_list_insert(&xwm->surfaces, &surface->link);
 | 
						wl_list_insert(&xwm->surfaces, &surface->link);
 | 
				
			||||||
	surface->state = wlr_list_create();
 | 
					 | 
				
			||||||
	wl_signal_init(&surface->events.destroy);
 | 
						wl_signal_init(&surface->events.destroy);
 | 
				
			||||||
	wl_signal_init(&surface->events.request_configure);
 | 
						wl_signal_init(&surface->events.request_configure);
 | 
				
			||||||
	wl_signal_init(&surface->events.request_move);
 | 
						wl_signal_init(&surface->events.request_move);
 | 
				
			||||||
	wl_signal_init(&surface->events.request_resize);
 | 
						wl_signal_init(&surface->events.request_resize);
 | 
				
			||||||
 | 
						wl_signal_init(&surface->events.request_maximize);
 | 
				
			||||||
 | 
						wl_signal_init(&surface->events.request_fullscreen);
 | 
				
			||||||
	wl_signal_init(&surface->events.map_notify);
 | 
						wl_signal_init(&surface->events.map_notify);
 | 
				
			||||||
	wl_signal_init(&surface->events.unmap_notify);
 | 
						wl_signal_init(&surface->events.unmap_notify);
 | 
				
			||||||
	wl_signal_init(&surface->events.set_class);
 | 
						wl_signal_init(&surface->events.set_class);
 | 
				
			||||||
	wl_signal_init(&surface->events.set_title);
 | 
						wl_signal_init(&surface->events.set_title);
 | 
				
			||||||
	wl_signal_init(&surface->events.set_parent);
 | 
						wl_signal_init(&surface->events.set_parent);
 | 
				
			||||||
	wl_signal_init(&surface->events.set_state);
 | 
					 | 
				
			||||||
	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);
 | 
				
			||||||
	return surface;
 | 
						return surface;
 | 
				
			||||||
| 
						 | 
					@ -447,6 +447,21 @@ static void read_surface_motif_hints(struct wlr_xwm *xwm,
 | 
				
			||||||
	wlr_log(L_DEBUG, "MOTIF_WM_HINTS (%d)", reply->value_len);
 | 
						wlr_log(L_DEBUG, "MOTIF_WM_HINTS (%d)", reply->value_len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void read_surface_net_wm_state(struct wlr_xwm *xwm,
 | 
				
			||||||
 | 
							struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) {
 | 
				
			||||||
 | 
						xsurface->fullscreen = 0;
 | 
				
			||||||
 | 
						xcb_atom_t *atom = xcb_get_property_value(reply);
 | 
				
			||||||
 | 
						atom = xcb_get_property_value(reply);
 | 
				
			||||||
 | 
						for (uint32_t i = 0; i < reply->value_len; i++) {
 | 
				
			||||||
 | 
							if (atom[i] == xwm->atoms[_NET_WM_STATE_FULLSCREEN])
 | 
				
			||||||
 | 
								xsurface->fullscreen = true;
 | 
				
			||||||
 | 
							if (atom[i] == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT])
 | 
				
			||||||
 | 
								xsurface->maximized_vert = true;
 | 
				
			||||||
 | 
							if (atom[i] == xwm->atoms[_NET_WM_STATE_MAXIMIZED_HORZ])
 | 
				
			||||||
 | 
								xsurface->maximized_horz = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void read_surface_property(struct wlr_xwm *xwm,
 | 
					static void read_surface_property(struct wlr_xwm *xwm,
 | 
				
			||||||
		struct wlr_xwayland_surface *surface, xcb_atom_t property) {
 | 
							struct wlr_xwayland_surface *surface, xcb_atom_t property) {
 | 
				
			||||||
	xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0,
 | 
						xcb_get_property_cookie_t cookie = xcb_get_property(xwm->xcb_conn, 0,
 | 
				
			||||||
| 
						 | 
					@ -471,7 +486,7 @@ static void read_surface_property(struct wlr_xwm *xwm,
 | 
				
			||||||
	} else if (property == xwm->atoms[WM_PROTOCOLS]) {
 | 
						} else if (property == xwm->atoms[WM_PROTOCOLS]) {
 | 
				
			||||||
		read_surface_protocols(xwm, surface, reply);
 | 
							read_surface_protocols(xwm, surface, reply);
 | 
				
			||||||
	} else if (property == xwm->atoms[NET_WM_STATE]) {
 | 
						} else if (property == xwm->atoms[NET_WM_STATE]) {
 | 
				
			||||||
		wlr_log(L_DEBUG, "TODO: read _NET_WM_STATE property");
 | 
							read_surface_net_wm_state(xwm, surface, reply);
 | 
				
			||||||
	} else if (property == xwm->atoms[WM_HINTS]) {
 | 
						} else if (property == xwm->atoms[WM_HINTS]) {
 | 
				
			||||||
		read_surface_hints(xwm, surface, reply);
 | 
							read_surface_hints(xwm, surface, reply);
 | 
				
			||||||
	} else if (property == xwm->atoms[WM_NORMAL_HINTS]) {
 | 
						} else if (property == xwm->atoms[WM_NORMAL_HINTS]) {
 | 
				
			||||||
| 
						 | 
					@ -762,6 +777,81 @@ static void handle_net_wm_moveresize_message(struct wlr_xwm *xwm,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define _NET_WM_STATE_REMOVE	0
 | 
				
			||||||
 | 
					#define _NET_WM_STATE_ADD	1
 | 
				
			||||||
 | 
					#define _NET_WM_STATE_TOGGLE	2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool update_state(int action, bool *state) {
 | 
				
			||||||
 | 
						int new_state, changed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (action) {
 | 
				
			||||||
 | 
							case _NET_WM_STATE_REMOVE:
 | 
				
			||||||
 | 
								new_state = false;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case _NET_WM_STATE_ADD:
 | 
				
			||||||
 | 
								new_state = true;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case _NET_WM_STATE_TOGGLE:
 | 
				
			||||||
 | 
								new_state = !*state;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						changed = (*state != new_state);
 | 
				
			||||||
 | 
						*state = new_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return changed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline bool xsurface_is_maximized(struct wlr_xwayland_surface *xsurface) {
 | 
				
			||||||
 | 
						return xsurface->maximized_horz && xsurface->maximized_vert;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void handle_net_wm_state_message(struct wlr_xwm *xwm,
 | 
				
			||||||
 | 
							xcb_client_message_event_t *client_message) {
 | 
				
			||||||
 | 
						struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, client_message->window);
 | 
				
			||||||
 | 
						if (!xsurface) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int maximized = xsurface_is_maximized(xsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						uint32_t action = client_message->data.data32[0];
 | 
				
			||||||
 | 
						uint32_t property = client_message->data.data32[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (property == xwm->atoms[_NET_WM_STATE_FULLSCREEN] &&
 | 
				
			||||||
 | 
								update_state(action, &xsurface->fullscreen)) {
 | 
				
			||||||
 | 
							xsurface_set_net_wm_state(xsurface);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (xsurface->fullscreen) {
 | 
				
			||||||
 | 
								xsurface->saved_width = xsurface->width;
 | 
				
			||||||
 | 
								xsurface->saved_height = xsurface->height;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							wl_signal_emit(&xsurface->events.request_fullscreen, xsurface);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (property == xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT] &&
 | 
				
			||||||
 | 
									update_state(action, &xsurface->maximized_vert)) {
 | 
				
			||||||
 | 
								xsurface_set_net_wm_state(xsurface);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (property == xwm->atoms[_NET_WM_STATE_MAXIMIZED_HORZ] &&
 | 
				
			||||||
 | 
									update_state(action, &xsurface->maximized_horz)) {
 | 
				
			||||||
 | 
								xsurface_set_net_wm_state(xsurface);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (maximized != xsurface_is_maximized(xsurface)) {
 | 
				
			||||||
 | 
								if (xsurface_is_maximized(xsurface)) {
 | 
				
			||||||
 | 
									xsurface->saved_width = xsurface->width;
 | 
				
			||||||
 | 
									xsurface->saved_height = xsurface->height;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								wl_signal_emit(&xsurface->events.request_maximize, xsurface);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_client_message(struct wlr_xwm *xwm,
 | 
					static void 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);
 | 
				
			||||||
| 
						 | 
					@ -769,7 +859,7 @@ static void handle_client_message(struct wlr_xwm *xwm,
 | 
				
			||||||
	if (ev->type == xwm->atoms[WL_SURFACE_ID]) {
 | 
						if (ev->type == xwm->atoms[WL_SURFACE_ID]) {
 | 
				
			||||||
		handle_surface_id_message(xwm, ev);
 | 
							handle_surface_id_message(xwm, ev);
 | 
				
			||||||
	} else if (ev->type == xwm->atoms[NET_WM_STATE]) {
 | 
						} else if (ev->type == xwm->atoms[NET_WM_STATE]) {
 | 
				
			||||||
		wlr_log(L_DEBUG, "TODO: handle _NET_WM_STATE client message");
 | 
							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]) {
 | 
				
			||||||
		handle_net_wm_moveresize_message(xwm, ev);
 | 
							handle_net_wm_moveresize_message(xwm, ev);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -1104,6 +1194,9 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
		xwm->atoms[NET_WM_STATE],
 | 
							xwm->atoms[NET_WM_STATE],
 | 
				
			||||||
		xwm->atoms[_NET_ACTIVE_WINDOW],
 | 
							xwm->atoms[_NET_ACTIVE_WINDOW],
 | 
				
			||||||
		xwm->atoms[_NET_WM_MOVERESIZE],
 | 
							xwm->atoms[_NET_WM_MOVERESIZE],
 | 
				
			||||||
 | 
							xwm->atoms[_NET_WM_STATE_FULLSCREEN],
 | 
				
			||||||
 | 
							xwm->atoms[_NET_WM_STATE_MAXIMIZED_HORZ],
 | 
				
			||||||
 | 
							xwm->atoms[_NET_WM_STATE_MAXIMIZED_VERT],
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	xcb_change_property(xwm->xcb_conn,
 | 
						xcb_change_property(xwm->xcb_conn,
 | 
				
			||||||
		XCB_PROP_MODE_REPLACE,
 | 
							XCB_PROP_MODE_REPLACE,
 | 
				
			||||||
| 
						 | 
					@ -1128,3 +1221,20 @@ struct wlr_xwm *xwm_create(struct wlr_xwayland *wlr_xwayland) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return xwm;
 | 
						return xwm;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_xwayland_surface_set_maximized(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
						struct wlr_xwayland_surface *surface, bool maximized) {
 | 
				
			||||||
 | 
						if (xsurface_is_maximized(surface) != maximized) {
 | 
				
			||||||
 | 
							surface->maximized_horz = maximized;
 | 
				
			||||||
 | 
							surface->maximized_vert = maximized;
 | 
				
			||||||
 | 
							xsurface_set_net_wm_state(surface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void wlr_xwayland_surface_set_fullscreen(struct wlr_xwayland *wlr_xwayland,
 | 
				
			||||||
 | 
						struct wlr_xwayland_surface *surface, bool fullscreen) {
 | 
				
			||||||
 | 
						if (surface->fullscreen != fullscreen) {
 | 
				
			||||||
 | 
							surface->fullscreen = fullscreen;
 | 
				
			||||||
 | 
							xsurface_set_net_wm_state(surface);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue