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