i3
|
00001 /* 00002 * vim:ts=4:sw=4:expandtab 00003 * 00004 * i3 - an improved dynamic tiling window manager 00005 * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE) 00006 * 00007 * A "match" is a data structure which acts like a mask or expression to match 00008 * certain windows or not. For example, when using commands, you can specify a 00009 * command like this: [title="*Firefox*"] kill. The title member of the match 00010 * data structure will then be filled and i3 will check each window using 00011 * match_matches_window() to find the windows affected by this command. 00012 * 00013 */ 00014 00015 #include "all.h" 00016 00017 /* 00018 * Initializes the Match data structure. This function is necessary because the 00019 * members representing boolean values (like dock) need to be initialized with 00020 * -1 instead of 0. 00021 * 00022 */ 00023 void match_init(Match *match) { 00024 memset(match, 0, sizeof(Match)); 00025 match->dock = -1; 00026 } 00027 00028 /* 00029 * Check if a match is empty. This is necessary while parsing commands to see 00030 * whether the user specified a match at all. 00031 * 00032 */ 00033 bool match_is_empty(Match *match) { 00034 /* we cannot simply use memcmp() because the structure is part of a 00035 * TAILQ and I don’t want to start with things like assuming that the 00036 * last member of a struct really is at the end in memory… */ 00037 return (match->title == NULL && 00038 match->mark == NULL && 00039 match->application == NULL && 00040 match->class == NULL && 00041 match->instance == NULL && 00042 match->id == XCB_NONE && 00043 match->con_id == NULL && 00044 match->dock == -1 && 00045 match->floating == M_ANY); 00046 } 00047 00048 /* 00049 * Copies the data of a match from src to dest. 00050 * 00051 */ 00052 void match_copy(Match *dest, Match *src) { 00053 memcpy(dest, src, sizeof(Match)); 00054 00055 #define STRDUP(field) do { \ 00056 if (src->field != NULL) \ 00057 dest->field = sstrdup(src->field); \ 00058 } while (0) 00059 00060 STRDUP(title); 00061 STRDUP(mark); 00062 STRDUP(application); 00063 STRDUP(class); 00064 STRDUP(instance); 00065 } 00066 00067 /* 00068 * Check if a match data structure matches the given window. 00069 * 00070 */ 00071 bool match_matches_window(Match *match, i3Window *window) { 00072 LOG("checking window %d (%s)\n", window->id, window->class_class); 00073 00074 /* TODO: pcre, full matching, … */ 00075 if (match->class != NULL) { 00076 if (window->class_class != NULL && strcasecmp(match->class, window->class_class) == 0) { 00077 LOG("window class matches (%s)\n", window->class_class); 00078 } else { 00079 LOG("window class does not match\n"); 00080 return false; 00081 } 00082 } 00083 00084 if (match->instance != NULL) { 00085 if (window->class_instance != NULL && strcasecmp(match->instance, window->class_instance) == 0) { 00086 LOG("window instance matches (%s)\n", window->class_instance); 00087 } else { 00088 LOG("window instance does not match\n"); 00089 return false; 00090 } 00091 } 00092 00093 if (match->id != XCB_NONE) { 00094 if (window->id == match->id) { 00095 LOG("match made by window id (%d)\n", window->id); 00096 } else { 00097 LOG("window id does not match\n"); 00098 return false; 00099 } 00100 } 00101 00102 /* TODO: pcre match */ 00103 if (match->title != NULL) { 00104 if (window->name_json != NULL && strcasecmp(match->title, window->name_json) == 0) { 00105 LOG("title matches (%s)\n", window->name_json); 00106 } else { 00107 LOG("title does not match\n"); 00108 return false; 00109 } 00110 } 00111 00112 if (match->dock != -1) { 00113 LOG("match->dock = %d, window->dock = %d\n", match->dock, window->dock); 00114 if ((window->dock == W_DOCK_TOP && match->dock == M_DOCK_TOP) || 00115 (window->dock == W_DOCK_BOTTOM && match->dock == M_DOCK_BOTTOM) || 00116 ((window->dock == W_DOCK_TOP || window->dock == W_DOCK_BOTTOM) && 00117 match->dock == M_DOCK_ANY) || 00118 (window->dock == W_NODOCK && match->dock == M_NODOCK)) { 00119 LOG("dock status matches\n"); 00120 } else { 00121 LOG("dock status does not match\n"); 00122 return false; 00123 } 00124 } 00125 00126 /* We don’t check the mark because this function is not even called when 00127 * the mark would have matched - it is checked in cmdparse.y itself */ 00128 if (match->mark != NULL) { 00129 LOG("mark does not match\n"); 00130 return false; 00131 } 00132 00133 return true; 00134 }