Actual source code: xinit.c
petsc-3.7.1 2016-05-15
Report Typos and Errors

      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.

      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: */

     14: #include <../src/sys/classes/draw/impls/x/ximpl.h>

     16: PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);

     18: /*
     19:   PetscDrawXiOpenDisplay - Open and setup a display
     20: */
     23: static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
     24: {
     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:   return(0);
     40: }

     44: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
     45: {

     49:   if (!XiWin) return(0);
     50:   PetscFree(XiWin->font);
     51:   if (XiWin->disp) {
     52: #if defined(PETSC_HAVE_SETJMP_H)
     53:     jmp_buf              jmpbuf;
     54:     PetscXIOErrorHandler xioerrhdl;
     55:     PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));
     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:     PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));
     67: #endif
     68:   }
     69:   return(0);
     70: }

     72: /*
     73:    PetscDrawXiCreateGC - setup the GC structure
     74: */
     77: static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
     78: {
     79:   XGCValues gcvalues;             /* window graphics context values */

     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:   return(0);
     91: }

     93: /*
     94:    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
     95: */
     98: PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
     99: {
    102:   PetscDrawXiOpenDisplay(XiWin,display);
    103:   PetscDrawXiCreateGC(XiWin,XiWin->foreground);
    104:   PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);
    105:   return(0);
    106: }

    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:  */
    114: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
    115: {
    116:   XEvent event;

    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:         return(0);
    133:         /* else ignore event */
    134:       }
    135:     }
    136:   }
    137:   return(0);
    138: }

    140: /*
    141:     Actually display a window at [x,y] with sizes (w,h)
    142: */
    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;

    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;

    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;

    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;

    190:   wmask = CWBackPixmap | CWBackPixel    | CWBorderPixmap  | CWBitGravity |
    191:           CWWinGravity | CWBackingStore | CWBackingPixel  | CWOverrideRedirect |
    192:           CWSaveUnder  | CWEventMask    | CWDontPropagate |
    193:           CWCursor     | CWColormap;

    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");

    198:   /* set window manager hints */
    199:   {
    200:     XWMHints      wm_hints;
    201:     XClassHint    class_hints;
    202:     XTextProperty windowname,iconname;

    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);

    209:     wm_hints.initial_state = NormalState;
    210:     wm_hints.input         = True;
    211:     wm_hints.flags         = StateHint|InputHint;

    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";

    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;

    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:   }

    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:   return(0);
    238: }

    242: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
    243: {

    247:   PetscDrawSetColormap_X(XiWin,(Colormap)0);
    248:   PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);
    249:   XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
    250:   XClearWindow(XiWin->disp,XiWin->win);
    251:   return(0);
    252: }

    254: /*
    255:    A version from an already defined window
    256: */
    259: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
    260: {
    261:   XWindowAttributes attributes;
    262:   PetscErrorCode    ierr;

    265:   XiWin->win = win;
    266:   XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
    267:   PetscDrawSetColormap_X(XiWin,attributes.colormap);
    268:   return(0);
    269: }

    273: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin)
    274: {
    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:   return(0);
    282: }

    286: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X* XiWin,int w,int h)
    287: {
    288:   XEvent event;
    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:   return(0);
    295: }

    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;
    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:   return(0);
    322: }