15c6c1daeSBarry Smith /* 25c6c1daeSBarry Smith This file contains routines to open an X window display and window 35c6c1daeSBarry Smith This consists of a number of routines that set the various 45c6c1daeSBarry Smith fields in the Window structure, which is passed to 55c6c1daeSBarry Smith all of these routines. 65c6c1daeSBarry Smith 75c6c1daeSBarry Smith Note that if you use the default visual and colormap, then you 85c6c1daeSBarry Smith can use these routines with any X toolkit that will give you the 95c6c1daeSBarry Smith Window id of the window that it is managing. Use that instead of the 105c6c1daeSBarry Smith call to PetscDrawXiCreateWindow . Similarly for the Display. 115c6c1daeSBarry Smith */ 125c6c1daeSBarry Smith 135c6c1daeSBarry Smith #include <../src/sys/classes/draw/impls/x/ximpl.h> 145c6c1daeSBarry Smith 1545f3bb6eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap); 165c6c1daeSBarry Smith 175c6c1daeSBarry Smith /* 1815d5bc79SLisandro Dalcin PetscDrawXiOpenDisplay - Open and setup a display 195c6c1daeSBarry Smith */ 20d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin, const char display[]) 21d71ae5a4SJacob Faibussowitsch { 225c6c1daeSBarry Smith PetscFunctionBegin; 2315d5bc79SLisandro Dalcin XiWin->disp = XOpenDisplay(display); 245c6c1daeSBarry Smith if (!XiWin->disp) { 2598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open display on %s\n\ 2615d5bc79SLisandro Dalcin Make sure your COMPUTE NODES are authorized to connect \n\ 275c6c1daeSBarry Smith to this X server and either your DISPLAY variable\n\ 289371c9d4SSatish Balay is set or you use the -display name option\n", 299371c9d4SSatish Balay display); 305c6c1daeSBarry Smith } 315c6c1daeSBarry Smith XiWin->screen = DefaultScreen(XiWin->disp); 32481cee7bSLisandro Dalcin XiWin->vis = DefaultVisual(XiWin->disp, XiWin->screen); 33481cee7bSLisandro Dalcin XiWin->depth = DefaultDepth(XiWin->disp, XiWin->screen); 3415d5bc79SLisandro Dalcin XiWin->cmap = DefaultColormap(XiWin->disp, XiWin->screen); 3515d5bc79SLisandro Dalcin XiWin->background = WhitePixel(XiWin->disp, XiWin->screen); 3615d5bc79SLisandro Dalcin XiWin->foreground = BlackPixel(XiWin->disp, XiWin->screen); 373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 385c6c1daeSBarry Smith } 395c6c1daeSBarry Smith 40d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin) 41d71ae5a4SJacob Faibussowitsch { 42815f00f0SLisandro Dalcin PetscFunctionBegin; 433ba16761SJacob Faibussowitsch if (!XiWin) PetscFunctionReturn(PETSC_SUCCESS); 449566063dSJacob Faibussowitsch PetscCall(PetscFree(XiWin->font)); 45815f00f0SLisandro Dalcin if (XiWin->disp) { 46815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 47815f00f0SLisandro Dalcin jmp_buf jmpbuf; 488434afd1SBarry Smith PetscXIOErrorHandlerFn *xioerrhdl; 499566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&jmpbuf, &PetscXIOErrorHandlerJumpBuf, sizeof(jmpbuf))); 50815f00f0SLisandro Dalcin xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump); 51815f00f0SLisandro Dalcin if (!setjmp(PetscXIOErrorHandlerJumpBuf)) 52815f00f0SLisandro Dalcin #endif 53815f00f0SLisandro Dalcin { 54815f00f0SLisandro Dalcin XFreeGC(XiWin->disp, XiWin->gc.set); 55815f00f0SLisandro Dalcin XCloseDisplay(XiWin->disp); 56815f00f0SLisandro Dalcin } 57815f00f0SLisandro Dalcin XiWin->disp = NULL; 58815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 59815f00f0SLisandro Dalcin (void)PetscSetXIOErrorHandler(xioerrhdl); 609566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&PetscXIOErrorHandlerJumpBuf, &jmpbuf, sizeof(jmpbuf))); 61815f00f0SLisandro Dalcin #endif 62815f00f0SLisandro Dalcin } 633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64815f00f0SLisandro Dalcin } 65815f00f0SLisandro Dalcin 665c6c1daeSBarry Smith /* 6709440f25SLisandro Dalcin PetscDrawXiCreateGC - setup the GC structure 685c6c1daeSBarry Smith */ 69d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin, PetscDrawXiPixVal fg) 70d71ae5a4SJacob Faibussowitsch { 715c6c1daeSBarry Smith XGCValues gcvalues; /* window graphics context values */ 725c6c1daeSBarry Smith 735c6c1daeSBarry Smith PetscFunctionBegin; 745c6c1daeSBarry Smith /* Set the graphics contexts */ 755c6c1daeSBarry Smith /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */ 765c6c1daeSBarry Smith /* (do this with function GXcopy; GXset will automatically write 1) */ 775c6c1daeSBarry Smith gcvalues.function = GXcopy; 785c6c1daeSBarry Smith gcvalues.foreground = fg; 795c6c1daeSBarry Smith XiWin->gc.cur_pix = fg; 805c6c1daeSBarry Smith XiWin->gc.set = XCreateGC(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), GCFunction | GCForeground, &gcvalues); 8108401ef6SPierre Jolivet PetscCheck(XiWin->gc.set, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to create X graphics context"); 823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8315d5bc79SLisandro Dalcin } 8415d5bc79SLisandro Dalcin 8515d5bc79SLisandro Dalcin /* 86815f00f0SLisandro Dalcin PetscDrawXiInit - basic setup the draw (display, graphics context, font) 8715d5bc79SLisandro Dalcin */ 88d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin, const char display[]) 89d71ae5a4SJacob Faibussowitsch { 9015d5bc79SLisandro Dalcin PetscFunctionBegin; 919566063dSJacob Faibussowitsch PetscCall(PetscDrawXiOpenDisplay(XiWin, display)); 929566063dSJacob Faibussowitsch PetscCall(PetscDrawXiCreateGC(XiWin, XiWin->foreground)); 939566063dSJacob Faibussowitsch PetscCall(PetscDrawXiFontFixed(XiWin, 6, 10, &XiWin->font)); 943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 955c6c1daeSBarry Smith } 965c6c1daeSBarry Smith 975c6c1daeSBarry Smith /* 9811cc89d2SBarry Smith This routine waits until the window is actually created. If the window was 9911cc89d2SBarry Smith never mapped it generates an error 10009440f25SLisandro Dalcin */ 101d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin) 102d71ae5a4SJacob Faibussowitsch { 10309440f25SLisandro Dalcin XEvent event; 10409440f25SLisandro Dalcin 10509440f25SLisandro Dalcin PetscFunctionBegin; 10609440f25SLisandro Dalcin while (1) { 10709440f25SLisandro Dalcin XMaskEvent(XiWin->disp, ExposureMask | StructureNotifyMask, &event); 10809440f25SLisandro Dalcin if (event.xany.window != XiWin->win) break; 10909440f25SLisandro Dalcin else { 11009440f25SLisandro Dalcin switch (event.type) { 11109440f25SLisandro Dalcin case ConfigureNotify: 11209440f25SLisandro Dalcin /* window has been moved or resized */ 11309440f25SLisandro Dalcin XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width; 11409440f25SLisandro Dalcin XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width; 11509440f25SLisandro Dalcin break; 116d71ae5a4SJacob Faibussowitsch case DestroyNotify: 117d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Window was not properly created"); 11809440f25SLisandro Dalcin case Expose: 1193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12009440f25SLisandro Dalcin /* else ignore event */ 12109440f25SLisandro Dalcin } 12209440f25SLisandro Dalcin } 12309440f25SLisandro Dalcin } 1243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 12509440f25SLisandro Dalcin } 12609440f25SLisandro Dalcin 12709440f25SLisandro Dalcin /* 1285c6c1daeSBarry Smith Actually display a window at [x,y] with sizes (w,h) 1295c6c1daeSBarry Smith */ 130d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin, char *label, int x, int y, int w, int h) 131d71ae5a4SJacob Faibussowitsch { 1325c6c1daeSBarry Smith unsigned int wavail, havail; 1335c6c1daeSBarry Smith XSizeHints size_hints; 1345c6c1daeSBarry Smith XWindowAttributes in_window_attributes; 1355c6c1daeSBarry Smith XSetWindowAttributes window_attributes; 13615d5bc79SLisandro Dalcin unsigned int border_width = 0; 13715d5bc79SLisandro Dalcin unsigned long backgnd_pixel = WhitePixel(XiWin->disp, XiWin->screen); 1385c6c1daeSBarry Smith unsigned long wmask; 1395c6c1daeSBarry Smith 1405c6c1daeSBarry Smith PetscFunctionBegin; 1415c6c1daeSBarry Smith /* get the available widths */ 1425c6c1daeSBarry Smith wavail = DisplayWidth(XiWin->disp, XiWin->screen); 1435c6c1daeSBarry Smith havail = DisplayHeight(XiWin->disp, XiWin->screen); 144cc73adaaSBarry Smith PetscCheck(w > 0 && h > 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "X Window display has invalid height or width"); 1455c6c1daeSBarry Smith if ((unsigned int)w > wavail) w = wavail; 1465c6c1daeSBarry Smith if ((unsigned int)h > havail) h = havail; 1475c6c1daeSBarry Smith 14815d5bc79SLisandro Dalcin if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x); 14915d5bc79SLisandro Dalcin if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y); 15015d5bc79SLisandro Dalcin x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x; 15115d5bc79SLisandro Dalcin y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y; 1525c6c1daeSBarry Smith 1535c6c1daeSBarry Smith /* We need XCreateWindow since we may need an visual other than the default one */ 1545c6c1daeSBarry Smith XGetWindowAttributes(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), &in_window_attributes); 1555c6c1daeSBarry Smith window_attributes.background_pixmap = None; 1565c6c1daeSBarry Smith window_attributes.background_pixel = backgnd_pixel; 1575c6c1daeSBarry Smith /* No border for now */ 1585c6c1daeSBarry Smith window_attributes.border_pixmap = None; 1595c6c1daeSBarry Smith /* 1605c6c1daeSBarry Smith window_attributes.border_pixel = border_pixel; 1615c6c1daeSBarry Smith */ 1625c6c1daeSBarry Smith window_attributes.bit_gravity = in_window_attributes.bit_gravity; 1635c6c1daeSBarry Smith window_attributes.win_gravity = in_window_attributes.win_gravity; 1645c6c1daeSBarry Smith /* Backing store is too slow in color systems */ 16515d5bc79SLisandro Dalcin window_attributes.backing_store = NotUseful; 1665c6c1daeSBarry Smith window_attributes.backing_pixel = backgnd_pixel; 1675c6c1daeSBarry Smith window_attributes.save_under = 1; 1685c6c1daeSBarry Smith window_attributes.event_mask = 0; 1695c6c1daeSBarry Smith window_attributes.do_not_propagate_mask = 0; 1705c6c1daeSBarry Smith window_attributes.override_redirect = 0; 1715c6c1daeSBarry Smith window_attributes.colormap = XiWin->cmap; 1725c6c1daeSBarry Smith /* None for cursor does NOT mean none, it means cursor of Parent */ 1735c6c1daeSBarry Smith window_attributes.cursor = None; 174a297a907SKarl Rupp 1759371c9d4SSatish Balay wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWDontPropagate | CWCursor | CWColormap; 1765c6c1daeSBarry Smith 17715d5bc79SLisandro Dalcin XiWin->win = XCreateWindow(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), x, y, w, h, border_width, XiWin->depth, InputOutput, XiWin->vis, wmask, &window_attributes); 17828b400f6SJacob Faibussowitsch PetscCheck(XiWin->win, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open X window"); 1795c6c1daeSBarry Smith 1805c6c1daeSBarry Smith /* set window manager hints */ 1815c6c1daeSBarry Smith { 1825c6c1daeSBarry Smith XWMHints wm_hints; 1835c6c1daeSBarry Smith XClassHint class_hints; 1845c6c1daeSBarry Smith XTextProperty windowname, iconname; 1855c6c1daeSBarry Smith 186a297a907SKarl Rupp if (label) XStringListToTextProperty(&label, 1, &windowname); 187a297a907SKarl Rupp else XStringListToTextProperty(&label, 0, &windowname); 188a297a907SKarl Rupp if (label) XStringListToTextProperty(&label, 1, &iconname); 189a297a907SKarl Rupp else XStringListToTextProperty(&label, 0, &iconname); 1905c6c1daeSBarry Smith 1915c6c1daeSBarry Smith wm_hints.initial_state = NormalState; 1925c6c1daeSBarry Smith wm_hints.input = True; 1935c6c1daeSBarry Smith wm_hints.flags = StateHint | InputHint; 1945c6c1daeSBarry Smith 1955c6c1daeSBarry Smith /* These properties can be used by window managers to decide how to display a window */ 1965c6c1daeSBarry Smith class_hints.res_name = (char *)"petsc"; 1975c6c1daeSBarry Smith class_hints.res_class = (char *)"PETSc"; 1985c6c1daeSBarry Smith 1995c6c1daeSBarry Smith size_hints.x = x; 2005c6c1daeSBarry Smith size_hints.y = y; 2015c6c1daeSBarry Smith size_hints.min_width = 4 * border_width; 2025c6c1daeSBarry Smith size_hints.min_height = 4 * border_width; 2035c6c1daeSBarry Smith size_hints.width = w; 2045c6c1daeSBarry Smith size_hints.height = h; 2055c6c1daeSBarry Smith size_hints.flags = USPosition | USSize | PMinSize; 2065c6c1daeSBarry Smith 20702c9f0b5SLisandro Dalcin XSetWMProperties(XiWin->disp, XiWin->win, &windowname, &iconname, NULL, 0, &size_hints, &wm_hints, &class_hints); 2085c6c1daeSBarry Smith XFree((void *)windowname.value); 2095c6c1daeSBarry Smith XFree((void *)iconname.value); 2105c6c1daeSBarry Smith } 211481cee7bSLisandro Dalcin 2125c6c1daeSBarry Smith /* make the window visible */ 2135c6c1daeSBarry Smith XSelectInput(XiWin->disp, XiWin->win, ExposureMask | StructureNotifyMask); 2145c6c1daeSBarry Smith XMapWindow(XiWin->disp, XiWin->win); 2155c6c1daeSBarry Smith /* some window systems are cruel and interfere with the placement of 2165c6c1daeSBarry Smith windows. We wait here for the window to be created or to die */ 217cc73adaaSBarry Smith PetscCall(PetscDrawXiWaitMap(XiWin)); 21873ecf448SLisandro Dalcin XSelectInput(XiWin->disp, XiWin->win, NoEventMask); 2193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2205c6c1daeSBarry Smith } 2215c6c1daeSBarry Smith 222d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin, char *name, int x, int y, int nx, int ny) 223d71ae5a4SJacob Faibussowitsch { 2245c6c1daeSBarry Smith PetscFunctionBegin; 2259566063dSJacob Faibussowitsch PetscCall(PetscDrawSetColormap_X(XiWin, (Colormap)0)); 2269566063dSJacob Faibussowitsch PetscCall(PetscDrawXiDisplayWindow(XiWin, name, x, y, nx, ny)); 22715d5bc79SLisandro Dalcin XSetWindowBackground(XiWin->disp, XiWin->win, XiWin->background); 22815d5bc79SLisandro Dalcin XClearWindow(XiWin->disp, XiWin->win); 2293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2305c6c1daeSBarry Smith } 2315c6c1daeSBarry Smith 2325c6c1daeSBarry Smith /* 2335c6c1daeSBarry Smith A version from an already defined window 2345c6c1daeSBarry Smith */ 235d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin, Window win) 236d71ae5a4SJacob Faibussowitsch { 2375c6c1daeSBarry Smith XWindowAttributes attributes; 2385c6c1daeSBarry Smith 2395c6c1daeSBarry Smith PetscFunctionBegin; 24015d5bc79SLisandro Dalcin XiWin->win = win; 24115d5bc79SLisandro Dalcin XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes); 2429566063dSJacob Faibussowitsch PetscCall(PetscDrawSetColormap_X(XiWin, attributes.colormap)); 2433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2445c6c1daeSBarry Smith } 2455c6c1daeSBarry Smith 246d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X *XiWin) 247d71ae5a4SJacob Faibussowitsch { 2485c6c1daeSBarry Smith PetscFunctionBegin; 24909440f25SLisandro Dalcin if (XiWin->drw) XFreePixmap(XiWin->disp, XiWin->drw); 25009440f25SLisandro Dalcin XiWin->drw = XCreatePixmap(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), XiWin->w, XiWin->h, XiWin->depth); 25109440f25SLisandro Dalcin PetscDrawXiSetPixVal(XiWin, XiWin->background); 25209440f25SLisandro Dalcin XFillRectangle(XiWin->disp, XiWin->drw, XiWin->gc.set, 0, 0, XiWin->w, XiWin->h); 25309440f25SLisandro Dalcin XSync(XiWin->disp, False); 2543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2555c6c1daeSBarry Smith } 25648db01dbSLisandro Dalcin 257d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h) 258d71ae5a4SJacob Faibussowitsch { 259bf780456SLisandro Dalcin XEvent event; 260*4d86920dSPierre Jolivet 261bf780456SLisandro Dalcin PetscFunctionBegin; 262bf780456SLisandro Dalcin XSelectInput(XiWin->disp, XiWin->win, StructureNotifyMask); 263bf780456SLisandro Dalcin XResizeWindow(XiWin->disp, XiWin->win, (unsigned int)w, (unsigned int)h); 264bf780456SLisandro Dalcin XWindowEvent(XiWin->disp, XiWin->win, StructureNotifyMask, &event); 265bf780456SLisandro Dalcin XSelectInput(XiWin->disp, XiWin->win, NoEventMask); 2663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 267bf780456SLisandro Dalcin } 268bf780456SLisandro Dalcin 269d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin, int *x, int *y, int *w, int *h) 270d71ae5a4SJacob Faibussowitsch { 27148db01dbSLisandro Dalcin XWindowAttributes attributes; 27248db01dbSLisandro Dalcin Window root, parent, child; 27348db01dbSLisandro Dalcin int xx = 0, yy = 0; 27448db01dbSLisandro Dalcin unsigned int ww = 0, hh = 0, dummy; 275*4d86920dSPierre Jolivet 27648db01dbSLisandro Dalcin PetscFunctionBegin; 27748db01dbSLisandro Dalcin if (XiWin->win) { 27848db01dbSLisandro Dalcin XGetGeometry(XiWin->disp, XiWin->win, &parent, &xx, &yy, &ww, &hh, &dummy, &dummy); 27948db01dbSLisandro Dalcin root = RootWindow(XiWin->disp, XiWin->screen); 28048db01dbSLisandro Dalcin if (!XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child)) { 28148db01dbSLisandro Dalcin XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes); 28248db01dbSLisandro Dalcin root = attributes.screen->root; 28348db01dbSLisandro Dalcin (void)XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child); 28448db01dbSLisandro Dalcin } 28548db01dbSLisandro Dalcin } else if (XiWin->drw) { 28648db01dbSLisandro Dalcin XGetGeometry(XiWin->disp, XiWin->drw, &root, &xx, &yy, &ww, &hh, &dummy, &dummy); 28748db01dbSLisandro Dalcin } 28848db01dbSLisandro Dalcin if (x) *x = xx; 28948db01dbSLisandro Dalcin if (y) *y = yy; 29048db01dbSLisandro Dalcin if (w) *w = (int)ww; 29148db01dbSLisandro Dalcin if (h) *h = (int)hh; 2923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29348db01dbSLisandro Dalcin } 294