mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #2276 from RyanDwyer/urgency
Implement urgency base functionality
This commit is contained in:
		
						commit
						d6bd314dff
					
				
					 18 changed files with 250 additions and 18 deletions
				
			
		| 
						 | 
				
			
			@ -152,6 +152,7 @@ sway_cmd cmd_swaybg_command;
 | 
			
		|||
sway_cmd cmd_swap;
 | 
			
		||||
sway_cmd cmd_title_format;
 | 
			
		||||
sway_cmd cmd_unmark;
 | 
			
		||||
sway_cmd cmd_urgent;
 | 
			
		||||
sway_cmd cmd_workspace;
 | 
			
		||||
sway_cmd cmd_ws_auto_back_and_forth;
 | 
			
		||||
sway_cmd cmd_workspace_layout;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -316,4 +316,6 @@ void container_floating_move_to(struct sway_container *con,
 | 
			
		|||
 */
 | 
			
		||||
void container_set_dirty(struct sway_container *container);
 | 
			
		||||
 | 
			
		||||
bool container_has_urgent_child(struct sway_container *container);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -70,6 +70,10 @@ struct sway_view {
 | 
			
		|||
	bool border_left;
 | 
			
		||||
	bool border_right;
 | 
			
		||||
 | 
			
		||||
	struct timespec urgent;
 | 
			
		||||
	bool allow_request_urgent;
 | 
			
		||||
	struct wl_event_source *urgent_timer;
 | 
			
		||||
 | 
			
		||||
	bool destroying;
 | 
			
		||||
 | 
			
		||||
	list_t *executed_criteria; // struct criteria *
 | 
			
		||||
| 
						 | 
				
			
			@ -305,4 +309,8 @@ void view_update_marks_textures(struct sway_view *view);
 | 
			
		|||
 */
 | 
			
		||||
bool view_is_visible(struct sway_view *view);
 | 
			
		||||
 | 
			
		||||
void view_set_urgent(struct sway_view *view, bool enable);
 | 
			
		||||
 | 
			
		||||
bool view_is_urgent(struct sway_view *view);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ struct sway_workspace {
 | 
			
		|||
	struct sway_view *fullscreen;
 | 
			
		||||
	struct sway_container *floating;
 | 
			
		||||
	list_t *output_priority;
 | 
			
		||||
	bool urgent;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern char *prev_workspace_name;
 | 
			
		||||
| 
						 | 
				
			
			@ -42,4 +43,7 @@ void workspace_output_add_priority(struct sway_container *workspace,
 | 
			
		|||
 | 
			
		||||
struct sway_container *workspace_output_get_highest_available(
 | 
			
		||||
		struct sway_container *ws, struct sway_container *exclude);
 | 
			
		||||
 | 
			
		||||
void workspace_detect_urgent(struct sway_container *workspace);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -154,6 +154,7 @@ static struct cmd_handler command_handlers[] = {
 | 
			
		|||
	{ "swap", cmd_swap },
 | 
			
		||||
	{ "title_format", cmd_title_format },
 | 
			
		||||
	{ "unmark", cmd_unmark },
 | 
			
		||||
	{ "urgent", cmd_urgent },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int handler_compare(const void *_a, const void *_b) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										36
									
								
								sway/commands/urgent.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								sway/commands/urgent.c
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
#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_urgent(int argc, char **argv) {
 | 
			
		||||
	struct cmd_results *error = NULL;
 | 
			
		||||
	if ((error = checkarg(argc, "urgent", EXPECTED_EQUAL_TO, 1))) {
 | 
			
		||||
		return error;
 | 
			
		||||
	}
 | 
			
		||||
	struct sway_container *container =
 | 
			
		||||
		config->handler_context.current_container;
 | 
			
		||||
	if (container->type != C_VIEW) {
 | 
			
		||||
		return cmd_results_new(CMD_INVALID, "urgent",
 | 
			
		||||
				"Only views can be urgent");
 | 
			
		||||
	}
 | 
			
		||||
	struct sway_view *view = container->sway_view;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(argv[0], "enable") == 0) {
 | 
			
		||||
		view_set_urgent(view, true);
 | 
			
		||||
	} else if (strcmp(argv[0], "disable") == 0) {
 | 
			
		||||
		view_set_urgent(view, false);
 | 
			
		||||
	} else if (strcmp(argv[0], "allow") == 0) {
 | 
			
		||||
		view->allow_request_urgent = true;
 | 
			
		||||
	} else if (strcmp(argv[0], "deny") == 0) {
 | 
			
		||||
		view->allow_request_urgent = false;
 | 
			
		||||
	} else {
 | 
			
		||||
		return cmd_results_new(CMD_INVALID, "urgent",
 | 
			
		||||
				"Expected 'urgent <enable|disable|allow|deny>'");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +46,31 @@ static int regex_cmp(const char *item, const pcre *regex) {
 | 
			
		|||
	return pcre_exec(regex, NULL, item, strlen(item), 0, 0, NULL, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cmp_urgent(const void *_a, const void *_b) {
 | 
			
		||||
	struct sway_view *a = *(void **)_a;
 | 
			
		||||
	struct sway_view *b = *(void **)_b;
 | 
			
		||||
 | 
			
		||||
	if (a->urgent.tv_sec < b->urgent.tv_sec) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	} else if (a->urgent.tv_sec > b->urgent.tv_sec) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	if (a->urgent.tv_nsec < b->urgent.tv_nsec) {
 | 
			
		||||
		return -1;
 | 
			
		||||
	} else if (a->urgent.tv_nsec > b->urgent.tv_nsec) {
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void find_urgent_iterator(struct sway_container *swayc, void *data) {
 | 
			
		||||
	if (swayc->type != C_VIEW || !view_is_urgent(swayc->sway_view)) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	list_t *urgent_views = data;
 | 
			
		||||
	list_add(urgent_views, swayc->sway_view);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool criteria_matches_view(struct criteria *criteria,
 | 
			
		||||
		struct sway_view *view) {
 | 
			
		||||
	if (criteria->title) {
 | 
			
		||||
| 
						 | 
				
			
			@ -133,9 +158,24 @@ static bool criteria_matches_view(struct criteria *criteria,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if (criteria->urgent) {
 | 
			
		||||
		// TODO
 | 
			
		||||
		if (!view_is_urgent(view)) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
		list_t *urgent_views = create_list();
 | 
			
		||||
		container_for_each_descendant_dfs(&root_container,
 | 
			
		||||
				find_urgent_iterator, urgent_views);
 | 
			
		||||
		list_stable_sort(urgent_views, cmp_urgent);
 | 
			
		||||
		struct sway_view *target;
 | 
			
		||||
		if (criteria->urgent == 'o') { // oldest
 | 
			
		||||
			target = urgent_views->items[0];
 | 
			
		||||
		} else { // latest
 | 
			
		||||
			target = urgent_views->items[urgent_views->length - 1];
 | 
			
		||||
		}
 | 
			
		||||
		list_free(urgent_views);
 | 
			
		||||
		if (view != target) {
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (criteria->workspace) {
 | 
			
		||||
		if (!view->swayc) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -553,7 +553,11 @@ static void render_container_simple(struct sway_output *output,
 | 
			
		|||
			struct wlr_texture *marks_texture;
 | 
			
		||||
			struct sway_container_state *state = &child->current;
 | 
			
		||||
 | 
			
		||||
			if (state->focused || parent_focused) {
 | 
			
		||||
			if (view_is_urgent(view)) {
 | 
			
		||||
				colors = &config->border_colors.urgent;
 | 
			
		||||
				title_texture = child->title_urgent;
 | 
			
		||||
				marks_texture = view->marks_urgent;
 | 
			
		||||
			} else if (state->focused || parent_focused) {
 | 
			
		||||
				colors = &config->border_colors.focused;
 | 
			
		||||
				title_texture = child->title_focused;
 | 
			
		||||
				marks_texture = view->marks_focused;
 | 
			
		||||
| 
						 | 
				
			
			@ -607,8 +611,14 @@ static void render_container_tabbed(struct sway_output *output,
 | 
			
		|||
		struct border_colors *colors;
 | 
			
		||||
		struct wlr_texture *title_texture;
 | 
			
		||||
		struct wlr_texture *marks_texture;
 | 
			
		||||
		bool urgent = view ?
 | 
			
		||||
			view_is_urgent(view) : container_has_urgent_child(child);
 | 
			
		||||
 | 
			
		||||
		if (cstate->focused || parent_focused) {
 | 
			
		||||
		if (urgent) {
 | 
			
		||||
			colors = &config->border_colors.urgent;
 | 
			
		||||
			title_texture = child->title_urgent;
 | 
			
		||||
			marks_texture = view ? view->marks_urgent : NULL;
 | 
			
		||||
		} else if (cstate->focused || parent_focused) {
 | 
			
		||||
			colors = &config->border_colors.focused;
 | 
			
		||||
			title_texture = child->title_focused;
 | 
			
		||||
			marks_texture = view ? view->marks_focused : NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -670,8 +680,14 @@ static void render_container_stacked(struct sway_output *output,
 | 
			
		|||
		struct border_colors *colors;
 | 
			
		||||
		struct wlr_texture *title_texture;
 | 
			
		||||
		struct wlr_texture *marks_texture;
 | 
			
		||||
		bool urgent = view ?
 | 
			
		||||
			view_is_urgent(view) : container_has_urgent_child(child);
 | 
			
		||||
 | 
			
		||||
		if (cstate->focused || parent_focused) {
 | 
			
		||||
		if (urgent) {
 | 
			
		||||
			colors = &config->border_colors.urgent;
 | 
			
		||||
			title_texture = child->title_urgent;
 | 
			
		||||
			marks_texture = view ? view->marks_urgent : NULL;
 | 
			
		||||
		} else if (cstate->focused || parent_focused) {
 | 
			
		||||
			colors = &config->border_colors.focused;
 | 
			
		||||
			title_texture = child->title_focused;
 | 
			
		||||
			marks_texture = view ? view->marks_focused : NULL;
 | 
			
		||||
| 
						 | 
				
			
			@ -731,7 +747,11 @@ static void render_floating_container(struct sway_output *soutput,
 | 
			
		|||
		struct wlr_texture *title_texture;
 | 
			
		||||
		struct wlr_texture *marks_texture;
 | 
			
		||||
 | 
			
		||||
		if (con->current.focused) {
 | 
			
		||||
		if (view_is_urgent(view)) {
 | 
			
		||||
			colors = &config->border_colors.urgent;
 | 
			
		||||
			title_texture = con->title_urgent;
 | 
			
		||||
			marks_texture = view->marks_urgent;
 | 
			
		||||
		} else if (con->current.focused) {
 | 
			
		||||
			colors = &config->border_colors.focused;
 | 
			
		||||
			title_texture = con->title_focused;
 | 
			
		||||
			marks_texture = view->marks_focused;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -297,6 +297,10 @@ static void handle_commit(struct wl_listener *listener, void *data) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	view_damage_from(view);
 | 
			
		||||
 | 
			
		||||
	if (view->allow_request_urgent) {
 | 
			
		||||
		view_set_urgent(view, (bool)xsurface->hints_urgency);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_unmap(struct wl_listener *listener, void *data) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -594,6 +594,12 @@ static void seat_send_unfocus(struct sway_container *container,
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_urgent_timeout(void *data) {
 | 
			
		||||
	struct sway_view *view = data;
 | 
			
		||||
	view_set_urgent(view, false);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seat_set_focus_warp(struct sway_seat *seat,
 | 
			
		||||
		struct sway_container *container, bool warp) {
 | 
			
		||||
	if (seat->focused_layer) {
 | 
			
		||||
| 
						 | 
				
			
			@ -671,6 +677,16 @@ void seat_set_focus_warp(struct sway_seat *seat,
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If urgent, start a timer to unset it
 | 
			
		||||
	if (container && container->type == C_VIEW &&
 | 
			
		||||
			view_is_urgent(container->sway_view) &&
 | 
			
		||||
			!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);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// If we've focused a floating container, bring it to the front.
 | 
			
		||||
	// We do this by putting it at the end of the floating list.
 | 
			
		||||
	// This must happen for both the pending and current children lists.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -170,7 +170,8 @@ static void ipc_json_describe_workspace(struct sway_container *workspace,
 | 
			
		|||
	json_object_object_add(object, "output", workspace->parent ?
 | 
			
		||||
			json_object_new_string(workspace->parent->name) : NULL);
 | 
			
		||||
	json_object_object_add(object, "type", json_object_new_string("workspace"));
 | 
			
		||||
	json_object_object_add(object, "urgent", json_object_new_boolean(false));
 | 
			
		||||
	json_object_object_add(object, "urgent",
 | 
			
		||||
			json_object_new_boolean(workspace->sway_workspace->urgent));
 | 
			
		||||
	json_object_object_add(object, "representation", workspace->formatted_title ?
 | 
			
		||||
			json_object_new_string(workspace->formatted_title) : NULL);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -196,6 +197,10 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
 | 
			
		|||
		json_object_object_add(object, "layout",
 | 
			
		||||
			json_object_new_string(ipc_json_layout_description(c->layout)));
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool urgent = c->type == C_VIEW ?
 | 
			
		||||
		view_is_urgent(c->sway_view) : container_has_urgent_child(c);
 | 
			
		||||
	json_object_object_add(object, "urgent", json_object_new_boolean(urgent));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void focus_inactive_children_iterator(struct sway_container *c, void *data) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,6 +77,7 @@ sway_sources = files(
 | 
			
		|||
	'commands/swap.c',
 | 
			
		||||
	'commands/title_format.c',
 | 
			
		||||
	'commands/unmark.c',
 | 
			
		||||
	'commands/urgent.c',
 | 
			
		||||
	'commands/workspace.c',
 | 
			
		||||
	'commands/workspace_layout.c',
 | 
			
		||||
	'commands/ws_auto_back_and_forth.c',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -499,6 +499,11 @@ config after the others, or it will be matched instead of the others.
 | 
			
		|||
	*unmark* will remove _identifier_ from the list of current marks on a
 | 
			
		||||
	window. If _identifier_ is omitted, all marks are removed.
 | 
			
		||||
 | 
			
		||||
*urgent* enable|disable|allow|deny
 | 
			
		||||
	Using _enable_ or _disable_ manually sets or unsets the window's urgent
 | 
			
		||||
	state. Using _allow_ or _deny_ controls the window's ability to set itself
 | 
			
		||||
	as urgent. By default, windows are allowed to set their own urgency.
 | 
			
		||||
 | 
			
		||||
*workspace* [number] <name>
 | 
			
		||||
	Switches to the specified workspace. The string "number" is optional and is
 | 
			
		||||
	used to sort workspaces.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -674,16 +674,23 @@ struct sway_container *floating_container_at(double lx, double ly,
 | 
			
		|||
void container_for_each_descendant_dfs(struct sway_container *container,
 | 
			
		||||
		void (*f)(struct sway_container *container, void *data),
 | 
			
		||||
		void *data) {
 | 
			
		||||
	if (container) {
 | 
			
		||||
	if (!container) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (container->children)  {
 | 
			
		||||
		for (int i = 0; i < container->children->length; ++i) {
 | 
			
		||||
				struct sway_container *child =
 | 
			
		||||
					container->children->items[i];
 | 
			
		||||
			struct sway_container *child = container->children->items[i];
 | 
			
		||||
			container_for_each_descendant_dfs(child, f, data);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (container->type == C_WORKSPACE)  {
 | 
			
		||||
		struct sway_container *floating = container->sway_workspace->floating;
 | 
			
		||||
		for (int i = 0; i < floating->children->length; ++i) {
 | 
			
		||||
			struct sway_container *child = floating->children->items[i];
 | 
			
		||||
			container_for_each_descendant_dfs(child, f, data);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	f(container, data);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void container_for_each_descendant_bfs(struct sway_container *con,
 | 
			
		||||
| 
						 | 
				
			
			@ -1063,6 +1070,8 @@ void container_floating_move_to(struct sway_container *con,
 | 
			
		|||
		container_add_child(new_workspace->sway_workspace->floating, con);
 | 
			
		||||
		arrange_windows(old_workspace);
 | 
			
		||||
		arrange_windows(new_workspace);
 | 
			
		||||
		workspace_detect_urgent(old_workspace);
 | 
			
		||||
		workspace_detect_urgent(new_workspace);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1073,3 +1082,12 @@ void container_set_dirty(struct sway_container *container) {
 | 
			
		|||
	container->dirty = true;
 | 
			
		||||
	list_add(server.dirty_containers, container);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool find_urgent_iterator(struct sway_container *con,
 | 
			
		||||
		void *data) {
 | 
			
		||||
	return con->type == C_VIEW && view_is_urgent(con->sway_view);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool container_has_urgent_child(struct sway_container *container) {
 | 
			
		||||
	return container_find(container, find_urgent_iterator, NULL);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -225,6 +225,15 @@ void container_move_to(struct sway_container *container,
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// Update workspace urgent state
 | 
			
		||||
	struct sway_container *old_workspace = old_parent;
 | 
			
		||||
	if (old_workspace->type != C_WORKSPACE) {
 | 
			
		||||
		old_workspace = container_parent(old_workspace, C_WORKSPACE);
 | 
			
		||||
	}
 | 
			
		||||
	if (new_workspace != old_workspace) {
 | 
			
		||||
		workspace_detect_urgent(new_workspace);
 | 
			
		||||
		workspace_detect_urgent(old_workspace);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool sway_dir_to_wlr(enum movement_direction dir,
 | 
			
		||||
| 
						 | 
				
			
			@ -548,6 +557,8 @@ void container_move(struct sway_container *container,
 | 
			
		|||
	}
 | 
			
		||||
	if (last_ws && next_ws && last_ws != next_ws) {
 | 
			
		||||
		ipc_event_workspace(last_ws, container, "focus");
 | 
			
		||||
		workspace_detect_urgent(last_ws);
 | 
			
		||||
		workspace_detect_urgent(next_ws);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ void view_init(struct sway_view *view, enum sway_view_type type,
 | 
			
		|||
	view->impl = impl;
 | 
			
		||||
	view->executed_criteria = create_list();
 | 
			
		||||
	view->marks = create_list();
 | 
			
		||||
	view->allow_request_urgent = true;
 | 
			
		||||
	wl_signal_init(&view->events.unmap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -609,16 +610,26 @@ void view_unmap(struct sway_view *view) {
 | 
			
		|||
	wl_list_remove(&view->surface_new_subsurface.link);
 | 
			
		||||
	wl_list_remove(&view->container_reparent.link);
 | 
			
		||||
 | 
			
		||||
	if (view->is_fullscreen) {
 | 
			
		||||
	if (view->urgent_timer) {
 | 
			
		||||
		wl_event_source_remove(view->urgent_timer);
 | 
			
		||||
		view->urgent_timer = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct sway_container *parent;
 | 
			
		||||
	struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
 | 
			
		||||
 | 
			
		||||
	if (view->is_fullscreen) {
 | 
			
		||||
		ws->sway_workspace->fullscreen = NULL;
 | 
			
		||||
		container_destroy(view->swayc);
 | 
			
		||||
		parent = container_destroy(view->swayc);
 | 
			
		||||
 | 
			
		||||
		arrange_windows(ws->parent);
 | 
			
		||||
	} else {
 | 
			
		||||
		struct sway_container *parent = container_destroy(view->swayc);
 | 
			
		||||
		arrange_windows(parent);
 | 
			
		||||
	}
 | 
			
		||||
	if (parent->type >= C_WORKSPACE) { // if the workspace still exists
 | 
			
		||||
		workspace_detect_urgent(ws);
 | 
			
		||||
	}
 | 
			
		||||
	transaction_commit_dirty();
 | 
			
		||||
	view->surface = NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1067,3 +1078,29 @@ bool view_is_visible(struct sway_view *view) {
 | 
			
		|||
	}
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void view_set_urgent(struct sway_view *view, bool enable) {
 | 
			
		||||
	if (enable) {
 | 
			
		||||
		struct sway_seat *seat = input_manager_current_seat(input_manager);
 | 
			
		||||
		if (seat_get_focus(seat) == view->swayc) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		clock_gettime(CLOCK_MONOTONIC, &view->urgent);
 | 
			
		||||
	} else {
 | 
			
		||||
		view->urgent = (struct timespec){ 0 };
 | 
			
		||||
		if (view->urgent_timer) {
 | 
			
		||||
			wl_event_source_remove(view->urgent_timer);
 | 
			
		||||
			view->urgent_timer = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	container_damage_whole(view->swayc);
 | 
			
		||||
 | 
			
		||||
	ipc_event_window(view->swayc, "urgent");
 | 
			
		||||
 | 
			
		||||
	struct sway_container *ws = container_parent(view->swayc, C_WORKSPACE);
 | 
			
		||||
	workspace_detect_urgent(ws);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool view_is_urgent(struct sway_view *view) {
 | 
			
		||||
	return view->urgent.tv_sec || view->urgent.tv_nsec;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#include "sway/ipc-server.h"
 | 
			
		||||
#include "sway/tree/arrange.h"
 | 
			
		||||
#include "sway/tree/container.h"
 | 
			
		||||
#include "sway/tree/view.h"
 | 
			
		||||
#include "sway/tree/workspace.h"
 | 
			
		||||
#include "list.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -518,3 +519,13 @@ struct sway_container *workspace_output_get_highest_available(
 | 
			
		|||
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void workspace_detect_urgent(struct sway_container *workspace) {
 | 
			
		||||
	bool new_urgent = container_has_urgent_child(workspace);
 | 
			
		||||
 | 
			
		||||
	if (workspace->sway_workspace->urgent != new_urgent) {
 | 
			
		||||
		workspace->sway_workspace->urgent = new_urgent;
 | 
			
		||||
		ipc_event_workspace(NULL, workspace, "urgent");
 | 
			
		||||
		container_damage_whole(workspace);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,6 +115,18 @@ static void ipc_parse_colors(
 | 
			
		|||
		config->colors.inactive_workspace.text = parse_color(
 | 
			
		||||
				json_object_get_string(inactive_workspace_text));
 | 
			
		||||
	}
 | 
			
		||||
	if (urgent_workspace_border) {
 | 
			
		||||
		config->colors.urgent_workspace.border = parse_color(
 | 
			
		||||
				json_object_get_string(urgent_workspace_border));
 | 
			
		||||
	}
 | 
			
		||||
	if (urgent_workspace_bg) {
 | 
			
		||||
		config->colors.urgent_workspace.background = parse_color(
 | 
			
		||||
				json_object_get_string(urgent_workspace_bg));
 | 
			
		||||
	}
 | 
			
		||||
	if (urgent_workspace_text) {
 | 
			
		||||
		config->colors.urgent_workspace.text = parse_color(
 | 
			
		||||
				json_object_get_string(urgent_workspace_text));
 | 
			
		||||
	}
 | 
			
		||||
	if (binding_mode_border) {
 | 
			
		||||
		config->colors.binding_mode.border = parse_color(
 | 
			
		||||
				json_object_get_string(binding_mode_border));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue