/*- * 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" /* find the lowest window above a certain level */ client_t *stacking_find_lowest(desktop_t *desktop, int layer) { int i; for (i = layer + 1; i < STACKLAYER_COUNT; i++) if (!TAILQ_EMPTY(&desktop->stacking_list[i])) return TAILQ_LAST(&desktop->stacking_list[i], stacklayer); return NULL; } /* raise below to just below above */ void stacking_raise_under(Window below, Window above) { Window windows[2]; windows[0] = above; windows[1] = below; XRestackWindows(display, windows, 2); } /* raise a client's frame window */ void stacking_raise(client_t *client) { desktop_t *desktop = client->workspace->desktop; client_t *lowest; /* see if it is already at the top of the layer */ if (!TAILQ_PREV(client, stacklayer, c_stacking)) return; /* put at the top of this layer */ TAILQ_REMOVE(&desktop->stacking_list[client->stacklayer], client, c_stacking); TAILQ_INSERT_HEAD(&desktop->stacking_list[client->stacklayer], client, c_stacking); /* now tell the server about it */ lowest = stacking_find_lowest(desktop, client->stacklayer); if (!lowest) XRaiseWindow(display, client->frame); else stacking_raise_under(client->frame, lowest->frame); /* tell plugins */ plugin_raise_notify(client, lowest); } /* lower a client's frame window */ void stacking_lower(client_t *client) { desktop_t *desktop = client->workspace->desktop; client_t *lowest; /* see if it is already the lowest */ if (!TAILQ_NEXT(client, c_stacking)) return; /* move this client to just below the lowest */ TAILQ_REMOVE(&desktop->stacking_list[client->stacklayer], client, c_stacking); TAILQ_INSERT_TAIL(&desktop->stacking_list[client->stacklayer], client, c_stacking); lowest = TAILQ_PREV(client, stacklayer, c_stacking); /* tell the server */ stacking_raise_under(client->frame, lowest->frame); /* tell plugins */ plugin_lower_notify(client, lowest); } /* add to the top of it's stacking layer */ void stacking_list_add(client_t *client) { desktop_t *desktop = client->workspace->desktop; client_t *lowest; /* link it into the list */ TAILQ_INSERT_HEAD(&desktop->stacking_list[client->stacklayer], client, c_stacking); desktop->window_count++; /* tell the server */ lowest = stacking_find_lowest(desktop, client->stacklayer); if (!lowest) XRaiseWindow(display, client->frame); else stacking_raise_under(client->frame, lowest->frame); } /* unlink from the stacking list */ void stacking_list_rm(client_t *client) { desktop_t *desktop = client->workspace->desktop; TAILQ_REMOVE(&desktop->stacking_list[client->stacklayer], client, c_stacking); desktop->window_count--; } /* send the full stacking for a desktop to the server */ void stacking_flush(desktop_t *desktop) { Window *windows; client_t *client; int i, n; /* make sure there are some windows */ if (desktop->window_count == 0) return; /* get memory for the windows array */ windows = malloc(desktop->window_count * sizeof(Window)); if (!windows) { warnx("malloc failure in stacking_flush"); return; } /* fill in the array */ for (i = STACKLAYER_COUNT - 1, n = 0; i >= 0; i--) TAILQ_FOREACH(client, &desktop->stacking_list[i], c_stacking) windows[n++] = client->frame; /* make sure our count wasn't off */ assert(desktop->window_count == n); /* tell the server */ XRestackWindows(display, windows, n); free(windows); }