]> git.lizzy.rs Git - bspwm.git/blobdiff - rule.c
Prevent potential memory leak
[bspwm.git] / rule.c
diff --git a/rule.c b/rule.c
index ad658f63db542c60bbdc85058a59eb85ede932ef..ecdd87d9405d7f268a60606806384f7cb0ddb277 100644 (file)
--- a/rule.c
+++ b/rule.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, Bastien Dejean
+/* Copyright (c) 2012, Bastien Dejean
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * The views and conclusions contained in the software and documentation are those
- * of the authors and should not be interpreted as representing official policies,
- * either expressed or implied, of the FreeBSD Project.
  */
 
 #include <stdio.h>
@@ -97,7 +93,9 @@ bool remove_rule_by_index(int idx)
 rule_consequence_t *make_rule_conquence(void)
 {
        rule_consequence_t *rc = calloc(1, sizeof(rule_consequence_t));
-       rc->manage = rc->focus = true;
+       rc->manage = rc->focus = rc->border = true;
+       rc->layer = NULL;
+       rc->state = NULL;
        return rc;
 }
 
@@ -115,7 +113,6 @@ void add_pending_rule(pending_rule_t *pr)
 {
        if (pr == NULL)
                return;
-       PRINTF("add pending rule %i\n", pr->fd);
        if (pending_rule_head == NULL) {
                pending_rule_head = pending_rule_tail = pr;
        } else {
@@ -129,7 +126,6 @@ void remove_pending_rule(pending_rule_t *pr)
 {
        if (pr == NULL)
                return;
-       PRINTF("remove pending rule %i\n", pr->fd);
        pending_rule_t *a = pr->prev;
        pending_rule_t *b = pr->next;
        if (a != NULL)
@@ -156,14 +152,18 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
                            a == ewmh->_NET_WM_WINDOW_TYPE_UTILITY) {
                                csq->focus = false;
                        } else if (a == ewmh->_NET_WM_WINDOW_TYPE_DIALOG) {
-                               csq->floating = true;
+                               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)
+                               if (a == ewmh->_NET_WM_WINDOW_TYPE_DESKTOP) {
                                        window_lower(win);
+                               }
                        }
                }
                xcb_ewmh_get_atoms_reply_wipe(&win_type);
@@ -174,10 +174,24 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
        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)
-                               csq->fullscreen = true;
-                       else if (a == ewmh->_NET_WM_STATE_STICKY)
+                       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);
        }
@@ -186,8 +200,12 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
        if (xcb_icccm_get_wm_normal_hints_reply(dpy, xcb_icccm_get_wm_normal_hints(dpy, win), &size_hints, NULL) == 1) {
                if (size_hints.min_width > 0 && size_hints.min_height > 0 &&
                    size_hints.min_width == size_hints.max_width &&
-                   size_hints.min_height == size_hints.max_height)
-                       csq->floating = true;
+                   size_hints.min_height == size_hints.max_height) {
+                       if (csq->state == NULL) {
+                               csq->state = malloc(sizeof(client_state_t));
+                       }
+                       *(csq->state) = STATE_FLOATING;
+               }
                csq->min_width = size_hints.min_width;
                csq->max_width = size_hints.max_width;
                csq->min_height = size_hints.min_height;
@@ -196,8 +214,12 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
 
        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)
-               csq->floating = true;
+       if (transient_for != XCB_NONE) {
+               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) {
@@ -221,8 +243,9 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
                                key = strtok(NULL, CSQ_BLK);
                                value = strtok(NULL, CSQ_BLK);
                        }
-                       if (rule->one_shot)
+                       if (rule->one_shot) {
                                remove_rule(rule);
+                       }
                }
                rule = next;
        }
@@ -230,15 +253,18 @@ void apply_rules(xcb_window_t win, rule_consequence_t *csq)
 
 bool schedule_rules(xcb_window_t win, rule_consequence_t *csq)
 {
-       if (external_rules_command[0] == '\0')
+       if (external_rules_command[0] == '\0') {
                return false;
+       }
        int fds[2];
-       if (pipe(fds) == -1)
+       if (pipe(fds) == -1) {
                return false;
+       }
        pid_t pid = fork();
        if (pid == 0) {
-               if (dpy != NULL)
+               if (dpy != NULL) {
                        close(xcb_get_file_descriptor(dpy));
+               }
                dup2(fds[1], 1);
                close(fds[0]);
                char wid[SMALEN];
@@ -284,33 +310,49 @@ void parse_key_value(char *key, char *value, rule_consequence_t *csq)
                snprintf(csq->node_desc, sizeof(csq->node_desc), "%s", value);
        } else if (streq("split_dir", key)) {
                snprintf(csq->split_dir, sizeof(csq->split_dir), "%s", value);
+       } else if (streq("state", key)) {
+               client_state_t cst;
+               if (parse_client_state(value, &cst)) {
+                       if (csq->state == NULL) {
+                               csq->state = malloc(sizeof(client_state_t));
+                       }
+                       *(csq->state) = cst;
+               }
+       } else if (streq("layer", key)) {
+               stack_layer_t lyr;
+               if (parse_stack_layer(value, &lyr)) {
+                       if (csq->layer == NULL) {
+                               csq->layer = malloc(sizeof(stack_layer_t));
+                       }
+                       *(csq->layer) = lyr;
+               }
+       } else if (streq("split_ratio", key)) {
+               double rat;
+               if (sscanf(value, "%lf", &rat) == 1 && rat > 0 && rat < 1) {
+                       csq->split_ratio = rat;
+               }
        } else if (parse_bool(value, &v)) {
-               if (streq("floating", key))
-                       csq->floating = v;
+               if (streq("locked", key))
+                       csq->locked = true;
 #define SETCSQ(name) \
                else if (streq(#name, key)) \
                        csq->name = v;
-               SETCSQ(pseudo_tiled)
-               SETCSQ(fullscreen)
-               SETCSQ(locked)
                SETCSQ(sticky)
                SETCSQ(private)
                SETCSQ(center)
-               SETCSQ(lower)
                SETCSQ(follow)
                SETCSQ(manage)
                SETCSQ(focus)
+               SETCSQ(border)
 #undef SETCSQ
        }
 }
 
-void list_rules(char *pattern, char *rsp)
+void list_rules(char *pattern, FILE *rsp)
 {
-       char line[MAXLEN];
        for (rule_t *r = rule_head; r != NULL; r = r->next) {
                if (pattern != NULL && !streq(pattern, r->cause))
                        continue;
-               snprintf(line, sizeof(line), "%s => %s\n", r->cause, r->effect);
-               strncat(rsp, line, REMLEN(rsp));
+               fprintf(rsp, "%s => %s\n", r->cause, r->effect);
        }
 }