Actual source code: xinit.c

  1: /*
  2:    This file contains routines to open an X window display and window
  3:    This consists of a number of routines that set the various
  4:    fields in the Window structure, which is passed to
  5:    all of these routines.

  7:    Note that if you use the default visual and colormap, then you
  8:    can use these routines with any X toolkit that will give you the
  9:    Window id of the window that it is managing.  Use that instead of the
 10:    call to PetscDrawXiCreateWindow .  Similarly for the Display.
 11: */

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

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

 17: /*
 18:   PetscDrawXiOpenDisplay - Open and setup a display
 19: */
 20: static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin, const char display[])
 21: {
 22:   PetscFunctionBegin;
 23:   XiWin->disp = XOpenDisplay(display);
 24:   if (!XiWin->disp) {
 25:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open display on %s\n\
 26:     Make sure your COMPUTE NODES are authorized to connect \n\
 27:     to this X server and either your DISPLAY variable\n\
 28:     is set or you use the -display name option\n",
 29:             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:   PetscFunctionReturn(PETSC_SUCCESS);
 38: }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

257: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h)
258: {
259:   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;

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