diff options
Diffstat (limited to 'sway/tree')
| -rw-r--r-- | sway/tree/container.c | 78 | ||||
| -rw-r--r-- | sway/tree/layout.c | 58 | ||||
| -rw-r--r-- | sway/tree/output.c | 39 | ||||
| -rw-r--r-- | sway/tree/view.c | 27 | ||||
| -rw-r--r-- | sway/tree/workspace.c | 56 | 
5 files changed, 185 insertions, 73 deletions
| diff --git a/sway/tree/container.c b/sway/tree/container.c index 2eac812e..8705edc7 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -6,16 +6,16 @@  #include <wayland-server.h>  #include <wlr/types/wlr_output_layout.h>  #include <wlr/types/wlr_wl_shell.h> +#include "log.h"  #include "sway/config.h" -#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;  } -static 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 @@ static 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,57 +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, -				"null output passed to container_output_destroy")) { -		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_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) { @@ -438,3 +389,14 @@ void container_for_each_descendant_bfs(struct sway_container *con,  		list_cat(queue, current->children);  	}  } + +bool container_has_anscestor(struct sway_container *descendant, +		struct sway_container *anscestor) { +	while (descendant->type != C_ROOT) { +		descendant = descendant->parent; +		if (descendant == anscestor) { +			return true; +		} +	} +	return false; +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index dc0ee5b4..588ceb2d 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -9,8 +9,10 @@  #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"  #include "list.h"  #include "log.h" @@ -98,37 +100,67 @@ 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; +	return container_reap_empty(parent); +} + +void container_move_to(struct sway_container* container, +		struct sway_container* destination) { +	if (container == destination +			|| container_has_anscestor(container, destination)) { +		return; +	} +	struct sway_container *old_parent = container_remove_child(container); +	container->width = container->height = 0; +	struct sway_container *new_parent = +		container_add_sibling(destination, container); +	if (old_parent) { +		arrange_windows(old_parent, -1, -1); +	} +	arrange_windows(new_parent, -1, -1);  }  enum sway_container_layout container_get_default_layout(  		struct sway_container *output) { -	/* TODO WLR  	if (config->default_layout != L_NONE) { -		//return config->default_layout; +		return config->default_layout;  	} else if (config->default_orientation != L_NONE) {  		return config->default_orientation; -	} else */if (output->width >= output->height) { +	} else if (output->width >= output->height) {  		return L_HORIZ;  	} else {  		return L_VERT; diff --git a/sway/tree/output.c b/sway/tree/output.c new file mode 100644 index 00000000..7248fd00 --- /dev/null +++ b/sway/tree/output.c @@ -0,0 +1,39 @@ +#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->destroy.link); +	wl_list_remove(&output->sway_output->mode.link); +	wl_list_remove(&output->sway_output->transform.link); + +	wl_list_remove(&output->sway_output->damage_destroy.link); +	wl_list_remove(&output->sway_output->damage_frame.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..b7d1a41b 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -1,5 +1,7 @@  #include <wayland-server.h>  #include <wlr/types/wlr_output_layout.h> +#include "log.h" +#include "sway/output.h"  #include "sway/tree/container.h"  #include "sway/tree/layout.h"  #include "sway/tree/view.h" @@ -94,3 +96,28 @@ 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; +} + +void view_damage_whole(struct sway_view *view) { +	struct sway_container *cont = NULL; +	for (int i = 0; i < root_container.children->length; ++i) { +		cont = root_container.children->items[i]; +		if (cont->type == C_OUTPUT) { +			output_damage_whole_view(cont->sway_output, view); +		} +	} +} + +void view_damage_from(struct sway_view *view) { +	// TODO +	view_damage_whole(view); +} 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; +} | 
