Actual source code: xinit.c


  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: {
 23:   PetscFunctionBegin;
 24:   XiWin->disp = XOpenDisplay(display);
 25:   if (!XiWin->disp) {
 26:     SETERRQ(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",
 30:             display);
 31:   }
 32:   XiWin->screen     = DefaultScreen(XiWin->disp);
 33:   XiWin->vis        = DefaultVisual(XiWin->disp, XiWin->screen);
 34:   XiWin->depth      = DefaultDepth(XiWin->disp, XiWin->screen);
 35:   XiWin->cmap       = DefaultColormap(XiWin->disp, XiWin->screen);
 36:   XiWin->background = WhitePixel(XiWin->disp, XiWin->screen);
 37:   XiWin->foreground = BlackPixel(XiWin->disp, XiWin->screen);
 38:   PetscFunctionReturn(PETSC_SUCCESS);
 39: }

 41: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
 42: {
 43:   PetscFunctionBegin;
 44:   if (!XiWin) PetscFunctionReturn(PETSC_SUCCESS);
 45:   PetscCall(PetscFree(XiWin->font));
 46:   if (XiWin->disp) {
 47: #if defined(PETSC_HAVE_SETJMP_H)
 48:     jmp_buf              jmpbuf;
 49:     PetscXIOErrorHandler xioerrhdl;
 50:     PetscCall(PetscMemcpy(&jmpbuf, &PetscXIOErrorHandlerJumpBuf, sizeof(jmpbuf)));
 51:     xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
 52:     if (!setjmp(PetscXIOErrorHandlerJumpBuf))
 53: #endif
 54:     {
 55:       XFreeGC(XiWin->disp, XiWin->gc.set);
 56:       XCloseDisplay(XiWin->disp);
 57:     }
 58:     XiWin->disp = NULL;
 59: #if defined(PETSC_HAVE_SETJMP_H)
 60:     (void)PetscSetXIOErrorHandler(xioerrhdl);
 61:     PetscCall(PetscMemcpy(&PetscXIOErrorHandlerJumpBuf, &jmpbuf, sizeof(jmpbuf)));
 62: #endif
 63:   }
 64:   PetscFunctionReturn(PETSC_SUCCESS);
 65: }

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

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

 86: /*
 87:    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
 88: */
 89: PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin, const char display[])
 90: {
 91:   PetscFunctionBegin;
 92:   PetscCall(PetscDrawXiOpenDisplay(XiWin, display));
 93:   PetscCall(PetscDrawXiCreateGC(XiWin, XiWin->foreground));
 94:   PetscCall(PetscDrawXiFontFixed(XiWin, 6, 10, &XiWin->font));
 95:   PetscFunctionReturn(PETSC_SUCCESS);
 96: }

 98: /*
 99:     This routine waits until the window is actually created. If the window was
100:     never mapped it generates an error
101: */
102: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
103: {
104:   XEvent event;

106:   PetscFunctionBegin;
107:   while (1) {
108:     XMaskEvent(XiWin->disp, ExposureMask | StructureNotifyMask, &event);
109:     if (event.xany.window != XiWin->win) break;
110:     else {
111:       switch (event.type) {
112:       case ConfigureNotify:
113:         /* window has been moved or resized */
114:         XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width;
115:         XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
116:         break;
117:       case DestroyNotify:
118:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Window was not properly created");
119:       case Expose:
120:         PetscFunctionReturn(PETSC_SUCCESS);
121:         /* else ignore event */
122:       }
123:     }
124:   }
125:   PetscFunctionReturn(PETSC_SUCCESS);
126: }

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

141:   PetscFunctionBegin;
142:   /* get the available widths */
143:   wavail = DisplayWidth(XiWin->disp, XiWin->screen);
144:   havail = DisplayHeight(XiWin->disp, XiWin->screen);
145:   PetscCheck(w > 0 && h > 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "X Window display has invalid height or width");
146:   if ((unsigned int)w > wavail) w = wavail;
147:   if ((unsigned int)h > havail) h = havail;

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

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

176:   wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWDontPropagate | CWCursor | CWColormap;

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

181:   /* set window manager hints */
182:   {
183:     XWMHints      wm_hints;
184:     XClassHint    class_hints;
185:     XTextProperty windowname, iconname;

187:     if (label) XStringListToTextProperty(&label, 1, &windowname);
188:     else XStringListToTextProperty(&label, 0, &windowname);
189:     if (label) XStringListToTextProperty(&label, 1, &iconname);
190:     else XStringListToTextProperty(&label, 0, &iconname);

192:     wm_hints.initial_state = NormalState;
193:     wm_hints.input         = True;
194:     wm_hints.flags         = StateHint | InputHint;

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

200:     size_hints.x          = x;
201:     size_hints.y          = y;
202:     size_hints.min_width  = 4 * border_width;
203:     size_hints.min_height = 4 * border_width;
204:     size_hints.width      = w;
205:     size_hints.height     = h;
206:     size_hints.flags      = USPosition | USSize | PMinSize;

208:     XSetWMProperties(XiWin->disp, XiWin->win, &windowname, &iconname, NULL, 0, &size_hints, &wm_hints, &class_hints);
209:     XFree((void *)windowname.value);
210:     XFree((void *)iconname.value);
211:   }

213:   /* make the window visible */
214:   XSelectInput(XiWin->disp, XiWin->win, ExposureMask | StructureNotifyMask);
215:   XMapWindow(XiWin->disp, XiWin->win);
216:   /* some window systems are cruel and interfere with the placement of
217:      windows.  We wait here for the window to be created or to die */
218:   PetscCall(PetscDrawXiWaitMap(XiWin));
219:   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
220:   PetscFunctionReturn(PETSC_SUCCESS);
221: }

223: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin, char *name, int x, int y, int nx, int ny)
224: {
225:   PetscFunctionBegin;
226:   PetscCall(PetscDrawSetColormap_X(XiWin, (Colormap)0));
227:   PetscCall(PetscDrawXiDisplayWindow(XiWin, name, x, y, nx, ny));
228:   XSetWindowBackground(XiWin->disp, XiWin->win, XiWin->background);
229:   XClearWindow(XiWin->disp, XiWin->win);
230:   PetscFunctionReturn(PETSC_SUCCESS);
231: }

233: /*
234:    A version from an already defined window
235: */
236: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin, Window win)
237: {
238:   XWindowAttributes attributes;

240:   PetscFunctionBegin;
241:   XiWin->win = win;
242:   XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
243:   PetscCall(PetscDrawSetColormap_X(XiWin, attributes.colormap));
244:   PetscFunctionReturn(PETSC_SUCCESS);
245: }

247: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X *XiWin)
248: {
249:   PetscFunctionBegin;
250:   if (XiWin->drw) XFreePixmap(XiWin->disp, XiWin->drw);
251:   XiWin->drw = XCreatePixmap(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), XiWin->w, XiWin->h, XiWin->depth);
252:   PetscDrawXiSetPixVal(XiWin, XiWin->background);
253:   XFillRectangle(XiWin->disp, XiWin->drw, XiWin->gc.set, 0, 0, XiWin->w, XiWin->h);
254:   XSync(XiWin->disp, False);
255:   PetscFunctionReturn(PETSC_SUCCESS);
256: }

258: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h)
259: {
260:   XEvent event;
261:   PetscFunctionBegin;
262:   XSelectInput(XiWin->disp, XiWin->win, StructureNotifyMask);
263:   XResizeWindow(XiWin->disp, XiWin->win, (unsigned int)w, (unsigned int)h);
264:   XWindowEvent(XiWin->disp, XiWin->win, StructureNotifyMask, &event);
265:   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
266:   PetscFunctionReturn(PETSC_SUCCESS);
267: }

269: PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin, int *x, int *y, int *w, int *h)
270: {
271:   XWindowAttributes attributes;
272:   Window            root, parent, child;
273:   int               xx = 0, yy = 0;
274:   unsigned int      ww = 0, hh = 0, dummy;
275:   PetscFunctionBegin;
276:   if (XiWin->win) {
277:     XGetGeometry(XiWin->disp, XiWin->win, &parent, &xx, &yy, &ww, &hh, &dummy, &dummy);
278:     root = RootWindow(XiWin->disp, XiWin->screen);
279:     if (!XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child)) {
280:       XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
281:       root = attributes.screen->root;
282:       (void)XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child);
283:     }
284:   } else if (XiWin->drw) {
285:     XGetGeometry(XiWin->disp, XiWin->drw, &root, &xx, &yy, &ww, &hh, &dummy, &dummy);
286:   }
287:   if (x) *x = xx;
288:   if (y) *y = yy;
289:   if (w) *w = (int)ww;
290:   if (h) *h = (int)hh;
291:   PetscFunctionReturn(PETSC_SUCCESS);
292: }