--- /dev/null
+language: c
+compiler:
+ - gcc
+ - clang
+before_install:
+ # The travis VMs run on Ubuntu 12.04 which is very old and a huge pain to get
+ # into a state where we can build a recent version of i3 :(.
+ - "echo 'deb http://archive.ubuntu.com/ubuntu/ trusty main universe' | sudo tee /etc/apt/sources.list.d/trusty.list"
+ - "echo 'APT::Default-Release \"precise\";' | sudo tee /etc/apt/apt.conf.d/default-release"
+
+ - "echo 'Package: libc6' > /tmp/pin"
+ - "echo 'Pin: release n=trusty' >> /tmp/pin"
+ - "echo 'Pin-Priority: 999' >> /tmp/pin"
+ - "echo '' >> /tmp/pin"
+
+ - "echo 'Package: libxkbcommon*' >> /tmp/pin"
+ - "echo 'Pin: release n=trusty' >> /tmp/pin"
+ - "echo 'Pin-Priority: 999' >> /tmp/pin"
+ - "echo '' >> /tmp/pin"
+
+ - "echo 'Package: libyajl*' >> /tmp/pin"
+ - "echo 'Pin: release n=trusty' >> /tmp/pin"
+ - "echo 'Pin-Priority: 999' >> /tmp/pin"
+ - "echo '' >> /tmp/pin"
+
+ - "echo 'Package: libxcb-image*' >> /tmp/pin"
+ - "echo 'Pin: release n=trusty' >> /tmp/pin"
+ - "echo 'Pin-Priority: 999' >> /tmp/pin"
+ - "echo '' >> /tmp/pin"
+
+ - sudo cp /tmp/pin /etc/apt/preferences.d/trustypin
+ - sudo apt-get update
+ - sudo apt-get install -t trusty libc6 libc6-dev
+ - sudo apt-get install --no-install-recommends devscripts equivs
+install:
+ - sudo mk-build-deps --install --remove --tool 'apt-get --no-install-recommends' debian/control
+ # Install as many dependencies as possible via apt because cpanm is not very reliable/easy to debug.
+ - sudo apt-get install --no-install-recommends libanyevent-perl libanyevent-i3-perl libextutils-pkgconfig-perl xcb-proto cpanminus xvfb xserver-xephyr xauth libinline-perl libxml-simple-perl libmouse-perl libmousex-nativetraits-perl libextutils-depends-perl perl-modules libtest-deep-perl libtest-exception-perl libxml-parser-perl libtest-simple-perl libtest-fatal-perl libdata-dump-perl libtest-differences-perl libxml-tokeparser-perl libtest-use-ok-perl libipc-run-perl
+ - sudo /bin/sh -c 'cpanm -n -v X11::XCB || true'
+ - sudo /bin/sh -c 'cpanm -n -v AnyEvent::I3 || true'
+script: make -j && (cd testcases && xvfb-run ./complete-run.pl --parallel=1)
+after_failure: cat testcases/latest/complete-run.log
Imagine for example using dmenu: The user starts dmenu by pressing Mod+d, dmenu
gets started with PID 3390. The user then decides to launch Firefox, which
-takes a long time. So he enters firefox into dmenu and presses enter. Firefox
+takes a long time. So they enter firefox into dmenu and press enter. Firefox
gets started with PID 4001. When it finally finishes loading, it creates an X11
window and uses MapWindow to make it visible. This is the first time i3
actually gets in touch with Firefox. It decides to map the window, but it has
# };
# ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
-# ┃ Run dmenu to ask the user for her choice ┃
+# ┃ Run dmenu to ask the user for their choice ┃
# ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
# open2 will just make dmenu’s STDERR go to our own STDERR.
# NOTE: This is not 100% accurate, as it only works for one level
# of nested containers. As this is a common use case, we use 'focus
# parent; $command' nevertheless. For advanced use cases, the user
- # has to modify his config.
+ # has to modify their config.
print "$statement $key focus parent; $command\n";
}
return;
* © 2009-2013 Michael Stapelberg and contributors (see also: LICENSE)
*
* i3-nagbar is a utility which displays a nag message, for example in the case
- * when the user has an error in his configuration file.
+ * when the user has an error in their configuration file.
*
*/
#include <stdio.h>
#######################################################################
# automatically start i3-config-wizard to offer the user to create a
-# keysym-based config which used his favorite modifier (alt or windows)
+# keysym-based config which used their favorite modifier (alt or windows)
#
# i3-config-wizard will not launch if there already is a config file
# in ~/.i3/config.
/** By default, focus follows mouse. If the user explicitly wants to
* turn this off (and instead rely only on the keyboard for changing
- * focus), we allow him to do this with this relatively special option.
+ * focus), we allow them to do this with this relatively special option.
* It is not planned to add any different focus models. */
bool disable_focus_follows_mouse;
/**
* An Assignment makes specific windows go to a specific workspace/output or
* run a command for that window. With this mechanism, the user can -- for
- * example -- assign his browser to workspace "www". Checking if a window is
+ * example -- assign their browser to workspace "www". Checking if a window is
* assigned works by comparing the Match data structure with the window (see
* match_matches_window()).
*
/**
* Kills the commanderror i3-nagbar process, if any.
*
- * Called when reloading/restarting, since the user probably fixed his wrong
+ * Called when reloading/restarting, since the user probably fixed their wrong
* keybindings.
*
* If wait_for_it is set (restarting), this function will waitpid(), otherwise,
*
*/
Con *output_get_content(Con *output);
+
+/**
+ * Returns an 'output' corresponding to one of left/right/down/up or a specific
+ * output name.
+ *
+ */
+Output *get_output_from_string(Output *current_output, const char *output_str);
* The container inherits the layout from the workspace.
*/
Con *workspace_encapsulate(Con *ws);
+
+/**
+ * Move the given workspace to the specified output.
+ * This returns true if and only if moving the workspace was successful.
+ *
+ */
+bool workspace_move_to_output(Con *ws, char *output);
cookie, &error);
if (reply == NULL) {
/* We return a safe estimate because a rendering error is better than
- * a crash. Plus, the user will see the error in his log. */
+ * a crash. Plus, the user will see the error in their log. */
fprintf(stderr, "Could not get text extents (X error code %d)\n",
error->error_code);
return savedFont->specific.xcb.info->max_bounds.character_width * text_len;
* gedit
* mc-edit
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
have $VISUAL or $EDITOR set.
== SEE ALSO
* w3m
* i3-sensible-editor(1)
-Please don’t complain about the order: If the user has any preference, he will
+Please don’t complain about the order: If the user has any preference, they will
have $PAGER set.
== SEE ALSO
* roxterm
* xfce4-terminal
-Please don’t complain about the order: If the user has any preference, she will
-have $TERMINAL set or modified her i3 configuration file.
+Please don’t complain about the order: If the user has any preference, they will
+have $TERMINAL set or modified their i3 configuration file.
== SEE ALSO
return 0;
}
- if (event->child != XCB_NONE) {
- DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
- return route_click(con, event, mod_pressed, CLICK_INSIDE);
- }
-
/* Check if the click was on the decoration of a child */
Con *child;
TAILQ_FOREACH(child, &(con->nodes_head), nodes) {
return route_click(child, event, mod_pressed, CLICK_DECORATION);
}
+ if (event->child != XCB_NONE) {
+ DLOG("event->child not XCB_NONE, so this is an event which originated from a click into the application, but the application did not handle it.\n");
+ return route_click(con, event, mod_pressed, CLICK_INSIDE);
+ }
+
return route_click(con, event, mod_pressed, CLICK_BORDER);
}
return (a - b) > ((fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon);
}
-/*
- * Returns an 'output' corresponding to one of left/right/down/up or a specific
- * output name.
- *
- */
-static Output *get_output_from_string(Output *current_output, const char *output_str) {
- Output *output;
-
- if (strcasecmp(output_str, "left") == 0)
- output = get_output_next_wrap(D_LEFT, current_output);
- else if (strcasecmp(output_str, "right") == 0)
- output = get_output_next_wrap(D_RIGHT, current_output);
- else if (strcasecmp(output_str, "up") == 0)
- output = get_output_next_wrap(D_UP, current_output);
- else if (strcasecmp(output_str, "down") == 0)
- output = get_output_next_wrap(D_DOWN, current_output);
- else
- output = get_output_by_name(output_str);
-
- return output;
-}
-
/*
* Returns the output containing the given container.
*/
HANDLE_EMPTY_MATCH;
- /* get the output */
Output *current_output = NULL;
- Output *output;
-
// TODO: fix the handling of criteria
TAILQ_FOREACH(current, &owindows, owindows)
current_output = get_output_of_con(current->con);
-
assert(current_output != NULL);
- // TODO: clean this up with commands.spec as soon as we switched away from the lex/yacc command parser
- if (strcasecmp(name, "up") == 0)
- output = get_output_next_wrap(D_UP, current_output);
- else if (strcasecmp(name, "down") == 0)
- output = get_output_next_wrap(D_DOWN, current_output);
- else if (strcasecmp(name, "left") == 0)
- output = get_output_next_wrap(D_LEFT, current_output);
- else if (strcasecmp(name, "right") == 0)
- output = get_output_next_wrap(D_RIGHT, current_output);
- else
- output = get_output_by_name(name);
-
+ Output *output = get_output_from_string(current_output, name);
if (!output) {
LOG("No such output found.\n");
ysuccess(false);
owindow *current;
TAILQ_FOREACH(current, &owindows, owindows) {
- Output *current_output = get_output_of_con(current->con);
- if (!current_output) {
- ELOG("Cannot get current output. This is a bug in i3.\n");
- ysuccess(false);
- return;
- }
- Output *output = get_output_from_string(current_output, name);
- if (!output) {
- ELOG("Could not get output from string \"%s\"\n", name);
+ Con *ws = con_get_workspace(current->con);
+ bool success = workspace_move_to_output(ws, name);
+ if (!success) {
+ ELOG("Failed to move workspace to output.\n");
ysuccess(false);
return;
}
-
- Con *content = output_get_content(output->con);
- LOG("got output %p with content %p\n", output, content);
-
- Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head));
- LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name);
-
- Con *ws = con_get_workspace(current->con);
- LOG("should move workspace %p / %s\n", ws, ws->name);
- bool workspace_was_visible = workspace_is_visible(ws);
-
- if (con_num_children(ws->parent) == 1) {
- LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name);
-
- /* check if we can find a workspace assigned to this output */
- bool used_assignment = false;
- struct Workspace_Assignment *assignment;
- TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
- if (strcmp(assignment->output, current_output->name) != 0)
- continue;
-
- /* check if this workspace is already attached to the tree */
- Con *workspace = NULL, *out;
- TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
- GREP_FIRST(workspace, output_get_content(out),
- !strcasecmp(child->name, assignment->name));
- if (workspace != NULL)
- continue;
-
- /* so create the workspace referenced to by this assignment */
- LOG("Creating workspace from assignment %s.\n", assignment->name);
- workspace_get(assignment->name, NULL);
- used_assignment = true;
- break;
- }
-
- /* if we couldn't create the workspace using an assignment, create
- * it on the output */
- if (!used_assignment)
- create_workspace_on_output(current_output, ws->parent);
-
- /* notify the IPC listeners */
- ipc_send_workspace_event("init", ws, NULL);
- }
- DLOG("Detaching\n");
-
- /* detach from the old output and attach to the new output */
- Con *old_content = ws->parent;
- con_detach(ws);
- if (workspace_was_visible) {
- /* The workspace which we just detached was visible, so focus
- * the next one in the focus-stack. */
- Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head));
- LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name);
- workspace_show(focus_ws);
- }
- con_attach(ws, content, false);
-
- /* fix the coordinates of the floating containers */
- Con *floating_con;
- TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
- floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
-
- ipc_send_workspace_event("move", ws, NULL);
- if (workspace_was_visible) {
- /* Focus the moved workspace on the destination output. */
- workspace_show(ws);
- }
-
- /* NB: We cannot simply work with previously_visible_ws since it might
- * have been cleaned up by workspace_show() already, depending on the
- * focus order/number of other workspaces on the output.
- * Instead, we loop through the available workspaces and only work with
- * previously_visible_ws if we still find it. */
- TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
- if (ws != previously_visible_ws)
- continue;
-
- /* Call the on_remove_child callback of the workspace which previously
- * was visible on the destination output. Since it is no longer
- * visible, it might need to get cleaned up. */
- CALL(previously_visible_ws, on_remove_child);
- break;
- }
}
cmd_output->needs_tree_render = true;
Con *parent = workspace->parent;
con_detach(workspace);
con_attach(workspace, parent, false);
+
+ /* Move the workspace to the correct output if it has an assignment */
+ struct Workspace_Assignment *assignment = NULL;
+ TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ if (assignment->output == NULL)
+ continue;
+ if (strcmp(assignment->name, workspace->name) != 0
+ && (!name_is_digits(assignment->name) || ws_name_to_number(assignment->name) != workspace->num)) {
+
+ continue;
+ }
+
+ workspace_move_to_output(workspace, assignment->output);
+ break;
+ }
+
/* Restore the previous focus since con_attach messes with the focus. */
con_focus(previously_focused);
fprintf(stderr, "Migration process exit code was != 0\n");
if (returncode == 2) {
fprintf(stderr, "could not start the migration script\n");
- /* TODO: script was not found. tell the user to fix his system or create a v4 config */
+ /* TODO: script was not found. tell the user to fix their system or create a v4 config */
} else if (returncode == 1) {
fprintf(stderr, "This already was a v4 config. Please add the following line to your config file:\n");
fprintf(stderr, "# i3 config file (v4)\n");
- /* TODO: nag the user with a message to include a hint for i3 in his config file */
+ /* TODO: nag the user with a message to include a hint for i3 in their config file */
}
return NULL;
}
return;
}
- /* Focus the output on which the user moved his cursor */
+ /* Focus the output on which the user moved their cursor */
Con *old_focused = focused;
Con *next = con_descend_focused(output_get_content(output->con));
/* Since we are switching outputs, this *must* be a different workspace, so
enter_child = true;
}
- /* If not, then the user moved his cursor to the root window. In that case, we adjust c_ws */
+ /* If not, then the user moved their cursor to the root window. In that case, we adjust c_ws */
if (con == NULL) {
DLOG("Getting screen at %d x %d\n", event->root_x, event->root_y);
check_crossing_screen_boundary(event->root_x, event->root_y);
handle_motion_notify((xcb_motion_notify_event_t *)event);
break;
- /* Enter window = user moved his mouse over the window */
+ /* Enter window = user moved their mouse over the window */
case XCB_ENTER_NOTIFY:
handle_enter_notify((xcb_enter_notify_event_t *)event);
break;
ELOG("Could not setup signal handler");
/* Ignore SIGPIPE to survive errors when an IPC client disconnects
- * while we are sending him a message */
+ * while we are sending them a message */
signal(SIGPIPE, SIG_IGN);
/* Autostarting exec-lines */
return NULL;
}
+
+/*
+ * Returns an 'output' corresponding to one of left/right/down/up or a specific
+ * output name.
+ *
+ */
+Output *get_output_from_string(Output *current_output, const char *output_str) {
+ Output *output;
+
+ if (strcasecmp(output_str, "left") == 0)
+ output = get_output_next_wrap(D_LEFT, current_output);
+ else if (strcasecmp(output_str, "right") == 0)
+ output = get_output_next_wrap(D_RIGHT, current_output);
+ else if (strcasecmp(output_str, "up") == 0)
+ output = get_output_next_wrap(D_UP, current_output);
+ else if (strcasecmp(output_str, "down") == 0)
+ output = get_output_next_wrap(D_DOWN, current_output);
+ else
+ output = get_output_by_name(output_str);
+
+ return output;
+}
return new;
}
+
+/**
+ * Move the given workspace to the specified output.
+ * This returns true if and only if moving the workspace was successful.
+ */
+bool workspace_move_to_output(Con *ws, char *name) {
+ LOG("Trying to move workspace %p / %s to output \"%s\".\n", ws, ws->name, name);
+
+ Con *current_output_con = con_get_output(ws);
+ if (!current_output_con) {
+ ELOG("Could not get the output container for workspace %p / %s.\n", ws, ws->name);
+ return false;
+ }
+
+ Output *current_output = get_output_by_name(current_output_con->name);
+ if (!current_output) {
+ ELOG("Cannot get current output. This is a bug in i3.\n");
+ return false;
+ }
+ Output *output = get_output_from_string(current_output, name);
+ if (!output) {
+ ELOG("Could not get output from string \"%s\"\n", name);
+ return false;
+ }
+
+ Con *content = output_get_content(output->con);
+ LOG("got output %p with content %p\n", output, content);
+
+ Con *previously_visible_ws = TAILQ_FIRST(&(content->nodes_head));
+ LOG("Previously visible workspace = %p / %s\n", previously_visible_ws, previously_visible_ws->name);
+
+ bool workspace_was_visible = workspace_is_visible(ws);
+ if (con_num_children(ws->parent) == 1) {
+ LOG("Creating a new workspace to replace \"%s\" (last on its output).\n", ws->name);
+
+ /* check if we can find a workspace assigned to this output */
+ bool used_assignment = false;
+ struct Workspace_Assignment *assignment;
+ TAILQ_FOREACH(assignment, &ws_assignments, ws_assignments) {
+ if (assignment->output == NULL || strcmp(assignment->output, current_output->name) != 0)
+ continue;
+
+ /* check if this workspace is already attached to the tree */
+ Con *workspace = NULL, *out;
+ TAILQ_FOREACH(out, &(croot->nodes_head), nodes)
+ GREP_FIRST(workspace, output_get_content(out),
+ !strcasecmp(child->name, assignment->name));
+ if (workspace != NULL)
+ continue;
+
+ /* so create the workspace referenced to by this assignment */
+ LOG("Creating workspace from assignment %s.\n", assignment->name);
+ workspace_get(assignment->name, NULL);
+ used_assignment = true;
+ break;
+ }
+
+ /* if we couldn't create the workspace using an assignment, create
+ * it on the output */
+ if (!used_assignment)
+ create_workspace_on_output(current_output, ws->parent);
+
+ /* notify the IPC listeners */
+ ipc_send_workspace_event("init", ws, NULL);
+ }
+ DLOG("Detaching\n");
+
+ /* detach from the old output and attach to the new output */
+ Con *old_content = ws->parent;
+ con_detach(ws);
+ if (workspace_was_visible) {
+ /* The workspace which we just detached was visible, so focus
+ * the next one in the focus-stack. */
+ Con *focus_ws = TAILQ_FIRST(&(old_content->focus_head));
+ LOG("workspace was visible, focusing %p / %s now\n", focus_ws, focus_ws->name);
+ workspace_show(focus_ws);
+ }
+ con_attach(ws, content, false);
+
+ /* fix the coordinates of the floating containers */
+ Con *floating_con;
+ TAILQ_FOREACH(floating_con, &(ws->floating_head), floating_windows)
+ floating_fix_coordinates(floating_con, &(old_content->rect), &(content->rect));
+
+ ipc_send_workspace_event("move", ws, NULL);
+ if (workspace_was_visible) {
+ /* Focus the moved workspace on the destination output. */
+ workspace_show(ws);
+ }
+
+ /* NB: We cannot simply work with previously_visible_ws since it might
+ * have been cleaned up by workspace_show() already, depending on the
+ * focus order/number of other workspaces on the output.
+ * Instead, we loop through the available workspaces and only work with
+ * previously_visible_ws if we still find it. */
+ TAILQ_FOREACH(ws, &(content->nodes_head), nodes) {
+ if (ws != previously_visible_ws)
+ continue;
+
+ /* Call the on_remove_child callback of the workspace which previously
+ * was visible on the destination output. Since it is no longer
+ * visible, it might need to get cleaned up. */
+ CALL(previously_visible_ws, on_remove_child);
+ break;
+ }
+
+ return true;
+}
END { cleanup() }
-exit 0;
+exit ($aggregator->failed > 0);
#
# Takes a test from the beginning of @testfiles and runs it.
}
sub cleanup {
+ my $exitcode = $?;
$_->() for our @CLEANUP;
- exit;
+ exit $exitcode;
}
# must be in a begin block because we C<exit 0> above
my $tests_total;
+sub noninteractive {
+ # CONTINUOUS_INTEGRATION gets set when running under Travis, see
+ # http://docs.travis-ci.com/user/ci-environment/ and
+ # https://github.com/travis-ci/travis-ci/issues/1337
+ return (! -t STDOUT) || $ENV{CONTINUOUS_INTEGRATION} eq 'true';
+}
+
# setup %ansi_line_upwards to map all working displays to the
# specific movement commands and initialize all status lines
sub status_init {
my $displays = $args{displays};
$tests_total = $args{tests};
+ return if noninteractive();
+
for my $n (1 .. @$displays) {
# since we are moving upwards, get $display in reverse order
my $display = $displays->[-$n];
my ($display, $msg) = @_;
my $status = "[$display] $msg";
+ return $status if noninteractive();
+
print
$ansi_save_cursor,
$ansi_line_upwards{$display},
sub status_completed {
my $num = shift;
+
+ return if noninteractive();
+
print
$ansi_save_cursor,
$ansi_clear_line,
--- /dev/null
+#!perl
+# vim:ts=4:sw=4:expandtab
+#
+# Please read the following documents before working on tests:
+# • http://build.i3wm.org/docs/testsuite.html
+# (or docs/testsuite)
+#
+# • http://build.i3wm.org/docs/lib-i3test.html
+# (alternatively: perldoc ./testcases/lib/i3test.pm)
+#
+# • http://build.i3wm.org/docs/ipc.html
+# (or docs/ipc)
+#
+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf
+# (unless you are already familiar with Perl)
+#
+#
+# Tests that workspaces are moved to the assigned output if they
+# are renamed to an assigned name.
+# Ticket: #1473
+
+use i3test i3_autostart => 0;
+
+my $config = <<EOT;
+# i3 config file (v4)
+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1
+fake-outputs 1024x768+0+0,1024x768+1024+0
+
+workspace 1 output fake-0
+workspace 2 output fake-1
+workspace 3:foo output fake-1
+workspace baz output fake-1
+EOT
+
+my $pid = launch_with_config($config);
+my $i3 = i3(get_socket_path());
+$i3->connect->recv;
+
+# Returns the name of the output on which this workspace resides
+sub get_output_for_workspace {
+ my $ws_name = shift @_;
+
+ foreach (grep { not $_->{name} =~ /^__/ } @{$i3->get_tree->recv->{nodes}}) {
+ my $output = $_->{name};
+ foreach (grep { $_->{name} =~ "content" } @{$_->{nodes}}) {
+ return $output if $_->{nodes}[0]->{name} =~ $ws_name;
+ }
+ }
+}
+
+##########################################################################
+# Renaming the workspace to an unassigned name does not move the workspace
+# (regression test)
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to unassigned';
+is(get_output_for_workspace('unassigned'), 'fake-0',
+ 'Unassigned workspace should stay on its output when being renamed');
+
+##########################################################################
+# Renaming a workspace by number only triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to 2';
+is(get_output_for_workspace('2'), 'fake-1',
+ 'Renaming the workspace to a number should move it to the assigned output');
+
+##########################################################################
+# Renaming a workspace by number and name triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to "2:foo"';
+is(get_output_for_workspace('2:foo'), 'fake-1',
+ 'Renaming the workspace to a number and name should move it to the assigned output');
+
+##########################################################################
+# Renaming a workspace by name only triggers the assignment
+##########################################################################
+
+cmd 'focus output fake-0';
+cmd 'rename workspace to baz';
+is(get_output_for_workspace('baz'), 'fake-1',
+ 'Renaming the workspace to a number and name should move it to the assigned output');
+
+
+exit_gracefully($pid);
+done_testing;