static void Resize (Widget widget) { ClockWidget w = (ClockWidget) widget; XGCValues xgcv; Widget parent; XWindowChanges xwc; int face_width, face_height; int x, y; Pixmap shape_mask; if (!XtIsRealized((Widget) w)) return; /* * compute desired border size */ SetTransform (&w->clock.maskt, 0, w->core.width, w->core.height, 0, -1.0, 1.0, -1.0, 1.0); face_width = abs (Xwidth (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt)); face_height = abs (Xheight (BORDER_SIZE(w), BORDER_SIZE(w), &w->clock.maskt)); /* * shape the windows and borders */ if (w->clock.shape_window) { SetTransform (&w->clock.t, face_width, w->core.width - face_width, w->core.height - face_height, face_height, -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2); /* * allocate a pixmap to draw shapes in */ if (w->clock.shape_mask && (w->clock.shape_width != w->core.width || w->clock.shape_height != w->core.height)) { XFreePixmap (XtDisplay (w), w->clock.shape_mask); w->clock.shape_mask = None; } if (!w->clock.shape_mask) { w->clock.shape_mask = XCreatePixmap (XtDisplay (w), XtWindow (w), w->core.width, w->core.height, 1); } shape_mask = w->clock.shape_mask; if (!w->clock.shapeGC) w->clock.shapeGC = XCreateGC (XtDisplay (w), shape_mask, 0, &xgcv); /* erase the pixmap */ XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC, 0, 0, w->core.width, w->core.height); XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); /* * draw the bounding shape. Doing this first * eliminates extra exposure events. */ if (w->clock.border_size > 0.0 || !w->clock.transparent) { TFillArc (XtDisplay (w), shape_mask, w->clock.shapeGC, &w->clock.maskt, -1.0, -1.0, 2.0, 2.0, 0, 360 * 64); } if (w->clock.transparent) { if (w->clock.border_size > 0.0) { XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); TFillArc (XtDisplay (w), shape_mask, w->clock.shapeGC, &w->clock.t, -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, WINDOW_WIDTH(w), WINDOW_HEIGHT(w), 0, 360 * 64); XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); } paint_jewel (w, shape_mask, w->clock.shapeGC); paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC); } /* * Find the highest enclosing widget and shape it */ x = 0; y = 0; for (parent = (Widget) w; XtParent (parent); parent = XtParent (parent)) { x = x + parent->core.x + parent->core.border_width; y = y + parent->core.y + parent->core.border_width; } XShapeCombineMask (XtDisplay (parent), XtWindow (parent), ShapeBounding, x, y, shape_mask, ShapeSet); /* erase the pixmap */ XSetForeground (XtDisplay (w), w->clock.shapeGC, 0); XFillRectangle (XtDisplay (w), shape_mask, w->clock.shapeGC, 0, 0, w->core.width, w->core.height); XSetForeground (XtDisplay (w), w->clock.shapeGC, 1); /* * draw the clip shape */ if (w->clock.transparent) { paint_jewel (w, shape_mask, w->clock.shapeGC); paint_hands (w, shape_mask, w->clock.shapeGC, w->clock.shapeGC); } else { TFillArc (XtDisplay (w), shape_mask, w->clock.shapeGC, &w->clock.t, -WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, WINDOW_WIDTH(w), WINDOW_HEIGHT(w), 0, 360 * 64); } XShapeCombineMask (XtDisplay (w), XtWindow (w), ShapeClip, 0, 0, shape_mask, ShapeSet); } else { /* * reconfigure the widget to split the availible * space between the window and the border */ if (face_width > face_height) xwc.border_width = face_height; else xwc.border_width = face_width; xwc.width = w->core.width - xwc.border_width * 2; xwc.height = w->core.height - xwc.border_width * 2; XConfigureWindow (XtDisplay (w), XtWindow (w), CWWidth|CWHeight|CWBorderWidth, &xwc); SetTransform (&w->clock.t, 0, xwc.width, xwc.height, 0, -WINDOW_WIDTH(w)/2, WINDOW_WIDTH(w)/2, -WINDOW_HEIGHT(w)/2, WINDOW_HEIGHT(w)/2); } }
/***** * Name: drawBalloonShaped * Return Type: void * Description: pops up the balloon widget as a shaped window * In: * w: XmBalloon Widget id; * x: absolute x popup position; * y: absolute y popup position; * width: desired widget width; * Returns: * nothing * Note: * This routine composes a *clipmask* for the widget to use when * it is displayed. The clipmask is initially empty and gets filled * according to the selected options. Once it is filled, the text * is rendered in the selected color. *****/ static void drawBalloonShaped(Widget w, Position x, Position y, int width) { BALLOON = (XmBalloonWidget)w; XGCValues xgc; int face_width, face_height, x_offset, y_offset; Dimension bwidth, bheight; Pixmap shape_mask; Display *dpy = XtDisplay(w); Window win = XtWindow(w); /* horizontal offset for text rendering */ x_offset = ATTR(margin_width) + ATTR(font_width); y_offset = 0.25 * ATTR(font_height); bwidth = 2*ATTR(margin_width) + width + 2*x_offset; bheight = 2*ATTR(margin_height) + ATTR(font_height) + 2*y_offset; /* resize to fit */ XtResizeWidget(w, bwidth, bheight, balloon->core.border_width); /* compute desired border size */ setTransform(&ATTR(maskt), 0, bwidth, bheight, 0, -1.0, 1.0, -1.0, 1.0); face_width = abs(Xwidth(BORDER_SIZE(balloon), BORDER_SIZE(balloon), &(ATTR(maskt)))); face_height = abs(Xheight(BORDER_SIZE(balloon), BORDER_SIZE(balloon), &(ATTR(maskt)))); setTransform(&ATTR(t), face_width, bwidth - face_width, bheight - face_height, face_height, -WINDOW_WIDTH(balloon)/2, WINDOW_WIDTH(balloon)/2, -WINDOW_HEIGHT(balloon)/2, WINDOW_HEIGHT(balloon)/2); /* Free up previous clipmask if the size differs */ if(ATTR(shape_mask) && ATTR(shape_width) != w->core.width && ATTR(shape_height) != w->core.height) { XFreePixmap(dpy, ATTR(shape_mask)); ATTR(shape_mask) = None; } /* allocate a clipmask (bitmap of depth one) */ if(!(ATTR(shape_mask))) { ATTR(shape_mask) = XCreatePixmap(dpy, win, bwidth, bheight, 1); ATTR(shape_width) = bwidth; ATTR(shape_height) = bheight; } shape_mask = ATTR(shape_mask); /* simple gc */ if(!(ATTR(shape_gc))) ATTR(shape_gc) = XCreateGC(dpy, shape_mask, 0, &xgc); /* make it fully transparent */ XSetForeground(dpy, ATTR(shape_gc), 0); XFillRectangle(dpy, shape_mask, ATTR(shape_gc), 0, 0, bwidth, bheight); XSetForeground(dpy, ATTR(shape_gc), 1); /***** * Fill in the border bits if we have a border. If we aren't transparent * a filled arc is created. *****/ if(ATTR(border_size) > 0.0 || !ATTR(transparent)) { FillArc(dpy, shape_mask, ATTR(shape_gc), &(ATTR(maskt)), -1.0, -1.0, 2.0, 2.0, 0, 360*64); } /***** * if we are being transparent, erase the inner part of the disk * and fill the bits for the text. If we aren't transparent we don't * have to do this 'cause the bits set for the disk already cover the * bits that cover the text. *****/ if(ATTR(transparent)) { if(ATTR(border_size) > 0.0) { XSetForeground(dpy, ATTR(shape_gc), 0); FillArc(dpy, shape_mask, ATTR(shape_gc), &(ATTR(maskt)), -WINDOW_WIDTH(balloon)/2, -WINDOW_HEIGHT(balloon)/2, WINDOW_WIDTH(balloon), WINDOW_HEIGHT(balloon), 0, 360*64); XSetForeground(dpy, ATTR(shape_gc), 1); } drawText(dpy, balloon, shape_mask, ATTR(shape_gc), x_offset, y_offset); } /* the highest enclosing widget is the widget itself */ XShapeCombineMask(dpy, win, ShapeBounding, 0, 0, shape_mask, ShapeSet); /* erase clipmask */ XSetForeground(dpy, ATTR(shape_gc), 0); XFillRectangle(dpy, shape_mask, ATTR(shape_gc), 0, 0, bwidth, bheight); XSetForeground(dpy, ATTR(shape_gc), 1); /* draw clip shape */ if(ATTR(transparent)) { drawText(dpy, balloon, shape_mask, ATTR(shape_gc), x_offset, y_offset); } else { FillArc(dpy, shape_mask, ATTR(shape_gc), &(ATTR(t)), -WINDOW_WIDTH(balloon)/2, -WINDOW_HEIGHT(balloon)/2, WINDOW_WIDTH(balloon), WINDOW_HEIGHT(balloon), 0, 360*64); } /* compose final clipmask */ XShapeCombineMask(dpy, win, ShapeClip, 0, 0, shape_mask, ShapeSet); /* move to correct location */ XtMoveWidget((Widget)balloon, x + 4, y + 4); /***** * pop it up. * Note that the label can change when the widget is already popped. *****/ if(!ATTR(popped)) XtPopup((Widget)balloon, XtGrabNone); ATTR(popped) = True; /* draw the text */ drawText(dpy, balloon, win, ATTR(gc), x_offset, y_offset); /* if we have got a popdown timeout, add it */ if(ATTR(popdown_delay)) { ATTR(popdown_id) = XtAppAddTimeOut(ATTR(context), ATTR(popdown_delay), popdownBalloon, (XtPointer)balloon); } }