Actual source code: xinit.c

petsc-3.10.5 2019-03-28
Report Typos and Errors

  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.

  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: */

 14:  #include <../src/sys/classes/draw/impls/x/ximpl.h>

 16: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);

 18: /*
 19:   PetscDrawXiOpenDisplay - Open and setup a display
 20: */
 21: static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
 22: {
 24:   XiWin->disp = XOpenDisplay(display);
 25:   if (!XiWin->disp) {
 26:     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\
 27:     Make sure your COMPUTE NODES are authorized to connect \n\
 28:     to this X server and either your DISPLAY variable\n\
 29:     is set or you use the -display name option\n",display);
 30:   }
 31:   XiWin->screen     = DefaultScreen(XiWin->disp);
 32:   XiWin->vis        = DefaultVisual(XiWin->disp,XiWin->screen);
 33:   XiWin->depth      = DefaultDepth(XiWin->disp,XiWin->screen);
 34:   XiWin->cmap       = DefaultColormap(XiWin->disp,XiWin->screen);
 35:   XiWin->background = WhitePixel(XiWin->disp,XiWin->screen);
 36:   XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen);
 37:   return(0);
 38: }

 40: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
 41: {

 45:   if (!XiWin) return(0);
 46:   PetscFree(XiWin->font);
 47:   if (XiWin->disp) {
 48: #if defined(PETSC_HAVE_SETJMP_H)
 49:     jmp_buf              jmpbuf;
 50:     PetscXIOErrorHandler xioerrhdl;
 51:     PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));
 52:     xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
 53:     if (!setjmp(PetscXIOErrorHandlerJumpBuf))
 54: #endif
 55:     {
 56:       XFreeGC(XiWin->disp,XiWin->gc.set);
 57:       XCloseDisplay(XiWin->disp);
 58:     }
 59:     XiWin->disp = NULL;
 60: #if defined(PETSC_HAVE_SETJMP_H)
 61:     (void)PetscSetXIOErrorHandler(xioerrhdl);
 62:     PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));
 63: #endif
 64:   }
 65:   return(0);
 66: }

 68: /*
 69:    PetscDrawXiCreateGC - setup the GC structure
 70: */
 71: static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
 72: {
 73:   XGCValues gcvalues;             /* window graphics context values */

 76:   /* Set the graphics contexts */
 77:   /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
 78:   /* (do this with function GXcopy; GXset will automatically write 1) */
 79:   gcvalues.function   = GXcopy;
 80:   gcvalues.foreground = fg;
 81:   XiWin->gc.cur_pix   = fg;
 82:   XiWin->gc.set       = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues);
 83:   if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context");
 84:   return(0);
 85: }

 87: /*
 88:    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
 89: */
 90: PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
 91: {
 94:   PetscDrawXiOpenDisplay(XiWin,display);
 95:   PetscDrawXiCreateGC(XiWin,XiWin->foreground);
 96:   PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);
 97:   return(0);
 98: }

100: /*
101:     This routine waits until the window is actually created or destroyed
102:     Returns 0 if window is mapped; 1 if window is destroyed.
103:  */
104: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
105: {
106:   XEvent event;

109:   while (1) {
110:     XMaskEvent(XiWin->disp,ExposureMask|StructureNotifyMask,&event);
111:     if (event.xany.window != XiWin->win) break;
112:     else {
113:       switch (event.type) {
114:       case ConfigureNotify:
115:         /* window has been moved or resized */
116:         XiWin->w = event.xconfigure.width  - 2 * event.xconfigure.border_width;
117:         XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
118:         break;
119:       case DestroyNotify:
120:         PetscFunctionReturn(1);
121:       case Expose:
122:         return(0);
123:         /* else ignore event */
124:       }
125:     }
126:   }
127:   return(0);
128: }

130: /*
131:     Actually display a window at [x,y] with sizes (w,h)
132: */
133: static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h)
134: {
135:   unsigned int         wavail,havail;
136:   XSizeHints           size_hints;
137:   XWindowAttributes    in_window_attributes;
138:   XSetWindowAttributes window_attributes;
139:   unsigned int         border_width = 0;
140:   unsigned long        backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen);
141:   unsigned long        wmask;

144:   /* get the available widths */
145:   wavail = DisplayWidth(XiWin->disp,XiWin->screen);
146:   havail = DisplayHeight(XiWin->disp,XiWin->screen);
147:   if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width");
148:   if ((unsigned int)w > wavail) w = wavail;
149:   if ((unsigned int)h > havail) h = havail;

151:   if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
152:   if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
153:   x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
154:   y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;

156:   /* We need XCreateWindow since we may need an visual other than the default one */
157:   XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes);
158:   window_attributes.background_pixmap = None;
159:   window_attributes.background_pixel  = backgnd_pixel;
160:   /* No border for now */
161:   window_attributes.border_pixmap     = None;
162:   /*
163:   window_attributes.border_pixel      = border_pixel;
164:   */
165:   window_attributes.bit_gravity       = in_window_attributes.bit_gravity;
166:   window_attributes.win_gravity       = in_window_attributes.win_gravity;
167:   /* Backing store is too slow in color systems */
168:   window_attributes.backing_store     = NotUseful;
169:   window_attributes.backing_pixel     = backgnd_pixel;
170:   window_attributes.save_under        = 1;
171:   window_attributes.event_mask        = 0;
172:   window_attributes.do_not_propagate_mask = 0;
173:   window_attributes.override_redirect = 0;
174:   window_attributes.colormap          = XiWin->cmap;
175:   /* None for cursor does NOT mean none, it means cursor of Parent */
176:   window_attributes.cursor            = None;

178:   wmask = CWBackPixmap | CWBackPixel    | CWBorderPixmap  | CWBitGravity |
179:           CWWinGravity | CWBackingStore | CWBackingPixel  | CWOverrideRedirect |
180:           CWSaveUnder  | CWEventMask    | CWDontPropagate |
181:           CWCursor     | CWColormap;

183:   XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes);
184:   if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window");

186:   /* set window manager hints */
187:   {
188:     XWMHints      wm_hints;
189:     XClassHint    class_hints;
190:     XTextProperty windowname,iconname;

192:     if (label) XStringListToTextProperty(&label,1,&windowname);
193:     else       XStringListToTextProperty(&label,0,&windowname);
194:     if (label) XStringListToTextProperty(&label,1,&iconname);
195:     else       XStringListToTextProperty(&label,0,&iconname);

197:     wm_hints.initial_state = NormalState;
198:     wm_hints.input         = True;
199:     wm_hints.flags         = StateHint|InputHint;

201:     /* These properties can be used by window managers to decide how to display a window */
202:     class_hints.res_name  = (char*)"petsc";
203:     class_hints.res_class = (char*)"PETSc";

205:     size_hints.x          = x;
206:     size_hints.y          = y;
207:     size_hints.min_width  = 4*border_width;
208:     size_hints.min_height = 4*border_width;
209:     size_hints.width      = w;
210:     size_hints.height     = h;
211:     size_hints.flags      = USPosition | USSize | PMinSize;

213:     XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints);
214:     XFree((void*)windowname.value);
215:     XFree((void*)iconname.value);
216:   }

218:   /* make the window visible */
219:   XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask);
220:   XMapWindow(XiWin->disp,XiWin->win);
221:   /* some window systems are cruel and interfere with the placement of
222:      windows.  We wait here for the window to be created or to die */
223:   if (PetscDrawXiWaitMap(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed");
224:   XSelectInput(XiWin->disp,XiWin->win,NoEventMask);
225:   return(0);
226: }

228: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
229: {

233:   PetscDrawSetColormap_X(XiWin,(Colormap)0);
234:   PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);
235:   XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
236:   XClearWindow(XiWin->disp,XiWin->win);
237:   return(0);
238: }

240: /*
241:    A version from an already defined window
242: */
243: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
244: {
245:   XWindowAttributes attributes;
246:   PetscErrorCode    ierr;

249:   XiWin->win = win;
250:   XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
251:   PetscDrawSetColormap_X(XiWin,attributes.colormap);
252:   return(0);
253: }

255: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin)
256: {
258:   if (XiWin->drw) XFreePixmap(XiWin->disp,XiWin->drw);
259:   XiWin->drw = XCreatePixmap(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),XiWin->w,XiWin->h,XiWin->depth);
260:   PetscDrawXiSetPixVal(XiWin,XiWin->background);
261:   XFillRectangle(XiWin->disp,XiWin->drw,XiWin->gc.set,0,0,XiWin->w,XiWin->h);
262:   XSync(XiWin->disp,False);
263:   return(0);
264: }

266: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X* XiWin,int w,int h)
267: {
268:   XEvent event;
270:   XSelectInput(XiWin->disp,XiWin->win,StructureNotifyMask);
271:   XResizeWindow(XiWin->disp,XiWin->win,(unsigned int)w,(unsigned int)h);
272:   XWindowEvent(XiWin->disp,XiWin->win,StructureNotifyMask,&event);
273:   XSelectInput(XiWin->disp,XiWin->win,NoEventMask);
274:   return(0);
275: }

277: PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin,int *x,int *y,int *w,int *h)
278: {
279:   XWindowAttributes attributes;
280:   Window            root,parent,child;
281:   int               xx=0,yy=0;
282:   unsigned int      ww=0,hh=0,dummy;
284:   if (XiWin->win) {
285:     XGetGeometry(XiWin->disp,XiWin->win,&parent,&xx,&yy,&ww,&hh,&dummy,&dummy);
286:     root = RootWindow(XiWin->disp,XiWin->screen);
287:     if (!XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child)) {
288:       XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
289:       root = attributes.screen->root;
290:       (void)XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child);
291:     }
292:   } else if (XiWin->drw) {
293:     XGetGeometry(XiWin->disp,XiWin->drw,&root,&xx,&yy,&ww,&hh,&dummy,&dummy);
294:   }
295:   if (x) *x = xx;
296:   if (y) *y = yy;
297:   if (w) *w = (int)ww;
298:   if (h) *h = (int)hh;
299:   return(0);
300: }