/*- * 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); }