+ if (pr == NULL) {
+ return;
+ }
+ if (pending_rule_head == NULL) {
+ pending_rule_head = pending_rule_tail = pr;
+ } else {
+ pending_rule_tail->next = pr;
+ pr->prev = pending_rule_tail;
+ pending_rule_tail = pr;
+ }
+}
+
+void remove_pending_rule(pending_rule_t *pr)
+{
+ if (pr == NULL) {
+ return;
+ }
+ pending_rule_t *a = pr->prev;
+ pending_rule_t *b = pr->next;
+ if (a != NULL) {
+ a->next = b;
+ }
+ if (b != NULL) {
+ b->prev = a;
+ }
+ if (pr == pending_rule_head) {
+ pending_rule_head = b;
+ }
+ if (pr == pending_rule_tail) {
+ pending_rule_tail = a;
+ }
+ close(pr->fd);
+ free(pr->csq);
+ free(pr);
+}
+
+void apply_rules(xcb_window_t win, rule_consequence_t *csq)
+{
+ xcb_ewmh_get_atoms_reply_t win_type;
+
+ if (xcb_ewmh_get_wm_window_type_reply(ewmh, xcb_ewmh_get_wm_window_type(ewmh, win), &win_type, NULL) == 1) {
+ for (unsigned int i = 0; i < win_type.atoms_len; i++) {
+ xcb_atom_t a = win_type.atoms[i];
+ if (a == ewmh->_NET_WM_WINDOW_TYPE_TOOLBAR ||
+ a == ewmh->_NET_WM_WINDOW_TYPE_UTILITY) {
+ csq->focus = false;
+ } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DIALOG) {
+ if (csq->state == NULL) {
+ csq->state = malloc(sizeof(client_state_t));
+ }
+ *(csq->state) = STATE_FLOATING;
+ csq->center = true;
+ } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DOCK ||
+ a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP ||
+ a == ewmh->_NET_WM_WINDOW_TYPE_NOTIFICATION) {
+ csq->manage = false;
+ if (a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP) {
+ window_lower(win);
+ }
+ }
+ }
+ xcb_ewmh_get_atoms_reply_wipe(&win_type);
+ }
+
+ xcb_ewmh_get_atoms_reply_t win_state;
+
+ if (xcb_ewmh_get_wm_state_reply(ewmh, xcb_ewmh_get_wm_state(ewmh, win), &win_state, NULL) == 1) {
+ for (unsigned int i = 0; i < win_state.atoms_len; i++) {
+ xcb_atom_t a = win_state.atoms[i];
+ if (a == ewmh->_NET_WM_STATE_FULLSCREEN) {
+ if (csq->state == NULL) {
+ csq->state = malloc(sizeof(client_state_t));
+ }
+ *(csq->state) = STATE_FULLSCREEN;
+ } else if (a == ewmh->_NET_WM_STATE_BELOW) {
+ if (csq->layer == NULL) {
+ csq->layer = malloc(sizeof(stack_layer_t));
+ }
+ *(csq->layer) = LAYER_BELOW;
+ } else if (a == ewmh->_NET_WM_STATE_ABOVE) {
+ if (csq->layer == NULL) {
+ csq->layer = malloc(sizeof(stack_layer_t));
+ }
+ *(csq->layer) = LAYER_ABOVE;
+ } else if (a == ewmh->_NET_WM_STATE_STICKY) {
+ csq->sticky = true;
+ }
+ }
+ xcb_ewmh_get_atoms_reply_wipe(&win_state);
+ }
+
+ xcb_window_t transient_for = XCB_NONE;
+ xcb_icccm_get_wm_transient_for_reply(dpy, xcb_icccm_get_wm_transient_for(dpy, win), &transient_for, NULL);
+ if (transient_for != XCB_NONE) {
+ if (csq->state == NULL) {
+ csq->state = malloc(sizeof(client_state_t));
+ }
+ *(csq->state) = STATE_FLOATING;
+ }
+
+ xcb_size_hints_t size_hints;
+ if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &size_hints, NULL) == 1) {
+ if ((size_hints.flags & (XCB_ICCCM_SIZE_HINT_P_MIN_SIZE|XCB_ICCCM_SIZE_HINT_P_MAX_SIZE)) &&
+ size_hints.min_width == size_hints.max_width && size_hints.min_height == size_hints.max_height) {
+ if (csq->state == NULL) {
+ csq->state = malloc(sizeof(client_state_t));
+ }
+ *(csq->state) = STATE_FLOATING;
+ }
+ }
+
+ xcb_icccm_get_wm_class_reply_t reply;
+ if (xcb_icccm_get_wm_class_reply(dpy, xcb_icccm_get_wm_class(dpy, win), &reply, NULL) == 1) {
+ snprintf(csq->class_name, sizeof(csq->class_name), "%s", reply.class_name);
+ snprintf(csq->instance_name, sizeof(csq->instance_name), "%s", reply.instance_name);
+ xcb_icccm_get_wm_class_reply_wipe(&reply);
+ }
+
+ rule_t *rule = rule_head;
+ while (rule != NULL) {
+ rule_t *next = rule->next;
+ if ((streq(rule->class_name, MATCH_ANY) || streq(rule->class_name, csq->class_name)) &&
+ (streq(rule->instance_name, MATCH_ANY) || streq(rule->instance_name, csq->instance_name))) {
+ char effect[MAXLEN];
+ snprintf(effect, sizeof(effect), "%s", rule->effect);
+ char *key = strtok(effect, CSQ_BLK);
+ char *value = strtok(NULL, CSQ_BLK);
+ while (key != NULL && value != NULL) {
+ parse_key_value(key, value, csq);
+ key = strtok(NULL, CSQ_BLK);
+ value = strtok(NULL, CSQ_BLK);
+ }
+ if (rule->one_shot) {
+ remove_rule(rule);
+ break;
+ }
+ }
+ rule = next;
+ }