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 }