mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #3041 from RyanDwyer/marks-props-to-container
Move view marks properties to container struct
This commit is contained in:
		
						commit
						8ad06f0ec5
					
				
					 16 changed files with 236 additions and 261 deletions
				
			
		| 
						 | 
					@ -127,6 +127,12 @@ struct sway_container {
 | 
				
			||||||
	size_t title_height;
 | 
						size_t title_height;
 | 
				
			||||||
	size_t title_baseline;
 | 
						size_t title_baseline;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_t *marks; // char *
 | 
				
			||||||
 | 
						struct wlr_texture *marks_focused;
 | 
				
			||||||
 | 
						struct wlr_texture *marks_focused_inactive;
 | 
				
			||||||
 | 
						struct wlr_texture *marks_unfocused;
 | 
				
			||||||
 | 
						struct wlr_texture *marks_urgent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct {
 | 
						struct {
 | 
				
			||||||
		struct wl_signal destroy;
 | 
							struct wl_signal destroy;
 | 
				
			||||||
	} events;
 | 
						} events;
 | 
				
			||||||
| 
						 | 
					@ -304,4 +310,26 @@ struct sway_container *container_split(struct sway_container *child,
 | 
				
			||||||
bool container_is_transient_for(struct sway_container *child,
 | 
					bool container_is_transient_for(struct sway_container *child,
 | 
				
			||||||
		struct sway_container *ancestor);
 | 
							struct sway_container *ancestor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Find any container that has the given mark and return it.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					struct sway_container *container_find_mark(char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Find any container that has the given mark and remove the mark from the
 | 
				
			||||||
 | 
					 * container. Returns true if it matched a container.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool container_find_and_unmark(char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Remove all marks from the container.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void container_clear_marks(struct sway_container *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool container_has_mark(struct sway_container *container, char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void container_add_mark(struct sway_container *container, char *mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void container_update_marks_textures(struct sway_container *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -100,12 +100,6 @@ struct sway_view {
 | 
				
			||||||
	bool destroying;
 | 
						bool destroying;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_t *executed_criteria; // struct criteria *
 | 
						list_t *executed_criteria; // struct criteria *
 | 
				
			||||||
	list_t *marks;             // char *
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct wlr_texture *marks_focused;
 | 
					 | 
				
			||||||
	struct wlr_texture *marks_focused_inactive;
 | 
					 | 
				
			||||||
	struct wlr_texture *marks_unfocused;
 | 
					 | 
				
			||||||
	struct wlr_texture *marks_urgent;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
 | 
							struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6;
 | 
				
			||||||
| 
						 | 
					@ -352,28 +346,6 @@ void view_update_title(struct sway_view *view, bool force);
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void view_execute_criteria(struct sway_view *view);
 | 
					void view_execute_criteria(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Find any view that has the given mark and return it.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct sway_view *view_find_mark(char *mark);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Find any view that has the given mark and remove the mark from the view.
 | 
					 | 
				
			||||||
 * Returns true if it matched a view.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
bool view_find_and_unmark(char *mark);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * Remove all marks from the view.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void view_clear_marks(struct sway_view *view);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool view_has_mark(struct sway_view *view, char *mark);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_add_mark(struct sway_view *view, char *mark);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_update_marks_textures(struct sway_view *view);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Returns true if there's a possibility the view may be rendered on screen.
 | 
					 * Returns true if there's a possibility the view may be rendered on screen.
 | 
				
			||||||
 * Intended for damage tracking.
 | 
					 * Intended for damage tracking.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,9 +5,7 @@
 | 
				
			||||||
#include "sway/tree/container.h"
 | 
					#include "sway/tree/container.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rebuild_textures_iterator(struct sway_container *con, void *data) {
 | 
					static void rebuild_textures_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
	if (con->view) {
 | 
						container_update_marks_textures(con);
 | 
				
			||||||
		view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	container_update_title_textures(con);
 | 
						container_update_title_textures(con);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,11 +19,10 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
 | 
				
			||||||
		return error;
 | 
							return error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_container *container = config->handler_context.container;
 | 
						struct sway_container *container = config->handler_context.container;
 | 
				
			||||||
	if (!container || !container->view) {
 | 
						if (!container) {
 | 
				
			||||||
		return cmd_results_new(CMD_INVALID, "mark",
 | 
							return cmd_results_new(CMD_INVALID, "mark",
 | 
				
			||||||
				"Only views can have marks");
 | 
									"Only containers can have marks");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_view *view = container->view;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool add = false, toggle = false;
 | 
						bool add = false, toggle = false;
 | 
				
			||||||
	while (argc > 0 && strncmp(*argv, "--", 2) == 0) {
 | 
						while (argc > 0 && strncmp(*argv, "--", 2) == 0) {
 | 
				
			||||||
| 
						 | 
					@ -47,22 +46,24 @@ struct cmd_results *cmd_mark(int argc, char **argv) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char *mark = join_args(argv, argc);
 | 
						char *mark = join_args(argv, argc);
 | 
				
			||||||
	bool had_mark = view_has_mark(view, mark);
 | 
						bool had_mark = container_has_mark(container, mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!add) {
 | 
						if (!add) {
 | 
				
			||||||
		// Replacing
 | 
							// Replacing
 | 
				
			||||||
		view_clear_marks(view);
 | 
							container_clear_marks(container);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view_find_and_unmark(mark);
 | 
						container_find_and_unmark(mark);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!toggle || !had_mark) {
 | 
						if (!toggle || !had_mark) {
 | 
				
			||||||
		view_add_mark(view, mark);
 | 
							container_add_mark(container, mark);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	free(mark);
 | 
						free(mark);
 | 
				
			||||||
	view_update_marks_textures(view);
 | 
						container_update_marks_textures(container);
 | 
				
			||||||
	view_execute_criteria(view);
 | 
						if (container->view) {
 | 
				
			||||||
 | 
							view_execute_criteria(container->view);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
						return cmd_results_new(CMD_SUCCESS, NULL, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -488,12 +488,12 @@ static struct cmd_results *cmd_move_container(int argc, char **argv) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		destination = seat_get_focus_inactive(seat, &new_output->node);
 | 
							destination = seat_get_focus_inactive(seat, &new_output->node);
 | 
				
			||||||
	} else if (strcasecmp(argv[1], "mark") == 0) {
 | 
						} else if (strcasecmp(argv[1], "mark") == 0) {
 | 
				
			||||||
		struct sway_view *dest_view = view_find_mark(argv[2]);
 | 
							struct sway_container *dest_con = container_find_mark(argv[2]);
 | 
				
			||||||
		if (dest_view == NULL) {
 | 
							if (dest_con == NULL) {
 | 
				
			||||||
			return cmd_results_new(CMD_FAILURE, "move",
 | 
								return cmd_results_new(CMD_FAILURE, "move",
 | 
				
			||||||
					"Mark '%s' not found", argv[2]);
 | 
										"Mark '%s' not found", argv[2]);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		destination = &dest_view->container->node;
 | 
							destination = &dest_con->node;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return cmd_results_new(CMD_INVALID, "move", expected_syntax);
 | 
							return cmd_results_new(CMD_INVALID, "move", expected_syntax);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,9 +10,7 @@
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rebuild_textures_iterator(struct sway_container *con, void *data) {
 | 
					static void rebuild_textures_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
	if (con->view) {
 | 
						container_update_marks_textures(con);
 | 
				
			||||||
		view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	container_update_title_textures(con);
 | 
						container_update_title_textures(con);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,9 +11,7 @@
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rebuild_marks_iterator(struct sway_container *con, void *data) {
 | 
					static void rebuild_marks_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
	if (con->view) {
 | 
						container_update_marks_textures(con);
 | 
				
			||||||
		view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd_results *cmd_show_marks(int argc, char **argv) {
 | 
					struct cmd_results *cmd_show_marks(int argc, char **argv) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -159,8 +159,8 @@ static bool test_id(struct sway_container *container, void *id) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool test_mark(struct sway_container *container, void *mark) {
 | 
					static bool test_mark(struct sway_container *container, void *mark) {
 | 
				
			||||||
	if (container->view && container->view->marks->length) {
 | 
						if (container->marks->length) {
 | 
				
			||||||
		return !list_seq_find(container->view->marks,
 | 
							return !list_seq_find(container->marks,
 | 
				
			||||||
				(int (*)(const void *, const void *))strcmp, mark);
 | 
									(int (*)(const void *, const void *))strcmp, mark);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,10 +9,8 @@
 | 
				
			||||||
#include "stringop.h"
 | 
					#include "stringop.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void remove_all_marks_iterator(struct sway_container *con, void *data) {
 | 
					static void remove_all_marks_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
	if (con->view) {
 | 
						container_clear_marks(con);
 | 
				
			||||||
		view_clear_marks(con->view);
 | 
						container_update_marks_textures(con);
 | 
				
			||||||
		view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// unmark                  Remove all marks from all views
 | 
					// unmark                  Remove all marks from all views
 | 
				
			||||||
| 
						 | 
					@ -21,15 +19,10 @@ static void remove_all_marks_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
// [criteria] unmark foo   Remove single mark from matched view
 | 
					// [criteria] unmark foo   Remove single mark from matched view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct cmd_results *cmd_unmark(int argc, char **argv) {
 | 
					struct cmd_results *cmd_unmark(int argc, char **argv) {
 | 
				
			||||||
	// Determine the view
 | 
						// Determine the container
 | 
				
			||||||
	struct sway_view *view = NULL;
 | 
						struct sway_container *con = NULL;
 | 
				
			||||||
	if (config->handler_context.using_criteria) {
 | 
						if (config->handler_context.using_criteria) {
 | 
				
			||||||
		struct sway_container *container = config->handler_context.container;
 | 
							con = config->handler_context.container;
 | 
				
			||||||
		if (!container || !container->view) {
 | 
					 | 
				
			||||||
			return cmd_results_new(CMD_INVALID, "unmark",
 | 
					 | 
				
			||||||
					"Only views can have marks");
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		view = container->view;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Determine the mark
 | 
						// Determine the mark
 | 
				
			||||||
| 
						 | 
					@ -38,20 +31,20 @@ struct cmd_results *cmd_unmark(int argc, char **argv) {
 | 
				
			||||||
		mark = join_args(argv, argc);
 | 
							mark = join_args(argv, argc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view && mark) {
 | 
						if (con && mark) {
 | 
				
			||||||
		// Remove the mark from the given view
 | 
							// Remove the mark from the given container
 | 
				
			||||||
		if (view_has_mark(view, mark)) {
 | 
							if (container_has_mark(con, mark)) {
 | 
				
			||||||
			view_find_and_unmark(mark);
 | 
								container_find_and_unmark(mark);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (view && !mark) {
 | 
						} else if (con && !mark) {
 | 
				
			||||||
		// Clear all marks from the given view
 | 
							// Clear all marks from the given container
 | 
				
			||||||
		view_clear_marks(view);
 | 
							container_clear_marks(con);
 | 
				
			||||||
		view_update_marks_textures(view);
 | 
							container_update_marks_textures(con);
 | 
				
			||||||
	} else if (!view && mark) {
 | 
						} else if (!con && mark) {
 | 
				
			||||||
		// Remove mark from whichever view has it
 | 
							// Remove mark from whichever container has it
 | 
				
			||||||
		view_find_and_unmark(mark);
 | 
							container_find_and_unmark(mark);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// Remove all marks from all views
 | 
							// Remove all marks from all containers
 | 
				
			||||||
		root_for_each_container(remove_all_marks_iterator, NULL);
 | 
							root_for_each_container(remove_all_marks_iterator, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	free(mark);
 | 
						free(mark);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,8 +121,9 @@ static bool criteria_matches_view(struct criteria *criteria,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (criteria->con_mark) {
 | 
						if (criteria->con_mark) {
 | 
				
			||||||
		bool exists = false;
 | 
							bool exists = false;
 | 
				
			||||||
		for (int i = 0; i < view->marks->length; ++i) {
 | 
							struct sway_container *con = view->container;
 | 
				
			||||||
			if (regex_cmp(view->marks->items[i], criteria->con_mark) == 0) {
 | 
							for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
 | 
								if (regex_cmp(con->marks->items[i], criteria->con_mark) == 0) {
 | 
				
			||||||
				exists = true;
 | 
									exists = true;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -532,9 +532,7 @@ static void handle_transform(struct wl_listener *listener, void *data) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void update_textures(struct sway_container *con, void *data) {
 | 
					static void update_textures(struct sway_container *con, void *data) {
 | 
				
			||||||
	container_update_title_textures(con);
 | 
						container_update_title_textures(con);
 | 
				
			||||||
	if (con->view) {
 | 
						container_update_marks_textures(con);
 | 
				
			||||||
		view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void handle_scale(struct wl_listener *listener, void *data) {
 | 
					static void handle_scale(struct wl_listener *listener, void *data) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -625,19 +625,19 @@ static void render_containers_linear(struct sway_output *output,
 | 
				
			||||||
			if (view_is_urgent(view)) {
 | 
								if (view_is_urgent(view)) {
 | 
				
			||||||
				colors = &config->border_colors.urgent;
 | 
									colors = &config->border_colors.urgent;
 | 
				
			||||||
				title_texture = child->title_urgent;
 | 
									title_texture = child->title_urgent;
 | 
				
			||||||
				marks_texture = view->marks_urgent;
 | 
									marks_texture = child->marks_urgent;
 | 
				
			||||||
			} else if (state->focused || parent->focused) {
 | 
								} else if (state->focused || parent->focused) {
 | 
				
			||||||
				colors = &config->border_colors.focused;
 | 
									colors = &config->border_colors.focused;
 | 
				
			||||||
				title_texture = child->title_focused;
 | 
									title_texture = child->title_focused;
 | 
				
			||||||
				marks_texture = view->marks_focused;
 | 
									marks_texture = child->marks_focused;
 | 
				
			||||||
			} else if (child == parent->active_child) {
 | 
								} else if (child == parent->active_child) {
 | 
				
			||||||
				colors = &config->border_colors.focused_inactive;
 | 
									colors = &config->border_colors.focused_inactive;
 | 
				
			||||||
				title_texture = child->title_focused_inactive;
 | 
									title_texture = child->title_focused_inactive;
 | 
				
			||||||
				marks_texture = view->marks_focused_inactive;
 | 
									marks_texture = child->marks_focused_inactive;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				colors = &config->border_colors.unfocused;
 | 
									colors = &config->border_colors.unfocused;
 | 
				
			||||||
				title_texture = child->title_unfocused;
 | 
									title_texture = child->title_unfocused;
 | 
				
			||||||
				marks_texture = view->marks_unfocused;
 | 
									marks_texture = child->marks_unfocused;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (state->border == B_NORMAL) {
 | 
								if (state->border == B_NORMAL) {
 | 
				
			||||||
| 
						 | 
					@ -681,19 +681,19 @@ static void render_containers_tabbed(struct sway_output *output,
 | 
				
			||||||
		if (urgent) {
 | 
							if (urgent) {
 | 
				
			||||||
			colors = &config->border_colors.urgent;
 | 
								colors = &config->border_colors.urgent;
 | 
				
			||||||
			title_texture = child->title_urgent;
 | 
								title_texture = child->title_urgent;
 | 
				
			||||||
			marks_texture = view ? view->marks_urgent : NULL;
 | 
								marks_texture = child->marks_urgent;
 | 
				
			||||||
		} else if (cstate->focused || parent->focused) {
 | 
							} else if (cstate->focused || parent->focused) {
 | 
				
			||||||
			colors = &config->border_colors.focused;
 | 
								colors = &config->border_colors.focused;
 | 
				
			||||||
			title_texture = child->title_focused;
 | 
								title_texture = child->title_focused;
 | 
				
			||||||
			marks_texture = view ? view->marks_focused : NULL;
 | 
								marks_texture = child->marks_focused;
 | 
				
			||||||
		} else if (child == parent->active_child) {
 | 
							} else if (child == parent->active_child) {
 | 
				
			||||||
			colors = &config->border_colors.focused_inactive;
 | 
								colors = &config->border_colors.focused_inactive;
 | 
				
			||||||
			title_texture = child->title_focused_inactive;
 | 
								title_texture = child->title_focused_inactive;
 | 
				
			||||||
			marks_texture = view ? view->marks_focused_inactive : NULL;
 | 
								marks_texture = child->marks_focused_inactive;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			colors = &config->border_colors.unfocused;
 | 
								colors = &config->border_colors.unfocused;
 | 
				
			||||||
			title_texture = child->title_unfocused;
 | 
								title_texture = child->title_unfocused;
 | 
				
			||||||
			marks_texture = view ? view->marks_unfocused : NULL;
 | 
								marks_texture = child->marks_unfocused;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int x = cstate->con_x + tab_width * i;
 | 
							int x = cstate->con_x + tab_width * i;
 | 
				
			||||||
| 
						 | 
					@ -746,19 +746,19 @@ static void render_containers_stacked(struct sway_output *output,
 | 
				
			||||||
		if (urgent) {
 | 
							if (urgent) {
 | 
				
			||||||
			colors = &config->border_colors.urgent;
 | 
								colors = &config->border_colors.urgent;
 | 
				
			||||||
			title_texture = child->title_urgent;
 | 
								title_texture = child->title_urgent;
 | 
				
			||||||
			marks_texture = view ? view->marks_urgent : NULL;
 | 
								marks_texture = child->marks_urgent;
 | 
				
			||||||
		} else if (cstate->focused || parent->focused) {
 | 
							} else if (cstate->focused || parent->focused) {
 | 
				
			||||||
			colors = &config->border_colors.focused;
 | 
								colors = &config->border_colors.focused;
 | 
				
			||||||
			title_texture = child->title_focused;
 | 
								title_texture = child->title_focused;
 | 
				
			||||||
			marks_texture = view ? view->marks_focused : NULL;
 | 
								marks_texture = child->marks_focused;
 | 
				
			||||||
		} else if (child == parent->active_child) {
 | 
							} else if (child == parent->active_child) {
 | 
				
			||||||
			colors = &config->border_colors.focused_inactive;
 | 
								colors = &config->border_colors.focused_inactive;
 | 
				
			||||||
			title_texture = child->title_focused_inactive;
 | 
								title_texture = child->title_focused_inactive;
 | 
				
			||||||
			marks_texture = view ? view->marks_focused_inactive : NULL;
 | 
								marks_texture = child->marks_focused_inactive;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			colors = &config->border_colors.unfocused;
 | 
								colors = &config->border_colors.unfocused;
 | 
				
			||||||
			title_texture = child->title_unfocused;
 | 
								title_texture = child->title_unfocused;
 | 
				
			||||||
			marks_texture = view ? view->marks_unfocused : NULL;
 | 
								marks_texture = child->marks_unfocused;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int y = parent->box.y + titlebar_height * i;
 | 
							int y = parent->box.y + titlebar_height * i;
 | 
				
			||||||
| 
						 | 
					@ -841,15 +841,15 @@ static void render_floating_container(struct sway_output *soutput,
 | 
				
			||||||
		if (view_is_urgent(view)) {
 | 
							if (view_is_urgent(view)) {
 | 
				
			||||||
			colors = &config->border_colors.urgent;
 | 
								colors = &config->border_colors.urgent;
 | 
				
			||||||
			title_texture = con->title_urgent;
 | 
								title_texture = con->title_urgent;
 | 
				
			||||||
			marks_texture = view->marks_urgent;
 | 
								marks_texture = con->marks_urgent;
 | 
				
			||||||
		} else if (con->current.focused) {
 | 
							} else if (con->current.focused) {
 | 
				
			||||||
			colors = &config->border_colors.focused;
 | 
								colors = &config->border_colors.focused;
 | 
				
			||||||
			title_texture = con->title_focused;
 | 
								title_texture = con->title_focused;
 | 
				
			||||||
			marks_texture = view->marks_focused;
 | 
								marks_texture = con->marks_focused;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			colors = &config->border_colors.unfocused;
 | 
								colors = &config->border_colors.unfocused;
 | 
				
			||||||
			title_texture = con->title_unfocused;
 | 
								title_texture = con->title_unfocused;
 | 
				
			||||||
			marks_texture = view->marks_unfocused;
 | 
								marks_texture = con->marks_unfocused;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (con->current.border == B_NORMAL) {
 | 
							if (con->current.border == B_NORMAL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -230,9 +230,9 @@ static void ipc_json_describe_view(struct sway_container *c, json_object *object
 | 
				
			||||||
			app_id ? json_object_new_string(app_id) : NULL);
 | 
								app_id ? json_object_new_string(app_id) : NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	json_object *marks = json_object_new_array();
 | 
						json_object *marks = json_object_new_array();
 | 
				
			||||||
	list_t *view_marks = c->view->marks;
 | 
						list_t *con_marks = c->marks;
 | 
				
			||||||
	for (int i = 0; i < view_marks->length; ++i) {
 | 
						for (int i = 0; i < con_marks->length; ++i) {
 | 
				
			||||||
		json_object_array_add(marks, json_object_new_string(view_marks->items[i]));
 | 
							json_object_array_add(marks, json_object_new_string(con_marks->items[i]));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	json_object_object_add(object, "marks", marks);
 | 
						json_object_object_add(object, "marks", marks);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -563,11 +563,9 @@ static void ipc_get_workspaces_callback(struct sway_workspace *workspace,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ipc_get_marks_callback(struct sway_container *con, void *data) {
 | 
					static void ipc_get_marks_callback(struct sway_container *con, void *data) {
 | 
				
			||||||
	json_object *marks = (json_object *)data;
 | 
						json_object *marks = (json_object *)data;
 | 
				
			||||||
	if (con->view && con->view->marks) {
 | 
						for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
		for (int i = 0; i < con->view->marks->length; ++i) {
 | 
							char *mark = (char *)con->marks->items[i];
 | 
				
			||||||
			char *mark = (char *)con->view->marks->items[i];
 | 
							json_object_array_add(marks, json_object_new_string(mark));
 | 
				
			||||||
			json_object_array_add(marks, json_object_new_string(mark));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -39,6 +39,7 @@ struct sway_container *container_create(struct sway_view *view) {
 | 
				
			||||||
		c->children = create_list();
 | 
							c->children = create_list();
 | 
				
			||||||
		c->current.children = create_list();
 | 
							c->current.children = create_list();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						c->marks = create_list();
 | 
				
			||||||
	c->outputs = create_list();
 | 
						c->outputs = create_list();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	wl_signal_init(&c->events.destroy);
 | 
						wl_signal_init(&c->events.destroy);
 | 
				
			||||||
| 
						 | 
					@ -66,6 +67,13 @@ void container_destroy(struct sway_container *con) {
 | 
				
			||||||
	list_free(con->current.children);
 | 
						list_free(con->current.children);
 | 
				
			||||||
	list_free(con->outputs);
 | 
						list_free(con->outputs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						list_foreach(con->marks, free);
 | 
				
			||||||
 | 
						list_free(con->marks);
 | 
				
			||||||
 | 
						wlr_texture_destroy(con->marks_focused);
 | 
				
			||||||
 | 
						wlr_texture_destroy(con->marks_focused_inactive);
 | 
				
			||||||
 | 
						wlr_texture_destroy(con->marks_unfocused);
 | 
				
			||||||
 | 
						wlr_texture_destroy(con->marks_urgent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (con->view) {
 | 
						if (con->view) {
 | 
				
			||||||
		if (con->view->container == con) {
 | 
							if (con->view->container == con) {
 | 
				
			||||||
			con->view->container = NULL;
 | 
								con->view->container = NULL;
 | 
				
			||||||
| 
						 | 
					@ -996,9 +1004,7 @@ void container_discover_outputs(struct sway_container *con) {
 | 
				
			||||||
	double new_scale = new_output ? new_output->wlr_output->scale : -1;
 | 
						double new_scale = new_output ? new_output->wlr_output->scale : -1;
 | 
				
			||||||
	if (old_scale != new_scale) {
 | 
						if (old_scale != new_scale) {
 | 
				
			||||||
		container_update_title_textures(con);
 | 
							container_update_title_textures(con);
 | 
				
			||||||
		if (con->view) {
 | 
							container_update_marks_textures(con);
 | 
				
			||||||
			view_update_marks_textures(con->view);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1218,3 +1224,142 @@ bool container_is_transient_for(struct sway_container *child,
 | 
				
			||||||
		child->view && ancestor->view &&
 | 
							child->view && ancestor->view &&
 | 
				
			||||||
		view_is_transient_for(child->view, ancestor->view);
 | 
							view_is_transient_for(child->view, ancestor->view);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool find_by_mark_iterator(struct sway_container *con, void *data) {
 | 
				
			||||||
 | 
						char *mark = data;
 | 
				
			||||||
 | 
						return container_has_mark(con, mark);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct sway_container *container_find_mark(char *mark) {
 | 
				
			||||||
 | 
						return root_find_container(find_by_mark_iterator, mark);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool container_find_and_unmark(char *mark) {
 | 
				
			||||||
 | 
						struct sway_container *con = root_find_container(
 | 
				
			||||||
 | 
							find_by_mark_iterator, mark);
 | 
				
			||||||
 | 
						if (!con) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
 | 
							char *con_mark = con->marks->items[i];
 | 
				
			||||||
 | 
							if (strcmp(con_mark, mark) == 0) {
 | 
				
			||||||
 | 
								free(con_mark);
 | 
				
			||||||
 | 
								list_del(con->marks, i);
 | 
				
			||||||
 | 
								container_update_marks_textures(con);
 | 
				
			||||||
 | 
								ipc_event_window(con, "mark");
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void container_clear_marks(struct sway_container *con) {
 | 
				
			||||||
 | 
						list_foreach(con->marks, free);
 | 
				
			||||||
 | 
						con->marks->length = 0;
 | 
				
			||||||
 | 
						ipc_event_window(con, "mark");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool container_has_mark(struct sway_container *con, char *mark) {
 | 
				
			||||||
 | 
						for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
 | 
							char *item = con->marks->items[i];
 | 
				
			||||||
 | 
							if (strcmp(item, mark) == 0) {
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void container_add_mark(struct sway_container *con, char *mark) {
 | 
				
			||||||
 | 
						list_add(con->marks, strdup(mark));
 | 
				
			||||||
 | 
						ipc_event_window(con, "mark");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void update_marks_texture(struct sway_container *con,
 | 
				
			||||||
 | 
							struct wlr_texture **texture, struct border_colors *class) {
 | 
				
			||||||
 | 
						struct sway_output *output = container_get_effective_output(con);
 | 
				
			||||||
 | 
						if (!output) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (*texture) {
 | 
				
			||||||
 | 
							wlr_texture_destroy(*texture);
 | 
				
			||||||
 | 
							*texture = NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (!con->marks->length) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						size_t len = 0;
 | 
				
			||||||
 | 
						for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
 | 
							char *mark = con->marks->items[i];
 | 
				
			||||||
 | 
							if (mark[0] != '_') {
 | 
				
			||||||
 | 
								len += strlen(mark) + 2;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						char *buffer = calloc(len + 1, 1);
 | 
				
			||||||
 | 
						char *part = malloc(len + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!sway_assert(buffer && part, "Unable to allocate memory")) {
 | 
				
			||||||
 | 
							free(buffer);
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (int i = 0; i < con->marks->length; ++i) {
 | 
				
			||||||
 | 
							char *mark = con->marks->items[i];
 | 
				
			||||||
 | 
							if (mark[0] != '_') {
 | 
				
			||||||
 | 
								sprintf(part, "[%s]", mark);
 | 
				
			||||||
 | 
								strcat(buffer, part);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						free(part);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double scale = output->wlr_output->scale;
 | 
				
			||||||
 | 
						int width = 0;
 | 
				
			||||||
 | 
						int height = con->title_height * scale;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_t *c = cairo_create(NULL);
 | 
				
			||||||
 | 
						get_text_size(c, config->font, &width, NULL, NULL, scale, false,
 | 
				
			||||||
 | 
								"%s", buffer);
 | 
				
			||||||
 | 
						cairo_destroy(c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_surface_t *surface = cairo_image_surface_create(
 | 
				
			||||||
 | 
								CAIRO_FORMAT_ARGB32, width, height);
 | 
				
			||||||
 | 
						cairo_t *cairo = cairo_create(surface);
 | 
				
			||||||
 | 
						cairo_set_source_rgba(cairo, class->background[0], class->background[1],
 | 
				
			||||||
 | 
								class->background[2], class->background[3]);
 | 
				
			||||||
 | 
						cairo_paint(cairo);
 | 
				
			||||||
 | 
						PangoContext *pango = pango_cairo_create_context(cairo);
 | 
				
			||||||
 | 
						cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
 | 
				
			||||||
 | 
						cairo_set_source_rgba(cairo, class->text[0], class->text[1],
 | 
				
			||||||
 | 
								class->text[2], class->text[3]);
 | 
				
			||||||
 | 
						cairo_move_to(cairo, 0, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pango_printf(cairo, config->font, scale, false, "%s", buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cairo_surface_flush(surface);
 | 
				
			||||||
 | 
						unsigned char *data = cairo_image_surface_get_data(surface);
 | 
				
			||||||
 | 
						int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
 | 
				
			||||||
 | 
						struct wlr_renderer *renderer = wlr_backend_get_renderer(
 | 
				
			||||||
 | 
								output->wlr_output->backend);
 | 
				
			||||||
 | 
						*texture = wlr_texture_from_pixels(
 | 
				
			||||||
 | 
								renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
 | 
				
			||||||
 | 
						cairo_surface_destroy(surface);
 | 
				
			||||||
 | 
						g_object_unref(pango);
 | 
				
			||||||
 | 
						cairo_destroy(cairo);
 | 
				
			||||||
 | 
						free(buffer);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void container_update_marks_textures(struct sway_container *con) {
 | 
				
			||||||
 | 
						if (!config->show_marks) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						update_marks_texture(con, &con->marks_focused,
 | 
				
			||||||
 | 
								&config->border_colors.focused);
 | 
				
			||||||
 | 
						update_marks_texture(con, &con->marks_focused_inactive,
 | 
				
			||||||
 | 
								&config->border_colors.focused_inactive);
 | 
				
			||||||
 | 
						update_marks_texture(con, &con->marks_unfocused,
 | 
				
			||||||
 | 
								&config->border_colors.unfocused);
 | 
				
			||||||
 | 
						update_marks_texture(con, &con->marks_urgent,
 | 
				
			||||||
 | 
								&config->border_colors.urgent);
 | 
				
			||||||
 | 
						container_damage_whole(con);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										155
									
								
								sway/tree/view.c
									
										
									
									
									
								
							
							
						
						
									
										155
									
								
								sway/tree/view.c
									
										
									
									
									
								
							| 
						 | 
					@ -35,7 +35,6 @@ void view_init(struct sway_view *view, enum sway_view_type type,
 | 
				
			||||||
	view->type = type;
 | 
						view->type = type;
 | 
				
			||||||
	view->impl = impl;
 | 
						view->impl = impl;
 | 
				
			||||||
	view->executed_criteria = create_list();
 | 
						view->executed_criteria = create_list();
 | 
				
			||||||
	view->marks = create_list();
 | 
					 | 
				
			||||||
	view->allow_request_urgent = true;
 | 
						view->allow_request_urgent = true;
 | 
				
			||||||
	wl_signal_init(&view->events.unmap);
 | 
						wl_signal_init(&view->events.unmap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -55,13 +54,6 @@ void view_destroy(struct sway_view *view) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list_free(view->executed_criteria);
 | 
						list_free(view->executed_criteria);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_foreach(view->marks, free);
 | 
					 | 
				
			||||||
	list_free(view->marks);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_texture_destroy(view->marks_focused);
 | 
					 | 
				
			||||||
	wlr_texture_destroy(view->marks_focused_inactive);
 | 
					 | 
				
			||||||
	wlr_texture_destroy(view->marks_unfocused);
 | 
					 | 
				
			||||||
	wlr_texture_destroy(view->marks_urgent);
 | 
					 | 
				
			||||||
	free(view->title_format);
 | 
						free(view->title_format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (view->impl->destroy) {
 | 
						if (view->impl->destroy) {
 | 
				
			||||||
| 
						 | 
					@ -937,153 +929,6 @@ void view_update_title(struct sway_view *view, bool force) {
 | 
				
			||||||
	ipc_event_window(view->container, "title");
 | 
						ipc_event_window(view->container, "title");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_by_mark_iterator(struct sway_container *con,
 | 
					 | 
				
			||||||
		void *data) {
 | 
					 | 
				
			||||||
	char *mark = data;
 | 
					 | 
				
			||||||
	return con->view && view_has_mark(con->view, mark);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct sway_view *view_find_mark(char *mark) {
 | 
					 | 
				
			||||||
	struct sway_container *container = root_find_container(
 | 
					 | 
				
			||||||
			find_by_mark_iterator, mark);
 | 
					 | 
				
			||||||
	if (!container) {
 | 
					 | 
				
			||||||
		return NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return container->view;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool view_find_and_unmark(char *mark) {
 | 
					 | 
				
			||||||
	struct sway_container *container = root_find_container(
 | 
					 | 
				
			||||||
		find_by_mark_iterator, mark);
 | 
					 | 
				
			||||||
	if (!container) {
 | 
					 | 
				
			||||||
		return false;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	struct sway_view *view = container->view;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (int i = 0; i < view->marks->length; ++i) {
 | 
					 | 
				
			||||||
		char *view_mark = view->marks->items[i];
 | 
					 | 
				
			||||||
		if (strcmp(view_mark, mark) == 0) {
 | 
					 | 
				
			||||||
			free(view_mark);
 | 
					 | 
				
			||||||
			list_del(view->marks, i);
 | 
					 | 
				
			||||||
			view_update_marks_textures(view);
 | 
					 | 
				
			||||||
			ipc_event_window(container, "mark");
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_clear_marks(struct sway_view *view) {
 | 
					 | 
				
			||||||
	list_foreach(view->marks, free);
 | 
					 | 
				
			||||||
	view->marks->length = 0;
 | 
					 | 
				
			||||||
	ipc_event_window(view->container, "mark");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool view_has_mark(struct sway_view *view, char *mark) {
 | 
					 | 
				
			||||||
	for (int i = 0; i < view->marks->length; ++i) {
 | 
					 | 
				
			||||||
		char *item = view->marks->items[i];
 | 
					 | 
				
			||||||
		if (strcmp(item, mark) == 0) {
 | 
					 | 
				
			||||||
			return true;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_add_mark(struct sway_view *view, char *mark) {
 | 
					 | 
				
			||||||
	list_add(view->marks, strdup(mark));
 | 
					 | 
				
			||||||
	ipc_event_window(view->container, "mark");
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void update_marks_texture(struct sway_view *view,
 | 
					 | 
				
			||||||
		struct wlr_texture **texture, struct border_colors *class) {
 | 
					 | 
				
			||||||
	struct sway_output *output =
 | 
					 | 
				
			||||||
		container_get_effective_output(view->container);
 | 
					 | 
				
			||||||
	if (!output) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (*texture) {
 | 
					 | 
				
			||||||
		wlr_texture_destroy(*texture);
 | 
					 | 
				
			||||||
		*texture = NULL;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if (!view->marks->length) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	size_t len = 0;
 | 
					 | 
				
			||||||
	for (int i = 0; i < view->marks->length; ++i) {
 | 
					 | 
				
			||||||
		char *mark = view->marks->items[i];
 | 
					 | 
				
			||||||
		if (mark[0] != '_') {
 | 
					 | 
				
			||||||
			len += strlen(mark) + 2;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	char *buffer = calloc(len + 1, 1);
 | 
					 | 
				
			||||||
	char *part = malloc(len + 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!sway_assert(buffer && part, "Unable to allocate memory")) {
 | 
					 | 
				
			||||||
		free(buffer);
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (int i = 0; i < view->marks->length; ++i) {
 | 
					 | 
				
			||||||
		char *mark = view->marks->items[i];
 | 
					 | 
				
			||||||
		if (mark[0] != '_') {
 | 
					 | 
				
			||||||
			sprintf(part, "[%s]", mark);
 | 
					 | 
				
			||||||
			strcat(buffer, part);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	free(part);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	double scale = output->wlr_output->scale;
 | 
					 | 
				
			||||||
	int width = 0;
 | 
					 | 
				
			||||||
	int height = view->container->title_height * scale;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_t *c = cairo_create(NULL);
 | 
					 | 
				
			||||||
	get_text_size(c, config->font, &width, NULL, NULL, scale, false,
 | 
					 | 
				
			||||||
			"%s", buffer);
 | 
					 | 
				
			||||||
	cairo_destroy(c);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_surface_t *surface = cairo_image_surface_create(
 | 
					 | 
				
			||||||
			CAIRO_FORMAT_ARGB32, width, height);
 | 
					 | 
				
			||||||
	cairo_t *cairo = cairo_create(surface);
 | 
					 | 
				
			||||||
	cairo_set_source_rgba(cairo, class->background[0], class->background[1],
 | 
					 | 
				
			||||||
			class->background[2], class->background[3]);
 | 
					 | 
				
			||||||
	cairo_paint(cairo);
 | 
					 | 
				
			||||||
	PangoContext *pango = pango_cairo_create_context(cairo);
 | 
					 | 
				
			||||||
	cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
 | 
					 | 
				
			||||||
	cairo_set_source_rgba(cairo, class->text[0], class->text[1],
 | 
					 | 
				
			||||||
			class->text[2], class->text[3]);
 | 
					 | 
				
			||||||
	cairo_move_to(cairo, 0, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pango_printf(cairo, config->font, scale, false, "%s", buffer);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cairo_surface_flush(surface);
 | 
					 | 
				
			||||||
	unsigned char *data = cairo_image_surface_get_data(surface);
 | 
					 | 
				
			||||||
	int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
 | 
					 | 
				
			||||||
	struct wlr_renderer *renderer = wlr_backend_get_renderer(
 | 
					 | 
				
			||||||
			output->wlr_output->backend);
 | 
					 | 
				
			||||||
	*texture = wlr_texture_from_pixels(
 | 
					 | 
				
			||||||
			renderer, WL_SHM_FORMAT_ARGB8888, stride, width, height, data);
 | 
					 | 
				
			||||||
	cairo_surface_destroy(surface);
 | 
					 | 
				
			||||||
	g_object_unref(pango);
 | 
					 | 
				
			||||||
	cairo_destroy(cairo);
 | 
					 | 
				
			||||||
	free(buffer);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void view_update_marks_textures(struct sway_view *view) {
 | 
					 | 
				
			||||||
	if (!config->show_marks) {
 | 
					 | 
				
			||||||
		return;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	update_marks_texture(view, &view->marks_focused,
 | 
					 | 
				
			||||||
			&config->border_colors.focused);
 | 
					 | 
				
			||||||
	update_marks_texture(view, &view->marks_focused_inactive,
 | 
					 | 
				
			||||||
			&config->border_colors.focused_inactive);
 | 
					 | 
				
			||||||
	update_marks_texture(view, &view->marks_unfocused,
 | 
					 | 
				
			||||||
			&config->border_colors.unfocused);
 | 
					 | 
				
			||||||
	update_marks_texture(view, &view->marks_urgent,
 | 
					 | 
				
			||||||
			&config->border_colors.urgent);
 | 
					 | 
				
			||||||
	container_damage_whole(view->container);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
bool view_is_visible(struct sway_view *view) {
 | 
					bool view_is_visible(struct sway_view *view) {
 | 
				
			||||||
	if (view->container->node.destroying) {
 | 
						if (view->container->node.destroying) {
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue