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 */ 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 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 */ 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 */ 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 */ 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 */ 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,0,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 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 */ 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 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 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 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