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