diff options
| -rw-r--r-- | include/sway/server.h | 4 | ||||
| -rw-r--r-- | include/sway/tree/view.h | 1 | ||||
| -rw-r--r-- | include/sway/xdg_decoration.h | 2 | ||||
| -rw-r--r-- | sway/desktop/layer_shell.c | 45 | ||||
| -rw-r--r-- | sway/desktop/xdg_shell.c | 87 | ||||
| -rw-r--r-- | sway/server.c | 6 | ||||
| -rw-r--r-- | sway/xdg_decoration.c | 59 | 
7 files changed, 114 insertions, 90 deletions
diff --git a/include/sway/server.h b/include/sway/server.h index be5c8d72..1b3166ce 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -59,7 +59,7 @@ struct sway_server {  	struct wl_listener layer_shell_surface;  	struct wlr_xdg_shell *xdg_shell; -	struct wl_listener xdg_shell_surface; +	struct wl_listener xdg_shell_toplevel;  	struct wlr_tablet_manager_v2 *tablet_v2; @@ -176,7 +176,7 @@ void handle_new_output(struct wl_listener *listener, void *data);  void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);  void handle_layer_shell_surface(struct wl_listener *listener, void *data);  void sway_session_lock_init(void); -void handle_xdg_shell_surface(struct wl_listener *listener, void *data); +void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data);  #if HAVE_XWAYLAND  void handle_xwayland_surface(struct wl_listener *listener, void *data);  #endif diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 960f9d71..856651a5 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -226,6 +226,7 @@ struct sway_xdg_popup {  	struct wlr_xdg_popup *wlr_xdg_popup; +	struct wl_listener surface_commit;  	struct wl_listener new_popup;  	struct wl_listener destroy;  }; diff --git a/include/sway/xdg_decoration.h b/include/sway/xdg_decoration.h index 8bef4c6d..2388ebcb 100644 --- a/include/sway/xdg_decoration.h +++ b/include/sway/xdg_decoration.h @@ -16,4 +16,6 @@ struct sway_xdg_decoration {  struct sway_xdg_decoration *xdg_decoration_from_surface(  	struct wlr_surface *surface); +void set_xdg_decoration_mode(struct sway_xdg_decoration *deco); +  #endif diff --git a/sway/desktop/layer_shell.c b/sway/desktop/layer_shell.c index 8c6cedfe..979c4449 100644 --- a/sway/desktop/layer_shell.c +++ b/sway/desktop/layer_shell.c @@ -542,6 +542,26 @@ static void popup_damage(struct sway_layer_popup *layer_popup, bool whole) {  	output_damage_surface(output, ox, oy, surface, whole);  } +static void popup_unconstrain(struct sway_layer_popup *popup) { +	struct sway_layer_surface *layer = popup_get_layer(popup); +	struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; + +	struct wlr_output *wlr_output = layer->layer_surface->output; +	sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); +	struct sway_output *output = wlr_output->data; + +	// the output box expressed in the coordinate system of the toplevel parent +	// of the popup +	struct wlr_box output_toplevel_sx_box = { +		.x = -layer->geo.x, +		.y = -layer->geo.y, +		.width = output->width, +		.height = output->height, +	}; + +	wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); +} +  static void popup_handle_map(struct wl_listener *listener, void *data) {  	struct sway_layer_popup *popup = wl_container_of(listener, popup, map);  	struct sway_layer_surface *layer = popup_get_layer(popup); @@ -558,6 +578,9 @@ static void popup_handle_unmap(struct wl_listener *listener, void *data) {  static void popup_handle_commit(struct wl_listener *listener, void *data) {  	struct sway_layer_popup *popup = wl_container_of(listener, popup, commit); +	if (popup->wlr_popup->base->initial_commit) { +		popup_unconstrain(popup); +	}  	popup_damage(popup, false);  } @@ -572,26 +595,6 @@ static void popup_handle_destroy(struct wl_listener *listener, void *data) {  	free(popup);  } -static void popup_unconstrain(struct sway_layer_popup *popup) { -	struct sway_layer_surface *layer = popup_get_layer(popup); -	struct wlr_xdg_popup *wlr_popup = popup->wlr_popup; - -	struct wlr_output *wlr_output = layer->layer_surface->output; -	sway_assert(wlr_output, "wlr_layer_surface_v1 has null output"); -	struct sway_output *output = wlr_output->data; - -	// the output box expressed in the coordinate system of the toplevel parent -	// of the popup -	struct wlr_box output_toplevel_sx_box = { -		.x = -layer->geo.x, -		.y = -layer->geo.y, -		.width = output->width, -		.height = output->height, -	}; - -	wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box); -} -  static void popup_handle_new_popup(struct wl_listener *listener, void *data);  static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup, @@ -617,8 +620,6 @@ static struct sway_layer_popup *create_popup(struct wlr_xdg_popup *wlr_popup,  	popup->new_popup.notify = popup_handle_new_popup;  	wl_signal_add(&wlr_popup->base->events.new_popup, &popup->new_popup); -	popup_unconstrain(popup); -  	return popup;  } diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 4c59b42a..63a0835b 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -38,6 +38,7 @@ static void popup_destroy(struct sway_view_child *child) {  		return;  	}  	struct sway_xdg_popup *popup = (struct sway_xdg_popup *)child; +	wl_list_remove(&popup->surface_commit.link);  	wl_list_remove(&popup->new_popup.link);  	wl_list_remove(&popup->destroy.link);  	free(popup); @@ -51,18 +52,6 @@ static const struct sway_view_child_impl popup_impl = {  static struct sway_xdg_popup *popup_create(  	struct wlr_xdg_popup *wlr_popup, struct sway_view *view); -static void popup_handle_new_popup(struct wl_listener *listener, void *data) { -	struct sway_xdg_popup *popup = -		wl_container_of(listener, popup, new_popup); -	struct wlr_xdg_popup *wlr_popup = data; -	popup_create(wlr_popup, popup->child.view); -} - -static void popup_handle_destroy(struct wl_listener *listener, void *data) { -	struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); -	view_child_destroy(&popup->child); -} -  static void popup_unconstrain(struct sway_xdg_popup *popup) {  	struct sway_view *view = popup->child.view;  	struct wlr_xdg_popup *wlr_popup = popup->wlr_xdg_popup; @@ -87,6 +76,25 @@ static void popup_unconstrain(struct sway_xdg_popup *popup) {  	wlr_xdg_popup_unconstrain_from_box(wlr_popup, &output_toplevel_sx_box);  } +static void popup_handle_surface_commit(struct wl_listener *listener, void *data) { +	struct sway_xdg_popup *popup = wl_container_of(listener, popup, surface_commit); +	if (popup->wlr_xdg_popup->base->initial_commit) { +		popup_unconstrain(popup); +	} +} + +static void popup_handle_new_popup(struct wl_listener *listener, void *data) { +	struct sway_xdg_popup *popup = +		wl_container_of(listener, popup, new_popup); +	struct wlr_xdg_popup *wlr_popup = data; +	popup_create(wlr_popup, popup->child.view); +} + +static void popup_handle_destroy(struct wl_listener *listener, void *data) { +	struct sway_xdg_popup *popup = wl_container_of(listener, popup, destroy); +	view_child_destroy(&popup->child); +} +  static struct sway_xdg_popup *popup_create(  		struct wlr_xdg_popup *wlr_popup, struct sway_view *view) {  	struct wlr_xdg_surface *xdg_surface = wlr_popup->base; @@ -97,22 +105,21 @@ static struct sway_xdg_popup *popup_create(  		return NULL;  	}  	view_child_init(&popup->child, &popup_impl, view, xdg_surface->surface); -	popup->wlr_xdg_popup = xdg_surface->popup; +	popup->wlr_xdg_popup = wlr_popup; +	wl_signal_add(&xdg_surface->surface->events.commit, &popup->surface_commit); +	popup->surface_commit.notify = popup_handle_surface_commit;  	wl_signal_add(&xdg_surface->events.new_popup, &popup->new_popup);  	popup->new_popup.notify = popup_handle_new_popup; -	wl_signal_add(&xdg_surface->events.destroy, &popup->destroy); +	wl_signal_add(&wlr_popup->events.destroy, &popup->destroy);  	popup->destroy.notify = popup_handle_destroy;  	wl_signal_add(&xdg_surface->surface->events.map, &popup->child.surface_map);  	wl_signal_add(&xdg_surface->surface->events.unmap, &popup->child.surface_unmap); -	popup_unconstrain(popup); -  	return popup;  } -  static struct sway_xdg_shell_view *xdg_shell_view_from_view(  		struct sway_view *view) {  	if (!sway_assert(view->type == SWAY_VIEW_XDG_SHELL, @@ -286,6 +293,19 @@ static void handle_commit(struct wl_listener *listener, void *data) {  	struct sway_view *view = &xdg_shell_view->view;  	struct wlr_xdg_surface *xdg_surface = view->wlr_xdg_toplevel->base; +	if (xdg_surface->initial_commit) { +		if (view->xdg_decoration != NULL) { +			set_xdg_decoration_mode(view->xdg_decoration); +		} +		// XXX: https://github.com/swaywm/sway/issues/2176 +		wlr_xdg_surface_schedule_configure(xdg_surface); +		return; +	} + +	if (!xdg_surface->surface->mapped) { +		return; +	} +  	struct wlr_box new_geo;  	wlr_xdg_surface_get_geometry(xdg_surface, &new_geo);  	bool new_size = new_geo.width != view->geometry.width || @@ -421,7 +441,6 @@ static void handle_unmap(struct wl_listener *listener, void *data) {  	view_unmap(view); -	wl_list_remove(&xdg_shell_view->commit.link);  	wl_list_remove(&xdg_shell_view->new_popup.link);  	wl_list_remove(&xdg_shell_view->request_maximize.link);  	wl_list_remove(&xdg_shell_view->request_fullscreen.link); @@ -464,10 +483,6 @@ static void handle_map(struct wl_listener *listener, void *data) {  	transaction_commit_dirty(); -	xdg_shell_view->commit.notify = handle_commit; -	wl_signal_add(&toplevel->base->surface->events.commit, -		&xdg_shell_view->commit); -  	xdg_shell_view->new_popup.notify = handle_new_popup;  	wl_signal_add(&toplevel->base->events.new_popup,  		&xdg_shell_view->new_popup); @@ -507,6 +522,7 @@ static void handle_destroy(struct wl_listener *listener, void *data) {  	wl_list_remove(&xdg_shell_view->destroy.link);  	wl_list_remove(&xdg_shell_view->map.link);  	wl_list_remove(&xdg_shell_view->unmap.link); +	wl_list_remove(&xdg_shell_view->commit.link);  	view->wlr_xdg_toplevel = NULL;  	if (view->xdg_decoration) {  		view->xdg_decoration->view = NULL; @@ -519,17 +535,12 @@ struct sway_view *view_from_wlr_xdg_surface(  	return xdg_surface->data;  } -void handle_xdg_shell_surface(struct wl_listener *listener, void *data) { -	struct wlr_xdg_surface *xdg_surface = data; - -	if (xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP) { -		sway_log(SWAY_DEBUG, "New xdg_shell popup"); -		return; -	} +void handle_xdg_shell_toplevel(struct wl_listener *listener, void *data) { +	struct wlr_xdg_toplevel *xdg_toplevel = data;  	sway_log(SWAY_DEBUG, "New xdg_shell toplevel title='%s' app_id='%s'", -		xdg_surface->toplevel->title, xdg_surface->toplevel->app_id); -	wlr_xdg_surface_ping(xdg_surface); +		xdg_toplevel->title, xdg_toplevel->app_id); +	wlr_xdg_surface_ping(xdg_toplevel->base);  	struct sway_xdg_shell_view *xdg_shell_view =  		calloc(1, sizeof(struct sway_xdg_shell_view)); @@ -538,16 +549,20 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {  	}  	view_init(&xdg_shell_view->view, SWAY_VIEW_XDG_SHELL, &view_impl); -	xdg_shell_view->view.wlr_xdg_toplevel = xdg_surface->toplevel; +	xdg_shell_view->view.wlr_xdg_toplevel = xdg_toplevel;  	xdg_shell_view->map.notify = handle_map; -	wl_signal_add(&xdg_surface->surface->events.map, &xdg_shell_view->map); +	wl_signal_add(&xdg_toplevel->base->surface->events.map, &xdg_shell_view->map);  	xdg_shell_view->unmap.notify = handle_unmap; -	wl_signal_add(&xdg_surface->surface->events.unmap, &xdg_shell_view->unmap); +	wl_signal_add(&xdg_toplevel->base->surface->events.unmap, &xdg_shell_view->unmap); + +	xdg_shell_view->commit.notify = handle_commit; +	wl_signal_add(&xdg_toplevel->base->surface->events.commit, +		&xdg_shell_view->commit);  	xdg_shell_view->destroy.notify = handle_destroy; -	wl_signal_add(&xdg_surface->events.destroy, &xdg_shell_view->destroy); +	wl_signal_add(&xdg_toplevel->events.destroy, &xdg_shell_view->destroy); -	xdg_surface->data = xdg_shell_view; +	xdg_toplevel->base->data = xdg_shell_view;  } diff --git a/sway/server.c b/sway/server.c index e4f8a7c8..be521621 100644 --- a/sway/server.c +++ b/sway/server.c @@ -185,9 +185,9 @@ bool server_init(struct sway_server *server) {  	server->xdg_shell = wlr_xdg_shell_create(server->wl_display,  		SWAY_XDG_SHELL_VERSION); -	wl_signal_add(&server->xdg_shell->events.new_surface, -		&server->xdg_shell_surface); -	server->xdg_shell_surface.notify = handle_xdg_shell_surface; +	wl_signal_add(&server->xdg_shell->events.new_toplevel, +		&server->xdg_shell_toplevel); +	server->xdg_shell_toplevel.notify = handle_xdg_shell_toplevel;  	server->tablet_v2 = wlr_tablet_v2_create(server->wl_display); diff --git a/sway/xdg_decoration.c b/sway/xdg_decoration.c index f7f5f5ed..fa8c6279 100644 --- a/sway/xdg_decoration.c +++ b/sway/xdg_decoration.c @@ -23,32 +23,7 @@ static void xdg_decoration_handle_request_mode(struct wl_listener *listener,  		void *data) {  	struct sway_xdg_decoration *deco =  		wl_container_of(listener, deco, request_mode); -	struct sway_view *view = deco->view; -	enum wlr_xdg_toplevel_decoration_v1_mode mode = -		WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; -	enum wlr_xdg_toplevel_decoration_v1_mode client_mode = -		deco->wlr_xdg_decoration->requested_mode; - -	bool floating; -	if (view->container) { -		floating = container_is_floating(view->container); -		bool csd = false; -		csd = client_mode == -			WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; -		view_update_csd_from_client(view, csd); -		arrange_container(view->container); -		transaction_commit_dirty(); -	} else { -		floating = view->impl->wants_floating && -			view->impl->wants_floating(view); -	} - -	if (floating && client_mode) { -		mode = client_mode; -	} - -	wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, -			mode); +	set_xdg_decoration_mode(deco);  }  void handle_xdg_decoration(struct wl_listener *listener, void *data) { @@ -72,7 +47,7 @@ void handle_xdg_decoration(struct wl_listener *listener, void *data) {  	wl_list_insert(&server.xdg_decorations, &deco->link); -	xdg_decoration_handle_request_mode(&deco->request_mode, wlr_deco); +	set_xdg_decoration_mode(deco);  }  struct sway_xdg_decoration *xdg_decoration_from_surface( @@ -85,3 +60,33 @@ struct sway_xdg_decoration *xdg_decoration_from_surface(  	}  	return NULL;  } + +void set_xdg_decoration_mode(struct sway_xdg_decoration *deco) { +	struct sway_view *view = deco->view; +	enum wlr_xdg_toplevel_decoration_v1_mode mode = +		WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; +	enum wlr_xdg_toplevel_decoration_v1_mode client_mode = +		deco->wlr_xdg_decoration->requested_mode; + +	bool floating; +	if (view->container) { +		floating = container_is_floating(view->container); +		bool csd = false; +		csd = client_mode == +			WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE; +		view_update_csd_from_client(view, csd); +		arrange_container(view->container); +		transaction_commit_dirty(); +	} else { +		floating = view->impl->wants_floating && +			view->impl->wants_floating(view); +	} + +	if (floating && client_mode) { +		mode = client_mode; +	} + +	if (view->wlr_xdg_toplevel->base->initialized) { +		wlr_xdg_toplevel_decoration_v1_set_mode(deco->wlr_xdg_decoration, mode); +	} +}  | 
