summaryrefslogtreecommitdiffstats
path: root/sway/criteria.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/criteria.c')
-rw-r--r--sway/criteria.c58
1 files changed, 51 insertions, 7 deletions
diff --git a/sway/criteria.c b/sway/criteria.c
index 04683f66..f5fe40cb 100644
--- a/sway/criteria.c
+++ b/sway/criteria.c
@@ -12,9 +12,12 @@
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_ID,
15 CRIT_CON_MARK, 16 CRIT_CON_MARK,
17 CRIT_FLOATING,
16 CRIT_ID, 18 CRIT_ID,
17 CRIT_INSTANCE, 19 CRIT_INSTANCE,
20 CRIT_TILING,
18 CRIT_TITLE, 21 CRIT_TITLE,
19 CRIT_URGENT, 22 CRIT_URGENT,
20 CRIT_WINDOW_ROLE, 23 CRIT_WINDOW_ROLE,
@@ -25,9 +28,12 @@ enum criteria_type { // *must* keep in sync with criteria_strings[]
25 28
26static const char * const criteria_strings[CRIT_LAST] = { 29static const char * const criteria_strings[CRIT_LAST] = {
27 [CRIT_CLASS] = "class", 30 [CRIT_CLASS] = "class",
31 [CRIT_CON_ID] = "con_id",
28 [CRIT_CON_MARK] = "con_mark", 32 [CRIT_CON_MARK] = "con_mark",
33 [CRIT_FLOATING] = "floating",
29 [CRIT_ID] = "id", 34 [CRIT_ID] = "id",
30 [CRIT_INSTANCE] = "instance", 35 [CRIT_INSTANCE] = "instance",
36 [CRIT_TILING] = "tiling",
31 [CRIT_TITLE] = "title", 37 [CRIT_TITLE] = "title",
32 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ... 38 [CRIT_URGENT] = "urgent", // either "latest" or "oldest" ...
33 [CRIT_WINDOW_ROLE] = "window_role", 39 [CRIT_WINDOW_ROLE] = "window_role",
@@ -108,6 +114,7 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
108 114
109 char **argv = *buf = calloc(max_tokens, sizeof(char*)); 115 char **argv = *buf = calloc(max_tokens, sizeof(char*));
110 argv[0] = base; // this needs to be freed by caller 116 argv[0] = base; // this needs to be freed by caller
117 bool quoted = true;
111 118
112 *argc = 1; // uneven = name, even = value 119 *argc = 1; // uneven = name, even = value
113 while (*head && *argc < max_tokens) { 120 while (*head && *argc < max_tokens) {
@@ -128,7 +135,8 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
128 if (*(namep) == ' ') { 135 if (*(namep) == ' ') {
129 namep = strrchr(namep, ' ') + 1; 136 namep = strrchr(namep, ' ') + 1;
130 } 137 }
131 argv[(*argc)++] = namep; 138 argv[*argc] = namep;
139 *argc += 1;
132 } 140 }
133 } else if (*head == '"') { 141 } else if (*head == '"') {
134 if (*argc % 2 != 0) { 142 if (*argc % 2 != 0) {
@@ -137,21 +145,38 @@ static char *crit_tokens(int *argc, char ***buf, const char * const criteria_str
137 "Found quoted value where it was not expected"); 145 "Found quoted value where it was not expected");
138 } else if (!valp) { // value starts here 146 } else if (!valp) { // value starts here
139 valp = head + 1; 147 valp = head + 1;
148 quoted = true;
140 } else { 149 } else {
141 // value ends here 150 // value ends here
142 argv[(*argc)++] = valp; 151 argv[*argc] = valp;
152 *argc += 1;
143 *head = '\0'; 153 *head = '\0';
144 valp = NULL; 154 valp = NULL;
145 namep = head + 1; 155 namep = head + 1;
146 } 156 }
147 } else if (*argc % 2 == 0 && !valp && *head != ' ') { 157 } else if (*argc % 2 == 0 && *head != ' ') {
148 // We're expecting a quoted value, haven't found one yet, and this 158 // parse unquoted values
149 // is not an empty space. 159 if (!valp) {
150 return strdup("Unable to parse criteria: " 160 quoted = false;
151 "Names must be unquoted, values must be quoted"); 161 valp = head; // value starts here
162 }
163 } else if (valp && !quoted && *head == ' ') {
164 // value ends here
165 argv[*argc] = valp;
166 *argc += 1;
167 *head = '\0';
168 valp = NULL;
169 namep = head + 1;
152 } 170 }
153 head++; 171 head++;
154 } 172 }
173
174 // catch last unquoted value if needed
175 if (valp && !quoted && !*head) {
176 argv[*argc] = valp;
177 *argc += 1;
178 }
179
155 return NULL; 180 return NULL;
156} 181}
157 182
@@ -263,6 +288,15 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
263 matches++; 288 matches++;
264 } 289 }
265 break; 290 break;
291 case CRIT_CON_ID: {
292 char *endptr;
293 size_t crit_id = strtoul(crit->raw, &endptr, 10);
294
295 if (*endptr == 0 && cont->id == crit_id) {
296 ++matches;
297 }
298 break;
299 }
266 case CRIT_CON_MARK: 300 case CRIT_CON_MARK:
267 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) { 301 if (crit->regex && cont->marks && (list_seq_find(cont->marks, (int (*)(const void *, const void *))regex_cmp, crit->regex) != -1)) {
268 // Make sure it isn't matching the NUL string 302 // Make sure it isn't matching the NUL string
@@ -271,6 +305,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
271 } 305 }
272 } 306 }
273 break; 307 break;
308 case CRIT_FLOATING:
309 if (cont->is_floating) {
310 matches++;
311 }
312 break;
274 case CRIT_ID: 313 case CRIT_ID:
275 if (!cont->app_id) { 314 if (!cont->app_id) {
276 // ignore 315 // ignore
@@ -290,6 +329,11 @@ static bool criteria_test(swayc_t *cont, list_t *tokens) {
290 matches++; 329 matches++;
291 } 330 }
292 break; 331 break;
332 case CRIT_TILING:
333 if (!cont->is_floating) {
334 matches++;
335 }
336 break;
293 case CRIT_TITLE: 337 case CRIT_TITLE:
294 if (!cont->name) { 338 if (!cont->name) {
295 // ignore 339 // ignore