diff --git a/include/sway/commands.h b/include/sway/commands.h
index 226cf932..1654eb48 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -4,6 +4,8 @@
 #include <wlr/util/edges.h>
 #include "config.h"
 
+struct sway_container;
+
 typedef struct cmd_results *sway_cmd(int argc, char **argv);
 
 struct cmd_handler {
@@ -50,8 +52,13 @@ struct cmd_handler *find_handler(char *line, struct cmd_handler *cmd_handlers,
 		int handlers_size);
 /**
  * Parse and executes a command.
+ *
+ * If the command string contains criteria then the command will be executed on
+ * all matching containers. Otherwise, it'll run on the `con` container. If
+ * `con` is NULL then it'll run on the currently focused container.
  */
-struct cmd_results *execute_command(char *command,  struct sway_seat *seat);
+struct cmd_results *execute_command(char *command,  struct sway_seat *seat,
+		struct sway_container *con);
 /**
  * Parse and handles a command during config file loading.
  *
diff --git a/sway/commands.c b/sway/commands.c
index 07169f1e..5b61f73a 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -237,7 +237,8 @@ static void set_config_node(struct sway_node *node) {
 	}
 }
 
-struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
+struct cmd_results *execute_command(char *_exec, struct sway_seat *seat,
+		struct sway_container *con) {
 	// Even though this function will process multiple commands we will only
 	// return the last error, if any (for now). (Since we have access to an
 	// error string we could e.g. concatenate all errors there.)
@@ -256,6 +257,15 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
 		}
 	}
 
+	// This is the container or workspace which this command will run on.
+	// Ignored if the command string contains criteria.
+	struct sway_node *node;
+	if (con) {
+		node = &con->node;
+	} else {
+		node = seat_get_focus_inactive(seat, &root->node);
+	}
+
 	config->handler_context.seat = seat;
 
 	head = exec;
@@ -318,9 +328,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
 			}
 
 			if (!config->handler_context.using_criteria) {
-				// without criteria, the command acts upon the focused
-				// container
-				set_config_node(seat_get_focus_inactive(seat, &root->node));
+				set_config_node(node);
 				struct cmd_results *res = handler->handle(argc-1, argv+1);
 				if (res->status != CMD_SUCCESS) {
 					free_argv(argc, argv);
diff --git a/sway/commands/bind.c b/sway/commands/bind.c
index 047018e0..820c2a6a 100644
--- a/sway/commands/bind.c
+++ b/sway/commands/bind.c
@@ -321,7 +321,7 @@ void seat_execute_command(struct sway_seat *seat, struct sway_binding *binding)
 	}
 
 	config->handler_context.seat = seat;
-	struct cmd_results *results = execute_command(binding->command, NULL);
+	struct cmd_results *results = execute_command(binding->command, NULL, NULL);
 	if (results->status == CMD_SUCCESS) {
 		ipc_event_binding(binding_copy);
 	} else {
diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c
index 00448be7..6d1ccdd7 100644
--- a/sway/desktop/xdg_shell.c
+++ b/sway/desktop/xdg_shell.c
@@ -401,7 +401,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
 	} else {
 		if (view->container->parent) {
 			arrange_container(view->container->parent);
-		} else {
+		} else if (view->container->workspace) {
 			arrange_workspace(view->container->workspace);
 		}
 	}
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c
index d2c9a68b..95ca396c 100644
--- a/sway/desktop/xdg_shell_v6.c
+++ b/sway/desktop/xdg_shell_v6.c
@@ -398,7 +398,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
 	} else {
 		if (view->container->parent) {
 			arrange_container(view->container->parent);
-		} else {
+		} else if (view->container->workspace) {
 			arrange_workspace(view->container->workspace);
 		}
 	}
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 3619f202..a12ac854 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -394,7 +394,7 @@ static void handle_map(struct wl_listener *listener, void *data) {
 	} else {
 		if (view->container->parent) {
 			arrange_container(view->container->parent);
-		} else {
+		} else if (view->container->workspace) {
 			arrange_workspace(view->container->workspace);
 		}
 	}
diff --git a/sway/ipc-server.c b/sway/ipc-server.c
index 8ae265f6..99959c97 100644
--- a/sway/ipc-server.c
+++ b/sway/ipc-server.c
@@ -580,7 +580,7 @@ void ipc_client_handle_command(struct ipc_client *client) {
 	switch (client->current_command) {
 	case IPC_COMMAND:
 	{
-		struct cmd_results *results = execute_command(buf, NULL);
+		struct cmd_results *results = execute_command(buf, NULL, NULL);
 		transaction_commit_dirty();
 		char *json = cmd_results_to_json(results);
 		int length = strlen(json);
diff --git a/sway/main.c b/sway/main.c
index 3d7cd158..990f5f3a 100644
--- a/sway/main.c
+++ b/sway/main.c
@@ -429,7 +429,7 @@ int main(int argc, char **argv) {
 	wlr_log(WLR_DEBUG, "Running deferred commands");
 	while (config->cmd_queue->length) {
 		char *line = config->cmd_queue->items[0];
-		struct cmd_results *res = execute_command(line, NULL);
+		struct cmd_results *res = execute_command(line, NULL, NULL);
 		if (res->status != CMD_SUCCESS) {
 			wlr_log(WLR_ERROR, "Error on line '%s': %s", line, res->error);
 		}
diff --git a/sway/tree/view.c b/sway/tree/view.c
index f61f5c84..e370443c 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -391,8 +391,6 @@ static bool view_has_executed_criteria(struct sway_view *view,
 }
 
 void view_execute_criteria(struct sway_view *view) {
-	struct sway_seat *seat = input_manager_current_seat(input_manager);
-	struct sway_node *prior_focus = seat_get_focus(seat);
 	list_t *criterias = criteria_for_view(view, CT_COMMAND);
 	for (int i = 0; i < criterias->length; i++) {
 		struct criteria *criteria = criterias->items[i];
@@ -403,16 +401,12 @@ void view_execute_criteria(struct sway_view *view) {
 		}
 		wlr_log(WLR_DEBUG, "for_window '%s' matches view %p, cmd: '%s'",
 				criteria->raw, view, criteria->cmdlist);
-		seat_set_focus_container(seat, view->container);
 		list_add(view->executed_criteria, criteria);
-		struct cmd_results *res = execute_command(criteria->cmdlist, NULL);
-		if (res->status != CMD_SUCCESS) {
-			wlr_log(WLR_ERROR, "Command '%s' failed: %s", res->input, res->error);
-		}
+		struct cmd_results *res = execute_command(
+				criteria->cmdlist, NULL, view->container);
 		free_cmd_results(res);
 	}
 	list_free(criterias);
-	seat_set_focus(seat, prior_focus);
 }
 
 static struct sway_workspace *select_workspace(struct sway_view *view) {