-#undef I3__FILE__
-#define I3__FILE__ "match.c"
/*
* vim:ts=4:sw=4:expandtab
*
*/
void match_init(Match *match) {
memset(match, 0, sizeof(Match));
- match->dock = M_DONTCHECK;
match->urgent = U_DONTCHECK;
+ match->window_mode = WM_ANY;
/* we use this as the placeholder value for "not set". */
match->window_type = UINT32_MAX;
}
match->id == XCB_NONE &&
match->window_type == UINT32_MAX &&
match->con_id == NULL &&
- match->dock == -1 &&
- match->floating == M_ANY);
+ match->dock == M_NODOCK &&
+ match->window_mode == WM_ANY);
}
/*
bool match_matches_window(Match *match, i3Window *window) {
LOG("Checking window 0x%08x (class %s)\n", window->id, window->class_class);
- if (match->class != NULL) {
- if (window->class_class == NULL)
- return false;
- if (strcmp(match->class->pattern, "__focused__") == 0 &&
- strcmp(window->class_class, focused->window->class_class) == 0) {
- LOG("window class matches focused window\n");
- } else if (regex_matches(match->class, window->class_class)) {
- LOG("window class matches (%s)\n", window->class_class);
- } else {
- return false;
- }
- }
+#define GET_FIELD_str(field) (field)
+#define GET_FIELD_i3string(field) (i3string_as_utf8(field))
+#define CHECK_WINDOW_FIELD(match_field, window_field, type) \
+ do { \
+ if (match->match_field != NULL) { \
+ if (window->window_field == NULL) { \
+ return false; \
+ } \
+ \
+ const char *window_field_str = GET_FIELD_##type(window->window_field); \
+ if (strcmp(match->match_field->pattern, "__focused__") == 0 && \
+ focused && focused->window && focused->window->window_field && \
+ strcmp(window_field_str, GET_FIELD_##type(focused->window->window_field)) == 0) { \
+ LOG("window " #match_field " matches focused window\n"); \
+ } else if (regex_matches(match->match_field, window_field_str)) { \
+ LOG("window " #match_field " matches (%s)\n", window_field_str); \
+ } else { \
+ return false; \
+ } \
+ } \
+ } while (0)
- if (match->instance != NULL) {
- if (window->class_instance == NULL)
- return false;
- if (strcmp(match->instance->pattern, "__focused__") == 0 &&
- strcmp(window->class_instance, focused->window->class_instance) == 0) {
- LOG("window instance matches focused window\n");
- } else if (regex_matches(match->instance, window->class_instance)) {
- LOG("window instance matches (%s)\n", window->class_instance);
- } else {
- return false;
- }
- }
+ CHECK_WINDOW_FIELD(class, class_class, str);
+ CHECK_WINDOW_FIELD(instance, class_instance, str);
if (match->id != XCB_NONE) {
if (window->id == match->id) {
}
}
- if (match->title != NULL) {
- if (window->name == NULL)
- return false;
-
- const char *title = i3string_as_utf8(window->name);
- if (strcmp(match->title->pattern, "__focused__") == 0 &&
- strcmp(title, i3string_as_utf8(focused->window->name)) == 0) {
- LOG("window title matches focused window\n");
- } else if (regex_matches(match->title, title)) {
- LOG("title matches (%s)\n", title);
- } else {
- return false;
- }
- }
-
- if (match->window_role != NULL) {
- if (window->role == NULL)
- return false;
- if (strcmp(match->window_role->pattern, "__focused__") == 0 &&
- strcmp(window->role, focused->window->role) == 0) {
- LOG("window role matches focused window\n");
- } else if (regex_matches(match->window_role, window->role)) {
- LOG("window_role matches (%s)\n", window->role);
- } else {
- return false;
- }
- }
+ CHECK_WINDOW_FIELD(title, name, i3string);
+ CHECK_WINDOW_FIELD(window_role, role, str);
if (match->window_type != UINT32_MAX) {
if (window->window_type == match->window_type) {
/* if we find a window that is newer than this one, bail */
TAILQ_FOREACH(con, &all_cons, all_cons) {
if ((con->window != NULL) &&
- _i3_timercmp(con->window->urgent, window->urgent, > )) {
+ _i3_timercmp(con->window->urgent, window->urgent, >)) {
return false;
}
}
TAILQ_FOREACH(con, &all_cons, all_cons) {
if ((con->window != NULL) &&
(con->window->urgent.tv_sec != 0) &&
- _i3_timercmp(con->window->urgent, window->urgent, < )) {
+ _i3_timercmp(con->window->urgent, window->urgent, <)) {
return false;
}
}
}
}
- /* We don’t check the mark because this function is not even called when
- * the mark would have matched - it is checked in cmdparse.y itself */
if (match->mark != NULL) {
- LOG("mark does not match\n");
- return false;
+ if ((con = con_by_window_id(window->id)) == NULL)
+ return false;
+
+ bool matched = false;
+ mark_t *mark;
+ TAILQ_FOREACH(mark, &(con->marks_head), marks) {
+ if (regex_matches(match->mark, mark->name)) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (matched) {
+ LOG("mark matches\n");
+ } else {
+ LOG("mark does not match\n");
+ return false;
+ }
+ }
+
+ if (match->window_mode != WM_ANY) {
+ if ((con = con_by_window_id(window->id)) == NULL)
+ return false;
+
+ const bool floating = (con_inside_floating(con) != NULL);
+
+ if ((match->window_mode == WM_TILING && floating) ||
+ (match->window_mode == WM_FLOATING && !floating)) {
+ LOG("window_mode does not match\n");
+ return false;
+ }
+
+ LOG("window_mode matches\n");
}
return true;
return;
}
- char *end;
- long parsed = strtol(cvalue, &end, 0);
- if (parsed == LONG_MIN ||
- parsed == LONG_MAX ||
- parsed < 0 ||
- (end && *end != '\0')) {
+ long parsed;
+ if (!parse_long(cvalue, &parsed, 0)) {
ELOG("Could not parse con id \"%s\"\n", cvalue);
match->error = sstrdup("invalid con_id");
} else {
}
if (strcmp(ctype, "id") == 0) {
- char *end;
- long parsed = strtol(cvalue, &end, 10);
- if (parsed == LONG_MIN ||
- parsed == LONG_MAX ||
- parsed < 0 ||
- (end && *end != '\0')) {
+ long parsed;
+ if (!parse_long(cvalue, &parsed, 0)) {
ELOG("Could not parse window id \"%s\"\n", cvalue);
match->error = sstrdup("invalid id");
} else {
return;
}
+ if (strcmp(ctype, "tiling") == 0) {
+ match->window_mode = WM_TILING;
+ return;
+ }
+
+ if (strcmp(ctype, "floating") == 0) {
+ match->window_mode = WM_FLOATING;
+ return;
+ }
+
ELOG("Unknown criterion: %s\n", ctype);
}