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