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