From b93f0686110274a29ea012476f2c0d17968fb1c1 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 16:12:35 -0700 Subject: [PATCH 1/5] proper view ordering --- include/container.h | 1 + include/layout.h | 1 - sway/container.c | 48 +++-- sway/handlers.c | 12 +- sway/layout.c | 413 ++++++++++++++++++++++++-------------------- sway/log.c | 3 +- 6 files changed, 269 insertions(+), 209 deletions(-) diff --git a/include/container.h b/include/container.h index fd621490d..66d8d81d5 100644 --- a/include/container.h +++ b/include/container.h @@ -82,6 +82,7 @@ swayc_t *destroy_view(swayc_t *view); swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); +swayc_t *swayc_by_handle(wlc_handle handle); 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 *); diff --git a/include/layout.h b/include/layout.h index 75e72d2fe..5d1f11acd 100644 --- a/include/layout.h +++ b/include/layout.h @@ -26,7 +26,6 @@ void focus_view(swayc_t *view); void focus_view_for(swayc_t *ancestor, swayc_t *container); swayc_t *get_focused_container(swayc_t *parent); -swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent); swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir); #endif diff --git a/sway/container.c b/sway/container.c index 7ccc2e098..054e1e49d 100644 --- a/sway/container.c +++ b/sway/container.c @@ -11,11 +11,17 @@ #define ASSERT_NONNULL(PTR) \ sway_assert (PTR, "%s: " #PTR "must be non-null", __func__) -static swayc_t *new_swayc(enum swayc_types type) { +static swayc_t *new_swayc(enum swayc_types type, wlc_handle handle) { swayc_t *c = calloc(1, sizeof(swayc_t)); - c->handle = -1; + if (handle > 0) { + c->handle = handle; + wlc_handle_set_user_data(handle, c); + } else { + c->handle = 0; + } c->layout = L_NONE; c->type = type; + c->gaps = 0; if (type != C_VIEW) { c->children = create_list(); } @@ -26,6 +32,9 @@ static void free_swayc(swayc_t *cont) { if (!ASSERT_NONNULL(cont)) { return; } + if (cont->handle > 0) { + wlc_handle_set_user_data(cont->handle, 0); + } // TODO does not properly handle containers with children, // TODO but functions that call this usually check for that if (cont->children) { @@ -58,7 +67,7 @@ static void free_swayc(swayc_t *cont) { // New containers static bool workspace_test(swayc_t *view, void *name) { - return strcasecmp(view->name, (char *)name) == 0; + return strcasecmp(view->name, name) == 0; } swayc_t *new_output(wlc_handle handle) { @@ -66,12 +75,10 @@ swayc_t *new_output(wlc_handle handle) { const char *name = wlc_output_get_name(handle); sway_log(L_DEBUG, "Added output %lu:%s", handle, name); - swayc_t *output = new_swayc(C_OUTPUT); + swayc_t *output = new_swayc(C_OUTPUT, handle); output->width = size->w; output->height = size->h; - output->handle = handle; output->name = name ? strdup(name) : NULL; - output->gaps = config->gaps_outer + config->gaps_inner / 2; add_child(&root_container, output); @@ -112,13 +119,14 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { return NULL; } sway_log(L_DEBUG, "Added workspace %s for output %u", name, (unsigned int)output->handle); - swayc_t *workspace = new_swayc(C_WORKSPACE); + swayc_t *workspace = new_swayc(C_WORKSPACE, 0); workspace->layout = L_HORIZ; // TODO: default layout workspace->x = output->x; workspace->y = output->y; workspace->width = output->width; workspace->height = output->height; + workspace->gaps = config->gaps_outer; workspace->name = strdup(name); workspace->visible = true; workspace->floating = create_list(); @@ -131,7 +139,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { if (!ASSERT_NONNULL(child)) { return NULL; } - swayc_t *cont = new_swayc(C_CONTAINER); + swayc_t *cont = new_swayc(C_CONTAINER, 0); sway_log(L_DEBUG, "creating container %p around %p", cont, child); @@ -177,11 +185,10 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { return NULL; } const char *title = wlc_view_get_title(handle); - swayc_t *view = new_swayc(C_VIEW); + swayc_t *view = new_swayc(C_VIEW, handle); sway_log(L_DEBUG, "Adding new view %lu:%s to container %p %d", handle, title, sibling, sibling ? sibling->type : 0); // Setup values - view->handle = handle; view->name = title ? strdup(title) : NULL; view->visible = true; view->is_focused = true; @@ -208,11 +215,10 @@ swayc_t *new_view(swayc_t *sibling, wlc_handle handle) { swayc_t *new_floating_view(wlc_handle handle) { const char *title = wlc_view_get_title(handle); - swayc_t *view = new_swayc(C_VIEW); + swayc_t *view = new_swayc(C_VIEW, handle); sway_log(L_DEBUG, "Adding new view %lu:%x:%s as a floating view", handle, wlc_view_get_type(handle), title); // Setup values - view->handle = handle; view->name = title ? strdup(title) : NULL; view->visible = true; @@ -241,7 +247,8 @@ swayc_t *new_floating_view(wlc_handle handle) { // Destroy container -swayc_t *destroy_output(swayc_t *output) { +#define DESTROY_FUNC __attribute__((nonnull)) swayc_t * +DESTROY_FUNC destroy_output(swayc_t *output) { if (!ASSERT_NONNULL(output)) { return NULL; } @@ -253,7 +260,7 @@ swayc_t *destroy_output(swayc_t *output) { return &root_container; } -swayc_t *destroy_workspace(swayc_t *workspace) { +DESTROY_FUNC destroy_workspace(swayc_t *workspace) { if (!ASSERT_NONNULL(workspace)) { return NULL; } @@ -276,7 +283,7 @@ swayc_t *destroy_workspace(swayc_t *workspace) { return NULL; } -swayc_t *destroy_container(swayc_t *container) { +DESTROY_FUNC destroy_container(swayc_t *container) { if (!ASSERT_NONNULL(container)) { return NULL; } @@ -289,7 +296,7 @@ swayc_t *destroy_container(swayc_t *container) { return container; } -swayc_t *destroy_view(swayc_t *view) { +DESTROY_FUNC destroy_view(swayc_t *view) { if (!ASSERT_NONNULL(view)) { return NULL; } @@ -303,6 +310,7 @@ swayc_t *destroy_view(swayc_t *view) { } return parent; } +#undef DESTROY_FUNC // Container lookup @@ -332,6 +340,11 @@ swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts layout) { return container; } +swayc_t *swayc_by_handle(wlc_handle handle) { + return wlc_handle_get_user_data(handle); +} + + swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { return NULL; @@ -398,10 +411,11 @@ void reset_gaps(swayc_t *view, void *data) { if (!ASSERT_NONNULL(view)) { return; } - if (view->type == C_OUTPUT) { + if (view->type == C_WORKSPACE) { view->gaps = config->gaps_outer; } if (view->type == C_VIEW) { view->gaps = config->gaps_inner; } } + diff --git a/sway/handlers.c b/sway/handlers.c index 79628fe5c..85c500be5 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -113,7 +113,7 @@ static void handle_output_destroyed(wlc_handle output) { static void handle_output_resolution_change(wlc_handle output, const struct wlc_size *from, const struct wlc_size *to) { sway_log(L_DEBUG, "Output %u resolution changed to %d x %d", (unsigned int)output, to->w, to->h); - swayc_t *c = get_swayc_for_handle(output, &root_container); + swayc_t *c = swayc_by_handle(output); if (!c) return; c->width = to->w; c->height = to->h; @@ -121,7 +121,7 @@ static void handle_output_resolution_change(wlc_handle output, const struct wlc_ } static void handle_output_focused(wlc_handle output, bool focus) { - swayc_t *c = get_swayc_for_handle(output, &root_container); + swayc_t *c = swayc_by_handle(output); // if for some reason this output doesnt exist, create it. if (!c) { handle_output_created(output); @@ -139,7 +139,7 @@ static bool handle_view_created(wlc_handle handle) { // Get parent container, to add view in if (parent) { - focused = get_swayc_for_handle(parent, &root_container); + focused = swayc_by_handle(parent); } if (!focused || focused->type == C_OUTPUT) { focused = get_focused_container(&root_container); @@ -196,7 +196,7 @@ static bool handle_view_created(wlc_handle handle) { static void handle_view_destroyed(wlc_handle handle) { sway_log(L_DEBUG, "Destroying window %lu", handle); - swayc_t *view = get_swayc_for_handle(handle, &root_container); + swayc_t *view = swayc_by_handle(handle); switch (wlc_view_get_type(handle)) { // regular view created regularly @@ -230,7 +230,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo // If the view is floating, then apply the geometry. // Otherwise save the desired width/height for the view. // This will not do anything for the time being as WLC improperly sends geometry requests - swayc_t *view = get_swayc_for_handle(handle, &root_container); + swayc_t *view = swayc_by_handle(handle); if (view) { view->desired_width = geometry->size.w; view->desired_height = geometry->size.h; @@ -246,7 +246,7 @@ static void handle_view_geometry_request(wlc_handle handle, const struct wlc_geo } static void handle_view_state_request(wlc_handle view, enum wlc_view_state_bit state, bool toggle) { - swayc_t *c = get_swayc_for_handle(view, &root_container); + swayc_t *c = swayc_by_handle(view); switch (state) { case WLC_BIT_FULLSCREEN: // i3 just lets it become fullscreen diff --git a/sway/layout.c b/sway/layout.c index 8c011fdb5..3cd716e95 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -18,6 +18,8 @@ void init_layout(void) { root_container.handle = -1; } +// Children of container functions + static int index_child(swayc_t *parent, swayc_t *child) { int i; for (i = 0; i < parent->children->length; ++i) { @@ -108,211 +110,254 @@ swayc_t *remove_child(swayc_t *child) { return parent; } +// Fitting functions +#define FIT_FUNC __attribute__((nonnull)) static void -void arrange_windows(swayc_t *container, int width, int height) { - int i; - if (width == -1 || height == -1) { - sway_log(L_DEBUG, "Arranging layout for %p", container); - width = container->width; - height = container->height; - } - - int x = 0, y = 0; - switch (container->type) { - case C_ROOT: - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, "Arranging output at %d", x); - child->x = x; - child->y = y; - arrange_windows(child, -1, -1); - // Removed for now because wlc works with relative positions - // Addition can be reconsidered once wlc positions are changed - // x += child->width; - } - return; - case C_OUTPUT: - container->width = width; - container->height = height; - // These lines make x/y negative and result in stuff glitching out - // Their addition can be reconsidered once wlc positions are changed - // x -= container->x; - // y -= container->y; - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - child->x = x + container->gaps; - child->y = y + container->gaps; - child->width = width - container->gaps * 2; - child->height = height - container->gaps * 2; - sway_log(L_DEBUG, "Arranging workspace #%d at %d, %d", i, child->x, child->y); - arrange_windows(child, -1, -1); - } - return; - case C_VIEW: - { - struct wlc_geometry geometry = { +FIT_FUNC _fit_view(swayc_t *view) { + sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view, + view->width, view->height, view->x, view->y); + struct wlc_geometry geo; + if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { + swayc_t *op = swayc_parent_by_type(view, C_OUTPUT); + geo = (struct wlc_geometry){ + .origin = { .x = 0, .y = 0 }, + .size = { .w = op->width, .h = op->height } + }; + } else { + if (view->is_floating) { + geo = (struct wlc_geometry){ .origin = { - .x = container->x + container->gaps / 2, - .y = container->y + container->gaps / 2 + .x = view->x, + .y = view->y, }, - .size = { - .w = width - container->gaps, - .h = height - container->gaps + .size = { + .w = view->width, + .h = view->height, } }; - if (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) { - swayc_t *parent = swayc_parent_by_type(container, C_OUTPUT); - geometry.origin.x = 0; - geometry.origin.y = 0; - geometry.size.w = parent->width; - geometry.size.h = parent->height; - wlc_view_set_geometry(container->handle, 0, &geometry); - wlc_view_bring_to_front(container->handle); - } else { - wlc_view_set_geometry(container->handle, 0, &geometry); - container->width = width; - container->height = height; + } else { + geo = (struct wlc_geometry){ + .origin = { + .x = view->x + view->gaps / 2, + .y = view->y + view->gaps / 2, + }, + .size = { + .w = view->width - view->gaps, + .h = view->height - view->gaps + } + }; + } + } + wlc_view_set_geometry(view->handle, 0, &geo); +} + +FIT_FUNC _fit_container(swayc_t *container) { + sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, container, + container->width, container->height, container->x, container->y); + swayc_t **child = (swayc_t **)container->children->items; + int i, len = container->children->length; + // geometry + int x = container->x; + int y = container->y; + int w = container->width; + int h = container->height; + // scaling + double s = 0; + switch (container->layout) { + default: + case L_HORIZ: + // Find scaling amount required to fit children in parent + for (i = 0; i < len; ++i, ++child) { + int *prev_w = &(*child)->width; + if (*prev_w <= 0) { + *prev_w = w / (len > 1 ? len - 1 : 1); } - sway_log(L_DEBUG, "Set view to %d x %d @ %d, %d", geometry.size.w, geometry.size.h, - geometry.origin.x, geometry.origin.y); + s += *prev_w; + } + sway_log(L_DEBUG,"s:%f",s); + if (s < 0.001) { + return; + } + s = w / s; + child = (swayc_t **)container->children->items; + for (i = 0; i < len; ++i, ++child) { + // Set geometry + (*child)->x = x; + (*child)->y = y; + // Scale width to fit in container + (*child)->width *= s; + (*child)->height = h; + // Increment x offset + x += (*child)->width; + // Recursibly resize children, depending on its type + ((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child); } return; - default: - container->width = width; - container->height = height; - break; - } - x = y = 0; - double scale = 0; - switch (container->layout) { - case L_HORIZ: - default: - // Calculate total width - for (i = 0; i < container->children->length; ++i) { - int *old_width = &((swayc_t *)container->children->items[i])->width; - if (*old_width <= 0) { - if (container->children->length > 1) { - *old_width = width / (container->children->length - 1); - } else { - *old_width = width; - } - } - scale += *old_width; - } - // Resize windows - if (scale > 0.1) { - scale = width / scale; - sway_log(L_DEBUG, "Arranging %p horizontally", container); - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, width, scale); - child->x = x + container->x; - child->y = y + container->y; - arrange_windows(child, child->width * scale, height); - x += child->width; - } - } - break; case L_VERT: - // Calculate total height - for (i = 0; i < container->children->length; ++i) { - int *old_height = &((swayc_t *)container->children->items[i])->height; - if (*old_height <= 0) { - if (container->children->length > 1) { - *old_height = height / (container->children->length - 1); - } else { - *old_height = height; - } + // Find scaling amount required to fit children in parent + for (i = 0; i < len; ++i, ++child) { + int *prev_h = &(*child)->height; + if (*prev_h <= 0) { + *prev_h = h / (len > 1 ? len - 1 : 1); } - scale += *old_height; + s += *prev_h; } - // Resize - if (scale > 0.1) { - scale = height / scale; - sway_log(L_DEBUG, "Arranging %p vertically", container); - for (i = 0; i < container->children->length; ++i) { - swayc_t *child = container->children->items[i]; - sway_log(L_DEBUG, "Calculating arrangement for %p:%d (will scale %d by %f)", child, child->type, height, scale); - child->x = x + container->x; - child->y = y + container->y; - arrange_windows(child, width, child->height * scale); - y += child->height; - } + if (s < 0.001) { + return; } - break; + s = h / s; + child = (swayc_t **)container->children->items; + for (i = 0; i < len; ++i, ++child) { + // Set geometry + (*child)->x = x; + (*child)->y = y; + // Scale height to fit in container + (*child)->height *= s; + (*child)->width = w; + // Increment y offset + y += (*child)->height; + // Recursibly resize children, depending on its type + ((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child); + } + return; + } +} + +FIT_FUNC _fit_workspace(swayc_t *workspace) { + workspace->x += workspace->gaps; + workspace->y += workspace->gaps; + workspace->width -= workspace->gaps * 2; + workspace->height -= workspace->gaps * 2; + sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, workspace, + workspace->width, workspace->height, workspace->x,workspace->y); + // workspace is treated same as container for tiling + _fit_container(workspace); + // Handle floating containers + swayc_t **child = (swayc_t **)workspace->floating->items; + int i, len = workspace->floating->length; + for (i = 0; i < len; ++i, ++child) { + // Fit floating depending on view + ((*child)->type == C_VIEW ? _fit_view : _fit_container)(*child); + } +} + +FIT_FUNC _fit_output(swayc_t *output) { + sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, output, output->width, + output->height, output->x,output->y); + swayc_t **child = (swayc_t **)output->children->items; + int i, len = output->children->length; + int x = output->x; + int y = output->y; + int w = output->width; + int h = output->height; + for (i = 0; i < len; ++i, ++child) { + // Set geometry with gaps + (*child)->x = x; + (*child)->y = y; + (*child)->width = w; + (*child)->height = h; + // recursivly fit children + _fit_workspace(*child); + } +} + +FIT_FUNC _fit_root(swayc_t *root) { + sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, root, root->width, + root->height, root->x,root->y); + swayc_t **child = (swayc_t **)root->children->items; + int i, len = root->children->length; + for (i = 0; i < len; ++i, ++child) { + (*child)->x = 0; + (*child)->y = 0; + _fit_output(*child); + } +} + +FIT_FUNC fit_children_in(swayc_t *swayc) { + switch (swayc->type) { + case C_ROOT: _fit_root(swayc); return; + case C_WORKSPACE: swayc = swayc->parent; + case C_OUTPUT: _fit_output(swayc); return; + case C_VIEW: swayc = swayc->parent; + case C_CONTAINER: _fit_container(swayc); return; + default: sway_assert(false, "%s: invalid type", __func__); + } +} +#undef FIT_FUNC + +__attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_handle top) { + // return handle + if (swayc->type == C_VIEW) { + return swayc->handle; + } + // return if no focus + if (swayc->focused == NULL) { + return 0; } - // Arrage floating layouts for workspaces last - if (container->type == C_WORKSPACE) { - for (i = 0; i < container->floating->length; ++i) { - swayc_t *view = container->floating->items[i]; - if (view->type == C_VIEW) { - // Set the geometry - struct wlc_geometry geometry = { - .origin = { - .x = view->x, - .y = view->y - }, - .size = { - .w = view->width, - .h = view->height - } - }; - if (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN) { - swayc_t *parent = swayc_parent_by_type(view, C_OUTPUT); - geometry.origin.x = 0; - geometry.origin.y = 0; - geometry.size.w = parent->width; - geometry.size.h = parent->height; - wlc_view_set_geometry(view->handle, 0, &geometry); - wlc_view_bring_to_front(view->handle); - } else { - wlc_view_set_geometry(view->handle, 0, &geometry); - // Bring the views to the front in order of the list, the list - // will be kept up to date so that more recently focused views - // have higher indexes - // This is conditional on there not being a fullscreen view in the workspace - if (!container->focused - || !(wlc_view_get_state(container->focused->handle) & WLC_BIT_FULLSCREEN)) { - wlc_view_bring_to_front(view->handle); - } - } + // TODO fix floating implementation. + // Recurse and get handle of focused container + wlc_handle bottom = order_children(swayc->focused, top); + + // TODO Used properly in workspace case + wlc_handle topmost = bottom; + (void) topmost; + + // Put handle below current top, or if there is no top, set it as bottom + if (top) { + wlc_view_send_below(bottom, top); + } else { + top = bottom; + } + + // recurse for all children with the current bottom handle as their top. + int i, len = swayc->children->length; + swayc_t **child = (swayc_t **)swayc->children->items; + for (i = 0; i < len; ++i, ++child) { + // Skip over the focused child + if (*child == swayc->focused) { + continue; + } + // Update current top, send it below previous bottom, and set new bottom + top = order_children(*child, bottom); + wlc_view_send_below(top, bottom); + bottom = top; + } + + // TODO fix floating implementation. + // If we are at a workspace, put floating containers above topmost + if (swayc->type == C_WORKSPACE) { + // TODO using the same hacky implementation as before. + // send floating windows to front + len = swayc->children->length; + child = (swayc_t **)swayc->floating->items; + + // chekc whether to send floating windows to the back or front + swayc_t *focused = get_focused_view(swayc); + bool tofront = swayc->parent->focused == swayc || (focused->type == C_VIEW + && (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)); + for (i = 0; i < len; ++i) { + if (tofront) { + wlc_view_bring_to_front((*child)->handle); + } else { + wlc_view_send_to_back((*child)->handle); } } } + // Return the bottom of this, which shall be the top of others, + return bottom; +} + +// Arrange layout + +void arrange_windows(swayc_t *container, int width, int height) { + fit_children_in(container); + order_children(container, 0); layout_log(&root_container, 0); + return; } -swayc_t *get_swayc_for_handle(wlc_handle handle, swayc_t *parent) { - if (parent->children == NULL) { - return NULL; - } - - // Search for floating workspaces - int i; - if (parent->type == C_WORKSPACE) { - for (i = 0; i < parent->floating->length; ++i) { - swayc_t *child = parent->floating->items[i]; - if (child->handle == handle) { - return child; - } - } - } - - 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_swayc_in_direction(swayc_t *container, enum movement_direction dir) { swayc_t *parent = container->parent; diff --git a/sway/log.c b/sway/log.c index 6e01421bc..5fe32f07c 100644 --- a/sway/log.c +++ b/sway/log.c @@ -16,7 +16,7 @@ static const char *verbosity_colors[] = { "", // L_SILENT "\x1B[1;31m", // L_ERROR "\x1B[1;34m", // L_INFO - "\x1B[1;30m", // L_DEBUG + "\x1B[1;32m", // L_DEBUG }; void init_log(int verbosity) { @@ -151,6 +151,7 @@ static void container_log(const swayc_t *c) { void layout_log(const swayc_t *c, int depth) { int i, d; int e = c->children ? c->children->length : 0; + if (L_DEBUG > v) return; container_log(c); if (e) { for (i = 0; i < e; ++i) { From e2046e6abaa3266c8de7662eec5a63b447d7e1d4 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 17:34:08 -0700 Subject: [PATCH 2/5] fixed plenty of bugs and crashes, and restored fullscreen/floating behavior. also fixed mode_toggle --- include/container.h | 6 +++- include/layout.h | 3 -- sway/commands.c | 70 +++++++++++++++++++-------------------- sway/container.c | 79 ++++++++++++++++++++++++++++++++++++++------- sway/focus.c | 8 ++--- sway/handlers.c | 5 ++- sway/layout.c | 78 ++++++++++++-------------------------------- 7 files changed, 135 insertions(+), 114 deletions(-) diff --git a/include/container.h b/include/container.h index 66d8d81d5..35b93802e 100644 --- a/include/container.h +++ b/include/container.h @@ -2,8 +2,8 @@ #define _SWAY_CONTAINER_H #include typedef struct sway_container swayc_t; - #include "layout.h" +#include "focus.h" enum swayc_types{ C_ROOT, @@ -78,11 +78,15 @@ swayc_t *destroy_container(swayc_t *container); // parent swayc_t *destroy_view(swayc_t *view); +// Container info +bool swayc_is_fullscreen(swayc_t *view); + // Container Lookup swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types); swayc_t *swayc_parent_by_layout(swayc_t *container, enum swayc_layouts); swayc_t *swayc_by_handle(wlc_handle handle); +swayc_t *swayc_by_direction(swayc_t *container, enum movement_direction dir); 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 *); diff --git a/include/layout.h b/include/layout.h index 5d1f11acd..10f6ecbfa 100644 --- a/include/layout.h +++ b/include/layout.h @@ -25,7 +25,4 @@ void unfocus_all(swayc_t *container); void focus_view(swayc_t *view); void focus_view_for(swayc_t *ancestor, swayc_t *container); -swayc_t *get_focused_container(swayc_t *parent); -swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir); - #endif diff --git a/sway/commands.c b/sway/commands.c index 3ac7f4dd4..08e7dca02 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -294,36 +294,39 @@ static bool cmd_focus(struct sway_config *config, int argc, char **argv) { } else if (strcasecmp(argv[0], "mode_toggle") == 0) { int i; swayc_t *focused = get_focused_view(active_workspace); - if (focused->is_floating) { - if (active_workspace->children->length > 0) { - for (i = 0;i < active_workspace->floating->length; i++) { - if (active_workspace->floating->items[i] == focused) { - floating_toggled_index = i; - break; + // Dont change focus if fullscreen + if (!swayc_is_fullscreen(focused)) { + if (focused->is_floating) { + if (active_workspace->children->length > 0) { + for (i = 0;i < active_workspace->floating->length; i++) { + if (active_workspace->floating->items[i] == focused) { + floating_toggled_index = i; + break; + } + } + if (active_workspace->children->length > tiled_toggled_index) { + set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index])); + } else { + set_focused_container(get_focused_view(active_workspace->children->items[0])); + tiled_toggled_index = 0; } } - if (active_workspace->children->length > tiled_toggled_index) { - set_focused_container(get_focused_view(active_workspace->children->items[tiled_toggled_index])); - } else { - set_focused_container(get_focused_view(active_workspace->children->items[0])); - tiled_toggled_index = 0; - } - } - } else { - if (active_workspace->floating->length > 0) { - for (i = 0;i < active_workspace->children->length; i++) { - if (active_workspace->children->items[i] == focused) { - tiled_toggled_index = i; - break; + } else { + if (active_workspace->floating->length > 0) { + for (i = 0;i < active_workspace->children->length; i++) { + if (active_workspace->children->items[i] == focused) { + tiled_toggled_index = i; + break; + } + } + if (active_workspace->floating->length > floating_toggled_index) { + swayc_t *floating = active_workspace->floating->items[floating_toggled_index]; + set_focused_container(get_focused_view(floating)); + } else { + swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1]; + set_focused_container(get_focused_view(floating)); + tiled_toggled_index = active_workspace->floating->length - 1; } - } - if (active_workspace->floating->length > floating_toggled_index) { - swayc_t *floating = active_workspace->floating->items[floating_toggled_index]; - set_focused_container(get_focused_view(floating)); - } else { - swayc_t *floating = active_workspace->floating->items[active_workspace->floating->length - 1]; - set_focused_container(get_focused_view(floating)); - tiled_toggled_index = active_workspace->floating->length - 1; } } } @@ -506,16 +509,13 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { } swayc_t *container = get_focused_view(&root_container); - bool current = (wlc_view_get_state(container->handle) & WLC_BIT_FULLSCREEN) > 0; + bool current = swayc_is_fullscreen(container); wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); - // Resize workspace if going from fullscreen -> notfullscreen - // otherwise just resize container - if (current) { - container = swayc_parent_by_type(container, C_WORKSPACE); + // Resize workspace + container = swayc_parent_by_type(container, C_WORKSPACE); + if (container) { + arrange_windows(container, -1, -1); } - // Only resize container when going into fullscreen - arrange_windows(container, -1, -1); - return true; } diff --git a/sway/container.c b/sway/container.c index 054e1e49d..e86f6a850 100644 --- a/sway/container.c +++ b/sway/container.c @@ -32,17 +32,16 @@ static void free_swayc(swayc_t *cont) { if (!ASSERT_NONNULL(cont)) { return; } - if (cont->handle > 0) { + sway_log(L_DEBUG, "destroying container %p, handle:%ld",cont, cont->handle); + if (cont->handle) { wlc_handle_set_user_data(cont->handle, 0); } - // TODO does not properly handle containers with children, - // TODO but functions that call this usually check for that + // Destroy all children if (cont->children) { - if (cont->children->length) { - int i; - for (i = 0; i < cont->children->length; ++i) { - free_swayc(cont->children->items[i]); - } + // children remove themselves from parent, so continue until theres no + // more children + while (cont->children->length) { + free_swayc(cont->children->items[0]); } list_free(cont->children); } @@ -255,7 +254,7 @@ DESTROY_FUNC destroy_output(swayc_t *output) { if (output->children->length == 0) { // TODO move workspaces to other outputs } - sway_log(L_DEBUG, "OUTPUT: Destroying output '%lu'", output->handle); + sway_log(L_DEBUG, "%s:'%lu'", __func__, output->handle); free_swayc(output); return &root_container; } @@ -288,7 +287,7 @@ DESTROY_FUNC destroy_container(swayc_t *container) { return NULL; } while (container->children->length == 0 && container->type == C_CONTAINER) { - sway_log(L_DEBUG, "Container: Destroying container '%p'", container); + sway_log(L_DEBUG, "%s: '%p'", __func__, container); swayc_t *parent = container->parent; free_swayc(container); container = parent; @@ -300,7 +299,7 @@ DESTROY_FUNC destroy_view(swayc_t *view) { if (!ASSERT_NONNULL(view)) { return NULL; } - sway_log(L_DEBUG, "Destroying view '%p'", view); + sway_log(L_DEBUG, "%s: '%p'", __func__, view); swayc_t *parent = view->parent; free_swayc(view); @@ -312,6 +311,14 @@ DESTROY_FUNC destroy_view(swayc_t *view) { } #undef DESTROY_FUNC +// Container info function + +bool swayc_is_fullscreen(swayc_t *view) { + return view + && view->type == C_VIEW + && (wlc_view_get_state(view->handle) & WLC_BIT_FULLSCREEN); +} + // Container lookup swayc_t *swayc_parent_by_type(swayc_t *container, enum swayc_types type) { @@ -344,6 +351,56 @@ swayc_t *swayc_by_handle(wlc_handle handle) { return wlc_handle_get_user_data(handle); } +swayc_t *swayc_by_direction(swayc_t *container, enum movement_direction dir) { + swayc_t *parent = container->parent; + + if (dir == MOVE_PARENT) { + if (parent->type == C_OUTPUT) { + return NULL; + } else { + return parent; + } + } + while (true) { + // Test if we can even make a difference here + bool can_move = false; + int diff = 0; + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent->layout == L_HORIZ || parent->type == C_ROOT) { + can_move = true; + diff = dir == MOVE_LEFT ? -1 : 1; + } + } else { + if (parent->layout == L_VERT) { + can_move = true; + diff = dir == MOVE_UP ? -1 : 1; + } + } + if (can_move) { + int i; + for (i = 0; i < parent->children->length; ++i) { + swayc_t *child = parent->children->items[i]; + if (child == container) { + break; + } + } + int desired = i + diff; + if (desired < 0 || desired >= parent->children->length) { + can_move = false; + } else { + return parent->children->items[desired]; + } + } + if (!can_move) { + container = parent; + parent = parent->parent; + if (!parent) { + // Nothing we can do + return NULL; + } + } + } +} swayc_t *find_container(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) { if (!container->children) { diff --git a/sway/focus.c b/sway/focus.c index 5008dbbf0..b349f4fbd 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -54,8 +54,8 @@ static void update_focus(swayc_t *c) { } bool move_focus(enum movement_direction direction) { - swayc_t *view = get_swayc_in_direction( - get_focused_container(&root_container), direction); + swayc_t *view = get_focused_container(&root_container); + view = swayc_by_direction(view, direction); if (view) { if (direction == MOVE_PARENT) { set_focused_container(view); @@ -103,8 +103,8 @@ void set_focused_container(swayc_t *c) { // if the workspace is the same, and previous focus is fullscreen, dont // change focus - if (workspace == active_workspace - && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { + sway_log(L_DEBUG,"%p==%p, f:%d", workspace, active_workspace, swayc_is_fullscreen(focused)); + if (workspace == active_workspace && swayc_is_fullscreen(focused)) { return; } diff --git a/sway/handlers.c b/sway/handlers.c index 85c500be5..4cbe8c472 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -422,8 +422,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct if (config->focus_follows_mouse && prev_handle != handle) { // Dont change focus if fullscreen swayc_t *focused = get_focused_view(view); - if (!(focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) - && !(pointer_state.l_held || pointer_state.r_held)) { + if (!swayc_is_fullscreen(focused) && !(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } @@ -451,7 +450,7 @@ static bool handle_pointer_button(wlc_handle view, uint32_t time, const struct w uint32_t button, enum wlc_button_state state, const struct wlc_origin *origin) { swayc_t *focused = get_focused_container(&root_container); // dont change focus if fullscreen - if (focused->type == C_VIEW && wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN) { + if (swayc_is_fullscreen(focused)) { return false; } if (state == WLC_BUTTON_STATE_PRESSED) { diff --git a/sway/layout.c b/sway/layout.c index 3cd716e95..e33c007cb 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -107,12 +107,12 @@ swayc_t *remove_child(swayc_t *child) { parent->focused = NULL; } } + child->parent = NULL; return parent; } // Fitting functions #define FIT_FUNC __attribute__((nonnull)) static void - FIT_FUNC _fit_view(swayc_t *view) { sway_log(L_DEBUG, "%s:%p: (%dx%d@%dx%d)", __func__, view, view->width, view->height, view->x, view->y); @@ -174,7 +174,6 @@ FIT_FUNC _fit_container(swayc_t *container) { } s += *prev_w; } - sway_log(L_DEBUG,"s:%f",s); if (s < 0.001) { return; } @@ -307,6 +306,7 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha // Put handle below current top, or if there is no top, set it as bottom if (top) { wlc_view_send_below(bottom, top); + sway_log(L_DEBUG,"putting %ld below %ld", bottom, top); } else { top = bottom; } @@ -322,6 +322,7 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha // Update current top, send it below previous bottom, and set new bottom top = order_children(*child, bottom); wlc_view_send_below(top, bottom); + sway_log(L_DEBUG,"putting %ld below %ld", bottom, top); bottom = top; } @@ -330,18 +331,32 @@ __attribute__((nonnull)) static wlc_handle order_children(swayc_t *swayc, wlc_ha if (swayc->type == C_WORKSPACE) { // TODO using the same hacky implementation as before. // send floating windows to front - len = swayc->children->length; + len = swayc->floating->length; child = (swayc_t **)swayc->floating->items; // chekc whether to send floating windows to the back or front swayc_t *focused = get_focused_view(swayc); - bool tofront = swayc->parent->focused == swayc || (focused->type == C_VIEW - && (wlc_view_get_state(focused->handle) & WLC_BIT_FULLSCREEN)); - for (i = 0; i < len; ++i) { + + bool tofront = swayc->parent->focused == swayc; + // Send focused view to front or back if fullscreen depending on tofront + if (!focused->is_floating && swayc_is_fullscreen(focused)) { + if (tofront) { + wlc_view_bring_to_front(focused->handle); + sway_log(L_DEBUG,"bring %ld to front (fullscreen)", focused->handle); + // we dont want to bring floating windows above fullscreen + // window + tofront = false; + } else { + wlc_view_send_to_back(focused->handle); + } + } + for (i = 0; i < len; ++i, ++child) { if (tofront) { wlc_view_bring_to_front((*child)->handle); + sway_log(L_DEBUG,"bring %ld to front (floating)", focused->handle); } else { wlc_view_send_to_back((*child)->handle); + sway_log(L_DEBUG,"sending %ld to back (floating)", focused->handle); } } } @@ -358,54 +373,3 @@ void arrange_windows(swayc_t *container, int width, int height) { return; } - -swayc_t *get_swayc_in_direction(swayc_t *container, enum movement_direction dir) { - swayc_t *parent = container->parent; - - if (dir == MOVE_PARENT) { - if (parent->type == C_OUTPUT) { - return NULL; - } else { - return parent; - } - } - while (true) { - // Test if we can even make a difference here - bool can_move = false; - int diff = 0; - if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { - if (parent->layout == L_HORIZ || parent->type == C_ROOT) { - can_move = true; - diff = dir == MOVE_LEFT ? -1 : 1; - } - } else { - if (parent->layout == L_VERT) { - can_move = true; - diff = dir == MOVE_UP ? -1 : 1; - } - } - if (can_move) { - int i; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - if (child == container) { - break; - } - } - int desired = i + diff; - if (desired < 0 || desired >= parent->children->length) { - can_move = false; - } else { - return parent->children->items[desired]; - } - } - if (!can_move) { - container = parent; - parent = parent->parent; - if (!parent) { - // Nothing we can do - return NULL; - } - } - } -} From 2290db9bc3e1ce8ea7846ffeba3613f93122608f Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 18:42:36 -0700 Subject: [PATCH 3/5] focus change fix for fullscreen, prevent containers from being created on floating windows --- sway/commands.c | 4 ++++ sway/container.c | 2 +- sway/focus.c | 27 ++++++++++++++++----------- sway/handlers.c | 4 +--- 4 files changed, 22 insertions(+), 15 deletions(-) diff --git a/sway/commands.c b/sway/commands.c index 08e7dca02..f9ff9d911 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -445,6 +445,9 @@ static bool _do_split(struct sway_config *config, int argc, char **argv, int lay } swayc_t *focused = get_focused_container(&root_container); + if (focused->is_floating) { + return true; + } if (focused->type == C_WORKSPACE && focused->children->length <= 1) { /* Case that focus is on an workspace with 0/1 children.change its layout */ sway_log(L_DEBUG, "changing workspace layout"); @@ -508,6 +511,7 @@ static bool cmd_fullscreen(struct sway_config *config, int argc, char **argv) { return false; } + //get focused view and check current state. swayc_t *container = get_focused_view(&root_container); bool current = swayc_is_fullscreen(container); wlc_view_set_state(container->handle, WLC_BIT_FULLSCREEN, !current); diff --git a/sway/container.c b/sway/container.c index e86f6a850..3d0c7f5f8 100644 --- a/sway/container.c +++ b/sway/container.c @@ -135,7 +135,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { } swayc_t *new_container(swayc_t *child, enum swayc_layouts layout) { - if (!ASSERT_NONNULL(child)) { + if (!ASSERT_NONNULL(child) || child->is_floating) { return NULL; } swayc_t *cont = new_swayc(C_CONTAINER, 0); diff --git a/sway/focus.c b/sway/focus.c index b349f4fbd..be1476025 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -84,10 +84,13 @@ void set_focused_container(swayc_t *c) { return; } sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); - - // Find previous focused view, and the new focused view, if they are the same return - swayc_t *focused = get_focused_view(&root_container); - swayc_t *workspace = active_workspace; + // Get workspace for c, get that workspaces current focused container. + // if that focsued container is fullscreen dont change focus + swayc_t *workspace = swayc_parent_by_type(c, C_WORKSPACE); + swayc_t *focused = get_focused_view(workspace); + if (swayc_is_fullscreen(focused)) { + return; + } // update container focus from here to root, making necessary changes along // the way @@ -101,13 +104,6 @@ void set_focused_container(swayc_t *c) { p->is_focused = false; } - // if the workspace is the same, and previous focus is fullscreen, dont - // change focus - sway_log(L_DEBUG,"%p==%p, f:%d", workspace, active_workspace, swayc_is_fullscreen(focused)); - if (workspace == active_workspace && swayc_is_fullscreen(focused)) { - return; - } - // get new focused view and set focus to it. p = get_focused_view(c); if (p->type == C_VIEW && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { @@ -137,6 +133,15 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { return; } } + + // Get workspace for c, get that workspaces current focused container. + // if that focsued container is fullscreen dont change focus + swayc_t *workspace = swayc_parent_by_type(c, C_WORKSPACE); + swayc_t *focused = get_focused_view(workspace); + if (swayc_is_fullscreen(focused)) { + return; + } + // Check if we changing a parent container that will see chnage bool effective = true; while (find != &root_container) { diff --git a/sway/handlers.c b/sway/handlers.c index 4cbe8c472..6c4c195ba 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -420,9 +420,7 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct } } if (config->focus_follows_mouse && prev_handle != handle) { - // Dont change focus if fullscreen - swayc_t *focused = get_focused_view(view); - if (!swayc_is_fullscreen(focused) && !(pointer_state.l_held || pointer_state.r_held)) { + if (!(pointer_state.l_held || pointer_state.r_held)) { set_focused_container(container_under_pointer()); } } From c61105d1e2de85b737621612615a8485df569f44 Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 18:49:13 -0700 Subject: [PATCH 4/5] does this fix it now --- sway/focus.c | 2 +- sway/handlers.c | 2 +- sway/layout.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sway/focus.c b/sway/focus.c index be1476025..76e76a42b 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -88,7 +88,7 @@ void set_focused_container(swayc_t *c) { // if that focsued container is fullscreen dont change focus swayc_t *workspace = swayc_parent_by_type(c, C_WORKSPACE); swayc_t *focused = get_focused_view(workspace); - if (swayc_is_fullscreen(focused)) { + if (active_workspace == workspace && swayc_is_fullscreen(focused)) { return; } diff --git a/sway/handlers.c b/sway/handlers.c index 6c4c195ba..7ba55cba6 100644 --- a/sway/handlers.c +++ b/sway/handlers.c @@ -513,7 +513,6 @@ static void handle_wlc_ready(void) { config->active = true; } - struct wlc_interface interface = { .output = { .created = handle_output_created, @@ -541,3 +540,4 @@ struct wlc_interface interface = { .ready = handle_wlc_ready } }; + diff --git a/sway/layout.c b/sway/layout.c index e33c007cb..f76ccd1df 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -15,7 +15,7 @@ void init_layout(void) { root_container.type = C_ROOT; root_container.layout = L_NONE; root_container.children = create_list(); - root_container.handle = -1; + root_container.handle = 0; } // Children of container functions From 4af49202c73dc3984eb2902f76479889cf8fb71d Mon Sep 17 00:00:00 2001 From: taiyu Date: Thu, 20 Aug 2015 19:24:07 -0700 Subject: [PATCH 5/5] floating bug fix --- sway/container.c | 5 ++++- sway/focus.c | 5 ++++- sway/layout.c | 9 +++++---- sway/workspace.c | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/sway/container.c b/sway/container.c index 3d0c7f5f8..f92612164 100644 --- a/sway/container.c +++ b/sway/container.c @@ -107,9 +107,12 @@ swayc_t *new_output(wlc_handle handle) { // create and initilize default workspace swayc_t *ws = new_workspace(output, ws_name); ws->is_focused = true; + if (!active_workspace) { + active_workspace = ws; + } free(ws_name); - + return output; } diff --git a/sway/focus.c b/sway/focus.c index 76e76a42b..6b2f8a7dc 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -86,7 +86,10 @@ void set_focused_container(swayc_t *c) { sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); // Get workspace for c, get that workspaces current focused container. // if that focsued container is fullscreen dont change focus - swayc_t *workspace = swayc_parent_by_type(c, C_WORKSPACE); + swayc_t *workspace = c; + if (workspace->type != C_WORKSPACE) { + workspace = swayc_parent_by_type(c, C_WORKSPACE); + } swayc_t *focused = get_focused_view(workspace); if (active_workspace == workspace && swayc_is_fullscreen(focused)) { return; diff --git a/sway/layout.c b/sway/layout.c index f76ccd1df..33acbe6ac 100644 --- a/sway/layout.c +++ b/sway/layout.c @@ -37,7 +37,8 @@ void add_child(swayc_t *parent, swayc_t *child) { child->parent = parent; // set focus for this container if (parent->children->length == 1) { - set_focused_container_for(parent, child); + parent->focused = child; + set_focused_container_for(parent, get_focused_view(parent)); } } @@ -48,7 +49,7 @@ void add_floating(swayc_t *ws, swayc_t *child) { child->parent = ws; child->is_floating = true; if (!ws->focused) { - set_focused_container_for(ws, child); + ws->focused = child; } } @@ -73,7 +74,7 @@ swayc_t *replace_child(swayc_t *child, swayc_t *new_child) { new_child->parent = child->parent; if (child->parent->focused == child) { - set_focused_container_for(child->parent, new_child); + child->parent->focused = new_child; } child->parent = NULL; return parent; @@ -102,7 +103,7 @@ swayc_t *remove_child(swayc_t *child) { // Set focused to new container if (parent->focused == child) { if (parent->children->length > 0) { - set_focused_container_for(parent, parent->children->items[i?i-1:0]); + parent->focused = parent->children->items[i?i-1:0]; } else { parent->focused = NULL; } diff --git a/sway/workspace.c b/sway/workspace.c index d436da8e2..ce626de4a 100644 --- a/sway/workspace.c +++ b/sway/workspace.c @@ -182,5 +182,5 @@ void workspace_switch(swayc_t *workspace) { } sway_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); set_focused_container(get_focused_view(workspace)); - arrange_windows(workspace, -1, -1); + arrange_windows(workspace->parent, -1, -1); }