Actual source code: xinit.c
petsc-3.9.4 2018-09-11
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: }