1
1
mirror of https://github.com/swaywm/sway synced 2024-11-18 00:24:17 +01:00

get swayc in direction

This commit is contained in:
Tony Crisci 2018-02-14 14:30:27 -05:00
parent 93084c9cf8
commit 946d9459c5
4 changed files with 201 additions and 0 deletions

@ -60,6 +60,9 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat);
swayc_t *sway_seat_get_focus_inactive(struct sway_seat *seat, swayc_t *container);
swayc_t *sway_seat_get_focus_by_type(struct sway_seat *seat,
enum swayc_types type);
void sway_seat_set_config(struct sway_seat *seat, struct seat_config *seat_config);
#endif

@ -4,6 +4,18 @@
#include <wlr/types/wlr_output_layout.h>
#include "sway/container.h"
enum movement_direction {
MOVE_LEFT,
MOVE_RIGHT,
MOVE_UP,
MOVE_DOWN,
MOVE_PARENT,
MOVE_CHILD,
MOVE_NEXT,
MOVE_PREV,
MOVE_FIRST
};
struct sway_container;
struct sway_root {
@ -25,5 +37,7 @@ struct sway_container *remove_child(struct sway_container *child);
enum swayc_layouts default_layout(struct sway_container *output);
void sort_workspaces(struct sway_container *output);
void arrange_windows(struct sway_container *container, double width, double height);
swayc_t *get_swayc_in_direction(swayc_t *container,
struct sway_seat *seat, enum movement_direction dir);
#endif

@ -358,6 +358,16 @@ swayc_t *sway_seat_get_focus(struct sway_seat *seat) {
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,
struct seat_config *seat_config) {
// clear configs

@ -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"
@ -346,3 +347,176 @@ 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) {
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);
}