Actual source code: xinit.c

      1: /*
      2:    This file contains routines to open an X window display and window
      3:    This consists of a number of routines that set the various
      4:    fields in the Window structure, which is passed to
      5:    all of these routines.

      7:    Note that if you use the default visual and colormap, then you
      8:    can use these routines with any X toolkit that will give you the
      9:    Window id of the window that it is managing.  Use that instead of the
     10:    call to PetscDrawXiCreateWindow .  Similarly for the Display.
     11: */

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

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

     17: /*
     18:   PetscDrawXiOpenDisplay - Open and setup a display
     19: */
     20: static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin, const char display[])
     21: {
     22:   PetscFunctionBegin;
     23:   XiWin->disp = XOpenDisplay(display);
     24:   if (!XiWin->disp) {
     25:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open display on %s\n\
     26:     Make sure your COMPUTE NODES are authorized to connect \n\
     27:     to this X server and either your DISPLAY variable\n\
     28:     is set or you use the -display name option\n",
     29:             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(PETSC_SUCCESS);
     38: }

     40: PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
     41: {
     42:   PetscFunctionBegin;
     43:   if (!XiWin) PetscFunctionReturn(PETSC_SUCCESS);
     44:   PetscCall(PetscFree(XiWin->font));
     45:   if (XiWin->disp) {
     46: #if defined(PETSC_HAVE_SETJMP_H)
     47:     jmp_buf                 jmpbuf;
     48:     PetscXIOErrorHandlerFn *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(PETSC_SUCCESS);
     64: }

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

     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(PETSC_SUCCESS);
     83: }

     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(PETSC_SUCCESS);
     95: }

     97: /*
     98:     This routine waits until the window is actually created. If the window was
     99:     never mapped it generates an error
    100: */
    101: static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin)
    102: {
    103:   XEvent event;

    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:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Window was not properly created");
    118:       case Expose:
    119:         PetscFunctionReturn(PETSC_SUCCESS);
    120:         /* else ignore event */
    121:       }
    122:     }
    123:   }
    124:   PetscFunctionReturn(PETSC_SUCCESS);
    125: }

    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;

    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;

    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;

    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;

    175:   wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWDontPropagate | CWCursor | CWColormap;

    177:   XiWin->win = XCreateWindow(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), x, y, w, h, border_width, XiWin->depth, InputOutput, XiWin->vis, wmask, &window_attributes);
    178:   PetscCheck(XiWin->win, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open X window");

    180:   /* set window manager hints */
    181:   {
    182:     XWMHints      wm_hints;
    183:     XClassHint    class_hints;
    184:     XTextProperty windowname, iconname;

    186:     if (label) XStringListToTextProperty(&label, 1, &windowname);
    187:     else XStringListToTextProperty(&label, 0, &windowname);
    188:     if (label) XStringListToTextProperty(&label, 1, &iconname);
    189:     else XStringListToTextProperty(&label, 0, &iconname);

    191:     wm_hints.initial_state = NormalState;
    192:     wm_hints.input         = True;
    193:     wm_hints.flags         = StateHint | InputHint;

    195:     /* These properties can be used by window managers to decide how to display a window */
    196:     class_hints.res_name  = (char *)"petsc";
    197:     class_hints.res_class = (char *)"PETSc";

    199:     size_hints.x          = x;
    200:     size_hints.y          = y;
    201:     size_hints.min_width  = 4 * border_width;
    202:     size_hints.min_height = 4 * border_width;
    203:     size_hints.width      = w;
    204:     size_hints.height     = h;
    205:     size_hints.flags      = USPosition | USSize | PMinSize;

    207:     XSetWMProperties(XiWin->disp, XiWin->win, &windowname, &iconname, NULL, 0, &size_hints, &wm_hints, &class_hints);
    208:     XFree((void *)windowname.value);
    209:     XFree((void *)iconname.value);
    210:   }

    212:   /* make the window visible */
    213:   XSelectInput(XiWin->disp, XiWin->win, ExposureMask | StructureNotifyMask);
    214:   XMapWindow(XiWin->disp, XiWin->win);
    215:   /* some window systems are cruel and interfere with the placement of
    216:      windows.  We wait here for the window to be created or to die */
    217:   PetscCall(PetscDrawXiWaitMap(XiWin));
    218:   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
    219:   PetscFunctionReturn(PETSC_SUCCESS);
    220: }

    222: PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin, char *name, int x, int y, int nx, int ny)
    223: {
    224:   PetscFunctionBegin;
    225:   PetscCall(PetscDrawSetColormap_X(XiWin, (Colormap)0));
    226:   PetscCall(PetscDrawXiDisplayWindow(XiWin, name, x, y, nx, ny));
    227:   XSetWindowBackground(XiWin->disp, XiWin->win, XiWin->background);
    228:   XClearWindow(XiWin->disp, XiWin->win);
    229:   PetscFunctionReturn(PETSC_SUCCESS);
    230: }

    232: /*
    233:    A version from an already defined window
    234: */
    235: PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin, Window win)
    236: {
    237:   XWindowAttributes attributes;

    239:   PetscFunctionBegin;
    240:   XiWin->win = win;
    241:   XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
    242:   PetscCall(PetscDrawSetColormap_X(XiWin, attributes.colormap));
    243:   PetscFunctionReturn(PETSC_SUCCESS);
    244: }

    246: PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X *XiWin)
    247: {
    248:   PetscFunctionBegin;
    249:   if (XiWin->drw) XFreePixmap(XiWin->disp, XiWin->drw);
    250:   XiWin->drw = XCreatePixmap(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), XiWin->w, XiWin->h, XiWin->depth);
    251:   PetscDrawXiSetPixVal(XiWin, XiWin->background);
    252:   XFillRectangle(XiWin->disp, XiWin->drw, XiWin->gc.set, 0, 0, XiWin->w, XiWin->h);
    253:   XSync(XiWin->disp, False);
    254:   PetscFunctionReturn(PETSC_SUCCESS);
    255: }

    257: PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h)
    258: {
    259:   XEvent event;

    261:   PetscFunctionBegin;
    262:   XSelectInput(XiWin->disp, XiWin->win, StructureNotifyMask);
    263:   XResizeWindow(XiWin->disp, XiWin->win, (unsigned int)w, (unsigned int)h);
    264:   XWindowEvent(XiWin->disp, XiWin->win, StructureNotifyMask, &event);
    265:   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
    266:   PetscFunctionReturn(PETSC_SUCCESS);
    267: }

    269: PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin, int *x, int *y, int *w, int *h)
    270: {
    271:   XWindowAttributes attributes;
    272:   Window            root, parent, child;
    273:   int               xx = 0, yy = 0;
    274:   unsigned int      ww = 0, hh = 0, dummy;

    276:   PetscFunctionBegin;
    277:   if (XiWin->win) {
    278:     XGetGeometry(XiWin->disp, XiWin->win, &parent, &xx, &yy, &ww, &hh, &dummy, &dummy);
    279:     root = RootWindow(XiWin->disp, XiWin->screen);
    280:     if (!XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child)) {
    281:       XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
    282:       root = attributes.screen->root;
    283:       (void)XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child);
    284:     }
    285:   } else if (XiWin->drw) {
    286:     XGetGeometry(XiWin->disp, XiWin->drw, &root, &xx, &yy, &ww, &hh, &dummy, &dummy);
    287:   }
    288:   if (x) *x = xx;
    289:   if (y) *y = yy;
    290:   if (w) *w = (int)ww;
    291:   if (h) *h = (int)hh;
    292:   PetscFunctionReturn(PETSC_SUCCESS);
    293: }