15c6c1daeSBarry Smith 25c6c1daeSBarry Smith /* 35c6c1daeSBarry Smith This file contains routines to open an X window display and window 45c6c1daeSBarry Smith This consists of a number of routines that set the various 55c6c1daeSBarry Smith fields in the Window structure, which is passed to 65c6c1daeSBarry Smith all of these routines. 75c6c1daeSBarry Smith 85c6c1daeSBarry Smith Note that if you use the default visual and colormap, then you 95c6c1daeSBarry Smith can use these routines with any X toolkit that will give you the 105c6c1daeSBarry Smith Window id of the window that it is managing. Use that instead of the 115c6c1daeSBarry Smith call to PetscDrawXiCreateWindow . Similarly for the Display. 125c6c1daeSBarry Smith */ 135c6c1daeSBarry Smith 145c6c1daeSBarry Smith #include <../src/sys/classes/draw/impls/x/ximpl.h> 155c6c1daeSBarry Smith 1615d5bc79SLisandro Dalcin extern PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap); 175c6c1daeSBarry Smith 185c6c1daeSBarry Smith /* 1915d5bc79SLisandro Dalcin PetscDrawXiOpenDisplay - Open and setup a display 205c6c1daeSBarry Smith */ 215c6c1daeSBarry Smith #undef __FUNCT__ 225c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiOpenDisplay" 2309440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[]) 245c6c1daeSBarry Smith { 255c6c1daeSBarry Smith PetscFunctionBegin; 2615d5bc79SLisandro Dalcin XiWin->disp = XOpenDisplay(display); 275c6c1daeSBarry Smith if (!XiWin->disp) { 2815d5bc79SLisandro Dalcin SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\ 2915d5bc79SLisandro Dalcin Make sure your COMPUTE NODES are authorized to connect \n\ 305c6c1daeSBarry Smith to this X server and either your DISPLAY variable\n\ 3115d5bc79SLisandro Dalcin is set or you use the -display name option\n",display); 325c6c1daeSBarry Smith } 335c6c1daeSBarry Smith XiWin->screen = DefaultScreen(XiWin->disp); 34481cee7bSLisandro Dalcin XiWin->vis = DefaultVisual(XiWin->disp,XiWin->screen); 35481cee7bSLisandro Dalcin XiWin->depth = DefaultDepth(XiWin->disp,XiWin->screen); 3615d5bc79SLisandro Dalcin XiWin->cmap = DefaultColormap(XiWin->disp,XiWin->screen); 3715d5bc79SLisandro Dalcin XiWin->background = WhitePixel(XiWin->disp,XiWin->screen); 3815d5bc79SLisandro Dalcin XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen); 395c6c1daeSBarry Smith PetscFunctionReturn(0); 405c6c1daeSBarry Smith } 415c6c1daeSBarry Smith 42815f00f0SLisandro Dalcin #undef __FUNCT__ 43815f00f0SLisandro Dalcin #define __FUNCT__ "PetscDrawXiClose" 44815f00f0SLisandro Dalcin PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin) 45815f00f0SLisandro Dalcin { 46815f00f0SLisandro Dalcin PetscErrorCode ierr; 47815f00f0SLisandro Dalcin 48815f00f0SLisandro Dalcin PetscFunctionBegin; 49815f00f0SLisandro Dalcin if (!XiWin) PetscFunctionReturn(0); 50815f00f0SLisandro Dalcin ierr = PetscFree(XiWin->font);CHKERRQ(ierr); 51815f00f0SLisandro Dalcin if (XiWin->disp) { 52815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 53815f00f0SLisandro Dalcin jmp_buf jmpbuf; 54815f00f0SLisandro Dalcin PetscXIOErrorHandler xioerrhdl; 55815f00f0SLisandro Dalcin ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr); 56815f00f0SLisandro Dalcin xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump); 57815f00f0SLisandro Dalcin if (!setjmp(PetscXIOErrorHandlerJumpBuf)) 58815f00f0SLisandro Dalcin #endif 59815f00f0SLisandro Dalcin { 60815f00f0SLisandro Dalcin XFreeGC(XiWin->disp,XiWin->gc.set); 61815f00f0SLisandro Dalcin XCloseDisplay(XiWin->disp); 62815f00f0SLisandro Dalcin } 63815f00f0SLisandro Dalcin XiWin->disp = NULL; 64815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H) 65815f00f0SLisandro Dalcin (void)PetscSetXIOErrorHandler(xioerrhdl); 66815f00f0SLisandro Dalcin ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr); 67815f00f0SLisandro Dalcin #endif 68815f00f0SLisandro Dalcin } 69815f00f0SLisandro Dalcin PetscFunctionReturn(0); 70815f00f0SLisandro Dalcin } 71815f00f0SLisandro Dalcin 725c6c1daeSBarry Smith /* 7309440f25SLisandro Dalcin PetscDrawXiCreateGC - setup the GC structure 745c6c1daeSBarry Smith */ 755c6c1daeSBarry Smith #undef __FUNCT__ 7609440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiCreateGC" 7709440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg) 785c6c1daeSBarry Smith { 795c6c1daeSBarry Smith XGCValues gcvalues; /* window graphics context values */ 805c6c1daeSBarry Smith 815c6c1daeSBarry Smith PetscFunctionBegin; 825c6c1daeSBarry Smith /* Set the graphics contexts */ 835c6c1daeSBarry Smith /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */ 845c6c1daeSBarry Smith /* (do this with function GXcopy; GXset will automatically write 1) */ 855c6c1daeSBarry Smith gcvalues.function = GXcopy; 865c6c1daeSBarry Smith gcvalues.foreground = fg; 875c6c1daeSBarry Smith XiWin->gc.cur_pix = fg; 885c6c1daeSBarry Smith XiWin->gc.set = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues); 8915d5bc79SLisandro Dalcin if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context"); 9015d5bc79SLisandro Dalcin PetscFunctionReturn(0); 9115d5bc79SLisandro Dalcin } 9215d5bc79SLisandro Dalcin 9315d5bc79SLisandro Dalcin /* 94815f00f0SLisandro Dalcin PetscDrawXiInit - basic setup the draw (display, graphics context, font) 9515d5bc79SLisandro Dalcin */ 9615d5bc79SLisandro Dalcin #undef __FUNCT__ 97815f00f0SLisandro Dalcin #define __FUNCT__ "PetscDrawXiInit" 9865d9662dSLisandro Dalcin PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[]) 9915d5bc79SLisandro Dalcin { 10015d5bc79SLisandro Dalcin PetscErrorCode ierr; 10115d5bc79SLisandro Dalcin PetscFunctionBegin; 10215d5bc79SLisandro Dalcin ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr); 10309440f25SLisandro Dalcin ierr = PetscDrawXiCreateGC(XiWin,XiWin->foreground);CHKERRQ(ierr); 10415d5bc79SLisandro Dalcin ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr); 1055c6c1daeSBarry Smith PetscFunctionReturn(0); 1065c6c1daeSBarry Smith } 1075c6c1daeSBarry Smith 1085c6c1daeSBarry Smith /* 10909440f25SLisandro Dalcin This routine waits until the window is actually created or destroyed 11009440f25SLisandro Dalcin Returns 0 if window is mapped; 1 if window is destroyed. 11109440f25SLisandro Dalcin */ 11209440f25SLisandro Dalcin #undef __FUNCT__ 11309440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiWaitMap" 11409440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin) 11509440f25SLisandro Dalcin { 11609440f25SLisandro Dalcin XEvent event; 11709440f25SLisandro Dalcin 11809440f25SLisandro Dalcin PetscFunctionBegin; 11909440f25SLisandro Dalcin while (1) { 12009440f25SLisandro Dalcin XMaskEvent(XiWin->disp,ExposureMask|StructureNotifyMask,&event); 12109440f25SLisandro Dalcin if (event.xany.window != XiWin->win) break; 12209440f25SLisandro Dalcin else { 12309440f25SLisandro Dalcin switch (event.type) { 12409440f25SLisandro Dalcin case ConfigureNotify: 12509440f25SLisandro Dalcin /* window has been moved or resized */ 12609440f25SLisandro Dalcin XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width; 12709440f25SLisandro Dalcin XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width; 12809440f25SLisandro Dalcin break; 12909440f25SLisandro Dalcin case DestroyNotify: 13009440f25SLisandro Dalcin PetscFunctionReturn(1); 13109440f25SLisandro Dalcin case Expose: 13209440f25SLisandro Dalcin PetscFunctionReturn(0); 13309440f25SLisandro Dalcin /* else ignore event */ 13409440f25SLisandro Dalcin } 13509440f25SLisandro Dalcin } 13609440f25SLisandro Dalcin } 13709440f25SLisandro Dalcin PetscFunctionReturn(0); 13809440f25SLisandro Dalcin } 13909440f25SLisandro Dalcin 14009440f25SLisandro Dalcin /* 1415c6c1daeSBarry Smith Actually display a window at [x,y] with sizes (w,h) 1425c6c1daeSBarry Smith */ 1435c6c1daeSBarry Smith #undef __FUNCT__ 1445c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiDisplayWindow" 14509440f25SLisandro Dalcin static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h) 1465c6c1daeSBarry Smith { 1475c6c1daeSBarry Smith unsigned int wavail,havail; 1485c6c1daeSBarry Smith XSizeHints size_hints; 1495c6c1daeSBarry Smith XWindowAttributes in_window_attributes; 1505c6c1daeSBarry Smith XSetWindowAttributes window_attributes; 15115d5bc79SLisandro Dalcin unsigned int border_width = 0; 15215d5bc79SLisandro Dalcin unsigned long backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen); 1535c6c1daeSBarry Smith unsigned long wmask; 1545c6c1daeSBarry Smith 1555c6c1daeSBarry Smith PetscFunctionBegin; 1565c6c1daeSBarry Smith /* get the available widths */ 1575c6c1daeSBarry Smith wavail = DisplayWidth(XiWin->disp,XiWin->screen); 1585c6c1daeSBarry Smith havail = DisplayHeight(XiWin->disp,XiWin->screen); 1595c6c1daeSBarry Smith if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width"); 1605c6c1daeSBarry Smith if ((unsigned int)w > wavail) w = wavail; 1615c6c1daeSBarry Smith if ((unsigned int)h > havail) h = havail; 1625c6c1daeSBarry Smith 16315d5bc79SLisandro Dalcin if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x); 16415d5bc79SLisandro Dalcin if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y); 16515d5bc79SLisandro Dalcin x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x; 16615d5bc79SLisandro Dalcin y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y; 1675c6c1daeSBarry Smith 1685c6c1daeSBarry Smith /* We need XCreateWindow since we may need an visual other than the default one */ 1695c6c1daeSBarry Smith XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes); 1705c6c1daeSBarry Smith window_attributes.background_pixmap = None; 1715c6c1daeSBarry Smith window_attributes.background_pixel = backgnd_pixel; 1725c6c1daeSBarry Smith /* No border for now */ 1735c6c1daeSBarry Smith window_attributes.border_pixmap = None; 1745c6c1daeSBarry Smith /* 1755c6c1daeSBarry Smith window_attributes.border_pixel = border_pixel; 1765c6c1daeSBarry Smith */ 1775c6c1daeSBarry Smith window_attributes.bit_gravity = in_window_attributes.bit_gravity; 1785c6c1daeSBarry Smith window_attributes.win_gravity = in_window_attributes.win_gravity; 1795c6c1daeSBarry Smith /* Backing store is too slow in color systems */ 18015d5bc79SLisandro Dalcin window_attributes.backing_store = NotUseful; 1815c6c1daeSBarry Smith window_attributes.backing_pixel = backgnd_pixel; 1825c6c1daeSBarry Smith window_attributes.save_under = 1; 1835c6c1daeSBarry Smith window_attributes.event_mask = 0; 1845c6c1daeSBarry Smith window_attributes.do_not_propagate_mask = 0; 1855c6c1daeSBarry Smith window_attributes.override_redirect = 0; 1865c6c1daeSBarry Smith window_attributes.colormap = XiWin->cmap; 1875c6c1daeSBarry Smith /* None for cursor does NOT mean none, it means cursor of Parent */ 1885c6c1daeSBarry Smith window_attributes.cursor = None; 189a297a907SKarl Rupp 1905c6c1daeSBarry Smith wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | 1915c6c1daeSBarry Smith CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | 1925c6c1daeSBarry Smith CWSaveUnder | CWEventMask | CWDontPropagate | 1935c6c1daeSBarry Smith CWCursor | CWColormap; 1945c6c1daeSBarry Smith 19515d5bc79SLisandro 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); 1965c6c1daeSBarry Smith if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window"); 1975c6c1daeSBarry Smith 1985c6c1daeSBarry Smith /* set window manager hints */ 1995c6c1daeSBarry Smith { 2005c6c1daeSBarry Smith XWMHints wm_hints; 2015c6c1daeSBarry Smith XClassHint class_hints; 2025c6c1daeSBarry Smith XTextProperty windowname,iconname; 2035c6c1daeSBarry Smith 204a297a907SKarl Rupp if (label) XStringListToTextProperty(&label,1,&windowname); 205a297a907SKarl Rupp else XStringListToTextProperty(&label,0,&windowname); 206a297a907SKarl Rupp if (label) XStringListToTextProperty(&label,1,&iconname); 207a297a907SKarl Rupp else XStringListToTextProperty(&label,0,&iconname); 2085c6c1daeSBarry Smith 2095c6c1daeSBarry Smith wm_hints.initial_state = NormalState; 2105c6c1daeSBarry Smith wm_hints.input = True; 2115c6c1daeSBarry Smith wm_hints.flags = StateHint|InputHint; 2125c6c1daeSBarry Smith 2135c6c1daeSBarry Smith /* These properties can be used by window managers to decide how to display a window */ 2145c6c1daeSBarry Smith class_hints.res_name = (char*)"petsc"; 2155c6c1daeSBarry Smith class_hints.res_class = (char*)"PETSc"; 2165c6c1daeSBarry Smith 2175c6c1daeSBarry Smith size_hints.x = x; 2185c6c1daeSBarry Smith size_hints.y = y; 2195c6c1daeSBarry Smith size_hints.min_width = 4*border_width; 2205c6c1daeSBarry Smith size_hints.min_height = 4*border_width; 2215c6c1daeSBarry Smith size_hints.width = w; 2225c6c1daeSBarry Smith size_hints.height = h; 2235c6c1daeSBarry Smith size_hints.flags = USPosition | USSize | PMinSize; 2245c6c1daeSBarry Smith 2255c6c1daeSBarry Smith XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints); 2265c6c1daeSBarry Smith XFree((void*)windowname.value); 2275c6c1daeSBarry Smith XFree((void*)iconname.value); 2285c6c1daeSBarry Smith } 229481cee7bSLisandro Dalcin 2305c6c1daeSBarry Smith /* make the window visible */ 2315c6c1daeSBarry Smith XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask); 2325c6c1daeSBarry Smith XMapWindow(XiWin->disp,XiWin->win); 2335c6c1daeSBarry Smith /* some window systems are cruel and interfere with the placement of 2345c6c1daeSBarry Smith windows. We wait here for the window to be created or to die */ 23509440f25SLisandro Dalcin if (PetscDrawXiWaitMap(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed"); 236*73ecf448SLisandro Dalcin XSelectInput(XiWin->disp,XiWin->win,NoEventMask); 2375c6c1daeSBarry Smith PetscFunctionReturn(0); 2385c6c1daeSBarry Smith } 2395c6c1daeSBarry Smith 2405c6c1daeSBarry Smith #undef __FUNCT__ 2415c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiQuickWindow" 24215d5bc79SLisandro Dalcin PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny) 2435c6c1daeSBarry Smith { 24415d5bc79SLisandro Dalcin Window root; 24515d5bc79SLisandro Dalcin unsigned int w,h,dummy; 2465c6c1daeSBarry Smith PetscErrorCode ierr; 2475c6c1daeSBarry Smith 2485c6c1daeSBarry Smith PetscFunctionBegin; 24915d5bc79SLisandro Dalcin ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr); 25015d5bc79SLisandro Dalcin ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr); 25115d5bc79SLisandro Dalcin XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background); 25215d5bc79SLisandro Dalcin XClearWindow(XiWin->disp,XiWin->win); 2535c6c1daeSBarry Smith 25415d5bc79SLisandro Dalcin XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy); 25515d5bc79SLisandro Dalcin XiWin->x = x; 25615d5bc79SLisandro Dalcin XiWin->y = y; 25715d5bc79SLisandro Dalcin XiWin->w = (int)w; 25815d5bc79SLisandro Dalcin XiWin->h = (int)h; 2595c6c1daeSBarry Smith PetscFunctionReturn(0); 2605c6c1daeSBarry Smith } 2615c6c1daeSBarry Smith 2625c6c1daeSBarry Smith /* 2635c6c1daeSBarry Smith A version from an already defined window 2645c6c1daeSBarry Smith */ 2655c6c1daeSBarry Smith #undef __FUNCT__ 2665c6c1daeSBarry Smith #define __FUNCT__ "PetscDrawXiQuickWindowFromWindow" 26715d5bc79SLisandro Dalcin PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win) 2685c6c1daeSBarry Smith { 2695c6c1daeSBarry Smith Window root; 27015d5bc79SLisandro Dalcin int x,y; 27115d5bc79SLisandro Dalcin unsigned int w,h,dummy; 2725c6c1daeSBarry Smith XWindowAttributes attributes; 27315d5bc79SLisandro Dalcin PetscErrorCode ierr; 2745c6c1daeSBarry Smith 2755c6c1daeSBarry Smith PetscFunctionBegin; 27615d5bc79SLisandro Dalcin XiWin->win = win; 27715d5bc79SLisandro Dalcin XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes); 27815d5bc79SLisandro Dalcin ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr); 279481cee7bSLisandro Dalcin 28015d5bc79SLisandro Dalcin XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy); 28115d5bc79SLisandro Dalcin XiWin->x = x; 28215d5bc79SLisandro Dalcin XiWin->y = y; 28315d5bc79SLisandro Dalcin XiWin->w = (int)w; 28415d5bc79SLisandro Dalcin XiWin->h = (int)h; 2855c6c1daeSBarry Smith PetscFunctionReturn(0); 2865c6c1daeSBarry Smith } 2875c6c1daeSBarry Smith 28809440f25SLisandro Dalcin #undef __FUNCT__ 28909440f25SLisandro Dalcin #define __FUNCT__ "PetscDrawXiQuickPixmap" 29009440f25SLisandro Dalcin PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X* XiWin) 29109440f25SLisandro Dalcin { 2925c6c1daeSBarry Smith PetscFunctionBegin; 29309440f25SLisandro Dalcin if (XiWin->drw) XFreePixmap(XiWin->disp,XiWin->drw); 29409440f25SLisandro Dalcin XiWin->drw = XCreatePixmap(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),XiWin->w,XiWin->h,XiWin->depth); 29509440f25SLisandro Dalcin PetscDrawXiSetPixVal(XiWin,XiWin->background); 29609440f25SLisandro Dalcin XFillRectangle(XiWin->disp,XiWin->drw,XiWin->gc.set,0,0,XiWin->w,XiWin->h); 29709440f25SLisandro Dalcin XSync(XiWin->disp,False); 2985c6c1daeSBarry Smith PetscFunctionReturn(0); 2995c6c1daeSBarry Smith } 300