diff options
| author | Tony Crisci <[email protected]> | 2018-03-30 15:47:53 -0400 | 
|---|---|---|
| committer | GitHub <[email protected]> | 2018-03-30 15:47:53 -0400 | 
| commit | 7eca02301ba309fa909ba9b12cb335f8f944f1ee (patch) | |
| tree | 8616074124e558fb6787be9cb3336d61663d9a86 /sway/tree | |
| parent | 1c50d79e1940d9dce6217d0ca19611a19709120a (diff) | |
| parent | 88f08a42f30c6d79adbc9c1d5d897113fcd3a6f4 (diff) | |
Merge pull request #1662 from swaywm/workspace-delete-fixes
Fix workspace deletion edge cases
Diffstat (limited to 'sway/tree')
| -rw-r--r-- | sway/tree/container.c | 103 | ||||
| -rw-r--r-- | sway/tree/layout.c | 60 | ||||
| -rw-r--r-- | sway/tree/output.c | 36 | ||||
| -rw-r--r-- | sway/tree/view.c | 11 | ||||
| -rw-r--r-- | sway/tree/workspace.c | 56 | 
5 files changed, 137 insertions, 129 deletions
| diff --git a/sway/tree/container.c b/sway/tree/container.c index ed39a154..c3cf6c64 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -10,12 +10,12 @@  #include "sway/tree/container.h"  #include "sway/input/input-manager.h"  #include "sway/input/seat.h" -#include "sway/tree/layout.h" +#include "sway/ipc-server.h"  #include "sway/output.h"  #include "sway/server.h" +#include "sway/tree/layout.h"  #include "sway/tree/view.h"  #include "sway/tree/workspace.h" -#include "sway/ipc-server.h"  #include "log.h"  static list_t *bfs_queue; @@ -58,13 +58,14 @@ static struct sway_container *container_create(enum sway_container_type type) {  	return c;  } -void container_destroy(struct sway_container *cont) { +struct sway_container *container_destroy(struct sway_container *cont) {  	if (cont == NULL) { -		return; +		return NULL;  	}  	wl_signal_emit(&cont->events.destroy, cont); +	struct sway_container *parent = cont->parent;  	if (cont->children) {  		// remove children until there are no more, container_destroy calls  		// container_remove_child, which removes child from this container @@ -77,13 +78,14 @@ void container_destroy(struct sway_container *cont) {  		list_foreach(cont->marks, free);  		list_free(cont->marks);  	} -	if (cont->parent) { -		container_remove_child(cont); +	if (parent) { +		parent = container_remove_child(cont);  	}  	if (cont->name) {  		free(cont->name);  	}  	free(cont); +	return parent;  }  struct sway_container *container_output_create( @@ -202,95 +204,6 @@ struct sway_container *container_view_create(struct sway_container *sibling,  	return swayc;  } -struct sway_container *container_output_destroy(struct sway_container *output) { -	if (!sway_assert(output, "cannot destroy null output")) { -		return NULL; -	} - -	if (output->children->length > 0) { -		// TODO save workspaces when there are no outputs. -		// TODO also check if there will ever be no outputs except for exiting -		// program -		if (root_container.children->length > 1) { -			int p = root_container.children->items[0] == output; -			// Move workspace from this output to another output -			while (output->children->length) { -				struct sway_container *child = output->children->items[0]; -				container_remove_child(child); -				container_add_child(root_container.children->items[p], child); -			} -			container_sort_workspaces(root_container.children->items[p]); -			arrange_windows(root_container.children->items[p], -				-1, -1); -		} -	} - -	wl_list_remove(&output->sway_output->frame.link); -	wl_list_remove(&output->sway_output->destroy.link); -	wl_list_remove(&output->sway_output->mode.link); - -	wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); -	container_destroy(output); - -	return &root_container; -} - -struct sway_container *container_workspace_destroy( -		struct sway_container *workspace) { -	if (!sway_assert(workspace, "cannot destroy null workspace")) { -		return NULL; -	} - -	// Do not destroy this if it's the last workspace on this output -	struct sway_container *output = container_parent(workspace, C_OUTPUT); -	if (output && output->children->length == 1) { -		return NULL; -	} - -	struct sway_container *parent = workspace->parent; -	if (workspace->children->length == 0) { -		// destroy the WS if there are no children (TODO check for floating) -		wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); -		ipc_event_workspace(workspace, NULL, "empty"); -	} else { -		// Move children to a different workspace on this output -		struct sway_container *new_workspace = NULL; -		// TODO move floating -		for (int i = 0; i < output->children->length; i++) { -			if (output->children->items[i] != workspace) { -				new_workspace = output->children->items[i]; -				break; -			} -		} - -		wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", -			workspace->name, new_workspace->name); -		for (int i = 0; i < workspace->children->length; i++) { -			container_move_to(workspace->children->items[i], new_workspace); -		} -	} - -	container_destroy(workspace); -	return parent; -} - -struct sway_container *container_view_destroy(struct sway_container *view) { -	if (!view) { -		return NULL; -	} -	wlr_log(L_DEBUG, "Destroying view '%s'", view->name); -	struct sway_container *parent = view->parent; -	container_destroy(view); - -	// TODO WLR: Destroy empty containers -	/* -	if (parent && parent->type == C_CONTAINER) { -		return destroy_container(parent); -	} -	*/ -	return parent; -} -  struct sway_container *container_set_layout(struct sway_container *container,  		enum sway_container_layout layout) {  	if (container->type == C_WORKSPACE) { diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 73c4849b..588ceb2d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -9,6 +9,7 @@  #include "sway/tree/container.h"  #include "sway/tree/layout.h"  #include "sway/output.h" +#include "sway/tree/workspace.h"  #include "sway/tree/view.h"  #include "sway/input/seat.h"  #include "sway/ipc-server.h" @@ -99,40 +100,42 @@ void container_add_child(struct sway_container *parent,  			parent, parent->type, parent->width, parent->height);  	list_add(parent->children, child);  	child->parent = parent; -	// set focus for this container -	/* TODO WLR -	if (parent->type == C_WORKSPACE && child->type == C_VIEW && -	(parent->workspace_layout == L_TABBED || parent->workspace_layout == -	L_STACKED)) { -		child = new_container(child, parent->workspace_layout); +} + +struct sway_container *container_reap_empty(struct sway_container *container) { +	if (!sway_assert(container, "reaping null container")) { +		return NULL;  	} -	*/ +	wlr_log(L_DEBUG, "reaping %p %s", container, container->name); +	while (container->children->length == 0) { +		if (container->type == C_WORKSPACE) { +			if (!workspace_is_visible(container)) { +				struct sway_container *parent = container->parent; +				container_workspace_destroy(container); +				return parent; +			} +			return container; +		} else if (container->type == C_CONTAINER) { +			struct sway_container *parent = container->parent; +			container_destroy(container); +			container = parent; +		} else { +			container = container->parent; +		} +	} +	return container;  }  struct sway_container *container_remove_child(struct sway_container *child) { -	int i;  	struct sway_container *parent = child->parent; -	for (i = 0; i < parent->children->length; ++i) { +	for (int i = 0; i < parent->children->length; ++i) {  		if (parent->children->items[i] == child) {  			list_del(parent->children, i);  			break;  		}  	}  	child->parent = NULL; -	return parent; -} - -struct sway_container *container_reap_empty(struct sway_container *container) { -	if (!sway_assert(container, "reaping null container")) { -		return NULL; -	} -	while (container->children->length == 0 && container->type == C_CONTAINER) { -		wlr_log(L_DEBUG, "Container: Destroying container '%p'", container); -		struct sway_container *parent = container->parent; -		container_destroy(container); -		container = parent; -	} -	return container; +	return container_reap_empty(parent);  }  void container_move_to(struct sway_container* container, @@ -145,16 +148,9 @@ void container_move_to(struct sway_container* container,  	container->width = container->height = 0;  	struct sway_container *new_parent =  		container_add_sibling(destination, container); -	if (destination->type == C_WORKSPACE) { -		// If the workspace only has one child after adding one, it -		// means that the workspace was just initialized. -		// TODO: Consider floating views in this test -		if (destination->children->length == 1) { -			ipc_event_workspace(NULL, destination, "init"); -		} +	if (old_parent) { +		arrange_windows(old_parent, -1, -1);  	} -	old_parent = container_reap_empty(old_parent); -	arrange_windows(old_parent, -1, -1);  	arrange_windows(new_parent, -1, -1);  } diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 00000000..2246cb11 --- /dev/null +++ b/sway/tree/output.c @@ -0,0 +1,36 @@ +#include "sway/tree/container.h" +#include "sway/tree/layout.h" +#include "sway/output.h" +#include "log.h" + +struct sway_container *container_output_destroy(struct sway_container *output) { +	if (!sway_assert(output, "cannot destroy null output")) { +		return NULL; +	} + +	if (output->children->length > 0) { +		// TODO save workspaces when there are no outputs. +		// TODO also check if there will ever be no outputs except for exiting +		// program +		if (root_container.children->length > 1) { +			int p = root_container.children->items[0] == output; +			// Move workspace from this output to another output +			while (output->children->length) { +				struct sway_container *child = output->children->items[0]; +				container_remove_child(child); +				container_add_child(root_container.children->items[p], child); +			} +			container_sort_workspaces(root_container.children->items[p]); +			arrange_windows(root_container.children->items[p], +				-1, -1); +		} +	} + +	wl_list_remove(&output->sway_output->frame.link); +	wl_list_remove(&output->sway_output->destroy.link); +	wl_list_remove(&output->sway_output->mode.link); + +	wlr_log(L_DEBUG, "OUTPUT: Destroying output '%s'", output->name); +	container_destroy(output); +	return &root_container; +} diff --git a/sway/tree/view.c b/sway/tree/view.c index d5325c31..480ff693 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -3,6 +3,7 @@  #include "sway/tree/container.h"  #include "sway/tree/layout.h"  #include "sway/tree/view.h" +#include "log.h"  const char *view_get_title(struct sway_view *view) {  	if (view->iface.get_prop) { @@ -94,3 +95,13 @@ void view_update_outputs(struct sway_view *view, const struct wlr_box *before) {  		}  	}  } + +struct sway_container *container_view_destroy(struct sway_container *view) { +	if (!view) { +		return NULL; +	} +	wlr_log(L_DEBUG, "Destroying view '%s'", view->name); +	struct sway_container *parent = container_destroy(view); +	arrange_windows(parent, -1, -1); +	return parent; +} diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 5800ea09..c629f1f1 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -6,9 +6,10 @@  #include <stdio.h>  #include <strings.h>  #include "stringop.h" -#include "sway/tree/container.h"  #include "sway/input/input-manager.h"  #include "sway/input/seat.h" +#include "sway/ipc-server.h" +#include "sway/tree/container.h"  #include "sway/tree/workspace.h"  #include "log.h"  #include "util.h" @@ -202,7 +203,48 @@ struct sway_container *workspace_create(const char *name) {  		sway_seat_get_focus_inactive(seat, &root_container);  	parent = focus;  	parent = container_parent(parent, C_OUTPUT); -	return container_workspace_create(parent, name); +	struct sway_container *new_ws = container_workspace_create(parent, name); +	ipc_event_workspace(NULL, new_ws, "init"); +	return new_ws; +} + +struct sway_container *container_workspace_destroy( +		struct sway_container *workspace) { +	if (!sway_assert(workspace, "cannot destroy null workspace")) { +		return NULL; +	} + +	// Do not destroy this if it's the last workspace on this output +	struct sway_container *output = container_parent(workspace, C_OUTPUT); +	if (output && output->children->length == 1) { +		return NULL; +	} + +	struct sway_container *parent = workspace->parent; +	if (workspace->children->length == 0) { +		// destroy the WS if there are no children (TODO check for floating) +		wlr_log(L_DEBUG, "destroying workspace '%s'", workspace->name); +		ipc_event_workspace(workspace, NULL, "empty"); +	} else { +		// Move children to a different workspace on this output +		struct sway_container *new_workspace = NULL; +		// TODO move floating +		for (int i = 0; i < output->children->length; i++) { +			if (output->children->items[i] != workspace) { +				new_workspace = output->children->items[i]; +				break; +			} +		} + +		wlr_log(L_DEBUG, "moving children to different workspace '%s' -> '%s'", +			workspace->name, new_workspace->name); +		for (int i = 0; i < workspace->children->length; i++) { +			container_move_to(workspace->children->items[i], new_workspace); +		} +	} + +	container_destroy(workspace); +	return parent;  }  /** @@ -343,3 +385,13 @@ bool workspace_switch(struct sway_container *workspace) {  	arrange_windows(output, -1, -1);  	return true;  } + +bool workspace_is_visible(struct sway_container *ws) { +	struct sway_container *output = container_parent(ws, C_OUTPUT); +	struct sway_seat *seat = input_manager_current_seat(input_manager); +	struct sway_container *focus = sway_seat_get_focus_inactive(seat, output); +	if (focus->type != C_WORKSPACE) { +		focus = container_parent(focus, C_WORKSPACE); +	} +	return focus == ws; +} | 
