plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

client.c (5575B)


      1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
      2 #include <stdio.h>
      3 #include <unistd.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <X11/X.h>
      7 #include <X11/Xlib.h>
      8 #include <X11/Xutil.h>
      9 #include "dat.h"
     10 #include "fns.h"
     11 
     12 Client	*clients;
     13 Client	*current;
     14 
     15 void
     16 setactive(Client *c, int on)
     17 {
     18 /*	dbg("setactive client %x %d", c->window, c->on); */
     19 
     20 	if(c->parent == c->screen->root)
     21 		return;
     22 
     23 	if(on){
     24 		XUngrabButton(dpy, AnyButton, AnyModifier, c->parent);
     25 		XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp());
     26 		if(c->proto & Ptakefocus)
     27 			sendcmessage(c->window, wm_protocols, wm_take_focus, 0, 1);
     28 		cmapfocus(c);
     29 	}else{
     30 		if(c->proto & Plosefocus)
     31 			sendcmessage(c->window, wm_protocols, wm_lose_focus, 0, 1);
     32 		XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False,
     33 			ButtonMask, GrabModeAsync, GrabModeSync, None, None);
     34 	}
     35 	draw_border(c, on);
     36 }
     37 
     38 void
     39 draw_border(Client *c, int active)
     40 {
     41 	unsigned long pixel;
     42 
     43 	if(active){
     44 		if(c->hold)
     45 			pixel = c->screen->activeholdborder;
     46 		else
     47 			pixel = c->screen->activeborder;
     48 	}else{
     49 		if(c->hold)
     50 			pixel = c->screen->inactiveholdborder;
     51 		else
     52 			pixel = c->screen->inactiveborder;
     53 	}
     54 
     55 	if(debug) fprintf(stderr, "draw_border %p pixel %ld active %d hold %d\n", (void*)c, pixel, active, c->hold);
     56 	XSetWindowBackground(dpy, c->parent, pixel);
     57 	XClearWindow(dpy, c->parent);
     58 }
     59 
     60 void
     61 active(Client *c)
     62 {
     63 	Client *cc;
     64 
     65 	if(c == 0){
     66 		fprintf(stderr, "rio: active(c==0)\n");
     67 		return;
     68 	}
     69 	if(c == current)
     70 		return;
     71 	if(current){
     72 		setactive(current, 0);
     73 		if(current->screen != c->screen)
     74 			cmapnofocus(current->screen);
     75 	}
     76 	setactive(c, 1);
     77 	for(cc = clients; cc; cc = cc->next)
     78 		if(cc->revert == c)
     79 			cc->revert = c->revert;
     80 	c->revert = current;
     81 	while(c->revert && !normal(c->revert))
     82 		c->revert = c->revert->revert;
     83 	current = c;
     84 #ifdef	DEBUG
     85 	if(debug)
     86 		dump_revert();
     87 #endif
     88 }
     89 
     90 void
     91 nofocus(void)
     92 {
     93 	static Window w = 0;
     94 	int mask;
     95 	XSetWindowAttributes attr;
     96 	Client *c;
     97 
     98 	if(current){
     99 		setactive(current, 0);
    100 		for(c = current->revert; c; c = c->revert)
    101 			if(normal(c)){
    102 				active(c);
    103 				return;
    104 			}
    105 		cmapnofocus(current->screen);
    106 		/* if no candidates to revert to, fall through */
    107 	}
    108 	current = 0;
    109 	if(w == 0){
    110 		mask = CWOverrideRedirect/*|CWColormap*/;
    111 		attr.override_redirect = 1;
    112 		/* attr.colormap = screens[0].def_cmap;*/
    113 		w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0,
    114 			0 /*screens[0].depth*/, InputOnly, 	screens[0].vis, mask, &attr);
    115 		XMapWindow(dpy, w);
    116 	}
    117 	XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp());
    118 }
    119 
    120 void
    121 top(Client *c)
    122 {
    123 	Client **l, *cc;
    124 
    125 	l = &clients;
    126 	for(cc = *l; cc; cc = *l){
    127 		if(cc == c){
    128 			*l = c->next;
    129 			c->next = clients;
    130 			clients = c;
    131 			return;
    132 		}
    133 		l = &cc->next;
    134 	}
    135 	fprintf(stderr, "rio: %p not on client list in top()\n", (void*)c);
    136 }
    137 
    138 Client *
    139 getclient(Window w, int create)
    140 {
    141 	Client *c;
    142 
    143 	if(w == 0 || getscreen(w))
    144 		return 0;
    145 
    146 	for(c = clients; c; c = c->next)
    147 		if(c->window == w || c->parent == w)
    148 			return c;
    149 
    150 	if(!create)
    151 		return 0;
    152 
    153 	c = (Client *)malloc(sizeof(Client));
    154 	if (!c){
    155 		fprintf(stderr, "rio: Failed to allocate memory\n");
    156 		exit(1);
    157 	}
    158 
    159 	memset(c, 0, sizeof(Client));
    160 	c->window = w;
    161 	/* c->parent will be set by the caller */
    162 	c->parent = None;
    163 	c->reparenting = 0;
    164 	c->state = WithdrawnState;
    165 	c->init = 0;
    166 	c->cmap = None;
    167 	c->label = c->class = 0;
    168 	c->revert = 0;
    169 	c->is9term = 0;
    170 	c->hold = 0;
    171 	c->ncmapwins = 0;
    172 	c->cmapwins = 0;
    173 	c->wmcmaps = 0;
    174 	c->next = clients;
    175 	c->virt = virt;
    176 	clients = c;
    177 	return c;
    178 }
    179 
    180 void
    181 rmclient(Client *c)
    182 {
    183 	Client *cc;
    184 
    185 	for(cc = current; cc && cc->revert; cc = cc->revert)
    186 		if(cc->revert == c)
    187 			cc->revert = cc->revert->revert;
    188 
    189 	if(c == clients)
    190 		clients = c->next;
    191 	for(cc = clients; cc && cc->next; cc = cc->next)
    192 		if(cc->next == c)
    193 			cc->next = cc->next->next;
    194 
    195 	if(hidden(c))
    196 		unhidec(c, 0);
    197 
    198 	if(c->parent != c->screen->root)
    199 		XDestroyWindow(dpy, c->parent);
    200 
    201 	c->parent = c->window = None;		/* paranoia */
    202 	if(current == c){
    203 		current = c->revert;
    204 		if(current == 0)
    205 			nofocus();
    206 		else {
    207 			if(current->screen != c->screen)
    208 				cmapnofocus(c->screen);
    209 			setactive(current, 1);
    210 		}
    211 	}
    212 	if(c->ncmapwins != 0){
    213 		XFree((char *)c->cmapwins);
    214 		free((char *)c->wmcmaps);
    215 	}
    216 	if(c->iconname != 0)
    217 		XFree((char*) c->iconname);
    218 	if(c->name != 0)
    219 		XFree((char*) c->name);
    220 	if(c->instance != 0)
    221 		XFree((char*) c->instance);
    222 	if(c->class != 0)
    223 		XFree((char*) c->class);
    224 	memset(c, 0, sizeof(Client));		/* paranoia */
    225 	free(c);
    226 }
    227 
    228 #ifdef	DEBUG
    229 void
    230 dump_revert(void)
    231 {
    232 	Client *c;
    233 	int i;
    234 
    235 	i = 0;
    236 	for(c = current; c; c = c->revert){
    237 		fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", (int)c->window, c->state);
    238 		if(i++ > 100)
    239 			break;
    240 		if(c->revert)
    241 			fprintf(stderr, " -> ");
    242 	}
    243 	if(current == 0)
    244 		fprintf(stderr, "empty");
    245 	fprintf(stderr, "\n");
    246 }
    247 
    248 void
    249 dump_clients(void)
    250 {
    251 	Client *c;
    252 
    253 	for(c = clients; c; c = c->next)
    254 		fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", (int)c->window, (int)c->parent, c->x, c->y);
    255 }
    256 #endif
    257 
    258 void
    259 shuffle(int up)
    260 {
    261 	Client **l, *c;
    262 
    263 	if(clients == 0 || clients->next == 0)
    264 		return;
    265 	if(!up){
    266 		c = 0;
    267 		/*for(c=clients; c->next; c=c->next) */
    268 		/*	; */
    269 		for(l=&clients; (*l)->next; l=&(*l)->next)
    270 			if ((*l)->state == 1)
    271 				c = *l;
    272 		if (c == 0)
    273 			return;
    274 		XMapRaised(dpy, c->parent);
    275 		top(c);
    276 		active(c);
    277 	}else{
    278 		c = clients;
    279 		for(l=&clients; *l; l=&(*l)->next)
    280 			;
    281 		clients = c->next;
    282 		*l = c;
    283 		c->next = 0;
    284 		XLowerWindow(dpy, c->window);
    285 	}
    286 /*	XMapRaised(dpy, clients->parent); */
    287 /*	top(clients);	 */
    288 /*	active(clients); */
    289 }