xref: /petsc/src/sys/classes/draw/impls/x/xinit.c (revision 9371c9d470a9602b6d10a8bf50c9b2280a79e45a)
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 
1645f3bb6eSLisandro Dalcin PETSC_INTERN PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X *, Colormap);
175c6c1daeSBarry Smith 
185c6c1daeSBarry Smith /*
1915d5bc79SLisandro Dalcin   PetscDrawXiOpenDisplay - Open and setup a display
205c6c1daeSBarry Smith */
21*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin, const char display[]) {
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\
28*9371c9d4SSatish Balay     is set or you use the -display name option\n",
29*9371c9d4SSatish 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);
375c6c1daeSBarry Smith   PetscFunctionReturn(0);
385c6c1daeSBarry Smith }
395c6c1daeSBarry Smith 
40*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin) {
41815f00f0SLisandro Dalcin   PetscFunctionBegin;
42815f00f0SLisandro Dalcin   if (!XiWin) PetscFunctionReturn(0);
439566063dSJacob Faibussowitsch   PetscCall(PetscFree(XiWin->font));
44815f00f0SLisandro Dalcin   if (XiWin->disp) {
45815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
46815f00f0SLisandro Dalcin     jmp_buf              jmpbuf;
47815f00f0SLisandro Dalcin     PetscXIOErrorHandler xioerrhdl;
489566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(&jmpbuf, &PetscXIOErrorHandlerJumpBuf, sizeof(jmpbuf)));
49815f00f0SLisandro Dalcin     xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
50815f00f0SLisandro Dalcin     if (!setjmp(PetscXIOErrorHandlerJumpBuf))
51815f00f0SLisandro Dalcin #endif
52815f00f0SLisandro Dalcin     {
53815f00f0SLisandro Dalcin       XFreeGC(XiWin->disp, XiWin->gc.set);
54815f00f0SLisandro Dalcin       XCloseDisplay(XiWin->disp);
55815f00f0SLisandro Dalcin     }
56815f00f0SLisandro Dalcin     XiWin->disp = NULL;
57815f00f0SLisandro Dalcin #if defined(PETSC_HAVE_SETJMP_H)
58815f00f0SLisandro Dalcin     (void)PetscSetXIOErrorHandler(xioerrhdl);
599566063dSJacob Faibussowitsch     PetscCall(PetscMemcpy(&PetscXIOErrorHandlerJumpBuf, &jmpbuf, sizeof(jmpbuf)));
60815f00f0SLisandro Dalcin #endif
61815f00f0SLisandro Dalcin   }
62815f00f0SLisandro Dalcin   PetscFunctionReturn(0);
63815f00f0SLisandro Dalcin }
64815f00f0SLisandro Dalcin 
655c6c1daeSBarry Smith /*
6609440f25SLisandro Dalcin    PetscDrawXiCreateGC - setup the GC structure
675c6c1daeSBarry Smith */
68*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiCreateGC(PetscDraw_X *XiWin, PetscDrawXiPixVal fg) {
695c6c1daeSBarry Smith   XGCValues gcvalues; /* window graphics context values */
705c6c1daeSBarry Smith 
715c6c1daeSBarry Smith   PetscFunctionBegin;
725c6c1daeSBarry Smith   /* Set the graphics contexts */
735c6c1daeSBarry Smith   /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
745c6c1daeSBarry Smith   /* (do this with function GXcopy; GXset will automatically write 1) */
755c6c1daeSBarry Smith   gcvalues.function   = GXcopy;
765c6c1daeSBarry Smith   gcvalues.foreground = fg;
775c6c1daeSBarry Smith   XiWin->gc.cur_pix   = fg;
785c6c1daeSBarry Smith   XiWin->gc.set       = XCreateGC(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), GCFunction | GCForeground, &gcvalues);
7908401ef6SPierre Jolivet   PetscCheck(XiWin->gc.set, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to create X graphics context");
8015d5bc79SLisandro Dalcin   PetscFunctionReturn(0);
8115d5bc79SLisandro Dalcin }
8215d5bc79SLisandro Dalcin 
8315d5bc79SLisandro Dalcin /*
84815f00f0SLisandro Dalcin    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
8515d5bc79SLisandro Dalcin */
86*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin, const char display[]) {
8715d5bc79SLisandro Dalcin   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(PetscDrawXiOpenDisplay(XiWin, display));
899566063dSJacob Faibussowitsch   PetscCall(PetscDrawXiCreateGC(XiWin, XiWin->foreground));
909566063dSJacob Faibussowitsch   PetscCall(PetscDrawXiFontFixed(XiWin, 6, 10, &XiWin->font));
915c6c1daeSBarry Smith   PetscFunctionReturn(0);
925c6c1daeSBarry Smith }
935c6c1daeSBarry Smith 
945c6c1daeSBarry Smith /*
9509440f25SLisandro Dalcin     This routine waits until the window is actually created or destroyed
9609440f25SLisandro Dalcin     Returns 0 if window is mapped; 1 if window is destroyed.
9709440f25SLisandro Dalcin  */
98*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiWaitMap(PetscDraw_X *XiWin) {
9909440f25SLisandro Dalcin   XEvent event;
10009440f25SLisandro Dalcin 
10109440f25SLisandro Dalcin   PetscFunctionBegin;
10209440f25SLisandro Dalcin   while (1) {
10309440f25SLisandro Dalcin     XMaskEvent(XiWin->disp, ExposureMask | StructureNotifyMask, &event);
10409440f25SLisandro Dalcin     if (event.xany.window != XiWin->win) break;
10509440f25SLisandro Dalcin     else {
10609440f25SLisandro Dalcin       switch (event.type) {
10709440f25SLisandro Dalcin       case ConfigureNotify:
10809440f25SLisandro Dalcin         /* window has been moved or resized */
10909440f25SLisandro Dalcin         XiWin->w = event.xconfigure.width - 2 * event.xconfigure.border_width;
11009440f25SLisandro Dalcin         XiWin->h = event.xconfigure.height - 2 * event.xconfigure.border_width;
11109440f25SLisandro Dalcin         break;
112*9371c9d4SSatish Balay       case DestroyNotify: PetscFunctionReturn(1);
11309440f25SLisandro Dalcin       case Expose:
11409440f25SLisandro Dalcin         PetscFunctionReturn(0);
11509440f25SLisandro Dalcin         /* else ignore event */
11609440f25SLisandro Dalcin       }
11709440f25SLisandro Dalcin     }
11809440f25SLisandro Dalcin   }
11909440f25SLisandro Dalcin   PetscFunctionReturn(0);
12009440f25SLisandro Dalcin }
12109440f25SLisandro Dalcin 
12209440f25SLisandro Dalcin /*
1235c6c1daeSBarry Smith     Actually display a window at [x,y] with sizes (w,h)
1245c6c1daeSBarry Smith */
125*9371c9d4SSatish Balay static PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin, char *label, int x, int y, int w, int h) {
1265c6c1daeSBarry Smith   unsigned int         wavail, havail;
1275c6c1daeSBarry Smith   XSizeHints           size_hints;
1285c6c1daeSBarry Smith   XWindowAttributes    in_window_attributes;
1295c6c1daeSBarry Smith   XSetWindowAttributes window_attributes;
13015d5bc79SLisandro Dalcin   unsigned int         border_width  = 0;
13115d5bc79SLisandro Dalcin   unsigned long        backgnd_pixel = WhitePixel(XiWin->disp, XiWin->screen);
1325c6c1daeSBarry Smith   unsigned long        wmask;
1335c6c1daeSBarry Smith 
1345c6c1daeSBarry Smith   PetscFunctionBegin;
1355c6c1daeSBarry Smith   /* get the available widths */
1365c6c1daeSBarry Smith   wavail = DisplayWidth(XiWin->disp, XiWin->screen);
1375c6c1daeSBarry Smith   havail = DisplayHeight(XiWin->disp, XiWin->screen);
138cc73adaaSBarry Smith   PetscCheck(w > 0 && h > 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "X Window display has invalid height or width");
1395c6c1daeSBarry Smith   if ((unsigned int)w > wavail) w = wavail;
1405c6c1daeSBarry Smith   if ((unsigned int)h > havail) h = havail;
1415c6c1daeSBarry Smith 
14215d5bc79SLisandro Dalcin   if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
14315d5bc79SLisandro Dalcin   if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
14415d5bc79SLisandro Dalcin   x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
14515d5bc79SLisandro Dalcin   y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;
1465c6c1daeSBarry Smith 
1475c6c1daeSBarry Smith   /* We need XCreateWindow since we may need an visual other than the default one */
1485c6c1daeSBarry Smith   XGetWindowAttributes(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), &in_window_attributes);
1495c6c1daeSBarry Smith   window_attributes.background_pixmap     = None;
1505c6c1daeSBarry Smith   window_attributes.background_pixel      = backgnd_pixel;
1515c6c1daeSBarry Smith   /* No border for now */
1525c6c1daeSBarry Smith   window_attributes.border_pixmap         = None;
1535c6c1daeSBarry Smith   /*
1545c6c1daeSBarry Smith   window_attributes.border_pixel      = border_pixel;
1555c6c1daeSBarry Smith   */
1565c6c1daeSBarry Smith   window_attributes.bit_gravity           = in_window_attributes.bit_gravity;
1575c6c1daeSBarry Smith   window_attributes.win_gravity           = in_window_attributes.win_gravity;
1585c6c1daeSBarry Smith   /* Backing store is too slow in color systems */
15915d5bc79SLisandro Dalcin   window_attributes.backing_store         = NotUseful;
1605c6c1daeSBarry Smith   window_attributes.backing_pixel         = backgnd_pixel;
1615c6c1daeSBarry Smith   window_attributes.save_under            = 1;
1625c6c1daeSBarry Smith   window_attributes.event_mask            = 0;
1635c6c1daeSBarry Smith   window_attributes.do_not_propagate_mask = 0;
1645c6c1daeSBarry Smith   window_attributes.override_redirect     = 0;
1655c6c1daeSBarry Smith   window_attributes.colormap              = XiWin->cmap;
1665c6c1daeSBarry Smith   /* None for cursor does NOT mean none, it means cursor of Parent */
1675c6c1daeSBarry Smith   window_attributes.cursor                = None;
168a297a907SKarl Rupp 
169*9371c9d4SSatish Balay   wmask = CWBackPixmap | CWBackPixel | CWBorderPixmap | CWBitGravity | CWWinGravity | CWBackingStore | CWBackingPixel | CWOverrideRedirect | CWSaveUnder | CWEventMask | CWDontPropagate | CWCursor | CWColormap;
1705c6c1daeSBarry Smith 
17115d5bc79SLisandro 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);
17228b400f6SJacob Faibussowitsch   PetscCheck(XiWin->win, PETSC_COMM_SELF, PETSC_ERR_LIB, "Unable to open X window");
1735c6c1daeSBarry Smith 
1745c6c1daeSBarry Smith   /* set window manager hints */
1755c6c1daeSBarry Smith   {
1765c6c1daeSBarry Smith     XWMHints      wm_hints;
1775c6c1daeSBarry Smith     XClassHint    class_hints;
1785c6c1daeSBarry Smith     XTextProperty windowname, iconname;
1795c6c1daeSBarry Smith 
180a297a907SKarl Rupp     if (label) XStringListToTextProperty(&label, 1, &windowname);
181a297a907SKarl Rupp     else XStringListToTextProperty(&label, 0, &windowname);
182a297a907SKarl Rupp     if (label) XStringListToTextProperty(&label, 1, &iconname);
183a297a907SKarl Rupp     else XStringListToTextProperty(&label, 0, &iconname);
1845c6c1daeSBarry Smith 
1855c6c1daeSBarry Smith     wm_hints.initial_state = NormalState;
1865c6c1daeSBarry Smith     wm_hints.input         = True;
1875c6c1daeSBarry Smith     wm_hints.flags         = StateHint | InputHint;
1885c6c1daeSBarry Smith 
1895c6c1daeSBarry Smith     /* These properties can be used by window managers to decide how to display a window */
1905c6c1daeSBarry Smith     class_hints.res_name  = (char *)"petsc";
1915c6c1daeSBarry Smith     class_hints.res_class = (char *)"PETSc";
1925c6c1daeSBarry Smith 
1935c6c1daeSBarry Smith     size_hints.x          = x;
1945c6c1daeSBarry Smith     size_hints.y          = y;
1955c6c1daeSBarry Smith     size_hints.min_width  = 4 * border_width;
1965c6c1daeSBarry Smith     size_hints.min_height = 4 * border_width;
1975c6c1daeSBarry Smith     size_hints.width      = w;
1985c6c1daeSBarry Smith     size_hints.height     = h;
1995c6c1daeSBarry Smith     size_hints.flags      = USPosition | USSize | PMinSize;
2005c6c1daeSBarry Smith 
20102c9f0b5SLisandro Dalcin     XSetWMProperties(XiWin->disp, XiWin->win, &windowname, &iconname, NULL, 0, &size_hints, &wm_hints, &class_hints);
2025c6c1daeSBarry Smith     XFree((void *)windowname.value);
2035c6c1daeSBarry Smith     XFree((void *)iconname.value);
2045c6c1daeSBarry Smith   }
205481cee7bSLisandro Dalcin 
2065c6c1daeSBarry Smith   /* make the window visible */
2075c6c1daeSBarry Smith   XSelectInput(XiWin->disp, XiWin->win, ExposureMask | StructureNotifyMask);
2085c6c1daeSBarry Smith   XMapWindow(XiWin->disp, XiWin->win);
2095c6c1daeSBarry Smith   /* some window systems are cruel and interfere with the placement of
2105c6c1daeSBarry Smith      windows.  We wait here for the window to be created or to die */
211cc73adaaSBarry Smith   PetscCall(PetscDrawXiWaitMap(XiWin));
21273ecf448SLisandro Dalcin   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
2135c6c1daeSBarry Smith   PetscFunctionReturn(0);
2145c6c1daeSBarry Smith }
2155c6c1daeSBarry Smith 
216*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin, char *name, int x, int y, int nx, int ny) {
2175c6c1daeSBarry Smith   PetscFunctionBegin;
2189566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetColormap_X(XiWin, (Colormap)0));
2199566063dSJacob Faibussowitsch   PetscCall(PetscDrawXiDisplayWindow(XiWin, name, x, y, nx, ny));
22015d5bc79SLisandro Dalcin   XSetWindowBackground(XiWin->disp, XiWin->win, XiWin->background);
22115d5bc79SLisandro Dalcin   XClearWindow(XiWin->disp, XiWin->win);
2225c6c1daeSBarry Smith   PetscFunctionReturn(0);
2235c6c1daeSBarry Smith }
2245c6c1daeSBarry Smith 
2255c6c1daeSBarry Smith /*
2265c6c1daeSBarry Smith    A version from an already defined window
2275c6c1daeSBarry Smith */
228*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin, Window win) {
2295c6c1daeSBarry Smith   XWindowAttributes attributes;
2305c6c1daeSBarry Smith 
2315c6c1daeSBarry Smith   PetscFunctionBegin;
23215d5bc79SLisandro Dalcin   XiWin->win = win;
23315d5bc79SLisandro Dalcin   XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
2349566063dSJacob Faibussowitsch   PetscCall(PetscDrawSetColormap_X(XiWin, attributes.colormap));
2355c6c1daeSBarry Smith   PetscFunctionReturn(0);
2365c6c1daeSBarry Smith }
2375c6c1daeSBarry Smith 
238*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiQuickPixmap(PetscDraw_X *XiWin) {
2395c6c1daeSBarry Smith   PetscFunctionBegin;
24009440f25SLisandro Dalcin   if (XiWin->drw) XFreePixmap(XiWin->disp, XiWin->drw);
24109440f25SLisandro Dalcin   XiWin->drw = XCreatePixmap(XiWin->disp, RootWindow(XiWin->disp, XiWin->screen), XiWin->w, XiWin->h, XiWin->depth);
24209440f25SLisandro Dalcin   PetscDrawXiSetPixVal(XiWin, XiWin->background);
24309440f25SLisandro Dalcin   XFillRectangle(XiWin->disp, XiWin->drw, XiWin->gc.set, 0, 0, XiWin->w, XiWin->h);
24409440f25SLisandro Dalcin   XSync(XiWin->disp, False);
2455c6c1daeSBarry Smith   PetscFunctionReturn(0);
2465c6c1daeSBarry Smith }
24748db01dbSLisandro Dalcin 
248*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiResizeWindow(PetscDraw_X *XiWin, int w, int h) {
249bf780456SLisandro Dalcin   XEvent event;
250bf780456SLisandro Dalcin   PetscFunctionBegin;
251bf780456SLisandro Dalcin   XSelectInput(XiWin->disp, XiWin->win, StructureNotifyMask);
252bf780456SLisandro Dalcin   XResizeWindow(XiWin->disp, XiWin->win, (unsigned int)w, (unsigned int)h);
253bf780456SLisandro Dalcin   XWindowEvent(XiWin->disp, XiWin->win, StructureNotifyMask, &event);
254bf780456SLisandro Dalcin   XSelectInput(XiWin->disp, XiWin->win, NoEventMask);
255bf780456SLisandro Dalcin   PetscFunctionReturn(0);
256bf780456SLisandro Dalcin }
257bf780456SLisandro Dalcin 
258*9371c9d4SSatish Balay PetscErrorCode PetscDrawXiGetGeometry(PetscDraw_X *XiWin, int *x, int *y, int *w, int *h) {
25948db01dbSLisandro Dalcin   XWindowAttributes attributes;
26048db01dbSLisandro Dalcin   Window            root, parent, child;
26148db01dbSLisandro Dalcin   int               xx = 0, yy = 0;
26248db01dbSLisandro Dalcin   unsigned int      ww = 0, hh = 0, dummy;
26348db01dbSLisandro Dalcin   PetscFunctionBegin;
26448db01dbSLisandro Dalcin   if (XiWin->win) {
26548db01dbSLisandro Dalcin     XGetGeometry(XiWin->disp, XiWin->win, &parent, &xx, &yy, &ww, &hh, &dummy, &dummy);
26648db01dbSLisandro Dalcin     root = RootWindow(XiWin->disp, XiWin->screen);
26748db01dbSLisandro Dalcin     if (!XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child)) {
26848db01dbSLisandro Dalcin       XGetWindowAttributes(XiWin->disp, XiWin->win, &attributes);
26948db01dbSLisandro Dalcin       root = attributes.screen->root;
27048db01dbSLisandro Dalcin       (void)XTranslateCoordinates(XiWin->disp, XiWin->win, root, 0, 0, &xx, &yy, &child);
27148db01dbSLisandro Dalcin     }
27248db01dbSLisandro Dalcin   } else if (XiWin->drw) {
27348db01dbSLisandro Dalcin     XGetGeometry(XiWin->disp, XiWin->drw, &root, &xx, &yy, &ww, &hh, &dummy, &dummy);
27448db01dbSLisandro Dalcin   }
27548db01dbSLisandro Dalcin   if (x) *x = xx;
27648db01dbSLisandro Dalcin   if (y) *y = yy;
27748db01dbSLisandro Dalcin   if (w) *w = (int)ww;
27848db01dbSLisandro Dalcin   if (h) *h = (int)hh;
27948db01dbSLisandro Dalcin   PetscFunctionReturn(0);
28048db01dbSLisandro Dalcin }
281