plan9port

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

event.c (12295B)


      1 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 #include <X11/X.h>
      5 #include <X11/Xos.h>
      6 #include <X11/Xlib.h>
      7 #include <X11/Xutil.h>
      8 #include <X11/Xatom.h>
      9 #include <X11/extensions/shape.h>
     10 #include "dat.h"
     11 #include "fns.h"
     12 #include "patchlevel.h"
     13 
     14 void
     15 mainloop(int shape_event)
     16 {
     17 	XEvent ev;
     18 
     19 	for(;;){
     20 		getevent(&ev);
     21 
     22 #ifdef	DEBUG_EV
     23 		if(debug){
     24 			ShowEvent(&ev);
     25 			printf("\n");
     26 		}
     27 #endif
     28 		switch (ev.type){
     29 		default:
     30 #ifdef	SHAPE
     31 			if(shape && ev.type == shape_event)
     32 				shapenotify((XShapeEvent *)&ev);
     33 			else
     34 #endif
     35 				fprintf(stderr, "rio: unknown ev.type %d\n", ev.type);
     36 			break;
     37 		case KeyPress:
     38 			keypress(&ev.xkey);
     39 			break;
     40 		case KeyRelease:
     41 			keyrelease(&ev.xkey);
     42 			break;
     43 		case ButtonPress:
     44 			button(&ev.xbutton);
     45 			break;
     46 		case ButtonRelease:
     47 			break;
     48 		case MapRequest:
     49 			mapreq(&ev.xmaprequest);
     50 			break;
     51 		case ConfigureRequest:
     52 			configurereq(&ev.xconfigurerequest);
     53 			break;
     54 		case CirculateRequest:
     55 			circulatereq(&ev.xcirculaterequest);
     56 			break;
     57 		case UnmapNotify:
     58 			unmap(&ev.xunmap);
     59 			break;
     60 		case CreateNotify:
     61 			newwindow(&ev.xcreatewindow);
     62 			break;
     63 		case DestroyNotify:
     64 			destroy(ev.xdestroywindow.window);
     65 			break;
     66 		case ClientMessage:
     67 			clientmesg(&ev.xclient);
     68 			break;
     69 		case ColormapNotify:
     70 			cmap(&ev.xcolormap);
     71 			break;
     72 		case PropertyNotify:
     73 			property(&ev.xproperty);
     74 			break;
     75 		case SelectionClear:
     76 			fprintf(stderr, "rio: SelectionClear (this should not happen)\n");
     77 			break;
     78 		case SelectionNotify:
     79 			fprintf(stderr, "rio: SelectionNotify (this should not happen)\n");
     80 			break;
     81 		case SelectionRequest:
     82 			fprintf(stderr, "rio: SelectionRequest (this should not happen)\n");
     83 			break;
     84 		case EnterNotify:
     85 			enter(&ev.xcrossing);
     86 			break;
     87 		case LeaveNotify:
     88 			leave(&ev.xcrossing);
     89 			break;
     90 		case ReparentNotify:
     91 			reparent(&ev.xreparent);
     92 			break;
     93 		case FocusIn:
     94 			focusin(&ev.xfocus);
     95 			break;
     96 		case MotionNotify:
     97 			motionnotify(&ev.xmotion);
     98 			break;
     99 		case Expose:
    100 		case NoExpose:
    101 		case FocusOut:
    102 		case ConfigureNotify:
    103 		case MapNotify:
    104 		case MappingNotify:
    105 		case GraphicsExpose:
    106 			/* not interested */
    107 			trace("ignore", 0, &ev);
    108 			break;
    109 		}
    110 	}
    111 }
    112 
    113 
    114 void
    115 configurereq(XConfigureRequestEvent *e)
    116 {
    117 	XWindowChanges wc;
    118 	Client *c;
    119 
    120 	/* we don't set curtime as nothing here uses it */
    121 	c = getclient(e->window, 0);
    122 	trace("configurereq", c, e);
    123 
    124 	e->value_mask &= ~CWSibling;
    125 
    126 	if(c){
    127 		if(e->value_mask & CWX)
    128 			c->x = e->x;
    129 		if(e->value_mask & CWY)
    130 			c->y = e->y;
    131 		if(e->value_mask & CWWidth)
    132 			c->dx = e->width;
    133 		if(e->value_mask & CWHeight)
    134 			c->dy = e->height;
    135 		if(e->value_mask & CWBorderWidth)
    136 			c->border = e->border_width;
    137 
    138 		if(c->dx >= c->screen->width && c->dy >= c->screen->height)
    139 			c->border = 0;
    140 		else
    141 			c->border = BORDER;
    142 
    143 		if(e->value_mask & CWStackMode){
    144 			if(e->detail == Above)
    145 				top(c);
    146 			else
    147 				e->value_mask &= ~CWStackMode;
    148 		}
    149 		e->value_mask |= CWX|CWY|CWHeight|CWWidth;
    150 
    151 		if(c->parent != c->screen->root && c->window == e->window){
    152 			wc.x = c->x - c->border;
    153 			wc.y = c->y - c->border;
    154 			wc.width = c->dx+c->border+c->border;
    155 			wc.height = c->dy+c->border+c->border;
    156 			wc.border_width = 1;
    157 			wc.sibling = None;
    158 			wc.stack_mode = e->detail;
    159 			XConfigureWindow(dpy, c->parent, e->value_mask, &wc);
    160 
    161 			if(e->value_mask & CWStackMode){
    162 				top(c);
    163 				active(c);
    164 			}
    165 		}
    166 	}
    167 
    168 	if(c && c->parent != c->screen->root){
    169 		wc.x = c->border;
    170 		wc.y = c->border;
    171 	}else {
    172 		wc.x = c->x;
    173 		wc.y = c->y;
    174 	}
    175 	wc.width = c->dx;
    176 	wc.height = c->dy;
    177 	wc.border_width = 0;
    178 	wc.sibling = None;
    179 	wc.stack_mode = Above;
    180 	e->value_mask &= ~CWStackMode;
    181 	e->value_mask |= CWBorderWidth;
    182 	XConfigureWindow(dpy, c->window, e->value_mask, &wc);
    183 }
    184 
    185 void
    186 mapreq(XMapRequestEvent *e)
    187 {
    188 	Client *c;
    189 	int i;
    190 
    191 	curtime = CurrentTime;
    192 	c = getclient(e->window, 0);
    193 	trace("mapreq", c, e);
    194 
    195 	if(c == 0 || c->window != e->window){
    196 		/* workaround for stupid NCDware */
    197 		fprintf(stderr, "rio: bad mapreq c %p w %x, rescanning\n",
    198 			(void*)c, (int)e->window);
    199 		for(i = 0; i < num_screens; i++)
    200 			scanwins(&screens[i]);
    201 		c = getclient(e->window, 0);
    202 		if(c == 0 || c->window != e->window){
    203 			fprintf(stderr, "rio: window not found after rescan\n");
    204 			return;
    205 		}
    206 	}
    207 
    208 	switch (c->state){
    209 	case WithdrawnState:
    210 		if(c->parent == c->screen->root){
    211 			if(!manage(c, 0))
    212 				return;
    213 			break;
    214 		}
    215 		XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
    216 		XAddToSaveSet(dpy, c->window);
    217 		/* fall through... */
    218 	case NormalState:
    219 		XMapWindow(dpy, c->window);
    220 		XMapRaised(dpy, c->parent);
    221 		top(c);
    222 		setstate(c, NormalState);
    223 		if(c->trans != None && current && c->trans == current->window)
    224 				active(c);
    225 		break;
    226 	case IconicState:
    227 		unhidec(c, 1);
    228 		break;
    229 	}
    230 }
    231 
    232 void
    233 unmap(XUnmapEvent *e)
    234 {
    235 	Client *c;
    236 
    237 	curtime = CurrentTime;
    238 	c = getclient(e->window, 0);
    239 	if(c){
    240 		switch (c->state){
    241 		case IconicState:
    242 			if(e->send_event){
    243 				unhidec(c, 0);
    244 				withdraw(c);
    245 			}
    246 			break;
    247 		case NormalState:
    248 			if(c == current)
    249 				nofocus();
    250 			if(!c->reparenting)
    251 				withdraw(c);
    252 			break;
    253 		}
    254 		c->reparenting = 0;
    255 	}
    256 }
    257 
    258 void
    259 circulatereq(XCirculateRequestEvent *e)
    260 {
    261 	fprintf(stderr, "It must be the warlock Krill!\n");  /* ☺ */
    262 }
    263 
    264 void
    265 newwindow(XCreateWindowEvent *e)
    266 {
    267 	Client *c;
    268 	ScreenInfo *s;
    269 
    270 	/* we don't set curtime as nothing here uses it */
    271 	if(e->override_redirect)
    272 		return;
    273 	c = getclient(e->window, 1);
    274 	if(c && c->window == e->window && (s = getscreen(e->parent))){
    275 		c->x = e->x;
    276 		c->y = e->y;
    277 		c->dx = e->width;
    278 		c->dy = e->height;
    279 		c->border = e->border_width;
    280 		c->screen = s;
    281 		if(c->parent == None)
    282 			c->parent = c->screen->root;
    283 	}
    284 }
    285 
    286 void
    287 destroy(Window w)
    288 {
    289 	int i;
    290 	Client *c;
    291 
    292 	curtime = CurrentTime;
    293 	c = getclient(w, 0);
    294 	if(c == 0)
    295 		return;
    296 
    297 	if(numvirtuals > 1)
    298 		for(i=0; i<numvirtuals; i++)
    299 			if(currents[i] == c)
    300 				currents[i] = 0;
    301 
    302 	rmclient(c);
    303 
    304 	/* flush any errors generated by the window's sudden demise */
    305 	ignore_badwindow = 1;
    306 	XSync(dpy, False);
    307 	ignore_badwindow = 0;
    308 }
    309 
    310 void
    311 clientmesg(XClientMessageEvent *e)
    312 {
    313 	Client *c;
    314 
    315 	curtime = CurrentTime;
    316 	if(e->message_type == exit_rio){
    317 		cleanup();
    318 		exit(0);
    319 	}
    320 	if(e->message_type == restart_rio){
    321 		fprintf(stderr, "*** rio restarting ***\n");
    322 		cleanup();
    323 		execvp(myargv[0], myargv);
    324 		perror("rio: exec failed");
    325 		exit(1);
    326 	}
    327 	if(e->message_type == wm_protocols)
    328 		return;
    329 	if(e->message_type == wm_change_state){
    330 		c = getclient(e->window, 0);
    331 		if(e->format == 32 && e->data.l[0] == IconicState && c != 0){
    332 			if(normal(c))
    333 				hide(c);
    334 		}
    335 		else
    336 			fprintf(stderr, "rio: WM_CHANGE_STATE: format %d data %d w 0x%x\n",
    337 				(int)e->format, (int)e->data.l[0], (int)e->window);
    338 		return;
    339 	}
    340 	if(e->message_type == wm_state){
    341 //		c = getclient(e->window, 0);
    342 //		if(e->format == 32 && e->data.l[1] == wm_state_fullscreen){
    343 //		}else
    344 		fprintf(stderr, "rio: WM_STATE: format %d data %d %d w 0x%x\n",
    345 			(int)e->format, (int)e->data.l[0], (int)e->data.l[1],
    346 			(int)e->window);
    347 		return;
    348 	}
    349 	fprintf(stderr, "rio: strange ClientMessage, type 0x%x window 0x%x\n",
    350 		(int)e->message_type, (int)e->window);
    351 }
    352 
    353 void
    354 cmap(XColormapEvent *e)
    355 {
    356 	Client *c;
    357 	int i;
    358 
    359 	/* we don't set curtime as nothing here uses it */
    360 	if(e->new){
    361 		c = getclient(e->window, 0);
    362 		if(c){
    363 			c->cmap = e->colormap;
    364 			if(c == current)
    365 				cmapfocus(c);
    366 		}
    367 		else
    368 			for(c = clients; c; c = c->next){
    369 				for(i = 0; i < c->ncmapwins; i++)
    370 					if(c->cmapwins[i] == e->window){
    371 						c->wmcmaps[i] = e->colormap;
    372 						if(c == current)
    373 							cmapfocus(c);
    374 						return;
    375 					}
    376 			}
    377 	}
    378 }
    379 
    380 void
    381 property(XPropertyEvent *e)
    382 {
    383 	Atom a;
    384 	int delete;
    385 	Client *c;
    386 	long msize;
    387 
    388 	/* we don't set curtime as nothing here uses it */
    389 	a = e->atom;
    390 	delete = (e->state == PropertyDelete);
    391 	c = getclient(e->window, 0);
    392 	if(c == 0)
    393 		return;
    394 
    395 	switch (a){
    396 	case XA_WM_ICON_NAME:
    397 		if(c->iconname != 0)
    398 			XFree((char*) c->iconname);
    399 		c->iconname = delete ? 0 : getprop(c->window, a);
    400 		setlabel(c);
    401 		renamec(c, c->label);
    402 		return;
    403 	case XA_WM_NAME:
    404 		if(c->name != 0)
    405 			XFree((char*) c->name);
    406 		c->name = delete ? 0 : getprop(c->window, a);
    407 		setlabel(c);
    408 		renamec(c, c->label);
    409 		return;
    410 	case XA_WM_TRANSIENT_FOR:
    411 		gettrans(c);
    412 		return;
    413 	case XA_WM_HINTS:
    414 	case XA_WM_SIZE_HINTS:
    415 	case XA_WM_ZOOM_HINTS:
    416 		/* placeholders to not forget.  ignore for now.  -Axel */
    417 		return;
    418 	case XA_WM_NORMAL_HINTS:
    419 		if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
    420 			c->size.flags = PSize;	/* not specified - punt */
    421 		return;
    422 	}
    423 	if(a == _rio_hold_mode){
    424 		c->hold = getiprop(c->window, _rio_hold_mode);
    425 		if(c == current)
    426 			draw_border(c, 1);
    427 	}
    428 	else if(a == wm_colormaps){
    429 		getcmaps(c);
    430 		if(c == current)
    431 			cmapfocus(c);
    432 	}
    433 }
    434 
    435 void
    436 reparent(XReparentEvent *e)
    437 {
    438 	Client *c;
    439 	XWindowAttributes attr;
    440 	ScreenInfo *s;
    441 
    442 	/* we don't set curtime as nothing here uses it */
    443 	if(!getscreen(e->event) || e->override_redirect)
    444 		return;
    445 	if((s = getscreen(e->parent)) != 0){
    446 		c = getclient(e->window, 1);
    447 		if(c != 0 && (c->dx == 0 || c->dy == 0)){
    448 			/* flush any errors */
    449 			ignore_badwindow = 1;
    450 			XGetWindowAttributes(dpy, c->window, &attr);
    451 			XSync(dpy, False);
    452 			ignore_badwindow = 0;
    453 
    454 			c->x = attr.x;
    455 			c->y = attr.y;
    456 			c->dx = attr.width;
    457 			c->dy = attr.height;
    458 			c->border = attr.border_width;
    459 			c->screen = s;
    460 			if(c->parent == None)
    461 				c->parent = c->screen->root;
    462 		}
    463 	}
    464 	else {
    465 		c = getclient(e->window, 0);
    466 		if(c != 0 && (c->parent == c->screen->root || withdrawn(c)))
    467 			rmclient(c);
    468 	}
    469 }
    470 
    471 #ifdef	SHAPE
    472 void
    473 shapenotify(XShapeEvent *e)
    474 {
    475 	Client *c;
    476 
    477 	/* we don't set curtime as nothing here uses it */
    478 	c = getclient(e->window, 0);
    479 	if(c == 0)
    480 		return;
    481 
    482 	setshape(c);
    483 }
    484 #endif
    485 
    486 void
    487 enter(XCrossingEvent *e)
    488 {
    489 	Client *c;
    490 
    491 	curtime = e->time;
    492 	if(!ffm)
    493 	if(e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual)
    494 		return;
    495 	c = getclient(e->window, 0);
    496 	if(c != 0 && c != current){
    497 		/* someone grabbed the pointer; make them current */
    498 		if(!ffm)
    499 			XMapRaised(dpy, c->parent);
    500 		top(c);
    501 		active(c);
    502 	}
    503 }
    504 
    505 void
    506 leave(XCrossingEvent *e)
    507 {
    508 	Client *c;
    509 
    510 	c = getclient(e->window, 0);
    511 	if(c)
    512 		XUndefineCursor(dpy, c->parent);
    513 /* 	XDefineCursor(dpy, c->parent, c->screen->arrow); */
    514 }
    515 
    516 void
    517 focusin(XFocusChangeEvent *e)
    518 {
    519 	Client *c;
    520 
    521 	curtime = CurrentTime;
    522 	if(e->detail != NotifyNonlinearVirtual)
    523 		return;
    524 	c = getclient(e->window, 0);
    525 	if(c != 0 && c->window == e->window && c != current){
    526 		/* someone grabbed keyboard or seized focus; make them current */
    527 		XMapRaised(dpy, c->parent);
    528 		top(c);
    529 		active(c);
    530 	}
    531 }
    532 
    533 BorderOrient
    534 borderorient(Client *c, int x, int y)
    535 {
    536 	if(x <= BORDER){
    537 		if(y <= CORNER){
    538 			if(debug) fprintf(stderr, "topleft\n");
    539 			return BorderWNW;
    540 		}
    541 		if(y >= (c->dy + 2*BORDER) - CORNER){
    542 			if(debug) fprintf(stderr, "botleft\n");
    543 			return BorderWSW;
    544 		}
    545 		if(y > CORNER &&
    546 			y < (c->dy + 2*BORDER) - CORNER){
    547 			if(debug) fprintf(stderr, "left\n");
    548 			return BorderW;
    549 		}
    550 	} else if(x <= CORNER){
    551 		if(y <= BORDER){
    552 			if(debug) fprintf(stderr, "topleft\n");
    553 			return BorderNNW;
    554 		}
    555 		if  (y >= (c->dy + BORDER)){
    556 			if(debug) fprintf(stderr, "botleft\n");
    557 			return BorderSSW;
    558 		}
    559 	} else if(x >= (c->dx + BORDER)){
    560 		if(y <= CORNER){
    561 			if(debug) fprintf(stderr, "topright\n");
    562 			return BorderENE;
    563 		}
    564 		if(y >= (c->dy + 2*BORDER) - CORNER){
    565 			if(debug) fprintf(stderr, "botright\n");
    566 			return BorderESE;
    567 		}
    568 		if(y > CORNER &&
    569 			y < (c->dy + 2*BORDER) - CORNER){
    570 			if(debug) fprintf(stderr, "right\n");
    571 			return BorderE;
    572 		}
    573 	} else if(x >= (c->dx + 2*BORDER) - CORNER){
    574 		if(y <= BORDER){
    575 			if(debug) fprintf(stderr, "topright\n");
    576 			return BorderNNE;
    577 		}
    578 		if  (y >= (c->dy + BORDER)){
    579 			if(debug) fprintf(stderr, "botright\n");
    580 			return BorderSSE;
    581 		}
    582 	} else if(x > CORNER &&
    583 			x < (c->dx + 2*BORDER) - CORNER){
    584 		if(y <= BORDER){
    585 			if(debug) fprintf(stderr, "top\n");
    586 			return BorderN;
    587 		}
    588 		if(y >= (c->dy + BORDER)){
    589 			if(debug) fprintf(stderr, "bot\n");
    590 			return BorderS;
    591 		}
    592 	}
    593 	return BorderUnknown;
    594 }
    595 
    596 void
    597 motionnotify(XMotionEvent *e)
    598 {
    599 	Client *c;
    600 	BorderOrient bl;
    601 
    602 	c = getclient(e->window, 0);
    603 	if(c){
    604 		bl = borderorient(c, e->x, e->y);
    605 		if(bl == BorderUnknown)
    606 			XUndefineCursor(dpy, c->parent);
    607 		else
    608 			XDefineCursor(dpy, c->parent, c->screen->bordcurs[bl]);
    609 	}
    610 }