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__ "PetscDrawSetSave_X" 281 PetscErrorCode PetscDrawSetSave_X(PetscDraw draw,const char *filename) 282 { 283 PetscErrorCode ierr; 284 #if defined(PETSC_HAVE_POPEN) 285 PetscMPIInt rank; 286 #endif 287 288 PetscFunctionBegin; 289 PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1); 290 #if defined(PETSC_HAVE_POPEN) 291 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 292 if (!rank) { 293 char command[PETSC_MAX_PATH_LEN]; 294 FILE *fd; 295 int err; 296 297 ierr = PetscMemzero(command,sizeof(command));CHKERRQ(ierr); 298 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"rm -fr %s %s.m4v",draw->savefilename,draw->savefilename);CHKERRQ(ierr); 299 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 300 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 301 ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"mkdir %s",draw->savefilename);CHKERRQ(ierr); 302 ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr); 303 ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr); 304 } 305 #endif 306 PetscFunctionReturn(0); 307 } 308 309 310 #if defined(PETSC_HAVE_AFTERIMAGE) 311 #include <afterimage.h> 312 313 /* String names of possible Afterimage formats */ 314 const char *PetscAfterImageFormats[] = { 315 ".Xpm", 316 ".Xpm.Z", 317 ".Xpm.gz", 318 ".Png", 319 ".Jpeg", 320 ".Xcf", /* Gimp format */ 321 ".Ppm", 322 ".Pnm", 323 "MS Windows Bitmap", 324 "MS Windows Icon", 325 "MS Windows Cursor", 326 ".Gif", 327 ".Tiff", 328 "Afterstep XMLScript", 329 "Scalable Vector Graphics (SVG)", 330 ".Xbm", 331 "Targa", 332 ".Pcx", 333 ".HTML", 334 "XML", 335 "Unknown" 336 }; 337 338 #undef __FUNCT__ 339 #define __FUNCT__ "PetscAfterimageStringToFormat" 340 static PetscErrorCode PetscAfterimageStringToFormat(const char *ext,ASImageFileTypes *format) 341 { 342 PetscInt i; 343 PetscErrorCode ierr; 344 PetscBool flg; 345 346 PetscFunctionBegin; 347 ierr = PetscStrcasecmp(".Jpg",ext,&flg);CHKERRQ(ierr); 348 if (flg) ext = ".Jpeg"; 349 for (i=0; i<sizeof(PetscAfterImageFormats)/sizeof(char**); i++) { 350 ierr = PetscStrcasecmp(PetscAfterImageFormats[i],ext,&flg);CHKERRQ(ierr); 351 if (flg) { 352 *format = (ASImageFileTypes)i; 353 PetscFunctionReturn(0); 354 } 355 } 356 *format = ASIT_Unknown; 357 PetscFunctionReturn(0); 358 } 359 360 #if defined(PETSC_HAVE_SAWS) 361 #include <petscviewersaws.h> 362 /* 363 The PetscAfterimage object and functions are used to maintain a list of file images created by Afterimage that can 364 be displayed by the SAWs webserver. 365 */ 366 typedef struct _P_PetscAfterimage *PetscAfterimage; 367 struct _P_PetscAfterimage { 368 PetscAfterimage next; 369 char *filename; 370 char *ext; 371 PetscInt cnt; 372 } ; 373 374 static PetscAfterimage afterimages = 0; 375 376 #undef __FUNCT__ 377 #define __FUNCT__ "PetscAfterimageDestroy" 378 static PetscErrorCode PetscAfterimageDestroy(void) 379 { 380 PetscErrorCode ierr; 381 PetscAfterimage afterimage,oafterimage = afterimages; 382 383 PetscFunctionBegin; 384 while (oafterimage) { 385 afterimage = oafterimage->next; 386 ierr = PetscFree(oafterimage->filename);CHKERRQ(ierr); 387 ierr = PetscFree(oafterimage->ext);CHKERRQ(ierr); 388 ierr = PetscFree(oafterimage);CHKERRQ(ierr); 389 oafterimage = afterimage; 390 } 391 PetscFunctionReturn(0); 392 } 393 394 #undef __FUNCT__ 395 #define __FUNCT__ "PetscAfterimageAdd" 396 static PetscErrorCode PetscAfterimageAdd(const char *filename,const char *ext,PetscInt cnt) 397 { 398 PetscErrorCode ierr; 399 PetscAfterimage afterimage,oafterimage = afterimages; 400 PetscBool flg; 401 402 PetscFunctionBegin; 403 if (oafterimage){ 404 ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr); 405 if (flg) { 406 oafterimage->cnt = cnt; 407 PetscFunctionReturn(0); 408 } 409 while (oafterimage->next) { 410 oafterimage = oafterimage->next; 411 ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr); 412 if (flg) { 413 oafterimage->cnt = cnt; 414 PetscFunctionReturn(0); 415 } 416 } 417 ierr = PetscNew(&afterimage);CHKERRQ(ierr); 418 oafterimage->next = afterimage; 419 } else { 420 ierr = PetscNew(&afterimage);CHKERRQ(ierr); 421 afterimages = afterimage; 422 } 423 ierr = PetscStrallocpy(filename,&afterimage->filename);CHKERRQ(ierr); 424 ierr = PetscStrallocpy(ext,&afterimage->ext);CHKERRQ(ierr); 425 afterimage->cnt = cnt; 426 ierr = PetscRegisterFinalize(PetscAfterimageDestroy);CHKERRQ(ierr); 427 PetscFunctionReturn(0); 428 } 429 430 #endif 431 432 #undef __FUNCT__ 433 #define __FUNCT__ "PetscDrawSave_X" 434 PetscErrorCode PetscDrawSave_X(PetscDraw draw) 435 { 436 PetscDraw_X *drawx = (PetscDraw_X*)draw->data; 437 XImage *image; 438 ASImage *asimage; 439 struct ASVisual *asv; 440 char filename[PETSC_MAX_PATH_LEN]; 441 PetscErrorCode ierr; 442 PetscMPIInt rank; 443 int depth; 444 ASImageFileTypes format; 445 446 PetscFunctionBegin; 447 if (!draw->savefilename) PetscFunctionReturn(0); 448 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 449 450 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 451 XSync(drawx->disp,True); 452 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 453 ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr); 454 455 ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr); 456 if (rank) goto finally; /* only process 0 handles the saving business */ 457 depth = DefaultDepth(drawx->disp,drawx->screen); 458 asv = create_asvisual(drawx->disp,drawx->screen,depth,NULL);if (!asv) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASVisual"); 459 image = XGetImage(drawx->disp,PetscDrawXiDrawable(drawx),0,0,drawx->w,drawx->h,AllPlanes,ZPixmap); 460 if (!image) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot XGetImage()"); 461 asimage = picture_ximage2asimage(asv,image,0,0);if (!asimage) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASImage"); 462 if (draw->savesinglefile) { 463 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s%s",draw->savefilename,draw->savefilename,draw->savefilenameext);CHKERRQ(ierr); 464 } else { 465 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s_%d%s",draw->savefilename,draw->savefilename,draw->savefilecount++,draw->savefilenameext);CHKERRQ(ierr); 466 } 467 ierr = PetscAfterimageStringToFormat(draw->savefilenameext,&format);CHKERRQ(ierr); 468 ASImage2file(asimage,0,filename,format,0); 469 #if defined(PETSC_HAVE_SAWS) 470 { 471 char body[4096]; 472 PetscAfterimage afterimage; 473 size_t len = 0; 474 475 ierr = PetscAfterimageAdd(draw->savefilename,draw->savefilenameext,draw->savefilecount-1);CHKERRQ(ierr); 476 afterimage = afterimages; 477 while (afterimage) { 478 if (draw->savesinglefile) { 479 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->ext);CHKERRQ(ierr); 480 } else { 481 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->cnt,afterimage->ext);CHKERRQ(ierr); 482 } 483 ierr = PetscStrlen(body,&len);CHKERRQ(ierr); 484 afterimage = afterimage->next; 485 } 486 ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr); 487 if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1)); 488 PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body)); 489 } 490 #endif 491 destroy_asvisual(asv,0); 492 XDestroyImage(image); 493 finally: 494 ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr); 495 PetscFunctionReturn(0); 496 } 497 498 /* 499 There are routines wanted by AfterImage for PNG files 500 */ 501 void crc32(void) {;} 502 void inflateReset(void) {;} 503 void deflateReset(void) {;} 504 void deflateInit2(void) {;} 505 void deflateInit2_(void) {;} 506 void deflate(void) {;} 507 void deflateEnd(void) {;} 508 509 #endif 510 511 512 513