Actual source code: xops.c
1: /* $Id: xops.c,v 1.156 2001/09/07 20:08:05 bsmith Exp $*/
3: /*
4: Defines the operations for the X PetscDraw implementation.
5: */
7: #include src/sys/src/draw/impls/x/ximpl.h
9: /*
10: These macros transform from the users coordinates to the
11: X-window pixel coordinates.
12: */
13: #define XTRANS(draw,xwin,x)
14: (int)(((xwin)->w)*((draw)->port_xl + (((x - (draw)->coor_xl)*
15: ((draw)->port_xr - (draw)->port_xl))/
16: ((draw)->coor_xr - (draw)->coor_xl))))
17: #define YTRANS(draw,xwin,y)
18: (int)(((xwin)->h)*(1.0-(draw)->port_yl - (((y - (draw)->coor_yl)*
19: ((draw)->port_yr - (draw)->port_yl))/
20: ((draw)->coor_yr - (draw)->coor_yl))))
22: int PetscDrawLine_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
23: {
24: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
25: int x1,y_1,x2,y2;
28: XiSetColor(XiWin,cl);
29: x1 = XTRANS(draw,XiWin,xl); x2 = XTRANS(draw,XiWin,xr);
30: y_1 = YTRANS(draw,XiWin,yl); y2 = YTRANS(draw,XiWin,yr);
31: XDrawLine(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,x1,y_1,x2,y2);
32: return(0);
33: }
35: static int PetscDrawPoint_X(PetscDraw draw,PetscReal x,PetscReal y,int c)
36: {
37: int xx,yy;
38: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
41: xx = XTRANS(draw,XiWin,x); yy = YTRANS(draw,XiWin,y);
42: XiSetColor(XiWin,c);
43: XDrawPoint(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,xx,yy);
44: return(0);
45: }
47: static int PetscDrawRectangle_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
48: {
49: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
50: int x1,y_1,w,h,c = (c1 + c2 + c3 + c4)/4;
53: XiSetColor(XiWin,c);
54: x1 = XTRANS(draw,XiWin,xl); w = XTRANS(draw,XiWin,xr) - x1;
55: y_1 = YTRANS(draw,XiWin,yr); h = YTRANS(draw,XiWin,yl) - y_1;
56: if (w <= 0) w = 1; if (h <= 0) h = 1;
57: XFillRectangle(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,x1,y_1,w,h);
58: return(0);
59: }
61: static int PetscDrawEllipse_X(PetscDraw Win, PetscReal x, PetscReal y, PetscReal a, PetscReal b, int c)
62: {
63: PetscDraw_X* XiWin = (PetscDraw_X*) Win->data;
64: int xA, yA, w, h;
67: XiSetColor(XiWin, c);
68: xA = XTRANS(Win, XiWin, x - a/2.0); w = XTRANS(Win, XiWin, x + a/2.0) - xA;
69: yA = YTRANS(Win, XiWin, y + b/2.0); h = YTRANS(Win, XiWin, y - b/2.0) - yA;
70: XFillArc(XiWin->disp, XiDrawable(XiWin), XiWin->gc.set, xA, yA, w, h, 0, 23040);
71: return(0);
72: }
74: EXTERN int PetscDrawInterpolatedTriangle_X(PetscDraw_X*,int,int,int,int,int,int,int,int,int);
76: static int PetscDrawTriangle_X(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,
77: PetscReal Y2,PetscReal X3,PetscReal Y3,int c1,int c2,int c3)
78: {
79: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
80: int ierr;
83: if (c1 == c2 && c2 == c3) {
84: XPoint pt[3];
85: XiSetColor(XiWin,c1);
86: pt[0].x = XTRANS(draw,XiWin,X1);
87: pt[0].y = YTRANS(draw,XiWin,Y_1);
88: pt[1].x = XTRANS(draw,XiWin,X2);
89: pt[1].y = YTRANS(draw,XiWin,Y2);
90: pt[2].x = XTRANS(draw,XiWin,X3);
91: pt[2].y = YTRANS(draw,XiWin,Y3);
92: XFillPolygon(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,pt,3,Convex,CoordModeOrigin);
93: } else {
94: int x1,y_1,x2,y2,x3,y3;
95: x1 = XTRANS(draw,XiWin,X1);
96: y_1 = YTRANS(draw,XiWin,Y_1);
97: x2 = XTRANS(draw,XiWin,X2);
98: y2 = YTRANS(draw,XiWin,Y2);
99: x3 = XTRANS(draw,XiWin,X3);
100: y3 = YTRANS(draw,XiWin,Y3);
101: PetscDrawInterpolatedTriangle_X(XiWin,x1,y_1,c1,x2,y2,c2,x3,y3,c3);
102: }
103: return(0);
104: }
106: static int PetscDrawString_X(PetscDraw draw,PetscReal x,PetscReal y,int c,char *chrs)
107: {
108: int xx,yy,ierr,len;
109: PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
110: char *substr;
111: PetscToken *token;
114: xx = XTRANS(draw,XiWin,x); yy = YTRANS(draw,XiWin,y);
115: XiSetColor(XiWin,c);
116:
117: PetscTokenCreate(chrs,'n',&token);
118: PetscTokenFind(token,&substr);
119: PetscStrlen(substr,&len);
120: XDrawString(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,xx,yy - XiWin->font->font_descent,substr,len);
121: PetscTokenFind(token,&substr);
122: while (substr) {
123: yy += 4*XiWin->font->font_descent;
124: PetscStrlen(substr,&len);
125: XDrawString(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,xx,yy - XiWin->font->font_descent,substr,len);
126: PetscTokenFind(token,&substr);
127: }
128: PetscTokenDestroy(token);
130: return(0);
131: }
133: EXTERN int XiFontFixed(PetscDraw_X*,int,int,XiFont **);
135: static int PetscDrawStringSetSize_X(PetscDraw draw,PetscReal x,PetscReal y)
136: {
137: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
138: int ierr,w,h;
141: w = (int)((XiWin->w)*x*(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
142: h = (int)((XiWin->h)*y*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
143: PetscFree(XiWin->font);
144: XiFontFixed(XiWin,w,h,&XiWin->font);
145: return(0);
146: }
148: int PetscDrawStringGetSize_X(PetscDraw draw,PetscReal *x,PetscReal *y)
149: {
150: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
151: PetscReal w,h;
154: w = XiWin->font->font_w; h = XiWin->font->font_h;
155: *x = w*(draw->coor_xr - draw->coor_xl)/(XiWin->w)*(draw->port_xr - draw->port_xl);
156: *y = h*(draw->coor_yr - draw->coor_yl)/(XiWin->h)*(draw->port_yr - draw->port_yl);
157: return(0);
158: }
160: int PetscDrawStringVertical_X(PetscDraw draw,PetscReal x,PetscReal y,int c,char *chrs)
161: {
162: int xx,yy,n,i,ierr;
163: PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
164: char tmp[2];
165: PetscReal tw,th;
166:
168: ierr = PetscStrlen(chrs,&n);
169: tmp[1] = 0;
170: XiSetColor(XiWin,c);
171: PetscDrawStringGetSize_X(draw,&tw,&th);
172: xx = XTRANS(draw,XiWin,x);
173: for (i=0; i<n; i++) {
174: tmp[0] = chrs[i];
175: yy = YTRANS(draw,XiWin,y-th*i);
176: XDrawString(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,
177: xx,yy - XiWin->font->font_descent,tmp,1);
178: }
179: return(0);
180: }
182: static int PetscDrawFlush_X(PetscDraw draw)
183: {
184: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
187: if (XiWin->drw) {
188: XCopyArea(XiWin->disp,XiWin->drw,XiWin->win,XiWin->gc.set,0,0,XiWin->w,XiWin->h,0,0);
189: }
190: XFlush(XiWin->disp); XSync(XiWin->disp,False);
191: return(0);
192: }
194: static int PetscDrawSynchronizedFlush_X(PetscDraw draw)
195: {
196: int rank,ierr;
197: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
200: XFlush(XiWin->disp);
201: if (XiWin->drw) {
202: MPI_Comm_rank(draw->comm,&rank);
203: /* make sure data has actually arrived at server */
204: XSync(XiWin->disp,False);
205: MPI_Barrier(draw->comm);
206: if (!rank) {
207: XCopyArea(XiWin->disp,XiWin->drw,XiWin->win,XiWin->gc.set,0,0,XiWin->w,XiWin->h,0,0);
208: XFlush(XiWin->disp);
209: }
210: XSync(XiWin->disp,False);
211: MPI_Barrier(draw->comm);
212: } else {
213: MPI_Barrier(draw->comm);
214: XSync(XiWin->disp,False);
215: MPI_Barrier(draw->comm);
216: }
217: return(0);
218: }
220: static int PetscDrawSetViewport_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
221: {
222: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
223: XRectangle box;
226: box.x = (int)(xl*XiWin->w); box.y = (int)((1.0-yr)*XiWin->h);
227: box.width = (int)((xr-xl)*XiWin->w);box.height = (int)((yr-yl)*XiWin->h);
228: XSetClipRectangles(XiWin->disp,XiWin->gc.set,0,0,&box,1,Unsorted);
229: return(0);
230: }
232: static int PetscDrawClear_X(PetscDraw draw)
233: {
234: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
235: int x, y, w, h;
238: x = (int)(draw->port_xl*XiWin->w);
239: w = (int)((draw->port_xr - draw->port_xl)*XiWin->w);
240: y = (int)((1.0-draw->port_yr)*XiWin->h);
241: h = (int)((draw->port_yr - draw->port_yl)*XiWin->h);
242: XiSetPixVal(XiWin,XiWin->background);
243: XFillRectangle(XiWin->disp,XiDrawable(XiWin),XiWin->gc.set,x,y,w,h);
244: return(0);
245: }
247: static int PetscDrawSynchronizedClear_X(PetscDraw draw)
248: {
249: int rank,ierr;
250: PetscDraw_X* XiWin = (PetscDraw_X*)draw->data;
253: MPI_Barrier(draw->comm);
254: MPI_Comm_rank(draw->comm,&rank);
255: if (!rank) {
256: PetscDrawClear_X(draw);
257: }
258: XFlush(XiWin->disp);
259: MPI_Barrier(draw->comm);
260: XSync(XiWin->disp,False);
261: MPI_Barrier(draw->comm);
262: return(0);
263: }
265: static int PetscDrawSetDoubleBuffer_X(PetscDraw draw)
266: {
267: PetscDraw_X* win = (PetscDraw_X*)draw->data;
268: int rank,ierr;
271: if (win->drw) return(0);
273: MPI_Comm_rank(draw->comm,&rank);
274: if (!rank) {
275: win->drw = XCreatePixmap(win->disp,win->win,win->w,win->h,win->depth);
276: }
277: /* try to make sure it is actually done before passing info to all */
278: XSync(win->disp,False);
279: MPI_Bcast(&win->drw,1,MPI_UNSIGNED_LONG,0,draw->comm);
280: return(0);
281: }
283: #include <X11/cursorfont.h>
285: static int PetscDrawGetMouseButton_X(PetscDraw draw,PetscDrawButton *button,PetscReal* x_user,
286: PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
287: {
288: XEvent report;
289: PetscDraw_X* win = (PetscDraw_X*)draw->data;
290: Window root,child;
291: int root_x,root_y,px,py;
292: unsigned int keys_button;
293: Cursor cursor = 0;
296: /* change cursor to indicate input */
297: if (!cursor) {
298: cursor = XCreateFontCursor(win->disp,XC_hand2);
299: if (!cursor) SETERRQ(PETSC_ERR_LIB,"Unable to create X cursor");
300: }
301: XDefineCursor(win->disp,win->win,cursor);
303: XSelectInput(win->disp,win->win,ButtonPressMask | ButtonReleaseMask);
305: while (XCheckTypedEvent(win->disp,ButtonPress,&report));
306: XMaskEvent(win->disp,ButtonReleaseMask,&report);
307: switch (report.xbutton.button) {
308: case Button1:
309: if (report.xbutton.state & ShiftMask)
310: *button = BUTTON_LEFT_SHIFT;
311: else
312: *button = BUTTON_LEFT;
313: break;
314: case Button2:
315: if (report.xbutton.state & ShiftMask)
316: *button = BUTTON_CENTER_SHIFT;
317: else
318: *button = BUTTON_CENTER;
319: break;
320: case Button3:
321: if (report.xbutton.state & ShiftMask)
322: *button = BUTTON_RIGHT_SHIFT;
323: else
324: *button = BUTTON_RIGHT;
325: break;
326: }
327: XQueryPointer(win->disp,report.xmotion.window,&root,&child,&root_x,&root_y,&px,&py,&keys_button);
329: if (x_phys) *x_phys = ((double)px)/((double)win->w);
330: if (y_phys) *y_phys = 1.0 - ((double)py)/((double)win->h);
332: if (x_user) *x_user = draw->coor_xl + ((((double)px)/((double)win->w)-draw->port_xl))*
333: (draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
334: if (y_user) *y_user = draw->coor_yl +
335: ((1.0 - ((double)py)/((double)win->h)-draw->port_yl))*
336: (draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
338: XUndefineCursor(win->disp,win->win);
339: XFlush(win->disp); XSync(win->disp,False);
340: return(0);
341: }
343: static int PetscDrawPause_X(PetscDraw draw)
344: {
348: if (draw->pause > 0) PetscSleep(draw->pause);
349: else if (draw->pause < 0) {
350: PetscDrawButton button;
351: int rank;
352: MPI_Comm_rank(draw->comm,&rank);
353: if (!rank) {
354: PetscDrawGetMouseButton(draw,&button,0,0,0,0);
355: if (button == BUTTON_CENTER) draw->pause = 0;
356: }
357: MPI_Bcast(&draw->pause,1,MPI_INT,0,draw->comm);
358: }
359: return(0);
360: }
362: static int PetscDrawGetPopup_X(PetscDraw draw,PetscDraw *popup)
363: {
364: int ierr;
365: PetscDraw_X* win = (PetscDraw_X*)draw->data;
368: PetscDrawOpenX(draw->comm,PETSC_NULL,PETSC_NULL,win->x,win->y+win->h+36,150,220,popup);
369: draw->popup = *popup;
370: return(0);
371: }
373: static int PetscDrawSetTitle_X(PetscDraw draw,char *title)
374: {
375: PetscDraw_X *win = (PetscDraw_X*)draw->data;
376: XTextProperty prop;
377: int ierr,len;
380: XGetWMName(win->disp,win->win,&prop);
381: prop.value = (unsigned char *)title;
382: ierr = PetscStrlen(title,&len);
383: prop.nitems = (long) len;
384: XSetWMName(win->disp,win->win,&prop);
385: return(0);
386: }
388: static int PetscDrawResizeWindow_X(PetscDraw draw,int w,int h)
389: {
390: PetscDraw_X *win = (PetscDraw_X*)draw->data;
391: unsigned int ww,hh,border,depth;
392: int x,y;
393: int ierr;
394: Window root;
397: XResizeWindow(win->disp,win->win,w,h);
398: XGetGeometry(win->disp,win->win,&root,&x,&y,&ww,&hh,&border,&depth);
399: PetscDrawCheckResizedWindow(draw);
400: return(0);
401: }
403: static int PetscDrawCheckResizedWindow_X(PetscDraw draw)
404: {
405: PetscDraw_X *win = (PetscDraw_X*)draw->data;
406: int x,y,rank,ierr;
407: Window root;
408: unsigned int w,h,border,depth,geo[2];
409: PetscReal xl,xr,yl,yr;
410: XRectangle box;
413: MPI_Comm_rank(draw->comm,&rank);
414: if (!rank) {
415: XSync(win->disp,False);
416: XGetGeometry(win->disp,win->win,&root,&x,&y,geo,geo+1,&border,&depth);
417: }
418: MPI_Bcast(geo,2,MPI_INT,0,draw->comm);
419: w = geo[0];
420: h = geo[1];
421: if (w == (unsigned int) win->w && h == (unsigned int) win->h) return(0);
423: /* record new window sizes */
425: win->h = h; win->w = w;
427: /* Free buffer space and create new version (only first processor does this) */
428: if (win->drw) {
429: win->drw = XCreatePixmap(win->disp,win->win,win->w,win->h,win->depth);
430: }
431: /* reset the clipping */
432: xl = draw->port_xl; yl = draw->port_yl;
433: xr = draw->port_xr; yr = draw->port_yr;
434: box.x = (int)(xl*win->w); box.y = (int)((1.0-yr)*win->h);
435: box.width = (int)((xr-xl)*win->w);box.height = (int)((yr-yl)*win->h);
436: XSetClipRectangles(win->disp,win->gc.set,0,0,&box,1,Unsorted);
438: /* try to make sure it is actually done before passing info to all */
439: XSync(win->disp,False);
440: MPI_Bcast(&win->drw,1,MPI_UNSIGNED_LONG,0,draw->comm);
441: return(0);
442: }
444: static int PetscDrawGetSingleton_X(PetscDraw,PetscDraw*);
445: static int PetscDrawRestoreSingleton_X(PetscDraw,PetscDraw*);
447: int PetscDrawDestroy_X(PetscDraw draw)
448: {
449: PetscDraw_X *win = (PetscDraw_X*)draw->data;
450: int ierr;
453: XFreeGC(win->disp,win->gc.set);
454: XCloseDisplay(win->disp);
455: if (draw->popup) {PetscDrawDestroy(draw->popup);}
456: PetscFree(win->font);
457: PetscFree(win);
458: return(0);
459: }
461: static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_X,
462: PetscDrawFlush_X,PetscDrawLine_X,
463: 0,
464: 0,
465: PetscDrawPoint_X,
466: 0,
467: PetscDrawString_X,
468: PetscDrawStringVertical_X,
469: PetscDrawStringSetSize_X,
470: PetscDrawStringGetSize_X,
471: PetscDrawSetViewport_X,
472: PetscDrawClear_X,
473: PetscDrawSynchronizedFlush_X,
474: PetscDrawRectangle_X,
475: PetscDrawTriangle_X,
476: PetscDrawEllipse_X,
477: PetscDrawGetMouseButton_X,
478: PetscDrawPause_X,
479: PetscDrawSynchronizedClear_X,
480: 0,
481: 0,
482: PetscDrawGetPopup_X,
483: PetscDrawSetTitle_X,
484: PetscDrawCheckResizedWindow_X,
485: PetscDrawResizeWindow_X,
486: PetscDrawDestroy_X,
487: 0,
488: PetscDrawGetSingleton_X,
489: PetscDrawRestoreSingleton_X };
492: EXTERN int XiQuickWindow(PetscDraw_X*,char*,char*,int,int,int,int);
493: EXTERN int XiQuickWindowFromWindow(PetscDraw_X*,char*,Window);
495: static int PetscDrawGetSingleton_X(PetscDraw draw,PetscDraw *sdraw)
496: {
497: int ierr;
498: PetscDraw_X *Xwin = (PetscDraw_X*)draw->data,*sXwin;
502: PetscDrawCreate(PETSC_COMM_SELF,draw->display,draw->title,draw->x,draw->y,draw->w,draw->h,sdraw);
503: PetscObjectChangeTypeName((PetscObject)*sdraw,PETSC_DRAW_X);
504: PetscMemcpy((*sdraw)->ops,&DvOps,sizeof(DvOps));
505: (*sdraw)->ops->destroy = 0;
507: (*sdraw)->pause = draw->pause;
508: (*sdraw)->coor_xl = draw->coor_xl;
509: (*sdraw)->coor_xr = draw->coor_xr;
510: (*sdraw)->coor_yl = draw->coor_yl;
511: (*sdraw)->coor_yr = draw->coor_yr;
512: (*sdraw)->port_xl = draw->port_xl;
513: (*sdraw)->port_xr = draw->port_xr;
514: (*sdraw)->port_yl = draw->port_yl;
515: (*sdraw)->port_yr = draw->port_yr;
516: (*sdraw)->popup = draw->popup;
518: /* actually create and open the window */
519: PetscNew(PetscDraw_X,&sXwin);
520: PetscMemzero(sXwin,sizeof(PetscDraw_X));
521: XiQuickWindowFromWindow(sXwin,draw->display,Xwin->win);
523: sXwin->x = Xwin->x;
524: sXwin->y = Xwin->y;
525: sXwin->w = Xwin->w;
526: sXwin->h = Xwin->h;
527: (*sdraw)->data = (void*)sXwin;
528: return(0);
529: }
531: static int PetscDrawRestoreSingleton_X(PetscDraw draw,PetscDraw *sdraw)
532: {
533: int ierr;
534: PetscDraw_X *sXwin = (PetscDraw_X*)(*sdraw)->data;
536: XFreeGC(sXwin->disp,sXwin->gc.set);
537: XCloseDisplay(sXwin->disp);
538: if ((*sdraw)->popup) {PetscDrawDestroy((*sdraw)->popup);}
539: PetscStrfree((*sdraw)->title);
540: PetscStrfree((*sdraw)->display);
541: PetscFree(sXwin->font);
542: PetscFree(sXwin);
543: PetscHeaderDestroy(*sdraw);
545: return(0);
546: }
548: int PetscDrawXGetDisplaySize_Private(const char name[],int *width,int *height)
549: {
550: Display *display;
553: display = XOpenDisplay(name);
554: if (!display) {
555: *width = 0;
556: *height = 0;
557: SETERRQ1(1,"Unable to open display on %sn. Make sure your DISPLAY variablen
558: is set,or you use the -display name option and xhost + has beenn
559: run on your displaying machine.n",name);
560: }
562: *width = DisplayWidth(display,0);
563: *height = DisplayHeight(display,0);
565: XCloseDisplay(display);
566: return(0);
567: }
569: EXTERN_C_BEGIN
570: int PetscDrawCreate_X(PetscDraw draw)
571: {
572: PetscDraw_X *Xwin;
573: int ierr,rank,xywh[4],osize = 4;
574: int x = draw->x,y = draw->y,w = draw->w,h = draw->h;
575: static int xavailable = 0,yavailable = 0,xmax = 0,ymax = 0,ybottom = 0;
576: PetscTruth flg;
579: if (!draw->display) {
580: PetscMalloc(128*sizeof(char),&draw->display);
581: PetscGetDisplay(draw->display,128);
582: }
584: /*
585: Initialize the display size
586: */
587: if (!xmax) {
588: PetscDrawXGetDisplaySize_Private(draw->display,&xmax,&ymax);
589: /* if some processors fail on this and others succed then this is a problem ! */
590: if (ierr) {
591: (*PetscErrorPrintf)("PETSc unable to use X windowsnproceeding without graphicsn");
592: PetscDrawSetType(draw,PETSC_DRAW_NULL);
593: return(0);
594: }
595: }
597: if (w == PETSC_DECIDE) w = draw->w = 300;
598: if (h == PETSC_DECIDE) h = draw->h = 300;
599: switch (w) {
600: case PETSC_DRAW_FULL_SIZE: w = draw->w = xmax - 10;
601: break;
602: case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2;
603: break;
604: case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3;
605: break;
606: case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4;
607: break;
608: }
609: switch (h) {
610: case PETSC_DRAW_FULL_SIZE: h = draw->h = ymax - 10;
611: break;
612: case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2;
613: break;
614: case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3;
615: break;
616: case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4;
617: break;
618: }
620: /* allow user to set location and size of window */
621: xywh[0] = x; xywh[1] = y; xywh[2] = w; xywh[3] = h;
622: PetscOptionsGetIntArray(PETSC_NULL,"-geometry",xywh,&osize,PETSC_NULL);
623: x = xywh[0]; y = xywh[1]; w = xywh[2]; h = xywh[3];
626: if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
627: /*
628: PETSc tries to place windows starting in the upper left corner and
629: moving across to the right.
630:
631: --------------------------------------------
632: | Region used so far +xavailable,yavailable |
633: | + |
634: | + |
635: |++++++++++++++++++++++ybottom |
636: | |
637: | |
638: |--------------------------------------------|
639: */
640: /* First: can we add it to the right? */
641: if (xavailable+w+10 <= xmax) {
642: x = xavailable;
643: y = yavailable;
644: ybottom = PetscMax(ybottom,y + h + 30);
645: } else {
646: /* No, so add it below on the left */
647: xavailable = 0;
648: x = 0;
649: yavailable = ybottom;
650: y = ybottom;
651: ybottom = ybottom + h + 30;
652: }
653: }
654: /* update available region */
655: xavailable = PetscMax(xavailable,x + w + 10);
656: if (xavailable >= xmax) {
657: xavailable = 0;
658: yavailable = yavailable + h + 30;
659: ybottom = yavailable;
660: }
661: if (yavailable >= ymax) {
662: y = 0;
663: yavailable = 0;
664: ybottom = 0;
665: }
667: PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));
669: /* actually create and open the window */
670: PetscNew(PetscDraw_X,&Xwin);
671: PetscLogObjectMemory(draw,sizeof(PetscDraw_X)+sizeof(struct _p_PetscDraw));
672: PetscMemzero(Xwin,sizeof(PetscDraw_X));
673: MPI_Comm_rank(draw->comm,&rank);
675: if (!rank) {
676: if (x < 0 || y < 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative corner of window");
677: if (w <= 0 || h <= 0) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Negative window width or height");
678: XiQuickWindow(Xwin,draw->display,draw->title,x,y,w,h);
679: MPI_Bcast(&Xwin->win,1,MPI_UNSIGNED_LONG,0,draw->comm);
680: } else {
681: unsigned long win = 0;
682: MPI_Bcast(&win,1,MPI_UNSIGNED_LONG,0,draw->comm);
683: XiQuickWindowFromWindow(Xwin,draw->display,win);
684: }
686: Xwin->x = x;
687: Xwin->y = y;
688: Xwin->w = w;
689: Xwin->h = h;
690: draw->data = (void*)Xwin;
692: /*
693: Need barrier here so processor 0 does not destroy the window before other
694: processors have completed XiQuickWindow()
695: */
696: PetscDrawClear(draw);
697: PetscDrawSynchronizedFlush(draw);
699: PetscOptionsHasName(PETSC_NULL,"-draw_double_buffer",&flg);
700: if (flg) {
701: PetscDrawSetDoubleBuffer(draw);
702: }
704: return(0);
705: }
706: EXTERN_C_END