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