313 lines
5.7 KiB
C
Executable file
313 lines
5.7 KiB
C
Executable file
/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <X11/X.h>
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include "dat.h"
|
|
#include "fns.h"
|
|
#include "config.h"
|
|
|
|
Client *clients;
|
|
Client *current;
|
|
|
|
void
|
|
setactive(Client *c, int on)
|
|
{
|
|
/* dbg("setactive client %x %d", c->window, c->on); */
|
|
|
|
if(c->parent == c->screen->root)
|
|
return;
|
|
|
|
if(on){
|
|
XUngrabButton(dpy, AnyButton, AnyModifier, c->parent);
|
|
XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp());
|
|
if(c->proto & Ptakefocus)
|
|
sendcmessage(c->window, wm_protocols, wm_take_focus, 0, 1);
|
|
cmapfocus(c);
|
|
}else{
|
|
if(c->proto & Plosefocus)
|
|
sendcmessage(c->window, wm_protocols, wm_lose_focus, 0, 1);
|
|
XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False,
|
|
ButtonMask, GrabModeAsync, GrabModeSync, None, None);
|
|
}
|
|
draw_border(c, on);
|
|
}
|
|
|
|
void
|
|
draw_border(Client *c, int active)
|
|
{
|
|
unsigned long pixel;
|
|
|
|
if(active){
|
|
if(c->hold)
|
|
pixel = c->screen->activeholdborder;
|
|
else
|
|
pixel = c->screen->activeborder;
|
|
}else{
|
|
if(c->hold)
|
|
pixel = c->screen->inactiveholdborder;
|
|
else
|
|
pixel = c->screen->inactiveborder;
|
|
}
|
|
|
|
if(debug) fprintf(stderr, "draw_border %p pixel %ld active %d hold %d\n", (void*)c, pixel, active, c->hold);
|
|
XSetWindowBackground(dpy, c->parent, pixel);
|
|
XClearWindow(dpy, c->parent);
|
|
}
|
|
|
|
void
|
|
active(Client *c)
|
|
{
|
|
Client *cc;
|
|
|
|
|
|
if(c == 0){
|
|
fprintf(stderr, "ryudo: active(c==0)\n");
|
|
return;
|
|
}
|
|
if(c == current)
|
|
return;
|
|
#ifdef AUTOSTICK
|
|
if (isautostick(c))
|
|
return;
|
|
#endif
|
|
if(current){
|
|
setactive(current, 0);
|
|
if(current->screen != c->screen)
|
|
cmapnofocus(current->screen);
|
|
}
|
|
setactive(c, 1);
|
|
for(cc = clients; cc; cc = cc->next)
|
|
if(cc->revert == c)
|
|
cc->revert = c->revert;
|
|
c->revert = current;
|
|
while(c->revert && !normal(c->revert))
|
|
c->revert = c->revert->revert;
|
|
current = c;
|
|
#ifdef DEBUG
|
|
if(debug)
|
|
dump_revert();
|
|
#endif
|
|
}
|
|
|
|
void
|
|
nofocus(void)
|
|
{
|
|
static Window w = 0;
|
|
int mask;
|
|
XSetWindowAttributes attr;
|
|
Client *c;
|
|
|
|
if(current){
|
|
setactive(current, 0);
|
|
for(c = current->revert; c; c = c->revert)
|
|
if(normal(c)){
|
|
active(c);
|
|
return;
|
|
}
|
|
cmapnofocus(current->screen);
|
|
/* if no candidates to revert to, fall through */
|
|
}
|
|
current = 0;
|
|
if(w == 0){
|
|
mask = CWOverrideRedirect/*|CWColormap*/;
|
|
attr.override_redirect = 1;
|
|
/* attr.colormap = screens[0].def_cmap;*/
|
|
w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0,
|
|
0 /*screens[0].depth*/, InputOnly, screens[0].vis, mask, &attr);
|
|
XMapWindow(dpy, w);
|
|
}
|
|
XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp());
|
|
}
|
|
|
|
void
|
|
top(Client *c)
|
|
{
|
|
Client **l, *cc;
|
|
|
|
l = &clients;
|
|
for(cc = *l; cc; cc = *l){
|
|
if(cc == c){
|
|
*l = c->next;
|
|
c->next = clients;
|
|
clients = c;
|
|
return;
|
|
}
|
|
l = &cc->next;
|
|
}
|
|
fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c);
|
|
}
|
|
|
|
Client *
|
|
getclient(Window w, int create)
|
|
{
|
|
Client *c;
|
|
|
|
if(w == 0 || getscreen(w))
|
|
return 0;
|
|
|
|
for(c = clients; c; c = c->next)
|
|
if(c->window == w || c->parent == w)
|
|
return c;
|
|
|
|
if(!create)
|
|
return 0;
|
|
|
|
c = (Client *)malloc(sizeof(Client));
|
|
memset(c, 0, sizeof(Client));
|
|
c->window = w;
|
|
/* c->parent will be set by the caller */
|
|
c->parent = None;
|
|
c->reparenting = 0;
|
|
c->state = WithdrawnState;
|
|
c->init = 0;
|
|
c->cmap = None;
|
|
c->label = c->class = 0;
|
|
c->revert = 0;
|
|
c->is9term = 0;
|
|
c->hold = 0;
|
|
c->ncmapwins = 0;
|
|
c->cmapwins = 0;
|
|
c->wmcmaps = 0;
|
|
c->next = clients;
|
|
c->virt = virt;
|
|
clients = c;
|
|
return c;
|
|
}
|
|
|
|
void
|
|
rmclient(Client *c)
|
|
{
|
|
Client *cc;
|
|
|
|
for(cc = current; cc && cc->revert; cc = cc->revert)
|
|
if(cc->revert == c)
|
|
cc->revert = cc->revert->revert;
|
|
|
|
if(c == clients)
|
|
clients = c->next;
|
|
for(cc = clients; cc && cc->next; cc = cc->next)
|
|
if(cc->next == c)
|
|
cc->next = cc->next->next;
|
|
|
|
if(hidden(c))
|
|
unhidec(c, 0);
|
|
|
|
if(c->parent != c->screen->root)
|
|
XDestroyWindow(dpy, c->parent);
|
|
|
|
c->parent = c->window = None; /* paranoia */
|
|
if(current == c){
|
|
current = c->revert;
|
|
if(current == 0)
|
|
nofocus();
|
|
else {
|
|
if(current->screen != c->screen)
|
|
cmapnofocus(c->screen);
|
|
setactive(current, 1);
|
|
}
|
|
}
|
|
if(c->ncmapwins != 0){
|
|
XFree((char *)c->cmapwins);
|
|
free((char *)c->wmcmaps);
|
|
}
|
|
if(c->iconname != 0)
|
|
XFree((char*) c->iconname);
|
|
if(c->name != 0)
|
|
XFree((char*) c->name);
|
|
if(c->instance != 0)
|
|
XFree((char*) c->instance);
|
|
if(c->class != 0)
|
|
XFree((char*) c->class);
|
|
memset(c, 0, sizeof(Client)); /* paranoia */
|
|
free(c);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
void
|
|
dump_revert(void)
|
|
{
|
|
Client *c;
|
|
int i;
|
|
|
|
i = 0;
|
|
for(c = current; c; c = c->revert){
|
|
fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", (int)c->window, c->state);
|
|
if(i++ > 100)
|
|
break;
|
|
if(c->revert)
|
|
fprintf(stderr, " -> ");
|
|
}
|
|
if(current == 0)
|
|
fprintf(stderr, "empty");
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
void
|
|
dump_clients(void)
|
|
{
|
|
Client *c;
|
|
|
|
for(c = clients; c; c = c->next)
|
|
fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", (int)c->window, (int)c->parent, c->x, c->y);
|
|
}
|
|
#endif
|
|
|
|
void
|
|
shuffle(int up)
|
|
{
|
|
Client **l, *c;
|
|
|
|
if(clients == 0 || clients->next == 0)
|
|
return;
|
|
if(!up){
|
|
c = 0;
|
|
/*for(c=clients; c->next; c=c->next) */
|
|
/* ; */
|
|
for(l=&clients; (*l)->next; l=&(*l)->next)
|
|
#ifdef AUTOSTICK
|
|
if ((*l)->state == 1 && !isautostick(*l))
|
|
c = *l;
|
|
#else
|
|
if ((*l)->state == 1)
|
|
c = *l;
|
|
#endif
|
|
if (c == 0)
|
|
return;
|
|
XMapRaised(dpy, c->parent);
|
|
top(c);
|
|
active(c);
|
|
}else{
|
|
c = clients;
|
|
for(l=&clients; *l; l=&(*l)->next)
|
|
;
|
|
clients = c->next;
|
|
*l = c;
|
|
c->next = 0;
|
|
XLowerWindow(dpy, c->window);
|
|
}
|
|
/* XMapRaised(dpy, clients->parent); */
|
|
/* top(clients); */
|
|
/* active(clients); */
|
|
}
|
|
|
|
#ifdef AUTOSTICK
|
|
int
|
|
isautostick(Client *c)
|
|
{
|
|
static char *autostick[] = AUTOSTICK;
|
|
char **a = autostick;
|
|
|
|
while(*a){
|
|
if(strstr(c->class, *a)) {
|
|
return 1;
|
|
}
|
|
++a;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|