diff options
Diffstat (limited to 'sway')
-rw-r--r-- | sway/commands.c | 3 | ||||
-rw-r--r-- | sway/commands/kill.c | 7 | ||||
-rw-r--r-- | sway/commands/workspace.c | 3 | ||||
-rw-r--r-- | sway/desktop/output.c | 10 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 3 | ||||
-rw-r--r-- | sway/input/input-manager.c | 2 | ||||
-rw-r--r-- | sway/input/seat.c | 183 | ||||
-rw-r--r-- | sway/ipc-json.c | 4 | ||||
-rw-r--r-- | sway/tree/container.c | 33 | ||||
-rw-r--r-- | sway/tree/layout.c | 208 | ||||
-rw-r--r-- | sway/tree/workspace.c | 37 |
11 files changed, 429 insertions, 64 deletions
diff --git a/sway/commands.c b/sway/commands.c index 0d4aa104..d8d29a1c 100644 --- a/sway/commands.c +++ b/sway/commands.c @@ -281,7 +281,8 @@ struct cmd_results *handle_command(char *_exec) { seat = sway_input_manager_get_default_seat(input_manager); } if (seat) { - config->handler_context.current_container = seat->focus; + config->handler_context.current_container = + sway_seat_get_focus(seat); struct cmd_results *res = handler->handle(argc-1, argv+1); if (res->status != CMD_SUCCESS) { free_argv(argc, argv); diff --git a/sway/commands/kill.c b/sway/commands/kill.c index cebf7f3c..4b3666be 100644 --- a/sway/commands/kill.c +++ b/sway/commands/kill.c @@ -10,11 +10,16 @@ struct cmd_results *cmd_kill(int argc, char **argv) { return cmd_results_new(CMD_FAILURE, "kill", "Command 'kill' cannot be used in the config file"); } + if (config->handler_context.current_container == NULL) { + wlr_log(L_DEBUG, "no container to kill"); + return cmd_results_new(CMD_SUCCESS, NULL, NULL); + } enum swayc_types type = config->handler_context.current_container->type; - if (type != C_VIEW || type != C_CONTAINER) { + if (type != C_VIEW && type != C_CONTAINER) { return cmd_results_new(CMD_INVALID, NULL, "Can only kill views and containers with this command"); } + // TODO close arbitrary containers without a view struct sway_view *view = config->handler_context.current_container->sway_view; diff --git a/sway/commands/workspace.c b/sway/commands/workspace.c index 12984ed4..fa891398 100644 --- a/sway/commands/workspace.c +++ b/sway/commands/workspace.c @@ -90,7 +90,8 @@ struct cmd_results *cmd_workspace(int argc, char **argv) { free(name); } workspace_switch(ws); - current_container = config->handler_context.seat->focus; + current_container = + sway_seat_get_focus(config->handler_context.seat); swayc_t *new_output = swayc_parent_by_type(current_container, C_OUTPUT); if (config->mouse_warping && old_output != new_output) { diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a66601b5..e250d450 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -220,12 +220,18 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); wlr_renderer_clear(renderer, &clear_color); + wlr_renderer_clear(renderer, &clear_color); + int buffer_age = -1; wlr_output_make_current(wlr_output, &buffer_age); - wlr_renderer_begin(server->renderer, wlr_output); wlr_renderer_begin(server->renderer, wlr_output); - swayc_t *workspace = soutput->swayc->focused; + struct sway_seat *seat = input_manager_current_seat(input_manager); + swayc_t *focus = sway_seat_get_focus_inactive(seat, soutput->swayc); + swayc_t *workspace = (focus->type == C_WORKSPACE ? + focus : + swayc_parent_by_type(focus, C_WORKSPACE)); + swayc_descendants_of_type(workspace, C_VIEW, output_frame_view, soutput); // render unmanaged views on top diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index ca56a9c0..b44d9e54 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -135,7 +135,8 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) { wl_signal_add(&xdg_surface->events.destroy, &sway_surface->destroy); struct sway_seat *seat = input_manager_current_seat(input_manager); - swayc_t *cont = new_view(seat->focus, sway_view); + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + swayc_t *cont = new_view(focus, sway_view); sway_view->swayc = cont; arrange_windows(cont->parent, -1, -1); diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index f59daea3..e6708bad 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c @@ -281,7 +281,7 @@ bool sway_input_manager_has_focus(struct sway_input_manager *input, swayc_t *container) { struct sway_seat *seat = NULL; wl_list_for_each(seat, &input->seats, link) { - if (seat->focus == container) { + if (sway_seat_get_focus(seat) == container) { return true; } } diff --git a/sway/input/seat.c b/sway/input/seat.c index 5e87986d..648e7914 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -32,6 +32,81 @@ void sway_seat_destroy(struct sway_seat *seat) { wlr_seat_destroy(seat->wlr_seat); } +static void handle_seat_container_destroy(struct wl_listener *listener, + void *data) { + struct sway_seat_container *seat_con = + wl_container_of(listener, seat_con, destroy); + struct sway_seat *seat = seat_con->seat; + swayc_t *con = seat_con->container; + + bool is_focus = (sway_seat_get_focus(seat) == con); + + wl_list_remove(&seat_con->link); + + if (is_focus) { + // pick next focus + sway_seat_set_focus(seat, NULL); + swayc_t *next = sway_seat_get_focus_inactive(seat, con->parent); + if (next == NULL) { + next = con->parent; + } + sway_seat_set_focus(seat, next); + } + + wl_list_remove(&seat_con->destroy.link); + + free(seat_con); +} + +static struct sway_seat_container *seat_container_from_container( + struct sway_seat *seat, swayc_t *con) { + if (con->type < C_WORKSPACE) { + // these don't get seat containers ever + return NULL; + } + + struct sway_seat_container *seat_con = NULL; + wl_list_for_each(seat_con, &seat->focus_stack, link) { + if (seat_con->container == con) { + return seat_con; + } + } + + seat_con = calloc(1, sizeof(struct sway_seat_container)); + if (seat_con == NULL) { + wlr_log(L_ERROR, "could not allocate seat container"); + return NULL; + } + + seat_con->container = con; + seat_con->seat = seat; + wl_list_insert(seat->focus_stack.prev, &seat_con->link); + wl_signal_add(&con->events.destroy, &seat_con->destroy); + seat_con->destroy.notify = handle_seat_container_destroy; + + return seat_con; +} + +static void handle_new_container(struct wl_listener *listener, void *data) { + struct sway_seat *seat = wl_container_of(listener, seat, new_container); + swayc_t *con = data; + seat_container_from_container(seat, con); +} + +static void collect_focus_iter(swayc_t *con, void *data) { + struct sway_seat *seat = data; + if (con->type > C_WORKSPACE) { + return; + } + struct sway_seat_container *seat_con = + seat_container_from_container(seat, con); + if (!seat_con) { + return; + } + wl_list_remove(&seat_con->link); + wl_list_insert(&seat->focus_stack, &seat_con->link); +} + struct sway_seat *sway_seat_create(struct sway_input_manager *input, const char *seat_name) { struct sway_seat *seat = calloc(1, sizeof(struct sway_seat)); @@ -52,6 +127,15 @@ struct sway_seat *sway_seat_create(struct sway_input_manager *input, return NULL; } + // init the focus stack + wl_list_init(&seat->focus_stack); + + container_for_each_bfs(&root_container, collect_focus_iter, seat); + + wl_signal_add(&root_container.sway_root->events.new_container, + &seat->new_container); + seat->new_container.notify = handle_new_container; + seat->input = input; wl_list_init(&seat->devices); @@ -81,13 +165,14 @@ static void seat_configure_keyboard(struct sway_seat *seat, struct wlr_keyboard *wlr_keyboard = seat_device->input_device->wlr_device->keyboard; sway_keyboard_configure(seat_device->keyboard); wlr_seat_set_keyboard(seat->wlr_seat, - seat_device->input_device->wlr_device); - if (seat->focus && seat->focus->type == C_VIEW) { + seat_device->input_device->wlr_device); + swayc_t *focus = sway_seat_get_focus(seat); + if (focus && focus->type == C_VIEW) { // force notify reenter to pick up the new configuration wlr_seat_keyboard_clear_focus(seat->wlr_seat); wlr_seat_keyboard_notify_enter(seat->wlr_seat, - seat->focus->sway_view->surface, wlr_keyboard->keycodes, - wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); + focus->sway_view->surface, wlr_keyboard->keycodes, + wlr_keyboard->num_keycodes, &wlr_keyboard->modifiers); } } @@ -204,47 +289,83 @@ void sway_seat_configure_xcursor(struct sway_seat *seat) { seat->cursor->cursor->y); } -static void handle_focus_destroy(struct wl_listener *listener, void *data) { - struct sway_seat *seat = wl_container_of(listener, seat, focus_destroy); - swayc_t *container = data; - sway_seat_set_focus(seat, container->parent); -} - void sway_seat_set_focus(struct sway_seat *seat, swayc_t *container) { - swayc_t *last_focus = seat->focus; + swayc_t *last_focus = sway_seat_get_focus(seat); - if (last_focus == container) { + if (container && last_focus == container) { return; } - if (last_focus && last_focus->type == C_VIEW) { - wl_list_remove(&seat->focus_destroy.link); - } + if (container) { + struct sway_seat_container *seat_con = + seat_container_from_container(seat, container); + if (!seat_con) { + return; + } - if (container && container->type == C_VIEW) { - struct sway_view *view = container->sway_view; - view_set_activated(view, true); - wl_signal_add(&container->events.destroy, &seat->focus_destroy); - seat->focus_destroy.notify = handle_focus_destroy; - - struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); - if (keyboard) { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, - keyboard->keycodes, keyboard->num_keycodes, - &keyboard->modifiers); - } else { - wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, - NULL, 0, NULL); + wl_list_remove(&seat_con->link); + wl_list_insert(&seat->focus_stack, &seat_con->link); + + if (container->type == C_VIEW) { + struct sway_view *view = container->sway_view; + view_set_activated(view, true); + struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(seat->wlr_seat); + if (keyboard) { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, + keyboard->keycodes, keyboard->num_keycodes, + &keyboard->modifiers); + } else { + wlr_seat_keyboard_notify_enter(seat->wlr_seat, view->surface, + NULL, 0, NULL); + } } } - seat->focus = container; - if (last_focus && last_focus->type == C_VIEW && !sway_input_manager_has_focus(seat->input, last_focus)) { struct sway_view *view = last_focus->sway_view; view_set_activated(view, false); } + + seat->has_focus = (container != NULL); +} + +swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container) { + struct sway_seat_container *current = NULL; + swayc_t *parent = NULL; + wl_list_for_each(current, &seat->focus_stack, link) { + parent = current->container->parent; + + if (current->container == container) { + return current->container; + } + + while (parent) { + if (parent == container) { + return current->container; + } + parent = parent->parent; + } + } + + return NULL; +} + +swayc_t *sway_seat_get_focus(struct sway_seat *seat) { + if (!seat->has_focus) { + return NULL; + } + return sway_seat_get_focus_inactive(seat, &root_container); +} + +swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat, + enum swayc_types type) { + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + if (focus->type == type) { + return focus; + } + + return swayc_parent_by_type(focus, type); } void sway_seat_set_config(struct sway_seat *seat, diff --git a/sway/ipc-json.c b/sway/ipc-json.c index bab9a201..f0afdc9f 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -74,8 +74,8 @@ static void ipc_json_describe_output(swayc_t *container, json_object *object) { json_object_object_add(object, "refresh", json_object_new_int(wlr_output->refresh)); json_object_object_add(object, "transform", json_object_new_string(ipc_json_get_output_transform(wlr_output->transform))); - json_object_object_add(object, "current_workspace", - (container->focused) ? json_object_new_string(container->focused->name) : NULL); + // TODO WLR need to set "current_workspace" to the currently focused + // workspace in a way that makes sense with multiseat } static void ipc_json_describe_workspace(swayc_t *workspace, json_object *object) { diff --git a/sway/tree/container.c b/sway/tree/container.c index 1a468c19..a6268133 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -151,19 +151,19 @@ swayc_t *new_output(struct sway_output *sway_output) { char *ws_name = workspace_next_name(output->name); wlr_log(L_DEBUG, "Creating default workspace %s", ws_name); swayc_t *ws = new_workspace(output, ws_name); - output->focused = ws; // Set each seat's focus if not already set // TODO FOCUS: this is probably stupid, we shouldn't define focus in two // places. We should probably put the active workspace on the sway_output // struct instead of trying to do focus semantics like this struct sway_seat *seat = NULL; wl_list_for_each(seat, &input_manager->seats, link) { - if (!seat->focus) { - seat->focus = ws; + if (!seat->has_focus) { + sway_seat_set_focus(seat, ws); } } free(ws_name); + wl_signal_emit(&root_container.sway_root->events.new_container, output); return output; } @@ -185,6 +185,7 @@ swayc_t *new_workspace(swayc_t *output, const char *name) { add_child(output, workspace); sort_workspaces(output); + wl_signal_emit(&root_container.sway_root->events.new_container, workspace); return workspace; } @@ -207,9 +208,9 @@ swayc_t *new_view(swayc_t *sibling, struct sway_view *sway_view) { add_child(sibling, swayc); } else { // Regular case, create as sibling of current container - // TODO WLR - //add_sibling(sibling, swayc); + add_sibling(sibling, swayc); } + wl_signal_emit(&root_container.sway_root->events.new_container, swayc); return swayc; } @@ -380,3 +381,25 @@ void container_map(swayc_t *container, void (*f)(swayc_t *view, void *data), voi f(container, data); } } + +void container_for_each_bfs(swayc_t *con, void (*f)(swayc_t *con, void *data), + void *data) { + list_t *queue = create_list(); + if (queue == NULL) { + wlr_log(L_ERROR, "could not allocate list"); + return; + } + + list_add(queue, con); + + swayc_t *current = NULL; + while (queue->length) { + current = queue->items[0]; + list_del(queue, 0); + f(current, data); + // TODO floating containers + list_cat(queue, current->children); + } + + list_free(queue); +} diff --git a/sway/tree/layout.c b/sway/tree/layout.c index 41ff81b2..205f42eb 100644 --- a/sway/tree/layout.c +++ b/sway/tree/layout.c @@ -10,6 +10,7 @@ #include "sway/layout.h" #include "sway/output.h" #include "sway/view.h" +#include "sway/input/seat.h" #include "list.h" #include "log.h" @@ -48,10 +49,12 @@ void init_layout(void) { root_container.layout = L_NONE; root_container.name = strdup("root"); root_container.children = create_list(); + wl_signal_init(&root_container.events.destroy); root_container.sway_root = calloc(1, sizeof(*root_container.sway_root)); root_container.sway_root->output_layout = wlr_output_layout_create(); wl_list_init(&root_container.sway_root->unmanaged_views); + wl_signal_init(&root_container.sway_root->events.new_container); root_container.sway_root->output_layout_change.notify = output_layout_change_notify; @@ -59,6 +62,32 @@ void init_layout(void) { &root_container.sway_root->output_layout_change); } +static int index_child(const swayc_t *child) { + // TODO handle floating + swayc_t *parent = child->parent; + int i, len; + len = parent->children->length; + for (i = 0; i < len; ++i) { + if (parent->children->items[i] == child) { + break; + } + } + + if (!sway_assert(i < len, "Stray container")) { + return -1; + } + return i; +} + +swayc_t *add_sibling(swayc_t *fixed, swayc_t *active) { + // TODO handle floating + swayc_t *parent = fixed->parent; + int i = index_child(fixed); + list_insert(parent->children, i + 1, active); + active->parent = parent; + return active->parent; +} + void add_child(swayc_t *parent, swayc_t *child) { wlr_log(L_DEBUG, "Adding %p (%d, %fx%f) to %p (%d, %fx%f)", child, child->type, child->width, child->height, @@ -66,9 +95,6 @@ void add_child(swayc_t *parent, swayc_t *child) { list_add(parent->children, child); child->parent = parent; // set focus for this container - if (!parent->focused) { - parent->focused = child; - } /* TODO WLR if (parent->type == C_WORKSPACE && child->type == C_VIEW && (parent->workspace_layout == L_TABBED || parent->workspace_layout == L_STACKED)) { child = new_container(child, parent->workspace_layout); @@ -321,3 +347,179 @@ void apply_vert_layout(swayc_t *container, */ } } + +/** + * Get swayc in the direction of newly entered output. + */ +static swayc_t *get_swayc_in_output_direction(swayc_t *output, + enum movement_direction dir, struct sway_seat *seat) { + // XXX is this really a seat function or can we do it with the default + // seat? + if (!output) { + return NULL; + } + + swayc_t *ws = sway_seat_get_focus_inactive(seat, output); + if (ws->type != C_WORKSPACE) { + ws = swayc_parent_by_type(ws, C_WORKSPACE); + } + + if (ws && ws->children->length > 0) { + switch (dir) { + case MOVE_LEFT: + // get most right child of new output + return ws->children->items[ws->children->length-1]; + case MOVE_RIGHT: + // get most left child of new output + return ws->children->items[0]; + case MOVE_UP: + case MOVE_DOWN: + { + swayc_t *focused = sway_seat_get_focus_inactive(seat, ws); + if (focused && focused->parent) { + swayc_t *parent = focused->parent; + if (parent->layout == L_VERT) { + if (dir == MOVE_UP) { + // get child furthest down on new output + return parent->children->items[parent->children->length-1]; + } else if (dir == MOVE_DOWN) { + // get child furthest up on new output + return parent->children->items[0]; + } + } + return focused; + } + break; + } + default: + break; + } + } + + return output; +} + +static void get_absolute_center_position(swayc_t *container, int *x, int *y) { + *x = container->x + container->width/2; + *y = container->y + container->height/2; +} + +static swayc_t *get_swayc_in_direction_under(swayc_t *container, + enum movement_direction dir, struct sway_seat *seat, swayc_t *limit) { + if (dir == MOVE_CHILD) { + return sway_seat_get_focus_inactive(seat, container); + } + + swayc_t *parent = container->parent; + if (dir == MOVE_PARENT) { + if (parent->type == C_OUTPUT) { + return NULL; + } else { + return parent; + } + } + + if (dir == MOVE_PREV || dir == MOVE_NEXT) { + int focused_idx = index_child(container); + if (focused_idx == -1) { + return NULL; + } else { + int desired = (focused_idx + (dir == MOVE_NEXT ? 1 : -1)) % + parent->children->length; + if (desired < 0) { + desired += parent->children->length; + } + return parent->children->items[desired]; + } + } + + // If moving to an adjacent output we need a starting position (since this + // output might border to multiple outputs). + //struct wlc_point abs_pos; + //get_absolute_center_position(container, &abs_pos); + + + // TODO WLR fullscreen + /* + if (container->type == C_VIEW && swayc_is_fullscreen(container)) { + wlr_log(L_DEBUG, "Moving from fullscreen view, skipping to output"); + container = swayc_parent_by_type(container, C_OUTPUT); + get_absolute_center_position(container, &abs_pos); + swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); + return get_swayc_in_output_direction(output, dir); + } + if (container->type == C_WORKSPACE && container->fullscreen) { + sway_log(L_DEBUG, "Moving to fullscreen view"); + return container->fullscreen; + } + */ + + swayc_t *wrap_candidate = NULL; + while (true) { + // Test if we can even make a difference here + bool can_move = false; + int desired; + int idx = index_child(container); + if (parent->type == C_ROOT) { + // TODO + /* + struct wlr_output_layout *layout = root_container.sway_root->output_layout; + wlr_output_layout_adjacent_output(layout, container->sway_output->wlr_output); + //swayc_t *output = swayc_adjacent_output(container, dir, &abs_pos, true); + if (!output || output == container) { + return wrap_candidate; + } + wlr_log(L_DEBUG, "Moving between outputs"); + return get_swayc_in_output_direction(output, dir, seat); + */ + } else { + if (dir == MOVE_LEFT || dir == MOVE_RIGHT) { + if (parent->layout == L_HORIZ || parent->layout == L_TABBED) { + can_move = true; + desired = idx + (dir == MOVE_LEFT ? -1 : 1); + } + } else { + if (parent->layout == L_VERT || parent->layout == L_STACKED) { + can_move = true; + desired = idx + (dir == MOVE_UP ? -1 : 1); + } + } + } + + if (can_move) { + // TODO handle floating + if (desired < 0 || desired >= parent->children->length) { + can_move = false; + int len = parent->children->length; + if (!wrap_candidate && len > 1) { + if (desired < 0) { + wrap_candidate = parent->children->items[len-1]; + } else { + wrap_candidate = parent->children->items[0]; + } + if (config->force_focus_wrapping) { + return wrap_candidate; + } + } + } else { + wlr_log(L_DEBUG, "%s cont %d-%p dir %i sibling %d: %p", __func__, + idx, container, dir, desired, parent->children->items[desired]); + return parent->children->items[desired]; + } + } + + if (!can_move) { + container = parent; + parent = parent->parent; + if (!parent || container == limit) { + // wrapping is the last chance + return wrap_candidate; + } + } + } +} + +swayc_t *get_swayc_in_direction(swayc_t *container, struct sway_seat *seat, + enum movement_direction dir) { + return get_swayc_in_direction_under(container, dir, seat, NULL); +} diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c index 23c630b6..861fda4d 100644 --- a/sway/tree/workspace.c +++ b/sway/tree/workspace.c @@ -63,9 +63,10 @@ static bool _workspace_by_name(swayc_t *view, void *data) { swayc_t *workspace_by_name(const char *name) { struct sway_seat *seat = input_manager_current_seat(input_manager); swayc_t *current_workspace = NULL, *current_output = NULL; - if (seat->focus) { - current_workspace = swayc_parent_by_type(seat->focus, C_WORKSPACE); - current_output = swayc_parent_by_type(seat->focus, C_OUTPUT); + swayc_t *focus = sway_seat_get_focus(seat); + if (focus) { + current_workspace = swayc_parent_by_type(focus, C_WORKSPACE); + current_output = swayc_parent_by_type(focus, C_OUTPUT); } if (strcmp(name, "prev") == 0) { return workspace_prev(current_workspace); @@ -102,7 +103,8 @@ swayc_t *workspace_create(const char *name) { } // Otherwise create a new one struct sway_seat *seat = input_manager_current_seat(input_manager); - parent = seat->focus; + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + parent = focus; parent = swayc_parent_by_type(parent, C_OUTPUT); return new_workspace(parent, name); } @@ -118,9 +120,15 @@ swayc_t *workspace_output_prev_next_impl(swayc_t *output, bool next) { return NULL; } + struct sway_seat *seat = input_manager_current_seat(input_manager); + swayc_t *focus = sway_seat_get_focus_inactive(seat, output); + swayc_t *workspace = (focus->type == C_WORKSPACE ? + focus : + swayc_parent_by_type(focus, C_WORKSPACE)); + int i; for (i = 0; i < output->children->length; i++) { - if (output->children->items[i] == output->focused) { + if (output->children->items[i] == workspace) { return output->children->items[ wrap(i + (next ? 1 : -1), output->children->length)]; } @@ -193,12 +201,13 @@ bool workspace_switch(swayc_t *workspace) { return false; } struct sway_seat *seat = input_manager_current_seat(input_manager); - if (!seat || !seat->focus) { + swayc_t *focus = sway_seat_get_focus_inactive(seat, &root_container); + if (!seat || !focus) { return false; } - swayc_t *active_ws = seat->focus; + swayc_t *active_ws = focus; if (active_ws->type != C_WORKSPACE) { - swayc_parent_by_type(seat->focus, C_WORKSPACE); + swayc_parent_by_type(focus, C_WORKSPACE); } if (config->auto_back_and_forth @@ -222,16 +231,12 @@ bool workspace_switch(swayc_t *workspace) { // TODO: Deal with sticky containers wlr_log(L_DEBUG, "Switching to workspace %p:%s", workspace, workspace->name); - // TODO FOCUS: Focus the last view this seat had focused on this workspace - if (workspace->children->length) { - // TODO FOCUS: This is really fucking stupid - sway_seat_set_focus(seat, workspace->children->items[0]); - } else { - sway_seat_set_focus(seat, workspace); + swayc_t *next = sway_seat_get_focus_inactive(seat, workspace); + if (next == NULL) { + next = workspace; } + sway_seat_set_focus(seat, next); swayc_t *output = swayc_parent_by_type(workspace, C_OUTPUT); - // TODO FOCUS: take a look at this - output->focused = workspace; arrange_windows(output, -1, -1); return true; } |