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