// compose a number of rectabgles into a window shape func ComposeShape(X *xgbutil.XUtil, dst xproto.Window, rects []xrect.Rect) (err error) { combine_bounds := make([]shape.CombineCookie, len(rects)) combine_clip := make([]shape.CombineCookie, len(rects)) var operation shape.Op for i, rect := range rects { // make rectangular window of correct goemetry win, err := xwindow.Generate(X) if err != nil { log.Fatalf("ComposeShape: Error creating rectange %v window.", rect) return err } win.Create(X.RootWin(), rect.X(), rect.Y(), rect.Width(), rect.Height(), xproto.CwBackPixel, 0xffffff) // choose operation. on the first one, we want to set the shape. if i == 0 { operation = shape.SoSet } else { operation = shape.SoUnion } // combine window request x, y := int16(rect.X()), int16(rect.Y()) combine_kind := shape.Kind(shape.SkBounding) combine_bounds[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id) combine_kind = shape.Kind(shape.SkClip) combine_clip[i] = shape.CombineChecked(X.Conn(), operation, combine_kind, combine_kind, dst, x, y, win.Id) } return nil }
func (c *Client) cbShapeNotify() xevent.ShapeNotifyFun { var err error f := func(X *xgbutil.XUtil, ev xevent.ShapeNotifyEvent) { // Many thanks to Openbox. I'll followed their lead. xoff, yoff := int16(c.frame.Left()), int16(c.frame.Top()) // var xoff, yoff int16 = 0, 0 // Update the client's shaped status. c.shaped = ev.Shaped // If the client is no longer shaped, clear the mask. if !c.shaped { err = shape.MaskChecked(wm.X.Conn(), shape.SoSet, ev.ShapeKind, c.frame.Parent().Id, xoff, yoff, xproto.PixmapNone).Check() if err != nil { logger.Warning.Printf("Error clearing Shape mask on '%s': %s", c, err) } return } // Now we have to shape the frame like the client. err = shape.CombineChecked(wm.X.Conn(), shape.SoSet, ev.ShapeKind, ev.ShapeKind, c.frame.Parent().Id, xoff, yoff, c.Id()).Check() if err != nil { logger.Warning.Printf("Error combining on '%s': %s", c, err) return } // If the client is being shaped and claims that it doesn't want // decorations, make sure it has "nada" instead of "slim". // We do this on startup, but maybe the client didn't say anything // about shaping then... // if !c.shouldDecor() { // c.FrameNada() // } // We don't even bother with shaping the frame if the client has any // kind of decoration. Unless I'm mistaken, shaping Wingo's decorations // to fit client shaping really isn't going to do anything... if _, ok := c.frame.(*frame.Nada); ok { return } // So this is only done with Slim/Borders/Full frames. It basically // negates the effects of shaping since we use one monolithic // rectangle. rect := xproto.Rectangle{ X: 0, Y: 0, Width: uint16(c.frame.Geom().Width()), Height: uint16(c.frame.Geom().Height()), } err = shape.RectanglesChecked(wm.X.Conn(), shape.SoUnion, shape.SkBounding, xproto.ClipOrderingUnsorted, c.frame.Parent().Id, 0, 0, []xproto.Rectangle{rect}).Check() if err != nil { logger.Warning.Printf("Error adding rectangles on '%s': %s", c, err) return } } return xevent.ShapeNotifyFun(f) }