/*- * 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 "plugutil.h" /* default flags and the like for a WM_CLASS */ typedef struct wcdefs { char *res_name; /* resource name */ char *res_class; /* pointer into res_name, don't free() it */ /* dgroup to use, or null */ dgroup_t *dgroup; /* stacking layer to put the client in */ int stacklayer; /* these correspond to clientflags_t, read client.h */ int nofocus; int noresize; int nomove; int noiconify; int nodelete; int sticky; SLIST_ENTRY(wcdefs) w_list; } wcdefs_t; /* list of wcdefs */ static SLIST_HEAD(, wcdefs) wcdefs_list = SLIST_HEAD_INITIALIZER(wcdefs_list); /* find a wcdefs based on a res_name and res_class */ static wcdefs_t *wcdefs_find(char *res_name, char *res_class) { wcdefs_t *wcdefs; /* make sure it has res_name and res_class */ if (!res_name || !res_class) return NULL; /* loop through and cmp the strings */ SLIST_FOREACH(wcdefs, &wcdefs_list, w_list) if (strcmp(wcdefs->res_class, res_class) == 0) if (strcmp(wcdefs->res_name, res_name) == 0) goto found; return NULL; found: return wcdefs; } /* handle default setting on newly arriving clients */ static int init_hints(int pcall, client_t *client) { wcdefs_t *wcdefs; /* find an appropriate wcdefs */ wcdefs = wcdefs_find(client->classhint.res_name, client->classhint.res_class); if (!wcdefs) return PLUGIN_OK; /* * set flags to our wcdefs flags. don't touch flags that the user didn't * say anything about in their rc. */ if (wcdefs->nofocus != -1) client->flags.nofocus = wcdefs->nofocus; if (wcdefs->noresize != -1) client->flags.noresize = wcdefs->noresize; if (wcdefs->nomove != -1) client->flags.nomove = wcdefs->nomove; if (wcdefs->noiconify != -1) client->flags.noiconify = wcdefs->noiconify; if (wcdefs->nodelete != -1) client->flags.nodelete = wcdefs->nodelete; if (wcdefs->sticky != -1) client->flags.sticky = wcdefs->sticky; /* set dgroup if we got one specified */ if (wcdefs->dgroup) client->dgroup = wcdefs->dgroup; /* set stacking layer if it was specified */ if (wcdefs->stacklayer != -1) client->stacklayer = wcdefs->stacklayer; return PLUGIN_OK; } /* build our defaults information structures */ int init() { wcdefs_t *wcdefs; param_t *param; char *res_name, *res_class; int i; /* get all the wcdefs_t's built */ SUBPARAMS_FOREACH(i, param, &plugin_this->params) { if (strcmp(param->name, "def") != 0) continue; /* get the res_name.res_class pair from the value */ res_name = strdup(param->value); if (!res_name) PERR("no memory to strdup res_name.res_class"); res_class = strrchr(res_name, '.'); if (*res_class != '\0') *res_class++ = '\0'; /* see if a entry exists, or make one */ wcdefs = wcdefs_find(res_name, res_class); if (!wcdefs) { wcdefs = malloc(sizeof(wcdefs_t)); if (!wcdefs) { free(res_name); PERR("no memory for wcdefs"); } /* init the structure */ wcdefs->res_name = res_name; wcdefs->res_class = res_class; wcdefs->dgroup = NULL; wcdefs->stacklayer = -1; wcdefs->nofocus = -1; wcdefs->noresize = -1; wcdefs->nomove = -1; wcdefs->noiconify = -1; wcdefs->nodelete = -1; wcdefs->sticky = -1; SLIST_INSERT_HEAD(&wcdefs_list, wcdefs, w_list); } else free(res_name); /* now read for anything they set */ OPTIONAL_PARAM(¶m->subparams, "nofocus", bool, wcdefs->nofocus, wcdefs->nofocus); OPTIONAL_PARAM(¶m->subparams, "noresize", bool, wcdefs->noresize, wcdefs->noresize); OPTIONAL_PARAM(¶m->subparams, "nomove", bool, wcdefs->nomove, wcdefs->nomove); OPTIONAL_PARAM(¶m->subparams, "noiconify", bool, wcdefs->noiconify, wcdefs->noiconify); OPTIONAL_PARAM(¶m->subparams, "nodelete", bool, wcdefs->nodelete, wcdefs->nodelete); OPTIONAL_PARAM(¶m->subparams, "sticky", bool, wcdefs->sticky, wcdefs->sticky); OPTIONAL_PARAM(¶m->subparams, "dgroup", dgroup, wcdefs->dgroup, wcdefs->dgroup); OPTIONAL_PARAM(¶m->subparams, "stacklayer", stacklayer, wcdefs->stacklayer, wcdefs->stacklayer); } return PLUGIN_OK; } /* register our callback */ int start() { plugin_callback_add(plugin_this, PCALL_INIT_HINTS, init_hints); return PLUGIN_OK; } /* free our wcdefs */ void shutdown() { wcdefs_t *wcdefs, *next; wcdefs = SLIST_FIRST(&wcdefs_list); while (wcdefs) { /* don't free res_class, it's just a ptr into res_name */ free(wcdefs->res_name); next = SLIST_NEXT(wcdefs, w_list); free(wcdefs); wcdefs = next; } }