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 #if defined(PETSC_HAVE_SAWS) 305 #include <petscviewersaws.h> 306 typedef struct _P_PetscGif *PetscGif; 307 struct _P_PetscGif { 308 PetscGif next; 309 char *filename; 310 } ; 311 312 static PetscGif gifs = 0; 313 314 #undef __FUNCT__ 315 #define __FUNCT__ "PetscGifDestroy" 316 static PetscErrorCode PetscGifDestroy(void) 317 { 318 PetscErrorCode ierr; 319 PetscGif gif,ogif = gifs; 320 321 PetscFunctionBegin; 322 while (ogif) { 323 gif = ogif->next; 324 ierr = PetscFree(ogif->filename);CHKERRQ(ierr); 325 ierr = PetscFree(ogif);CHKERRQ(ierr); 326 ogif = gif; 327 } 328 PetscFunctionReturn(0); 329 } 330 331 #undef __FUNCT__ 332 #define __FUNCT__ "PetscGifAdd" 333 static PetscErrorCode PetscGifAdd(const char *filename) 334 { 335 PetscErrorCode ierr; 336 PetscGif gif,ogif = gifs; 337 PetscBool flg; 338 339 PetscFunctionBegin; 340 if (ogif){ 341 ierr = PetscStrcmp(filename,ogif->filename,&flg);CHKERRQ(ierr); 342 if (flg) PetscFunctionReturn(0); 343 while (ogif->next) { 344 ogif = ogif->next; 345 ierr = PetscStrcmp(filename,ogif->filename,&flg);CHKERRQ(ierr); 346 if (flg) PetscFunctionReturn(0); 347 } 348 ierr = PetscNew(&gif);CHKERRQ(ierr); 349 ogif->next = gif; 350 } else { 351 ierr = PetscNew(&gif);CHKERRQ(ierr); 352 gifs = gif; 353 } 354 ierr = PetscStrallocpy(filename,&gif->filename);CHKERRQ(ierr); 355 ierr = PetscRegisterFinalize(PetscGifDestroy);CHKERRQ(ierr); 356 PetscFunctionReturn(0); 357 } 358 359 #endif 360 361 #undef __FUNCT__ 362 #define __FUNCT__ "PetscDrawSave_X" 363 PetscErrorCode PetscDrawSave_X(PetscDraw draw) 364 { 365 PetscDraw_X *drawx = (PetscDraw_X*)draw->data; 366 XImage *image; 367 ASImage *asimage; 368 struct ASVisual *asv; 369 char filename[PETSC_MAX_PATH_LEN]; 370 PetscErrorCode ierr; 371 PetscMPIInt rank; 372 int depth; 373 374 PetscFunctionBegin; 375 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr); 376 if (rank) PetscFunctionReturn(0); 377 if (!draw->savefilename) PetscFunctionReturn(0); 378 if (draw->savefilecount == -1) { 379 /* The first PetscDrawClear() should happen before any drawing has been done, hence do not save at the first PetscDrawClear() */ 380 draw->savefilecount++; 381 PetscFunctionReturn(0); 382 } 383 XSynchronize(drawx->disp, True); 384 depth = DefaultDepth( drawx->disp, drawx->screen ); 385 asv = create_asvisual(drawx->disp, drawx->screen, depth, NULL);if (!asv) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASVisual"); 386 387 image = XGetImage(drawx->disp, drawx->drw ? drawx->drw : drawx->win, 0, 0, drawx->w, drawx->h, AllPlanes, ZPixmap); 388 if (!image) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot XGetImage()");\ 389 asimage = picture_ximage2asimage (asv,image,0,0);if (!asimage) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASImage"); 390 if (draw->savesinglefile) { 391 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s.Gif",draw->savefilename,draw->savefilename);CHKERRQ(ierr); 392 } else { 393 ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s_%d.Gif",draw->savefilename,draw->savefilename,draw->savefilecount++);CHKERRQ(ierr); 394 } 395 ASImage2file(asimage, 0, filename,ASIT_Gif,0); 396 #if defined(PETSC_HAVE_SAWS) 397 { 398 char body[4096]; 399 PetscGif gif; 400 size_t len = 0; 401 402 ierr = PetscGifAdd(draw->savefilename);CHKERRQ(ierr); 403 gif = gifs; 404 while (gif) { 405 ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s.Gif\" alt=\"None\">",gif->filename,gif->filename);CHKERRQ(ierr); 406 ierr = PetscStrlen(body,&len);CHKERRQ(ierr); 407 gif = gif->next; 408 } 409 ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr); 410 if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1)); 411 PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body)); 412 } 413 #endif 414 415 XDestroyImage(image); 416 destroy_asvisual(asv,0); 417 PetscFunctionReturn(0); 418 } 419 /* 420 There are routines wanted by AfterImage for PNG files 421 */ 422 void crc32(void) {;} 423 void inflateReset(void) {;} 424 void deflateReset(void) {;} 425 void deflateInit2(void) {;} 426 void deflateInit2_(void) {;} 427 void deflate(void) {;} 428 void deflateEnd(void) {;} 429 430 #endif 431 432 433 434