summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sway/tree/view.h16
-rw-r--r--sway/commands.c2
-rw-r--r--sway/commands/mark.c68
-rw-r--r--sway/commands/unmark.c32
-rw-r--r--sway/criteria.c12
-rw-r--r--sway/meson.build2
-rw-r--r--sway/tree/view.c49
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 */
254void view_execute_criteria(struct sway_view *view); 255void 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 */
261bool view_find_and_unmark(char *mark);
262
263/**
264 * Remove all marks from the view.
265 */
266void view_clear_marks(struct sway_view *view);
267
268bool 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
190static int handler_compare(const void *_a, const void *_b) { 192static 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
16struct 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
10struct 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
731static 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
737bool 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
756void 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
764bool 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}