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