From 148f59f3a670a7008bc6c2bc07712fd58b1f6e69 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 8 Aug 2015 17:44:51 -0400 Subject: [PATCH] Refactor in-memory tree --- sway/handlers.c | 5 +- sway/layout.c | 168 +++++++++++++++++++++++++++--------------------- sway/layout.h | 47 ++++++++++---- sway/list.c | 3 + 4 files changed, 133 insertions(+), 90 deletions(-) diff --git a/sway/handlers.c b/sway/handlers.c index af33f785..27087295 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -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)); } diff --git a/sway/layout.c b/sway/layout.c index e95ee423..f2fe4021 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -5,40 +5,37 @@ #include "log.h" #include "layout.h" -list_t *outputs; -wlc_handle focused_view; +swayc_t root_container; void arrange_windows() { + // TODO } void init_layout() { - outputs = create_list(); - focused_view = -1; + root_container.type = C_ROOT; + 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) { - int i; - for (i = 0; i < outputs->length; ++i) { - struct sway_container *c = outputs->items[i]; - if (c->output == output) { - return c; - } - } - return NULL; +void free_swayc(swayc_t *container) { + // NOTE: Does not handle moving children into a different container + list_free(container->children); + free(container); } -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; - } +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 { - struct sway_container *res; - if ((res = get_container_for_view_recurse(handle, index, child))) { + swayc_t *res; + if ((res = get_swayc_for_handle(handle, child))) { return res; } } @@ -46,77 +43,102 @@ struct sway_container *get_container_for_view_recurse(wlc_handle handle, int *in 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; - } +swayc_t *get_focused_container(swayc_t *parent) { + if (parent->focused == NULL) { + return parent; } - return NULL; + return get_focused_container(parent->focused); } 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 + 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; } - // 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); + 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 i; + for (i = 0; i < view->parent->children->length; ++i) { + if (view->parent->children->items[i] == view) { + list_del(view->parent->children, i); + break; + } + } - int index; - struct sway_container *container = get_container_for_view(view, &index); - list_del(container->children, index); + free_swayc(view); - wlc_view_focus(get_topmost(wlc_view_get_output(view), 0)); + // 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) { - return; + 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); } diff --git a/sway/layout.h b/sway/layout.h index 3d14252b..94e78a93 100644 --- a/sway/layout.h +++ b/sway/layout.h @@ -4,29 +4,48 @@ #include #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 diff --git a/sway/list.c b/sway/list.c index 120cfbcd..82d6c144 100644 --- a/sway/list.c +++ b/sway/list.c @@ -12,6 +12,9 @@ list_t *create_list() { } void list_free(list_t *list) { + if (list == NULL) { + return; + } free(list->items); free(list); }