diff options
-rw-r--r-- | include/sway/tree/view.h | 16 | ||||
-rw-r--r-- | sway/commands.c | 2 | ||||
-rw-r--r-- | sway/commands/mark.c | 68 | ||||
-rw-r--r-- | sway/commands/unmark.c | 32 | ||||
-rw-r--r-- | sway/criteria.c | 12 | ||||
-rw-r--r-- | sway/meson.build | 2 | ||||
-rw-r--r-- | sway/tree/view.c | 49 |
7 files changed, 178 insertions, 3 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index f12386dc..7ed4d3df 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -60,7 +60,8 @@ struct sway_view { | |||
60 | bool border_left; | 60 | bool border_left; |
61 | bool border_right; | 61 | bool border_right; |
62 | 62 | ||
63 | list_t *executed_criteria; | 63 | list_t *executed_criteria; // struct criteria * |
64 | list_t *marks; // char * | ||
64 | 65 | ||
65 | union { | 66 | union { |
66 | struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; | 67 | struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6; |
@@ -253,4 +254,17 @@ void view_update_title(struct sway_view *view, bool force); | |||
253 | */ | 254 | */ |
254 | void view_execute_criteria(struct sway_view *view); | 255 | void view_execute_criteria(struct sway_view *view); |
255 | 256 | ||
257 | /** | ||
258 | * Find any view that has the given mark and remove the mark from the view. | ||
259 | * Returns true if it matched a view. | ||
260 | */ | ||
261 | bool view_find_and_unmark(char *mark); | ||
262 | |||
263 | /** | ||
264 | * Remove all marks from the view. | ||
265 | */ | ||
266 | void view_clear_marks(struct sway_view *view); | ||
267 | |||
268 | bool view_has_mark(struct sway_view *view, char *mark); | ||
269 | |||
256 | #endif | 270 | #endif |
diff --git a/sway/commands.c b/sway/commands.c index 60c64776..31d241a8 100644 --- a/sway/commands.c +++ b/sway/commands.c | |||
@@ -175,6 +175,7 @@ static struct cmd_handler command_handlers[] = { | |||
175 | { "focus", cmd_focus }, | 175 | { "focus", cmd_focus }, |
176 | { "kill", cmd_kill }, | 176 | { "kill", cmd_kill }, |
177 | { "layout", cmd_layout }, | 177 | { "layout", cmd_layout }, |
178 | { "mark", cmd_mark }, | ||
178 | { "move", cmd_move }, | 179 | { "move", cmd_move }, |
179 | { "opacity", cmd_opacity }, | 180 | { "opacity", cmd_opacity }, |
180 | { "reload", cmd_reload }, | 181 | { "reload", cmd_reload }, |
@@ -185,6 +186,7 @@ static struct cmd_handler command_handlers[] = { | |||
185 | { "splitt", cmd_splitt }, | 186 | { "splitt", cmd_splitt }, |
186 | { "splitv", cmd_splitv }, | 187 | { "splitv", cmd_splitv }, |
187 | { "title_format", cmd_title_format }, | 188 | { "title_format", cmd_title_format }, |
189 | { "unmark", cmd_unmark }, | ||
188 | }; | 190 | }; |
189 | 191 | ||
190 | static int handler_compare(const void *_a, const void *_b) { | 192 | static int handler_compare(const void *_a, const void *_b) { |
diff --git a/sway/commands/mark.c b/sway/commands/mark.c new file mode 100644 index 00000000..782e8ab9 --- /dev/null +++ b/sway/commands/mark.c | |||
@@ -0,0 +1,68 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/tree/view.h" | ||
6 | #include "list.h" | ||
7 | #include "log.h" | ||
8 | #include "stringop.h" | ||
9 | |||
10 | // mark foo Same as mark --replace foo | ||
11 | // mark --add foo Add this mark to view's list | ||
12 | // mark --replace foo Replace view's marks with this single one | ||
13 | // mark --add --toggle foo Toggle current mark and persist other marks | ||
14 | // mark --replace --toggle foo Toggle current mark and remove other marks | ||
15 | |||
16 | struct cmd_results *cmd_mark(int argc, char **argv) { | ||
17 | struct cmd_results *error = NULL; | ||
18 | if ((error = checkarg(argc, "mark", EXPECTED_AT_LEAST, 1))) { | ||
19 | return error; | ||
20 | } | ||
21 | struct sway_container *container = | ||
22 | config->handler_context.current_container; | ||
23 | if (container->type != C_VIEW) { | ||
24 | return cmd_results_new(CMD_INVALID, "mark", | ||
25 | "Only views can have marks"); | ||
26 | } | ||
27 | struct sway_view *view = container->sway_view; | ||
28 | |||
29 | bool add = false, toggle = false; | ||
30 | while (argc > 0 && strncmp(*argv, "--", 2) == 0) { | ||
31 | if (strcmp(*argv, "--add") == 0) { | ||
32 | add = true; | ||
33 | } else if (strcmp(*argv, "--replace") == 0) { | ||
34 | add = false; | ||
35 | } else if (strcmp(*argv, "--toggle") == 0) { | ||
36 | toggle = true; | ||
37 | } else { | ||
38 | return cmd_results_new(CMD_INVALID, "mark", | ||
39 | "Unrecognized argument '%s'", *argv); | ||
40 | } | ||
41 | ++argv; | ||
42 | --argc; | ||
43 | } | ||
44 | |||
45 | if (!argc) { | ||
46 | return cmd_results_new(CMD_INVALID, "mark", | ||
47 | "Expected '[--add|--replace] [--toggle] <identifier>'"); | ||
48 | } | ||
49 | |||
50 | char *mark = join_args(argv, argc); | ||
51 | bool had_mark = view_has_mark(view, mark); | ||
52 | |||
53 | if (!add) { | ||
54 | // Replacing | ||
55 | view_clear_marks(view); | ||
56 | } | ||
57 | |||
58 | view_find_and_unmark(mark); | ||
59 | |||
60 | if (!toggle || (toggle && !had_mark)) { | ||
61 | list_add(view->marks, strdup(mark)); | ||
62 | } | ||
63 | |||
64 | free(mark); | ||
65 | view_execute_criteria(view); | ||
66 | |||
67 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
68 | } | ||
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c new file mode 100644 index 00000000..a7d39432 --- /dev/null +++ b/sway/commands/unmark.c | |||
@@ -0,0 +1,32 @@ | |||
1 | #define _POSIX_C_SOURCE 200809L | ||
2 | #include <string.h> | ||
3 | #include "sway/commands.h" | ||
4 | #include "sway/config.h" | ||
5 | #include "sway/tree/view.h" | ||
6 | #include "list.h" | ||
7 | #include "log.h" | ||
8 | #include "stringop.h" | ||
9 | |||
10 | struct cmd_results *cmd_unmark(int argc, char **argv) { | ||
11 | if (argc == 0) { | ||
12 | // Remove all marks from the current container | ||
13 | struct sway_container *container = | ||
14 | config->handler_context.current_container; | ||
15 | if (container->type != C_VIEW) { | ||
16 | return cmd_results_new(CMD_INVALID, "unmark", | ||
17 | "Only views can have marks"); | ||
18 | } | ||
19 | view_clear_marks(container->sway_view); | ||
20 | } else { | ||
21 | // Remove a single mark from whichever container has it | ||
22 | char *mark = join_args(argv, argc); | ||
23 | if (!view_find_and_unmark(mark)) { | ||
24 | free(mark); | ||
25 | return cmd_results_new(CMD_INVALID, "unmark", | ||
26 | "No view exists with that mark"); | ||
27 | } | ||
28 | free(mark); | ||
29 | } | ||
30 | |||
31 | return cmd_results_new(CMD_SUCCESS, NULL, NULL); | ||
32 | } | ||
diff --git a/sway/criteria.c b/sway/criteria.c index 248260ec..4295cacc 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -75,8 +75,16 @@ static bool criteria_matches_view(struct criteria *criteria, | |||
75 | } | 75 | } |
76 | 76 | ||
77 | if (criteria->con_mark) { | 77 | if (criteria->con_mark) { |
78 | // TODO | 78 | bool exists = false; |
79 | return false; | 79 | for (int i = 0; i < view->marks->length; ++i) { |
80 | if (regex_cmp(view->marks->items[i], criteria->con_mark) == 0) { | ||
81 | exists = true; | ||
82 | break; | ||
83 | } | ||
84 | } | ||
85 | if (!exists) { | ||
86 | return false; | ||
87 | } | ||
80 | } | 88 | } |
81 | 89 | ||
82 | if (criteria->con_id) { // Internal ID | 90 | if (criteria->con_id) { // Internal ID |
diff --git a/sway/meson.build b/sway/meson.build index 67c2a422..ed14b51a 100644 --- a/sway/meson.build +++ b/sway/meson.build | |||
@@ -43,6 +43,7 @@ sway_sources = files( | |||
43 | 'commands/fullscreen.c', | 43 | 'commands/fullscreen.c', |
44 | 'commands/hide_edge_borders.c', | 44 | 'commands/hide_edge_borders.c', |
45 | 'commands/kill.c', | 45 | 'commands/kill.c', |
46 | 'commands/mark.c', | ||
46 | 'commands/opacity.c', | 47 | 'commands/opacity.c', |
47 | 'commands/include.c', | 48 | 'commands/include.c', |
48 | 'commands/input.c', | 49 | 'commands/input.c', |
@@ -62,6 +63,7 @@ sway_sources = files( | |||
62 | 'commands/split.c', | 63 | 'commands/split.c', |
63 | 'commands/swaybg_command.c', | 64 | 'commands/swaybg_command.c', |
64 | 'commands/title_format.c', | 65 | 'commands/title_format.c', |
66 | 'commands/unmark.c', | ||
65 | 'commands/workspace.c', | 67 | 'commands/workspace.c', |
66 | 'commands/ws_auto_back_and_forth.c', | 68 | 'commands/ws_auto_back_and_forth.c', |
67 | 69 | ||
diff --git a/sway/tree/view.c b/sway/tree/view.c index 8da72667..ec7f3031 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -23,6 +23,7 @@ void view_init(struct sway_view *view, enum sway_view_type type, | |||
23 | view->type = type; | 23 | view->type = type; |
24 | view->impl = impl; | 24 | view->impl = impl; |
25 | view->executed_criteria = create_list(); | 25 | view->executed_criteria = create_list(); |
26 | view->marks = create_list(); | ||
26 | wl_signal_init(&view->events.unmap); | 27 | wl_signal_init(&view->events.unmap); |
27 | } | 28 | } |
28 | 29 | ||
@@ -37,6 +38,11 @@ void view_destroy(struct sway_view *view) { | |||
37 | 38 | ||
38 | list_free(view->executed_criteria); | 39 | list_free(view->executed_criteria); |
39 | 40 | ||
41 | for (int i = 0; i < view->marks->length; ++i) { | ||
42 | free(view->marks->items[i]); | ||
43 | } | ||
44 | list_free(view->marks); | ||
45 | |||
40 | container_destroy(view->swayc); | 46 | container_destroy(view->swayc); |
41 | 47 | ||
42 | if (view->impl->destroy) { | 48 | if (view->impl->destroy) { |
@@ -721,3 +727,46 @@ void view_update_title(struct sway_view *view, bool force) { | |||
721 | container_notify_child_title_changed(view->swayc->parent); | 727 | container_notify_child_title_changed(view->swayc->parent); |
722 | config_update_font_height(false); | 728 | config_update_font_height(false); |
723 | } | 729 | } |
730 | |||
731 | static bool find_by_mark_iterator(struct sway_container *con, | ||
732 | void *data) { | ||
733 | char *mark = data; | ||
734 | return con->type == C_VIEW && view_has_mark(con->sway_view, mark); | ||
735 | } | ||
736 | |||
737 | bool view_find_and_unmark(char *mark) { | ||
738 | struct sway_container *container = container_find(&root_container, | ||
739 | find_by_mark_iterator, mark); | ||
740 | if (!container) { | ||
741 | return false; | ||
742 | } | ||
743 | struct sway_view *view = container->sway_view; | ||
744 | |||
745 | for (int i = 0; i < view->marks->length; ++i) { | ||
746 | char *view_mark = view->marks->items[i]; | ||
747 | if (strcmp(view_mark, mark) == 0) { | ||
748 | free(view_mark); | ||
749 | list_del(view->marks, i); | ||
750 | return true; | ||
751 | } | ||
752 | } | ||
753 | return false; | ||
754 | } | ||
755 | |||
756 | void view_clear_marks(struct sway_view *view) { | ||
757 | for (int i = 0; i < view->marks->length; ++i) { | ||
758 | free(view->marks->items[i]); | ||
759 | } | ||
760 | list_free(view->marks); | ||
761 | view->marks = create_list(); | ||
762 | } | ||
763 | |||
764 | bool view_has_mark(struct sway_view *view, char *mark) { | ||
765 | for (int i = 0; i < view->marks->length; ++i) { | ||
766 | char *item = view->marks->items[i]; | ||
767 | if (strcmp(item, mark) == 0) { | ||
768 | return true; | ||
769 | } | ||
770 | } | ||
771 | return false; | ||
772 | } | ||