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: }