Actual source code: xinit.c
petsc-3.7.3 2016-08-01
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: */
23: static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
24: {
26: XiWin->disp = XOpenDisplay(display);
27: if (!XiWin->disp) {
28: SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\
29: Make sure your COMPUTE NODES are authorized to connect \n\
30: to this X server and either your DISPLAY variable\n\
31: is set or you use the -display name option\n",display);
32: }
33: XiWin->screen = DefaultScreen(XiWin->disp);
34: XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen);
35: XiWin->depth = DefaultDepth(XiWin->disp,XiWin->screen);
36: XiWin->cmap = DefaultColormap(XiWin->disp,XiWin->screen);
37: XiWin->background = WhitePixel(XiWin->disp,XiWin->screen);
38: XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen);
39: return(0);
40: }
44: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
45: {
49: if (!XiWin) return(0);
50: PetscFree(XiWin->font);
51: if (XiWin->disp) {
52: #if defined(PETSC_HAVE_SETJMP_H)
53: jmp_buf jmpbuf;
54: PetscXIOErrorHandler xioerrhdl;
55: PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));
56: xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
57: if (!setjmp(PetscXIOErrorHandlerJumpBuf))
58: #endif
59: {
60: XFreeGC(XiWin->disp,XiWin->gc.set);
61: XCloseDisplay(XiWin->disp);
62: }
63: XiWin->disp = NULL;
64: #if defined(PETSC_HAVE_SETJMP_H)
65: (void)PetscSetXIOErrorHandler(xioerrhdl);
66: PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));
67: #endif
68: }
69: return(0);
70: }
72: /*
73: PetscDrawXiCreateGC - setup the GC structure
74: */
77: static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
78: {
79: XGCValues gcvalues; /* window graphics context values */
82: /* Set the graphics contexts */
83: /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
84: /* (do this with function GXcopy; GXset will automatically write 1) */
85: gcvalues.function = GXcopy;
86: gcvalues.foreground = fg;
87: XiWin->gc.cur_pix = fg;
88: XiWin->gc.set = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues);
89: if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context");
90: return(0);
91: }
93: /*
94: PetscDrawXiInit - basic setup the draw (display, graphics context, font)
95: */
98: PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
99: {
102: PetscDrawXiOpenDisplay(XiWin,display);
103: PetscDrawXiCreateGC(XiWin,XiWin->foreground);
104: PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);
105: return(0);
106: }
108: /*
109: This routine waits until the window is actually created or destroyed
110: Returns 0 if window is mapped; 1 if window is destroyed.
111: */
114: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
115: {
116: XEvent event;
119: while (1) {
120: XMaskEvent(XiWin->disp,ExposureMask|StructureNotifyMask,&event);
121: if (event.xany.window != XiWin->win) break;
122: else {
123: switch (event.type) {
124: case ConfigureNotify:
125: /* window has been moved or resized */
126: XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width;
127: XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
128: break;
129: case DestroyNotify:
130: PetscFunctionReturn(1);
131: case Expose:
132: return(0);
133: /* else ignore event */
134: }
135: }
136: }
137: return(0);
138: }
140: /*
141: Actually display a window at [x,y] with sizes (w,h)
142: */
145: static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h)
146: {
147: unsigned int wavail,havail;
148: XSizeHints size_hints;
149: XWindowAttributes in_window_attributes;
150: XSetWindowAttributes window_attributes;
151: unsigned int border_width = 0;
152: unsigned long backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen);
153: unsigned long wmask;
156: /* get the available widths */
157: wavail = DisplayWidth(XiWin->disp,XiWin->screen);
158: havail = DisplayHeight(XiWin->disp,XiWin->screen);
159: if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width");
160: if ((unsigned int)w > wavail) w = wavail;
161: if ((unsigned int)h > havail) h = havail;
163: if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
164: if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
165: x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
166: y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;
168: /* We need XCreateWindow since we may need an visual other than the default one */
169: XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes);
170: window_attributes.background_pixmap = None;
171: window_attributes.background_pixel = backgnd_pixel;
172: /* No border for now */
173: window_attributes.border_pixmap = None;
174: /*
175: window_attributes.border_pixel = border_pixel;
176: */
177: window_attributes.bit_gravity = in_window_attributes.bit_gravity;
178: window_attributes.win_gravity = in_window_attributes.win_gravity;
179: /* Backing store is too slow in color systems */
180: window_attributes.backing_store = NotUseful;
181: window_attributes.backing_pixel = backgnd_pixel;
182: window_attributes.save_under = 1;
183: window_attributes.event_mask = 0;
184: window_attributes.do_not_propagate_mask = 0;
185: window_attributes.override_redirect = 0;
186: window_attributes.colormap = XiWin->cmap;
187: /* None for cursor does NOT mean none, it means cursor of Parent */
188: window_attributes.cursor = None;
190: wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity |
191: CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect |
192: CWSaveUnder | CWEventMask | CWDontPropagate |
193: CWCursor | CWColormap;
195: XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes);
196: if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window");
198: /* set window manager hints */
199: {
200: XWMHints wm_hints;
201: XClassHint class_hints;
202: XTextProperty windowname,iconname;
204: if (label) XStringListToTextProperty(&label,1,&windowname);
205: else XStringListToTextProperty(&label,0,&windowname);
206: if (label) XStringListToTextProperty(&label,1,&iconname);
207: else XStringListToTextProperty(&label,0,&iconname);
209: wm_hints.initial_state = NormalState;
210: wm_hints.input = True;
211: wm_hints.flags = StateHint|InputHint;
213: /* These properties can be used by window managers to decide how to display a window */
214: class_hints.res_name = (char*)"petsc";
215: class_hints.res_class = (char*)"PETSc";
217: size_hints.x = x;
218: size_hints.y = y;
219: size_hints.min_width = 4*border_width;
220: size_hints.min_height = 4*border_width;
221: size_hints.width = w;
222: size_hints.height = h;
223: size_hints.flags = USPosition | USSize | PMinSize;
225: XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints);
226: XFree((void*)windowname.value);
227: XFree((void*)iconname.value);
228: }
230: /* make the window visible */
231: XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask);
232: XMapWindow(XiWin->disp,XiWin->win);
233: /* some window systems are cruel and interfere with the placement of
234: windows. We wait here for the window to be created or to die */
235: if (PetscDrawXiWaitMap(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed");
236: XSelectInput(XiWin->disp,XiWin->win,NoEventMask);
237: return(0);
238: }
242: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
243: {
247: PetscDrawSetColormap_X(XiWin,(Colormap)0);
248: PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);
249: XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
250: XClearWindow(XiWin->disp,XiWin->win);
251: return(0);
252: }
254: /*
255: A version from an already defined window
256: */
259: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
260: {
261: XWindowAttributes attributes;
262: PetscErrorCode ierr;
265: XiWin->win = win;
266: XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
267: PetscDrawSetColormap_X(XiWin,attributes.colormap);
268: return(0);
269: }
273: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin)
274: {
276: if (XiWin->drw) XFreePixmap(XiWin->disp,XiWin->drw);
277: XiWin->drw = XCreatePixmap(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),XiWin->w,XiWin->h,XiWin->depth);
278: PetscDrawXiSetPixVal(XiWin,XiWin->background);
279: XFillRectangle(XiWin->disp,XiWin->drw,XiWin->gc.set,0,0,XiWin->w,XiWin->h);
280: XSync(XiWin->disp,False);
281: return(0);
282: }
286: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X* XiWin,int w,int h)
287: {
288: XEvent event;
290: XSelectInput(XiWin->disp,XiWin->win,StructureNotifyMask);
291: XResizeWindow(XiWin->disp,XiWin->win,(unsigned int)w,(unsigned int)h);
292: XWindowEvent(XiWin->disp,XiWin->win,StructureNotifyMask,&event);
293: XSelectInput(XiWin->disp,XiWin->win,NoEventMask);
294: return(0);
295: }
299: PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin,int *x,int *y,int *w,int *h)
300: {
301: XWindowAttributes attributes;
302: Window root,parent,child;
303: int xx=0,yy=0;
304: unsigned int ww=0,hh=0,dummy;
306: if (XiWin->win) {
307: XGetGeometry(XiWin->disp,XiWin->win,&parent,&xx,&yy,&ww,&hh,&dummy,&dummy);
308: root = RootWindow(XiWin->disp,XiWin->screen);
309: if (!XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child)) {
310: XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
311: root = attributes.screen->root;
312: (void)XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child);
313: }
314: } else if (XiWin->drw) {
315: XGetGeometry(XiWin->disp,XiWin->drw,&root,&xx,&yy,&ww,&hh,&dummy,&dummy);
316: }
317: if (x) *x = xx;
318: if (y) *y = yy;
319: if (w) *w = (int)ww;
320: if (h) *h = (int)hh;
321: return(0);
322: }