1/* 2 * Functions related to the window ring. 3 * 4 * Invariants: 5 * - If a window is not on the ring, its TwmWindow::ring.next and .prev 6 * are both NULL. 7 * - If a window is on the ring, they are both not NULL and point to a 8 * window which is also on the ring. 9 * - Corollary: if a window is the only one on the ring, .next and .prev 10 * point to itself. 11 * - Functions which act on the "current" ring window, i.e. the window 12 * that has most recently been entered and is on the ring, use 13 * Scr->RingLeader. 14 * - If RingLeader is NULL, fall back to Scr->Ring. 15 * - If Ring is NULL, the ring is empty (and RingLeader is also NULL). 16 */ 17 18#include "ctwm.h" 19 20#include <assert.h> 21 22#include "screen.h" 23#include "win_ring.h" 24 25void 26UnlinkWindowFromRing(TwmWindow *win) 27{ 28 TwmWindow *prev = win->ring.prev; 29 TwmWindow *next = win->ring.next; 30 31 // We call this unconditionally at various window deletion times, and 32 // if it's not on the ring, there's nothing to do. e.g., if we don't 33 // have any WindowRing config enabled... 34 if(!WindowIsOnRing(win)) { 35 return; 36 } 37 38 // But if it is, prev/next should always exist. 39 assert(prev != NULL); 40 assert(next != NULL); 41 42 /* 43 * 1. Unlink window 44 * 2. If window was only thing in ring, null out ring 45 * 3. If window was ring leader, set to next (or null) 46 * 47 * If the window is the only one in the ring, prev == next == win, 48 * so the unlinking effectively is a NOP, but that doesn't matter. 49 */ 50 prev->ring.next = next; 51 next->ring.prev = prev; 52 53 win->ring.next = win->ring.prev = NULL; 54 55 if(Scr->Ring == win) { 56 Scr->Ring = (next != win ? next : NULL); 57 } 58 59 if(!Scr->Ring || Scr->RingLeader == win) { 60 Scr->RingLeader = Scr->Ring; 61 } 62} 63 64static void 65AddWindowToRingUnchecked(TwmWindow *win, TwmWindow *after) 66{ 67 TwmWindow *before = after->ring.next; 68 69 win->ring.next = before; 70 win->ring.prev = after; 71 72 after->ring.next = win; 73 before->ring.prev = win; 74} 75 76void 77AddWindowToRing(TwmWindow *win) 78{ 79 assert(win->ring.next == NULL); 80 assert(win->ring.prev == NULL); 81 82 if(Scr->Ring) { 83 AddWindowToRingUnchecked(win, Scr->Ring); 84 } 85 else { 86 win->ring.next = win->ring.prev = Scr->Ring = win; 87 } 88} 89