From b8cba33c013e580e6e793ec67a5442407d94a002 Mon Sep 17 00:00:00 2001 From: Taiyu Date: Fri, 14 Aug 2015 12:42:19 -0700 Subject: [PATCH] changed swayc related functions, cleaned up some functions, moved wlc related things into handlers --- sway/commands.c | 93 ++++++++++++---- sway/container.c | 205 ++++++++++++++++++++++++++++++++++- sway/container.h | 63 +++++++++++ sway/handlers.c | 84 +++++++++++---- sway/handlers.h | 3 + sway/layout.c | 273 ++++++++++++----------------------------------- sway/layout.h | 55 ++-------- sway/movement.c | 8 +- sway/workspace.c | 28 +---- sway/workspace.h | 2 + 10 files changed, 491 insertions(+), 323 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index cae35237..a0a95eef 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -228,33 +228,25 @@ static bool cmd_set(struct sway_config *config, int argc, char **argv) { } static bool _do_split(struct sway_config *config, int argc, char **argv, int layout) { - char *name = layout == L_VERT ? "splitv": - layout == L_HORIZ ? "splith":"split"; + char *name = layout == L_VERT ? "splitv" : + layout == L_HORIZ ? "splith" : "split"; if (!checkarg(argc, name, EXPECTED_EQUAL_TO, 0)) { return false; } swayc_t *focused = get_focused_container(&root_container); + + /* Case that focus is on an empty workspace. change its layout */ if (focused->type == C_WORKSPACE) { - sway_log(L_DEBUG, "Dont split workspaces"); - if (focused->children->length == 0) { - focused->layout = layout; - } + focused->layout = layout; + return true; + } + /* Case of no siblings. change parent layout */ + if (focused->parent->children->length == 1) { + focused->parent->layout = layout; return true; } - swayc_t *parent = focused->parent; - sway_log(L_DEBUG, "Splitting %p vertically with %p", parent, focused); - int index = remove_container_from_parent(parent, focused); - swayc_t *new_container = create_container(parent, -1); - new_container->layout = layout; - new_container->weight = focused->weight; - new_container->width = focused->width; - new_container->height = focused->height; - new_container->x = focused->x; - new_container->y = focused->y; - focused->weight = 1; - focused->parent = new_container; - list_insert(parent->children, index, new_container); - list_add(new_container->children, focused); + /* regular case where new split container is build around focused container */ + swayc_t *parent = new_container(focused, layout); focus_view(focused); arrange_windows(parent, -1, -1); return true; @@ -302,15 +294,72 @@ static bool cmd_workspace(struct sway_config *config, int argc, char **argv) { swayc_t *workspace = workspace_find_by_name(argv[0]); if (!workspace) { workspace = workspace_create(argv[0]); - } else sway_log(L_DEBUG, "workspace exists, all ok"); - + } workspace_switch(workspace); return true; } +/* XXX:DEBUG:XXX */ +static void container_log(const swayc_t *c) { + fprintf(stderr, "focus:%c|", + c == get_focused_container(&root_container) ? 'F' : //Focused + c == active_workspace ? 'W' : //active workspace + c == &root_container ? 'R' : //root + 'X');//not any others + fprintf(stderr,"(%p)",c); + fprintf(stderr,"(p:%p)",c->parent); + fprintf(stderr,"(f:%p)",c->focused); + fprintf(stderr,"Type:"); + fprintf(stderr, + c->type == C_ROOT ? "Root|" : + c->type == C_OUTPUT ? "Output|" : + c->type == C_WORKSPACE ? "Workspace|" : + c->type == C_CONTAINER ? "Container|" : + c->type == C_VIEW ? "View|" : + "Unknown|"); + fprintf(stderr,"layout:"); + fprintf(stderr, + c->layout == L_NONE ? "NONE|" : + c->layout == L_HORIZ ? "Horiz|": + c->layout == L_VERT ? "Vert|": + c->layout == L_STACKED ? "Stacked|": + c->layout == L_FLOATING ? "Floating|": + "Unknown|"); + fprintf(stderr, "w:%d|h:%d|", c->width, c->height); + fprintf(stderr, "x:%d|y:%d|", c->x, c->y); + fprintf(stderr, "vis:%c|", c->visible?'t':'f'); + fprintf(stderr, "wgt:%d|", c->weight); + fprintf(stderr, "name:%.16s|", c->name); + fprintf(stderr, "children:%d\n",c->children?c->children->length:0); +} +void layout_log(const swayc_t *c, int depth) { + int i; + int e = c->children?c->children->length:0; + for (i = 0; i < depth; ++i) fputc(' ', stderr); + container_log(c); + if (e) { + for (i = 0; i < depth; ++i) fputc(' ', stderr); + fprintf(stderr,"(\n"); + for (i = 0; i < e; ++i) { + layout_log(c->children->items[i], depth + 1); + } + for (i = 0; i < depth; ++i) fputc(' ', stderr); + fprintf(stderr,")\n"); + } +} +bool cmd_debug_print_layout(struct sway_config *config, int argc, char **argv) { + fprintf(stderr,"root:%p\nactive workspace:%p\n",&root_container, active_workspace); + layout_log(&root_container, 0); + return true; +} +/* XXX:DEBUG:XXX */ + /* Keep alphabetized */ static struct cmd_handler handlers[] = { { "bindsym", cmd_bindsym }, + //DEBUG + { "debug_print_layout", cmd_debug_print_layout }, + //DEBUG { "exec", cmd_exec }, { "exec_always", cmd_exec_always }, { "exit", cmd_exit }, diff --git a/sway/container.c b/sway/container.c index c637daca..1c17e92f 100644 --- a/sway/container.c +++ b/sway/container.c @@ -1,18 +1,213 @@ +#include +#include +#include #include "container.h" +#include "workspace.h" #include "layout.h" +#include "log.h" -void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { + +static swayc_t *new_swayc(enum swayc_types type) { + swayc_t *c = calloc(1, sizeof(swayc_t)); + c->handle = -1; + c->layout = L_NONE; + c->type = type; + c->weight = 1; + if (type != C_VIEW) { + c->children = create_list(); + } + return c; +} + +static void free_swayc(swayc_t *c) { + //TODO does not properly handle containers with children, + //TODO but functions that call this usually check for that + if (c->children) { + list_free(c->children); + } + if (c->parent) { + remove_child(c->parent, c); + } + free(c); +} + +/* New containers */ +static void add_output_widths(swayc_t *container, void *_width) { + int *width = _width; + if (container->type == C_OUTPUT) { + *width += container->width; + } +} + +swayc_t *new_output(wlc_handle handle) { + sway_log(L_DEBUG, "Added output %d", handle); + const struct wlc_size* size = wlc_output_get_resolution(handle); + + swayc_t *output = new_swayc(C_OUTPUT); + output->width = size->w; + output->height = size->h; + output->handle = handle; + + add_child(&root_container, output); + + //TODO something with this + int total_width = 0; + container_map(&root_container, add_output_widths, &total_width); + + //Create workspace + char *ws_name = workspace_next_name(); + new_workspace(output, ws_name); + free(ws_name); + + return output; +} + +swayc_t *new_workspace(swayc_t * output, const char *name) { + sway_log(L_DEBUG, "Added workspace %s for output %d", name, output->handle); + swayc_t *workspace = new_swayc(C_WORKSPACE); + + workspace->layout = L_HORIZ; // TODO:default layout + workspace->width = output->width; + workspace->height = output->height; + workspace->name = strdup(name); + workspace->visible = true; + + add_child(output, workspace); + return workspace; +} + +swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { + swayc_t *cont = new_swayc(C_CONTAINER); + + sway_log(L_DEBUG, "creating container %p around %p", cont, child); + + cont->layout = layout; + cont->width = child->width; + cont->height = child->height; + cont->x = child->x; + cont->y = child->y; + cont->visible = child->visible; + + swayc_t *parent = replace_child(child, cont); + if (parent) { + add_child(cont, child); + } + return cont; +} + +swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { + const uint32_t type = wlc_view_get_type(handle); + const char *title = wlc_view_get_title(handle); + /* Skip if unmanaged window */ + if ((type & WLC_BIT_OVERRIDE_REDIRECT) || (type & WLC_BIT_UNMANAGED) || + (type & WLC_BIT_POPUP) || (type & WLC_BIT_MODAL) || (type & WLC_BIT_SPLASH)) { + sway_log(L_DEBUG, "Leaving view %d:%s alone (unmanaged)", handle, title); + return NULL; + } + + swayc_t *view = new_swayc(C_VIEW); + sway_log(L_DEBUG, "Adding new view %d:%s:%d to container %p %d", + handle, title, type, sibling, sibling?sibling->type:0); + //Setup values + view->handle = handle; + view->name = strdup(title); + view->visible = true; + + //Case of focused workspace, just create as child of it + if (sibling->type == C_WORKSPACE) { + add_child(sibling, view); + } + //Regular case, create as sibling of current container + else { + add_sibling(sibling, view); + } + return view; +} + + +swayc_t *destroy_output(swayc_t *output) { + if (output->children->length == 0) { + //TODO move workspaces to other outputs + } + sway_log(L_DEBUG, "OUTPUT: Destroying output '%d'", output->handle); + free_swayc(output); + return &root_container; +} + +swayc_t *destroy_workspace(swayc_t *workspace) { + //TODO move containers to other workspaces? + //for now just dont delete + if (workspace->children->length == 0) { + sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); + swayc_t *parent = workspace->parent; + free_swayc(workspace); + return parent; + } + return NULL; +} + +swayc_t *destroy_container(swayc_t *container) { + while (container->children->length == 0 && container->type == C_CONTAINER) { + sway_log(L_DEBUG, "Container: Destroying container '%p'", container); + swayc_t *parent = container->parent; + free_swayc(container); + + if (parent->focused == container) { + parent->focused = NULL; + } + container = parent; + } + return container; +} + +swayc_t *destroy_view(swayc_t *view) { + if (view == NULL) { + sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); + return NULL; + } + sway_log(L_DEBUG, "Destroying view '%p'", view); + swayc_t *parent = view->parent; + free_swayc(view); + + if (parent->focused == view) { + parent->focused = NULL; + } + //Destroy empty containers + if (parent->type == C_CONTAINER) { + return destroy_container(parent); + } + return parent; +} + + +swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { + return NULL; + } + int i; + for (i = 0; i < container->children->length; ++i) { + swayc_t *child = container->children->items[i]; + if (test(child, data)) { + return child; + } else { + swayc_t *_ = find_container(child, test, data); + if (_) { + return _; + } + } + } + return NULL; +} + +void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), void *data) { + if (!container->children || !container->children->length) { return; } int i; for (i = 0; i < container->children->length; ++i) { swayc_t *child = container->children->items[i]; f(child, data); - - if (child->children) { - container_map(child, f, data); - } + container_map(child, f, data); } } diff --git a/sway/container.h b/sway/container.h index d853661c..a54e016a 100644 --- a/sway/container.h +++ b/sway/container.h @@ -1,8 +1,71 @@ #ifndef _SWAY_CONTAINER_H #define _SWAY_CONTAINER_H +#include +typedef struct sway_container swayc_t; #include "layout.h" +enum swayc_types{ + C_ROOT, + C_OUTPUT, + C_WORKSPACE, + C_CONTAINER, + C_VIEW, + //Keep last + C_TYPES, +}; + +enum swayc_layouts{ + L_NONE, + L_HORIZ, + L_VERT, + L_STACKED, + L_TABBED, + L_FLOATING, + //Keep last + L_LAYOUTS, +}; + +struct sway_container { + wlc_handle handle; + + enum swayc_types type; + + enum swayc_layouts layout; + + // Not including borders or margins + int width, height; + + int x, y; + + bool visible; + + int weight; + + char *name; + + list_t *children; + + struct sway_container *parent; + struct sway_container *focused; +}; + + +swayc_t *new_output(wlc_handle handle); +swayc_t *new_workspace(swayc_t * output, const char *name); +//Creates container Around child (parent child) -> (parent (container child)) +swayc_t *new_container(swayc_t *child, enum swayc_layouts layout); +//Creates view as a sibling of current focused container, or as child of a workspace +swayc_t *new_view(swayc_t *sibling, wlc_handle handle); + + +swayc_t *destroy_output(swayc_t *output); +//destroys workspace if empty and returns parent pointer, else returns NULL +swayc_t *destroy_workspace(swayc_t *workspace); +swayc_t *destroy_container(swayc_t *container); +swayc_t *destroy_view(swayc_t *view); + +swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); void container_map(swayc_t *, void (*f)(swayc_t *, void *), void *); #endif diff --git a/sway/handlers.c b/sway/handlers.c index 48c6cbf7..393a2181 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -9,14 +9,53 @@ #include "commands.h" #include "handlers.h" #include "stringop.h" +#include "workspace.h" + +static struct wlc_origin mouse_origin; + +static bool pointer_test(swayc_t *view, void *_origin) { + const struct wlc_origin *origin = _origin; + if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y + && origin->x < view->x + view->width && origin->y < view->y + view->height + && view->visible) { + return true; + } + return false; +} + +void focus_pointer(void) { + swayc_t *focused = find_container(&root_container, pointer_test, &mouse_origin); + if (focused) { + sway_log(L_DEBUG, "Switching focus to %p", focused); + unfocus_all(&root_container); + focus_view(focused); + } else { + focus_view(active_workspace); + } +} static bool handle_output_created(wlc_handle output) { - add_output(output); + swayc_t *op = new_output(output); + + //Switch to workspace if we need to + if (active_workspace == NULL) { + swayc_t *ws = op->children->items[0]; + workspace_switch(ws); + } return true; } static void handle_output_destroyed(wlc_handle output) { - destroy_output(output); + int i; + list_t *list = root_container.children; + for (i = 0; i < list->length; ++i) { + if (((swayc_t *)list->items[i])->handle == output) { + break; + } + } + if (i < list->length) { + destroy_output(list->items[i]); + } } static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { @@ -37,14 +76,33 @@ static void handle_output_focused(wlc_handle output, bool focus) { } } -static bool handle_view_created(wlc_handle view) { - add_view(view); +static bool handle_view_created(wlc_handle handle) { + swayc_t *container = get_focused_container(&root_container); + swayc_t *view = new_view(container, handle); + unfocus_all(&root_container); + if (view) { + focus_view(view); + arrange_windows(view->parent, -1, -1); + } else { //Unmanaged view + wlc_view_set_state(handle, WLC_BIT_ACTIVATED, true); + wlc_view_focus(handle); + } return true; } -static void handle_view_destroyed(wlc_handle view) { - sway_log(L_DEBUG, "Destroying window %d", view); - destroy_view(get_swayc_for_handle(view, &root_container)); +static void handle_view_destroyed(wlc_handle handle) { + sway_log(L_DEBUG, "Destroying window %d", handle); + swayc_t *view = get_swayc_for_handle(handle, &root_container); + swayc_t *parent; + swayc_t *focused = get_focused_container(&root_container); + + if (view) { + parent = destroy_view(view); + arrange_windows(parent, -1, -1); + } + if (!focused || focused == view) { + focus_pointer(); + } } static void handle_view_focus(wlc_handle view, bool focus) { @@ -121,18 +179,6 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier return cmd_success; } -bool pointer_test(swayc_t *view, void *_origin) { - const struct wlc_origin *origin = _origin; - if (view->type == C_VIEW && origin->x >= view->x && origin->y >= view->y - && origin->x < view->x + view->width && origin->y < view->y + view->height - && view->visible) { - return true; - } - return false; -} - -struct wlc_origin mouse_origin; - static bool handle_pointer_motion(wlc_handle view, uint32_t time, const struct wlc_origin *origin) { mouse_origin = *origin; if (!config->focus_follows_mouse) { diff --git a/sway/handlers.h b/sway/handlers.h index 798b3b50..b8b171c3 100644 --- a/sway/handlers.h +++ b/sway/handlers.h @@ -6,4 +6,7 @@ extern struct wlc_interface interface; +//set focus to current pointer location +void focus_pointer(void); + #endif diff --git a/sway/layout.c b/sway/layout.c index ccf29f34..0db4dc4d 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -9,25 +9,75 @@ swayc_t root_container; -swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { - if (!container->children) { +void init_layout(void) { + root_container.type = C_ROOT; + root_container.layout = L_NONE; + root_container.children = create_list(); + root_container.handle = -1; +} + +static int index_child(swayc_t *parent, swayc_t *child) { + int i; + for (i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + break; + } + } + return i; +} + +void add_child(swayc_t *parent, swayc_t *child) { + sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, + child->width, child->height, parent, parent->type, parent->width, parent->height); + list_add(parent->children, child); + child->parent = parent; + if(parent->focused == NULL) { + parent->focused = child; + } +} + +swayc_t *add_sibling(swayc_t *sibling, swayc_t *child) { + swayc_t *parent = sibling->parent; + int i = index_child(parent, sibling); + if (i == parent->children->length) { + --i; + } + list_insert(parent->children, i+1, child); + child->parent = parent; + return child->parent; +} + +swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { + swayc_t *parent = child->parent; + if (parent == NULL) { return NULL; } + int i = index_child(parent, child); + parent->children->items[i] = new_child; + new_child->parent = child->parent; + + if (child->parent->focused == child) { + child->parent->focused = new_child; + } + child->parent = NULL; + return parent; +} + +swayc_t *remove_child(swayc_t *parent, swayc_t *child) { int i; - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - if (test(child, data)) { - return child; - } else { - swayc_t *_ = find_container(child, test, data); - if (_) { - return _; - } + for (i = 0; i < parent->children->length; ++i) { + if (parent->children->items[i] == child) { + list_del(parent->children, i); + break; } } - return NULL; + if (parent->focused == child) { + parent->focused = NULL; + } + return parent; } + void arrange_windows(swayc_t *container, int width, int height) { int i; if (width == -1 || height == -1) { @@ -131,25 +181,6 @@ void arrange_windows(swayc_t *container, int width, int height) { } } -void init_layout(void) { - root_container.type = C_ROOT; - root_container.layout = L_NONE; - 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 - if (container->parent) { - remove_container_from_parent(container->parent, container); - } - list_free(container->children); - if (container->name) { - free(container->name); - } - free(container); -} - swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { if (parent->children == NULL) { return NULL; @@ -176,99 +207,6 @@ swayc_t *get_focused_container(swayc_t *parent) { return get_focused_container(parent->focused); } -void add_view(wlc_handle view_handle) { - const uint32_t type = wlc_view_get_type(view_handle); - const char *title = wlc_view_get_title(view_handle); - if ((type & WLC_BIT_OVERRIDE_REDIRECT) || (type & WLC_BIT_UNMANAGED) || (type & - WLC_BIT_POPUP) || (type & WLC_BIT_MODAL) || (type & WLC_BIT_SPLASH)) { - sway_log(L_DEBUG, "Leaving view %d:%s alone (unmanaged)", view_handle, title); - unfocus_all(&root_container); - wlc_view_set_state(view_handle, WLC_BIT_ACTIVATED, true); - wlc_view_focus(view_handle); - return; - } - - swayc_t *parent = get_focused_container(&root_container); - sway_log(L_DEBUG, "Adding new view %d:%s:%d under container %p %d", view_handle, title, type, parent, parent->type); - - while (parent->type == C_VIEW) { - parent = parent->parent; - } - - swayc_t *view = calloc(1, sizeof(swayc_t)); - view->weight = 1; - view->layout = L_NONE; - view->handle = view_handle; - view->parent = parent; - view->type = C_VIEW; - view->visible = true; - if (title) { - view->name = malloc(strlen(title) + 1); - strcpy(view->name, title); - } - add_child(parent, view); - - unfocus_all(&root_container); - focus_view(view); - - arrange_windows(parent, -1, -1); -} - -int remove_container_from_parent(swayc_t *parent, swayc_t *container) { - int i; - for (i = 0; i < parent->children->length; ++i) { - if (parent->children->items[i] == container) { - list_del(parent->children, i); - break; - } - } - - if (parent->focused == container) { - parent->focused = NULL; - } - - return i; -} - -void destroy_view(swayc_t *view) { - if (view == NULL) { - sway_log(L_DEBUG, "Warning: NULL passed into destroy_view"); - return; - } - sway_log(L_DEBUG, "Destroying container %p", view); - swayc_t *parent = view->parent; - if (!parent) { - return; - } - - int i; - for (i = 0; i < parent->children->length; ++i) { - if (parent->children->items[i] == view) { - list_del(parent->children, i); - break; - } - } - - free_swayc(view); - - if (parent->focused == view) { - parent->focused = NULL; - } - - unfocus_all(&root_container); - if (parent->children->length != 0) { - focus_view(parent->children->items[0]); - } else { - focus_view(parent); - } - - arrange_windows(parent, -1, -1); - - if (parent->children->length == 0 && parent->type == C_CONTAINER) { - destroy_view(parent); - } -} - void unfocus_all(swayc_t *container) { if (container->children == NULL) { return; @@ -285,85 +223,16 @@ void unfocus_all(swayc_t *container) { } void focus_view(swayc_t *view) { - sway_log(L_DEBUG, "Setting focus for %p", view); - if (view == &root_container) { - // Propegate wayland focus down - swayc_t *child = view->focused; - while (child && child->type != C_VIEW) { - child = child->focused; - } - if (child) { - wlc_view_set_state(child->handle, WLC_BIT_ACTIVATED, true); - wlc_view_focus(child->handle); - } - return; - } - view->parent->focused = view; - focus_view(view->parent); -} - -void add_child(swayc_t *parent, swayc_t *child) { - sway_log(L_DEBUG, "Adding %p (%d, %dx%d) to %p (%d, %dx%d)", child, child->type, - child->width, child->height, parent, parent->type, parent->width, parent->height); - list_add(parent->children, child); -} - -swayc_t *create_container(swayc_t *parent, wlc_handle handle) { - swayc_t *c = calloc(1, sizeof(swayc_t)); - c->weight = 1; - c->handle = handle; - c->parent = parent; - c->layout = L_NONE; - c->type = C_CONTAINER; - c->children = create_list(); - return c; -} - -void add_output_widths(swayc_t *container, void *_width) { - int *width = _width; - if (container->type == C_OUTPUT) { - *width += container->width; + sway_log(L_DEBUG, "Setting focus to %p", view); + if (view->type == C_VIEW) { + wlc_view_set_state(view->handle, WLC_BIT_ACTIVATED, true); + wlc_view_bring_to_front(view->handle); + wlc_view_focus(view->handle); } -} - -void add_output(wlc_handle output) { - sway_log(L_DEBUG, "Adding output %d", output); - const struct wlc_size* size = wlc_output_get_resolution(output); - - swayc_t *container = create_container(&root_container, output); - container->type = C_OUTPUT; - container->width = size->w; - container->height = size->h; - add_child(&root_container, container); - - int total_width = 0; - container_map(&root_container, add_output_widths, &total_width); - - swayc_t *workspace = create_container(container, -1); - workspace->type = C_WORKSPACE; - workspace->name = workspace_next_name(); - workspace->width = size->w; // TODO: gaps - workspace->height = size->h; - workspace->layout = L_HORIZ; // TODO: Get default layout from config - add_child(container, workspace); - sway_log(L_DEBUG, "Added workspace %s for output %d", workspace->name, output); - - if (root_container.focused == NULL) { - workspace_switch(workspace); - unfocus_all(&root_container); - focus_view(workspace); + // Propagete focus up + while (view != &root_container) { + view->parent->focused = view; + view = view->parent; } } -void destroy_output(wlc_handle output) { - 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; - } - } -} diff --git a/sway/layout.h b/sway/layout.h index b4769e08..a136f917 100644 --- a/sway/layout.h +++ b/sway/layout.h @@ -3,62 +3,23 @@ #include #include "list.h" - -struct sway_container { - 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; - - int x, y; - - bool visible; - - int weight; - - char *name; - - list_t *children; - - struct sway_container *parent; - struct sway_container *focused; -}; - -typedef struct sway_container swayc_t; +#include "container.h" extern swayc_t root_container; void init_layout(void); + void add_child(swayc_t *parent, swayc_t *child); -void add_output(wlc_handle output); -void destroy_output(wlc_handle output); -void destroy_view(swayc_t *view); -void add_view(wlc_handle view); +//Returns parent container wihch needs to be rearranged. +swayc_t *add_sibling(swayc_t *sibling, swayc_t *child); +swayc_t *replace_child(swayc_t *child, swayc_t *new_child); +swayc_t *remove_child(swayc_t *parent, swayc_t *child); + void unfocus_all(swayc_t *container); void focus_view(swayc_t *view); void arrange_windows(swayc_t *container, int width, int height); -swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data); swayc_t *get_focused_container(swayc_t *parent); -int remove_container_from_parent(swayc_t *parent, swayc_t *container); -swayc_t *create_container(swayc_t *parent, wlc_handle handle); -void free_swayc(swayc_t *container); + swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); #endif diff --git a/sway/movement.c b/sway/movement.c index 166e6508..de987679 100644 --- a/sway/movement.c +++ b/sway/movement.c @@ -10,14 +10,12 @@ bool move_focus(enum movement_direction direction) { swayc_t *parent = current->parent; if (direction == MOVE_PARENT) { - current = parent; - parent = parent->parent; - if (parent->type == C_ROOT) { + if (parent->type == C_OUTPUT) { sway_log(L_DEBUG, "Focus cannot move to parent"); return false; } else { - sway_log(L_DEBUG, "Moving focus away from %p", current); - unfocus_all(parent); + sway_log(L_DEBUG, "Moving focus away from %p to %p", current, parent); + unfocus_all(parent->parent); focus_view(parent); return true; } diff --git a/sway/workspace.c b/sway/workspace.c index 906d0c5d..88596dfe 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -6,6 +6,7 @@ #include "list.h" #include "log.h" #include "container.h" +#include "handlers.h" #include "config.h" #include "stringop.h" @@ -71,16 +72,7 @@ swayc_t *workspace_create(const char* name) { while(parent->type != C_OUTPUT) { parent = parent->parent; } - - swayc_t *workspace = create_container(parent, -1); - workspace->type = C_WORKSPACE; - workspace->name = strdup(name); - workspace->width = parent->width; - workspace->height = parent->height; - workspace->layout = L_HORIZ; // todo: thing - - add_child(parent, workspace); - return workspace; + return new_workspace(parent, name); } bool workspace_by_name(swayc_t *view, void *data) { @@ -88,23 +80,13 @@ bool workspace_by_name(swayc_t *view, void *data) { (strcasecmp(view->name, (char *) data) == 0); } -bool workspace_destroy(swayc_t *workspace) { - //Dont destroy if there are children - if (workspace->children->length) { - return false; - } - sway_log(L_DEBUG, "Workspace: Destroying workspace '%s'", workspace->name); - free_swayc(workspace); - return true; -} - void set_mask(swayc_t *view, void *data) { uint32_t *p = data; if(view->type == C_VIEW) { wlc_view_set_mask(view->handle, *p); - view->visible = (*p == 2); } + view->visible = (*p == 2); } swayc_t *workspace_find_by_name(const char* name) { @@ -123,9 +105,9 @@ void workspace_switch(swayc_t *workspace) { container_map(workspace, set_mask, &mask); wlc_output_set_mask(wlc_get_focused_output(), 2); - unfocus_all(active_workspace); + unfocus_all(&root_container); focus_view(workspace); - workspace_destroy(active_workspace); + destroy_workspace(active_workspace); } active_workspace = workspace; } diff --git a/sway/workspace.h b/sway/workspace.h index 19f0d4c1..523ce633 100644 --- a/sway/workspace.h +++ b/sway/workspace.h @@ -5,6 +5,8 @@ #include "list.h" #include "layout.h" +extern swayc_t *active_workspace; + char *workspace_next_name(void); swayc_t *workspace_create(const char*); swayc_t *workspace_find_by_name(const char*);