xref: /petsc/src/sys/classes/draw/impls/x/xinit.c (revision 481cee7b9d2ba1ac12db554daff76ad6aa1c27eb)
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