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) { void handle_view_destroyed(wlc_handle view) {
destroy_view(view); destroy_view(get_swayc_for_handle(view, &root_container));
return true; return true;
} }
void handle_view_focus(wlc_handle view, bool focus) { void handle_view_focus(wlc_handle view, bool focus) {
printf("View focused\n");
wlc_view_set_state(view, WLC_BIT_ACTIVATED, focus); 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 "log.h"
#include "layout.h" #include "layout.h"
list_t *outputs; swayc_t root_container;
wlc_handle focused_view;
void arrange_windows() { void arrange_windows() {
// TODO
} }
void init_layout() { void init_layout() {
outputs = create_list(); root_container.type = C_ROOT;
focused_view = -1; root_container.layout = L_HORIZ; // TODO: Default layout
root_container.children = create_list();
root_container.handle = -1;
} }
struct sway_container *get_container(wlc_handle output, int *index) { 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; int i;
for (i = 0; i < outputs->length; ++i) { for (i = 0; i < parent->children->length; ++i) {
struct sway_container *c = outputs->items[i]; swayc_t *child = parent->children->items[i];
if (c->output == output) { if (child->handle == handle) {
return c; return child;
} else {
swayc_t *res;
if ((res = get_swayc_for_handle(handle, child))) {
return res;
}
} }
} }
return NULL; return NULL;
} }
struct sway_container *get_container_for_view_recurse(wlc_handle handle, int *index, struct sway_container *parent) { swayc_t *get_focused_container(swayc_t *parent) {
int j; if (parent->focused == NULL) {
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; return parent;
} }
} else { return get_focused_container(parent->focused);
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) { void add_view(wlc_handle view_handle) {
struct sway_container *container; swayc_t *parent = get_focused_container(&root_container);
int _; sway_log(L_DEBUG, "Adding new view %d under container %d", view_handle, (int)parent->type);
if (focused_view == -1) { // Add it to the output container while (parent->type == C_VIEW) {
sway_log(L_DEBUG, "Adding initial view for output", view_handle); parent = parent->parent;
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 swayc_t *view = calloc(1, sizeof(swayc_t));
struct sway_container *view = malloc(sizeof(struct sway_container)); view->layout = L_NONE;
view->layout = LAYOUT_IS_VIEW; view->handle = view_handle;
view->children = NULL; view->parent = parent;
view->output = view_handle; view->type = C_VIEW;
list_add(container->children, view); list_add(parent->children, view);
wlc_view_focus(view_handle); wlc_view_focus(view_handle);
arrange_windows(); arrange_windows();
} }
void destroy_view(wlc_handle view) { void destroy_view(swayc_t *view) {
sway_log(L_DEBUG, "Destroying view %d", view); sway_log(L_DEBUG, "Destroying container %p", view);
if (!view->parent) {
return;
}
int index; int i;
struct sway_container *container = get_container_for_view(view, &index); for (i = 0; i < view->parent->children->length; ++i) {
list_del(container->children, index); 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(); 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) { void add_output(wlc_handle output) {
struct sway_container *container = malloc(sizeof(struct sway_container)); sway_log(L_DEBUG, "Adding output %d", output);
// TODO: Get default layout from config const struct wlc_size* size = wlc_output_get_resolution(output);
container->output = output;
swayc_t *container = calloc(1, sizeof(swayc_t));
container->handle = output;
container->type = C_OUTPUT;
container->children = create_list(); container->children = create_list();
container->layout = LAYOUT_TILE_HORIZ; container->parent = &root_container;
list_add(outputs, 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) { void destroy_output(wlc_handle output) {
int index; sway_log(L_DEBUG, "Destroying output %d", output);
struct sway_container *c = get_container(output, &index); int i;
// TODO: Move all windows in this output somewhere else? for (i = 0; i < root_container.children->length; ++i) {
// I don't think this will ever be called unless we destroy the output ourselves swayc_t *c = root_container.children->items[i];
if (!c) { if (c->handle == output) {
list_del(root_container.children, i);
free_swayc(c);
return; 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 <wlc/wlc.h>
#include "list.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 { 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; list_t *children;
container_layout_t layout;
struct sway_container *parent; struct sway_container *parent;
struct sway_container *focused;
}; };
extern list_t *outputs; typedef struct sway_container swayc_t;
extern wlc_handle focused_view;
extern swayc_t root_container;
void init_layout(); void init_layout();
void add_output(wlc_handle output); void add_output(wlc_handle output);
void destroy_output(wlc_handle output); void destroy_output(wlc_handle output);
wlc_handle get_topmost(wlc_handle output, size_t offset); void destroy_view(swayc_t *view);
void destroy_view(wlc_handle view);
void add_view(wlc_handle 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 #endif

View file

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