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 #undef __FUNCT__ 22 #define __FUNCT__ "PetscDrawXiOpenDisplay" 23 static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[]) 24 { 25 PetscFunctionBegin; 26 XiWin->disp = XOpenDisplay(display); 27 if (!XiWin->disp) { 28 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\ 29 Make sure your COMPUTE NODES are authorized to connect \n\ 30 to this X server and either your DISPLAY variable\n\ 31 is set or you use the -display name option\n",display); 32 } 33 XiWin->screen = DefaultScreen(XiWin->disp); 34 XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen); 35 XiWin->depth = DefaultDepth(XiWin->disp,XiWin->screen); 36 XiWin->cmap = DefaultColormap(XiWin->disp,XiWin->screen); 37 XiWin->background = WhitePixel(XiWin->disp,XiWin->screen); 38 XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen); 39 PetscFunctionReturn(0); 40 } 41 42 #undef __FUNCT__ 43 #define __FUNCT__ "PetscDrawXiClose" 44 PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin) 45 { 46 PetscErrorCode ierr; 47 48 PetscFunctionBegin; 49 if (!XiWin) PetscFunctionReturn(0); 50 ierr = PetscFree(XiWin->font);CHKERRQ(ierr); 51 if (XiWin->disp) { 52 #if defined(PETSC_HAVE_SETJMP_H) 53 jmp_buf jmpbuf; 54 PetscXIOErrorHandler xioerrhdl; 55 ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr); 56 xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump); 57 if (!setjmp(PetscXIOErrorHandlerJumpBuf)) 58 #endif 59 { 60 XFreeGC(XiWin->disp,XiWin->gc.set); 61 XCloseDisplay(XiWin->disp); 62 } 63 XiWin->disp = NULL; 64 #if defined(PETSC_HAVE_SETJMP_H) 65 (void)PetscSetXIOErrorHandler(xioerrhdl); 66 ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr); 67 #endif 68 } 69 PetscFunctionReturn(0); 70 } 71 72 /* 73 PetscDrawXiCreateGC - setup the GC structure 74 */ 75 #undef __FUNCT__ 76 #define __FUNCT__ "PetscDrawXiCreateGC" 77 static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg) 78 { 79 XGCValues gcvalues; /* window graphics context values */ 80 81 PetscFunctionBegin; 82 /* Set the graphics contexts */ 83 /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */ 84 /* (do this with function GXcopy; GXset will automatically write 1) */ 85 gcvalues.function = GXcopy; 86 gcvalues.foreground = fg; 87 XiWin->gc.cur_pix = fg; 88 XiWin->gc.set = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues); 89 if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context"); 90 PetscFunctionReturn(0); 91 } 92 93 /* 94 PetscDrawXiInit - basic setup the draw (display, graphics context, font) 95 */ 96 #undef __FUNCT__ 97 #define __FUNCT__ "PetscDrawXiInit" 98 PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[]) 99 { 100 PetscErrorCode ierr; 101 PetscFunctionBegin; 102 ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr); 103 ierr = PetscDrawXiCreateGC(XiWin,XiWin->foreground);CHKERRQ(ierr); 104 ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr); 105 PetscFunctionReturn(0); 106 } 107 108 /* 109 This routine waits until the window is actually created or destroyed 110 Returns 0 if window is mapped; 1 if window is destroyed. 111 */ 112 #undef __FUNCT__ 113 #define __FUNCT__ "PetscDrawXiWaitMap" 114 static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin) 115 { 116 XEvent event; 117 118 PetscFunctionBegin; 119 while (1) { 120 XMaskEvent(XiWin->disp,ExposureMask|StructureNotifyMask,&event); 121 if (event.xany.window != XiWin->win) break; 122 else { 123 switch (event.type) { 124 case ConfigureNotify: 125 /* window has been moved or resized */ 126 XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width; 127 XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width; 128 break; 129 case DestroyNotify: 130 PetscFunctionReturn(1); 131 case Expose: 132 PetscFunctionReturn(0); 133 /* else ignore event */ 134 } 135 } 136 } 137 PetscFunctionReturn(0); 138 } 139 140 /* 141 Actually display a window at [x,y] with sizes (w,h) 142 */ 143 #undef __FUNCT__ 144 #define __FUNCT__ "PetscDrawXiDisplayWindow" 145 static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h) 146 { 147 unsigned int wavail,havail; 148 XSizeHints size_hints; 149 XWindowAttributes in_window_attributes; 150 XSetWindowAttributes window_attributes; 151 unsigned int border_width = 0; 152 unsigned long backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen); 153 unsigned long wmask; 154 155 PetscFunctionBegin; 156 /* get the available widths */ 157 wavail = DisplayWidth(XiWin->disp,XiWin->screen); 158 havail = DisplayHeight(XiWin->disp,XiWin->screen); 159 if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width"); 160 if ((unsigned int)w > wavail) w = wavail; 161 if ((unsigned int)h > havail) h = havail; 162 163 if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x); 164 if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y); 165 x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x; 166 y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y; 167 168 /* We need XCreateWindow since we may need an visual other than the default one */ 169 XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes); 170 window_attributes.background_pixmap = None; 171 window_attributes.background_pixel = backgnd_pixel; 172 /* No border for now */ 173 window_attributes.border_pixmap = None; 174 /* 175 window_attributes.border_pixel = border_pixel; 176 */ 177 window_attributes.bit_gravity = in_window_attributes.bit_gravity; 178 window_attributes.win_gravity = in_window_attributes.win_gravity; 179 /* Backing store is too slow in color systems */ 180 window_attributes.backing_store = NotUseful; 181 window_attributes.backing_pixel = backgnd_pixel; 182 window_attributes.save_under = 1; 183 window_attributes.event_mask = 0; 184 window_attributes.do_not_propagate_mask = 0; 185 window_attributes.override_redirect = 0; 186 window_attributes.colormap = XiWin->cmap; 187 /* None for cursor does NOT mean none, it means cursor of Parent */ 188 window_attributes.cursor = None; 189 190 wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | 191 CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | 192 CWSaveUnder | CWEventMask | CWDontPropagate | 193 CWCursor | CWColormap; 194 195 XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes); 196 if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window"); 197 198 /* set window manager hints */ 199 { 200 XWMHints wm_hints; 201 XClassHint class_hints; 202 XTextProperty windowname,iconname; 203 204 if (label) XStringListToTextProperty(&label,1,&windowname); 205 else XStringListToTextProperty(&label,0,&windowname); 206 if (label) XStringListToTextProperty(&label,1,&iconname); 207 else XStringListToTextProperty(&label,0,&iconname); 208 209 wm_hints.initial_state = NormalState; 210 wm_hints.input = True; 211 wm_hints.flags = StateHint|InputHint; 212 213 /* These properties can be used by window managers to decide how to display a window */ 214 class_hints.res_name = (char*)"petsc"; 215 class_hints.res_class = (char*)"PETSc"; 216 217 size_hints.x = x; 218 size_hints.y = y; 219 size_hints.min_width = 4*border_width; 220 size_hints.min_height = 4*border_width; 221 size_hints.width = w; 222 size_hints.height = h; 223 size_hints.flags = USPosition | USSize | PMinSize; 224 225 XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints); 226 XFree((void*)windowname.value); 227 XFree((void*)iconname.value); 228 } 229 230 /* make the window visible */ 231 XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask); 232 XMapWindow(XiWin->disp,XiWin->win); 233 /* some window systems are cruel and interfere with the placement of 234 windows. We wait here for the window to be created or to die */ 235 if (PetscDrawXiWaitMap(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed"); 236 XSelectInput(XiWin->disp,XiWin->win,NoEventMask); 237 PetscFunctionReturn(0); 238 } 239 240 #undef __FUNCT__ 241 #define __FUNCT__ "PetscDrawXiQuickWindow" 242 PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny) 243 { 244 PetscErrorCode ierr; 245 246 PetscFunctionBegin; 247 ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr); 248 ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr); 249 XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background); 250 XClearWindow(XiWin->disp,XiWin->win); 251 PetscFunctionReturn(0); 252 } 253 254 /* 255 A version from an already defined window 256 */ 257 #undef __FUNCT__ 258 #define __FUNCT__ "PetscDrawXiQuickWindowFromWindow" 259 PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win) 260 { 261 XWindowAttributes attributes; 262 PetscErrorCode ierr; 263 264 PetscFunctionBegin; 265 XiWin->win = win; 266 XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes); 267 ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr); 268 PetscFunctionReturn(0); 269 } 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "PetscDrawXiQuickPixmap" 273 PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin) 274 { 275 PetscFunctionBegin; 276 if (XiWin->drw) XFreePixmap(XiWin->disp,XiWin->drw); 277 XiWin->drw = XCreatePixmap(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),XiWin->w,XiWin->h,XiWin->depth); 278 PetscDrawXiSetPixVal(XiWin,XiWin->background); 279 XFillRectangle(XiWin->disp,XiWin->drw,XiWin->gc.set,0,0,XiWin->w,XiWin->h); 280 XSync(XiWin->disp,False); 281 PetscFunctionReturn(0); 282 } 283 284 #undef __FUNCT__ 285 #define __FUNCT__ "PetscDrawXiResizeWindow" 286 PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X* XiWin,int w,int h) 287 { 288 XEvent event; 289 PetscFunctionBegin; 290 XSelectInput(XiWin->disp,XiWin->win,StructureNotifyMask); 291 XResizeWindow(XiWin->disp,XiWin->win,(unsigned int)w,(unsigned int)h); 292 XWindowEvent(XiWin->disp,XiWin->win,StructureNotifyMask,&event); 293 XSelectInput(XiWin->disp,XiWin->win,NoEventMask); 294 PetscFunctionReturn(0); 295 } 296 297 #undef __FUNCT__ 298 #define __FUNCT__ "PetscDrawXiGetGeometry" 299 PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin,int *x,int *y,int *w,int *h) 300 { 301 XWindowAttributes attributes; 302 Window root,parent,child; 303 int xx=0,yy=0; 304 unsigned int ww=0,hh=0,dummy; 305 PetscFunctionBegin; 306 if (XiWin->win) { 307 XGetGeometry(XiWin->disp,XiWin->win,&parent,&xx,&yy,&ww,&hh,&dummy,&dummy); 308 root = RootWindow(XiWin->disp,XiWin->screen); 309 if (!XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child)) { 310 XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes); 311 root = attributes.screen->root; 312 (void)XTranslateCoordinates(XiWin->disp,XiWin->win,root,0,0,&xx,&yy,&child); 313 } 314 } else if (XiWin->drw) { 315 XGetGeometry(XiWin->disp,XiWin->drw,&root,&xx,&yy,&ww,&hh,&dummy,&dummy); 316 } 317 if (x) *x = xx; 318 if (y) *y = yy; 319 if (w) *w = (int)ww; 320 if (h) *h = (int)hh; 321 PetscFunctionReturn(0); 322 } 323