PageRenderTime 73ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/src/sys/classes/draw/impls/x/xops.c

https://bitbucket.org/tferma/petsc
C | 865 lines | 712 code | 92 blank | 61 comment | 154 complexity | 5c3ed60fe85975e315bf3f6116a116f4 MD5 | raw file
  1. /*
  2. Defines the operations for the X PetscDraw implementation.
  3. */
  4. #include <../src/sys/classes/draw/impls/x/ximpl.h> /*I "petscsys.h" I*/
  5. /*
  6. These macros transform from the users coordinates to the X-window pixel coordinates.
  7. */
  8. #define XTRANS(draw,xwin,x) ((int)(((xwin)->w-1)*((draw)->port_xl + (((x - (draw)->coor_xl)*((draw)->port_xr - (draw)->port_xl))/((draw)->coor_xr - (draw)->coor_xl)))))
  9. #define YTRANS(draw,xwin,y) (((xwin)->h-1) - (int)(((xwin)->h-1)*((draw)->port_yl + (((y - (draw)->coor_yl)*((draw)->port_yr - (draw)->port_yl))/((draw)->coor_yr - (draw)->coor_yl)))))
  10. #define ITRANS(draw,xwin,i) ((draw)->coor_xl + (((PetscReal)(i))*((draw)->coor_xr - (draw)->coor_xl)/((xwin)->w-1) - (draw)->port_xl)/((draw)->port_xr - (draw)->port_xl))
  11. #define JTRANS(draw,xwin,j) ((draw)->coor_yl + (((PetscReal)(j))/((xwin)->h-1) + (draw)->port_yl - 1)*((draw)->coor_yr - (draw)->coor_yl)/((draw)->port_yl - (draw)->port_yr))
  12. #undef __FUNCT__
  13. #define __FUNCT__ "PetscDrawSetViewport_X"
  14. static PetscErrorCode PetscDrawSetViewport_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr)
  15. {
  16. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  17. int xa,ya,xb,yb,xmax = XiWin->w-1,ymax = XiWin->h-1;
  18. XRectangle box;
  19. PetscErrorCode ierr;
  20. PetscFunctionBegin;
  21. xa = (int)(xl*xmax); ya = ymax - (int)(yr*ymax);
  22. xb = (int)(xr*xmax); yb = ymax - (int)(yl*ymax);
  23. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  24. box.x = (short)xa; box.width = (unsigned short)(xb + 1 - xa);
  25. box.y = (short)ya; box.height = (unsigned short)(yb + 1 - ya);
  26. XSetClipRectangles(XiWin->disp,XiWin->gc.set,0,0,&box,1,Unsorted);
  27. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  28. PetscFunctionReturn(0);
  29. }
  30. #undef __FUNCT__
  31. #define __FUNCT__ "PetscDrawCoordinateToPixel_X"
  32. static PetscErrorCode PetscDrawCoordinateToPixel_X(PetscDraw draw,PetscReal x,PetscReal y,int *i,int *j)
  33. {
  34. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  35. PetscFunctionBegin;
  36. *i = XTRANS(draw,XiWin,x);
  37. *j = YTRANS(draw,XiWin,y);
  38. PetscFunctionReturn(0);
  39. }
  40. #undef __FUNCT__
  41. #define __FUNCT__ "PetscDrawPixelToCoordinate_X"
  42. static PetscErrorCode PetscDrawPixelToCoordinate_X(PetscDraw draw,int i,int j,PetscReal *x,PetscReal *y)
  43. {
  44. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  45. PetscFunctionBegin;
  46. *x = ITRANS(draw,XiWin,i);
  47. *y = JTRANS(draw,XiWin,j);
  48. PetscFunctionReturn(0);
  49. }
  50. #undef __FUNCT__
  51. #define __FUNCT__ "PetscDrawPoint_X"
  52. static PetscErrorCode PetscDrawPoint_X(PetscDraw draw,PetscReal x,PetscReal y,int c)
  53. {
  54. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  55. int xx,yy,i,j;
  56. PetscFunctionBegin;
  57. xx = XTRANS(draw,XiWin,x);
  58. yy = YTRANS(draw,XiWin,y);
  59. PetscDrawXiSetColor(XiWin,c);
  60. for (i=-1; i<2; i++) {
  61. for (j=-1; j<2; j++) {
  62. XDrawPoint(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,xx+i,yy+j);
  63. }
  64. }
  65. PetscFunctionReturn(0);
  66. }
  67. #undef __FUNCT__
  68. #define __FUNCT__ "PetscDrawPointPixel_X"
  69. static PetscErrorCode PetscDrawPointPixel_X(PetscDraw draw,int x,int y,int c)
  70. {
  71. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  72. PetscFunctionBegin;
  73. PetscDrawXiSetColor(XiWin,c);
  74. XDrawPoint(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x,y);
  75. PetscFunctionReturn(0);
  76. }
  77. #undef __FUNCT__
  78. #define __FUNCT__ "PetscDrawLine_X"
  79. static PetscErrorCode PetscDrawLine_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
  80. {
  81. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  82. int x_1,y_1,x_2,y_2;
  83. PetscFunctionBegin;
  84. PetscDrawXiSetColor(XiWin,cl);
  85. x_1 = XTRANS(draw,XiWin,xl); x_2 = XTRANS(draw,XiWin,xr);
  86. y_1 = YTRANS(draw,XiWin,yl); y_2 = YTRANS(draw,XiWin,yr);
  87. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_1,y_1,x_2,y_2);
  88. PetscFunctionReturn(0);
  89. }
  90. #undef __FUNCT__
  91. #define __FUNCT__ "PetscDrawArrow_X"
  92. static PetscErrorCode PetscDrawArrow_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int cl)
  93. {
  94. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  95. int x_1,y_1,x_2,y_2;
  96. PetscFunctionBegin;
  97. PetscDrawXiSetColor(XiWin,cl);
  98. x_1 = XTRANS(draw,XiWin,xl); x_2 = XTRANS(draw,XiWin,xr);
  99. y_1 = YTRANS(draw,XiWin,yl); y_2 = YTRANS(draw,XiWin,yr);
  100. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_1,y_1,x_2,y_2);
  101. if (x_1 == x_2 && y_1 == y_2) PetscFunctionReturn(0);
  102. if (x_1 == x_2 && PetscAbs(y_1 - y_2) > 7) {
  103. if (y_2 > y_1) {
  104. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2-3,y_2-3);
  105. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2+3,y_2-3);
  106. } else {
  107. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2-3,y_2+3);
  108. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2+3,y_2+3);
  109. }
  110. }
  111. if (y_1 == y_2 && PetscAbs(x_1 - x_2) > 7) {
  112. if (x_2 > x_1) {
  113. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2-3,y_2-3,x_2,y_2);
  114. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2-3,y_2+3,x_2,y_2);
  115. } else {
  116. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2+3,y_2-3);
  117. XDrawLine(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x_2,y_2,x_2+3,y_2+3);
  118. }
  119. }
  120. PetscFunctionReturn(0);
  121. }
  122. #undef __FUNCT__
  123. #define __FUNCT__ "PetscDrawRectangle_X"
  124. static PetscErrorCode PetscDrawRectangle_X(PetscDraw draw,PetscReal xl,PetscReal yl,PetscReal xr,PetscReal yr,int c1,int c2,int c3,int c4)
  125. {
  126. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  127. int x,y,w,h,c = (c1 + c2 + c3 + c4)/4;
  128. PetscFunctionBegin;
  129. PetscDrawXiSetColor(XiWin,c);
  130. x = XTRANS(draw,XiWin,xl); w = XTRANS(draw,XiWin,xr) + 1 - x; if (w <= 0) w = 1;
  131. y = YTRANS(draw,XiWin,yr); h = YTRANS(draw,XiWin,yl) + 1 - y; if (h <= 0) h = 1;
  132. XFillRectangle(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,x,y,w,h);
  133. PetscFunctionReturn(0);
  134. }
  135. #undef __FUNCT__
  136. #define __FUNCT__ "PetscDrawEllipse_X"
  137. static PetscErrorCode PetscDrawEllipse_X(PetscDraw draw,PetscReal x,PetscReal y,PetscReal a,PetscReal b,int c)
  138. {
  139. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  140. int xA,yA,w,h;
  141. PetscFunctionBegin;
  142. PetscDrawXiSetColor(XiWin, c);
  143. xA = XTRANS(draw,XiWin, x - a/2); w = XTRANS(draw,XiWin, x + a/2) + 1 - xA; w = PetscAbs(w);
  144. yA = YTRANS(draw,XiWin, y + b/2); h = YTRANS(draw,XiWin, y - b/2) + 1 - yA; h = PetscAbs(h);
  145. XFillArc(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,xA,yA,w,h,0,360*64);
  146. PetscFunctionReturn(0);
  147. }
  148. PETSC_INTERN PetscErrorCode PetscDrawInterpolatedTriangle_X(PetscDraw_X*,int,int,int,int,int,int,int,int,int);
  149. #undef __FUNCT__
  150. #define __FUNCT__ "PetscDrawTriangle_X"
  151. static PetscErrorCode PetscDrawTriangle_X(PetscDraw draw,PetscReal X1,PetscReal Y_1,PetscReal X2,PetscReal Y2,PetscReal X3,PetscReal Y3,int c1,int c2,int c3)
  152. {
  153. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  154. PetscErrorCode ierr;
  155. PetscFunctionBegin;
  156. if (c1 == c2 && c2 == c3) {
  157. XPoint pt[3];
  158. PetscDrawXiSetColor(XiWin,c1);
  159. pt[0].x = XTRANS(draw,XiWin,X1);
  160. pt[0].y = YTRANS(draw,XiWin,Y_1);
  161. pt[1].x = XTRANS(draw,XiWin,X2);
  162. pt[1].y = YTRANS(draw,XiWin,Y2);
  163. pt[2].x = XTRANS(draw,XiWin,X3);
  164. pt[2].y = YTRANS(draw,XiWin,Y3);
  165. XFillPolygon(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,pt,3,Convex,CoordModeOrigin);
  166. } else {
  167. int x1,y_1,x2,y2,x3,y3;
  168. x1 = XTRANS(draw,XiWin,X1);
  169. y_1 = YTRANS(draw,XiWin,Y_1);
  170. x2 = XTRANS(draw,XiWin,X2);
  171. y2 = YTRANS(draw,XiWin,Y2);
  172. x3 = XTRANS(draw,XiWin,X3);
  173. y3 = YTRANS(draw,XiWin,Y3);
  174. ierr = PetscDrawInterpolatedTriangle_X(XiWin,x1,y_1,c1,x2,y2,c2,x3,y3,c3);CHKERRQ(ierr);
  175. }
  176. PetscFunctionReturn(0);
  177. }
  178. #undef __FUNCT__
  179. #define __FUNCT__ "PetscDrawStringSetSize_X"
  180. static PetscErrorCode PetscDrawStringSetSize_X(PetscDraw draw,PetscReal x,PetscReal y)
  181. {
  182. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  183. int w,h;
  184. PetscErrorCode ierr;
  185. PetscFunctionBegin;
  186. w = (int)((XiWin->w)*x*(draw->port_xr - draw->port_xl)/(draw->coor_xr - draw->coor_xl));
  187. h = (int)((XiWin->h)*y*(draw->port_yr - draw->port_yl)/(draw->coor_yr - draw->coor_yl));
  188. ierr = PetscFree(XiWin->font);CHKERRQ(ierr);
  189. ierr = PetscDrawXiFontFixed(XiWin,w,h,&XiWin->font);CHKERRQ(ierr);
  190. PetscFunctionReturn(0);
  191. }
  192. #undef __FUNCT__
  193. #define __FUNCT__ "PetscDrawStringGetSize_X"
  194. static PetscErrorCode PetscDrawStringGetSize_X(PetscDraw draw,PetscReal *x,PetscReal *y)
  195. {
  196. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  197. PetscReal w,h;
  198. PetscFunctionBegin;
  199. w = XiWin->font->font_w; h = XiWin->font->font_h;
  200. if (x) *x = w*(draw->coor_xr - draw->coor_xl)/((XiWin->w)*(draw->port_xr - draw->port_xl));
  201. if (y) *y = h*(draw->coor_yr - draw->coor_yl)/((XiWin->h)*(draw->port_yr - draw->port_yl));
  202. PetscFunctionReturn(0);
  203. }
  204. #undef __FUNCT__
  205. #define __FUNCT__ "PetscDrawString_X"
  206. static PetscErrorCode PetscDrawString_X(PetscDraw draw,PetscReal x,PetscReal y,int c,const char chrs[])
  207. {
  208. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  209. int xx,yy,descent = XiWin->font->font_descent;
  210. size_t len;
  211. char *substr;
  212. PetscToken token;
  213. PetscErrorCode ierr;
  214. PetscFunctionBegin;
  215. xx = XTRANS(draw,XiWin,x);
  216. yy = YTRANS(draw,XiWin,y);
  217. PetscDrawXiSetColor(XiWin,c);
  218. ierr = PetscTokenCreate(chrs,'\n',&token);CHKERRQ(ierr);
  219. ierr = PetscTokenFind(token,&substr);CHKERRQ(ierr);
  220. while (substr) {
  221. ierr = PetscStrlen(substr,&len);CHKERRQ(ierr);
  222. XDrawString(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,xx,yy-descent,substr,len);
  223. yy += XiWin->font->font_h;
  224. ierr = PetscTokenFind(token,&substr);CHKERRQ(ierr);
  225. }
  226. ierr = PetscTokenDestroy(&token);CHKERRQ(ierr);
  227. PetscFunctionReturn(0);
  228. }
  229. #undef __FUNCT__
  230. #define __FUNCT__ "PetscDrawStringVertical_X"
  231. static PetscErrorCode PetscDrawStringVertical_X(PetscDraw draw,PetscReal x,PetscReal y,int c,const char text[])
  232. {
  233. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  234. int xx,yy,offset = XiWin->font->font_h - XiWin->font->font_descent;
  235. char chr[2] = {0, 0};
  236. PetscFunctionBegin;
  237. xx = XTRANS(draw,XiWin,x);
  238. yy = YTRANS(draw,XiWin,y);
  239. PetscDrawXiSetColor(XiWin,c);
  240. while ((chr[0] = *text++)) {
  241. XDrawString(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,xx,yy+offset,chr,1);
  242. yy += XiWin->font->font_h;
  243. }
  244. PetscFunctionReturn(0);
  245. }
  246. #undef __FUNCT__
  247. #define __FUNCT__ "PetscDrawFlush_X"
  248. static PetscErrorCode PetscDrawFlush_X(PetscDraw draw)
  249. {
  250. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  251. PetscMPIInt rank;
  252. PetscErrorCode ierr;
  253. PetscFunctionBegin;
  254. /* make sure the X server processed requests from all processes */
  255. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  256. XSync(XiWin->disp,False);
  257. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  258. ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  259. /* transfer pixmap contents to window (only the first process does this) */
  260. if (XiWin->drw && XiWin->win) {
  261. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  262. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  263. if (!rank) XCopyArea(XiWin->disp,XiWin->drw,XiWin->win,XiWin->gc.set,0,0,XiWin->w,XiWin->h,0,0);
  264. if (!rank) XSync(XiWin->disp,False);
  265. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  266. ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  267. }
  268. PetscFunctionReturn(0);
  269. }
  270. #undef __FUNCT__
  271. #define __FUNCT__ "PetscDrawClear_X"
  272. static PetscErrorCode PetscDrawClear_X(PetscDraw draw)
  273. {
  274. PetscDraw_X *XiWin = (PetscDraw_X*)draw->data;
  275. int xmax = XiWin->w-1, ymax = XiWin->h-1;
  276. PetscReal xl = draw->port_xl, yl = draw->port_yl;
  277. PetscReal xr = draw->port_xr, yr = draw->port_yr;
  278. PetscMPIInt rank;
  279. PetscErrorCode ierr;
  280. PetscFunctionBegin;
  281. /* make sure the X server processed requests from all processes */
  282. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  283. XSync(XiWin->disp,False);
  284. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  285. ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  286. /* only the first process handles the clearing business */
  287. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  288. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  289. if (!rank) {
  290. int xa = (int)(xl*xmax), ya = ymax - (int)(yr*ymax);
  291. int xb = (int)(xr*xmax), yb = ymax - (int)(yl*ymax);
  292. unsigned int w = (unsigned int)(xb + 1 - xa);
  293. unsigned int h = (unsigned int)(yb + 1 - ya);
  294. PetscDrawXiSetPixVal(XiWin,XiWin->background);
  295. XFillRectangle(XiWin->disp,PetscDrawXiDrawable(XiWin),XiWin->gc.set,xa,ya,w,h);
  296. XSync(XiWin->disp,False);
  297. }
  298. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  299. ierr = MPI_Barrier(PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  300. PetscFunctionReturn(0);
  301. }
  302. #undef __FUNCT__
  303. #define __FUNCT__ "PetscDrawSetDoubleBuffer_X"
  304. static PetscErrorCode PetscDrawSetDoubleBuffer_X(PetscDraw draw)
  305. {
  306. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  307. PetscMPIInt rank;
  308. PetscErrorCode ierr;
  309. PetscFunctionBegin;
  310. if (win->drw) PetscFunctionReturn(0);
  311. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  312. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  313. if (!rank) {ierr = PetscDrawXiQuickPixmap(win);CHKERRQ(ierr);}
  314. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  315. ierr = MPI_Bcast(&win->drw,1,MPI_UNSIGNED_LONG,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  316. PetscFunctionReturn(0);
  317. }
  318. #undef __FUNCT__
  319. #define __FUNCT__ "PetscDrawGetPopup_X"
  320. static PetscErrorCode PetscDrawGetPopup_X(PetscDraw draw,PetscDraw *popup)
  321. {
  322. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  323. PetscBool flg = PETSC_TRUE;
  324. PetscErrorCode ierr;
  325. PetscFunctionBegin;
  326. ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_popup",&flg,NULL);CHKERRQ(ierr);
  327. if (!flg || !win->win) {*popup = NULL; PetscFunctionReturn(0);}
  328. ierr = PetscDrawCreate(PetscObjectComm((PetscObject)draw),draw->display,NULL,win->x,win->y+win->h+10,220,220,popup);CHKERRQ(ierr);
  329. ierr = PetscObjectSetOptionsPrefix((PetscObject)*popup,"popup_");CHKERRQ(ierr);
  330. ierr = PetscObjectAppendOptionsPrefix((PetscObject)*popup,((PetscObject)draw)->prefix);CHKERRQ(ierr);
  331. ierr = PetscDrawSetType(*popup,PETSC_DRAW_X);CHKERRQ(ierr);
  332. draw->popup = *popup;
  333. PetscFunctionReturn(0);
  334. }
  335. #undef __FUNCT__
  336. #define __FUNCT__ "PetscDrawSetTitle_X"
  337. static PetscErrorCode PetscDrawSetTitle_X(PetscDraw draw,const char title[])
  338. {
  339. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  340. PetscMPIInt rank;
  341. PetscErrorCode ierr;
  342. PetscFunctionBegin;
  343. if (!win->win) PetscFunctionReturn(0);
  344. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  345. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  346. if (!rank) {
  347. size_t len;
  348. XTextProperty prop;
  349. ierr = PetscStrlen(title,&len);CHKERRQ(ierr);
  350. XGetWMName(win->disp,win->win,&prop);
  351. XFree((void*)prop.value);
  352. prop.value = (unsigned char*)title;
  353. prop.nitems = (long)len;
  354. XSetWMName(win->disp,win->win,&prop);
  355. }
  356. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  357. PetscFunctionReturn(0);
  358. }
  359. #undef __FUNCT__
  360. #define __FUNCT__ "PetscDrawCheckResizedWindow_X"
  361. static PetscErrorCode PetscDrawCheckResizedWindow_X(PetscDraw draw)
  362. {
  363. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  364. int xywh[4];
  365. PetscMPIInt rank;
  366. PetscErrorCode ierr;
  367. PetscFunctionBegin;
  368. if (!win->win) PetscFunctionReturn(0);
  369. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  370. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  371. if (!rank) {ierr = PetscDrawXiGetGeometry(win,xywh,xywh+1,xywh+2,xywh+3);CHKERRQ(ierr);}
  372. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  373. ierr = MPI_Bcast(xywh,4,MPI_INT,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  374. /* record new window position */
  375. draw->x = win->x = xywh[0];
  376. draw->y = win->y = xywh[1];
  377. if (xywh[2] == win->w && xywh[3] == win->h) PetscFunctionReturn(0);
  378. /* record new window sizes */
  379. draw->w = win->w = xywh[2];
  380. draw->h = win->h = xywh[3];
  381. /* recreate pixmap (only first processor does this) */
  382. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  383. if (!rank && win->drw) {ierr = PetscDrawXiQuickPixmap(win);CHKERRQ(ierr);}
  384. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  385. ierr = MPI_Bcast(&win->drw,1,MPI_UNSIGNED_LONG,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  386. /* reset the clipping */
  387. ierr = PetscDrawSetViewport_X(draw,draw->port_xl,draw->port_yl,draw->port_xr,draw->port_yr);CHKERRQ(ierr);
  388. PetscFunctionReturn(0);
  389. }
  390. #undef __FUNCT__
  391. #define __FUNCT__ "PetscDrawResizeWindow_X"
  392. static PetscErrorCode PetscDrawResizeWindow_X(PetscDraw draw,int w,int h)
  393. {
  394. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  395. PetscMPIInt rank;
  396. PetscErrorCode ierr;
  397. PetscFunctionBegin;
  398. if (w == win->w && h == win->h) PetscFunctionReturn(0);
  399. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  400. if (win->win) {
  401. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  402. if (!rank) {ierr = PetscDrawXiResizeWindow(win,w,h);CHKERRQ(ierr);}
  403. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  404. ierr = PetscDrawCheckResizedWindow_X(draw);CHKERRQ(ierr);
  405. } else if (win->drw) {
  406. draw->w = win->w = w; draw->h = win->h = h;
  407. /* recreate pixmap (only first processor does this) */
  408. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  409. if (!rank) {ierr = PetscDrawXiQuickPixmap(win);CHKERRQ(ierr);}
  410. ierr = MPI_Bcast(&win->drw,1,MPI_UNSIGNED_LONG,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  411. /* reset the clipping */
  412. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  413. ierr = PetscDrawSetViewport_X(draw,draw->port_xl,draw->port_yl,draw->port_xr,draw->port_yr);CHKERRQ(ierr);
  414. }
  415. PetscFunctionReturn(0);
  416. }
  417. #include <X11/cursorfont.h>
  418. #undef __FUNCT__
  419. #define __FUNCT__ "PetscDrawGetMouseButton_X"
  420. static PetscErrorCode PetscDrawGetMouseButton_X(PetscDraw draw,PetscDrawButton *button,PetscReal *x_user,PetscReal *y_user,PetscReal *x_phys,PetscReal *y_phys)
  421. {
  422. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  423. Cursor cursor;
  424. XEvent report;
  425. Window root,child;
  426. int root_x,root_y,px=0,py=0;
  427. unsigned int w,h,border,depth;
  428. unsigned int keys_button;
  429. PetscMPIInt rank;
  430. PetscReal xx,yy;
  431. PetscErrorCode ierr;
  432. PetscFunctionBegin;
  433. *button = PETSC_BUTTON_NONE;
  434. if (!win->win) PetscFunctionReturn(0);
  435. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  436. ierr = PetscDrawCollectiveBegin(draw);CHKERRQ(ierr);
  437. if (rank) goto finally;
  438. /* change cursor to indicate input */
  439. cursor = XCreateFontCursor(win->disp,XC_hand2); if (!cursor) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X cursor");
  440. XDefineCursor(win->disp,win->win,cursor);
  441. /* wait for mouse button events */
  442. XSelectInput(win->disp,win->win,ButtonPressMask|ButtonReleaseMask);
  443. while (XCheckTypedEvent(win->disp,ButtonPress,&report));
  444. XMaskEvent(win->disp,ButtonReleaseMask,&report);
  445. /* get mouse pointer coordinates */
  446. XQueryPointer(win->disp,report.xmotion.window,&root,&child,&root_x,&root_y,&px,&py,&keys_button);
  447. /* the user may resize the window before pressing the mouse button */
  448. XGetGeometry(win->disp,win->win,&root,&root_x,&root_y,&w,&h,&border,&depth);
  449. /* cleanup input event handler and cursor */
  450. XSelectInput(win->disp,win->win,NoEventMask);
  451. XUndefineCursor(win->disp,win->win);
  452. XFreeCursor(win->disp, cursor);
  453. XSync(win->disp,False);
  454. switch (report.xbutton.button) {
  455. case Button1: *button = PETSC_BUTTON_LEFT; break;
  456. case Button2: *button = PETSC_BUTTON_CENTER; break;
  457. case Button3: *button = PETSC_BUTTON_RIGHT; break;
  458. case Button4: *button = PETSC_BUTTON_WHEEL_UP; break;
  459. case Button5: *button = PETSC_BUTTON_WHEEL_DOWN; break;
  460. }
  461. if (report.xbutton.state & ShiftMask) {
  462. switch (report.xbutton.button) {
  463. case Button1: *button = PETSC_BUTTON_LEFT_SHIFT; break;
  464. case Button2: *button = PETSC_BUTTON_CENTER_SHIFT; break;
  465. case Button3: *button = PETSC_BUTTON_RIGHT_SHIFT; break;
  466. }
  467. }
  468. xx = ((PetscReal)px)/w;
  469. yy = 1 - ((PetscReal)py)/h;
  470. if (x_user) *x_user = draw->coor_xl + (xx - draw->port_xl)*(draw->coor_xr - draw->coor_xl)/(draw->port_xr - draw->port_xl);
  471. if (y_user) *y_user = draw->coor_yl + (yy - draw->port_yl)*(draw->coor_yr - draw->coor_yl)/(draw->port_yr - draw->port_yl);
  472. if (x_phys) *x_phys = xx;
  473. if (y_phys) *y_phys = yy;
  474. finally:
  475. ierr = PetscDrawCollectiveEnd(draw);CHKERRQ(ierr);
  476. ierr = PetscDrawCheckResizedWindow_X(draw);CHKERRQ(ierr);
  477. PetscFunctionReturn(0);
  478. }
  479. #undef __FUNCT__
  480. #define __FUNCT__ "PetscDrawPause_X"
  481. static PetscErrorCode PetscDrawPause_X(PetscDraw draw)
  482. {
  483. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  484. PetscErrorCode ierr;
  485. PetscFunctionBegin;
  486. if (!win->win) PetscFunctionReturn(0);
  487. if (draw->pause > 0) PetscSleep(draw->pause);
  488. else if (draw->pause == -1) {
  489. PetscDrawButton button = PETSC_BUTTON_NONE;
  490. ierr = PetscDrawGetMouseButton(draw,&button,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
  491. if (button == PETSC_BUTTON_CENTER) draw->pause = 0;
  492. }
  493. PetscFunctionReturn(0);
  494. }
  495. #undef __FUNCT__
  496. #define __FUNCT__ "PetscDrawDestroy_X"
  497. static PetscErrorCode PetscDrawDestroy_X(PetscDraw draw)
  498. {
  499. PetscDraw_X *win = (PetscDraw_X*)draw->data;
  500. PetscErrorCode ierr;
  501. PetscFunctionBegin;
  502. ierr = PetscDrawDestroy(&draw->popup);CHKERRQ(ierr);
  503. ierr = PetscDrawXiClose(win);CHKERRQ(ierr);
  504. ierr = PetscFree(draw->data);CHKERRQ(ierr);
  505. PetscFunctionReturn(0);
  506. }
  507. static PetscErrorCode PetscDrawGetSingleton_X(PetscDraw,PetscDraw*);
  508. static PetscErrorCode PetscDrawRestoreSingleton_X(PetscDraw,PetscDraw*);
  509. PETSC_INTERN PetscErrorCode PetscDrawGetImage_X(PetscDraw,unsigned char[][3],unsigned int*,unsigned int*,unsigned char*[]);
  510. static struct _PetscDrawOps DvOps = { PetscDrawSetDoubleBuffer_X,
  511. PetscDrawFlush_X,
  512. PetscDrawLine_X,
  513. 0,
  514. 0,
  515. PetscDrawPoint_X,
  516. 0,
  517. PetscDrawString_X,
  518. PetscDrawStringVertical_X,
  519. PetscDrawStringSetSize_X,
  520. PetscDrawStringGetSize_X,
  521. PetscDrawSetViewport_X,
  522. PetscDrawClear_X,
  523. PetscDrawRectangle_X,
  524. PetscDrawTriangle_X,
  525. PetscDrawEllipse_X,
  526. PetscDrawGetMouseButton_X,
  527. PetscDrawPause_X,
  528. 0,
  529. 0,
  530. PetscDrawGetPopup_X,
  531. PetscDrawSetTitle_X,
  532. PetscDrawCheckResizedWindow_X,
  533. PetscDrawResizeWindow_X,
  534. PetscDrawDestroy_X,
  535. 0,
  536. PetscDrawGetSingleton_X,
  537. PetscDrawRestoreSingleton_X,
  538. 0,
  539. PetscDrawGetImage_X,
  540. 0,
  541. PetscDrawArrow_X,
  542. PetscDrawCoordinateToPixel_X,
  543. PetscDrawPixelToCoordinate_X,
  544. PetscDrawPointPixel_X,
  545. 0};
  546. #undef __FUNCT__
  547. #define __FUNCT__ "PetscDrawGetSingleton_X"
  548. static PetscErrorCode PetscDrawGetSingleton_X(PetscDraw draw,PetscDraw *sdraw)
  549. {
  550. PetscDraw_X *Xwin = (PetscDraw_X*)draw->data,*sXwin;
  551. PetscErrorCode ierr;
  552. PetscFunctionBegin;
  553. ierr = PetscDrawCreate(PETSC_COMM_SELF,draw->display,draw->title,draw->x,draw->y,draw->w,draw->h,sdraw);CHKERRQ(ierr);
  554. ierr = PetscObjectChangeTypeName((PetscObject)*sdraw,PETSC_DRAW_X);CHKERRQ(ierr);
  555. ierr = PetscMemcpy((*sdraw)->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
  556. if (draw->popup) {
  557. ierr = PetscDrawGetSingleton(draw->popup,&(*sdraw)->popup);CHKERRQ(ierr);
  558. }
  559. (*sdraw)->pause = draw->pause;
  560. (*sdraw)->coor_xl = draw->coor_xl;
  561. (*sdraw)->coor_xr = draw->coor_xr;
  562. (*sdraw)->coor_yl = draw->coor_yl;
  563. (*sdraw)->coor_yr = draw->coor_yr;
  564. (*sdraw)->port_xl = draw->port_xl;
  565. (*sdraw)->port_xr = draw->port_xr;
  566. (*sdraw)->port_yl = draw->port_yl;
  567. (*sdraw)->port_yr = draw->port_yr;
  568. /* share drawables (windows and/or pixmap) from the parent draw */
  569. ierr = PetscNewLog(*sdraw,&sXwin);CHKERRQ(ierr);
  570. (*sdraw)->data = (void*)sXwin;
  571. ierr = PetscDrawXiInit(sXwin,draw->display);CHKERRQ(ierr);
  572. if (Xwin->win) {
  573. ierr = PetscDrawXiQuickWindowFromWindow(sXwin,Xwin->win);CHKERRQ(ierr);
  574. sXwin->drw = Xwin->drw; /* XXX If the window is ever resized, this is wrong! */
  575. } else if (Xwin->drw) {
  576. ierr = PetscDrawXiColormap(sXwin);CHKERRQ(ierr);
  577. sXwin->drw = Xwin->drw;
  578. }
  579. ierr = PetscDrawXiGetGeometry(sXwin,&sXwin->x,&sXwin->y,&sXwin->w,&sXwin->h);CHKERRQ(ierr);
  580. (*sdraw)->x = sXwin->x; (*sdraw)->y = sXwin->y;
  581. (*sdraw)->w = sXwin->w; (*sdraw)->h = sXwin->h;
  582. PetscFunctionReturn(0);
  583. }
  584. #undef __FUNCT__
  585. #define __FUNCT__ "PetscDrawRestoreSingleton_X"
  586. static PetscErrorCode PetscDrawRestoreSingleton_X(PetscDraw draw,PetscDraw *sdraw)
  587. {
  588. PetscErrorCode ierr;
  589. PetscFunctionBegin;
  590. if (draw->popup && (*sdraw)->popup) {
  591. PetscBool isdrawx;
  592. PetscDraw_X *pXwin = (PetscDraw_X*)draw->popup->data;
  593. PetscDraw_X *sXwin = (PetscDraw_X*)(*sdraw)->popup->data;
  594. ierr = PetscObjectTypeCompare((PetscObject)draw->popup,PETSC_DRAW_X,&isdrawx);CHKERRQ(ierr);
  595. if (!isdrawx) goto finally;
  596. ierr = PetscObjectTypeCompare((PetscObject)(*sdraw)->popup,PETSC_DRAW_X,&isdrawx);CHKERRQ(ierr);
  597. if (!isdrawx) goto finally;
  598. if (sXwin->win == pXwin->win) {
  599. ierr = PetscDrawRestoreSingleton(draw->popup,&(*sdraw)->popup);CHKERRQ(ierr);
  600. }
  601. }
  602. finally:
  603. ierr = PetscDrawDestroy(sdraw);CHKERRQ(ierr);
  604. PetscFunctionReturn(0);
  605. }
  606. #undef __FUNCT__
  607. #define __FUNCT__ "PetscDrawXGetDisplaySize_Private"
  608. static PetscErrorCode PetscDrawXGetDisplaySize_Private(const char name[],int *width,int *height)
  609. {
  610. Display *display;
  611. PetscFunctionBegin;
  612. display = XOpenDisplay(name);
  613. if (!display) {
  614. *width = *height = 0;
  615. SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\
  616. Make sure your COMPUTE NODES are authorized to connect\n\
  617. to this X server and either your DISPLAY variable\n\
  618. is set or you use the -display name option\n",name);
  619. }
  620. *width = (int)DisplayWidth(display,DefaultScreen(display));
  621. *height = (int)DisplayHeight(display,DefaultScreen(display));
  622. XCloseDisplay(display);
  623. PetscFunctionReturn(0);
  624. }
  625. /*MC
  626. PETSC_DRAW_X - PETSc graphics device that uses either X windows or its virtual version Xvfb
  627. Options Database Keys:
  628. + -display <display> - sets the display to use
  629. . -x_virtual - forces use of a X virtual display Xvfb that will not display anything but -draw_save will still work.
  630. Xvfb is automatically started up in PetscSetDisplay() with this option
  631. . -draw_size w,h - percentage of screeen (either 1, .5, .3, .25), or size in pixels
  632. . -geometry x,y,w,h - set location and size in pixels
  633. . -draw_virtual - do not open a window (draw on a pixmap), -draw_save will still work
  634. - -draw_double_buffer - avoid window flickering (draw on pixmap and flush to window)
  635. Level: beginner
  636. .seealso: PetscDrawOpenX(), PetscDrawSetDisplay(), PetscDrawSetFromOptions()
  637. M*/
  638. #undef __FUNCT__
  639. #define __FUNCT__ "PetscDrawCreate_X"
  640. PETSC_EXTERN PetscErrorCode PetscDrawCreate_X(PetscDraw draw)
  641. {
  642. PetscDraw_X *Xwin;
  643. PetscErrorCode ierr;
  644. PetscMPIInt rank;
  645. int x = draw->x,y = draw->y,w = draw->w,h = draw->h;
  646. static int xavailable = 0,yavailable = 0,ybottom = 0,xmax = 0,ymax = 0;
  647. PetscBool set,dvirtual = PETSC_FALSE,doublebuffer = PETSC_TRUE;
  648. PetscInt xywh[4],osize = 4,nsizes=2;
  649. PetscReal sizes[2] = {.3,.3};
  650. PetscFunctionBegin;
  651. /* get the display variable */
  652. if (!draw->display) {
  653. ierr = PetscMalloc1(256,&draw->display);CHKERRQ(ierr);
  654. ierr = PetscGetDisplay(draw->display,256);CHKERRQ(ierr);
  655. }
  656. /* initialize the display size */
  657. if (!xmax) {
  658. ierr = PetscDrawXGetDisplaySize_Private(draw->display,&xmax,&ymax);
  659. /* if some processors fail on this and others succed then this is a problem ! */
  660. if (ierr) {
  661. (*PetscErrorPrintf)("PETSc unable to use X windows\nproceeding without graphics\n");
  662. ierr = PetscDrawSetType(draw,PETSC_DRAW_NULL);CHKERRQ(ierr);
  663. PetscFunctionReturn(0);
  664. }
  665. }
  666. /* allow user to set size of drawable */
  667. ierr = PetscOptionsGetRealArray(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_size",sizes,&nsizes,&set);CHKERRQ(ierr);
  668. if (set && nsizes == 1 && sizes[0] > 1.0) sizes[1] = sizes[0];
  669. if (set) {
  670. if (sizes[0] > 1.0) w = (int)sizes[0];
  671. else if (sizes[0] == 1.0) w = PETSC_DRAW_FULL_SIZE;
  672. else if (sizes[0] == .5) w = PETSC_DRAW_HALF_SIZE;
  673. else if (sizes[0] == .3) w = PETSC_DRAW_THIRD_SIZE;
  674. else if (sizes[0] == .25) w = PETSC_DRAW_QUARTER_SIZE;
  675. if (sizes[1] > 1.0) h = (int)sizes[1];
  676. else if (sizes[1] == 1.0) h = PETSC_DRAW_FULL_SIZE;
  677. else if (sizes[1] == .5) h = PETSC_DRAW_HALF_SIZE;
  678. else if (sizes[1] == .3) h = PETSC_DRAW_THIRD_SIZE;
  679. else if (sizes[1] == .25) h = PETSC_DRAW_QUARTER_SIZE;
  680. }
  681. if (w == PETSC_DECIDE || w == PETSC_DEFAULT) w = draw->w = 300;
  682. if (h == PETSC_DECIDE || h == PETSC_DEFAULT) h = draw->h = 300;
  683. switch (w) {
  684. case PETSC_DRAW_FULL_SIZE: w = draw->w = (xmax - 10); break;
  685. case PETSC_DRAW_HALF_SIZE: w = draw->w = (xmax - 20)/2; break;
  686. case PETSC_DRAW_THIRD_SIZE: w = draw->w = (xmax - 30)/3; break;
  687. case PETSC_DRAW_QUARTER_SIZE: w = draw->w = (xmax - 40)/4; break;
  688. }
  689. switch (h) {
  690. case PETSC_DRAW_FULL_SIZE: h = draw->h = (ymax - 10); break;
  691. case PETSC_DRAW_HALF_SIZE: h = draw->h = (ymax - 20)/2; break;
  692. case PETSC_DRAW_THIRD_SIZE: h = draw->h = (ymax - 30)/3; break;
  693. case PETSC_DRAW_QUARTER_SIZE: h = draw->h = (ymax - 40)/4; break;
  694. }
  695. ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_virtual",&dvirtual,NULL);CHKERRQ(ierr);
  696. if (!dvirtual) {
  697. /* allow user to set location and size of window */
  698. xywh[0] = x; xywh[1] = y; xywh[2] = w; xywh[3] = h;
  699. ierr = PetscOptionsGetIntArray(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-geometry",xywh,&osize,NULL);CHKERRQ(ierr);
  700. x = (int)xywh[0]; y = (int)xywh[1]; w = (int)xywh[2]; h = (int)xywh[3];
  701. if (w == PETSC_DECIDE || w == PETSC_DEFAULT) w = 300;
  702. if (h == PETSC_DECIDE || h == PETSC_DEFAULT) h = 300;
  703. draw->x = x; draw->y = y; draw->w = w; draw->h = h;
  704. if (draw->x == PETSC_DECIDE || draw->y == PETSC_DECIDE) {
  705. /*
  706. PETSc tries to place windows starting in the upper left corner
  707. and moving across to the right.
  708. +0,0-------------------------------------------+
  709. | Region used so far +xavailable,yavailable |
  710. | | |
  711. | | |
  712. +--------------------- +ybottom |
  713. | |
  714. | |
  715. +----------------------------------------------+xmax,ymax
  716. */
  717. /* First: can we add it to the right? */
  718. if (xavailable + w + 10 <= xmax) {
  719. x = xavailable;
  720. y = yavailable;
  721. ybottom = PetscMax(ybottom,y + h + 30);
  722. } else {
  723. /* No, so add it below on the left */
  724. xavailable = x = 0;
  725. yavailable = y = ybottom;
  726. ybottom = ybottom + h + 30;
  727. }
  728. }
  729. /* update available region */
  730. xavailable = PetscMax(xavailable,x + w + 10);
  731. if (xavailable >= xmax) {
  732. xavailable = 0;
  733. yavailable = yavailable + h + 30;
  734. ybottom = yavailable;
  735. }
  736. if (yavailable >= ymax) {
  737. y = 0;
  738. yavailable = 0;
  739. ybottom = 0;
  740. }
  741. } /* endif(!dvirtual) */
  742. ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
  743. if (!rank && (w <= 0 || h <= 0)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative window width or height");
  744. ierr = PetscNewLog(draw,&Xwin);CHKERRQ(ierr);
  745. ierr = PetscMemcpy(draw->ops,&DvOps,sizeof(DvOps));CHKERRQ(ierr);
  746. draw->data = (void*)Xwin;
  747. ierr = PetscDrawXiInit(Xwin,draw->display);CHKERRQ(ierr);
  748. if (!dvirtual) {
  749. Xwin->x = x; Xwin->y = y;
  750. Xwin->w = w; Xwin->h = h;
  751. if (!rank) {ierr = PetscDrawXiQuickWindow(Xwin,draw->title,x,y,w,h);CHKERRQ(ierr);}
  752. ierr = MPI_Bcast(&Xwin->win,1,MPI_UNSIGNED_LONG,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  753. if (rank) {ierr = PetscDrawXiQuickWindowFromWindow(Xwin,Xwin->win);CHKERRQ(ierr);}
  754. } else {
  755. Xwin->x = 0; Xwin->y = 0;
  756. Xwin->w = w; Xwin->h = h;
  757. ierr = PetscDrawXiColormap(Xwin);CHKERRQ(ierr);
  758. if (!rank) {ierr = PetscDrawXiQuickPixmap(Xwin);CHKERRQ(ierr);}
  759. ierr = MPI_Bcast(&Xwin->drw,1,MPI_UNSIGNED_LONG,0,PetscObjectComm((PetscObject)draw));CHKERRQ(ierr);
  760. }
  761. ierr = PetscDrawXiGetGeometry(Xwin,&Xwin->x,&Xwin->y,&Xwin->w,&Xwin->h);CHKERRQ(ierr);
  762. draw->x = Xwin->x; draw->y = Xwin->y;
  763. draw->w = Xwin->w; draw->h = Xwin->h;
  764. ierr = PetscOptionsGetBool(((PetscObject)draw)->options,((PetscObject)draw)->prefix,"-draw_double_buffer",&doublebuffer,NULL);CHKERRQ(ierr);
  765. if (doublebuffer) {ierr = PetscDrawSetDoubleBuffer(draw);CHKERRQ(ierr);}
  766. PetscFunctionReturn(0);
  767. }