예제 #1
0
파일: tree.c 프로젝트: ThomasAdam/bspwm
void swap_nodes(node_t *n1, node_t *n2)
{
    if (n1 == NULL || n2 == NULL || n1 == n2)
        return;

    PUTS("swap nodes");

    /* (n1 and n2 are leaves) */
    node_t *pn1 = n1->parent;
    node_t *pn2 = n2->parent;
    bool n1_first_child = is_first_child(n1);
    bool n2_first_child = is_first_child(n2);

    if (pn1 != NULL) {
        if (n1_first_child)
            pn1->first_child = n2;
        else
            pn1->second_child = n2;
    }

    if (pn2 != NULL) {
        if (n2_first_child)
            pn2->first_child = n1;
        else
            pn2->second_child = n1;
    }

    n1->parent = pn2;
    n2->parent = pn1;

    if (n1->vacant != n2->vacant) {
        update_vacant_state(n1->parent);
        update_vacant_state(n2->parent);
    }
}
예제 #2
0
파일: tag.c 프로젝트: mztriz/bspwm
void set_visibility(monitor_t *m, desktop_t *d, node_t *n, bool visible)
{
    PRINTF("set visibilty %X: %s\n", n->client->window, BOOLSTR(visible));

    if (!n->client->floating) {
        n->vacant = !visible;
        update_vacant_state(n->parent);
        if (visible)
            rotate_brother(n);
        else
            unrotate_brother(n);
    }
    if (visible) {
        if (m->desk == d)
            window_show(n->client->window);
        if (d->focus == NULL) {
            if (mon->desk == d)
                focus_node(m, d, n);
            else
                pseudo_focus(d, n);
        }
    } else {
        if (m->desk == d || n->client->sticky)
            window_hide(n->client->window);
        if (d->focus == n) {
            node_t *f = history_get_node(d, n);
            if (f == NULL)
                f = closest_visible(d, n);
            if (mon->desk == d)
                focus_node(m, d, f);
            else
                pseudo_focus(d, f);
        }
    }
}
예제 #3
0
파일: tree.c 프로젝트: ThomasAdam/bspwm
void unlink_node(desktop_t *d, node_t *n)
{
    if (d == NULL || n == NULL)
        return;

    PRINTF("unlink node %X\n", n->client->window);

    node_t *p = n->parent;

    if (p == NULL) {
        d->root = NULL;
        d->focus = NULL;
        d->last_focus = NULL;
    } else {
        node_t *b;
        node_t *g = p->parent;
        bool n_first_child = is_first_child(n);
        if (n_first_child) {
            b = p->second_child;
            if (n->client->born_as == MODE_AUTOMATIC)
                rotate_tree(b, ROTATE_COUNTER_CLOCKWISE);
        } else {
            b = p->first_child;
            if (n->client->born_as == MODE_AUTOMATIC)
                rotate_tree(b, ROTATE_CLOCKWISE);
        }
        b->parent = g;
        if (g != NULL) {
            if (is_first_child(p))
                g->first_child = b;
            else
                g->second_child = b;
        } else {
            d->root = b;
        }

        n->parent = NULL;
        free(p);

        if (n == d->last_focus) {
            d->last_focus = NULL;
        } else if (n == d->focus) {
            if (d->last_focus != NULL)
                d->focus = d->last_focus;
            else
                d->focus = (n_first_child ? first_extrema(b) : second_extrema(b));
            d->last_focus = NULL;
        }

        update_vacant_state(b->parent);
    }
}
예제 #4
0
파일: tree.c 프로젝트: ThomasAdam/bspwm
void restore(char *file_path)
{
    if (file_path == NULL)
        return;

    FILE *snapshot = fopen(file_path, "r");
    if (snapshot == NULL) {
        warn("restore: can't open file\n");
        return;
    }

    char line[MAXLEN];
    monitor_t *m = NULL;
    desktop_t *d = NULL;
    node_t *n = NULL;
    num_clients = 0;
    unsigned int level, last_level = 0, max_uid = 0;
    bool aborted = false;

    while (!aborted && fgets(line, sizeof(line), snapshot) != NULL) {
        unsigned int len = strlen(line);
        level = 0;
        while (level < strlen(line) && isspace(line[level]))
            level++;
        if (level == 0) {
            if (m == NULL)
                m = mon_head;
            else
                m = m->next;
            if (len >= 2)
                switch (line[len - 2]) {
                    case '#':
                        mon = m;
                        break;
                    case '~':
                        last_mon = m;
                        break;
                }
        } else if (level == 2) {
            if (d == NULL)
                d = m->desk_head;
            else
                d = d->next;
            int i = len - 1;
            while (i > 0 && !isupper(line[i]))
                i--;
            if (line[i] == 'M')
                d->layout = LAYOUT_MONOCLE;
            else if (line[i] == 'T')
                d->layout = LAYOUT_TILED;
            if (len >= 2)
                switch (line[len - 2]) {
                    case '@':
                        m->desk = d;
                        break;
                    case '~':
                        m->last_desk = d;
                        break;
                }
        } else {
            node_t *birth = make_node();
            if (level == 4) {
                empty_desktop(d);
                d->root = birth;
            } else {
                if (level > last_level) {
                    n->first_child = birth;
                } else {
                    do {
                        n = n->parent;
                    } while (n != NULL && n->second_child != NULL);
                    if (n == NULL) {
                        warn("restore: file is malformed\n");
                        aborted = true;
                    }
                    n->second_child = birth;
                }
                birth->parent = n;
            }
            n = birth;

            if (isupper(line[level])) {
                char st;
                sscanf(line + level, "%c %lf", &st, &n->split_ratio);
                if (st == 'H')
                    n->split_type = TYPE_HORIZONTAL;
                else if (st == 'V')
                    n->split_type = TYPE_VERTICAL;
            } else {
                client_t *c = make_client(XCB_NONE);
                num_clients++;
                char ba, floating, transient, fullscreen, urgent, locked;
                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c%c%c%c%c", &ba, c->class_name, &c->window, &c->uid, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &floating, &transient, &fullscreen, &urgent, &locked);
                if (ba == 'a')
                    c->born_as = MODE_AUTOMATIC;
                else if (ba == 'm')
                    c->born_as = MODE_MANUAL;
                c->floating = (floating == '-' ? false : true);
                c->transient = (transient == '-' ? false : true);
                c->fullscreen = (fullscreen == '-' ? false : true);
                c->urgent = (urgent == '-' ? false : true);
                c->locked = (locked == '-' ? false : true);
                if (c->uid > max_uid)
                    max_uid = c->uid;
                n->client = c;
                if (len >= 2)
                    switch (line[len - 2]) {
                        case '*':
                            d->focus = n;
                            break;
                        case '~':
                            d->last_focus = n;
                            break;
                    }
            }
        }
        last_level = level;
    }

    if (!aborted) {
        client_uid = max_uid + 1;
        for (monitor_t *m = mon_head; m != NULL; m = m->next)
            for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
                for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n)) {
                    uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
                    xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
                    if (n->client->floating) {
                        n->vacant = true;
                        update_vacant_state(n->parent);
                    }
                }
    }

    fclose(snapshot);
}
예제 #5
0
파일: tree.c 프로젝트: ThomasAdam/bspwm
void insert_node(monitor_t *m, desktop_t *d, node_t *n)
{
    if (d == NULL || n == NULL)
        return;

    PRINTF("insert node %X\n", n->client->window);

    node_t *focus = d->focus;

    if (focus == NULL) {
        d->root = n;
    } else {
        node_t *dad = make_node();
        node_t *fopar = focus->parent;
        n->parent = dad;
        n->client->born_as = split_mode;
        switch (split_mode) {
            case MODE_AUTOMATIC:
                if (fopar == NULL) {
                    dad->first_child = n;
                    dad->second_child = focus;
                    if (m->rectangle.width > m->rectangle.height)
                        dad->split_type = TYPE_VERTICAL;
                    else
                        dad->split_type = TYPE_HORIZONTAL;
                    focus->parent = dad;
                    d->root = dad;
                } else {
                    node_t *grandpa = fopar->parent;
                    dad->parent = grandpa;
                    if (grandpa != NULL) {
                        if (is_first_child(fopar))
                            grandpa->first_child = dad;
                        else
                            grandpa->second_child = dad;
                    } else {
                        d->root = dad;
                    }
                    dad->split_type = fopar->split_type;
                    dad->split_ratio = fopar->split_ratio;
                    fopar->parent = dad;
                    if (is_first_child(focus)) {
                        dad->first_child = n;
                        dad->second_child = fopar;
                        rotate_tree(fopar, ROTATE_CLOCKWISE);
                    } else {
                        dad->first_child = fopar;
                        dad->second_child = n;
                        rotate_tree(fopar, ROTATE_COUNTER_CLOCKWISE);
                    }
                }
                break;
            case MODE_MANUAL:
                if (fopar != NULL) {
                    if (is_first_child(focus))
                        fopar->first_child = dad;
                    else
                        fopar->second_child = dad;
                }
                dad->split_ratio = focus->split_ratio;
                dad->parent = fopar;
                focus->parent = dad;
                switch (split_dir) {
                    case DIR_LEFT:
                        dad->split_type = TYPE_VERTICAL;
                        dad->first_child = n;
                        dad->second_child = focus;
                        break;
                    case DIR_RIGHT:
                        dad->split_type = TYPE_VERTICAL;
                        dad->first_child = focus;
                        dad->second_child = n;
                        break;
                    case DIR_UP:
                        dad->split_type = TYPE_HORIZONTAL;
                        dad->first_child = n;
                        dad->second_child = focus;
                        break;
                    case DIR_DOWN:
                        dad->split_type = TYPE_HORIZONTAL;
                        dad->first_child = focus;
                        dad->second_child = n;
                        break;
                }
                if (d->root == focus)
                    d->root = dad;
                split_mode = MODE_AUTOMATIC;
                break;
        }
        if (focus->vacant)
            update_vacant_state(fopar);
    }
}
예제 #6
0
파일: restore.c 프로젝트: neynt/bspwm
void restore_tree(char *file_path)
{
    if (file_path == NULL)
        return;

    FILE *snapshot = fopen(file_path, "r");
    if (snapshot == NULL) {
        warn("Restore tree: can't open file\n");
        return;
    }

    PUTS("restore tree");

    char line[MAXLEN];
    char name[MAXLEN];
    coordinates_t loc;
    monitor_t *m = NULL;
    desktop_t *d = NULL;
    node_t *n = NULL;
    num_clients = 0;
    unsigned int level, last_level = 0;

    while (fgets(line, sizeof(line), snapshot) != NULL) {
        unsigned int len = strlen(line);
        level = 0;

        while (level < len && isspace(line[level]))
            level++;

        if (level == 0) {
            int x, y, left, right, top, bottom;
            unsigned int w, h;
            char end = 0;
            name[0] = '\0';
            sscanf(line + level, "%s %ux%u%i%i %i,%i,%i,%i %c", name, &w, &h, &x, &y, &top, &right, &bottom, &left, &end);
            m = find_monitor(name);
            if (m == NULL)
                continue;
            m->rectangle = (xcb_rectangle_t) {x, y, w, h};
            m->top_padding = top;
            m->right_padding = right;
            m->bottom_padding = bottom;
            m->left_padding = left;
            if (end == '#')
                mon = m;
            else if (end == '~')
                last_mon = m;

        } else if (level == 2) {
            if (m == NULL)
                continue;
            int wg;
            char layout = 0, end = 0;
            name[0] = '\0';
            loc.desktop = NULL;
            sscanf(line + level, "%s %i %c %c", name, &wg, &layout, &end);
            locate_desktop(name, &loc);
            d = loc.desktop;
            if (d == NULL)
                continue;
            d->window_gap = wg;
            if (layout == 'M')
                d->layout = LAYOUT_MONOCLE;
            else if (layout == 'T')
                d->layout = LAYOUT_TILED;
            if (end == '@')
                m->desk = d;
            else if (end == '~')
                m->last_desk = d;

        } else {
            if (m == NULL || d == NULL)
                continue;
            node_t *birth = make_node();
            if (level == 4) {
                empty_desktop(d);
                d->root = birth;
            } else if (n != NULL) {
                if (level > last_level) {
                    n->first_child = birth;
                } else {
                    do {
                        n = n->parent;
                    } while (n != NULL && n->second_child != NULL);
                    if (n == NULL)
                        continue;
                    n->second_child = birth;
                }
                birth->parent = n;
            }
            n = birth;

            char br;
            if (isupper(line[level])) {
                char st;
                sscanf(line + level, "%c %c %lf", &st, &br, &n->split_ratio);
                if (st == 'H')
                    n->split_type = TYPE_HORIZONTAL;
                else if (st == 'V')
                    n->split_type = TYPE_VERTICAL;
            } else {
                client_t *c = make_client(XCB_NONE);
                num_clients++;
                char floating, transient, fullscreen, urgent, locked, sd, sm, end = 0;
                sscanf(line + level, "%c %s %X %u %hux%hu%hi%hi %c %c%c%c%c%c%c %c", &br, c->class_name, &c->window, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &sd, &floating, &transient, &fullscreen, &urgent, &locked, &sm, &end);
                c->floating = (floating == '-' ? false : true);
                c->transient = (transient == '-' ? false : true);
                c->fullscreen = (fullscreen == '-' ? false : true);
                c->urgent = (urgent == '-' ? false : true);
                c->locked = (locked == '-' ? false : true);
                n->split_mode = (sm == '-' ? MODE_AUTOMATIC : MODE_MANUAL);
                if (sd == 'U')
                    n->split_dir = DIR_UP;
                else if (sd == 'R')
                    n->split_dir = DIR_RIGHT;
                else if (sd == 'D')
                    n->split_dir = DIR_DOWN;
                else if (sd == 'L')
                    n->split_dir = DIR_LEFT;
                n->client = c;
                if (end == '*')
                    d->focus = n;
            }
            if (br == 'a')
                n->birth_rotation = 90;
            else if (br == 'c')
                n->birth_rotation = 270;
            else if (br == 'm')
                n->birth_rotation = 0;
        }
        last_level = level;
    }

    fclose(snapshot);

    for (monitor_t *m = mon_head; m != NULL; m = m->next)
        for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
            for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
                uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
                xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
                if (n->client->floating) {
                    n->vacant = true;
                    update_vacant_state(n->parent);
                }
            }
    ewmh_update_current_desktop();
}