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