1 2 /* 3 This file contains routines to open an X window display and window 4 This consists of a number of routines that set the various 5 fields in the Window structure, which is passed to 6 all of these routines. 7 8 Note that if you use the default visual and colormap, then you 9 can use these routines with any X toolkit that will give you the 10 Window id of the window that it is managing. Use that instead of the 11 call to PetscDrawXiCreateWindow . Similarly for the Display. 12 */ 13 14 #include <../src/sys/classes/draw/impls/x/ximpl.h> 15 16 extern PetscErrorCode PetscDrawXi_wait_map(PetscDraw_X*); 17 extern PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X*,int,int,PetscDrawXiFont**); 18 extern PetscErrorCode PetscDrawXiInitCmap(PetscDraw_X*); 19 extern PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap); 20 21 /* 22 PetscDrawXiOpenDisplay - Open and setup a display 23 */ 24 #undef __FUNCT__ 25 #define __FUNCT__ "PetscDrawXiOpenDisplay" 26 PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[]) 27 { 28 PetscFunctionBegin; 29 XiWin->disp = XOpenDisplay(display); 30 if (!XiWin->disp) { 31 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\ 32 Make sure your COMPUTE NODES are authorized to connect \n\ 33 to this X server and either your DISPLAY variable\n\ 34 is set or you use the -display name option\n",display); 35 } 36 XiWin->screen = DefaultScreen(XiWin->disp); 37 XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen); 38 XiWin->depth = DefaultDepth(XiWin->disp,XiWin->screen); 39 XiWin->cmap = DefaultColormap(XiWin->disp,XiWin->screen); 40 XiWin->background = WhitePixel(XiWin->disp,XiWin->screen); 41 XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen); 42 PetscFunctionReturn(0); 43 } 44 45 #undef __FUNCT__ 46 #define __FUNCT__ "PetscDrawXiClose" 47 PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin) 48 { 49 PetscErrorCode ierr; 50 51 PetscFunctionBegin; 52 if (!XiWin) PetscFunctionReturn(0); 53 ierr = PetscFree(XiWin->font);CHKERRQ(ierr); 54 if (XiWin->disp) { 55 #if defined(PETSC_HAVE_SETJMP_H) 56 jmp_buf jmpbuf; 57 PetscXIOErrorHandler xioerrhdl; 58 ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr); 59 xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump); 60 if (!setjmp(PetscXIOErrorHandlerJumpBuf)) 61 #endif 62 { 63 XFreeGC(XiWin->disp,XiWin->gc.set); 64 XCloseDisplay(XiWin->disp); 65 } 66 XiWin->disp = NULL; 67 #if defined(PETSC_HAVE_SETJMP_H) 68 (void)PetscSetXIOErrorHandler(xioerrhdl); 69 ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr); 70 #endif 71 } 72 PetscFunctionReturn(0); 73 } 74 75 /* 76 PetscDrawXiSetGC - setup the GC structure 77 */ 78 #undef __FUNCT__ 79 #define __FUNCT__ "PetscDrawXiSetGC" 80 PetscErrorCode PetscDrawXiSetGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg) 81 { 82 XGCValues gcvalues; /* window graphics context values */ 83 84 PetscFunctionBegin; 85 /* Set the graphics contexts */ 86 /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */ 87 /* (do this with function GXcopy; GXset will automatically write 1) */ 88 gcvalues.function = GXcopy; 89 gcvalues.foreground = fg; 90 XiWin->gc.cur_pix = fg; 91 XiWin->gc.set = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues); 92 if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context"); 93 PetscFunctionReturn(0); 94 } 95 96 /* 97 PetscDrawXiInit - basic setup the draw (display, graphics context, font) 98 */ 99 #undef __FUNCT__ 100 #define __FUNCT__ "PetscDrawXiInit" 101 PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[]) 102 { 103 PetscErrorCode ierr; 104 PetscFunctionBegin; 105 ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr); 106 ierr = PetscDrawXiSetGC(XiWin,XiWin->foreground);CHKERRQ(ierr); 107 ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr); 108 PetscFunctionReturn(0); 109 } 110 111 /* 112 Actually display a window at [x,y] with sizes (w,h) 113 */ 114 #undef __FUNCT__ 115 #define __FUNCT__ "PetscDrawXiDisplayWindow" 116 PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h) 117 { 118 unsigned int wavail,havail; 119 XSizeHints size_hints; 120 XWindowAttributes in_window_attributes; 121 XSetWindowAttributes window_attributes; 122 unsigned int border_width = 0; 123 unsigned long backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen); 124 unsigned long wmask; 125 126 PetscFunctionBegin; 127 /* get the available widths */ 128 wavail = DisplayWidth(XiWin->disp,XiWin->screen); 129 havail = DisplayHeight(XiWin->disp,XiWin->screen); 130 if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width"); 131 if ((unsigned int)w > wavail) w = wavail; 132 if ((unsigned int)h > havail) h = havail; 133 134 if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x); 135 if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y); 136 x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x; 137 y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y; 138 139 /* We need XCreateWindow since we may need an visual other than the default one */ 140 XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes); 141 window_attributes.background_pixmap = None; 142 window_attributes.background_pixel = backgnd_pixel; 143 /* No border for now */ 144 window_attributes.border_pixmap = None; 145 /* 146 window_attributes.border_pixel = border_pixel; 147 */ 148 window_attributes.bit_gravity = in_window_attributes.bit_gravity; 149 window_attributes.win_gravity = in_window_attributes.win_gravity; 150 /* Backing store is too slow in color systems */ 151 window_attributes.backing_store = NotUseful; 152 window_attributes.backing_pixel = backgnd_pixel; 153 window_attributes.save_under = 1; 154 window_attributes.event_mask = 0; 155 window_attributes.do_not_propagate_mask = 0; 156 window_attributes.override_redirect = 0; 157 window_attributes.colormap = XiWin->cmap; 158 /* None for cursor does NOT mean none, it means cursor of Parent */ 159 window_attributes.cursor = None; 160 161 wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | 162 CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | 163 CWSaveUnder | CWEventMask | CWDontPropagate | 164 CWCursor | CWColormap; 165 166 XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes); 167 if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window"); 168 169 /* set window manager hints */ 170 { 171 XWMHints wm_hints; 172 XClassHint class_hints; 173 XTextProperty windowname,iconname; 174 175 if (label) XStringListToTextProperty(&label,1,&windowname); 176 else XStringListToTextProperty(&label,0,&windowname); 177 if (label) XStringListToTextProperty(&label,1,&iconname); 178 else XStringListToTextProperty(&label,0,&iconname); 179 180 wm_hints.initial_state = NormalState; 181 wm_hints.input = True; 182 wm_hints.flags = StateHint|InputHint; 183 184 /* These properties can be used by window managers to decide how to display a window */ 185 class_hints.res_name = (char*)"petsc"; 186 class_hints.res_class = (char*)"PETSc"; 187 188 size_hints.x = x; 189 size_hints.y = y; 190 size_hints.min_width = 4*border_width; 191 size_hints.min_height = 4*border_width; 192 size_hints.width = w; 193 size_hints.height = h; 194 size_hints.flags = USPosition | USSize | PMinSize; 195 196 XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints); 197 XFree((void*)windowname.value); 198 XFree((void*)iconname.value); 199 } 200 201 /* make the window visible */ 202 XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask); 203 XMapWindow(XiWin->disp,XiWin->win); 204 205 /* some window systems are cruel and interfere with the placement of 206 windows. We wait here for the window to be created or to die */ 207 if (PetscDrawXi_wait_map(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed"); 208 PetscFunctionReturn(0); 209 } 210 211 #undef __FUNCT__ 212 #define __FUNCT__ "PetscDrawXiQuickWindow" 213 PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny) 214 { 215 Window root; 216 unsigned int w,h,dummy; 217 PetscErrorCode ierr; 218 219 PetscFunctionBegin; 220 ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr); 221 ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr); 222 XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background); 223 XClearWindow(XiWin->disp,XiWin->win); 224 225 XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy); 226 XiWin->x = x; 227 XiWin->y = y; 228 XiWin->w = (int)w; 229 XiWin->h = (int)h; 230 PetscFunctionReturn(0); 231 } 232 233 /* 234 A version from an already defined window 235 */ 236 #undef __FUNCT__ 237 #define __FUNCT__ "PetscDrawXiQuickWindowFromWindow" 238 PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win) 239 { 240 Window root; 241 int x,y; 242 unsigned int w,h,dummy; 243 XWindowAttributes attributes; 244 PetscErrorCode ierr; 245 246 PetscFunctionBegin; 247 XiWin->win = win; 248 XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes); 249 ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr); 250 251 XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy); 252 XiWin->x = x; 253 XiWin->y = y; 254 XiWin->w = (int)w; 255 XiWin->h = (int)h; 256 PetscFunctionReturn(0); 257 } 258 259 /* 260 PetscDrawXiSetWindowLabel - Sets new label in open window. 261 */ 262 #undef __FUNCT__ 263 #define __FUNCT__ "PetscDrawXiSetWindowLabel" 264 PetscErrorCode PetscDrawXiSetWindowLabel(PetscDraw_X *XiWin,char *label) 265 { 266 XTextProperty prop; 267 size_t len; 268 PetscErrorCode ierr; 269 270 PetscFunctionBegin; 271 ierr = PetscStrlen(label,&len);CHKERRQ(ierr); 272 XGetWMName(XiWin->disp,XiWin->win,&prop); 273 prop.value = (unsigned char*)label; 274 prop.nitems = (long)len; 275 XSetWMName(XiWin->disp,XiWin->win,&prop); 276 PetscFunctionReturn(0); 277 } 278 279 #undef __FUNCT__ 280 #define __FUNCT__ "PetscDrawXiSetToBackground" 281 PetscErrorCode PetscDrawXiSetToBackground(PetscDraw_X *XiWin) 282 { 283 PetscFunctionBegin; 284 if (XiWin->gc.cur_pix != XiWin->background) { 285 XSetForeground(XiWin->disp,XiWin->gc.set,XiWin->background); 286 XiWin->gc.cur_pix = XiWin->background; 287 } 288 PetscFunctionReturn(0); 289 290 } 291 292 #undef __FUNCT__ 293 #define __FUNCT__ "PetscDrawSetSave_X" 294 PetscErrorCode PetscDrawSetSave_X(PetscDraw draw,const char *filename) 295 { 296 PetscErrorCode ierr; 297 #if defined(PETSC_HAVE_POPEN) 298 PetscMPIInt rank; 299 #endif 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 303 #if defined(PETSC_HAVE_POPEN) 304 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 305 if (!rank) { 306 char command[PETSC_MAX_PATH_LEN]; 307 FILE *fd; 308 int err; 309 310 ierr = PetscMemzero(command,sizeof(command));CHKERRQ(ierr); 311 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"rm -fr %s %s.m4v",draw->savefilename,draw->savefilename);CHKERRQ(ierr); 312 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 313 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 314 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"mkdir %s",draw->savefilename);CHKERRQ(ierr); 315 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 316 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 317 } 318 #endif 319 PetscFunctionReturn(0); 320 } 321 322 323 #if defined(PETSC_HAVE_AFTERIMAGE) 324 #include <afterimage.h> 325 326 /* String names of possible Afterimage formats */ 327 const char *PetscAfterImageFormats[] = { 328 ".Xpm", 329 ".Xpm.Z", 330 ".Xpm.gz", 331 ".Png", 332 ".Jpeg", 333 ".Xcf", /* Gimp format */ 334 ".Ppm", 335 ".Pnm", 336 "MS Windows Bitmap", 337 "MS Windows Icon", 338 "MS Windows Cursor", 339 ".Gif", 340 ".Tiff", 341 "Afterstep XMLScript", 342 "Scalable Vector Graphics (SVG)", 343 ".Xbm", 344 "Targa", 345 ".Pcx", 346 ".HTML", 347 "XML", 348 "Unknown" 349 }; 350 351 #undef __FUNCT__ 352 #define __FUNCT__ "PetscAfterimageStringToFormat" 353 static PetscErrorCode PetscAfterimageStringToFormat(const char *ext,ASImageFileTypes *format) 354 { 355 PetscInt i; 356 PetscErrorCode ierr; 357 PetscBool flg; 358 359 PetscFunctionBegin; 360 ierr = PetscStrcasecmp(".Jpg",ext,&flg);CHKERRQ(ierr); 361 if (flg) ext = ".Jpeg"; 362 for (i=0; i<sizeof(PetscAfterImageFormats)/sizeof(char**); i++) { 363 ierr = PetscStrcasecmp(PetscAfterImageFormats[i],ext,&flg);CHKERRQ(ierr); 364 if (flg) { 365 *format = (ASImageFileTypes)i; 366 PetscFunctionReturn(0); 367 } 368 } 369 *format = ASIT_Unknown; 370 PetscFunctionReturn(0); 371 } 372 373 #if defined(PETSC_HAVE_SAWS) 374 #include <petscviewersaws.h> 375 /* 376 The PetscAfterimage object and functions are used to maintain a list of file images created by Afterimage that can 377 be displayed by the SAWs webserver. 378 */ 379 typedef struct _P_PetscAfterimage *PetscAfterimage; 380 struct _P_PetscAfterimage { 381 PetscAfterimage next; 382 char *filename; 383 char *ext; 384 PetscInt cnt; 385 } ; 386 387 static PetscAfterimage afterimages = 0; 388 389 #undef __FUNCT__ 390 #define __FUNCT__ "PetscAfterimageDestroy" 391 static PetscErrorCode PetscAfterimageDestroy(void) 392 { 393 PetscErrorCode ierr; 394 PetscAfterimage afterimage,oafterimage = afterimages; 395 396 PetscFunctionBegin; 397 while (oafterimage) { 398 afterimage = oafterimage->next; 399 ierr = PetscFree(oafterimage->filename);CHKERRQ(ierr); 400 ierr = PetscFree(oafterimage->ext);CHKERRQ(ierr); 401 ierr = PetscFree(oafterimage);CHKERRQ(ierr); 402 oafterimage = afterimage; 403 } 404 PetscFunctionReturn(0); 405 } 406 407 #undef __FUNCT__ 408 #define __FUNCT__ "PetscAfterimageAdd" 409 static PetscErrorCode PetscAfterimageAdd(const char *filename,const char *ext,PetscInt cnt) 410 { 411 PetscErrorCode ierr; 412 PetscAfterimage afterimage,oafterimage = afterimages; 413 PetscBool flg; 414 415 PetscFunctionBegin; 416 if (oafterimage){ 417 ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr); 418 if (flg) { 419 oafterimage->cnt = cnt; 420 PetscFunctionReturn(0); 421 } 422 while (oafterimage->next) { 423 oafterimage = oafterimage->next; 424 ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr); 425 if (flg) { 426 oafterimage->cnt = cnt; 427 PetscFunctionReturn(0); 428 } 429 } 430 ierr = PetscNew(&afterimage);CHKERRQ(ierr); 431 oafterimage->next = afterimage; 432 } else { 433 ierr = PetscNew(&afterimage);CHKERRQ(ierr); 434 afterimages = afterimage; 435 } 436 ierr = PetscStrallocpy(filename,&afterimage->filename);CHKERRQ(ierr); 437 ierr = PetscStrallocpy(ext,&afterimage->ext);CHKERRQ(ierr); 438 afterimage->cnt = cnt; 439 ierr = PetscRegisterFinalize(PetscAfterimageDestroy);CHKERRQ(ierr); 440 PetscFunctionReturn(0); 441 } 442 443 #endif 444 445 #undef __FUNCT__ 446 #define __FUNCT__ "PetscDrawSave_X" 447 PetscErrorCode PetscDrawSave_X(PetscDraw draw) 448 { 449 PetscDraw_X *drawx = (PetscDraw_X*)draw->data; 450 XImage *image; 451 ASImage *asimage; 452 struct ASVisual *asv; 453 char filename[PETSC_MAX_PATH_LEN]; 454 PetscErrorCode ierr; 455 PetscMPIInt rank; 456 int depth; 457 ASImageFileTypes format; 458 459 PetscFunctionBegin; 460 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 461 if (rank) PetscFunctionReturn(0); 462 if (!draw->savefilename) PetscFunctionReturn(0); 463 if (draw->savefilecount == -1) { 464 /* The first PetscDrawClear() should happen before any drawing has been done, hence do not save at the first PetscDrawClear() */ 465 draw->savefilecount++; 466 PetscFunctionReturn(0); 467 } 468 XSynchronize(drawx->disp, True); 469 depth = DefaultDepth( drawx->disp, drawx->screen ); 470 asv = create_asvisual(drawx->disp, drawx->screen, depth, NULL);if (!asv) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASVisual"); 471 472 image = XGetImage(drawx->disp, drawx->drw ? drawx->drw : drawx->win, 0, 0, drawx->w, drawx->h, AllPlanes, ZPixmap); 473 if (!image) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot XGetImage()"); 474 asimage = picture_ximage2asimage (asv,image,0,0);if (!asimage) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASImage"); 475 if (draw->savesinglefile) { 476 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s%s",draw->savefilename,draw->savefilename,draw->savefilenameext);CHKERRQ(ierr); 477 } else { 478 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s_%d%s",draw->savefilename,draw->savefilename,draw->savefilecount++,draw->savefilenameext);CHKERRQ(ierr); 479 } 480 ierr = PetscAfterimageStringToFormat(draw->savefilenameext,&format);CHKERRQ(ierr); 481 ASImage2file(asimage, 0, filename,format,0); 482 #if defined(PETSC_HAVE_SAWS) 483 { 484 char body[4096]; 485 PetscAfterimage afterimage; 486 size_t len = 0; 487 488 ierr = PetscAfterimageAdd(draw->savefilename,draw->savefilenameext,draw->savefilecount-1);CHKERRQ(ierr); 489 afterimage = afterimages; 490 while (afterimage) { 491 if (draw->savesinglefile) { 492 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->ext);CHKERRQ(ierr); 493 } else { 494 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->cnt,afterimage->ext);CHKERRQ(ierr); 495 } 496 ierr = PetscStrlen(body,&len);CHKERRQ(ierr); 497 afterimage = afterimage->next; 498 } 499 ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr); 500 if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1)); 501 PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body)); 502 } 503 #endif 504 505 XDestroyImage(image); 506 destroy_asvisual(asv,0); 507 PetscFunctionReturn(0); 508 } 509 /* 510 There are routines wanted by AfterImage for PNG files 511 */ 512 void crc32(void) {;} 513 void inflateReset(void) {;} 514 void deflateReset(void) {;} 515 void deflateInit2(void) {;} 516 void deflateInit2_(void) {;} 517 void deflate(void) {;} 518 void deflateEnd(void) {;} 519 520 #endif 521 522 523 524