mirror of
https://github.com/vale981/bspwm
synced 2025-03-05 18:01:37 -05:00
191 lines
5.6 KiB
C
191 lines
5.6 KiB
C
/* * Copyright (c) 2012-2013 Bastien Dejean
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without modification,
|
|
* are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation and/or
|
|
* other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 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.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include "bspwm.h"
|
|
#include "window.h"
|
|
#include "history.h"
|
|
#include "tree.h"
|
|
#include "tag.h"
|
|
|
|
tag_t *make_tag(char *name, int idx)
|
|
{
|
|
tag_t *tag = malloc(sizeof(tag_t));
|
|
if (tag != NULL) {
|
|
snprintf(tag->name, sizeof(tag->name), "%s", name);
|
|
tag->mask = 1 << idx;
|
|
}
|
|
return tag;
|
|
}
|
|
|
|
bool add_tag(char *name)
|
|
{
|
|
if (num_tags >= MAXTAGS)
|
|
return false;
|
|
tag_t *tag = make_tag(name, num_tags);
|
|
if (tag == NULL)
|
|
return false;
|
|
tags[num_tags] = tag;
|
|
num_tags++;
|
|
return true;
|
|
}
|
|
|
|
bool remove_tag(char *name)
|
|
{
|
|
for (int i = 0; i < num_tags; i++)
|
|
if (streq(tags[i]->name, name))
|
|
return remove_tag_by_index(i);
|
|
return false;
|
|
}
|
|
|
|
bool remove_tag_by_index(int i)
|
|
{
|
|
if (i >= num_tags)
|
|
return false;
|
|
for (monitor_t *m = mon_head; m != NULL; m = m->next)
|
|
for (desktop_t *d = m->desk_head; d != NULL; d = d->next) {
|
|
tag_desktop(m, d, d->tags_field & ~tags[i]->mask);
|
|
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root))
|
|
tag_node(m, d, n, d, n->client->tags_field & ~tags[i]->mask);
|
|
}
|
|
free(tags[i]);
|
|
for (int j = i; j < (num_tags - 1); j++)
|
|
tags[j] = tags[j + 1];
|
|
tags[num_tags - 1] = NULL;
|
|
num_tags--;
|
|
return true;
|
|
}
|
|
|
|
tag_t *get_tag(char *name)
|
|
{
|
|
for (int i = 0; i < num_tags; i++)
|
|
if (streq(tags[i]->name, name))
|
|
return tags[i];
|
|
return NULL;
|
|
}
|
|
|
|
tag_t *get_tag_by_index(int i)
|
|
{
|
|
if (i >= num_tags)
|
|
return NULL;
|
|
return tags[i];
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
void set_presence(monitor_t *m, desktop_t *d, node_t *n, bool present)
|
|
{
|
|
if (is_visible(d, n) != present) {
|
|
if (present)
|
|
tag_node(m, d, n, d, n->client->tags_field | d->tags_field);
|
|
else
|
|
tag_node(m, d, n, d, n->client->tags_field & ~d->tags_field);
|
|
}
|
|
}
|
|
|
|
void tag_node(monitor_t *m, desktop_t *d, node_t *n, desktop_t *ds, unsigned int tags_field)
|
|
{
|
|
if (num_tags < 1)
|
|
return;
|
|
bool visible = is_visible(ds, n);
|
|
n->client->tags_field = tags_field;
|
|
if ((visible && (tags_field & d->tags_field) == 0)
|
|
|| (!visible && (tags_field & d->tags_field) != 0)) {
|
|
set_visibility(m, d, n, !visible);
|
|
arrange(m, d);
|
|
}
|
|
}
|
|
|
|
void tag_desktop(monitor_t *m, desktop_t *d, unsigned int tags_field)
|
|
{
|
|
if (num_tags < 1)
|
|
return;
|
|
bool dirty = false;
|
|
unsigned int old_tags_field = d->tags_field;
|
|
d->tags_field = tags_field;
|
|
for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n, d->root)) {
|
|
bool old_visible = (old_tags_field & n->client->tags_field) != 0;
|
|
bool visible = (tags_field & n->client->tags_field) != 0;
|
|
if (old_visible != visible) {
|
|
set_visibility(m, d, n, visible);
|
|
dirty = true;
|
|
}
|
|
}
|
|
if (dirty)
|
|
arrange(m, d);
|
|
if (d == mon->desk)
|
|
put_status();
|
|
}
|
|
|
|
void list_tags(char *rsp)
|
|
{
|
|
char line[MAXLEN];
|
|
for (int i = 0; i < num_tags; i++) {
|
|
snprintf(line, sizeof(line), "%s %u\n", tags[i]->name, tags[i]->mask);
|
|
strncat(rsp, line, REMLEN(rsp));
|
|
}
|
|
}
|
|
|
|
void init_tags(void)
|
|
{
|
|
num_tags = 0;
|
|
for (int i = 0; i < MAXTAGS; i++)
|
|
tags[i] = NULL;
|
|
add_tag(DEFAULT_TAG_NAME);
|
|
}
|