diff --git a/include/con.h b/include/con.h index 0fa660a1..1c7bb932 100644 --- a/include/con.h +++ b/include/con.h @@ -152,6 +152,13 @@ bool con_has_parent(Con *con, Con *parent); */ Con *con_by_window_id(xcb_window_t window); +/** + * Returns the container with the given container ID or NULL if no such + * container exists. + * + */ +Con *con_by_con_id(long target); + /** * Returns the container with the given frame ID or NULL if no such container * exists. diff --git a/src/commands.c b/src/commands.c index bbe7d265..faee3916 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1841,7 +1841,7 @@ void cmd_swap(I3_CMD, const char *mode, const char *arg) { return; } - con = (Con *)target; + con = con_by_con_id(target); } else if (strcmp(mode, "mark") == 0) { con = con_by_mark(arg); } else { diff --git a/src/con.c b/src/con.c index cf923ec8..b520c110 100644 --- a/src/con.c +++ b/src/con.c @@ -557,6 +557,22 @@ Con *con_by_window_id(xcb_window_t window) { return NULL; } +/* + * Returns the container with the given container ID or NULL if no such + * container exists. + * + */ +Con *con_by_con_id(long target) { + Con *con; + TAILQ_FOREACH(con, &all_cons, all_cons) { + if (con == (Con *)target) { + return con; + } + } + + return NULL; +} + /* * Returns the container with the given frame ID or NULL if no such container * exists. diff --git a/testcases/t/265-swap.t b/testcases/t/265-swap.t index f86bba71..e3c8e97c 100644 --- a/testcases/t/265-swap.t +++ b/testcases/t/265-swap.t @@ -32,6 +32,38 @@ my ($nodes, $expected_focus, $A, $B, $F); my ($result); my @urgent; +############################################################################### +# Invalid con_id should not crash i3 +# See issue #2895. +############################################################################### + +$pid = launch_with_config($config); +$ws = fresh_workspace; + +open_window; +cmd "swap container with con_id 1"; + +does_i3_live; +exit_gracefully($pid); + +############################################################################### +# Swap 2 windows in different workspaces using con_id +############################################################################### + +$pid = launch_with_config($config); + +$ws = fresh_workspace; +open_window; +$A = get_focused($ws); + +$ws = fresh_workspace; +open_window; + +cmd "swap container with con_id $A"; +is(get_focused($ws), $A, 'A is now focused'); + +exit_gracefully($pid); + ############################################################################### # Swap two containers next to each other. # Focus should stay on B because both windows are on the focused workspace.