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; - } - } - } -}