summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2017-04-03 14:52:20 -0400
committerLibravatar GitHub <noreply@github.com>2017-04-03 14:52:20 -0400
commit7d43a76b4e765eb8072c09cdec3847e877cf65d7 (patch)
tree030844d9fb13be7814dd760a6ffedbec8f5264cd
parentUpdate man page (diff)
parentImpliment i3-style marks (diff)
downloadsway-7d43a76b4e765eb8072c09cdec3847e877cf65d7.tar.gz
sway-7d43a76b4e765eb8072c09cdec3847e877cf65d7.tar.zst
sway-7d43a76b4e765eb8072c09cdec3847e877cf65d7.zip
Merge pull request #1145 from 4e554c4c/marks
Impliment i3-style marks
-rw-r--r--include/sway/commands.h3
-rw-r--r--include/sway/config.h1
-rw-r--r--include/sway/container.h5
-rw-r--r--sway/border.c23
-rw-r--r--sway/commands.c3
-rw-r--r--sway/commands/mark.c74
-rw-r--r--sway/commands/show_marks.c13
-rw-r--r--sway/commands/unmark.c31
-rw-r--r--sway/config.c1
-rw-r--r--sway/container.c4
-rw-r--r--sway/criteria.c11
-rw-r--r--sway/sway.5.txt20
12 files changed, 189 insertions, 0 deletions
diff --git a/include/sway/commands.h b/include/sway/commands.h
index 511bee4d..35a2f92a 100644
--- a/include/sway/commands.h
+++ b/include/sway/commands.h
@@ -126,6 +126,7 @@ sway_cmd cmd_ipc;
126sway_cmd cmd_kill; 126sway_cmd cmd_kill;
127sway_cmd cmd_layout; 127sway_cmd cmd_layout;
128sway_cmd cmd_log_colors; 128sway_cmd cmd_log_colors;
129sway_cmd cmd_mark;
129sway_cmd cmd_mode; 130sway_cmd cmd_mode;
130sway_cmd cmd_mouse_warping; 131sway_cmd cmd_mouse_warping;
131sway_cmd cmd_move; 132sway_cmd cmd_move;
@@ -140,12 +141,14 @@ sway_cmd cmd_resize;
140sway_cmd cmd_scratchpad; 141sway_cmd cmd_scratchpad;
141sway_cmd cmd_seamless_mouse; 142sway_cmd cmd_seamless_mouse;
142sway_cmd cmd_set; 143sway_cmd cmd_set;
144sway_cmd cmd_show_marks;
143sway_cmd cmd_smart_gaps; 145sway_cmd cmd_smart_gaps;
144sway_cmd cmd_split; 146sway_cmd cmd_split;
145sway_cmd cmd_splith; 147sway_cmd cmd_splith;
146sway_cmd cmd_splitt; 148sway_cmd cmd_splitt;
147sway_cmd cmd_splitv; 149sway_cmd cmd_splitv;
148sway_cmd cmd_sticky; 150sway_cmd cmd_sticky;
151sway_cmd cmd_unmark;
149sway_cmd cmd_workspace; 152sway_cmd cmd_workspace;
150sway_cmd cmd_ws_auto_back_and_forth; 153sway_cmd cmd_ws_auto_back_and_forth;
151sway_cmd cmd_workspace_layout; 154sway_cmd cmd_workspace_layout;
diff --git a/include/sway/config.h b/include/sway/config.h
index d77fbd51..2de90434 100644
--- a/include/sway/config.h
+++ b/include/sway/config.h
@@ -275,6 +275,7 @@ struct sway_config {
275 bool reading; 275 bool reading;
276 bool auto_back_and_forth; 276 bool auto_back_and_forth;
277 bool seamless_mouse; 277 bool seamless_mouse;
278 bool show_marks;
278 279
279 bool edge_gaps; 280 bool edge_gaps;
280 bool smart_gaps; 281 bool smart_gaps;
diff --git a/include/sway/container.h b/include/sway/container.h
index 46925589..37192ce3 100644
--- a/include/sway/container.h
+++ b/include/sway/container.h
@@ -165,6 +165,11 @@ struct sway_container {
165 * Number of slave groups (e.g. columns) in auto layouts. 165 * Number of slave groups (e.g. columns) in auto layouts.
166 */ 166 */
167 size_t nb_slave_groups; 167 size_t nb_slave_groups;
168
169 /**
170 * Marks applied to the container, list_t of char*.
171 */
172 list_t *marks;
168}; 173};
169 174
170enum visibility_mask { 175enum visibility_mask {
diff --git a/sway/border.c b/sway/border.c
index d79029a9..10ad92c2 100644
--- a/sway/border.c
+++ b/sway/border.c
@@ -1,8 +1,11 @@
1#define _XOPEN_SOURCE 500
1#include <wlc/wlc-render.h> 2#include <wlc/wlc-render.h>
2#include <cairo/cairo.h> 3#include <cairo/cairo.h>
3#include <pango/pangocairo.h> 4#include <pango/pangocairo.h>
4#include <stdlib.h> 5#include <stdlib.h>
5#include <stdio.h> 6#include <stdio.h>
7#include <string.h>
8#include <strings.h>
6#include <arpa/inet.h> 9#include <arpa/inet.h>
7#include "sway/border.h" 10#include "sway/border.h"
8#include "sway/container.h" 11#include "sway/container.h"
@@ -190,6 +193,26 @@ static void render_title_bar(swayc_t *view, cairo_t *cr, struct wlc_geometry *b,
190 cairo_set_source_u32(cr, colors->text); 193 cairo_set_source_u32(cr, colors->text);
191 pango_printf(cr, config->font, 1, false, "%s", view->name); 194 pango_printf(cr, config->font, 1, false, "%s", view->name);
192 } 195 }
196 // Marks
197 if (config->show_marks && view->marks) {
198 int total_len = 0;
199
200 for(int i = view->marks->length - 1; i >= 0; --i) {
201 char *mark = (char *)view->marks->items[i];
202 if (*mark != '_') {
203 int width, height;
204 get_text_size(cr, config->font, &width, &height, 1, false, "[%s]", mark);
205 total_len += width;
206 if ((int)tb->size.w + x - (total_len + 2) < x + 2) {
207 break;
208 } else {
209 cairo_move_to(cr, (int)tb->size.w + x - (total_len + 2), y + 2);
210 cairo_set_source_u32(cr, colors->text);
211 pango_printf(cr, config->font, 1, false, "[%s]", mark);
212 }
213 }
214 }
215 }
193 216
194 // titlebars has a border all around for tabbed layouts 217 // titlebars has a border all around for tabbed layouts
195 if (view->parent->layout == L_TABBED) { 218 if (view->parent->layout == L_TABBED) {
diff --git a/sway/commands.c b/sway/commands.c
index c330ebee..971ff505 100644
--- a/sway/commands.c
+++ b/sway/commands.c
@@ -190,6 +190,7 @@ static struct cmd_handler handlers[] = {
190 { "kill", cmd_kill }, 190 { "kill", cmd_kill },
191 { "layout", cmd_layout }, 191 { "layout", cmd_layout },
192 { "log_colors", cmd_log_colors }, 192 { "log_colors", cmd_log_colors },
193 { "mark", cmd_mark },
193 { "mode", cmd_mode }, 194 { "mode", cmd_mode },
194 { "mouse_warping", cmd_mouse_warping }, 195 { "mouse_warping", cmd_mouse_warping },
195 { "move", cmd_move }, 196 { "move", cmd_move },
@@ -203,12 +204,14 @@ static struct cmd_handler handlers[] = {
203 { "scratchpad", cmd_scratchpad }, 204 { "scratchpad", cmd_scratchpad },
204 { "seamless_mouse", cmd_seamless_mouse }, 205 { "seamless_mouse", cmd_seamless_mouse },
205 { "set", cmd_set }, 206 { "set", cmd_set },
207 { "show_marks", cmd_show_marks },
206 { "smart_gaps", cmd_smart_gaps }, 208 { "smart_gaps", cmd_smart_gaps },
207 { "split", cmd_split }, 209 { "split", cmd_split },
208 { "splith", cmd_splith }, 210 { "splith", cmd_splith },
209 { "splitt", cmd_splitt }, 211 { "splitt", cmd_splitt },
210 { "splitv", cmd_splitv }, 212 { "splitv", cmd_splitv },
211 { "sticky", cmd_sticky }, 213 { "sticky", cmd_sticky },
214 { "unmark", cmd_unmark },
212 { "workspace", cmd_workspace }, 215 { "workspace", cmd_workspace },
213 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth }, 216 { "workspace_auto_back_and_forth", cmd_ws_auto_back_and_forth },
214 { "workspace_layout", cmd_workspace_layout }, 217 { "workspace_layout", cmd_workspace_layout },
diff --git a/sway/commands/mark.c b/sway/commands/mark.c
new file mode 100644
index 00000000..68a84af7
--- /dev/null
+++ b/sway/commands/mark.c
@@ -0,0 +1,74 @@
1#include <string.h>
2#include <strings.h>
3#include <stdbool.h>
4#include "sway/commands.h"
5#include "list.h"
6#include "stringop.h"
7
8struct cmd_results *cmd_mark(int argc, char **argv) {
9 struct cmd_results *error = NULL;
10 if (config->reading) return cmd_results_new(CMD_FAILURE, "mark", "Can't be used in config file.");
11 if ((error = checkarg(argc, "floating", EXPECTED_AT_LEAST, 1))) {
12 return error;
13 }
14
15 swayc_t *view = get_focused_container(&root_container);
16 bool add = false;
17 bool toggle = false;
18
19 if (strcmp(argv[0], "--add") == 0) {
20 --argc; ++argv;
21 add = true;
22 } else if (strcmp(argv[0], "--replace") == 0) {
23 --argc; ++argv;
24 }
25
26 if (argc && strcmp(argv[0], "--toggle") == 0) {
27 --argc; ++argv;
28 toggle = true;
29 }
30
31 if (argc) {
32 char *mark = join_args(argv, argc);
33 if (view->marks) {
34 if (add) {
35 int index;
36 if ((index = list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark)) != -1) {
37 if (toggle) {
38 free(view->marks->items[index]);
39 list_del(view->marks, index);
40
41 if (0 == view->marks->length) {
42 list_free(view->marks);
43 view->marks = NULL;
44 }
45 }
46 free(mark);
47 } else {
48 list_add(view->marks, mark);
49 }
50 } else {
51 if (toggle && list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark) != -1) {
52 // Delete the list
53 list_foreach(view->marks, free);
54 list_free(view->marks);
55 view->marks = NULL;
56 } else {
57 // Delete and replace with a new list
58 list_foreach(view->marks, free);
59 list_free(view->marks);
60
61 view->marks = create_list();
62 list_add(view->marks, mark);
63 }
64 }
65 } else {
66 view->marks = create_list();
67 list_add(view->marks, mark);
68 }
69 } else {
70 return cmd_results_new(CMD_FAILURE, "mark",
71 "Expected 'mark [--add|--replace] [--toggle] <mark>'");
72 }
73 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
74}
diff --git a/sway/commands/show_marks.c b/sway/commands/show_marks.c
new file mode 100644
index 00000000..ed56d9e5
--- /dev/null
+++ b/sway/commands/show_marks.c
@@ -0,0 +1,13 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/commands.h"
4
5struct cmd_results *cmd_show_marks(int argc, char **argv) {
6 struct cmd_results *error = NULL;
7 if ((error = checkarg(argc, "show_marks", EXPECTED_EQUAL_TO, 1))) {
8 return error;
9 }
10
11 config->show_marks = !strcasecmp(argv[0], "on");
12 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
13}
diff --git a/sway/commands/unmark.c b/sway/commands/unmark.c
new file mode 100644
index 00000000..34a2ae44
--- /dev/null
+++ b/sway/commands/unmark.c
@@ -0,0 +1,31 @@
1#include <string.h>
2#include <strings.h>
3#include "sway/commands.h"
4#include "list.h"
5#include "stringop.h"
6
7struct cmd_results *cmd_unmark(int argc, char **argv) {
8 swayc_t *view = get_focused_container(&root_container);
9
10 if (view->marks) {
11 if (argc) {
12 char *mark = join_args(argv, argc);
13 int index;
14 if ((index = list_seq_find(view->marks, (int (*)(const void *, const void *))strcmp, mark)) != -1) {
15 free(view->marks->items[index]);
16 list_del(view->marks, index);
17
18 if (view->marks->length == 0) {
19 list_free(view->marks);
20 view->marks = NULL;
21 }
22 }
23 free(mark);
24 } else {
25 list_foreach(view->marks, free);
26 list_free(view->marks);
27 view->marks = NULL;
28 }
29 }
30 return cmd_results_new(CMD_SUCCESS, NULL, NULL);
31}
diff --git a/sway/config.c b/sway/config.c
index 46faf643..c8432a2a 100644
--- a/sway/config.c
+++ b/sway/config.c
@@ -329,6 +329,7 @@ static void config_defaults(struct sway_config *config) {
329 config->auto_back_and_forth = false; 329 config->auto_back_and_forth = false;
330 config->seamless_mouse = true; 330 config->seamless_mouse = true;
331 config->reading = false; 331 config->reading = false;
332 config->show_marks = true;
332 333
333 config->edge_gaps = true; 334 config->edge_gaps = true;
334 config->smart_gaps = false; 335 config->smart_gaps = false;
diff --git a/sway/container.c b/sway/container.c
index 707aa4d8..08aa77a8 100644
--- a/sway/container.c
+++ b/sway/container.c
@@ -61,6 +61,10 @@ static void free_swayc(swayc_t *cont) {
61 } 61 }
62 list_free(cont->floating); 62 list_free(cont->floating);
63 } 63 }
64 if (cont->marks) {
65 list_foreach(cont->marks, free);
66 list_free(cont->marks);
67 }
64 if (cont->parent) { 68 if (cont->parent) {
65 remove_child(cont); 69 remove_child(cont);
66 } 70 }
diff --git a/sway/criteria.c b/sway/criteria.c
index bc0523ce..3ffc48f0 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -12,6 +12,7 @@
12 12
13enum criteria_type { // *must* keep in sync with criteria_strings[] 13enum criteria_type { // *must* keep in sync with criteria_strings[]
14 CRIT_CLASS, 14 CRIT_CLASS,
15 CRIT_CON_MARK,
15 CRIT_ID, 16 CRIT_ID,
16 CRIT_INSTANCE, 17 CRIT_INSTANCE,
17 CRIT_TITLE, 18 CRIT_TITLE,
@@ -25,6 +26,7 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
25// this *must* match the ordering in criteria_type enum 26// this *must* match the ordering in criteria_type enum
26static const char * const criteria_strings[] = { 27static const char * const criteria_strings[] = {
27 "class", 28 "class",
29 "con_mark",
28 "id", 30 "id",
29 "instance", 31 "instance",
30 "title", 32 "title",
@@ -243,6 +245,10 @@ ect_cleanup:
243 return error; 245 return error;
244} 246}
245 247
248int regex_cmp(const char *item, const regex_t *regex) {
249 return regexec(regex, item, 0, NULL, 0);
250}
251
246// test a single view if it matches list of criteria tokens (all of them). 252// test a single view if it matches list of criteria tokens (all of them).
247static bool criteria_test(swayc_t *cont, list_t *tokens) { 253static bool criteria_test(swayc_t *cont, list_t *tokens) {
248 if (cont->type != C_VIEW) { 254 if (cont->type != C_VIEW) {
@@ -264,6 +270,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
264 matches++; 270 matches++;
265 } 271 }
266 break; 272 break;
273 case CRIT_CON_MARK:
274 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
275 ++matches;
276 }
277 break;
267 case CRIT_ID: 278 case CRIT_ID:
268 if (!cont->app_id) { 279 if (!cont->app_id) {
269 // ignore 280 // ignore
diff --git a/sway/sway.5.txt b/sway/sway.5.txt
index 5d143d97..3cccdfd5 100644
--- a/sway/sway.5.txt
+++ b/sway/sway.5.txt
@@ -316,6 +316,14 @@ The default colors are:
316 If smart_gaps are _on_ then gaps will only be enabled if a workspace has more 316 If smart_gaps are _on_ then gaps will only be enabled if a workspace has more
317 than one child container. 317 than one child container.
318 318
319**mark** <--add|--replace> <--toggle> <identifier>::
320 Marks are arbitrary labels that can be used to identify certain windows and
321 then jump to them at a later time. By default, the **mark** command sets
322 _identifier_ as the only mark on a window. By specifying _--add_, mark will
323 add _identifier_ to the list of current marks. If _--toggle_ is specified mark
324 will remove _identifier_ if it is already a label. Marks may be found by using
325 a criteria. See the **Criteria** section below.
326
319**mode** <mode_name>:: 327**mode** <mode_name>::
320 Switches to the given mode_name. The default mode is simply _default_. To 328 Switches to the given mode_name. The default mode is simply _default_. To
321 create a new mode in config append _{_ to this command, the following lines 329 create a new mode in config append _{_ to this command, the following lines
@@ -368,6 +376,15 @@ The default colors are:
368 be configured with perfectly aligned adjacent positions for this option to 376 be configured with perfectly aligned adjacent positions for this option to
369 have any effect. 377 have any effect.
370 378
379**show_marks** <on|off>::
380 If **show_marks** is on then marks will be showed in the window decoration.
381 However, any mark that starts with an underscore will not be drawn even if the
382 option is on. The default option is _on_.
383
384**unmark** <identifier>::
385 **Unmark** will remove _identifier_ from the list of current marks on a window. If
386 no _identifier_ is specified then **unmark** will remove all marks.
387
371**workspace** [number] <name>:: 388**workspace** [number] <name>::
372 Switches to the specified workspace. The string "number" is optional. The 389 Switches to the specified workspace. The string "number" is optional. The
373 worspace _name_, if unquoted, may not contain the string "output", as sway 390 worspace _name_, if unquoted, may not contain the string "output", as sway
@@ -416,6 +433,9 @@ Currently supported attributes:
416 is _focused_ then the window class must be the same as that of the currently 433 is _focused_ then the window class must be the same as that of the currently
417 focused window. 434 focused window.
418 435
436**con_mark**::
437 Compare against the window marks. Can be a regular expression.
438
419**id**:: 439**id**::
420 Compare value against the app id. Can be a regular expression. 440 Compare value against the app id. Can be a regular expression.
421 441