aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-05-14 21:44:05 -0400
committerLibravatar GitHub <noreply@github.com>2018-05-14 21:44:05 -0400
commit95f6d0deba26436445b45d4d056c1f6dd2ee82da (patch)
treedf558830f4c0f5bc9e8943cfbf60532f2293aeda
parentMerge pull request #1978 from RedSoxFan/fix-1975 (diff)
parentChange unmark implemention to match i3's (diff)
downloadsway-95f6d0deba26436445b45d4d056c1f6dd2ee82da.tar.gz
sway-95f6d0deba26436445b45d4d056c1f6dd2ee82da.tar.zst
sway-95f6d0deba26436445b45d4d056c1f6dd2ee82da.zip
Merge pull request #1954 from RyanDwyer/marks
Implement marks
-rw-r--r--include/sway/config.h1
-rw-r--r--include/sway/tree/view.h16
-rw-r--r--sway/commands.c8
-rw-r--r--sway/commands/mark.c68
-rw-r--r--sway/commands/unmark.c59
-rw-r--r--sway/criteria.c12
-rw-r--r--sway/meson.build2
-rw-r--r--sway/tree/view.c49
8 files changed, 209 insertions, 6 deletions
diff --git a/include/sway/config.h b/include/sway/config.h
index f77c3b50..33f52156 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -368,6 +368,7 @@ struct sway_config {
368 struct seat_config *seat_config; 368 struct seat_config *seat_config;
369 struct sway_seat *seat; 369 struct sway_seat *seat;
370 struct sway_container *current_container; 370 struct sway_container *current_container;
371 bool using_criteria;
371 } handler_context; 372 } handler_context;
372}; 373};
373 374
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..9b6d6459 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) {
@@ -300,7 +302,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
300 head = exec; 302 head = exec;
301 do { 303 do {
302 // Extract criteria (valid for this command list only). 304 // Extract criteria (valid for this command list only).
303 bool has_criteria = false; 305 config->handler_context.using_criteria = false;
304 if (*head == '[') { 306 if (*head == '[') {
305 char *error = NULL; 307 char *error = NULL;
306 struct criteria *criteria = criteria_parse(head, &error); 308 struct criteria *criteria = criteria_parse(head, &error);
@@ -313,7 +315,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
313 views = criteria_get_views(criteria); 315 views = criteria_get_views(criteria);
314 head += strlen(criteria->raw); 316 head += strlen(criteria->raw);
315 criteria_destroy(criteria); 317 criteria_destroy(criteria);
316 has_criteria = true; 318 config->handler_context.using_criteria = true;
317 // Skip leading whitespace 319 // Skip leading whitespace
318 head += strspn(head, whitespace); 320 head += strspn(head, whitespace);
319 } 321 }
@@ -350,7 +352,7 @@ struct cmd_results *execute_command(char *_exec, struct sway_seat *seat) {
350 goto cleanup; 352 goto cleanup;
351 } 353 }
352 354
353 if (!has_criteria) { 355 if (!config->handler_context.using_criteria) {
354 // without criteria, the command acts upon the focused 356 // without criteria, the command acts upon the focused
355 // container 357 // container
356 config->handler_context.current_container = 358 config->handler_context.current_container =
diff --git a/sway/commands/mark.c b/sway/commands/mark.c
new file mode 100644
index 00000000..b131f2f3
--- /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 || !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..ea2a5709
--- /dev/null
+++ b/sway/commands/unmark.c
@@ -0,0 +1,59 @@
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
10static void remove_all_marks_iterator(struct sway_container *con, void *data) {
11 if (con->type == C_VIEW) {
12 view_clear_marks(con->sway_view);
13 }
14}
15
16// unmark Remove all marks from all views
17// unmark foo Remove single mark from whichever view has it
18// [criteria] unmark Remove all marks from matched view
19// [criteria] unmark foo Remove single mark from matched view
20
21struct cmd_results *cmd_unmark(int argc, char **argv) {
22 // Determine the view
23 struct sway_view *view = NULL;
24 if (config->handler_context.using_criteria) {
25 struct sway_container *container =
26 config->handler_context.current_container;
27 if (container->type != C_VIEW) {
28 return cmd_results_new(CMD_INVALID, "unmark",
29 "Only views can have marks");
30 }
31 view = container->sway_view;
32 }
33
34 // Determine the mark
35 char *mark = NULL;
36 if (argc > 0) {
37 mark = join_args(argv, argc);
38 }
39
40 if (view && mark) {
41 // Remove the mark from the given view
42 if (view_has_mark(view, mark)) {
43 view_find_and_unmark(mark);
44 }
45 } else if (view && !mark) {
46 // Clear all marks from the given view
47 view_clear_marks(view);
48 } else if (!view && mark) {
49 // Remove mark from whichever view has it
50 view_find_and_unmark(mark);
51 } else {
52 // Remove all marks from all views
53 container_for_each_descendant_dfs(&root_container,
54 remove_all_marks_iterator, NULL);
55 }
56 free(mark);
57
58 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
59}
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}