/* * This file is part of firk's window manager for x11 (fwm) * Copyright (C) 2016-2021 firk * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #include #include "main.h" #include "base.h" #include "config.h" #include "winlist.h" #define HT_SIZE (MAX_TOTAL_WINDOWS/3+1) static WInfo wlist[MAX_TOTAL_WINDOWS]; static int numwlist = 0; static WInfo *freelist; static WInfo *ht[HT_SIZE]; extern WInfo * WInfo_new(Window window) { WInfo * wi; unsigned int h; h = ((unsigned long)window) % HT_SIZE; for(wi=ht[h]; wi; wi=wi->wdb.next) assert(wi->window!=window); if(wi = freelist) freelist = wi->wdb.next; else if(numwlistwdb.self); bzero(wi, sizeof(*wi)); wi->wdb.self = wi; wi->window = window; wi->wdb.next = ht[h]; ht[h] = wi; return wi; } extern WInfo * WInfo_search(Window window) { WInfo * wi; unsigned int h; h = ((unsigned long)window) % HT_SIZE; for(wi=ht[h]; wi; wi=wi->wdb.next) { assert(wi->wdb.self==wi); if(wi->window==window) return wi; } return NULL; } extern void WInfo_delete(WInfo * wi) { WInfo **pwi, *cwi; unsigned int h; assert(wi); assert(wi->wdb.self==wi); assert(!wi->wdb.list); h = ((unsigned long)wi->window) % HT_SIZE; for(pwi=ht+h; cwi=*pwi; pwi=&cwi->wdb.next) if(cwi==wi) { *pwi = wi->wdb.next; bzero(wi, sizeof(*wi)); wi->wdb.next = freelist; freelist = wi; return; } assert(!"deleting wi not in list"); } static void wl_remove_wi(WList * wl, WInfo * wi) { WInfo *tb, *tt; assert(wl->bottom && wl->top); tb = wi->wdb.to_bottom; tt = wi->wdb.to_top; if(tb) { assert(wl->bottom!=wi); assert(tb->wdb.to_top==wi); tb->wdb.to_top = tt; } else { assert(wl->bottom==wi); wl->bottom = tt; } if(tt) { assert(wl->top!=wi); assert(tt->wdb.to_bottom==wi); tt->wdb.to_bottom = tb; } else { assert(wl->top==wi); wl->top = tb; } wi->wdb.to_bottom = wi->wdb.to_top = NULL; wi->wdb.list = NULL; } extern void WList_raise_window(WList * wl, WInfo * wi) { WInfo * cwi; assert(wi); assert(wi->wdb.self==wi); if(wi->wdb.list) { assert(wi->wdb.list==wl); if(wl->top==wi) return; wl_remove_wi(wl, wi); } assert(!wi->wdb.to_top && !wi->wdb.to_bottom); if(wi->wdb.to_bottom = cwi = wl->top) { assert(wl->bottom); assert(!cwi->wdb.to_top); cwi->wdb.to_top = wi; } else { assert(!wl->bottom); wl->bottom = wi; } wl->top = wi; wi->wdb.list = wl; } extern void WList_remove_window(WList * wl, WInfo * wi) { assert(wi); assert(wi->wdb.self==wi); assert(wi->wdb.list==wl); wl_remove_wi(wl, wi); } extern void WList_activate(WList * wl, Window top, Window bottom) { /* TODO: this function does not update focus_num and other taskbar.c vars; this function does not send TAKE_FOCUS event tonew focused window; also this function is not used currently; TODO: reorganize code */ WInfo * wi; Window order[MAX_TOTAL_WINDOWS+2]; int n; order[0] = top; for(n=1, wi=wl->top; wi; n++, wi=wi->wdb.to_bottom) { assert(n<=MAX_TOTAL_WINDOWS); order[n] = wi->window; } assert(n<=MAX_TOTAL_WINDOWS+1); order[n++] = bottom; XRestackWindows(display, order, n); }