17 #define _i3_timercmp(a, b, CMP) \
18 (((a).tv_sec == (b).tv_sec) ? ((a).tv_usec CMP(b).tv_usec) : ((a).tv_sec CMP(b).tv_sec))
27 memset(match, 0,
sizeof(
Match));
28 match->
urgent = U_DONTCHECK;
43 return (match->
title == NULL &&
44 match->
mark == NULL &&
46 match->
class == NULL &&
50 match->
hexid == NULL &&
51 match->
urgent == U_DONTCHECK &&
52 match->
id == XCB_NONE &&
55 match->
dock == M_NODOCK &&
64 memcpy(dest, src,
sizeof(
Match));
69 #define DUPLICATE_REGEX(field) \
71 if (src->field != NULL) \
72 dest->field = regex_new(src->field->pattern); \
92 #define GET_FIELD_str(field) (field)
93 #define GET_FIELD_i3string(field) (i3string_as_utf8(field))
94 #define CHECK_WINDOW_FIELD(match_field, window_field, type) \
96 if (match->match_field != NULL) { \
97 const char *window_field_str = window->window_field == NULL \
99 : GET_FIELD_##type(window->window_field); \
100 if (strcmp(match->match_field->pattern, "__focused__") == 0 && \
101 focused && focused->window && focused->window->window_field && \
102 strcmp(window_field_str, GET_FIELD_##type(focused->window->window_field)) == 0) { \
103 LOG("window " #match_field " matches focused window\n"); \
104 } else if (regex_matches(match->match_field, window_field_str)) { \
105 LOG("window " #match_field " matches (%s)\n", window_field_str); \
115 if (match->
id != XCB_NONE) {
116 if (window->
id == match->
id) {
117 LOG(
"match made by window id (%d)\n", window->
id);
119 LOG(
"window id does not match\n");
124 if (match->
hexid != NULL) {
125 if (window->
name == NULL)
130 LOG(
"hexid matches (%s)\n", hexid);
150 if (match->
urgent == U_LATEST) {
152 if (window->
urgent.tv_sec == 0) {
157 if ((con->
window != NULL) &&
162 LOG(
"urgent matches latest\n");
165 if (match->
urgent == U_OLDEST) {
167 if (window->
urgent.tv_sec == 0) {
172 if ((con->
window != NULL) &&
178 LOG(
"urgent matches oldest\n");
191 LOG(
"workspace matches focused workspace\n");
193 LOG(
"workspace matches (%s)\n", ws->
name);
199 if (match->
dock != M_DONTCHECK) {
200 if ((window->
dock == W_DOCK_TOP && match->
dock == M_DOCK_TOP) ||
201 (window->
dock == W_DOCK_BOTTOM && match->
dock == M_DOCK_BOTTOM) ||
202 ((window->
dock == W_DOCK_TOP || window->
dock == W_DOCK_BOTTOM) &&
203 match->
dock == M_DOCK_ANY) ||
204 (window->
dock == W_NODOCK && match->
dock == M_NODOCK)) {
205 LOG(
"dock status matches\n");
207 LOG(
"dock status does not match\n");
212 if (match->
mark != NULL) {
216 bool matched =
false;
226 LOG(
"mark matches\n");
228 LOG(
"mark does not match\n");
240 if (con->
floating != FLOATING_AUTO_OFF) {
245 if (con->
floating != FLOATING_USER_OFF) {
254 case WM_FLOATING_AUTO:
255 if (con->
floating != FLOATING_AUTO_ON) {
259 case WM_FLOATING_USER:
260 if (con->
floating != FLOATING_USER_ON) {
273 LOG(
"window_mode matches\n");
300 assert(match != NULL);
301 DLOG(
"ctype=*%s*, cvalue=*%s*\n", ctype, cvalue);
303 if (strcmp(ctype,
"class") == 0) {
309 if (strcmp(ctype,
"instance") == 0) {
315 if (strcmp(ctype,
"window_role") == 0) {
321 if (strcmp(ctype,
"con_id") == 0) {
322 if (strcmp(cvalue,
"__focused__") == 0) {
329 ELOG(
"Could not parse con id \"%s\"\n", cvalue);
338 if (strcmp(ctype,
"id") == 0) {
341 ELOG(
"Could not parse window id \"%s\"\n", cvalue);
345 DLOG(
"window id as int = %d\n", match->
id);
350 if (strcmp(ctype,
"hexid") == 0) {
356 if (strcmp(ctype,
"window_type") == 0) {
357 if (strcasecmp(cvalue,
"normal") == 0) {
359 }
else if (strcasecmp(cvalue,
"dialog") == 0) {
361 }
else if (strcasecmp(cvalue,
"utility") == 0) {
362 match->
window_type = A__NET_WM_WINDOW_TYPE_UTILITY;
363 }
else if (strcasecmp(cvalue,
"toolbar") == 0) {
364 match->
window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR;
365 }
else if (strcasecmp(cvalue,
"splash") == 0) {
367 }
else if (strcasecmp(cvalue,
"menu") == 0) {
369 }
else if (strcasecmp(cvalue,
"dropdown_menu") == 0) {
370 match->
window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
371 }
else if (strcasecmp(cvalue,
"popup_menu") == 0) {
372 match->
window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU;
373 }
else if (strcasecmp(cvalue,
"tooltip") == 0) {
374 match->
window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP;
375 }
else if (strcasecmp(cvalue,
"notification") == 0) {
376 match->
window_type = A__NET_WM_WINDOW_TYPE_NOTIFICATION;
378 ELOG(
"unknown window_type value \"%s\"\n", cvalue);
385 if (strcmp(ctype,
"con_mark") == 0) {
391 if (strcmp(ctype,
"title") == 0) {
397 if (strcmp(ctype,
"urgent") == 0) {
398 if (strcasecmp(cvalue,
"latest") == 0 ||
399 strcasecmp(cvalue,
"newest") == 0 ||
400 strcasecmp(cvalue,
"recent") == 0 ||
401 strcasecmp(cvalue,
"last") == 0) {
403 }
else if (strcasecmp(cvalue,
"oldest") == 0 ||
404 strcasecmp(cvalue,
"first") == 0) {
410 if (strcmp(ctype,
"workspace") == 0) {
416 if (strcmp(ctype,
"tiling") == 0) {
421 if (strcmp(ctype,
"tiling_from") == 0 &&
423 strcmp(cvalue,
"auto") == 0) {
428 if (strcmp(ctype,
"tiling_from") == 0 &&
430 strcmp(cvalue,
"user") == 0) {
435 if (strcmp(ctype,
"floating") == 0) {
440 if (strcmp(ctype,
"floating_from") == 0 &&
442 strcmp(cvalue,
"auto") == 0) {
447 if (strcmp(ctype,
"floating_from") == 0 &&
449 strcmp(cvalue,
"user") == 0) {
454 ELOG(
"Unknown criterion: %s\n", ctype);
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
Con * con_by_window_id(xcb_window_t window)
Returns the container with the given client window ID or NULL if no such container exists.
Con * con_inside_floating(Con *con)
Checks if the given container is either floating or inside some floating container.
struct pending_marks * marks
#define _i3_timercmp(a, b, CMP)
#define DUPLICATE_REGEX(field)
bool match_is_empty(Match *match)
Check if a match is empty.
void match_init(Match *match)
Initializes the Match data structure.
void match_copy(Match *dest, Match *src)
Copies the data of a match from src to dest.
void match_free(Match *match)
Frees the given match.
bool match_matches_window(Match *match, i3Window *window)
Check if a match data structure matches the given window.
void match_parse_property(Match *match, const char *ctype, const char *cvalue)
Interprets a ctype=cvalue pair and adds it to the given match specification.
#define CHECK_WINDOW_FIELD(match_field, window_field, type)
struct regex * regex_new(const char *pattern)
Creates a new 'regex' struct containing the given pattern and a PCRE compiled regular expression.
bool regex_matches(struct regex *regex, const char *input)
Checks if the given regular expression matches the given input and returns true if it does.
void regex_free(struct regex *regex)
Frees the given regular expression.
struct all_cons_head all_cons
bool parse_long(const char *str, long *out, int base)
Converts a string into a long using strtol().
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
#define TAILQ_FOREACH(var, head, field)
A 'Window' is a type which contains an xcb_window_t and all the related information (hints like _NET_...
struct timeval urgent
When this window was marked urgent.
i3String * name
The name of the window.
xcb_atom_t window_type
The _NET_WM_WINDOW_TYPE for this window.
enum Window::@13 dock
Whether the window says it is a dock window.
A "match" is a data structure which acts like a mask or expression to match certain windows or not.
struct regex * window_role
struct regex * application
enum Match::@16 window_mode
A 'Con' represents everything from the X11 root window down to a single X11 window.
enum Con::@21 floating
floating? (= not in tiling layout) This cannot be simply a bool because we want to keep track of whet...