Refactor in-memory tree

This commit is contained in:
Drew DeVault 2015-08-08 17:44:51 -04:00
parent 0427fddb5a
commit 148f59f3a6
4 changed files with 133 additions and 90 deletions

View file

@ -22,12 +22,11 @@ bool handle_view_created(wlc_handle view) {
}
void handle_view_destroyed(wlc_handle view) {
destroy_view(view);
destroy_view(get_swayc_for_handle(view, &root_container));
return true;
}
void handle_view_focus(wlc_handle view, bool focus) {
printf("View focused\n");
wlc_view_set_state(view, WLC_BIT_ACTIVATED, focus);
focused_view = view;
focus_view(get_swayc_for_handle(view, &root_container));
}

View file

@ -5,118 +5,140 @@
#include "log.h"
#include "layout.h"
list_t *outputs;
wlc_handle focused_view;
swayc_t root_container;
void arrange_windows() {
}
void init_layout() {
outputs = create_list();
focused_view = -1;
}
struct sway_container *get_container(wlc_handle output, int *index) {
int i;
for (i = 0; i < outputs->length; ++i) {
struct sway_container *c = outputs->items[i];
if (c->output == output) {
return c;
}
}
return NULL;
}
struct sway_container *get_container_for_view_recurse(wlc_handle handle, int *index, struct sway_container *parent) {
int j;
for (j = 0; j < parent->children->length; ++j) {
struct sway_container *child = parent->children->items[j];
if (child->layout == LAYOUT_IS_VIEW) {
if (child->output == handle) {
*index = j;
return parent;
}
} else {
struct sway_container *res;
if ((res = get_container_for_view_recurse(handle, index, child))) {
return res;
}
}
}
return NULL;
}
struct sway_container *get_container_for_view(wlc_handle handle, int *index) {
int i;
for (i = 0; i < outputs->length; ++i) {
struct sway_container *c = outputs->items[i];
struct sway_container *res;
if ((res = get_container_for_view_recurse(handle, index, c))) {
return res;
}
}
return NULL;
}
void add_view(wlc_handle view_handle) {
struct sway_container *container;
int _;
if (focused_view == -1) { // Add it to the output container
sway_log(L_DEBUG, "Adding initial view for output", view_handle);
wlc_handle output = wlc_get_focused_output();
container = get_container(output, &_);
} else {
sway_log(L_DEBUG, "Adding view %d to output", view_handle);
// TODO
}
// Create "container" for this view
struct sway_container *view = malloc(sizeof(struct sway_container));
view->layout = LAYOUT_IS_VIEW;
view->children = NULL;
view->output = view_handle;
list_add(container->children, view);
void init_layout() {
root_container.type = C_ROOT;
root_container.layout = L_HORIZ; // TODO: Default layout
root_container.children = create_list();
root_container.handle = -1;
}
void free_swayc(swayc_t *container) {
// NOTE: Does not handle moving children into a different container
list_free(container->children);
free(container);
}
swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) {
if (parent->children == NULL) {
return NULL;
}
int i;
for (i = 0; i < parent->children->length; ++i) {
swayc_t *child = parent->children->items[i];
if (child->handle == handle) {
return child;
} else {
swayc_t *res;
if ((res = get_swayc_for_handle(handle, child))) {
return res;
}
}
}
return NULL;
}
swayc_t *get_focused_container(swayc_t *parent) {
if (parent->focused == NULL) {
return parent;
}
return get_focused_container(parent->focused);
}
void add_view(wlc_handle view_handle) {
swayc_t *parent = get_focused_container(&root_container);
sway_log(L_DEBUG, "Adding new view %d under container %d", view_handle, (int)parent->type);
while (parent->type == C_VIEW) {
parent = parent->parent;
}
swayc_t *view = calloc(1, sizeof(swayc_t));
view->layout = L_NONE;
view->handle = view_handle;
view->parent = parent;
view->type = C_VIEW;
list_add(parent->children, view);
wlc_view_focus(view_handle);
arrange_windows();
}
void destroy_view(wlc_handle view) {
sway_log(L_DEBUG, "Destroying view %d", view);
void destroy_view(swayc_t *view) {
sway_log(L_DEBUG, "Destroying container %p", view);
if (!view->parent) {
return;
}
int index;
struct sway_container *container = get_container_for_view(view, &index);
list_del(container->children, index);
int i;
for (i = 0; i < view->parent->children->length; ++i) {
if (view->parent->children->items[i] == view) {
list_del(view->parent->children, i);
break;
}
}
wlc_view_focus(get_topmost(wlc_view_get_output(view), 0));
free_swayc(view);
// TODO: Focus some other window
arrange_windows();
}
void focus_view(swayc_t *view) {
if (view == &root_container) {
return;
}
view->parent->focused = view;
focus_view(view->parent);
}
void add_output(wlc_handle output) {
struct sway_container *container = malloc(sizeof(struct sway_container));
// TODO: Get default layout from config
container->output = output;
sway_log(L_DEBUG, "Adding output %d", output);
const struct wlc_size* size = wlc_output_get_resolution(output);
swayc_t *container = calloc(1, sizeof(swayc_t));
container->handle = output;
container->type = C_OUTPUT;
container->children = create_list();
container->layout = LAYOUT_TILE_HORIZ;
list_add(outputs, container);
container->parent = &root_container;
container->layout = L_NONE;
container->width = size->w;
container->height = size->h;
list_add(root_container.children, container);
swayc_t *workspace = calloc(1, sizeof(swayc_t));
workspace->handle = -1;
workspace->type = C_WORKSPACE;
workspace->parent = container;
workspace->width = size->w; // TODO: gaps
workspace->height = size->h;
workspace->layout = L_HORIZ; // TODO: Get default layout from config
workspace->children = create_list();
list_add(container->children, workspace);
if (root_container.focused == NULL) {
focus_view(workspace);
}
}
void destroy_output(wlc_handle output) {
int index;
struct sway_container *c = get_container(output, &index);
// TODO: Move all windows in this output somewhere else?
// I don't think this will ever be called unless we destroy the output ourselves
if (!c) {
sway_log(L_DEBUG, "Destroying output %d", output);
int i;
for (i = 0; i < root_container.children->length; ++i) {
swayc_t *c = root_container.children->items[i];
if (c->handle == output) {
list_del(root_container.children, i);
free_swayc(c);
return;
}
list_del(outputs, index);
}
wlc_handle get_topmost(wlc_handle output, size_t offset) {
size_t memb;
const wlc_handle *views = wlc_output_get_views(output, &memb);
return (memb > 0 ? views[(memb - 1 + offset) % memb] : 0);
}

View file

@ -4,29 +4,48 @@
#include <wlc/wlc.h>
#include "list.h"
typedef enum {
LAYOUT_IS_VIEW,
LAYOUT_TILE_HORIZ,
LAYOUT_TILE_VERT,
LAYOUT_TABBED,
LAYOUT_STACKED
} container_layout_t;
struct sway_container {
wlc_handle output;
wlc_handle handle;
enum {
C_ROOT,
C_OUTPUT,
C_WORKSPACE,
C_CONTAINER,
C_VIEW
} type;
enum {
L_NONE,
L_HORIZ,
L_VERT,
L_STACKED,
L_TABBED,
L_FLOATING
} layout;
// Not including borders or margins
int width, height;
char *name;
list_t *children;
container_layout_t layout;
struct sway_container *parent;
struct sway_container *focused;
};
extern list_t *outputs;
extern wlc_handle focused_view;
typedef struct sway_container swayc_t;
extern swayc_t root_container;
void init_layout();
void add_output(wlc_handle output);
void destroy_output(wlc_handle output);
wlc_handle get_topmost(wlc_handle output, size_t offset);
void destroy_view(wlc_handle view);
void destroy_view(swayc_t *view);
void add_view(wlc_handle view);
void focus_view(swayc_t *view);
swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent);
#endif

View file

@ -12,6 +12,9 @@ list_t *create_list() {
}
void list_free(list_t *list) {
if (list == NULL) {
return;
}
free(list->items);
free(list);
}