Fix edge cases when moving floating container to new workspace

* Removes container_floating_move_to_container, instead opting to put
that logic in container_move_to
* In the seat code, focusing a floating view now updates the pending
state only and lets the next transaction carry it over to the current
state. This is required, otherwise it would crash.
* When unfullscreening a floating container, an output check is now done
to see if it should center it.
This commit is contained in:
Ryan Dwyer 2018-08-07 09:30:27 +10:00
parent 36281609ea
commit a0649190de
4 changed files with 47 additions and 54 deletions

View file

@ -322,6 +322,12 @@ void container_get_box(struct sway_container *container, struct wlr_box *box);
void container_floating_translate(struct sway_container *con, void container_floating_translate(struct sway_container *con,
double x_amount, double y_amount); double x_amount, double y_amount);
/**
* Choose an output for the floating container's new position.
*/
struct sway_container *container_floating_find_output(
struct sway_container *con);
/** /**
* Move a floating container to a new layout-local position. * Move a floating container to a new layout-local position.
*/ */
@ -333,9 +339,6 @@ void container_floating_move_to(struct sway_container *con,
*/ */
void container_floating_move_to_center(struct sway_container *con); void container_floating_move_to_center(struct sway_container *con);
void container_floating_move_to_container(struct sway_container *container,
struct sway_container *destination);
/** /**
* Mark a container as dirty if it isn't already. Dirty containers will be * Mark a container as dirty if it isn't already. Dirty containers will be
* included in the next transaction then unmarked as dirty. * included in the next transaction then unmarked as dirty.

View file

@ -717,12 +717,8 @@ void seat_set_focus_warp(struct sway_seat *seat,
// If we've focused a floating container, bring it to the front. // If we've focused a floating container, bring it to the front.
// We do this by putting it at the end of the floating list. // We do this by putting it at the end of the floating list.
// This must happen for both the pending and current children lists.
if (container && container_is_floating(container)) { if (container && container_is_floating(container)) {
list_move_to_end(container->parent->children, container); list_move_to_end(container->parent->children, container);
if (container_has_ancestor(container, container->current.parent)) {
list_move_to_end(container->parent->current.children, container);
}
} }
// clean up unfocused empty workspace on new output // clean up unfocused empty workspace on new output

View file

@ -1182,7 +1182,7 @@ void container_floating_translate(struct sway_container *con,
* one, otherwise we'll choose whichever output is closest to the container's * one, otherwise we'll choose whichever output is closest to the container's
* center. * center.
*/ */
static struct sway_container *container_floating_find_output( struct sway_container *container_floating_find_output(
struct sway_container *con) { struct sway_container *con) {
double center_x = con->x + con->width / 2; double center_x = con->x + con->width / 2;
double center_y = con->y + con->height / 2; double center_y = con->y + con->height / 2;
@ -1245,39 +1245,6 @@ void container_floating_move_to_center(struct sway_container *con) {
container_floating_translate(con, new_lx - con->x, new_ly - con->y); container_floating_translate(con, new_lx - con->x, new_ly - con->y);
} }
void container_floating_move_to_container(struct sway_container *container,
struct sway_container *destination) {
// Resolve destination into a workspace
struct sway_container *new_ws = NULL;
if (destination->type == C_OUTPUT) {
new_ws = output_get_active_workspace(destination->sway_output);
} else if (destination->type == C_WORKSPACE) {
new_ws = destination;
} else {
new_ws = container_parent(destination, C_WORKSPACE);
}
if (!new_ws) {
// This can happen if the user has run "move container to mark foo",
// where mark foo is on a hidden scratchpad container.
return;
}
struct sway_container *old_ws = container_parent(container, C_WORKSPACE);
if (old_ws != new_ws) {
container_remove_child(container);
container_add_child(new_ws->sway_workspace->floating, container);
arrange_windows(old_ws);
arrange_windows(new_ws);
workspace_detect_urgent(old_ws);
workspace_detect_urgent(new_ws);
}
// If the container's center doesn't overlap the new workspace, center it
// within the workspace.
struct sway_container *output = container_floating_find_output(container);
if (new_ws->parent != output) {
container_floating_move_to_center(container);
}
}
void container_set_dirty(struct sway_container *container) { void container_set_dirty(struct sway_container *container) {
if (container->dirty) { if (container->dirty) {
return; return;
@ -1357,6 +1324,11 @@ void container_set_fullscreen(struct sway_container *container, bool enable) {
container->y = container->saved_y; container->y = container->saved_y;
container->width = container->saved_width; container->width = container->saved_width;
container->height = container->saved_height; container->height = container->saved_height;
struct sway_container *output =
container_floating_find_output(container);
if (!container_has_ancestor(container, output)) {
container_floating_move_to_center(container);
}
} else { } else {
container->width = container->saved_width; container->width = container->saved_width;
container->height = container->saved_height; container->height = container->saved_height;

View file

@ -150,22 +150,44 @@ void container_move_to(struct sway_container *container,
|| container_has_ancestor(container, destination)) { || container_has_ancestor(container, destination)) {
return; return;
} }
struct sway_container *old_parent = NULL;
struct sway_container *new_parent = NULL;
if (container_is_floating(container)) { if (container_is_floating(container)) {
container_floating_move_to_container(container, destination); // Resolve destination into a workspace
return; struct sway_container *new_ws = NULL;
} if (destination->type == C_OUTPUT) {
struct sway_container *old_parent = container_remove_child(container); new_ws = output_get_active_workspace(destination->sway_output);
container->width = container->height = 0; } else if (destination->type == C_WORKSPACE) {
container->saved_width = container->saved_height = 0; new_ws = destination;
} else {
struct sway_container *new_parent; new_ws = container_parent(destination, C_WORKSPACE);
}
if (destination->type == C_VIEW) { if (!new_ws) {
new_parent = container_add_sibling(destination, container); // This can happen if the user has run "move container to mark foo",
// where mark foo is on a hidden scratchpad container.
return;
}
struct sway_container *old_output =
container_parent(container, C_OUTPUT);
old_parent = container_remove_child(container);
container_add_child(new_ws->sway_workspace->floating, container);
// If changing output, center it within the workspace
if (old_output != new_ws->parent && !container->is_fullscreen) {
container_floating_move_to_center(container);
}
} else { } else {
new_parent = destination; old_parent = container_remove_child(container);
container_add_child(destination, container); container->width = container->height = 0;
container->saved_width = container->saved_height = 0;
if (destination->type == C_VIEW) {
new_parent = container_add_sibling(destination, container);
} else {
new_parent = destination;
container_add_child(destination, container);
}
} }
wl_signal_emit(&container->events.reparent, old_parent); wl_signal_emit(&container->events.reparent, old_parent);
if (container->type == C_VIEW) { if (container->type == C_VIEW) {