| 1 | – | /* Copyright (c) 1997 Silicon Graphics, Inc. */ | 
| 2 | – |  | 
| 1 |  | #ifndef lint | 
| 2 | < | static char SCCSid[] = "$SunId$ SGI"; | 
| 2 | > | static const char       RCSid[] = "$Id$"; | 
| 3 |  | #endif | 
| 6 | – |  | 
| 4 |  | /* | 
| 5 |  | * X11 driver for holodeck display. | 
| 6 |  | * Based on rview driver. | 
| 7 |  | */ | 
| 8 |  |  | 
| 9 |  | #include "standard.h" | 
| 13 | – | #include "rhd_qtree.h" | 
| 14 | – |  | 
| 10 |  | #include  <X11/Xlib.h> | 
| 11 |  | #include  <X11/cursorfont.h> | 
| 12 |  | #include  <X11/Xutil.h> | 
| 13 | < |  | 
| 13 | > | #include  <time.h> | 
| 14 | > | #include "rhd_qtree.h" | 
| 15 |  | #include  "x11icon.h" | 
| 16 |  |  | 
| 17 | + | #ifndef RAYQLEN | 
| 18 | + | #define RAYQLEN         50000           /* max. rays to queue before flush */ | 
| 19 | + | #endif | 
| 20 | + |  | 
| 21 |  | #ifndef FEQ | 
| 22 |  | #define FEQ(a,b)        ((a)-(b) <= FTINY && (a)-(b) >= -FTINY) | 
| 23 |  | #endif | 
| 24 |  |  | 
| 25 | – | #define CTRL(c)         ((c)-'@') | 
| 26 | – |  | 
| 25 |  | #define GAMMA           2.2             /* default gamma correction */ | 
| 26 |  |  | 
| 27 | < | #define MOVPCT          10              /* percent distance to move */ | 
| 27 | > | #define FRAMESTATE(s)   (((s)&(ShiftMask|ControlMask))==(ShiftMask|ControlMask)) | 
| 28 | > |  | 
| 29 | > | #define MOVPCT          7               /* percent distance to move /frame */ | 
| 30 |  | #define MOVDIR(b)       ((b)==Button1 ? 1 : (b)==Button2 ? 0 : -1) | 
| 31 | + | #define MOVDEG          (-5)            /* degrees to orbit CW/down /frame */ | 
| 32 | + | #define MOVORB(s)       ((s)&ShiftMask ? 1 : (s)&ControlMask ? -1 : 0) | 
| 33 |  |  | 
| 34 |  | #define MINWIDTH        480             /* minimum graphics window width */ | 
| 35 |  | #define MINHEIGHT       400             /* minimum graphics window height */ | 
| 47 |  |  | 
| 48 |  | struct driver   odev;                   /* global device driver structure */ | 
| 49 |  |  | 
| 50 | + | char odev_args[64];                     /* command arguments */ | 
| 51 | + |  | 
| 52 |  | static XEvent  currentevent;            /* current event */ | 
| 53 |  |  | 
| 54 |  | static int  ncolors = 0;                /* color table size */ | 
| 68 |  |  | 
| 69 |  | static int      headlocked = 0;         /* lock vertical motion */ | 
| 70 |  |  | 
| 71 | < | static int  getpixels(), xnewcolr(), freepixels(), resizewindow(), | 
| 71 | > | static int  getpixels(), xnewcolr(), freepixels(), resizewindow(), getframe(), | 
| 72 |  | getevent(), getkey(), moveview(), getmove(), fixwindow(); | 
| 73 |  | static unsigned long  true_pixel(); | 
| 74 |  |  | 
| 85 |  | for (cp = tail; *cp && *cp != '.'; cp++) | 
| 86 |  | ; | 
| 87 |  | if (cp-tail == 3 && !strncmp(tail, "x11", 3)) | 
| 88 | < | return(TM_F_CAMERA); | 
| 88 | > | return(TM_F_CAMERA|TM_F_NOSTDERR); | 
| 89 |  | if (cp-tail == 4 && !strncmp(tail, "x11h", 4)) | 
| 90 | < | return(TM_F_HUMAN); | 
| 90 | > | return(TM_F_HUMAN|TM_F_NOSTDERR); | 
| 91 |  | error(USER, "illegal driver name"); | 
| 92 |  | } | 
| 93 |  |  | 
| 96 |  | char  *id; | 
| 97 |  | { | 
| 98 |  | extern char  *getenv(); | 
| 99 | < | char  *gv; | 
| 99 | > | static RGBPRIMS myprims = STDPRIMS; | 
| 100 | > | char  *ev; | 
| 101 |  | double  gamval = GAMMA; | 
| 102 | + | RGBPRIMP        dpri = stdprims; | 
| 103 |  | int  nplanes; | 
| 104 |  | XSetWindowAttributes    ourwinattr; | 
| 105 |  | XWMHints  ourxwmhints; | 
| 132 |  | ourwhite = WhitePixel(ourdisplay,ourscreen); | 
| 133 |  | } | 
| 134 |  | /* set gamma and tone mapping */ | 
| 135 | < | if ((gv = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL | 
| 136 | < | || (gv = getenv("DISPLAY_GAMMA")) != NULL) | 
| 137 | < | gamval = atof(gv); | 
| 138 | < | if (tmInit(mytmflags(), stdprims, gamval) == NULL) | 
| 135 | > | if ((ev = XGetDefault(ourdisplay, "radiance", "gamma")) != NULL | 
| 136 | > | || (ev = getenv("DISPLAY_GAMMA")) != NULL) | 
| 137 | > | gamval = atof(ev); | 
| 138 | > | if ((ev = getenv("DISPLAY_PRIMARIES")) != NULL && | 
| 139 | > | sscanf(ev, "%f %f %f %f %f %f %f %f", | 
| 140 | > | &myprims[RED][CIEX],&myprims[RED][CIEY], | 
| 141 | > | &myprims[GRN][CIEX],&myprims[GRN][CIEY], | 
| 142 | > | &myprims[BLU][CIEX],&myprims[BLU][CIEY], | 
| 143 | > | &myprims[WHT][CIEX],&myprims[WHT][CIEY]) >= 6) | 
| 144 | > | dpri = myprims; | 
| 145 | > | if (tmInit(mytmflags(), dpri, gamval) == NULL) | 
| 146 |  | error(SYSTEM, "not enough memory in dev_open"); | 
| 147 |  | /* open window */ | 
| 148 |  | ourwinattr.background_pixel = ourblack; | 
| 171 |  | oursizhints.min_height = MINHEIGHT; | 
| 172 |  | oursizhints.flags = PMinSize; | 
| 173 |  | XSetNormalHints(ourdisplay, gwind, &oursizhints); | 
| 161 | – | /* map the window and get its size */ | 
| 162 | – | XMapWindow(ourdisplay, gwind); | 
| 163 | – | dev_input(); | 
| 164 | – | /* allocate our leaf pile */ | 
| 165 | – | if (!qtAllocLeaves(DisplayWidth(ourdisplay,ourscreen) * | 
| 166 | – | DisplayHeight(ourdisplay,ourscreen) / | 
| 167 | – | (qtMinNodesiz*qtMinNodesiz))) | 
| 168 | – | error(SYSTEM, "insufficient memory for leaf storage"); | 
| 169 | – |  | 
| 174 |  | /* figure out sensible view */ | 
| 175 |  | pwidth = (double)DisplayWidthMM(ourdisplay, ourscreen) / | 
| 176 |  | DisplayWidth(ourdisplay, ourscreen); | 
| 177 |  | pheight = (double)DisplayHeightMM(ourdisplay, ourscreen) / | 
| 178 |  | DisplayHeight(ourdisplay, ourscreen); | 
| 179 | < | copystruct(&odev.v, &stdview); | 
| 176 | < | odev.name = id; | 
| 179 | > | odev.v = stdview; | 
| 180 |  | odev.v.type = VT_PER; | 
| 181 | < | odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres); | 
| 182 | < | odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres); | 
| 181 | > | /* map the window and get its size */ | 
| 182 | > | XMapWindow(ourdisplay, gwind); | 
| 183 | > | dev_input();                    /* sets size and view angles */ | 
| 184 | > | /* allocate our leaf pile */ | 
| 185 | > | if (!qtAllocLeaves(DisplayWidth(ourdisplay,ourscreen) * | 
| 186 | > | DisplayHeight(ourdisplay,ourscreen) * 3 / | 
| 187 | > | (qtMinNodesiz*qtMinNodesiz*2))) | 
| 188 | > | error(SYSTEM, "insufficient memory for leaf storage"); | 
| 189 | > | odev.name = id; | 
| 190 |  | odev.ifd = ConnectionNumber(ourdisplay); | 
| 191 |  | } | 
| 192 |  |  | 
| 208 |  | } | 
| 209 |  |  | 
| 210 |  |  | 
| 211 | + |  | 
| 212 | + | dev_clear()                     /* clear our quadtree */ | 
| 213 | + | { | 
| 214 | + | qtCompost(100); | 
| 215 | + | if (ncolors > 0) | 
| 216 | + | new_ctab(ncolors); | 
| 217 | + | rayqleft = 0;                   /* hold off update */ | 
| 218 | + | } | 
| 219 | + |  | 
| 220 | + |  | 
| 221 | + | int | 
| 222 |  | dev_view(nv)                    /* assign new driver view */ | 
| 223 |  | VIEW    *nv; | 
| 224 |  | { | 
| 225 | + | if (nv->type == VT_PAR ||               /* check view legality */ | 
| 226 | + | nv->horiz > 160. || nv->vert > 160.) { | 
| 227 | + | error(COMMAND, "illegal view type/angle"); | 
| 228 | + | nv->type = VT_PER; | 
| 229 | + | nv->horiz = odev.v.horiz; | 
| 230 | + | nv->vert = odev.v.vert; | 
| 231 | + | return(0); | 
| 232 | + | } | 
| 233 | + | if (nv->vfore > FTINY) { | 
| 234 | + | error(COMMAND, "cannot handle fore clipping"); | 
| 235 | + | nv->vfore = 0.; | 
| 236 | + | return(0); | 
| 237 | + | } | 
| 238 |  | if (nv != &odev.v) { | 
| 239 |  | if (!FEQ(nv->horiz,odev.v.horiz) ||     /* resize window? */ | 
| 240 |  | !FEQ(nv->vert,odev.v.vert)) { | 
| 241 | < | odev.hres = 2.*VIEWDIST*tan(PI/180./2.*nv->horiz) / | 
| 242 | < | pwidth; | 
| 243 | < | odev.vres = 2.*VIEWDIST*tan(PI/180./2.*nv->vert) / | 
| 244 | < | pheight; | 
| 241 | > | int     dw = DisplayWidth(ourdisplay,ourscreen); | 
| 242 | > | int     dh = DisplayHeight(ourdisplay,ourscreen); | 
| 243 | > |  | 
| 244 | > | dw -= 25;       /* for window frame */ | 
| 245 | > | dh -= 50; | 
| 246 | > | odev.hres = 2.*VIEWDIST/pwidth * | 
| 247 | > | tan(PI/180./2.*nv->horiz); | 
| 248 | > | odev.vres = 2.*VIEWDIST/pheight * | 
| 249 | > | tan(PI/180./2.*nv->vert); | 
| 250 | > | if (odev.hres > dw) { | 
| 251 | > | odev.vres = dw * odev.vres / odev.hres; | 
| 252 | > | odev.hres = dw; | 
| 253 | > | } | 
| 254 | > | if (odev.vres > dh) { | 
| 255 | > | odev.hres = dh * odev.hres / odev.vres; | 
| 256 | > | odev.vres = dh; | 
| 257 | > | } | 
| 258 |  | XResizeWindow(ourdisplay, gwind, odev.hres, odev.vres); | 
| 259 | + | dev_input();    /* wait for resize event */ | 
| 260 |  | } | 
| 261 | < | copystruct(&odev.v, nv); | 
| 261 | > | odev.v = *nv; | 
| 262 |  | } | 
| 263 |  | qtReplant(); | 
| 264 | + | return(1); | 
| 265 |  | } | 
| 266 |  |  | 
| 267 |  |  | 
| 268 | + | dev_section(ofn)                /* add octree for geometry rendering */ | 
| 269 | + | char    *ofn; | 
| 270 | + | { | 
| 271 | + | /* unimplemented */ | 
| 272 | + | } | 
| 273 | + |  | 
| 274 | + |  | 
| 275 | + | dev_auxcom(cmd, args)           /* process an auxiliary command */ | 
| 276 | + | char    *cmd, *args; | 
| 277 | + | { | 
| 278 | + | sprintf(errmsg, "%s: unknown command", cmd); | 
| 279 | + | error(COMMAND, errmsg); | 
| 280 | + | } | 
| 281 | + |  | 
| 282 | + |  | 
| 283 | + | VIEW * | 
| 284 | + | dev_auxview(n, hvres)           /* return nth auxiliary view */ | 
| 285 | + | int     n; | 
| 286 | + | int     hvres[2]; | 
| 287 | + | { | 
| 288 | + | if (n) | 
| 289 | + | return(NULL); | 
| 290 | + | hvres[0] = odev.hres; hvres[1] = odev.vres; | 
| 291 | + | return(&odev.v); | 
| 292 | + | } | 
| 293 | + |  | 
| 294 | + |  | 
| 295 |  | int | 
| 296 |  | dev_input()                     /* get X11 input */ | 
| 297 |  | { | 
| 300 |  | do | 
| 301 |  | getevent(); | 
| 302 |  |  | 
| 303 | < | while (XQLength(ourdisplay) > 0); | 
| 303 | > | while (XPending(ourdisplay) > 0); | 
| 304 |  |  | 
| 305 | + | odev.inpready = 0; | 
| 306 | + |  | 
| 307 |  | return(inpresflags); | 
| 308 |  | } | 
| 309 |  |  | 
| 330 |  | dev_flush()                     /* flush output */ | 
| 331 |  | { | 
| 332 |  | qtUpdate(); | 
| 333 | < | return(XPending(ourdisplay)); | 
| 333 | > | rayqleft = RAYQLEN; | 
| 334 | > | return(odev.inpready = XPending(ourdisplay)); | 
| 335 |  | } | 
| 336 |  |  | 
| 337 |  |  | 
| 375 |  | return(ncolors = 0); | 
| 376 |  | if (XAllocColorCells(ourdisplay,ourmap,0,NULL,0,pixval,ncolors)) | 
| 377 |  | break; | 
| 378 | < | free((char *)pixval); | 
| 378 | > | free((void *)pixval); | 
| 379 |  | pixval = NULL; | 
| 380 |  | } | 
| 381 |  | if (pixval == NULL) { | 
| 410 |  | if (ncolors == 0) | 
| 411 |  | return; | 
| 412 |  | XFreeColors(ourdisplay,ourmap,pixval,ncolors,0L); | 
| 413 | < | free((char *)pixval); | 
| 413 | > | free((void *)pixval); | 
| 414 |  | pixval = NULL; | 
| 415 |  | ncolors = 0; | 
| 416 |  | if (ourmap != DefaultColormap(ourdisplay,ourscreen)) | 
| 460 |  | getkey(levptr(XKeyPressedEvent)); | 
| 461 |  | break; | 
| 462 |  | case ButtonPress: | 
| 463 | < | getmove(levptr(XButtonPressedEvent)); | 
| 463 | > | if (FRAMESTATE(levptr(XButtonPressedEvent)->state)) | 
| 464 | > | getframe(levptr(XButtonPressedEvent)); | 
| 465 | > | else | 
| 466 | > | getmove(levptr(XButtonPressedEvent)); | 
| 467 |  | break; | 
| 468 |  | } | 
| 469 |  | } | 
| 474 |  | int     dp[2][2]; | 
| 475 |  | FVECT   wp[2]; | 
| 476 |  | { | 
| 477 | < | static FVECT    vmin = {0.,0.,0.}, vmax = {1.,1.,FHUGE}; | 
| 478 | < | FVECT   ip[2]; | 
| 479 | < | /* not exactly right, but who cares? */ | 
| 480 | < | viewloc(ip[0], &odev.v, wp[0]); | 
| 481 | < | viewloc(ip[1], &odev.v, wp[1]); | 
| 477 | > | static FVECT    vmin = {0.,0.,0.}, vmax = {1.-FTINY,1.-FTINY,FHUGE}; | 
| 478 | > | FVECT   wpc[2], ip[2]; | 
| 479 | > | double  d, d0, d1; | 
| 480 | > | /* check for points behind view */ | 
| 481 | > | d = DOT(odev.v.vp, odev.v.vdir); | 
| 482 | > | d0 = DOT(wp[0], odev.v.vdir) - d; | 
| 483 | > | d1 = DOT(wp[1], odev.v.vdir) - d; | 
| 484 | > | /* work on copy of world points */ | 
| 485 | > | if (d0 <= d1) { | 
| 486 | > | VCOPY(wpc[0], wp[0]); VCOPY(wpc[1], wp[1]); | 
| 487 | > | } else { | 
| 488 | > | d = d0; d0 = d1; d1 = d; | 
| 489 | > | VCOPY(wpc[1], wp[0]); VCOPY(wpc[0], wp[1]); | 
| 490 | > | } | 
| 491 | > | if (d0 <= FTINY) { | 
| 492 | > | if (d1 <= FTINY) return(0); | 
| 493 | > | VSUB(wpc[0], wpc[0], wpc[1]); | 
| 494 | > | d = .99*d1/(d1-d0); | 
| 495 | > | VSUM(wpc[0], wpc[1], wpc[0], d); | 
| 496 | > | } | 
| 497 | > | /* get view coordinates and clip to window */ | 
| 498 | > | viewloc(ip[0], &odev.v, wpc[0]); | 
| 499 | > | viewloc(ip[1], &odev.v, wpc[1]); | 
| 500 |  | if (!clip(ip[0], ip[1], vmin, vmax)) | 
| 501 |  | return(0); | 
| 502 |  | dp[0][0] = ip[0][0]*odev.hres; | 
| 527 |  | static BYTE     gridrgb[3] = {0x0, 0xff, 0xff}; | 
| 528 |  | unsigned long  pixel; | 
| 529 |  |  | 
| 430 | – | if (!mapped || odev.v.type != VT_PER) | 
| 431 | – | return; | 
| 530 |  | if (ncolors > 0) | 
| 531 |  | pixel = pixval[get_pixel(gridrgb, xnewcolr)]; | 
| 532 |  | else | 
| 538 |  |  | 
| 539 |  |  | 
| 540 |  | static | 
| 541 | < | moveview(dx, dy, move)          /* move our view */ | 
| 542 | < | int     dx, dy, move; | 
| 541 | > | moveview(dx, dy, mov, orb)      /* move our view */ | 
| 542 | > | int     dx, dy, mov, orb; | 
| 543 |  | { | 
| 544 |  | VIEW    nv; | 
| 545 | + | FVECT   odir, v1; | 
| 546 |  | double  d; | 
| 547 | < | register int    i, li; | 
| 547 | > | register int    li; | 
| 548 |  | /* start with old view */ | 
| 549 | < | copystruct(&nv, &odev.v); | 
| 549 | > | nv = odev.v; | 
| 550 |  | /* change view direction */ | 
| 551 | < | if (move) { | 
| 551 | > | if (mov | orb) { | 
| 552 |  | if ((li = qtFindLeaf(dx, dy)) < 0) | 
| 553 |  | return(0);      /* not on window */ | 
| 554 | < | for (i = 0; i < 3; i++) | 
| 456 | < | nv.vdir[i] = qtL.wp[li][i] - nv.vp[i]; | 
| 554 | > | VSUM(odir, qtL.wp[li], nv.vp, -1.); | 
| 555 |  | } else { | 
| 556 |  | if (viewray(nv.vp, nv.vdir, &odev.v, | 
| 557 |  | (dx+.5)/odev.hres, (dy+.5)/odev.vres) < -FTINY) | 
| 558 |  | return(0);      /* outside view */ | 
| 559 |  | } | 
| 560 | < | /* move viewpoint */ | 
| 561 | < | if (move > 0) | 
| 562 | < | for (i = 0; i < 3; i++) | 
| 563 | < | nv.vp[i] += MOVPCT/100. * nv.vdir[i]; | 
| 564 | < | else if (move < 0) | 
| 565 | < | for (i = 0; i < 3; i++) | 
| 566 | < | nv.vp[i] -= MOVPCT/100. * nv.vdir[i]; | 
| 567 | < | if (move && headlocked) { | 
| 568 | < | d = 0;          /* bring head back to same height */ | 
| 569 | < | for (i = 0; i < 3; i++) | 
| 570 | < | d += odev.v.vup[i] * (odev.v.vp[i] - nv.vp[i]); | 
| 571 | < | for (i = 0; i < 3; i++) | 
| 572 | < | nv.vp[i] += d * odev.v.vup[i]; | 
| 560 | > | if (orb && mov) {               /* orbit left/right */ | 
| 561 | > | spinvector(odir, odir, nv.vup, d=MOVDEG*PI/180.*mov); | 
| 562 | > | VSUM(nv.vp, qtL.wp[li], odir, -1.); | 
| 563 | > | spinvector(nv.vdir, nv.vdir, nv.vup, d); | 
| 564 | > | } else if (orb) {               /* orbit up/down */ | 
| 565 | > | fcross(v1, odir, nv.vup); | 
| 566 | > | if (normalize(v1) == 0.) | 
| 567 | > | return(0); | 
| 568 | > | spinvector(odir, odir, v1, d=MOVDEG*PI/180.*orb); | 
| 569 | > | VSUM(nv.vp, qtL.wp[li], odir, -1.); | 
| 570 | > | spinvector(nv.vdir, nv.vdir, v1, d); | 
| 571 | > | } else if (mov) {               /* move forward/backward */ | 
| 572 | > | d = MOVPCT/100. * mov; | 
| 573 | > | VSUM(nv.vp, nv.vp, odir, d); | 
| 574 |  | } | 
| 575 | + | if (!mov ^ !orb && headlocked) {        /* restore head height */ | 
| 576 | + | VSUM(v1, odev.v.vp, nv.vp, -1.); | 
| 577 | + | d = DOT(v1, odev.v.vup); | 
| 578 | + | VSUM(nv.vp, nv.vp, odev.v.vup, d); | 
| 579 | + | } | 
| 580 |  | if (setview(&nv) != NULL) | 
| 581 |  | return(0);      /* illegal view */ | 
| 582 |  | dev_view(&nv); | 
| 583 | < | inpresflags |= DEV_NEWVIEW; | 
| 583 | > | inpresflags |= DFL(DC_SETVIEW); | 
| 584 |  | return(1); | 
| 585 |  | } | 
| 586 |  |  | 
| 587 |  |  | 
| 588 |  | static | 
| 589 | + | getframe(ebut)                          /* get focus frame */ | 
| 590 | + | XButtonPressedEvent     *ebut; | 
| 591 | + | { | 
| 592 | + | int     startx = ebut->x, starty = ebut->y; | 
| 593 | + | int     endx, endy; | 
| 594 | + |  | 
| 595 | + | XMaskEvent(ourdisplay, ButtonReleaseMask, levptr(XEvent)); | 
| 596 | + | endx = levptr(XButtonReleasedEvent)->x; | 
| 597 | + | endy = levptr(XButtonReleasedEvent)->y; | 
| 598 | + | if ((endx == startx) | (endy == starty)) { | 
| 599 | + | XBell(ourdisplay, 0); | 
| 600 | + | return; | 
| 601 | + | } | 
| 602 | + | if (endx < startx) {register int c = endx; endx = startx; startx = c;} | 
| 603 | + | if (endy < starty) {register int c = endy; endy = starty; starty = c;} | 
| 604 | + | sprintf(odev_args, "%.3f %.3f %.3f %.3f", | 
| 605 | + | (startx+.5)/odev.hres, 1.-(endy+.5)/odev.vres, | 
| 606 | + | (endx+.5)/odev.hres, 1.-(starty+.5)/odev.vres); | 
| 607 | + | inpresflags |= DFL(DC_FOCUS); | 
| 608 | + | } | 
| 609 | + |  | 
| 610 | + |  | 
| 611 | + | static | 
| 612 | + | waitabit()                              /* pause a moment */ | 
| 613 | + | { | 
| 614 | + | struct timespec ts; | 
| 615 | + | ts.tv_sec = 0; | 
| 616 | + | ts.tv_nsec = 50000000; | 
| 617 | + | nanosleep(&ts, NULL); | 
| 618 | + | } | 
| 619 | + |  | 
| 620 | + |  | 
| 621 | + | static | 
| 622 |  | getmove(ebut)                           /* get view change */ | 
| 623 |  | XButtonPressedEvent     *ebut; | 
| 624 |  | { | 
| 625 | < | int     whichbutton = ebut->button; | 
| 625 | > | int     movdir = MOVDIR(ebut->button); | 
| 626 | > | int     movorb = MOVORB(ebut->state); | 
| 627 |  | int     oldnodesiz = qtMinNodesiz; | 
| 628 |  | Window  rootw, childw; | 
| 629 |  | int     rootx, rooty, wx, wy; | 
| 634 |  |  | 
| 635 |  | while (!XCheckMaskEvent(ourdisplay, | 
| 636 |  | ButtonReleaseMask, levptr(XEvent))) { | 
| 637 | < |  | 
| 637 | > | waitabit(); | 
| 638 |  | if (!XQueryPointer(ourdisplay, gwind, &rootw, &childw, | 
| 639 |  | &rootx, &rooty, &wx, &wy, &statemask)) | 
| 640 |  | break;          /* on another screen */ | 
| 641 |  |  | 
| 642 | < | if (!moveview(wx, odev.vres-1-wy, MOVDIR(whichbutton))) { | 
| 642 | > | if (!moveview(wx, odev.vres-1-wy, movdir, movorb)) { | 
| 643 |  | sleep(1); | 
| 644 |  | continue; | 
| 645 |  | } | 
| 647 |  | qtUpdate(); | 
| 648 |  | draw_grids(); | 
| 649 |  | } | 
| 650 | < | if (!(inpresflags & DEV_NEWVIEW)) {     /* do final motion */ | 
| 651 | < | whichbutton = levptr(XButtonReleasedEvent)->button; | 
| 650 | > | if (!(inpresflags & DFL(DC_SETVIEW))) { /* do final motion */ | 
| 651 | > | movdir = MOVDIR(levptr(XButtonReleasedEvent)->button); | 
| 652 |  | wx = levptr(XButtonReleasedEvent)->x; | 
| 653 |  | wy = levptr(XButtonReleasedEvent)->y; | 
| 654 | < | moveview(wx, odev.vres-1-wy, MOVDIR(whichbutton)); | 
| 654 | > | moveview(wx, odev.vres-1-wy, movdir, movorb); | 
| 655 |  | } | 
| 656 |  | dev_flush(); | 
| 657 |  |  | 
| 663 |  | getkey(ekey)                            /* get input key */ | 
| 664 |  | register XKeyPressedEvent  *ekey; | 
| 665 |  | { | 
| 666 | + | Window  rootw, childw; | 
| 667 | + | int     rootx, rooty, wx, wy; | 
| 668 | + | unsigned int    statemask; | 
| 669 |  | int  n; | 
| 670 |  | char    buf[8]; | 
| 671 |  |  | 
| 679 |  | case 'H':                       /* turn off height motion lock */ | 
| 680 |  | headlocked = 0; | 
| 681 |  | return; | 
| 682 | < | case CTRL('S'): | 
| 682 | > | case 'l':                       /* retrieve last view */ | 
| 683 | > | inpresflags |= DFL(DC_LASTVIEW); | 
| 684 | > | return; | 
| 685 | > | case 'f':                       /* frame view position */ | 
| 686 | > | if (!XQueryPointer(ourdisplay, gwind, &rootw, &childw, | 
| 687 | > | &rootx, &rooty, &wx, &wy, &statemask)) | 
| 688 | > | return;         /* on another screen */ | 
| 689 | > | sprintf(odev_args, "%.4f %.4f", (wx+.5)/odev.hres, | 
| 690 | > | 1.-(wy+.5)/odev.vres); | 
| 691 | > | inpresflags |= DFL(DC_FOCUS); | 
| 692 | > | return; | 
| 693 | > | case 'F':                       /* unfocus */ | 
| 694 | > | odev_args[0] = '\0'; | 
| 695 | > | inpresflags |= DFL(DC_FOCUS); | 
| 696 | > | return; | 
| 697 |  | case 'p':                       /* pause computation */ | 
| 698 | < | inpresflags |= DEV_WAIT; | 
| 698 | > | inpresflags |= DFL(DC_PAUSE); | 
| 699 |  | return; | 
| 700 |  | case 'v':                       /* spit out view */ | 
| 701 | < | inpresflags |= DEV_PUTVIEW; | 
| 701 | > | inpresflags |= DFL(DC_GETVIEW); | 
| 702 |  | return; | 
| 548 | – | case CTRL('Q'): | 
| 703 |  | case '\n': | 
| 704 |  | case '\r':                      /* resume computation */ | 
| 705 | < | inpresflags |= DEV_RESUME; | 
| 705 | > | inpresflags |= DFL(DC_RESUME); | 
| 706 |  | return; | 
| 707 |  | case CTRL('R'):                 /* redraw screen */ | 
| 708 |  | if (ncolors > 0) | 
| 710 |  | qtRedraw(0, 0, odev.hres, odev.vres); | 
| 711 |  | return; | 
| 712 |  | case CTRL('L'):                 /* refresh from server */ | 
| 713 | < | if (inpresflags & DEV_REDRAW) | 
| 713 | > | if (inpresflags & DFL(DC_REDRAW)) | 
| 714 |  | return; | 
| 715 |  | XClearWindow(ourdisplay, gwind); | 
| 716 |  | draw_grids(); | 
| 718 |  | qtCompost(100);                 /* unload the old tree */ | 
| 719 |  | if (ncolors > 0) | 
| 720 |  | new_ctab(ncolors); | 
| 721 | < | inpresflags |= DEV_REDRAW;      /* resend values from server */ | 
| 721 | > | inpresflags |= DFL(DC_REDRAW);  /* resend values from server */ | 
| 722 | > | rayqleft = 0;                   /* hold off update */ | 
| 723 |  | return; | 
| 724 | < | case CTRL('D'): | 
| 725 | < | case 'Q': | 
| 724 | > | case 'K':                       /* kill rtrace process(es) */ | 
| 725 | > | inpresflags |= DFL(DC_KILL); | 
| 726 | > | break; | 
| 727 | > | case 'R':                       /* restart rtrace */ | 
| 728 | > | inpresflags |= DFL(DC_RESTART); | 
| 729 | > | break; | 
| 730 | > | case 'C':                       /* clobber holodeck */ | 
| 731 | > | inpresflags |= DFL(DC_CLOBBER); | 
| 732 | > | break; | 
| 733 |  | case 'q':                       /* quit the program */ | 
| 734 | < | inpresflags |= DEV_SHUTDOWN; | 
| 734 | > | inpresflags |= DFL(DC_QUIT); | 
| 735 |  | return; | 
| 736 |  | default: | 
| 737 |  | XBell(ourdisplay, 0); | 
| 747 |  | if (odev.hres == 0 || odev.vres == 0) { /* first exposure */ | 
| 748 |  | odev.hres = eexp->width; | 
| 749 |  | odev.vres = eexp->height; | 
| 588 | – | inpresflags |= DEV_NEWSIZE; | 
| 750 |  | } | 
| 751 |  | qtRedraw(eexp->x, odev.vres - eexp->y - eexp->height, | 
| 752 |  | eexp->x + eexp->width, odev.vres - eexp->y); | 
| 760 |  | if (ersz->width == odev.hres && ersz->height == odev.vres) | 
| 761 |  | return; | 
| 762 |  |  | 
| 602 | – | if (odev.hres != 0 && odev.vres != 0) { | 
| 603 | – | odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres); | 
| 604 | – | odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres); | 
| 605 | – | inpresflags |= DEV_NEWVIEW; | 
| 606 | – | } | 
| 763 |  | odev.hres = ersz->width; | 
| 764 |  | odev.vres = ersz->height; | 
| 765 |  |  | 
| 766 | < | inpresflags |= DEV_NEWSIZE; | 
| 766 | > | odev.v.horiz = 2.*180./PI * atan(0.5/VIEWDIST*pwidth*odev.hres); | 
| 767 | > | odev.v.vert = 2.*180./PI * atan(0.5/VIEWDIST*pheight*odev.vres); | 
| 768 | > |  | 
| 769 | > | inpresflags |= DFL(DC_SETVIEW); | 
| 770 |  | } |