diff options
-rw-r--r-- | include/sway/tree/view.h | 2 | ||||
-rw-r--r-- | sway/criteria.c | 204 | ||||
-rw-r--r-- | sway/tree/view.c | 7 |
3 files changed, 42 insertions, 171 deletions
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 65cadea1..144ad038 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -176,8 +176,6 @@ const char *view_get_instance(struct sway_view *view); | |||
176 | 176 | ||
177 | uint32_t view_get_x11_window_id(struct sway_view *view); | 177 | uint32_t view_get_x11_window_id(struct sway_view *view); |
178 | 178 | ||
179 | const char *view_get_window_role(struct sway_view *view); | ||
180 | |||
181 | uint32_t view_get_window_type(struct sway_view *view); | 179 | uint32_t view_get_window_type(struct sway_view *view); |
182 | 180 | ||
183 | const char *view_get_type(struct sway_view *view); | 181 | const char *view_get_type(struct sway_view *view); |
diff --git a/sway/criteria.c b/sway/criteria.c index 294b2922..7da790e6 100644 --- a/sway/criteria.c +++ b/sway/criteria.c | |||
@@ -190,128 +190,19 @@ static bool generate_regex(pcre **regex, char *value) { | |||
190 | return true; | 190 | return true; |
191 | } | 191 | } |
192 | 192 | ||
193 | enum criteria_token { | ||
194 | T_APP_ID, | ||
195 | T_CLASS, | ||
196 | T_CON_ID, | ||
197 | T_CON_MARK, | ||
198 | T_FLOATING, | ||
199 | T_ID, | ||
200 | T_INSTANCE, | ||
201 | T_TILING, | ||
202 | T_TITLE, | ||
203 | T_URGENT, | ||
204 | T_WINDOW_ROLE, | ||
205 | T_WINDOW_TYPE, | ||
206 | T_WORKSPACE, | ||
207 | |||
208 | T_INVALID, | ||
209 | }; | ||
210 | |||
211 | static enum criteria_token token_from_name(char *name) { | ||
212 | if (strcmp(name, "app_id") == 0) { | ||
213 | return T_APP_ID; | ||
214 | } else if (strcmp(name, "class") == 0) { | ||
215 | return T_CLASS; | ||
216 | } else if (strcmp(name, "con_id") == 0) { | ||
217 | return T_CON_ID; | ||
218 | } else if (strcmp(name, "con_mark") == 0) { | ||
219 | return T_CON_MARK; | ||
220 | } else if (strcmp(name, "id") == 0) { | ||
221 | return T_ID; | ||
222 | } else if (strcmp(name, "instance") == 0) { | ||
223 | return T_INSTANCE; | ||
224 | } else if (strcmp(name, "title") == 0) { | ||
225 | return T_TITLE; | ||
226 | } else if (strcmp(name, "urgent") == 0) { | ||
227 | return T_URGENT; | ||
228 | } else if (strcmp(name, "window_role") == 0) { | ||
229 | return T_WINDOW_ROLE; | ||
230 | } else if (strcmp(name, "window_type") == 0) { | ||
231 | return T_WINDOW_TYPE; | ||
232 | } else if (strcmp(name, "workspace") == 0) { | ||
233 | return T_WORKSPACE; | ||
234 | } | ||
235 | return T_INVALID; | ||
236 | } | ||
237 | |||
238 | /** | ||
239 | * Get a property of the focused view. | ||
240 | * | ||
241 | * Note that we are taking the focused view at the time of criteria parsing, not | ||
242 | * at the time of execution. This is because __focused__ only makes sense when | ||
243 | * using criteria via IPC. Using __focused__ in config is not useful because | ||
244 | * criteria is only executed once per view. | ||
245 | */ | ||
246 | static char *get_focused_prop(enum criteria_token token) { | ||
247 | struct sway_seat *seat = input_manager_current_seat(input_manager); | ||
248 | struct sway_container *focus = seat_get_focus(seat); | ||
249 | |||
250 | if (!focus || focus->type != C_VIEW) { | ||
251 | return NULL; | ||
252 | } | ||
253 | struct sway_view *view = focus->sway_view; | ||
254 | const char *value = NULL; | ||
255 | |||
256 | switch (token) { | ||
257 | case T_APP_ID: | ||
258 | value = view_get_app_id(view); | ||
259 | break; | ||
260 | case T_CLASS: | ||
261 | value = view_get_class(view); | ||
262 | break; | ||
263 | case T_INSTANCE: | ||
264 | value = view_get_instance(view); | ||
265 | break; | ||
266 | case T_TITLE: | ||
267 | value = view_get_class(view); | ||
268 | break; | ||
269 | case T_WINDOW_ROLE: | ||
270 | value = view_get_class(view); | ||
271 | break; | ||
272 | case T_WORKSPACE: | ||
273 | { | ||
274 | struct sway_container *ws = container_parent(focus, C_WORKSPACE); | ||
275 | if (ws) { | ||
276 | value = ws->name; | ||
277 | } | ||
278 | } | ||
279 | break; | ||
280 | case T_CON_ID: // These do not support __focused__ | ||
281 | case T_CON_MARK: | ||
282 | case T_FLOATING: | ||
283 | case T_ID: | ||
284 | case T_TILING: | ||
285 | case T_URGENT: | ||
286 | case T_WINDOW_TYPE: | ||
287 | case T_INVALID: | ||
288 | break; | ||
289 | } | ||
290 | if (value) { | ||
291 | return strdup(value); | ||
292 | } | ||
293 | return NULL; | ||
294 | } | ||
295 | |||
296 | static bool parse_token(struct criteria *criteria, char *name, char *value) { | 193 | static bool parse_token(struct criteria *criteria, char *name, char *value) { |
297 | enum criteria_token token = token_from_name(name); | ||
298 | if (token == T_INVALID) { | ||
299 | const char *fmt = "Token '%s' is not recognized"; | ||
300 | int len = strlen(fmt) + strlen(name) - 1; | ||
301 | error = malloc(len); | ||
302 | snprintf(error, len, fmt, name); | ||
303 | return false; | ||
304 | } | ||
305 | |||
306 | char *effective_value = NULL; | ||
307 | if (value && strcmp(value, "__focused__") == 0) { | ||
308 | effective_value = get_focused_prop(token); | ||
309 | } else if (value) { | ||
310 | effective_value = strdup(value); | ||
311 | } | ||
312 | |||
313 | // Require value, unless token is floating or tiled | 194 | // Require value, unless token is floating or tiled |
314 | if (!effective_value && token != T_FLOATING && token != T_TILING) { | 195 | if (!value && (strcmp(name, "title") == 0 |
196 | || strcmp(name, "app_id") == 0 | ||
197 | || strcmp(name, "class") == 0 | ||
198 | || strcmp(name, "instance") == 0 | ||
199 | || strcmp(name, "con_id") == 0 | ||
200 | || strcmp(name, "con_mark") == 0 | ||
201 | || strcmp(name, "window_role") == 0 | ||
202 | || strcmp(name, "window_type") == 0 | ||
203 | || strcmp(name, "id") == 0 | ||
204 | || strcmp(name, "urgent") == 0 | ||
205 | || strcmp(name, "workspace") == 0)) { | ||
315 | const char *fmt = "Token '%s' requires a value"; | 206 | const char *fmt = "Token '%s' requires a value"; |
316 | int len = strlen(fmt) + strlen(name) - 1; | 207 | int len = strlen(fmt) + strlen(name) - 1; |
317 | error = malloc(len); | 208 | error = malloc(len); |
@@ -319,64 +210,53 @@ static bool parse_token(struct criteria *criteria, char *name, char *value) { | |||
319 | return false; | 210 | return false; |
320 | } | 211 | } |
321 | 212 | ||
322 | char *endptr = NULL; | 213 | if (strcmp(name, "title") == 0) { |
323 | switch (token) { | 214 | generate_regex(&criteria->title, value); |
324 | case T_TITLE: | 215 | } else if (strcmp(name, "app_id") == 0) { |
325 | generate_regex(&criteria->title, effective_value); | 216 | generate_regex(&criteria->app_id, value); |
326 | break; | 217 | } else if (strcmp(name, "class") == 0) { |
327 | case T_APP_ID: | 218 | generate_regex(&criteria->class, value); |
328 | generate_regex(&criteria->app_id, effective_value); | 219 | } else if (strcmp(name, "instance") == 0) { |
329 | break; | 220 | generate_regex(&criteria->instance, value); |
330 | case T_CLASS: | 221 | } else if (strcmp(name, "con_id") == 0) { |
331 | generate_regex(&criteria->class, effective_value); | 222 | char *endptr; |
332 | break; | 223 | criteria->con_id = strtoul(value, &endptr, 10); |
333 | case T_INSTANCE: | ||
334 | generate_regex(&criteria->instance, effective_value); | ||
335 | break; | ||
336 | case T_CON_ID: | ||
337 | criteria->con_id = strtoul(effective_value, &endptr, 10); | ||
338 | if (*endptr != 0) { | 224 | if (*endptr != 0) { |
339 | error = strdup("The value for 'con_id' should be numeric"); | 225 | error = strdup("The value for 'con_id' should be numeric"); |
340 | } | 226 | } |
341 | break; | 227 | } else if (strcmp(name, "con_mark") == 0) { |
342 | case T_CON_MARK: | 228 | generate_regex(&criteria->con_mark, value); |
343 | generate_regex(&criteria->con_mark, effective_value); | 229 | } else if (strcmp(name, "window_role") == 0) { |
344 | break; | 230 | generate_regex(&criteria->window_role, value); |
345 | case T_WINDOW_ROLE: | 231 | } else if (strcmp(name, "window_type") == 0) { |
346 | generate_regex(&criteria->window_role, effective_value); | ||
347 | break; | ||
348 | case T_WINDOW_TYPE: | ||
349 | // TODO: This is a string but will be stored as an enum or integer | 232 | // TODO: This is a string but will be stored as an enum or integer |
350 | break; | 233 | } else if (strcmp(name, "id") == 0) { |
351 | case T_ID: | 234 | char *endptr; |
352 | criteria->id = strtoul(effective_value, &endptr, 10); | 235 | criteria->id = strtoul(value, &endptr, 10); |
353 | if (*endptr != 0) { | 236 | if (*endptr != 0) { |
354 | error = strdup("The value for 'id' should be numeric"); | 237 | error = strdup("The value for 'id' should be numeric"); |
355 | } | 238 | } |
356 | break; | 239 | } else if (strcmp(name, "floating") == 0) { |
357 | case T_FLOATING: | ||
358 | criteria->floating = true; | 240 | criteria->floating = true; |
359 | break; | 241 | } else if (strcmp(name, "tiling") == 0) { |
360 | case T_TILING: | ||
361 | criteria->tiling = true; | 242 | criteria->tiling = true; |
362 | break; | 243 | } else if (strcmp(name, "urgent") == 0) { |
363 | case T_URGENT: | 244 | if (strcmp(value, "latest") == 0) { |
364 | if (strcmp(effective_value, "latest") == 0) { | ||
365 | criteria->urgent = 'l'; | 245 | criteria->urgent = 'l'; |
366 | } else if (strcmp(effective_value, "oldest") == 0) { | 246 | } else if (strcmp(value, "oldest") == 0) { |
367 | criteria->urgent = 'o'; | 247 | criteria->urgent = 'o'; |
368 | } else { | 248 | } else { |
369 | error = | 249 | error = |
370 | strdup("The value for 'urgent' must be 'latest' or 'oldest'"); | 250 | strdup("The value for 'urgent' must be 'latest' or 'oldest'"); |
371 | } | 251 | } |
372 | break; | 252 | } else if (strcmp(name, "workspace") == 0) { |
373 | case T_WORKSPACE: | 253 | criteria->workspace = strdup(value); |
374 | criteria->workspace = strdup(effective_value); | 254 | } else { |
375 | break; | 255 | const char *fmt = "Token '%s' is not recognized"; |
376 | case T_INVALID: | 256 | int len = strlen(fmt) + strlen(name) - 1; |
377 | break; | 257 | error = malloc(len); |
258 | snprintf(error, len, fmt, name); | ||
378 | } | 259 | } |
379 | free(effective_value); | ||
380 | 260 | ||
381 | if (error) { | 261 | if (error) { |
382 | return false; | 262 | return false; |
diff --git a/sway/tree/view.c b/sway/tree/view.c index 3b3b6eaf..7431ac06 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -79,13 +79,6 @@ uint32_t view_get_x11_window_id(struct sway_view *view) { | |||
79 | return 0; | 79 | return 0; |
80 | } | 80 | } |
81 | 81 | ||
82 | const char *view_get_window_role(struct sway_view *view) { | ||
83 | if (view->impl->get_string_prop) { | ||
84 | return view->impl->get_string_prop(view, VIEW_PROP_WINDOW_ROLE); | ||
85 | } | ||
86 | return NULL; | ||
87 | } | ||
88 | |||
89 | uint32_t view_get_window_type(struct sway_view *view) { | 82 | uint32_t view_get_window_type(struct sway_view *view) { |
90 | if (view->impl->get_int_prop) { | 83 | if (view->impl->get_int_prop) { |
91 | return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); | 84 | return view->impl->get_int_prop(view, VIEW_PROP_WINDOW_TYPE); |