Fix crash when trying to split and float a dock container.
Since splitting a docking container was allowed and successful, the check to prevent floating it fails to work. This causes a crash because the workspace of the container cannot be determined as the dockarea is higher up in the tree than the workspace it belongs to. This patch extends to sanity check to nested dock containers when trying to float a container and also disallows manually splitting a docked container or changing its layout. fixes #2034
This commit is contained in:
parent
d187214562
commit
3d6c76eb93
|
@ -112,6 +112,12 @@ bool con_is_internal(Con *con);
|
||||||
*/
|
*/
|
||||||
bool con_is_floating(Con *con);
|
bool con_is_floating(Con *con);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the container is a docked container.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool con_is_docked(Con *con);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the given container is either floating or inside some floating
|
* Checks if the given container is either floating or inside some floating
|
||||||
* container. It returns the FLOATING_CON container.
|
* container. It returns the FLOATING_CON container.
|
||||||
|
|
|
@ -1188,17 +1188,19 @@ void cmd_move_workspace_to_output(I3_CMD, const char *name) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_split(I3_CMD, const char *direction) {
|
void cmd_split(I3_CMD, const char *direction) {
|
||||||
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
owindow *current;
|
owindow *current;
|
||||||
/* TODO: use matches */
|
|
||||||
LOG("splitting in direction %c\n", direction[0]);
|
LOG("splitting in direction %c\n", direction[0]);
|
||||||
if (match_is_empty(current_match))
|
|
||||||
tree_split(focused, (direction[0] == 'v' ? VERT : HORIZ));
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
|
if (con_is_docked(current->con)) {
|
||||||
|
ELOG("Cannot split a docked container, skipping.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
|
tree_split(current->con, (direction[0] == 'v' ? VERT : HORIZ));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
|
@ -1524,9 +1526,10 @@ void cmd_move_direction(I3_CMD, const char *direction, long move_px) {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void cmd_layout(I3_CMD, const char *layout_str) {
|
void cmd_layout(I3_CMD, const char *layout_str) {
|
||||||
|
HANDLE_EMPTY_MATCH;
|
||||||
|
|
||||||
if (strcmp(layout_str, "stacking") == 0)
|
if (strcmp(layout_str, "stacking") == 0)
|
||||||
layout_str = "stacked";
|
layout_str = "stacked";
|
||||||
owindow *current;
|
|
||||||
layout_t layout;
|
layout_t layout;
|
||||||
/* default is a special case which will be handled in con_set_layout(). */
|
/* default is a special case which will be handled in con_set_layout(). */
|
||||||
if (strcmp(layout_str, "default") == 0)
|
if (strcmp(layout_str, "default") == 0)
|
||||||
|
@ -1546,15 +1549,16 @@ void cmd_layout(I3_CMD, const char *layout_str) {
|
||||||
|
|
||||||
DLOG("changing layout to %s (%d)\n", layout_str, layout);
|
DLOG("changing layout to %s (%d)\n", layout_str, layout);
|
||||||
|
|
||||||
/* check if the match is empty, not if the result is empty */
|
owindow *current;
|
||||||
if (match_is_empty(current_match))
|
|
||||||
con_set_layout(focused, layout);
|
|
||||||
else {
|
|
||||||
TAILQ_FOREACH(current, &owindows, owindows) {
|
TAILQ_FOREACH(current, &owindows, owindows) {
|
||||||
|
if (con_is_docked(current->con)) {
|
||||||
|
ELOG("cannot change layout of a docked container, skipping it.\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
DLOG("matching: %p / %s\n", current->con, current->con->name);
|
||||||
con_set_layout(current->con, layout);
|
con_set_layout(current->con, layout);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
cmd_output->needs_tree_render = true;
|
cmd_output->needs_tree_render = true;
|
||||||
// XXX: default reply for now, make this a better reply
|
// XXX: default reply for now, make this a better reply
|
||||||
|
|
14
src/con.c
14
src/con.c
|
@ -448,6 +448,20 @@ bool con_is_floating(Con *con) {
|
||||||
return (con->floating >= FLOATING_AUTO_ON);
|
return (con->floating >= FLOATING_AUTO_ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true if the container is a docked container.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
bool con_is_docked(Con *con) {
|
||||||
|
if (con->parent == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (con->parent->type == CT_DOCKAREA)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return con_is_docked(con->parent);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if the given container is either floating or inside some floating
|
* Checks if the given container is either floating or inside some floating
|
||||||
* container. It returns the FLOATING_CON container.
|
* container. It returns the FLOATING_CON container.
|
||||||
|
|
|
@ -108,7 +108,7 @@ void floating_check_size(Con *floating_con) {
|
||||||
void floating_enable(Con *con, bool automatic) {
|
void floating_enable(Con *con, bool automatic) {
|
||||||
bool set_focus = (con == focused);
|
bool set_focus = (con == focused);
|
||||||
|
|
||||||
if (con->parent && con->parent->type == CT_DOCKAREA) {
|
if (con_is_docked(con)) {
|
||||||
LOG("Container is a dock window, not enabling floating mode.\n");
|
LOG("Container is a dock window, not enabling floating mode.\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue