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: 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: return 0;
38: }
40: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
41: {
42: if (!XiWin) return 0;
43: PetscFree(XiWin->font);
44: if (XiWin->disp) {
45: #if defined(PETSC_HAVE_SETJMP_H)
46: jmp_buf jmpbuf;
47: PetscXIOErrorHandler xioerrhdl;
48: PetscMemcpy(&jmpbuf, &PetscXIOErrorHandlerJumpBuf, sizeof(jmpbuf));
49: xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
50: if (!setjmp(PetscXIOErrorHandlerJumpBuf))
51: #endif
52: {
53: XFreeGC(XiWin->disp, XiWin->gc.set);
54: XCloseDisplay(XiWin->disp);
55: }
56: XiWin->disp = NULL;
57: #if defined(PETSC_HAVE_SETJMP_H)
58: (void)PetscSetXIOErrorHandler(xioerrhdl);
59: PetscMemcpy(&PetscXIOErrorHandlerJumpBuf, &jmpbuf, sizeof(jmpbuf));
60: #endif
61: }
62: return 0;
63: }
65: /*
66: PetscDrawXiCreateGC - setup the GC structure
67: */
68: static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin, PetscDrawXiPixVal fg)
69: {
70: XGCValues gcvalues; /* window graphics context values */
72: /* Set the graphics contexts */
73: /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
74: /* (do this with function GXcopy; GXset will automatically write 1) */
75: gcvalues.function = GXcopy;
76: gcvalues.foreground = fg;
77: XiWin->gc.cur_pix = fg;
78: XiWin->gc.set = XCreateGC(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), GCFunction | GCForeground, &gcvalues);
80: return 0;
81: }
83: /*
84: PetscDrawXiInit - basic setup the draw (display, graphics context, font)
85: */
86: PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin, const char display[])
87: {
88: PetscDrawXiOpenDisplay(XiWin, display);
89: PetscDrawXiCreateGC(XiWin, XiWin->foreground);
90: PetscDrawXiFontFixed(XiWin, 6, 10, &XiWin->font);
91: return 0;
92: }
94: /*
95: This routine waits until the window is actually created. If the window was
96: never mapped it generates an error
97: */
98: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
99: {
100: XEvent event;
102: while (1) {
103: XMaskEvent(XiWin->disp, ExposureMask | StructureNotifyMask, &event);
104: if (event.xany.window != XiWin->win) break;
105: else {
106: switch (event.type) {
107: case ConfigureNotify:
108: /* window has been moved or resized */
109: XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width;
110: XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
111: break;
112: case DestroyNotify:
113: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Window was not properly created");
114: case Expose:
115: return 0;
116: /* else ignore event */
117: }
118: }
119: }
120: return 0;
121: }
123: /*
124: Actually display a window at [x,y] with sizes (w,h)
125: */
126: static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin, char *label, int x, int y, int w, int h)
127: {
128: unsigned int wavail, havail;
129: XSizeHints size_hints;
130: XWindowAttributes in_window_attributes;
131: XSetWindowAttributes window_attributes;
132: unsigned int border_width = 0;
133: unsigned long backgnd_pixel = WhitePixel(XiWin->disp, XiWin->screen);
134: unsigned long wmask;
136: /* get the available widths */
137: wavail = DisplayWidth(XiWin->disp, XiWin->screen);
138: havail = DisplayHeight(XiWin->disp, XiWin->screen);
140: if ((unsigned int)w > wavail) w = wavail;
141: if ((unsigned int)h > havail) h = havail;
143: if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
144: if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
145: x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
146: y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;
148: /* We need XCreateWindow since we may need an visual other than the default one */
149: XGetWindowAttributes(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), &in_window_attributes);
150: window_attributes.background_pixmap = None;
151: window_attributes.background_pixel = backgnd_pixel;
152: /* No border for now */
153: window_attributes.border_pixmap = None;
154: /*
155: window_attributes.border_pixel = border_pixel;
156: */
157: window_attributes.bit_gravity = in_window_attributes.bit_gravity;
158: window_attributes.win_gravity = in_window_attributes.win_gravity;
159: /* Backing store is too slow in color systems */
160: window_attributes.backing_store = NotUseful;
161: window_attributes.backing_pixel = backgnd_pixel;
162: window_attributes.save_under = 1;
163: window_attributes.event_mask = 0;
164: window_attributes.do_not_propagate_mask = 0;
165: window_attributes.override_redirect = 0;
166: window_attributes.colormap = XiWin->cmap;
167: /* None for cursor does NOT mean none, it means cursor of Parent */
168: window_attributes.cursor = None;
170: wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWDontPropagate | CWCursor | CWColormap;
172: XiWin->win = XCreateWindow(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), x, y, w, h, border_width, XiWin->depth, InputOutput, XiWin->vis, wmask, &window_attributes);
175: /* set window manager hints */
176: {
177: XWMHints wm_hints;
178: XClassHint class_hints;
179: XTextProperty windowname, iconname;
181: if (label) XStringListToTextProperty(&label, 1, &windowname);
182: else XStringListToTextProperty(&label, 0, &windowname);
183: if (label) XStringListToTextProperty(&label, 1, &iconname);
184: else XStringListToTextProperty(&label, 0, &iconname);
186: wm_hints.initial_state = NormalState;
187: wm_hints.input = True;
188: wm_hints.flags = StateHint | InputHint;
190: /* These properties can be used by window managers to decide how to display a window */
191: class_hints.res_name = (char *)"petsc";
192: class_hints.res_class = (char *)"PETSc";
194: size_hints.x = x;
195: size_hints.y = y;
196: size_hints.min_width = 4 * border_width;
197: size_hints.min_height = 4 * border_width;
198: size_hints.width = w;
199: size_hints.height = h;
200: size_hints.flags = USPosition | USSize | PMinSize;
202: XSetWMProperties(XiWin->disp, XiWin->win, &windowname, &iconname, NULL, 0, &size_hints, &wm_hints, &class_hints);
203: XFree((void *)windowname.value);
204: XFree((void *)iconname.value);
205: }
207: /* make the window visible */
208: XSelectInput(XiWin->disp, XiWin->win, ExposureMask | StructureNotifyMask);
209: XMapWindow(XiWin->disp, XiWin->win);
210: /* some window systems are cruel and interfere with the placement of
211: windows. We wait here for the window to be created or to die */
212: PetscDrawXiWaitMap(XiWin);
213: XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
214: return 0;
215: }
217: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin, char *name, int x, int y, int nx, int ny)
218: {
219: PetscDrawSetColormap_X(XiWin, (Colormap)0);
220: PetscDrawXiDisplayWindow(XiWin, name, x, y, nx, ny);
221: XSetWindowBackground(XiWin->disp, XiWin->win, XiWin->background);
222: XClearWindow(XiWin->disp, XiWin->win);
223: return 0;
224: }
226: /*
227: A version from an already defined window
228: */
229: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin, Window win)
230: {
231: XWindowAttributes attributes;
233: XiWin->win = win;
234: XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
235: PetscDrawSetColormap_X(XiWin, attributes.colormap);
236: return 0;
237: }
239: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X *XiWin)
240: {
241: if (XiWin->drw) XFreePixmap(XiWin->disp, XiWin->drw);
242: XiWin->drw = XCreatePixmap(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), XiWin->w, XiWin->h, XiWin->depth);
243: PetscDrawXiSetPixVal(XiWin, XiWin->background);
244: XFillRectangle(XiWin->disp, XiWin->drw, XiWin->gc.set, 0, 0, XiWin->w, XiWin->h);
245: XSync(XiWin->disp, False);
246: return 0;
247: }
249: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h)
250: {
251: XEvent event;
252: XSelectInput(XiWin->disp, XiWin->win, StructureNotifyMask);
253: XResizeWindow(XiWin->disp, XiWin->win, (unsigned int)w, (unsigned int)h);
254: XWindowEvent(XiWin->disp, XiWin->win, StructureNotifyMask, &event);
255: XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
256: return 0;
257: }
259: PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin, int *x, int *y, int *w, int *h)
260: {
261: XWindowAttributes attributes;
262: Window root, parent, child;
263: int xx = 0, yy = 0;
264: unsigned int ww = 0, hh = 0, dummy;
265: if (XiWin->win) {
266: XGetGeometry(XiWin->disp, XiWin->win, &parent, &xx, &yy, &ww, &hh, &dummy, &dummy);
267: root = RootWindow(XiWin->disp, XiWin->screen);
268: if (!XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child)) {
269: XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
270: root = attributes.screen->root;
271: (void)XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child);
272: }
273: } else if (XiWin->drw) {
274: XGetGeometry(XiWin->disp, XiWin->drw, &root, &xx, &yy, &ww, &hh, &dummy, &dummy);
275: }
276: if (x) *x = xx;
277: if (y) *y = yy;
278: if (w) *w = (int)ww;
279: if (h) *h = (int)hh;
280: return 0;
281: }