diff options
Diffstat (limited to 'sway/focus.c')
-rw-r--r-- | sway/focus.c | 154 |
1 files changed, 70 insertions, 84 deletions
diff --git a/sway/focus.c b/sway/focus.c index 99cb2570..5008dbbf 100644 --- a/sway/focus.c +++ b/sway/focus.c @@ -3,6 +3,7 @@ #include "focus.h" #include "log.h" #include "workspace.h" +#include "layout.h" bool locked_container_focus = false; bool locked_view_focus = false; @@ -14,11 +15,17 @@ static void update_focus(swayc_t *c) { swayc_t *parent = c->parent; if (parent->focused != c) { switch (c->type) { + // Shouldnt happen case C_ROOT: return; + + // Case where output changes case C_OUTPUT: - wlc_output_focus(c->parent->handle); + wlc_output_focus(c->handle); + // Set new workspace to the outputs focused workspace + active_workspace = c->focused; break; - // switching workspaces + + // Case where workspace changes case C_WORKSPACE: if (parent->focused) { swayc_t *ws = parent->focused; @@ -29,10 +36,12 @@ static void update_focus(swayc_t *c) { mask = 2; container_map(c, set_view_visibility, &mask); wlc_output_set_mask(parent->handle, 2); + c->parent->focused = c; destroy_workspace(ws); } active_workspace = c; break; + default: case C_VIEW: case C_CONTAINER: @@ -45,70 +54,17 @@ static void update_focus(swayc_t *c) { } bool move_focus(enum movement_direction direction) { - if (locked_container_focus) { - return false; - } - swayc_t *current = get_focused_container(&root_container); - swayc_t *parent = current->parent; - - if (direction == MOVE_PARENT) { - if (parent->type == C_OUTPUT) { - sway_log(L_DEBUG, "Focus cannot move to parent"); - return false; - } else { - sway_log(L_DEBUG, "Moving focus from %p:%ld to %p:%ld", - current, current->handle, parent, parent->handle); - set_focused_container(parent); - return true; - } - } - - while (true) { - sway_log(L_DEBUG, "Moving focus away from %p", current); - - // Test if we can even make a difference here - bool can_move = false; - int diff = 0; - if (direction == MOVE_LEFT || direction == MOVE_RIGHT) { - if (parent->layout == L_HORIZ || parent->type == C_ROOT) { - can_move = true; - diff = direction == MOVE_LEFT ? -1 : 1; - } + swayc_t *view = get_swayc_in_direction( + get_focused_container(&root_container), direction); + if (view) { + if (direction == MOVE_PARENT) { + set_focused_container(view); } else { - if (parent->layout == L_VERT) { - can_move = true; - diff = direction == MOVE_UP ? -1 : 1; - } - } - sway_log(L_DEBUG, "Can move? %s", can_move ? "yes" : "no"); - if (can_move) { - int i; - for (i = 0; i < parent->children->length; ++i) { - swayc_t *child = parent->children->items[i]; - if (child == current) { - break; - } - } - int desired = i + diff; - sway_log(L_DEBUG, "Moving from %d to %d", i, desired); - if (desired < 0 || desired >= parent->children->length) { - can_move = false; - } else { - swayc_t *newview = parent->children->items[desired]; - set_focused_container(get_focused_view(newview)); - return true; - } - } - if (!can_move) { - sway_log(L_DEBUG, "Can't move at current level, moving up tree"); - current = parent; - parent = parent->parent; - if (!parent) { - // Nothing we can do - return false; - } + set_focused_container(get_focused_view(view)); } + return true; } + return false; } swayc_t *get_focused_container(swayc_t *parent) { @@ -128,25 +84,44 @@ void set_focused_container(swayc_t *c) { return; } sway_log(L_DEBUG, "Setting focus to %p:%ld", c, c->handle); - if (c->type != C_ROOT && c->type != C_OUTPUT) { - c->is_focused = true; - } - swayc_t *prev_view = get_focused_view(&root_container); + + // 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; + + // update container focus from here to root, making necessary changes along + // the way swayc_t *p = c; + if (p->type != C_OUTPUT && p->type != C_ROOT) { + p->is_focused = true; + } while (p != &root_container) { update_focus(p); p = p->parent; p->is_focused = false; } - if (!locked_view_focus) { - p = get_focused_view(c); - // Set focus to p - if (p && !(wlc_view_get_type(p->handle) & WLC_BIT_POPUP)) { - if (prev_view) { - wlc_view_set_state(prev_view->handle, WLC_BIT_ACTIVATED, false); - } - wlc_view_focus(p->handle); + + // 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) { + 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)) { + // unactivate previous focus + if (focused->type == C_VIEW) { + wlc_view_set_state(focused->handle, WLC_BIT_ACTIVATED, false); + } + // activate current focus + if (p->type == C_VIEW) { wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); + // set focus if view_focus is unlocked + if (!locked_view_focus) { + wlc_view_focus(p->handle); + } } } } @@ -156,12 +131,25 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { return; } swayc_t *find = c; - //Ensure that a is an ancestor of c + // Ensure that a is an ancestor of c while (find != a && (find = find->parent)) { if (find == &root_container) { return; } } + // Check if we changing a parent container that will see chnage + bool effective = true; + while (find != &root_container) { + if (find->parent->focused != find) { + effective = false; + } + find = find->parent; + } + if (effective) { + // Go to set_focused_container + set_focused_container(c); + return; + } sway_log(L_DEBUG, "Setting focus for %p:%ld to %p:%ld", a, a->handle, c, c->handle); @@ -173,19 +161,17 @@ void set_focused_container_for(swayc_t *a, swayc_t *c) { p = p->parent; p->is_focused = false; } - if (!locked_view_focus) { - p = get_focused_view(c); - // Set focus to p - if (p) { - wlc_view_focus(p->handle); - wlc_view_set_state(p->handle, WLC_BIT_ACTIVATED, true); - } - } } swayc_t *get_focused_view(swayc_t *parent) { while (parent && parent->type != C_VIEW) { + if (parent->type == C_WORKSPACE && parent->focused == NULL) { + return parent; + } parent = parent->focused; } + if (parent == NULL) { + return active_workspace; + } return parent; } |