/*-
* Copyright (c) 2001 Jordan DeLong
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the author nor the names of contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 "wm.h"
/* default dgroup, in case a dgroup isn't made in the rcfile */
dgroup_t dgroup_empty = { "EMPTY" /* compiler 0s the rest */ };
/* the list of decoration groups */
static SLIST_HEAD(, dgroup) dgroup_list = { &dgroup_empty };
/* free all dgroup allocated memory */
void dgroup_shutdown() {
dgroup_t *dgroup, *next;
/*
* free the entire list of dgroup_t's; decor_t's are
* freed elsewhere (decor_shutdown). we loop till we
* get to dgroup_empty, which is statically allocated
* and doesn't need to be freed. dgroup_empty is always
* on the very end of dgroup_list.
*/
dgroup = SLIST_FIRST(&dgroup_list);
while (dgroup != &dgroup_empty) {
free(dgroup->ident);
free(dgroup->decor);
next = SLIST_NEXT(dgroup, dg_list);
free(dgroup);
dgroup = next;
}
}
/* add a decoration group */
dgroup_t *dgroup_add(char *ident) {
dgroup_t *dgroup;
dgroup = calloc(1, sizeof(dgroup_t));
if (!dgroup)
return NULL;
dgroup->ident = ident;
SLIST_INSERT_HEAD(&dgroup_list, dgroup, dg_list);
return dgroup;
}
/* find a dgroup by identifier; used in the rcfile parser */
dgroup_t *dgroup_ident(char *ident) {
dgroup_t *dgroup;
SLIST_FOREACH(dgroup, &dgroup_list, dg_list)
if (strcmp(dgroup->ident, ident) == 0)
return dgroup;
return NULL;
}
/* add a decoration unit to a dgroup */
int dgroup_add_decor(dgroup_t *dgroup, decor_t *decor) {
decor_t **tmp;
dgroup->decor_count++;
tmp = realloc(dgroup->decor, dgroup->decor_count * sizeof(decor_t *));
if (!tmp)
return -1;
dgroup->decor = tmp;
dgroup->decor[dgroup->decor_count - 1] = decor;
return 0;
}
/* learn spacing information for all our decoration groups */
void dgroup_learn_space() {
dgroup_t *dgroup;
int i;
SLIST_FOREACH(dgroup, &dgroup_list, dg_list)
for (i = 0; i < dgroup->decor_count; i++) {
if (dgroup->decor[i]->edge == DE_TOP) {
if (dgroup->top_space < dgroup->decor[i]->pixmap->height)
dgroup->top_space = dgroup->decor[i]->pixmap->height;
} else if (dgroup->decor[i]->edge == DE_LEFT) {
if (dgroup->left_space < dgroup->decor[i]->pixmap->width)
dgroup->left_space = dgroup->decor[i]->pixmap->width;
} else if (dgroup->decor[i]->edge == DE_RIGHT) {
if (dgroup->right_space < dgroup->decor[i]->pixmap->width)
dgroup->right_space = dgroup->decor[i]->pixmap->width;
} else if (dgroup->decor[i]->edge == DE_BOTTOM) {
if (dgroup->bottom_space < dgroup->decor[i]->pixmap->height)
dgroup->bottom_space = dgroup->decor[i]->pixmap->height;
}
}
}
/* switch the dgroup used by a client */
void dgroup_switch(client_t *client, dgroup_t *dgroup) {
XRectangle rect;
decor_undecor(client);
if (!dgroup) {
if (SLIST_NEXT(client->dgroup, dg_list))
client->dgroup = SLIST_NEXT(client->dgroup, dg_list);
else
client->dgroup = SLIST_FIRST(&dgroup_list);
} else
client->dgroup = dgroup;
/*
* the meat of client_sizeframe, we don't actually call it to aviod having
* to unneccesarily reshape the window's decor twice.
*/
XMoveResizeWindow(display, client->frame, client->x, client->y,
client->width + client->dgroup->left_space
+ client->dgroup->right_space,
client->height + client->dgroup->top_space
+ client->dgroup->bottom_space);
XMoveWindow(display, client->window, client->dgroup->left_space,
client->dgroup->top_space);
/* fill in any old shaping */
rect.x = 0;
rect.y = 0;
rect.width = client->width + client->dgroup->left_space
+ client->dgroup->right_space;
rect.height = client->height + client->dgroup->top_space
+ client->dgroup->bottom_space;
XShapeCombineRectangles(display, client->frame, ShapeBounding,
0, 0, &rect, 1, ShapeSet, Unsorted);
/* make the new decoration */
decor_decorate(client);
if (client->flags.shaped)
client_shape(client);
/* if the decor should be focused...focus it */
if (client_focused == client)
decor_focus(client);
}
syntax highlighted by Code2HTML, v. 0.9.1