Switch to adjacent output when hitting output edge.

container: Add neighbours struct (for output containers). In order to
move the mouse between the outputs this struct is added to keep track of
each outputs' neighbours.

Neighbour relationships are updated during output creation/destruction
and output command invocation (e.g. via config reload).
This commit is contained in:
S. Christoffer Eliesen 2015-10-20 19:28:45 +02:00
parent 3e2579b22c
commit 9f45a67f2c
4 changed files with 118 additions and 1 deletions

View file

@ -27,6 +27,15 @@ enum swayc_layouts{
L_LAYOUTS,
};
// This is meant to be used by outputs who need to know who their adjacent
// outputs are in order for "mouse between outputs" to work.
//
// (This is obviously a naïve implementation since it assumes a single,
// perfectly aligned neighbour per edge.)
struct swayc_neighbours {
struct sway_container *top, *right, *bottom, *left;
};
struct sway_container {
wlc_handle handle;
@ -54,6 +63,8 @@ struct sway_container {
struct sway_container *parent;
struct sway_container *focused;
struct swayc_neighbours *neighbours;
};
enum visibility_mask {
@ -70,6 +81,7 @@ swayc_t *new_container(swayc_t *child, enum swayc_layouts layout);
swayc_t *new_view(swayc_t *sibling, wlc_handle handle);
// Creates view as a new floating view which is in the active workspace
swayc_t *new_floating_view(wlc_handle handle);
void reset_neighbour_relations(swayc_t *output);
// Container Destroying

View file

@ -310,6 +310,41 @@ void apply_output_config(struct output_config *oc, swayc_t *output) {
}
output->x = x;
}
// Populate neighbours struct for given output. Will also update reverse
// relations.
reset_neighbour_relations(output);
for(int i = 0; i < root_container.children->length; ++i) {
swayc_t *c = root_container.children->items[i];
if (c == output || c->type != C_OUTPUT) {
continue;
}
// TODO: This implementation is naïve: We assume all outputs are
// perfectly aligned.
if (c->y == output->y) {
if (c->x + c->width == output->x) {
sway_log(L_DEBUG, "%s is right of %s", output->name, c->name);
c->neighbours->right = output;
output->neighbours->left = c;
} else if (output->x + output->width == c->x) {
sway_log(L_DEBUG, "%s is left of %s", output->name, c->name);
c->neighbours->left = output;
output->neighbours->right = c;
}
} else if (c->x == output->x) {
if (c->y + c->height == output->y) {
sway_log(L_DEBUG, "%s is below %s", output->name, c->name);
c->neighbours->bottom = output;
output->neighbours->top = c;
} else if (output->y + output->height == c->y) {
sway_log(L_DEBUG, "%s is above %s", output->name, c->name);
c->neighbours->top = output;
output->neighbours->bottom = c;
}
}
}
}
char *do_var_replacement(char *str) {

View file

@ -19,9 +19,18 @@ static swayc_t *new_swayc(enum swayc_types type) {
c->gaps = -1;
c->layout = L_NONE;
c->type = type;
if (type != C_VIEW) {
c->children = create_list();
}
if (type == C_OUTPUT) {
c->neighbours = malloc(sizeof(struct swayc_neighbours));
c->neighbours->top = NULL;
c->neighbours->right = NULL;
c->neighbours->bottom = NULL;
c->neighbours->left = NULL;
}
return c;
}
@ -49,6 +58,9 @@ static void free_swayc(swayc_t *cont) {
if (cont->name) {
free(cont->name);
}
if (cont->neighbours) {
free(cont->neighbours);
}
free(cont);
}
@ -292,6 +304,8 @@ swayc_t *destroy_output(swayc_t *output) {
arrange_windows(root_container.children->items[p], -1, -1);
}
}
reset_neighbour_relations(output);
sway_log(L_DEBUG, "OUTPUT: Destroying output '%lu'", output->handle);
free_swayc(output);
return &root_container;
@ -349,8 +363,29 @@ swayc_t *destroy_view(swayc_t *view) {
return parent;
}
// Container lookup
// Modify container
// Make output inaccesible via its neighbours.
void reset_neighbour_relations(swayc_t *output) {
if (output->neighbours->top) {
output->neighbours->top->neighbours->bottom = NULL;
output->neighbours->top = NULL;
}
if (output->neighbours->right) {
output->neighbours->right->neighbours->left = NULL;
output->neighbours->right = NULL;
}
if (output->neighbours->bottom) {
output->neighbours->bottom->neighbours->top = NULL;
output->neighbours->bottom = NULL;
}
if (output->neighbours->left) {
output->neighbours->left->neighbours->right = NULL;
output->neighbours->left = NULL;
}
}
// Container lookup
swayc_t *swayc_by_test(swayc_t *container, bool (*test)(swayc_t *view, void *data), void *data) {
if (!container->children) {

View file

@ -353,6 +353,41 @@ static bool handle_key(wlc_handle view, uint32_t time, const struct wlc_modifier
}
static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct wlc_origin *origin) {
// Switch to adjacent output if touching output edge.
//
// Since this doesn't currently support moving windows between outputs we
// don't do the switch if the pointer is in a mode.
if (!pointer_state.mode) {
swayc_t *output = swayc_active_output();
if (origin->x == 0) {
swayc_t *adjacent = output->neighbours->left;
if (adjacent) {
sway_log(L_DEBUG, "%s: Left adjacent output is: %s", output->name, adjacent->name);
workspace_switch(adjacent->focused);
}
} else if ((double)origin->x == output->width) {
swayc_t *adjacent = output->neighbours->right;
if (adjacent) {
sway_log(L_DEBUG, "%s: Right adjacent output is: %s", output->name, adjacent->name);
workspace_switch(adjacent->focused);
}
}
if (origin->y == 0) {
swayc_t *adjacent = output->neighbours->top;
if (adjacent) {
sway_log(L_DEBUG, "%s: Top adjacent output is: %s", output->name, adjacent->name);
workspace_switch(adjacent->focused);
}
} else if ((double)origin->y == output->height) {
swayc_t *adjacent = output->neighbours->bottom;
if (adjacent) {
sway_log(L_DEBUG, "%s: Bottom adjacent output is: %s", output->name, adjacent->name);
workspace_switch(adjacent->focused);
}
}
}
// Update pointer origin
pointer_state.delta.x = origin->x - pointer_state.origin.x;
pointer_state.delta.y = origin->y - pointer_state.origin.y;