Merge pull request #1702 from acrisci/split-containers2

properly close container containers
This commit is contained in:
emersion 2018-04-04 00:26:31 -04:00 committed by GitHub
commit dee71871d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 367 additions and 312 deletions

View file

@ -91,13 +91,11 @@ struct sway_container {
} events;
};
// TODO make private and use the container-specific create functions
struct sway_container *container_create(enum sway_container_type type);
const char *container_type_to_str(enum sway_container_type type);
// TODO only one container create function and pass the type?
struct sway_container *container_output_create(
struct sway_container *output_create(
struct sway_output *sway_output);
/**
@ -110,35 +108,26 @@ struct sway_container *container_container_create();
* Create a new output. Outputs are children of the root container and have no
* order in the tree structure.
*/
struct sway_container *container_output_create(struct sway_output *sway_output);
struct sway_container *output_create(struct sway_output *sway_output);
/**
* Create a new workspace container. Workspaces are children of an output
* container and are ordered alphabetically by name.
*/
struct sway_container *container_workspace_create(struct sway_container *output, const char *name);
struct sway_container *workspace_create(struct sway_container *output, const char *name);
/*
* Create a new view container. A view can be a child of a workspace container
* or a container container and are rendered in the order and structure of
* how they are attached to the tree.
*/
// TODO view containers should be created in a detached state.
struct sway_container *container_view_create(
struct sway_container *sibling, struct sway_view *sway_view);
// TODO don't return the parent on destroy
struct sway_container *container_destroy(struct sway_container *container);
struct sway_container *container_workspace_destroy(struct sway_container *container);
struct sway_container *container_output_destroy(struct sway_container *container);
struct sway_container *container_view_destroy(struct sway_container *container);
struct sway_container *container_close(struct sway_container *container);
// TODO move to layout.c
struct sway_container *container_set_layout(struct sway_container *container,
enum sway_container_layout layout);
// TODO rename to container_descendants_for_each()
void container_descendants(struct sway_container *root,
enum sway_container_type type,
void (*func)(struct sway_container *item, void *data), void *data);
@ -153,7 +142,6 @@ struct sway_container *container_find(struct sway_container *container,
/**
* Finds a parent container with the given struct sway_containerype.
*/
// TODO rename to container_parent_of_type()
struct sway_container *container_parent(struct sway_container *container,
enum sway_container_type type);
@ -190,4 +178,6 @@ bool container_has_anscestor(struct sway_container *container,
bool container_has_child(struct sway_container *con,
struct sway_container *child);
void container_create_notify(struct sway_container *container);
#endif

View file

@ -29,42 +29,37 @@ struct sway_root {
void layout_init(void);
// TODO move to tree.h
void container_add_child(struct sway_container *parent,
struct sway_container *child);
// TODO move to tree.h
struct sway_container *container_add_sibling(struct sway_container *parent,
struct sway_container *child);
// TODO move to tree.h
struct sway_container *container_remove_child(struct sway_container *child);
// TODO PRIVATE in tree.h
struct sway_container *container_reap_empty(struct sway_container *container);
struct sway_container *container_replace_child(struct sway_container *child,
struct sway_container *new_child);
struct sway_container *container_set_layout(struct sway_container *container,
enum sway_container_layout layout);
// TODO move to tree.h
void container_move_to(struct sway_container* container,
struct sway_container* destination);
void container_move(struct sway_container *container,
enum movement_direction dir, int move_amt);
// TODO move to output.c
enum sway_container_layout container_get_default_layout(
struct sway_container *output);
struct sway_container *con);
// TODO move to output.c
void container_sort_workspaces(struct sway_container *output);
void arrange_windows(struct sway_container *container,
double width, double height);
// TODO move to container.h
struct sway_container *container_get_in_direction(struct sway_container
*container, struct sway_seat *seat, enum movement_direction dir);
// TODO move to tree.h
struct sway_container *container_split(struct sway_container *child,
enum sway_container_layout layout);

View file

View file

@ -7,8 +7,6 @@ extern char *prev_workspace_name;
char *workspace_next_name(const char *output_name);
struct sway_container *workspace_create(const char *name);
bool workspace_switch(struct sway_container *workspace);
struct sway_container *workspace_by_number(const char* name);

View file

@ -10,22 +10,7 @@ struct cmd_results *cmd_kill(int argc, char **argv) {
struct sway_container *con =
config->handler_context.current_container;
switch (con->type) {
case C_ROOT:
case C_OUTPUT:
case C_WORKSPACE:
case C_TYPES:
return cmd_results_new(CMD_INVALID, NULL,
"Can only kill views and containers with this command");
break;
case C_CONTAINER:
con = container_destroy(con);
arrange_windows(con, -1, -1);
break;
case C_VIEW:
view_close(con->sway_view);
break;
}
container_close(con);
return cmd_results_new(CMD_SUCCESS, NULL, NULL);
}

View file

@ -28,8 +28,7 @@ struct cmd_results *cmd_layout(int argc, char **argv) {
if (strcasecmp(argv[0], "default") == 0) {
container_set_layout(parent, parent->prev_layout);
if (parent->layout == L_NONE) {
struct sway_container *output = container_parent(parent, C_OUTPUT);
container_set_layout(parent, container_get_default_layout(output));
container_set_layout(parent, container_get_default_layout(parent));
}
} else {
if (parent->layout != L_TABBED && parent->layout != L_STACKED) {

View file

@ -74,7 +74,7 @@ static struct cmd_results *cmd_move_container(struct sway_container *current,
ws = workspace_by_name(ws_name);
}
if (!ws) {
ws = workspace_create(ws_name ? ws_name : num_name);
ws = workspace_create(NULL, ws_name ? ws_name : num_name);
}
free(ws_name);
struct sway_container *old_parent = current->parent;

View file

@ -61,7 +61,7 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
if (strcasecmp(argv[0], "number") == 0) {
if (!(ws = workspace_by_number(argv[1]))) {
char *name = join_args(argv + 1, argc - 1);
ws = workspace_create(name);
ws = workspace_create(NULL, name);
free(name);
}
} else if (strcasecmp(argv[0], "next") == 0) {
@ -80,12 +80,12 @@ struct cmd_results *cmd_workspace(int argc, char **argv) {
ws = old_workspace;
} else if (prev_workspace_name
&& !(ws = workspace_by_name(prev_workspace_name))) {
ws = workspace_create(prev_workspace_name);
ws = workspace_create(NULL, prev_workspace_name);
}
} else {
char *name = join_args(argv, argc);
if (!(ws = workspace_by_name(name))) {
ws = workspace_create(name);
ws = workspace_create(NULL, name);
}
free(name);
}

View file

@ -128,8 +128,9 @@ void apply_output_config(struct output_config *oc, struct sway_container *output
struct wlr_output *wlr_output = output->sway_output->wlr_output;
if (oc && oc->enabled == 0) {
container_output_destroy(output);
wlr_output_layout_remove(output_layout, wlr_output);
container_destroy(output);
wlr_output_layout_remove(root_container.sway_root->output_layout,
wlr_output);
return;
}

View file

@ -2,6 +2,7 @@
#include <assert.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
#include <wayland-server.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
@ -21,6 +22,16 @@
#include "sway/tree/layout.h"
#include "sway/tree/view.h"
struct sway_container *output_by_name(const char *name) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *output = root_container.children->items[i];
if (strcasecmp(output->name, name) == 0) {
return output;
}
}
return NULL;
}
/**
* Rotate a child's position relative to a parent. The parent size is (pw, ph),
* the child position is (*sx, *sy) and its size is (sw, sh).
@ -334,12 +345,12 @@ void output_damage_whole_view(struct sway_output *output,
static void damage_handle_destroy(struct wl_listener *listener, void *data) {
struct sway_output *output =
wl_container_of(listener, output, damage_destroy);
container_output_destroy(output->swayc);
container_destroy(output->swayc);
}
static void handle_destroy(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, destroy);
container_output_destroy(output->swayc);
container_destroy(output->swayc);
}
static void handle_mode(struct wl_listener *listener, void *data) {
@ -381,7 +392,7 @@ void handle_new_output(struct wl_listener *listener, void *data) {
output->damage = wlr_output_damage_create(wlr_output);
output->swayc = container_output_create(output);
output->swayc = output_create(output);
if (!output->swayc) {
free(output);
return;

View file

@ -384,7 +384,7 @@ void seat_set_focus_warp(struct sway_seat *seat,
if (last_ws) {
ipc_event_workspace(last_ws, container, "focus");
if (last_ws->children->length == 0) {
container_workspace_destroy(last_ws);
container_destroy(last_ws);
}
}
struct sway_container *last_output = last_focus;

View file

@ -86,9 +86,9 @@ sway_sources = files(
'security.c',
'tree/container.c',
'tree/layout.c',
'tree/output.c',
'tree/view.c',
'tree/workspace.c',
'tree/output.c',
)
sway_deps = [

View file

@ -1,4 +1,5 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@ -6,7 +7,6 @@
#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/input/input-manager.h"
#include "sway/input/seat.h"
@ -50,7 +50,7 @@ const char *container_type_to_str(enum sway_container_type type) {
}
}
static void notify_new_container(struct sway_container *container) {
void container_create_notify(struct sway_container *container) {
wl_signal_emit(&root_container.sway_root->events.new_container, container);
ipc_event_window(container, "new");
}
@ -76,21 +76,21 @@ struct sway_container *container_create(enum sway_container_type type) {
return c;
}
static struct sway_container *_container_destroy(struct sway_container *cont) {
static void _container_destroy(struct sway_container *cont) {
if (cont == NULL) {
return NULL;
return;
}
wl_signal_emit(&cont->events.destroy, cont);
struct sway_container *parent = cont->parent;
if (cont->children != NULL) {
if (cont->children != NULL && cont->children->length) {
// remove children until there are no more, container_destroy calls
// container_remove_child, which removes child from this container
while (cont->children != NULL && cont->children->length != 0) {
while (cont->children != NULL) {
struct sway_container *child = cont->children->items[0];
container_remove_child(child);
container_destroy(child);
_container_destroy(child);
}
}
if (cont->marks) {
@ -106,106 +106,200 @@ static struct sway_container *_container_destroy(struct sway_container *cont) {
list_free(cont->children);
cont->children = NULL;
free(cont);
}
static 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->scale.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;
}
static 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);
output_damage_whole(output->sway_output);
return parent;
}
struct sway_container *container_destroy(struct sway_container *cont) {
struct sway_container *parent = _container_destroy(cont);
parent = container_reap_empty(parent);
arrange_windows(&root_container, -1, -1);
return parent;
static void container_root_finish(struct sway_container *con) {
wlr_log(L_ERROR, "TODO: destroy the root container");
}
struct sway_container *container_output_create(
struct sway_output *sway_output) {
struct wlr_box size;
wlr_output_effective_resolution(sway_output->wlr_output, &size.width,
&size.height);
const char *name = sway_output->wlr_output->name;
char identifier[128];
output_get_identifier(identifier, sizeof(identifier), sway_output);
struct output_config *oc = NULL, *all = NULL;
for (int i = 0; i < config->output_configs->length; ++i) {
struct output_config *cur = config->output_configs->items[i];
if (strcasecmp(name, cur->name) == 0 ||
strcasecmp(identifier, cur->name) == 0) {
wlr_log(L_DEBUG, "Matched output config for %s", name);
oc = cur;
static bool container_reap_empty(struct sway_container *con) {
switch (con->type) {
case C_ROOT:
case C_OUTPUT:
// dont reap these
break;
case C_WORKSPACE:
if (!workspace_is_visible(con) && con->children->length == 0) {
container_workspace_destroy(con);
return true;
}
if (strcasecmp("*", cur->name) == 0) {
wlr_log(L_DEBUG, "Matched wildcard output config for %s", name);
all = cur;
break;
case C_CONTAINER:
if (con->children->length == 0) {
_container_destroy(con);
return true;
} else if (con->children->length == 1) {
struct sway_container *child = con->children->items[0];
if (child->type == C_CONTAINER) {
container_remove_child(child);
container_replace_child(con, child);
_container_destroy(con);
return true;
}
}
case C_VIEW:
break;
case C_TYPES:
sway_assert(false, "container_reap_empty called on an invalid "
"container");
break;
}
if (oc && all) {
return false;
}
struct sway_container *container_destroy(struct sway_container *con) {
if (con == NULL) {
return NULL;
}
struct sway_container *parent = con->parent;
switch (con->type) {
case C_ROOT:
container_root_finish(con);
break;
case C_OUTPUT:
// dont try to reap the root after this
container_output_destroy(con);
break;
case C_WORKSPACE:
// dont try to reap the output after this
container_workspace_destroy(con);
break;
case C_CONTAINER:
if (con->children->length) {
for (int i = 0; i < con->children->length; ++i) {
struct sway_container *child = con->children->items[0];
container_remove_child(child);
container_add_child(parent, child);
}
}
_container_destroy(con);
break;
case C_VIEW:
_container_destroy(con);
break;
case C_TYPES:
wlr_log(L_ERROR, "container_destroy called on an invalid "
"container");
break;
}
struct sway_container *tmp = parent;
while (parent) {
tmp = parent->parent;
if (!container_reap_empty(parent)) {
break;
}
}
if (!oc) {
oc = all;
parent = tmp;
}
if (oc && !oc->enabled) {
return NULL;
}
struct sway_container *output = container_create(C_OUTPUT);
output->sway_output = sway_output;
output->name = strdup(name);
if (output->name == NULL) {
container_destroy(output);
return NULL;
}
// Insert the child before applying config so that the container coordinates
// get updated
container_add_child(&root_container, output);
apply_output_config(oc, output);
load_swaybars();
// Create workspace
char *ws_name = workspace_next_name(output->name);
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
struct sway_container *ws = container_workspace_create(output, ws_name);
// Set each seat's focus if not already set
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input_manager->seats, link) {
if (!seat->has_focus) {
seat_set_focus(seat, ws);
}
}
free(ws_name);
notify_new_container(output);
return output;
return tmp;
}
struct sway_container *container_workspace_create(
struct sway_container *output, const char *name) {
if (!sway_assert(output,
"container_workspace_create called with null output")) {
static void container_close_func(struct sway_container *container, void *data) {
if (container->type == C_VIEW) {
view_close(container->sway_view);
}
}
struct sway_container *container_close(struct sway_container *con) {
if (!sway_assert(con != NULL,
"container_close called with a NULL container")) {
return NULL;
}
wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name);
struct sway_container *workspace = container_create(C_WORKSPACE);
workspace->x = output->x;
workspace->y = output->y;
workspace->width = output->width;
workspace->height = output->height;
workspace->name = !name ? NULL : strdup(name);
workspace->prev_layout = L_NONE;
workspace->layout = container_get_default_layout(output);
workspace->workspace_layout = container_get_default_layout(output);
struct sway_container *parent = con->parent;
container_add_child(output, workspace);
container_sort_workspaces(output);
notify_new_container(workspace);
return workspace;
if (con->type == C_VIEW) {
view_close(con->sway_view);
} else {
container_for_each_descendant_dfs(con, container_close_func, NULL);
}
return parent;
}
struct sway_container *container_view_create(struct sway_container *sibling,
@ -231,23 +325,10 @@ struct sway_container *container_view_create(struct sway_container *sibling,
// Regular case, create as sibling of current container
container_add_sibling(sibling, swayc);
}
notify_new_container(swayc);
container_create_notify(swayc);
return swayc;
}
struct sway_container *container_set_layout(struct sway_container *container,
enum sway_container_layout layout) {
if (container->type == C_WORKSPACE) {
container->workspace_layout = layout;
if (layout == L_HORIZ || layout == L_VERT) {
container->layout = layout;
}
} else {
container->layout = layout;
}
return container;
}
void container_descendants(struct sway_container *root,
enum sway_container_type type,
void (*func)(struct sway_container *item, void *data), void *data) {

View file

@ -1,5 +1,4 @@
#define _POSIX_C_SOURCE 200809L
#include <assert.h>
#include <ctype.h>
#include <math.h>
#include <stdbool.h>
@ -52,6 +51,19 @@ static void output_layout_handle_change(struct wl_listener *listener,
arrange_windows(&root_container, -1, -1);
}
struct sway_container *container_set_layout(struct sway_container *container,
enum sway_container_layout layout) {
if (container->type == C_WORKSPACE) {
container->workspace_layout = layout;
if (layout == L_HORIZ || layout == L_VERT) {
container->layout = layout;
}
} else {
container->layout = layout;
}
return container;
}
void layout_init(void) {
root_container.id = 0; // normally assigned in new_swayc()
root_container.type = C_ROOT;
@ -107,32 +119,6 @@ void container_add_child(struct sway_container *parent,
child->parent = parent;
}
struct sway_container *container_reap_empty(struct sway_container *container) {
if (container == NULL) {
return NULL;
}
wlr_log(L_DEBUG, "Reaping %p %s '%s'", container,
container_type_to_str(container->type), container->name);
while (container->type != C_ROOT && container->type != C_OUTPUT
&& 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) {
struct sway_container *parent = child->parent;
for (int i = 0; i < parent->children->length; ++i) {
@ -167,7 +153,7 @@ void container_move_to(struct sway_container *container,
if (old_parent->children->length == 0) {
char *ws_name = workspace_next_name(old_parent->name);
struct sway_container *ws =
container_workspace_create(old_parent, ws_name);
workspace_create(old_parent, ws_name);
free(ws_name);
seat_set_focus(seat, ws);
}
@ -186,12 +172,22 @@ void container_move(struct sway_container *container,
}
enum sway_container_layout container_get_default_layout(
struct sway_container *output) {
struct sway_container *con) {
if (con->type != C_OUTPUT) {
con = container_parent(con, C_OUTPUT);
}
if (!sway_assert(con != NULL,
"container_get_default_layout must be called on an attached"
" container below the root container")) {
return 0;
}
if (config->default_layout != L_NONE) {
return config->default_layout;
} else if (config->default_orientation != L_NONE) {
return config->default_orientation;
} else if (output->width >= output->height) {
} else if (con->width >= con->height) {
return L_HORIZ;
} else {
return L_VERT;

View file

@ -1,51 +1,73 @@
#define _POSIX_C_SOURCE 200809L
#include <string.h>
#include <strings.h>
#include "sway/tree/container.h"
#include "sway/tree/layout.h"
#include "sway/output.h"
#include "sway/tree/output.h"
#include "sway/tree/workspace.h"
#include "log.h"
struct sway_container *container_output_destroy(struct sway_container *output) {
if (!sway_assert(output, "cannot destroy null output")) {
struct sway_container *output_create(
struct sway_output *sway_output) {
struct wlr_box size;
wlr_output_effective_resolution(sway_output->wlr_output, &size.width,
&size.height);
const char *name = sway_output->wlr_output->name;
char identifier[128];
output_get_identifier(identifier, sizeof(identifier), sway_output);
struct output_config *oc = NULL, *all = NULL;
for (int i = 0; i < config->output_configs->length; ++i) {
struct output_config *cur = config->output_configs->items[i];
if (strcasecmp(name, cur->name) == 0 ||
strcasecmp(identifier, cur->name) == 0) {
wlr_log(L_DEBUG, "Matched output config for %s", name);
oc = cur;
}
if (strcasecmp("*", cur->name) == 0) {
wlr_log(L_DEBUG, "Matched wildcard output config for %s", name);
all = cur;
}
if (oc && all) {
break;
}
}
if (!oc) {
oc = all;
}
if (oc && !oc->enabled) {
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);
struct sway_container *output = container_create(C_OUTPUT);
output->sway_output = sway_output;
output->name = strdup(name);
if (output->name == NULL) {
container_destroy(output);
return NULL;
}
apply_output_config(oc, output);
container_add_child(&root_container, output);
load_swaybars();
// Create workspace
char *ws_name = workspace_next_name(output->name);
wlr_log(L_DEBUG, "Creating default workspace %s", ws_name);
struct sway_container *ws = workspace_create(output, ws_name);
// Set each seat's focus if not already set
struct sway_seat *seat = NULL;
wl_list_for_each(seat, &input_manager->seats, link) {
if (!seat->has_focus) {
seat_set_focus(seat, ws);
}
}
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->scale.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;
free(ws_name);
container_create_notify(output);
return output;
}
struct sway_container *output_by_name(const char *name) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *output = root_container.children->items[i];
if (strcasecmp(output->name, name) == 0){
return output;
}
}
return NULL;
}

View file

@ -27,8 +27,7 @@ void view_destroy(struct sway_view *view) {
view_unmap(view);
}
container_view_destroy(view->swayc);
free(view);
container_destroy(view->swayc);
}
const char *view_get_title(struct sway_view *view) {
@ -78,16 +77,6 @@ void view_close(struct sway_view *view) {
}
}
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) {
for (int i = 0; i < root_container.children->length; ++i) {
struct sway_container *cont = root_container.children->items[i];
@ -160,10 +149,12 @@ void view_unmap(struct sway_view *view) {
view_damage_whole(view);
container_view_destroy(view->swayc);
struct sway_container *parent = container_destroy(view->swayc);
view->swayc = NULL;
view->surface = NULL;
arrange_windows(parent, -1, -1);
}
void view_update_position(struct sway_view *view, double ox, double oy) {

View file

@ -14,6 +14,58 @@
#include "log.h"
#include "util.h"
static struct sway_container *get_workspace_initial_output(const char *name) {
struct sway_container *parent;
// Search for workspace<->output pair
int e = config->workspace_outputs->length;
for (int i = 0; i < config->workspace_outputs->length; ++i) {
struct workspace_output *wso = config->workspace_outputs->items[i];
if (strcasecmp(wso->workspace, name) == 0) {
// Find output to use if it exists
e = root_container.children->length;
for (i = 0; i < e; ++i) {
parent = root_container.children->items[i];
if (strcmp(parent->name, wso->output) == 0) {
return parent;
}
}
break;
}
}
// Otherwise put it on the focused output
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
seat_get_focus_inactive(seat, &root_container);
parent = focus;
parent = container_parent(parent, C_OUTPUT);
return parent;
}
struct sway_container *workspace_create(struct sway_container *output,
const char *name) {
if (output == NULL) {
output = get_workspace_initial_output(name);
}
wlr_log(L_DEBUG, "Added workspace %s for output %s", name, output->name);
struct sway_container *workspace = container_create(C_WORKSPACE);
workspace->x = output->x;
workspace->y = output->y;
workspace->width = output->width;
workspace->height = output->height;
workspace->name = !name ? NULL : strdup(name);
workspace->prev_layout = L_NONE;
workspace->layout = container_get_default_layout(output);
workspace->workspace_layout = workspace->layout;
container_add_child(output, workspace);
container_sort_workspaces(output);
container_create_notify(workspace);
return workspace;
}
char *prev_workspace_name = NULL;
struct workspace_by_number_data {
int len;
@ -197,74 +249,6 @@ struct sway_container *workspace_by_name(const char *name) {
}
}
struct sway_container *workspace_create(const char *name) {
struct sway_container *parent;
// Search for workspace<->output pair
int i, e = config->workspace_outputs->length;
for (i = 0; i < e; ++i) {
struct workspace_output *wso = config->workspace_outputs->items[i];
if (strcasecmp(wso->workspace, name) == 0) {
// Find output to use if it exists
e = root_container.children->length;
for (i = 0; i < e; ++i) {
parent = root_container.children->items[i];
if (strcmp(parent->name, wso->output) == 0) {
return container_workspace_create(parent, name);
}
}
break;
}
}
// Otherwise create a new one
struct sway_seat *seat = input_manager_current_seat(input_manager);
struct sway_container *focus =
seat_get_focus_inactive(seat, &root_container);
parent = focus;
parent = container_parent(parent, C_OUTPUT);
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;
}
/**
* Get the previous or next workspace on the specified output. Wraps around at
* the end and beginning. If next is false, the previous workspace is returned,
@ -376,7 +360,9 @@ bool workspace_switch(struct sway_container *workspace) {
&& active_ws == workspace
&& prev_workspace_name) {
struct sway_container *new_ws = workspace_by_name(prev_workspace_name);
workspace = new_ws ? new_ws : workspace_create(prev_workspace_name);
workspace = new_ws ?
new_ws :
workspace_create(NULL, prev_workspace_name);
}
if (!prev_workspace_name || (strcmp(prev_workspace_name, active_ws->name)