/**
* @file clientlist.c
* @author Joe Wingbermuehle
* @date 2007
*
* @brief Functions to manage lists of clients.
*
*/
#include "jwm.h"
#include "clientlist.h"
#include "client.h"
#include "main.h"
ClientNode *nodes[LAYER_COUNT];
ClientNode *nodeTail[LAYER_COUNT];
static Window *windowStack = NULL; /**< Image of the window stack. */
static int windowStackSize = 0; /**< Size of the image. */
static int windowStackCurrent = 0; /**< Current location in the image. */
/** Determine if a client is allowed focus. */
int ShouldFocus(const ClientNode *np) {
if(np->state.desktop != currentDesktop
&& !(np->state.status & STAT_STICKY)) {
return 0;
}
if(np->state.status & STAT_NOLIST) {
return 0;
}
if(!(np->state.status & STAT_MAPPED)) {
return 0;
}
if(np->owner != None) {
return 0;
}
return 1;
}
/** Start walking the window stack. */
void StartWindowStackWalk() {
/* Get an image of the window stack.
* Here we get the Window IDs rather than client pointers so
* clients can be added/removed without disrupting the stack walk.
*/
ClientNode *np;
int layer;
int count;
/* If we are already walking the stack, just return. */
if(windowStack != NULL) {
return;
}
/* First determine how much space to allocate for windows. */
count = 0;
for(layer = LAYER_TOP; layer >= LAYER_BOTTOM; layer--) {
for(np = nodes[layer]; np; np = np->next) {
if(ShouldFocus(np)) {
++count;
}
}
}
/* If there were no windows to walk, don't even start. */
if(count == 0) {
return;
}
/* Allocate space for the windows. */
windowStack = Allocate(sizeof(Window) * count);
/* Copy windows into the array. */
windowStackSize = 0;
for(layer = LAYER_TOP; layer >= LAYER_BOTTOM; layer--) {
for(np = nodes[layer]; np; np = np->next) {
if(ShouldFocus(np)) {
windowStack[windowStackSize++] = np->window;
}
}
}
Assert(windowStackSize == count);
windowStackCurrent = 0;
}
/** Move to the next window in the window stack. */
void WalkWindowStack() {
ClientNode *np;
int x;
if(windowStack != NULL) {
/* Loop until we either raise a window or go through them all. */
for(x = 0; x < windowStackSize; x++) {
/* Move to the next window (wrap if needed). */
windowStackCurrent = (windowStackCurrent + 1) % windowStackSize;
/* Look up the window. */
np = FindClientByWindow(windowStack[windowStackCurrent]);
/* Skip this window if it no longer exists or is currently in
* a state that doesn't allow focus.
*/
if(np == NULL || !ShouldFocus(np)) {
continue;
}
/* Raise and focus the window. */
RaiseClient(np);
FocusClient(np);
break;
}
}
}
/** Stop walking the window stack. */
void StopWindowStackWalk() {
/* All we have to do here is free the window stack array. */
if(windowStack != NULL) {
Release(windowStack);
windowStack = NULL;
windowStackSize = 0;
windowStackCurrent = 0;
}
}
/** Focus the next client in the stacking order. */
void FocusNextStacked(ClientNode *np) {
int x;
ClientNode *tp;
Assert(np);
for(tp = np->next; tp; tp = tp->next) {
if((tp->state.status & (STAT_MAPPED | STAT_SHADED))
&& !(tp->state.status & STAT_HIDDEN)) {
FocusClient(tp);
return;
}
}
for(x = np->state.layer - 1; x >= LAYER_BOTTOM; x--) {
for(tp = nodes[x]; tp; tp = tp->next) {
if((tp->state.status & (STAT_MAPPED | STAT_SHADED))
&& !(tp->state.status & STAT_HIDDEN)) {
FocusClient(tp);
return;
}
}
}
}
syntax highlighted by Code2HTML, v. 0.9.1