1
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.
7
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 */
13
14 #include <../src/sys/classes/draw/impls/x/ximpl.h>
15
16 PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);
17
18 /*
19 PetscDrawXiOpenDisplay - Open and setup a display
20 */
PetscDrawXiOpenDisplay(PetscDraw_X * XiWin,const char display[])21 static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
22 {
23 PetscFunctionBegin;
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 PetscFunctionReturn(0);
38 }
39
PetscDrawXiClose(PetscDraw_X * XiWin)40 PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
41 {
42 PetscErrorCode ierr;
43
44 PetscFunctionBegin;
45 if (!XiWin) PetscFunctionReturn(0);
46 ierr = PetscFree(XiWin->font);CHKERRQ(ierr);
47 if (XiWin->disp) {
48 #if defined(PETSC_HAVE_SETJMP_H)
49 jmp_buf jmpbuf;
50 PetscXIOErrorHandler xioerrhdl;
51 ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr);
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 ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr);
63 #endif
64 }
65 PetscFunctionReturn(0);
66 }
67
68 /*
69 PetscDrawXiCreateGC - setup the GC structure
70 */
PetscDrawXiCreateGC(PetscDraw_X * XiWin,PetscDrawXiPixVal fg)71 static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
72 {
73 XGCValues gcvalues; /* window graphics context values */
74
75 PetscFunctionBegin;
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 PetscFunctionReturn(0);
85 }
86
87 /*
88 PetscDrawXiInit - basic setup the draw (display, graphics context, font)
89 */
PetscDrawXiInit(PetscDraw_X * XiWin,const char display[])90 PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
91 {
92 PetscErrorCode ierr;
93 PetscFunctionBegin;
94 ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr);
95 ierr = PetscDrawXiCreateGC(XiWin,XiWin->foreground);CHKERRQ(ierr);
96 ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr);
97 PetscFunctionReturn(0);
98 }
99
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 */
PetscDrawXiWaitMap(PetscDraw_X * XiWin)104 static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
105 {
106 XEvent event;
107
108 PetscFunctionBegin;
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 PetscFunctionReturn(0);
123 /* else ignore event */
124 }
125 }
126 }
127 PetscFunctionReturn(0);
128 }
129
130 /*
131 Actually display a window at [x,y] with sizes (w,h)
132 */
PetscDrawXiDisplayWindow(PetscDraw_X * XiWin,char * label,int x,int y,int w,int h)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;
142
143 PetscFunctionBegin;
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;
150
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;
155
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;
177
178 wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity |
179 CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect |
180 CWSaveUnder | CWEventMask | CWDontPropagate |
181 CWCursor | CWColormap;
182
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");
185
186 /* set window manager hints */
187 {
188 XWMHints wm_hints;
189 XClassHint class_hints;
190 XTextProperty windowname,iconname;
191
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);
196
197 wm_hints.initial_state = NormalState;
198 wm_hints.input = True;
199 wm_hints.flags = StateHint|InputHint;
200
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";
204
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;
212
213 XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,NULL,0,&size_hints,&wm_hints,&class_hints);
214 XFree((void*)windowname.value);
215 XFree((void*)iconname.value);
216 }
217
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 PetscFunctionReturn(0);
226 }
227
PetscDrawXiQuickWindow(PetscDraw_X * XiWin,char * name,int x,int y,int nx,int ny)228 PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
229 {
230 PetscErrorCode ierr;
231
232 PetscFunctionBegin;
233 ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr);
234 ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr);
235 XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
236 XClearWindow(XiWin->disp,XiWin->win);
237 PetscFunctionReturn(0);
238 }
239
240 /*
241 A version from an already defined window
242 */
PetscDrawXiQuickWindowFromWindow(PetscDraw_X * XiWin,Window win)243 PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
244 {
245 XWindowAttributes attributes;
246 PetscErrorCode ierr;
247
248 PetscFunctionBegin;
249 XiWin->win = win;
250 XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
251 ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr);
252 PetscFunctionReturn(0);
253 }
254
PetscDrawXiQuickPixmap(PetscDraw_X * XiWin)255 PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin)
256 {
257 PetscFunctionBegin;
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 PetscFunctionReturn(0);
264 }
265
PetscDrawXiResizeWindow(PetscDraw_X * XiWin,int w,int h)266 PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X* XiWin,int w,int h)
267 {
268 XEvent event;
269 PetscFunctionBegin;
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 PetscFunctionReturn(0);
275 }
276
PetscDrawXiGetGeometry(PetscDraw_X * XiWin,int * x,int * y,int * w,int * h)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;
283 PetscFunctionBegin;
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 PetscFunctionReturn(0);
300 }
301