2 #define I3__FILE__ "match.c"
19 #define _i3_timercmp(a, b, CMP) \
20 (((a).tv_sec == (b).tv_sec) ? ((a).tv_usec CMP(b).tv_usec) : ((a).tv_sec CMP(b).tv_sec))
29 memset(match, 0,
sizeof(
Match));
30 match->
dock = M_DONTCHECK;
31 match->
urgent = U_DONTCHECK;
45 return (match->
title == NULL &&
46 match->
mark == NULL &&
48 match->
class == NULL &&
52 match->
urgent == U_DONTCHECK &&
53 match->
id == XCB_NONE &&
65 memcpy(dest, src,
sizeof(
Match));
70 #define DUPLICATE_REGEX(field) \
72 if (src->field != NULL) \
73 dest->field = regex_new(src->field->pattern); \
92 if (match->
class != NULL) {
97 LOG(
"window class matches focused window\n");
110 LOG(
"window instance matches focused window\n");
118 if (match->
id != XCB_NONE) {
119 if (window->
id == match->
id) {
120 LOG(
"match made by window id (%d)\n", window->
id);
122 LOG(
"window id does not match\n");
127 if (match->
title != NULL) {
128 if (window->
name == NULL)
132 if (strcmp(match->
title->
pattern,
"__focused__") == 0 &&
134 LOG(
"window title matches focused window\n");
136 LOG(
"title matches (%s)\n", title);
143 if (window->
role == NULL)
147 LOG(
"window role matches focused window\n");
149 LOG(
"window_role matches (%s)\n", window->
role);
164 if (match->
urgent == U_LATEST) {
166 if (window->
urgent.tv_sec == 0) {
171 if ((con->
window != NULL) &&
176 LOG(
"urgent matches latest\n");
179 if (match->
urgent == U_OLDEST) {
181 if (window->
urgent.tv_sec == 0) {
186 if ((con->
window != NULL) &&
192 LOG(
"urgent matches oldest\n");
205 LOG(
"workspace matches focused workspace\n");
207 LOG(
"workspace matches (%s)\n", ws->
name);
213 if (match->
dock != M_DONTCHECK) {
214 if ((window->
dock == W_DOCK_TOP && match->
dock == M_DOCK_TOP) ||
215 (window->
dock == W_DOCK_BOTTOM && match->
dock == M_DOCK_BOTTOM) ||
216 ((window->
dock == W_DOCK_TOP || window->
dock == W_DOCK_BOTTOM) &&
217 match->
dock == M_DOCK_ANY) ||
218 (window->
dock == W_NODOCK && match->
dock == M_NODOCK)) {
219 LOG(
"dock status matches\n");
221 LOG(
"dock status does not match\n");
226 if (match->
mark != NULL) {
230 bool matched =
false;
240 LOG(
"mark matches\n");
242 LOG(
"mark does not match\n");
270 assert(match != NULL);
271 DLOG(
"ctype=*%s*, cvalue=*%s*\n", ctype, cvalue);
273 if (strcmp(ctype,
"class") == 0) {
279 if (strcmp(ctype,
"instance") == 0) {
285 if (strcmp(ctype,
"window_role") == 0) {
291 if (strcmp(ctype,
"con_id") == 0) {
292 if (strcmp(cvalue,
"__focused__") == 0) {
298 long parsed = strtol(cvalue, &end, 0);
299 if (parsed == LONG_MIN ||
300 parsed == LONG_MAX ||
302 (end && *end !=
'\0')) {
303 ELOG(
"Could not parse con id \"%s\"\n", cvalue);
312 if (strcmp(ctype,
"id") == 0) {
314 long parsed = strtol(cvalue, &end, 0);
315 if (parsed == LONG_MIN ||
316 parsed == LONG_MAX ||
318 (end && *end !=
'\0')) {
319 ELOG(
"Could not parse window id \"%s\"\n", cvalue);
323 DLOG(
"window id as int = %d\n", match->
id);
328 if (strcmp(ctype,
"window_type") == 0) {
329 if (strcasecmp(cvalue,
"normal") == 0) {
331 }
else if (strcasecmp(cvalue,
"dialog") == 0) {
333 }
else if (strcasecmp(cvalue,
"utility") == 0) {
334 match->
window_type = A__NET_WM_WINDOW_TYPE_UTILITY;
335 }
else if (strcasecmp(cvalue,
"toolbar") == 0) {
336 match->
window_type = A__NET_WM_WINDOW_TYPE_TOOLBAR;
337 }
else if (strcasecmp(cvalue,
"splash") == 0) {
339 }
else if (strcasecmp(cvalue,
"menu") == 0) {
341 }
else if (strcasecmp(cvalue,
"dropdown_menu") == 0) {
342 match->
window_type = A__NET_WM_WINDOW_TYPE_DROPDOWN_MENU;
343 }
else if (strcasecmp(cvalue,
"popup_menu") == 0) {
344 match->
window_type = A__NET_WM_WINDOW_TYPE_POPUP_MENU;
345 }
else if (strcasecmp(cvalue,
"tooltip") == 0) {
346 match->
window_type = A__NET_WM_WINDOW_TYPE_TOOLTIP;
347 }
else if (strcasecmp(cvalue,
"notification") == 0) {
348 match->
window_type = A__NET_WM_WINDOW_TYPE_NOTIFICATION;
350 ELOG(
"unknown window_type value \"%s\"\n", cvalue);
357 if (strcmp(ctype,
"con_mark") == 0) {
363 if (strcmp(ctype,
"title") == 0) {
369 if (strcmp(ctype,
"urgent") == 0) {
370 if (strcasecmp(cvalue,
"latest") == 0 ||
371 strcasecmp(cvalue,
"newest") == 0 ||
372 strcasecmp(cvalue,
"recent") == 0 ||
373 strcasecmp(cvalue,
"last") == 0) {
375 }
else if (strcasecmp(cvalue,
"oldest") == 0 ||
376 strcasecmp(cvalue,
"first") == 0) {
382 if (strcmp(ctype,
"workspace") == 0) {
388 ELOG(
"Unknown criterion: %s\n", ctype);
bool match_is_empty(Match *match)
Check if a match is empty.
i3String * name
The name of the window.
bool match_matches_window(Match *match, i3Window *window)
Check if a match data structure matches the given window.
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...
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.
void match_init(Match *match)
#define TAILQ_FOREACH(var, head, field)
struct timeval urgent
When this window was marked urgent.
void match_free(Match *match)
Frees the given match.
#define DUPLICATE_REGEX(field)
#define _i3_timercmp(a, b, CMP)
void regex_free(struct regex *regex)
Frees the given regular expression.
Con * con_get_workspace(Con *con)
Gets the workspace container this node is on.
A 'Window' is a type which contains an xcb_window_t and all the related information (hints like _NET_...
void match_copy(Match *dest, Match *src)
Copies the data of a match from src to dest.
struct regex * window_role
A 'Con' represents everything from the X11 root window down to a single X11 window.
const char * i3string_as_utf8(i3String *str)
Returns the UTF-8 encoded version of the i3String.
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
struct regex * application
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...
A "match" is a data structure which acts like a mask or expression to match certain windows or not...
struct all_cons_head all_cons
enum Window::@13 dock
Whether the window says it is a dock window.
char * role
The WM_WINDOW_ROLE of this window (for example, the pidgin buddy window sets "buddy list")...
xcb_atom_t window_type
The _NET_WM_WINDOW_TYPE for this window.