diff --git a/include/sway/commands.h b/include/sway/commands.h
index 1e93e2a38..e71a7228e 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -113,6 +113,7 @@ sway_cmd cmd_focus_follows_mouse;
 sway_cmd cmd_focus_wrapping;
 sway_cmd cmd_font;
 sway_cmd cmd_for_window;
+sway_cmd cmd_force_display_urgency_hint;
 sway_cmd cmd_force_focus_wrapping;
 sway_cmd cmd_fullscreen;
 sway_cmd cmd_gaps;
diff --git a/include/sway/config.h b/include/sway/config.h
index 6f6710e92..877683997 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -324,6 +324,7 @@ struct sway_config {
 	char *font;
 	size_t font_height;
 	bool pango_markup;
+	size_t urgent_timeout;
 
 	// Flags
 	bool focus_follows_mouse;
diff --git a/sway/commands.c b/sway/commands.c
index 73c968ead..f1f035745 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -108,6 +108,7 @@ static struct cmd_handler handlers[] = {
 	{ "focus_wrapping", cmd_focus_wrapping },
 	{ "font", cmd_font },
 	{ "for_window", cmd_for_window },
+	{ "force_display_urgency_hint", cmd_force_display_urgency_hint },
 	{ "force_focus_wrapping", cmd_force_focus_wrapping },
 	{ "fullscreen", cmd_fullscreen },
 	{ "gaps", cmd_gaps },
diff --git a/sway/commands/force_display_urgency_hint.c b/sway/commands/force_display_urgency_hint.c
new file mode 100644
index 000000000..a25ffff8d
--- /dev/null
+++ b/sway/commands/force_display_urgency_hint.c
@@ -0,0 +1,28 @@
+#include "log.h"
+#include "sway/commands.h"
+#include "sway/config.h"
+#include "sway/tree/arrange.h"
+#include "sway/tree/container.h"
+#include "sway/tree/view.h"
+#include "sway/tree/layout.h"
+
+struct cmd_results *cmd_force_display_urgency_hint(int argc, char **argv) {
+	struct cmd_results *error = NULL;
+	if ((error = checkarg(argc, "force_display_urgency_hint",
+					EXPECTED_AT_LEAST, 1))) {
+		return error;
+	}
+
+	char *err;
+	int timeout = (int)strtol(argv[0], &err, 10);
+	if (*err) {
+		if (strcmp(err, "ms") != 0) {
+			return cmd_results_new(CMD_INVALID, "force_display_urgency_hint",
+					"Expected 'force_display_urgency_hint <timeout> ms'");
+		}
+	}
+
+	config->urgent_timeout = timeout > 0 ? timeout : 0;
+
+	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
+}
diff --git a/sway/config.c b/sway/config.c
index 005008120..4b8928526 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -186,6 +186,7 @@ static void config_defaults(struct sway_config *config) {
 	config->default_orientation = L_NONE;
 	if (!(config->font = strdup("monospace 10"))) goto cleanup;
 	config->font_height = 17; // height of monospace 10
+	config->urgent_timeout = 500;
 
 	// floating view
 	config->floating_maximum_width = 0;
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c
index 72dc7ca20..bce0a37ba 100644
--- a/sway/desktop/xwayland.c
+++ b/sway/desktop/xwayland.c
@@ -442,6 +442,12 @@ static void handle_set_hints(struct wl_listener *listener, void *data) {
 	if (!xsurface->mapped) {
 		return;
 	}
+	if (!xsurface->hints_urgency && view->urgent_timer) {
+		// The view is is in the timeout period. We'll ignore the request to
+		// unset urgency so that the view remains urgent until the timer clears
+		// it.
+		return;
+	}
 	if (view->allow_request_urgent) {
 		view_set_urgent(view, (bool)xsurface->hints_urgency);
 	}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index eadf3b26c..816429d31 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -679,12 +679,14 @@ void seat_set_focus_warp(struct sway_seat *seat,
 
 	// If urgent, start a timer to unset it
 	if (container && container->type == C_VIEW &&
+			last_workspace && last_workspace != new_workspace &&
 			view_is_urgent(container->sway_view) &&
+			config->urgent_timeout > 0 &&
 			!container->sway_view->urgent_timer) {
 		struct sway_view *view = container->sway_view;
 		view->urgent_timer = wl_event_loop_add_timer(server.wl_event_loop,
 				handle_urgent_timeout, view);
-		wl_event_source_timer_update(view->urgent_timer, 1000);
+		wl_event_source_timer_update(view->urgent_timer, config->urgent_timeout);
 	}
 
 	// If we've focused a floating container, bring it to the front.
diff --git a/sway/meson.build b/sway/meson.build
index c58d3470d..09bc40b84 100644
--- a/sway/meson.build
+++ b/sway/meson.build
@@ -47,6 +47,7 @@ sway_sources = files(
 	'commands/focus_wrapping.c',
 	'commands/font.c',
 	'commands/for_window.c',
+	'commands/force_display_urgency_hint.c',
 	'commands/force_focus_wrapping.c',
 	'commands/fullscreen.c',
 	'commands/gaps.c',